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