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 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(sk_tool_utils::create_portable_typeface("Helvetica", SkTypeface::kNormal));
     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 device 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, &bounds);
    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 position.
    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 }
    205