• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "gm.h"
9 #include "SkCanvas.h"
10 #include "SkTypeface.h"
11 
12 /* This test tries to define the effect of using hairline strokes on text.
13  * Provides non-hairline images for reference and consistency checks.
14  * glyph_pos_(h/n)_(s/f/b)
15  *   -> test hairline/non-hairline stroke/fill/stroke+fill.
16  */
17 static const SkScalar kTextHeight = 14.0f;
18 static const char kText[] = "Proportional Hamburgefons #% fi";
19 
20 static void drawTestCase(SkCanvas* canvas,
21                          SkScalar textScale,
22                          SkScalar strokeWidth,
23                          SkPaint::Style strokeStyle);
24 
draw_gm(SkCanvas * canvas,SkScalar strokeWidth,SkPaint::Style strokeStyle)25 static void draw_gm(SkCanvas* canvas,
26                     SkScalar strokeWidth,
27                     SkPaint::Style strokeStyle) {
28         // There's a black pixel at 40, 40 for reference.
29         canvas->drawPoint(40.0f, 40.0f, SK_ColorBLACK);
30 
31         // Two reference images.
32         canvas->translate(50.0f, 50.0f);
33         drawTestCase(canvas, 1.0f, strokeWidth, strokeStyle);
34 
35         canvas->translate(0.0f, 50.0f);
36         drawTestCase(canvas, 3.0f, strokeWidth, strokeStyle);
37 
38         // Uniform scaling test.
39         canvas->translate(0.0f, 100.0f);
40         canvas->save();
41         canvas->scale(3.0f, 3.0f);
42         drawTestCase(canvas, 1.0f, strokeWidth, strokeStyle);
43         canvas->restore();
44 
45         // Non-uniform scaling test.
46         canvas->translate(0.0f, 100.0f);
47         canvas->save();
48         canvas->scale(3.0f, 6.0f);
49         drawTestCase(canvas, 1.0f, strokeWidth, strokeStyle);
50         canvas->restore();
51 
52         // Skew test.
53         canvas->translate(0.0f, 80.0f);
54         canvas->save();
55         canvas->scale(3.0f, 3.0f);
56         SkMatrix skew;
57         skew.setIdentity();
58         skew.setSkewX(8.0f / 25.0f);
59         skew.setSkewY(2.0f / 25.0f);
60         canvas->concat(skew);
61         drawTestCase(canvas, 1.0f, strokeWidth, strokeStyle);
62         canvas->restore();
63 
64         // Perspective test.
65         canvas->translate(0.0f, 80.0f);
66         canvas->save();
67         SkMatrix perspective;
68         perspective.setIdentity();
69         perspective.setPerspX(-SkScalarInvert(340));
70         perspective.setSkewX(8.0f / 25.0f);
71         perspective.setSkewY(2.0f / 25.0f);
72 
73         canvas->concat(perspective);
74         drawTestCase(canvas, 1.0f, strokeWidth, strokeStyle);
75         canvas->restore();
76 }
77 
drawTestCase(SkCanvas * canvas,SkScalar textScale,SkScalar strokeWidth,SkPaint::Style strokeStyle)78 static void drawTestCase(SkCanvas* canvas,
79                          SkScalar textScale,
80                          SkScalar strokeWidth,
81                          SkPaint::Style strokeStyle) {
82         SkPaint paint;
83         paint.setColor(SK_ColorBLACK);
84         paint.setAntiAlias(true);
85         paint.setTextSize(kTextHeight * textScale);
86         sk_tool_utils::set_portable_typeface(&paint);
87         paint.setStrokeWidth(strokeWidth);
88         paint.setStyle(strokeStyle);
89 
90         // This demonstrates that we can not measure the text if
91         // there's a device transform. The canvas total matrix will
92         // end up being a device transform.
93         bool drawRef = !(canvas->getTotalMatrix().getType() &
94                          ~(SkMatrix::kIdentity_Mask | SkMatrix::kTranslate_Mask));
95 
96         SkRect bounds;
97         if (drawRef) {
98             SkScalar advance = paint.measureText(kText, sizeof(kText) - 1, &bounds);
99 
100             paint.setStrokeWidth(0.0f);
101             paint.setStyle(SkPaint::kStroke_Style);
102 
103             // Green box is the measured text bounds.
104             paint.setColor(SK_ColorGREEN);
105             canvas->drawRect(bounds, paint);
106 
107             // Red line is the measured advance from the 0,0 of the text position.
108             paint.setColor(SK_ColorRED);
109             canvas->drawLine(0.0f, 0.0f, advance, 0.0f, paint);
110         }
111 
112         // Black text is the testcase, eg. the text.
113         paint.setColor(SK_ColorBLACK);
114         paint.setStrokeWidth(strokeWidth);
115         paint.setStyle(strokeStyle);
116         canvas->drawText(kText, sizeof(kText) - 1, 0.0f, 0.0f, paint);
117 
118         if (drawRef) {
119             SkScalar widths[sizeof(kText) - 1];
120             paint.getTextWidths(kText, sizeof(kText) - 1, widths, nullptr);
121 
122             paint.setStrokeWidth(0.0f);
123             paint.setStyle(SkPaint::kStroke_Style);
124 
125             // Magenta lines are the positions for the characters.
126             paint.setColor(SK_ColorMAGENTA);
127             SkScalar w = bounds.x();
128             for (size_t i = 0; i < sizeof(kText) - 1; ++i) {
129                 canvas->drawLine(w, 0.0f, w, 5.0f, paint);
130                 w += widths[i];
131             }
132         }
133 }
134 
135 DEF_SIMPLE_GM(glyph_pos_h_b, c, 800, 600) {
136     draw_gm(c, 0.0f, SkPaint::kStrokeAndFill_Style);
137 }
138 DEF_SIMPLE_GM(glyph_pos_n_b, c, 800, 600) {
139     draw_gm(c, 1.2f, SkPaint::kStrokeAndFill_Style);
140 }
141 DEF_SIMPLE_GM(glyph_pos_h_s, c, 800, 600) {
142     draw_gm(c, 0.0f, SkPaint::kStroke_Style);
143 }
144 DEF_SIMPLE_GM(glyph_pos_n_s, c, 800, 600) {
145     draw_gm(c, 1.2f, SkPaint::kStroke_Style);
146 }
147 DEF_SIMPLE_GM(glyph_pos_h_f, c, 800, 600) {
148     draw_gm(c, 0.0f, SkPaint::kFill_Style);
149 }
150 DEF_SIMPLE_GM(glyph_pos_n_f, c, 800, 600) {
151     draw_gm(c, 1.2f, SkPaint::kFill_Style);
152 }
153