xref: /third_party/skia/gm/inversepaths.cpp (revision cb93a386)
1/*
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
8#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkPaint.h"
11#include "include/core/SkPath.h"
12#include "include/core/SkPathEffect.h"
13#include "include/core/SkRect.h"
14#include "include/core/SkRefCnt.h"
15#include "include/core/SkScalar.h"
16#include "include/core/SkTypes.h"
17#include "include/effects/SkDashPathEffect.h"
18
19#include <utility>
20
21static SkPath generate_square(SkScalar cx, SkScalar cy, SkScalar w) {
22    return SkPath::Rect(SkRect::MakeXYWH(cx - w / 2, cy - w / 2, w, w));
23}
24
25static SkPath generate_rect_line(SkScalar cx, SkScalar cy, SkScalar l) {
26    return SkPath::Rect(SkRect::MakeXYWH(cx - l / 2, cy, l, 0));
27}
28
29static SkPath generate_circle(SkScalar cx, SkScalar cy, SkScalar d) {
30    return SkPath::Circle(cx, cy, d/2, SkPathDirection::kCW);
31}
32
33static SkPath generate_line(SkScalar cx, SkScalar cy, SkScalar l) {
34    return SkPath::Line({cx - l / 2, cy}, {cx + l / 2, cy});
35}
36
37namespace {
38struct Style {
39    Style(SkPaint::Style paintStyle, sk_sp<SkPathEffect> pe = sk_sp<SkPathEffect>())
40        : fPaintStyle(paintStyle)
41        , fPathEffect(std::move(pe)) {}
42    SkPaint::Style      fPaintStyle;
43    sk_sp<SkPathEffect> fPathEffect;
44};
45
46sk_sp<SkPathEffect> make_dash() {
47    constexpr SkScalar kIntervals[] = { 4.f, 3.f };
48    return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), 0);
49}
50
51Style styles[] {
52    {SkPaint::kStroke_Style},
53    {SkPaint::kStrokeAndFill_Style},
54    {SkPaint::kFill_Style},
55    {SkPaint::kStroke_Style, make_dash()},
56};
57
58SkScalar pathSizes[] = {
59        40,
60        10,
61        0
62};
63SkScalar strokeWidths[] = {
64        10,
65        0
66};
67SkPath (*paths[])(SkScalar, SkScalar, SkScalar) = {
68        generate_square,
69        generate_rect_line,
70        generate_circle,
71        generate_line
72};
73
74const SkScalar slideWidth = 90, slideHeight = 90;
75const SkScalar slideBoundary = 5;
76
77}  // namespace
78
79DEF_SIMPLE_GM(inverse_paths, canvas, 800, 1200) {
80    SkScalar cx = slideWidth / 2 + slideBoundary;
81    SkScalar cy = slideHeight / 2 + slideBoundary;
82    SkScalar dx = slideWidth + 2 * slideBoundary;
83    SkScalar dy = slideHeight + 2 * slideBoundary;
84
85    SkRect clipRect = SkRect::MakeLTRB(slideBoundary, slideBoundary,
86                                       slideBoundary + slideWidth,
87                                       slideBoundary + slideHeight);
88    SkPaint clipPaint;
89    clipPaint.setStyle(SkPaint::kStroke_Style);
90    clipPaint.setStrokeWidth(SkIntToScalar(2));
91
92    SkPaint outlinePaint;
93    outlinePaint.setColor(0x40000000);
94    outlinePaint.setStyle(SkPaint::kStroke_Style);
95    outlinePaint.setStrokeWidth(SkIntToScalar(0));
96
97    for (size_t styleIndex = 0; styleIndex < SK_ARRAY_COUNT(styles);
98            styleIndex++) {
99        for (size_t sizeIndex = 0; sizeIndex < SK_ARRAY_COUNT(pathSizes);
100                sizeIndex++) {
101            SkScalar size = pathSizes[sizeIndex];
102
103            canvas->save();
104
105            for (size_t widthIndex = 0;
106                    widthIndex < SK_ARRAY_COUNT(strokeWidths);
107                    widthIndex++) {
108                SkPaint paint;
109                paint.setColor(0xff007000);
110                paint.setStrokeWidth(strokeWidths[widthIndex]);
111                paint.setStyle(styles[styleIndex].fPaintStyle);
112                paint.setPathEffect(styles[styleIndex].fPathEffect);
113
114                for (size_t pathIndex = 0;
115                        pathIndex < SK_ARRAY_COUNT(paths);
116                        pathIndex++) {
117                    canvas->drawRect(clipRect, clipPaint);
118
119                    canvas->save();
120                    canvas->clipRect(clipRect);
121
122                    SkPath path = paths[pathIndex](cx, cy, size);
123                    path.setFillType(SkPathFillType::kInverseWinding);
124                    canvas->drawPath(path, paint);
125
126                    path.setFillType(SkPathFillType::kWinding);
127                    canvas->drawPath(path, outlinePaint);
128
129                    canvas->restore();
130                    canvas->translate(dx, 0);
131                }
132            }
133            canvas->restore();
134            canvas->translate(0, dy);
135        }
136    }
137}
138