blob: 31136e697ed33111583695a75979e20b5be7ab64 [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"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkCanvas.h"
10#include "include/core/SkColor.h"
11#include "include/core/SkFont.h"
12#include "include/core/SkPaint.h"
13#include "include/core/SkPoint.h"
14#include "include/core/SkRect.h"
15#include "include/core/SkScalar.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "include/core/SkShader.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040017#include "include/core/SkSize.h"
18#include "include/core/SkString.h"
19#include "include/core/SkTypeface.h"
20#include "include/core/SkTypes.h"
21#include "tools/ToolUtils.h"
bsalomon87cbcf32015-04-22 08:51:38 -070022
23// This class of GMs test how edges/verts snap near rounding boundaries in device space without
24// anti-aliaing.
25class PixelSnapGM : public skiagm::GM {
26public:
27 PixelSnapGM() {}
28
29protected:
30 // kTrans should be even or checkboards wont agree in different test cases.
Brian Salomon9fa47cc2021-10-08 18:48:26 -040031 inline static constexpr int kTrans = 14;
32 inline static constexpr int kLabelPad = 4;
bsalomon87cbcf32015-04-22 08:51:38 -070033 // The inverse of this value should be a perfect SkScalar.
Brian Salomon9fa47cc2021-10-08 18:48:26 -040034 inline static constexpr int kSubPixelSteps = 8;
35 inline static constexpr int kLabelTextSize = 9;
bsalomon87cbcf32015-04-22 08:51:38 -070036
bungeman99fe8222015-08-20 07:57:51 -070037 static_assert(kSubPixelSteps < 99, "label_offset_too_small");
Brian Salomon9fa47cc2021-10-08 18:48:26 -040038 inline static constexpr int kLabelOffsetX = 2 * kLabelTextSize + kLabelPad;
39 inline static constexpr int kLabelOffsetY = kLabelTextSize + kLabelPad;
bsalomonc6534a22015-04-22 11:34:46 -070040
bsalomon87cbcf32015-04-22 08:51:38 -070041 SkISize onISize() override {
bsalomonc6534a22015-04-22 11:34:46 -070042 return SkISize::Make((kSubPixelSteps + 1) * kTrans + kLabelOffsetX + kLabelPad,
43 (kSubPixelSteps + 1) * kTrans + kLabelOffsetY + kLabelPad);
bsalomon87cbcf32015-04-22 08:51:38 -070044 }
45
46 void onDraw(SkCanvas* canvas) override {
47 SkPaint bgPaint;
Mike Kleinea3f0142019-03-20 11:12:10 -050048 bgPaint.setShader(ToolUtils::create_checkerboard_shader(0xFFAAAAAA, 0xFF777777, 1));
bsalomon87cbcf32015-04-22 08:51:38 -070049 canvas->drawPaint(bgPaint);
50
51 SkString offset;
52 SkPaint labelPaint;
bsalomon87cbcf32015-04-22 08:51:38 -070053 labelPaint.setColor(SK_ColorWHITE);
Mike Kleinea3f0142019-03-20 11:12:10 -050054 SkFont font(ToolUtils::create_portable_typeface(), SkIntToScalar(kLabelTextSize));
bsalomon87cbcf32015-04-22 08:51:38 -070055 SkPaint linePaint;
56 linePaint.setColor(SK_ColorWHITE);
57
caryclarkf597c422015-07-28 10:37:53 -070058 // Draw row labels
59 canvas->save();
60 canvas->translate(0, SkIntToScalar(kLabelOffsetY));
61 for (int i = 0; i <= kSubPixelSteps; ++i) {
62 offset.printf("%d", i);
Hal Canarydf2d27e2019-01-08 09:38:02 -050063 canvas->drawString(offset, 0, i * kTrans + SkIntToScalar(kLabelTextSize),
64 font, labelPaint);
caryclarkf597c422015-07-28 10:37:53 -070065 }
66 canvas->restore();
bsalomon87cbcf32015-04-22 08:51:38 -070067
caryclarkf597c422015-07-28 10:37:53 -070068 // Draw col labels
69 canvas->save();
70 canvas->translate(SkIntToScalar(kLabelOffsetX), 0);
71 for (int i = 0; i <= kSubPixelSteps; ++i) {
72 offset.printf("%d", i);
Hal Canarydf2d27e2019-01-08 09:38:02 -050073 canvas->drawString(offset, i * SkIntToScalar(kTrans), SkIntToScalar(kLabelTextSize),
74 font, labelPaint);
caryclarkf597c422015-07-28 10:37:53 -070075 }
76 canvas->restore();
bsalomon87cbcf32015-04-22 08:51:38 -070077
bsalomonc6534a22015-04-22 11:34:46 -070078 canvas->translate(SkIntToScalar(kLabelOffsetX), SkIntToScalar(kLabelOffsetY));
bsalomon87cbcf32015-04-22 08:51:38 -070079
80 // Draw test case grid lines (Draw them all at pixel centers to hopefully avoid any
81 // snapping issues).
82 for (int i = 0; i <= kSubPixelSteps + 1; ++i) {
83 canvas->drawLine(0.5f,
84 i * SkIntToScalar(kTrans) + 0.5f,
85 SkIntToScalar(kTrans) * (kSubPixelSteps + 1) + 0.5f,
86 i * SkIntToScalar(kTrans) + 0.5f,
87 linePaint);
88 canvas->drawLine(i * SkIntToScalar(kTrans) + 0.5f,
89 0.5f,
90 i * SkIntToScalar(kTrans) + 0.5f,
91 SkIntToScalar(kTrans) * (kSubPixelSteps + 1) + 0.5f,
92 linePaint);
93 }
94
95 for (int i = 0; i <= kSubPixelSteps; ++i) {
96 for (int j = 0; j <= kSubPixelSteps; ++j) {
97 canvas->save();
98 // +1's account for the grid lines around each test case.
99 canvas->translate(j * (kTrans + 1.f/kSubPixelSteps) + 1,
100 i * (kTrans + 1.f/kSubPixelSteps) + 1);
101 this->drawElement(canvas);
102 canvas->restore();
103 }
104 }
105 }
106
107 virtual void drawElement(SkCanvas*) = 0;
108
109private:
John Stiles7571f9e2020-09-02 22:42:33 -0400110 using INHERITED = skiagm::GM;
bsalomon87cbcf32015-04-22 08:51:38 -0700111};
112
113class PointSnapGM : public PixelSnapGM {
114protected:
115 SkString onShortName() override { return SkString("pixel_snap_point"); }
Mike Reed3661bc92017-02-22 13:21:42 -0500116 void drawElement(SkCanvas* canvas) override {
117 const SkPoint pt = { 1, 1 };
118 SkPaint paint;
119 paint.setColor(SK_ColorBLUE);
120 canvas->drawPoints(SkCanvas::kPoints_PointMode, 1, &pt, paint);
121 }
bsalomon87cbcf32015-04-22 08:51:38 -0700122
123private:
John Stiles7571f9e2020-09-02 22:42:33 -0400124 using INHERITED = PixelSnapGM;
bsalomon87cbcf32015-04-22 08:51:38 -0700125};
126
127class LineSnapGM : public PixelSnapGM {
128protected:
129 SkString onShortName() override { return SkString("pixel_snap_line"); }
130 void drawElement(SkCanvas* canvas) override {
131 SkPaint paint;
132 paint.setColor(SK_ColorGREEN);
133 // Draw a horizontal and vertical line, each length 3.
134 canvas->drawLine(1, 1, 4, 1, paint);
135 canvas->drawLine(6, 1, 6, 4, paint);
136 }
137
138private:
John Stiles7571f9e2020-09-02 22:42:33 -0400139 using INHERITED = PixelSnapGM;
bsalomon87cbcf32015-04-22 08:51:38 -0700140};
141
142class RectSnapGM : public PixelSnapGM {
143protected:
144 SkString onShortName() override { return SkString("pixel_snap_rect"); }
145 void drawElement(SkCanvas* canvas) override {
146 SkPaint paint;
147 paint.setColor(SK_ColorRED);
148 canvas->drawRect(SkRect::MakeXYWH(1, 1, 3, 3), paint);
149 }
150
151private:
John Stiles7571f9e2020-09-02 22:42:33 -0400152 using INHERITED = PixelSnapGM;
bsalomon87cbcf32015-04-22 08:51:38 -0700153};
154
155class ComboSnapGM : public PixelSnapGM {
156protected:
157 SkString onShortName() override { return SkString("pixel_snap_combo"); }
158 void drawElement(SkCanvas* canvas) override {
159 SkPaint paint;
160 paint.setAntiAlias(false);
161 // A rectangle that exactly covers a pixel, a point at each corner, 8 horiz/vert lines
162 // at rect corners (two at each corner, extending away from rect). They are drawn in this
163 // order lines (green), points (blue), rect(red).
164 SkRect rect = SkRect::MakeXYWH(3, 3, 1, 1);
165 paint.setColor(SK_ColorGREEN);
Mike Reed3661bc92017-02-22 13:21:42 -0500166 const SkPoint lines[] = {
167 { 3, 3 }, { 0, 3 },
168 { 3, 3 }, { 3, 0 },
169 { 4, 3 }, { 7, 3 },
170 { 4, 3 }, { 4, 0 },
171 { 3, 4 }, { 0, 4 },
172 { 3, 4 }, { 3, 7 },
173 { 4, 4 }, { 7, 4 },
174 { 4, 4 }, { 4, 7 },
175 };
176 canvas->drawPoints(SkCanvas::kLines_PointMode, SK_ARRAY_COUNT(lines), lines, paint);
177
178 const SkPoint pts[] = {
179 { 4, 3 }, { 4, 4, }, { 3, 3 }, { 3, 4 },
180 };
181 paint.setColor(SK_ColorBLUE);
182 canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(pts), pts, paint);
183
bsalomon87cbcf32015-04-22 08:51:38 -0700184 paint.setColor(SK_ColorRED);
185 canvas->drawRect(rect, paint);
186 }
187
188private:
John Stiles7571f9e2020-09-02 22:42:33 -0400189 using INHERITED = PixelSnapGM;
bsalomon87cbcf32015-04-22 08:51:38 -0700190};
191
192//////////////////////////////////////////////////////////////////////////////
halcanary385fe4d2015-08-26 13:07:48 -0700193DEF_GM(return new PointSnapGM;)
194DEF_GM(return new LineSnapGM;)
195DEF_GM(return new RectSnapGM;)
196DEF_GM(return new ComboSnapGM;)