| 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 |