Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2015 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 
     11 #include "SkShader.h"
     12 
     13 // This class of GMs test how edges/verts snap near rounding boundaries in device space without
     14 // anti-aliaing.
     15 class PixelSnapGM : public skiagm::GM {
     16 public:
     17     PixelSnapGM() {}
     18 
     19 protected:
     20     // kTrans should be even or checkboards wont agree in different test cases.
     21     static constexpr int kTrans = 14;
     22     static constexpr int kLabelPad = 4;
     23     // The inverse of this value should be a perfect SkScalar.
     24     static constexpr int kSubPixelSteps = 8;
     25     static constexpr int kLabelTextSize = 9;
     26 
     27     static_assert(kSubPixelSteps < 99, "label_offset_too_small");
     28     static constexpr int kLabelOffsetX = 2 * kLabelTextSize + kLabelPad;
     29     static constexpr int kLabelOffsetY = kLabelTextSize + kLabelPad;
     30 
     31     SkISize onISize() override {
     32         return SkISize::Make((kSubPixelSteps + 1) * kTrans + kLabelOffsetX + kLabelPad,
     33                              (kSubPixelSteps + 1) * kTrans + kLabelOffsetY + kLabelPad);
     34     }
     35 
     36     void onDraw(SkCanvas* canvas) override {
     37         SkPaint bgPaint;
     38         bgPaint.setShader(
     39                 sk_tool_utils::create_checkerboard_shader(
     40                 sk_tool_utils::color_to_565(0xFFAAAAAA),
     41                 sk_tool_utils::color_to_565(0xFF777777), 1));
     42         canvas->drawPaint(bgPaint);
     43 
     44         SkString offset;
     45         SkPaint labelPaint;
     46         labelPaint.setAntiAlias(true);
     47         labelPaint.setColor(SK_ColorWHITE);
     48         labelPaint.setTextSize(SkIntToScalar(kLabelTextSize));
     49         sk_tool_utils::set_portable_typeface(&labelPaint);
     50         SkPaint linePaint;
     51         linePaint.setColor(SK_ColorWHITE);
     52 
     53         // Draw row labels
     54         canvas->save();
     55             canvas->translate(0, SkIntToScalar(kLabelOffsetY));
     56             for (int i = 0; i <= kSubPixelSteps; ++i) {
     57                 offset.printf("%d", i);
     58                 canvas->drawText(offset.c_str(), offset.size(),
     59                                     0, i * kTrans + labelPaint.getTextSize(),
     60                                     labelPaint);
     61             }
     62         canvas->restore();
     63 
     64         // Draw col labels
     65         canvas->save();
     66             canvas->translate(SkIntToScalar(kLabelOffsetX), 0);
     67             for (int i = 0; i <= kSubPixelSteps; ++i) {
     68                 offset.printf("%d", i);
     69                 canvas->drawText(offset.c_str(), offset.size(),
     70                                     i * SkIntToScalar(kTrans), labelPaint.getTextSize(),
     71                                     labelPaint);
     72             }
     73         canvas->restore();
     74 
     75         canvas->translate(SkIntToScalar(kLabelOffsetX), SkIntToScalar(kLabelOffsetY));
     76 
     77         // Draw test case grid lines (Draw them all at pixel centers to hopefully avoid any
     78         // snapping issues).
     79         for (int i = 0; i <= kSubPixelSteps + 1; ++i) {
     80             canvas->drawLine(0.5f,
     81                              i * SkIntToScalar(kTrans) + 0.5f,
     82                              SkIntToScalar(kTrans) * (kSubPixelSteps + 1) + 0.5f,
     83                              i * SkIntToScalar(kTrans) + 0.5f,
     84                              linePaint);
     85             canvas->drawLine(i * SkIntToScalar(kTrans) + 0.5f,
     86                              0.5f,
     87                              i * SkIntToScalar(kTrans) + 0.5f,
     88                              SkIntToScalar(kTrans) * (kSubPixelSteps + 1) + 0.5f,
     89                              linePaint);
     90         }
     91 
     92         for (int i = 0; i <= kSubPixelSteps; ++i) {
     93             for (int j = 0; j <= kSubPixelSteps; ++j) {
     94                 canvas->save();
     95                 // +1's account for the grid lines around each test case.
     96                 canvas->translate(j * (kTrans + 1.f/kSubPixelSteps) + 1,
     97                                   i * (kTrans + 1.f/kSubPixelSteps) + 1);
     98                 this->drawElement(canvas);
     99                 canvas->restore();
    100             }
    101         }
    102     }
    103 
    104     virtual void drawElement(SkCanvas*) = 0;
    105 
    106 private:
    107     typedef skiagm::GM INHERITED;
    108 };
    109 
    110 class PointSnapGM : public PixelSnapGM {
    111 protected:
    112     SkString onShortName() override { return SkString("pixel_snap_point"); }
    113     void drawElement(SkCanvas* canvas) override {
    114         const SkPoint pt = { 1, 1 };
    115         SkPaint paint;
    116         paint.setColor(SK_ColorBLUE);
    117         canvas->drawPoints(SkCanvas::kPoints_PointMode, 1, &pt, paint);
    118     }
    119 
    120 private:
    121     typedef PixelSnapGM INHERITED;
    122 };
    123 
    124 class LineSnapGM : public PixelSnapGM {
    125 protected:
    126     SkString onShortName() override { return SkString("pixel_snap_line"); }
    127     void drawElement(SkCanvas* canvas) override {
    128         SkPaint paint;
    129         paint.setColor(SK_ColorGREEN);
    130         // Draw a horizontal and vertical line, each length 3.
    131         canvas->drawLine(1, 1, 4, 1, paint);
    132         canvas->drawLine(6, 1, 6, 4, paint);
    133     }
    134 
    135 private:
    136     typedef PixelSnapGM INHERITED;
    137 };
    138 
    139 class RectSnapGM : public PixelSnapGM {
    140 protected:
    141     SkString onShortName() override { return SkString("pixel_snap_rect"); }
    142     void drawElement(SkCanvas* canvas) override {
    143         SkPaint paint;
    144         paint.setColor(SK_ColorRED);
    145         canvas->drawRect(SkRect::MakeXYWH(1, 1, 3, 3), paint);
    146     }
    147 
    148 private:
    149     typedef PixelSnapGM INHERITED;
    150 };
    151 
    152 class ComboSnapGM : public PixelSnapGM {
    153 protected:
    154     SkString onShortName() override { return SkString("pixel_snap_combo"); }
    155     void drawElement(SkCanvas* canvas) override {
    156         SkPaint paint;
    157         paint.setAntiAlias(false);
    158         // A rectangle that exactly covers a pixel, a point at each corner, 8 horiz/vert lines
    159         // at rect corners (two at each corner, extending away from rect). They are drawn in this
    160         // order lines (green), points (blue), rect(red).
    161         SkRect rect = SkRect::MakeXYWH(3, 3, 1, 1);
    162         paint.setColor(SK_ColorGREEN);
    163         const SkPoint lines[] = {
    164             { 3, 3 }, { 0, 3 },
    165             { 3, 3 }, { 3, 0 },
    166             { 4, 3 }, { 7, 3 },
    167             { 4, 3 }, { 4, 0 },
    168             { 3, 4 }, { 0, 4 },
    169             { 3, 4 }, { 3, 7 },
    170             { 4, 4 }, { 7, 4 },
    171             { 4, 4 }, { 4, 7 },
    172         };
    173         canvas->drawPoints(SkCanvas::kLines_PointMode, SK_ARRAY_COUNT(lines), lines, paint);
    174 
    175         const SkPoint pts[] = {
    176             { 4, 3 }, { 4, 4, }, { 3, 3 }, { 3, 4 },
    177         };
    178         paint.setColor(SK_ColorBLUE);
    179         canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(pts), pts, paint);
    180 
    181         paint.setColor(SK_ColorRED);
    182         canvas->drawRect(rect, paint);
    183     }
    184 
    185 private:
    186     typedef PixelSnapGM INHERITED;
    187 };
    188 
    189 //////////////////////////////////////////////////////////////////////////////
    190 DEF_GM(return new PointSnapGM;)
    191 DEF_GM(return new LineSnapGM;)
    192 DEF_GM(return new RectSnapGM;)
    193 DEF_GM(return new ComboSnapGM;)
    194