xref: /aosp_15_r20/external/skia/gm/strokerect.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2012 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/SkColor.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkPath.h"
13 #include "include/core/SkPathUtils.h"
14 #include "include/core/SkPoint.h"
15 #include "include/core/SkRect.h"
16 #include "include/core/SkScalar.h"
17 #include "include/core/SkSize.h"
18 #include "include/core/SkString.h"
19 #include "include/core/SkTypes.h"
20 #include "include/private/base/SkTemplates.h"
21 
22 #include <float.h>
23 
24 using namespace skia_private;
25 
26 #define STROKE_WIDTH    SkIntToScalar(20)
27 
draw_path(SkCanvas * canvas,const SkPath & path,const SkRect & rect,SkPaint::Join join,int doFill)28 static void draw_path(SkCanvas* canvas, const SkPath& path, const SkRect& rect,
29                       SkPaint::Join join, int doFill) {
30     SkPaint paint;
31     paint.setAntiAlias(true);
32     paint.setStyle(doFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style);
33 
34     paint.setColor(SK_ColorGRAY);
35     paint.setStrokeWidth(STROKE_WIDTH);
36     paint.setStrokeJoin(join);
37     canvas->drawRect(rect, paint);
38 
39     paint.setStyle(SkPaint::kStroke_Style);
40     paint.setStrokeWidth(0);
41     paint.setColor(SK_ColorRED);
42     canvas->drawPath(path, paint);
43 
44     paint.setStrokeWidth(3);
45     paint.setStrokeJoin(SkPaint::kMiter_Join);
46     int n = path.countPoints();
47     AutoTArray<SkPoint> points(n);
48     path.getPoints(points.get(), n);
49     canvas->drawPoints(SkCanvas::kPoints_PointMode, n, points.get(), paint);
50 }
51 
52 /*
53  *  Test calling SkStroker for rectangles. Cases to cover:
54  *
55  *  geometry: normal, small (smaller than stroke-width), empty, inverted
56  *  joint-type for the corners
57  */
58 class StrokeRectGM : public skiagm::GM {
59 public:
StrokeRectGM()60     StrokeRectGM() {}
61 
62 protected:
getName() const63     SkString getName() const override { return SkString("strokerect"); }
64 
getISize()65     SkISize getISize() override { return SkISize::Make(1400, 740); }
66 
onDraw(SkCanvas * canvas)67     void onDraw(SkCanvas* canvas) override {
68         canvas->drawColor(SK_ColorWHITE);
69         canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
70 
71         SkPaint paint;
72         paint.setStyle(SkPaint::kStroke_Style);
73         paint.setStrokeWidth(STROKE_WIDTH);
74 
75         constexpr SkPaint::Join gJoins[] = {
76             SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join
77         };
78 
79         constexpr SkScalar W = 80;
80         constexpr SkScalar H = 80;
81         constexpr SkRect gRects[] = {
82             { 0, 0, W, H },
83             { W, 0, 0, H },
84             { 0, H, W, 0 },
85             { 0, 0, STROKE_WIDTH, H },
86             { 0, 0, W, STROKE_WIDTH },
87             { 0, 0, STROKE_WIDTH/2, STROKE_WIDTH/2 },
88             { 0, 0, W, 0 },
89             { 0, 0, 0, H },
90             { 0, 0, 0, 0 },
91             { 0, 0, W, FLT_EPSILON },
92             { 0, 0, FLT_EPSILON, H },
93             { 0, 0, FLT_EPSILON, FLT_EPSILON },
94         };
95 
96         for (int doFill = 0; doFill <= 1; ++doFill) {
97             for (size_t i = 0; i < std::size(gJoins); ++i) {
98                 SkPaint::Join join = gJoins[i];
99                 paint.setStrokeJoin(join);
100 
101                 SkAutoCanvasRestore acr(canvas, true);
102                 for (size_t j = 0; j < std::size(gRects); ++j) {
103                     const SkRect& r = gRects[j];
104 
105                     SkPath path, fillPath;
106                     path.addRect(r);
107                     skpathutils::FillPathWithPaint(path, paint, &fillPath);
108                     draw_path(canvas, fillPath, r, join, doFill);
109 
110                     canvas->translate(W + 2 * STROKE_WIDTH, 0);
111                 }
112                 acr.restore();
113                 canvas->translate(0, H + 2 * STROKE_WIDTH);
114             }
115             paint.setStyle(SkPaint::kStrokeAndFill_Style);
116         }
117     }
118 
119 private:
120     using INHERITED = GM;
121 };
122 DEF_GM(return new StrokeRectGM;)
123 
124 ///////////////////////////////////////////////////////////////////////////////////////////////////
125 
126 /*
127  *  Exercise rect-stroking (which is specialized from paths) when the resulting stroke-width is
128  *  non-square. See https://bugs.chromium.org/p/skia/issues/detail?id=5408
129  */
130 DEF_SIMPLE_GM(strokerect_anisotropic_5408, canvas, 200, 50) {
131     SkPaint p;
132     p.setStyle(SkPaint::kStroke_Style);
133     p.setStrokeWidth(6);
134 
135     canvas->scale(10, 1);
136     SkRect r = SkRect::MakeXYWH(5, 20, 10, 10);
137     canvas->drawRect(r, p);
138 }
139