Home | History | Annotate | Download | only in gm
      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