blob: 01a3272735b5b3c8b75624b80a44fb07453e5e15 [file] [log] [blame]
bsalomon87cbcf32015-04-22 08:51:38 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "tools/ToolUtils.h"
bsalomon87cbcf32015-04-22 08:51:38 -070010
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkShader.h"
bsalomon87cbcf32015-04-22 08:51:38 -070012
13// This class of GMs test how edges/verts snap near rounding boundaries in device space without
14// anti-aliaing.
15class PixelSnapGM : public skiagm::GM {
16public:
17 PixelSnapGM() {}
18
19protected:
20 // kTrans should be even or checkboards wont agree in different test cases.
mtkleindbfd7ab2016-09-01 11:24:54 -070021 static constexpr int kTrans = 14;
22 static constexpr int kLabelPad = 4;
bsalomon87cbcf32015-04-22 08:51:38 -070023 // The inverse of this value should be a perfect SkScalar.
mtkleindbfd7ab2016-09-01 11:24:54 -070024 static constexpr int kSubPixelSteps = 8;
25 static constexpr int kLabelTextSize = 9;
bsalomon87cbcf32015-04-22 08:51:38 -070026
bungeman99fe8222015-08-20 07:57:51 -070027 static_assert(kSubPixelSteps < 99, "label_offset_too_small");
mtkleindbfd7ab2016-09-01 11:24:54 -070028 static constexpr int kLabelOffsetX = 2 * kLabelTextSize + kLabelPad;
29 static constexpr int kLabelOffsetY = kLabelTextSize + kLabelPad;
bsalomonc6534a22015-04-22 11:34:46 -070030
bsalomon87cbcf32015-04-22 08:51:38 -070031 SkISize onISize() override {
bsalomonc6534a22015-04-22 11:34:46 -070032 return SkISize::Make((kSubPixelSteps + 1) * kTrans + kLabelOffsetX + kLabelPad,
33 (kSubPixelSteps + 1) * kTrans + kLabelOffsetY + kLabelPad);
bsalomon87cbcf32015-04-22 08:51:38 -070034 }
35
36 void onDraw(SkCanvas* canvas) override {
37 SkPaint bgPaint;
Mike Kleinea3f0142019-03-20 11:12:10 -050038 bgPaint.setShader(ToolUtils::create_checkerboard_shader(0xFFAAAAAA, 0xFF777777, 1));
bsalomon87cbcf32015-04-22 08:51:38 -070039 canvas->drawPaint(bgPaint);
40
41 SkString offset;
42 SkPaint labelPaint;
bsalomon87cbcf32015-04-22 08:51:38 -070043 labelPaint.setColor(SK_ColorWHITE);
Mike Kleinea3f0142019-03-20 11:12:10 -050044 SkFont font(ToolUtils::create_portable_typeface(), SkIntToScalar(kLabelTextSize));
bsalomon87cbcf32015-04-22 08:51:38 -070045 SkPaint linePaint;
46 linePaint.setColor(SK_ColorWHITE);
47
caryclarkf597c422015-07-28 10:37:53 -070048 // Draw row labels
49 canvas->save();
50 canvas->translate(0, SkIntToScalar(kLabelOffsetY));
51 for (int i = 0; i <= kSubPixelSteps; ++i) {
52 offset.printf("%d", i);
Hal Canarydf2d27e2019-01-08 09:38:02 -050053 canvas->drawString(offset, 0, i * kTrans + SkIntToScalar(kLabelTextSize),
54 font, labelPaint);
caryclarkf597c422015-07-28 10:37:53 -070055 }
56 canvas->restore();
bsalomon87cbcf32015-04-22 08:51:38 -070057
caryclarkf597c422015-07-28 10:37:53 -070058 // Draw col labels
59 canvas->save();
60 canvas->translate(SkIntToScalar(kLabelOffsetX), 0);
61 for (int i = 0; i <= kSubPixelSteps; ++i) {
62 offset.printf("%d", i);
Hal Canarydf2d27e2019-01-08 09:38:02 -050063 canvas->drawString(offset, i * SkIntToScalar(kTrans), SkIntToScalar(kLabelTextSize),
64 font, labelPaint);
caryclarkf597c422015-07-28 10:37:53 -070065 }
66 canvas->restore();
bsalomon87cbcf32015-04-22 08:51:38 -070067
bsalomonc6534a22015-04-22 11:34:46 -070068 canvas->translate(SkIntToScalar(kLabelOffsetX), SkIntToScalar(kLabelOffsetY));
bsalomon87cbcf32015-04-22 08:51:38 -070069
70 // Draw test case grid lines (Draw them all at pixel centers to hopefully avoid any
71 // snapping issues).
72 for (int i = 0; i <= kSubPixelSteps + 1; ++i) {
73 canvas->drawLine(0.5f,
74 i * SkIntToScalar(kTrans) + 0.5f,
75 SkIntToScalar(kTrans) * (kSubPixelSteps + 1) + 0.5f,
76 i * SkIntToScalar(kTrans) + 0.5f,
77 linePaint);
78 canvas->drawLine(i * SkIntToScalar(kTrans) + 0.5f,
79 0.5f,
80 i * SkIntToScalar(kTrans) + 0.5f,
81 SkIntToScalar(kTrans) * (kSubPixelSteps + 1) + 0.5f,
82 linePaint);
83 }
84
85 for (int i = 0; i <= kSubPixelSteps; ++i) {
86 for (int j = 0; j <= kSubPixelSteps; ++j) {
87 canvas->save();
88 // +1's account for the grid lines around each test case.
89 canvas->translate(j * (kTrans + 1.f/kSubPixelSteps) + 1,
90 i * (kTrans + 1.f/kSubPixelSteps) + 1);
91 this->drawElement(canvas);
92 canvas->restore();
93 }
94 }
95 }
96
97 virtual void drawElement(SkCanvas*) = 0;
98
99private:
100 typedef skiagm::GM INHERITED;
101};
102
103class PointSnapGM : public PixelSnapGM {
104protected:
105 SkString onShortName() override { return SkString("pixel_snap_point"); }
Mike Reed3661bc92017-02-22 13:21:42 -0500106 void drawElement(SkCanvas* canvas) override {
107 const SkPoint pt = { 1, 1 };
108 SkPaint paint;
109 paint.setColor(SK_ColorBLUE);
110 canvas->drawPoints(SkCanvas::kPoints_PointMode, 1, &pt, paint);
111 }
bsalomon87cbcf32015-04-22 08:51:38 -0700112
113private:
114 typedef PixelSnapGM INHERITED;
115};
116
117class LineSnapGM : public PixelSnapGM {
118protected:
119 SkString onShortName() override { return SkString("pixel_snap_line"); }
120 void drawElement(SkCanvas* canvas) override {
121 SkPaint paint;
122 paint.setColor(SK_ColorGREEN);
123 // Draw a horizontal and vertical line, each length 3.
124 canvas->drawLine(1, 1, 4, 1, paint);
125 canvas->drawLine(6, 1, 6, 4, paint);
126 }
127
128private:
129 typedef PixelSnapGM INHERITED;
130};
131
132class RectSnapGM : public PixelSnapGM {
133protected:
134 SkString onShortName() override { return SkString("pixel_snap_rect"); }
135 void drawElement(SkCanvas* canvas) override {
136 SkPaint paint;
137 paint.setColor(SK_ColorRED);
138 canvas->drawRect(SkRect::MakeXYWH(1, 1, 3, 3), paint);
139 }
140
141private:
142 typedef PixelSnapGM INHERITED;
143};
144
145class ComboSnapGM : public PixelSnapGM {
146protected:
147 SkString onShortName() override { return SkString("pixel_snap_combo"); }
148 void drawElement(SkCanvas* canvas) override {
149 SkPaint paint;
150 paint.setAntiAlias(false);
151 // A rectangle that exactly covers a pixel, a point at each corner, 8 horiz/vert lines
152 // at rect corners (two at each corner, extending away from rect). They are drawn in this
153 // order lines (green), points (blue), rect(red).
154 SkRect rect = SkRect::MakeXYWH(3, 3, 1, 1);
155 paint.setColor(SK_ColorGREEN);
Mike Reed3661bc92017-02-22 13:21:42 -0500156 const SkPoint lines[] = {
157 { 3, 3 }, { 0, 3 },
158 { 3, 3 }, { 3, 0 },
159 { 4, 3 }, { 7, 3 },
160 { 4, 3 }, { 4, 0 },
161 { 3, 4 }, { 0, 4 },
162 { 3, 4 }, { 3, 7 },
163 { 4, 4 }, { 7, 4 },
164 { 4, 4 }, { 4, 7 },
165 };
166 canvas->drawPoints(SkCanvas::kLines_PointMode, SK_ARRAY_COUNT(lines), lines, paint);
167
168 const SkPoint pts[] = {
169 { 4, 3 }, { 4, 4, }, { 3, 3 }, { 3, 4 },
170 };
171 paint.setColor(SK_ColorBLUE);
172 canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(pts), pts, paint);
173
bsalomon87cbcf32015-04-22 08:51:38 -0700174 paint.setColor(SK_ColorRED);
175 canvas->drawRect(rect, paint);
176 }
177
178private:
179 typedef PixelSnapGM INHERITED;
180};
181
182//////////////////////////////////////////////////////////////////////////////
halcanary385fe4d2015-08-26 13:07:48 -0700183DEF_GM(return new PointSnapGM;)
184DEF_GM(return new LineSnapGM;)
185DEF_GM(return new RectSnapGM;)
186DEF_GM(return new ComboSnapGM;)