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 |