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