Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
overstroke.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2016 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
9/*
10 * This GM exercises stroking of paths with large stroke lengths, which is
11 * referred to as "overstroke" for brevity. In Skia as of 8/2016 we offset
12 * each part of the curve the request amount even if it makes the offsets
13 * overlap and create holes. There is not a really great algorithm for this
14 * and several other 2D graphics engines have the same bug.
15 *
16 * The old Nvidia Path Renderer used to yield correct results, so a possible
17 * direction of attack is to use the GPU and a completely different algorithm.
18 *
19 * See crbug.com/589769 skbug.com/5405 skbug.com/5406
20 */
21
22#include "gm/gm.h"
30#include "include/core/SkRect.h"
33
34#include <cstddef>
35
38
39//////// path and paint builders
40
42 SkPaint p;
43 p.setAntiAlias(true);
44 p.setStyle(SkPaint::kStroke_Style);
45 p.setStrokeWidth(NORMALSTROKE_WIDTH);
46 p.setColor(SK_ColorBLUE);
47
48 return p;
49}
50
52 SkPaint p;
53 p.setAntiAlias(true);
54 p.setStyle(SkPaint::kStroke_Style);
55 p.setStrokeWidth(OVERSTROKE_WIDTH);
56
57 return p;
58}
59
61 return SkPathBuilder().moveTo(0, 0)
62 .lineTo(100, 0)
63 .quadTo(50, -40, 0, 0)
64 .close()
65 .detach();
66}
67
69 SkPath path;
70 path.moveTo(0, 0);
71 path.cubicTo(25, 75,
72 75, -50,
73 100, 0);
74
75 return path;
76}
77
79 SkRect oval = SkRect::MakeXYWH(0, -25, 100, 50);
80
81 return SkPathBuilder().arcTo(oval, 0, 359, true).close().detach();
82}
83
85 SkPath ribs;
86
87 const SkScalar spacing = 5.0f;
88 float accum = 0.0f;
89
90 SkPathMeasure meas(path, false);
91 SkScalar length = meas.getLength();
93 SkVector tan;
94 while (accum < length) {
95 if (meas.getPosTan(accum, &pos, &tan)) {
96 tan.scale(radius);
98
99 ribs.moveTo(pos.x() + tan.x(), pos.y() + tan.y());
100 ribs.lineTo(pos.x() - tan.x(), pos.y() - tan.y());
101 }
102 accum += spacing;
103 }
104
105 return ribs;
106}
107
108void draw_ribs(SkCanvas *canvas, SkPath path) {
109 SkPath ribs = ribs_path(path, OVERSTROKE_WIDTH/2.0f);
111 p.setStrokeWidth(1);
112 p.setColor(SK_ColorBLUE);
113 p.setColor(SK_ColorGREEN);
114
115 canvas->drawPath(ribs, p);
116}
117
118///////// quads
119
121 // scaled so it's visible
122 // canvas->scale(8, 8);
123
125 SkPath path = quad_path();
126
127 draw_ribs(canvas, path);
128 canvas->drawPath(path, p);
129}
130
133 SkPath path = quad_path();
134
135 canvas->drawPath(path, p);
136 draw_ribs(canvas, path);
137}
138
140 SkPath path = quad_path();
142
143 SkPaint fillp = make_normal_paint();
145
146 SkPath fillpath;
147 skpathutils::FillPathWithPaint(path, p, &fillpath);
148
149 canvas->drawPath(fillpath, fillp);
150}
151
153 canvas->translate(400, 0);
154 draw_large_quad(canvas);
155 draw_quad_fillpath(canvas);
156}
157
158////////// cubics
159
162 SkPath path = cubic_path();
163
164 draw_ribs(canvas, path);
165 canvas->drawPath(path, p);
166}
167
170 SkPath path = cubic_path();
171
172 canvas->drawPath(path, p);
173 draw_ribs(canvas, path);
174}
175
177 SkPath path = cubic_path();
179
180 SkPaint fillp = make_normal_paint();
182
183 SkPath fillpath;
184 skpathutils::FillPathWithPaint(path, p, &fillpath);
185
186 canvas->drawPath(fillpath, fillp);
187}
188
190 canvas->translate(400, 0);
191 draw_large_cubic(canvas);
192 draw_cubic_fillpath(canvas);
193}
194
195////////// ovals
196
199
200 SkPath path = oval_path();
201
202 draw_ribs(canvas, path);
203 canvas->drawPath(path, p);
204}
205
208 SkPath path = oval_path();
209
210 canvas->drawPath(path, p);
211 draw_ribs(canvas, path);
212}
213
215 SkPath path = oval_path();
217
218 SkPaint fillp = make_normal_paint();
220
221 SkPath fillpath;
222 skpathutils::FillPathWithPaint(path, p, &fillpath);
223
224 canvas->drawPath(fillpath, fillp);
225}
226
228 canvas->translate(400, 0);
229 draw_large_oval(canvas);
230 draw_oval_fillpath(canvas);
231}
232
233////////// gm
234
239
240DEF_SIMPLE_GM(OverStroke, canvas, 500, 500) {
241 const size_t length = sizeof(examples) / sizeof(examples[0]);
242 const size_t width = 2;
243
244 for (size_t i = 0; i < length; i++) {
245 int x = (int)(i % width);
246 int y = (int)(i / width);
247
248 canvas->save();
249 canvas->translate(150.0f * x, 150.0f * y);
250 canvas->scale(0.2f, 0.2f);
251 canvas->translate(300.0f, 400.0f);
252
253 examples[i](canvas);
254
255 canvas->restore();
256 }
257}
SkPoint pos
constexpr SkColor SK_ColorMAGENTA
Definition SkColor.h:147
constexpr SkColor SK_ColorBLUE
Definition SkColor.h:135
constexpr SkColor SK_ColorGREEN
Definition SkColor.h:131
Type::kYUV Type::kRGBA() int(0.7 *637)
void translate(SkScalar dx, SkScalar dy)
void drawPath(const SkPath &path, const SkPaint &paint)
void setColor(SkColor color)
Definition SkPaint.cpp:119
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
SkPathBuilder & close()
SkPathBuilder & arcTo(const SkRect &oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg, bool forceMoveTo)
SkPathBuilder & lineTo(SkPoint pt)
SkPathBuilder & moveTo(SkPoint pt)
SkPathBuilder & quadTo(SkPoint pt1, SkPoint pt2)
SkScalar getLength()
bool getPosTan(SkScalar distance, SkPoint *position, SkVector *tangent)
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
SkPath & lineTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:718
static void RotateCCW(const SkPoint &src, SkPoint *dst)
Definition SkPointPriv.h:72
float SkScalar
Definition extension.cpp:12
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
Definition gm.h:50
size_t length
double y
double x
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)
void draw_ribs(SkCanvas *canvas, SkPath path)
SkPaint make_normal_paint()
void draw_large_quad(SkCanvas *canvas)
const SkScalar OVERSTROKE_WIDTH
SkPath quad_path()
SkPath cubic_path()
void(* examples[])(SkCanvas *canvas)
SkPath ribs_path(SkPath path, SkScalar radius)
void draw_stroked_quad(SkCanvas *canvas)
void draw_quad_fillpath(SkCanvas *canvas)
void draw_oval_fillpath(SkCanvas *canvas)
SkPath oval_path()
void draw_stroked_oval(SkCanvas *canvas)
const SkScalar NORMALSTROKE_WIDTH
SkPaint make_overstroke_paint()
void draw_small_quad(SkCanvas *canvas)
void draw_large_cubic(SkCanvas *canvas)
void draw_small_oval(SkCanvas *canvas)
void draw_stroked_cubic(SkCanvas *canvas)
void draw_large_oval(SkCanvas *canvas)
void draw_small_cubic(SkCanvas *canvas)
void draw_cubic_fillpath(SkCanvas *canvas)
int32_t width
void scale(float scale, SkPoint *dst) const
Definition SkPoint.cpp:17
constexpr float y() const
constexpr float x() const
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659