blob: 19b0121ea542626c41cb9bfd6ec54e9c5b0131c5 [file] [log] [blame]
robertphillips@google.com8d3c6402013-08-20 12:11:31 +00001/*
2 * Copyright 2013 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/SkPaint.h"
Mike Reed92f6eb12020-08-25 11:48:41 -040012#include "include/core/SkPathBuilder.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkRRect.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040014#include "include/core/SkRect.h"
15#include "include/core/SkScalar.h"
16#include "include/core/SkSize.h"
17#include "include/core/SkString.h"
18#include "include/core/SkTypes.h"
Kevin Lubick0d4d1142023-02-13 09:13:10 -050019#include "src/base/SkRandom.h"
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000020
21namespace skiagm {
22
23// Test out various combinations of nested rects, ovals and rrects.
24class NestedGM : public GM {
25public:
robertphillips2e5b4c52015-05-19 04:35:38 -070026 NestedGM(bool doAA, bool flipped) : fDoAA(doAA), fFlipped(flipped) {
Mike Kleind46dce32018-08-16 10:17:03 -040027 this->setBGColor(0xFFDDDDDD);
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000028 }
29
30protected:
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000031 SkString getName() const override {
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000032 SkString name("nested");
robertphillips2e5b4c52015-05-19 04:35:38 -070033 if (fFlipped) {
34 name.append("_flipY");
35 }
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000036 if (fDoAA) {
37 name.append("_aa");
38 } else {
39 name.append("_bw");
40 }
41 return name;
42 }
43
Leandro Lovisolo8f023882023-08-15 21:13:52 +000044 SkISize getISize() override { return SkISize::Make(kImageWidth, kImageHeight); }
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000045
46 enum Shapes {
47 kRect_Shape = 0,
48 kRRect_Shape,
49 kOval_Shape,
50 kShapeCount
51 };
52
Mike Reed92f6eb12020-08-25 11:48:41 -040053 static void AddShape(SkPathBuilder* b, const SkRect& rect, Shapes shape, SkPathDirection dir) {
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000054 switch (shape) {
55 case kRect_Shape:
Mike Reed92f6eb12020-08-25 11:48:41 -040056 b->addRect(rect, dir);
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000057 break;
58 case kRRect_Shape: {
59 SkRRect rr;
60 rr.setRectXY(rect, 5, 5);
Mike Reed92f6eb12020-08-25 11:48:41 -040061 b->addRRect(rr, dir);
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000062 break;
63 }
64 case kOval_Shape:
Mike Reed92f6eb12020-08-25 11:48:41 -040065 b->addOval(rect, dir);
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000066 break;
67 default:
68 break;
69 }
70 }
71
mtklein36352bf2015-03-25 18:17:31 -070072 void onDraw(SkCanvas* canvas) override {
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000073
74 SkPaint shapePaint;
75 shapePaint.setColor(SK_ColorBLACK);
76 shapePaint.setAntiAlias(fDoAA);
77
78 SkRect outerRect = SkRect::MakeWH(40, 40);
79
80 SkRect innerRects[] = {
81 { 10, 10, 30, 30 }, // small
82 { .5f, 18, 4.5f, 22 } // smaller and offset to left
83 };
84
85 // draw a background pattern to make transparency errors more apparent
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000086 SkRandom rand;
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000087
88 for (int y = 0; y < kImageHeight; y += 10) {
89 for (int x = 0; x < kImageWidth; x += 10) {
skia.committer@gmail.comb74bdf02013-08-21 07:01:29 +000090 SkRect r = SkRect::MakeXYWH(SkIntToScalar(x),
91 SkIntToScalar(y),
robertphillips@google.com8d3c6402013-08-20 12:11:31 +000092 10, 10);
93 SkPaint p;
94 p.setColor(rand.nextU() | 0xFF000000);
95 canvas->drawRect(r, p);
96 }
97 }
98
robertphillips2e5b4c52015-05-19 04:35:38 -070099 SkScalar xOff = 2, yOff = 2;
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000100 for (int outerShape = 0; outerShape < kShapeCount; ++outerShape) {
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000101 for (int innerShape = 0; innerShape < kShapeCount; ++innerShape) {
Herb Derbyc37b3862022-06-21 09:49:17 -0400102 for (size_t innerRect = 0; innerRect < std::size(innerRects); ++innerRect) {
Mike Reed92f6eb12020-08-25 11:48:41 -0400103 SkPathBuilder builder;
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000104
Mike Reed92f6eb12020-08-25 11:48:41 -0400105 AddShape(&builder, outerRect, (Shapes) outerShape, SkPathDirection::kCW);
106 AddShape(&builder, innerRects[innerRect], (Shapes) innerShape,
Mike Reed30bc5272019-11-22 18:34:02 +0000107 SkPathDirection::kCCW);
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000108
robertphillips2e5b4c52015-05-19 04:35:38 -0700109 canvas->save();
110 if (fFlipped) {
111 canvas->scale(1.0f, -1.0f);
112 canvas->translate(xOff, -yOff - 40.0f);
113 } else {
114 canvas->translate(xOff, yOff);
115 }
116
Mike Reed92f6eb12020-08-25 11:48:41 -0400117 canvas->drawPath(builder.detach(), shapePaint);
robertphillips2e5b4c52015-05-19 04:35:38 -0700118 canvas->restore();
119
120 xOff += 45;
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000121 }
122 }
robertphillips2e5b4c52015-05-19 04:35:38 -0700123
124 xOff = 2;
125 yOff += 45;
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000126 }
127
128 }
129
130private:
Brian Salomon9fa47cc2021-10-08 18:48:26 -0400131 inline static constexpr int kImageWidth = 269;
132 inline static constexpr int kImageHeight = 134;
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000133
134 bool fDoAA;
robertphillips2e5b4c52015-05-19 04:35:38 -0700135 bool fFlipped;
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000136
John Stiles7571f9e2020-09-02 22:42:33 -0400137 using INHERITED = GM;
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000138};
139
140///////////////////////////////////////////////////////////////////////////////
141
robertphillips2e5b4c52015-05-19 04:35:38 -0700142DEF_GM( return new NestedGM(/* doAA = */ true, /* flipped = */ false); )
143DEF_GM( return new NestedGM(/* doAA = */ false, /* flipped = */ false); )
144DEF_GM( return new NestedGM(/* doAA = */ true, /* flipped = */ true); )
145DEF_GM( return new NestedGM(/* doAA = */ false, /* flipped = */ true); )
robertphillips@google.com8d3c6402013-08-20 12:11:31 +0000146
Michael Ludwig144926d2021-09-10 09:34:47 -0400147DEF_SIMPLE_GM(nested_hairline_square, canvas, 64, 64) {
148 // See crbug.com/1234194 - This should draw 1 row of 3 stroked squares, with a second 0.5px
149 // shifted row of squares below it.
150 auto drawEllipses = [&]() {
151 canvas->save();
152 // Originally the SVG string "M5,14H0V9h5V14Z M1,13h3v-3H1V13Z" but that just specifies a
153 // 5px wide square outside a 3px wide square.
154 SkPath square;
155 square.addRect(SkRect::MakeLTRB(0.f, 9.f, 5.f, 14.f));
156 square.addRect(SkRect::MakeLTRB(1.f, 10.f, 4.f, 13.f), SkPathDirection::kCCW);
157
158 // From the bug, SVG viewbox was (0, 0, 24, 24), so the above coordinates are relative to
159 // that, but the svg was then the child of a div that was 16x16, so it's scaled down. This
160 // converts the 1px wide nested rects into subpixel nested rects.
161 canvas->scale(16.f / 24.f, 16.f / 24.f);
162
163 SkPaint paint;
164 paint.setColor(SkColorSetARGB(255, 70, 70, 70));
165 paint.setAntiAlias(true);
166
167 // The original SVG drew 3 separate paths, but these were just translations of the original
168 // path baked into a path string.
169 canvas->drawPath(square, paint);
170 canvas->translate(10.f, 0.f);
171 canvas->drawPath(square, paint);
172 canvas->translate(10.f, 0.f);
173 canvas->drawPath(square, paint);
174
175 canvas->restore();
176 };
177
178 drawEllipses();
179 canvas->translate(0.5f, 16.f);
180 drawEllipses();
181}
182
John Stilesa6841be2020-08-06 14:11:56 -0400183} // namespace skiagm