Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: gm/OverStroke.cpp

Issue 2218773003: Rework Overstroke GM to show differences between expected and actual (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Add note regarding nvpr Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 8
9 /* 9 /*
10 * This GM exercises stroking of paths with large stroke lengths, which is 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 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 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 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. 14 * and several other 2D graphics engines have the same bug.
15 * 15 *
16 * If we run this using Nvidia Path Renderer with:
17 * `path/to/dm --match OverStroke -w gm_out --gpu --config nvpr16`
18 * then we get correct results, so that is a possible direction of attack -
19 * use the GPU and a completely different algorithm to get correctness in
20 * Skia.
21 *
16 * See crbug.com/589769 skbug.com/5405 skbug.com/5406 22 * See crbug.com/589769 skbug.com/5405 skbug.com/5406
17 */ 23 */
18 24
19 25
20 #include "gm.h" 26 #include "gm.h"
21 #include "SkPaint.h" 27 #include "SkPaint.h"
22 #include "SkPath.h" 28 #include "SkPath.h"
29 #include "SkPathMeasure.h"
30
31 const SkScalar OVERSTROKE_WIDTH = 500.0f;
32 const SkScalar NORMALSTROKE_WIDTH = 3.0f;
23 33
24 //////// path and paint builders 34 //////// path and paint builders
25 35
36 SkPaint make_normal_paint() {
37 SkPaint p;
38 p.setAntiAlias(true);
39 p.setStyle(SkPaint::kStroke_Style);
40 p.setStrokeWidth(NORMALSTROKE_WIDTH);
41 p.setColor(SK_ColorBLUE);
42
43 return p;
44 }
45
26 SkPaint make_overstroke_paint() { 46 SkPaint make_overstroke_paint() {
27 SkPaint p; 47 SkPaint p;
28 p.setAntiAlias(true); 48 p.setAntiAlias(true);
29 p.setStyle(SkPaint::kStroke_Style); 49 p.setStyle(SkPaint::kStroke_Style);
30 p.setStrokeWidth(500); 50 p.setStrokeWidth(OVERSTROKE_WIDTH);
31 51
32 return p; 52 return p;
33 } 53 }
34 54
35 SkPath quad_path() { 55 SkPath quad_path() {
36 SkPath path; 56 SkPath path;
37 path.moveTo(0, 0); 57 path.moveTo(0, 0);
38 path.lineTo(100, 0); 58 path.lineTo(100, 0);
39 path.quadTo(50, -40, 59 path.quadTo(50, -40,
40 0, 0); 60 0, 0);
61 path.close();
41 62
42 return path; 63 return path;
43 } 64 }
44 65
45 SkPath cubic_path() { 66 SkPath cubic_path() {
46 SkPath path; 67 SkPath path;
47 path.moveTo(0, 0); 68 path.moveTo(0, 0);
48 path.cubicTo(25, 75, 69 path.cubicTo(25, 75,
49 75, -50, 70 75, -50,
50 100, 0); 71 100, 0);
51 72
52 return path; 73 return path;
53 } 74 }
54 75
55 SkPath oval_path() { 76 SkPath oval_path() {
56 SkRect oval = SkRect::MakeXYWH(0, -25, 100, 50); 77 SkRect oval = SkRect::MakeXYWH(0, -25, 100, 50);
57 78
58 SkPath path; 79 SkPath path;
59 path.arcTo(oval, 0, 359, true); 80 path.arcTo(oval, 0, 359, true);
60 path.close(); 81 path.close();
61 82
62 return path; 83 return path;
63 } 84 }
64 85
86 SkPath ribs_path(SkPath path, SkScalar radius) {
87 SkPath ribs;
88
89 const SkScalar spacing = 5.0f;
90 float accum = 0.0f;
91
92 SkPathMeasure meas(path, false);
93 SkScalar length = meas.getLength();
94 SkPoint pos;
95 SkVector tan;
96 while (accum < length) {
97 if (meas.getPosTan(accum, &pos, &tan)) {
98 tan.scale(radius);
99 tan.rotateCCW();
100
101 ribs.moveTo(pos.x() + tan.x(), pos.y() + tan.y());
102 ribs.lineTo(pos.x() - tan.x(), pos.y() - tan.y());
103 }
104 accum += spacing;
105 }
106
107 return ribs;
108 }
109
110 void draw_ribs(SkCanvas *canvas, SkPath path) {
111 SkPath ribs = ribs_path(path, OVERSTROKE_WIDTH/2.0f);
112 SkPaint p = make_normal_paint();
113 p.setStrokeWidth(1);
114 p.setColor(SK_ColorBLUE);
115 p.setColor(SK_ColorGREEN);
116
117 canvas->drawPath(ribs, p);
118 }
119
65 ///////// quads 120 ///////// quads
66 121
67 void draw_small_quad(SkCanvas *canvas) { 122 void draw_small_quad(SkCanvas *canvas) {
68 // scaled so it's visible 123 // scaled so it's visible
69 canvas->scale(8, 8); 124 // canvas->scale(8, 8);
70 125
71 SkPaint p; 126 SkPaint p = make_normal_paint();
72 p.setAntiAlias(true);
73 p.setStyle(SkPaint::kStroke_Style);
74 p.setStrokeWidth(3);
75
76 SkPath path = quad_path(); 127 SkPath path = quad_path();
77 128
129 draw_ribs(canvas, path);
78 canvas->drawPath(path, p); 130 canvas->drawPath(path, p);
79 } 131 }
80 132
81 void draw_large_quad(SkCanvas *canvas) { 133 void draw_large_quad(SkCanvas *canvas) {
82 SkPaint p = make_overstroke_paint(); 134 SkPaint p = make_overstroke_paint();
83 SkPath path = quad_path(); 135 SkPath path = quad_path();
84 136
85 canvas->drawPath(path, p); 137 canvas->drawPath(path, p);
138 draw_ribs(canvas, path);
86 } 139 }
87 140
88 void draw_quad_fillpath(SkCanvas *canvas) { 141 void draw_quad_fillpath(SkCanvas *canvas) {
89 SkPath path = quad_path(); 142 SkPath path = quad_path();
90 SkPaint p = make_overstroke_paint(); 143 SkPaint p = make_overstroke_paint();
91 144
92 SkPaint fillp; 145 SkPaint fillp = make_normal_paint();
93 fillp.setAntiAlias(true);
94 fillp.setStyle(SkPaint::kStroke_Style);
95 fillp.setColor(SK_ColorMAGENTA); 146 fillp.setColor(SK_ColorMAGENTA);
96 147
97 SkPath fillpath; 148 SkPath fillpath;
98 p.getFillPath(path, &fillpath); 149 p.getFillPath(path, &fillpath);
99 150
100 canvas->drawPath(fillpath, fillp); 151 canvas->drawPath(fillpath, fillp);
101 } 152 }
102 153
103 void draw_stroked_quad(SkCanvas *canvas) { 154 void draw_stroked_quad(SkCanvas *canvas) {
104 canvas->translate(200, 0); 155 canvas->translate(400, 0);
105 draw_large_quad(canvas); 156 draw_large_quad(canvas);
106 draw_quad_fillpath(canvas); 157 draw_quad_fillpath(canvas);
107 } 158 }
108 159
109 ////////// cubics 160 ////////// cubics
110 161
111 void draw_small_cubic(SkCanvas *canvas) { 162 void draw_small_cubic(SkCanvas *canvas) {
112 // scaled so it's visible 163 SkPaint p = make_normal_paint();
113 canvas->scale(8, 8);
114
115 SkPaint p;
116 p.setAntiAlias(true);
117 p.setStyle(SkPaint::kStroke_Style);
118 p.setStrokeWidth(3);
119
120 SkPath path = cubic_path(); 164 SkPath path = cubic_path();
121 165
166 draw_ribs(canvas, path);
122 canvas->drawPath(path, p); 167 canvas->drawPath(path, p);
123 } 168 }
124 169
125 void draw_large_cubic(SkCanvas *canvas) { 170 void draw_large_cubic(SkCanvas *canvas) {
126 SkPaint p = make_overstroke_paint(); 171 SkPaint p = make_overstroke_paint();
127 SkPath path = cubic_path(); 172 SkPath path = cubic_path();
128 173
129 canvas->drawPath(path, p); 174 canvas->drawPath(path, p);
175 draw_ribs(canvas, path);
130 } 176 }
131 177
132 void draw_cubic_fillpath(SkCanvas *canvas) { 178 void draw_cubic_fillpath(SkCanvas *canvas) {
133 SkPath path = cubic_path(); 179 SkPath path = cubic_path();
134 SkPaint p = make_overstroke_paint(); 180 SkPaint p = make_overstroke_paint();
135 181
136 SkPaint fillp; 182 SkPaint fillp = make_normal_paint();
137 fillp.setAntiAlias(true);
138 fillp.setStyle(SkPaint::kStroke_Style);
139 fillp.setColor(SK_ColorMAGENTA); 183 fillp.setColor(SK_ColorMAGENTA);
140 184
141 SkPath fillpath; 185 SkPath fillpath;
142 p.getFillPath(path, &fillpath); 186 p.getFillPath(path, &fillpath);
143 187
144 canvas->drawPath(fillpath, fillp); 188 canvas->drawPath(fillpath, fillp);
145 } 189 }
146 190
147 void draw_stroked_cubic(SkCanvas *canvas) { 191 void draw_stroked_cubic(SkCanvas *canvas) {
148 canvas->translate(400, 0); 192 canvas->translate(400, 0);
149 draw_large_cubic(canvas); 193 draw_large_cubic(canvas);
150 draw_cubic_fillpath(canvas); 194 draw_cubic_fillpath(canvas);
151 } 195 }
152 196
153 ////////// ovals 197 ////////// ovals
154 198
155 void draw_small_oval(SkCanvas *canvas) { 199 void draw_small_oval(SkCanvas *canvas) {
156 // scaled so it's visible 200 SkPaint p = make_normal_paint();
157 canvas->scale(8, 8);
158
159 SkPaint p;
160 p.setAntiAlias(true);
161 p.setStyle(SkPaint::kStroke_Style);
162 p.setStrokeWidth(3);
163 201
164 SkPath path = oval_path(); 202 SkPath path = oval_path();
165 203
204 draw_ribs(canvas, path);
166 canvas->drawPath(path, p); 205 canvas->drawPath(path, p);
167 } 206 }
168 207
169 void draw_large_oval(SkCanvas *canvas) { 208 void draw_large_oval(SkCanvas *canvas) {
170 SkPaint p = make_overstroke_paint(); 209 SkPaint p = make_overstroke_paint();
171 SkPath path = oval_path(); 210 SkPath path = oval_path();
172 211
173 canvas->drawPath(path, p); 212 canvas->drawPath(path, p);
213 draw_ribs(canvas, path);
174 } 214 }
175 215
176 void draw_oval_fillpath(SkCanvas *canvas) { 216 void draw_oval_fillpath(SkCanvas *canvas) {
177 SkPath path = oval_path(); 217 SkPath path = oval_path();
178 SkPaint p = make_overstroke_paint(); 218 SkPaint p = make_overstroke_paint();
179 219
180 SkPaint fillp; 220 SkPaint fillp = make_normal_paint();
181 fillp.setAntiAlias(true);
182 fillp.setStyle(SkPaint::kStroke_Style);
183 fillp.setColor(SK_ColorMAGENTA); 221 fillp.setColor(SK_ColorMAGENTA);
184 222
185 SkPath fillpath; 223 SkPath fillpath;
186 p.getFillPath(path, &fillpath); 224 p.getFillPath(path, &fillpath);
187 225
188 canvas->drawPath(fillpath, fillp); 226 canvas->drawPath(fillpath, fillp);
189 } 227 }
190 228
191 void draw_stroked_oval(SkCanvas *canvas) { 229 void draw_stroked_oval(SkCanvas *canvas) {
192 canvas->translate(400, 0); 230 canvas->translate(400, 0);
(...skipping 10 matching lines...) Expand all
203 241
204 DEF_SIMPLE_GM(OverStroke, canvas, 500, 500) { 242 DEF_SIMPLE_GM(OverStroke, canvas, 500, 500) {
205 const size_t length = sizeof(examples) / sizeof(examples[0]); 243 const size_t length = sizeof(examples) / sizeof(examples[0]);
206 const size_t width = 2; 244 const size_t width = 2;
207 245
208 for (size_t i = 0; i < length; i++) { 246 for (size_t i = 0; i < length; i++) {
209 int x = (int)(i % width); 247 int x = (int)(i % width);
210 int y = (int)(i / width); 248 int y = (int)(i / width);
211 249
212 canvas->save(); 250 canvas->save();
213 canvas->translate(200.0f * x, 150.0f * y); 251 canvas->translate(150.0f * x, 150.0f * y);
214 canvas->scale(0.25f, 0.25f); 252 canvas->scale(0.2f, 0.2f);
215 canvas->translate(100.0f, 400.0f); 253 canvas->translate(300.0f, 400.0f);
216 254
217 examples[i](canvas); 255 examples[i](canvas);
218 256
219 canvas->restore(); 257 canvas->restore();
220 } 258 }
221 } 259 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698