1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "gm/gm.h"
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
12cb93a386Sopenharmony_ci#include "include/core/SkPathBuilder.h"
13cb93a386Sopenharmony_ci#include "include/core/SkRRect.h"
14cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
15cb93a386Sopenharmony_ci#include "include/core/SkScalar.h"
16cb93a386Sopenharmony_ci#include "include/core/SkSize.h"
17cb93a386Sopenharmony_ci#include "include/core/SkString.h"
18cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
19cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h"
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_cinamespace skiagm {
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci// Test out various combinations of nested rects, ovals and rrects.
24cb93a386Sopenharmony_ciclass NestedGM : public GM {
25cb93a386Sopenharmony_cipublic:
26cb93a386Sopenharmony_ci    NestedGM(bool doAA, bool flipped) : fDoAA(doAA), fFlipped(flipped) {
27cb93a386Sopenharmony_ci        this->setBGColor(0xFFDDDDDD);
28cb93a386Sopenharmony_ci    }
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ciprotected:
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    SkString onShortName() override {
33cb93a386Sopenharmony_ci        SkString name("nested");
34cb93a386Sopenharmony_ci        if (fFlipped) {
35cb93a386Sopenharmony_ci            name.append("_flipY");
36cb93a386Sopenharmony_ci        }
37cb93a386Sopenharmony_ci        if (fDoAA) {
38cb93a386Sopenharmony_ci            name.append("_aa");
39cb93a386Sopenharmony_ci        } else {
40cb93a386Sopenharmony_ci            name.append("_bw");
41cb93a386Sopenharmony_ci        }
42cb93a386Sopenharmony_ci        return name;
43cb93a386Sopenharmony_ci    }
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_ci    SkISize onISize() override {
46cb93a386Sopenharmony_ci        return SkISize::Make(kImageWidth, kImageHeight);
47cb93a386Sopenharmony_ci    }
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    enum Shapes {
50cb93a386Sopenharmony_ci        kRect_Shape = 0,
51cb93a386Sopenharmony_ci        kRRect_Shape,
52cb93a386Sopenharmony_ci        kOval_Shape,
53cb93a386Sopenharmony_ci        kShapeCount
54cb93a386Sopenharmony_ci    };
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci    static void AddShape(SkPathBuilder* b, const SkRect& rect, Shapes shape, SkPathDirection dir) {
57cb93a386Sopenharmony_ci        switch (shape) {
58cb93a386Sopenharmony_ci            case kRect_Shape:
59cb93a386Sopenharmony_ci                b->addRect(rect, dir);
60cb93a386Sopenharmony_ci                break;
61cb93a386Sopenharmony_ci            case kRRect_Shape: {
62cb93a386Sopenharmony_ci                SkRRect rr;
63cb93a386Sopenharmony_ci                rr.setRectXY(rect, 5, 5);
64cb93a386Sopenharmony_ci                b->addRRect(rr, dir);
65cb93a386Sopenharmony_ci                break;
66cb93a386Sopenharmony_ci                }
67cb93a386Sopenharmony_ci            case kOval_Shape:
68cb93a386Sopenharmony_ci                b->addOval(rect, dir);
69cb93a386Sopenharmony_ci                break;
70cb93a386Sopenharmony_ci            default:
71cb93a386Sopenharmony_ci                break;
72cb93a386Sopenharmony_ci        }
73cb93a386Sopenharmony_ci    }
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    void onDraw(SkCanvas* canvas) override {
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci        SkPaint shapePaint;
78cb93a386Sopenharmony_ci        shapePaint.setColor(SK_ColorBLACK);
79cb93a386Sopenharmony_ci        shapePaint.setAntiAlias(fDoAA);
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci        SkRect outerRect = SkRect::MakeWH(40, 40);
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ci        SkRect innerRects[] = {
84cb93a386Sopenharmony_ci            { 10, 10, 30, 30 },     // small
85cb93a386Sopenharmony_ci            { .5f, 18, 4.5f, 22 }   // smaller and offset to left
86cb93a386Sopenharmony_ci        };
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ci        // draw a background pattern to make transparency errors more apparent
89cb93a386Sopenharmony_ci        SkRandom rand;
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ci        for (int y = 0; y < kImageHeight; y += 10) {
92cb93a386Sopenharmony_ci            for (int x = 0; x < kImageWidth; x += 10) {
93cb93a386Sopenharmony_ci                SkRect r = SkRect::MakeXYWH(SkIntToScalar(x),
94cb93a386Sopenharmony_ci                                            SkIntToScalar(y),
95cb93a386Sopenharmony_ci                                            10, 10);
96cb93a386Sopenharmony_ci                SkPaint p;
97cb93a386Sopenharmony_ci                p.setColor(rand.nextU() | 0xFF000000);
98cb93a386Sopenharmony_ci                canvas->drawRect(r, p);
99cb93a386Sopenharmony_ci            }
100cb93a386Sopenharmony_ci        }
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci        SkScalar xOff = 2, yOff = 2;
103cb93a386Sopenharmony_ci        for (int outerShape = 0; outerShape < kShapeCount; ++outerShape) {
104cb93a386Sopenharmony_ci            for (int innerShape = 0; innerShape < kShapeCount; ++innerShape) {
105cb93a386Sopenharmony_ci                for (size_t innerRect = 0; innerRect < SK_ARRAY_COUNT(innerRects); ++innerRect) {
106cb93a386Sopenharmony_ci                    SkPathBuilder builder;
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci                    AddShape(&builder, outerRect, (Shapes) outerShape, SkPathDirection::kCW);
109cb93a386Sopenharmony_ci                    AddShape(&builder, innerRects[innerRect], (Shapes) innerShape,
110cb93a386Sopenharmony_ci                             SkPathDirection::kCCW);
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci                    canvas->save();
113cb93a386Sopenharmony_ci                    if (fFlipped) {
114cb93a386Sopenharmony_ci                        canvas->scale(1.0f, -1.0f);
115cb93a386Sopenharmony_ci                        canvas->translate(xOff, -yOff - 40.0f);
116cb93a386Sopenharmony_ci                    } else {
117cb93a386Sopenharmony_ci                        canvas->translate(xOff, yOff);
118cb93a386Sopenharmony_ci                    }
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci                    canvas->drawPath(builder.detach(), shapePaint);
121cb93a386Sopenharmony_ci                    canvas->restore();
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci                    xOff += 45;
124cb93a386Sopenharmony_ci                }
125cb93a386Sopenharmony_ci            }
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci            xOff = 2;
128cb93a386Sopenharmony_ci            yOff += 45;
129cb93a386Sopenharmony_ci        }
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci    }
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ciprivate:
134cb93a386Sopenharmony_ci    inline static constexpr int kImageWidth = 269;
135cb93a386Sopenharmony_ci    inline static constexpr int kImageHeight = 134;
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci    bool fDoAA;
138cb93a386Sopenharmony_ci    bool fFlipped;
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci    using INHERITED = GM;
141cb93a386Sopenharmony_ci};
142cb93a386Sopenharmony_ci
143cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
144cb93a386Sopenharmony_ci
145cb93a386Sopenharmony_ciDEF_GM( return new NestedGM(/* doAA = */ true,  /* flipped = */ false); )
146cb93a386Sopenharmony_ciDEF_GM( return new NestedGM(/* doAA = */ false, /* flipped = */ false); )
147cb93a386Sopenharmony_ciDEF_GM( return new NestedGM(/* doAA = */ true,  /* flipped = */ true); )
148cb93a386Sopenharmony_ciDEF_GM( return new NestedGM(/* doAA = */ false, /* flipped = */ true); )
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_ciDEF_SIMPLE_GM(nested_hairline_square, canvas, 64, 64) {
151cb93a386Sopenharmony_ci    // See crbug.com/1234194 - This should draw 1 row of 3 stroked squares, with a second 0.5px
152cb93a386Sopenharmony_ci    // shifted row of squares below it.
153cb93a386Sopenharmony_ci    auto drawEllipses = [&]() {
154cb93a386Sopenharmony_ci        canvas->save();
155cb93a386Sopenharmony_ci        // Originally the SVG string "M5,14H0V9h5V14Z M1,13h3v-3H1V13Z" but that just specifies a
156cb93a386Sopenharmony_ci        // 5px wide square outside a 3px wide square.
157cb93a386Sopenharmony_ci        SkPath square;
158cb93a386Sopenharmony_ci        square.addRect(SkRect::MakeLTRB(0.f, 9.f, 5.f, 14.f));
159cb93a386Sopenharmony_ci        square.addRect(SkRect::MakeLTRB(1.f, 10.f, 4.f, 13.f), SkPathDirection::kCCW);
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_ci        // From the bug, SVG viewbox was (0, 0, 24, 24), so the above coordinates are relative to
162cb93a386Sopenharmony_ci        // that, but the svg was then the child of a div that was 16x16, so it's scaled down. This
163cb93a386Sopenharmony_ci        // converts the 1px wide nested rects into subpixel nested rects.
164cb93a386Sopenharmony_ci        canvas->scale(16.f / 24.f, 16.f / 24.f);
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci        SkPaint paint;
167cb93a386Sopenharmony_ci        paint.setColor(SkColorSetARGB(255, 70, 70, 70));
168cb93a386Sopenharmony_ci        paint.setAntiAlias(true);
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci        // The original SVG drew 3 separate paths, but these were just translations of the original
171cb93a386Sopenharmony_ci        // path baked into a path string.
172cb93a386Sopenharmony_ci        canvas->drawPath(square, paint);
173cb93a386Sopenharmony_ci        canvas->translate(10.f, 0.f);
174cb93a386Sopenharmony_ci        canvas->drawPath(square, paint);
175cb93a386Sopenharmony_ci        canvas->translate(10.f, 0.f);
176cb93a386Sopenharmony_ci        canvas->drawPath(square, paint);
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ci        canvas->restore();
179cb93a386Sopenharmony_ci    };
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_ci    drawEllipses();
182cb93a386Sopenharmony_ci    canvas->translate(0.5f, 16.f);
183cb93a386Sopenharmony_ci    drawEllipses();
184cb93a386Sopenharmony_ci}
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ci}  // namespace skiagm
187