OLD | NEW |
| (Empty) |
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 namespace skiagm { | |
21 | |
22 class GlyphPosGM : public GM { | |
23 public: | |
24 GlyphPosGM(SkScalar strokeWidth, SkPaint::Style strokeStyle) | |
25 : fStrokeWidth(strokeWidth) | |
26 , fStrokeStyle(strokeStyle) { | |
27 } | |
28 | |
29 protected: | |
30 virtual uint32_t onGetFlags() const SK_OVERRIDE { | |
31 return kSkipTiled_Flag; | |
32 } | |
33 | |
34 virtual SkString onShortName() SK_OVERRIDE { | |
35 SkString str("glyph_pos"); | |
36 if (fStrokeWidth == 0.0f) { | |
37 str.append("_h"); // h == Hairline. | |
38 } else { | |
39 str.append("_n"); // n == Normal. | |
40 } | |
41 if (fStrokeStyle == SkPaint::kStroke_Style) { | |
42 str.append("_s"); | |
43 } else if (fStrokeStyle == SkPaint::kFill_Style) { | |
44 str.append("_f"); | |
45 } else { | |
46 str.append("_b"); // b == Both. | |
47 } | |
48 return str; | |
49 } | |
50 | |
51 virtual SkISize onISize() { return SkISize::Make(800, 600); } | |
52 | |
53 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { | |
54 if (!fProp) { | |
55 fProp.reset(SkTypeface::CreateFromName("Helvetica", SkTypeface::kNor
mal)); | |
56 } | |
57 | |
58 // There's a black pixel at 40, 40 for reference. | |
59 canvas->drawPoint(40.0f, 40.0f, SK_ColorBLACK); | |
60 | |
61 // Two reference images. | |
62 canvas->translate(50.0f, 50.0f); | |
63 drawTestCase(canvas, 1.0f); | |
64 | |
65 canvas->translate(0.0f, 50.0f); | |
66 drawTestCase(canvas, 3.0f); | |
67 | |
68 // Uniform scaling test. | |
69 canvas->translate(0.0f, 100.0f); | |
70 canvas->save(); | |
71 canvas->scale(3.0f, 3.0f); | |
72 drawTestCase(canvas, 1.0f); | |
73 canvas->restore(); | |
74 | |
75 // Non-uniform scaling test. | |
76 canvas->translate(0.0f, 100.0f); | |
77 canvas->save(); | |
78 canvas->scale(3.0f, 6.0f); | |
79 drawTestCase(canvas, 1.0f); | |
80 canvas->restore(); | |
81 | |
82 // Skew test. | |
83 canvas->translate(0.0f, 80.0f); | |
84 canvas->save(); | |
85 canvas->scale(3.0f, 3.0f); | |
86 SkMatrix skew; | |
87 skew.setIdentity(); | |
88 skew.setSkewX(SkScalarDiv(8.0f, | |
89 25.0f)); | |
90 skew.setSkewY(SkScalarDiv(2.0f, | |
91 25.0f)); | |
92 canvas->concat(skew); | |
93 drawTestCase(canvas, 1.0f); | |
94 canvas->restore(); | |
95 | |
96 // Perspective test. | |
97 canvas->translate(0.0f, 80.0f); | |
98 canvas->save(); | |
99 SkMatrix perspective; | |
100 perspective.setIdentity(); | |
101 perspective.setPerspX(-SkScalarDiv(SK_Scalar1, 340.0f)); | |
102 perspective.setSkewX(SkScalarDiv(8.0f, | |
103 25.0f)); | |
104 perspective.setSkewY(SkScalarDiv(2.0f, | |
105 25.0f)); | |
106 | |
107 | |
108 canvas->concat(perspective); | |
109 drawTestCase(canvas, 1.0f); | |
110 canvas->restore(); | |
111 } | |
112 | |
113 void drawTestCase(SkCanvas* canvas, SkScalar textScale) { | |
114 SkPaint paint; | |
115 paint.setColor(SK_ColorBLACK); | |
116 paint.setAntiAlias(true); | |
117 paint.setTextSize(kTextHeight * textScale); | |
118 paint.setTypeface(fProp); | |
119 paint.setDevKernText(true); | |
120 paint.setStrokeWidth(fStrokeWidth); | |
121 paint.setStyle(fStrokeStyle); | |
122 | |
123 // This demonstrates that we can not measure the text if there's a devic
e transform. The | |
124 // canvas total matrix will end up being a device transform. | |
125 bool drawRef = !(canvas->getTotalMatrix().getType() & | |
126 ~(SkMatrix::kIdentity_Mask | SkMatrix::kTranslate_Mask)
); | |
127 | |
128 SkRect bounds; | |
129 if (drawRef) { | |
130 SkScalar advance = paint.measureText(kText, sizeof(kText) - 1, &boun
ds); | |
131 | |
132 paint.setStrokeWidth(0.0f); | |
133 paint.setStyle(SkPaint::kStroke_Style); | |
134 | |
135 // Green box is the measured text bounds. | |
136 paint.setColor(SK_ColorGREEN); | |
137 canvas->drawRect(bounds, paint); | |
138 | |
139 // Red line is the measured advance from the 0,0 of the text positio
n. | |
140 paint.setColor(SK_ColorRED); | |
141 canvas->drawLine(0.0f, 0.0f, advance, 0.0f, paint); | |
142 } | |
143 | |
144 // Black text is the testcase, eg. the text. | |
145 paint.setColor(SK_ColorBLACK); | |
146 paint.setStrokeWidth(fStrokeWidth); | |
147 paint.setStyle(fStrokeStyle); | |
148 canvas->drawText(kText, sizeof(kText) - 1, 0.0f, 0.0f, paint); | |
149 | |
150 if (drawRef) { | |
151 SkScalar widths[sizeof(kText) - 1]; | |
152 paint.getTextWidths(kText, sizeof(kText) - 1, widths, NULL); | |
153 | |
154 paint.setStrokeWidth(0.0f); | |
155 paint.setStyle(SkPaint::kStroke_Style); | |
156 | |
157 // Magenta lines are the positions for the characters. | |
158 paint.setColor(SK_ColorMAGENTA); | |
159 SkScalar w = bounds.x(); | |
160 for (size_t i = 0; i < sizeof(kText) - 1; ++i) { | |
161 canvas->drawLine(w, 0.0f, w, 5.0f, paint); | |
162 w += widths[i]; | |
163 } | |
164 } | |
165 } | |
166 | |
167 private: | |
168 SkAutoTUnref<SkTypeface> fProp; | |
169 SkScalar fStrokeWidth; | |
170 SkPaint::Style fStrokeStyle; | |
171 | |
172 typedef GM INHERITED; | |
173 }; | |
174 | |
175 ////////////////////////////////////////////////////////////////////////////// | |
176 | |
177 static GM* GlyphPosHairlineStrokeAndFillFactory(void*) { | |
178 return new GlyphPosGM(0.0f, SkPaint::kStrokeAndFill_Style); | |
179 } | |
180 static GM* GlyphPosStrokeAndFillFactory(void*) { | |
181 return new GlyphPosGM(1.2f, SkPaint::kStrokeAndFill_Style); | |
182 } | |
183 static GM* GlyphPosHairlineStrokeFactory(void*) { | |
184 return new GlyphPosGM(0.0f, SkPaint::kStroke_Style); | |
185 } | |
186 static GM* GlyphPosStrokeFactory(void*) { | |
187 return new GlyphPosGM(1.2f, SkPaint::kStroke_Style); | |
188 } | |
189 static GM* GlyphPosHairlineFillFactory(void*) { | |
190 return new GlyphPosGM(0.0f, SkPaint::kFill_Style); | |
191 } | |
192 static GM* GlyphPosFillFactory(void*) { | |
193 return new GlyphPosGM(1.2f, SkPaint::kFill_Style); | |
194 } | |
195 | |
196 static GMRegistry reg1(GlyphPosHairlineStrokeAndFillFactory); | |
197 static GMRegistry reg2(GlyphPosStrokeAndFillFactory); | |
198 static GMRegistry reg3(GlyphPosHairlineStrokeFactory); | |
199 static GMRegistry reg4(GlyphPosStrokeFactory); | |
200 static GMRegistry reg5(GlyphPosHairlineFillFactory); | |
201 static GMRegistry reg6(GlyphPosFillFactory); | |
202 | |
203 | |
204 } | |
OLD | NEW |