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

Side by Side Diff: gm/path_stroke_with_zero_length.cpp

Issue 1527083002: add caps for hairline moveTo / close (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: check if readpixels fails Created 5 years 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 | src/core/SkScan_Hairline.cpp » ('j') | 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 2015 Google Inc. 2 * Copyright 2015 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 #include "SkPath.h" 8 #include "SkPath.h"
9 #include "SkStream.h" 9 #include "SkStream.h"
10 #include "gm.h" 10 #include "gm.h"
11 11
12
12 // Test how short paths are stroked with various caps 13 // Test how short paths are stroked with various caps
13 DEF_SIMPLE_GM(path_stroke_with_zero_length, canvas, 240, 120) { 14 class StrokeZeroGM : public skiagm::GM {
14 SkPath paths[5]; 15 SkPath fPaths[8];
15 paths[0].moveTo(30.0f, 0); // single line segment 16 SkPath fClipL, fClipR, fClipS;
16 paths[0].rLineTo(30.0f, 0);
17 17
18 paths[1].moveTo(90.0f, 0); // single line segment with close 18 protected:
19 paths[1].rLineTo(30.0f, 0); 19 void onOnceBeforeDraw() override {
20 paths[1].close(); 20 fClipL.moveTo(0, 0);
21 fClipL.lineTo(3, 0);
22 fClipL.lineTo(2.5f, 1);
23 fClipL.lineTo(3.5f, 2.5f);
24 fClipL.lineTo(2.5f, 4);
25 fClipL.lineTo(3, 5);
26 fClipL.lineTo(0, 5);
27 fClipL.close();
21 28
22 paths[2].moveTo(150.0f, 0); // zero-length line 29 fClipR.moveTo(34, 0);
23 paths[2].rLineTo(0, 0); 30 fClipR.lineTo(34, 5);
31 fClipR.lineTo(31, 5);
32 fClipR.lineTo(30.5, 4);
33 fClipR.lineTo(31.5, 2.5);
34 fClipR.lineTo(30.5, 1);
35 fClipR.lineTo(31, 0);
36 fClipR.close();
24 37
25 paths[3].moveTo(180.0f, 0); // zero-length line with close 38 fClipS.addRect(SkRect::MakeIWH(4, 5));
26 paths[3].rLineTo(0, 0);
27 paths[3].close();
28 39
29 paths[4].moveTo(210.0f, 0); // close only, no line 40 fPaths[0].moveTo(30, 0); // single line segment
30 paths[4].close(); 41 fPaths[0].rLineTo(30, 0);
31 42
32 auto drawPaths = [&](const SkPaint& paint) { 43 fPaths[1].moveTo(90, 0); // single line segment with close (does not dr aw caps)
33 canvas->translate(0, 30.0f); 44 fPaths[1].rLineTo(30, 0);
34 for (const SkPath& path : paths) { 45 fPaths[1].close();
35 canvas->drawPath(path, paint); 46
47 fPaths[2].moveTo(150, 0); // zero-length line
48 fPaths[2].rLineTo(0, 0);
49
50 fPaths[3].moveTo(180, 0); // zero-length line with close (expected not to draw)
51 fPaths[3].rLineTo(0, 0);
52 fPaths[3].close();
53
54 fPaths[4].moveTo(210, 0); // close only, no line
55 fPaths[4].close();
56
57 fPaths[5].moveTo(30, 90); // all combos below should draw two caps
58 fPaths[5].rLineTo(0, 0);
59 fPaths[5].moveTo(60, 90);
60 fPaths[5].rLineTo(0, 0);
61
62 fPaths[6].moveTo(90, 90);
63 fPaths[6].close();
64 fPaths[6].moveTo(120, 90);
65 fPaths[6].close();
66
67 fPaths[7].moveTo(150, 90);
68 fPaths[7].rLineTo(0, 0);
69 fPaths[7].moveTo(180, 90);
70 fPaths[7].close();
71 }
72
73
74 SkString onShortName() override {
75 return SkString("path_stroke_with_zero_length");
76 }
77
78 SkISize onISize() override {
79 return SkISize::Make(1120, 840);
80 }
81
82 void onDraw(SkCanvas* canvas) override {
83 SkPaint bkgrnd;
84 bkgrnd.setColor(SK_ColorWHITE);
85 canvas->drawRect(SkRect::MakeIWH(onISize().fWidth, onISize().fHeight), b kgrnd);
86
87 auto drawPaths = [&](SkPaint& paint, int indexMask) {
88 canvas->translate(0, 30.0f);
89 int index = 0;
90 for (const SkPath& path : fPaths) {
91 if (indexMask & (1 << index)) {
92 canvas->drawPath(path, paint);
93 }
94 if (paint.getStrokeWidth() < 2) {
95 drawFat(canvas, path, paint, index);
96 }
97 ++index;
98 }
99 };
100
101 if (false) { // debugging variant that draws a single element
102 SkScalar width = 0;
103 bool antialias = true;
104
105 SkPaint butt;
106 butt.setAntiAlias(antialias);
107 butt.setStyle(SkPaint::kStroke_Style);
108 butt.setStrokeWidth(width);
109
110 SkPaint round(butt);
111 round.setStrokeCap(SkPaint::kRound_Cap);
112 drawPaths(round, 1 << 7);
113 return;
36 } 114 }
37 };
38
39 SkAutoCanvasRestore autoCanvasRestore(canvas, true);
40 115
41 SkPaint butt; 116 SkScalar widths[] = { 0, .999f, 1, 1.001f, 20 };
42 butt.setStyle(SkPaint::kStroke_Style); 117 bool aliases[] = { false, true };
43 butt.setStrokeWidth(20.0f); 118 for (bool antialias : aliases) {
44 butt.setStrokeCap(SkPaint::kButt_Cap); 119 canvas->save();
45 drawPaths(butt); 120 for (SkScalar width : widths) {
121 canvas->save();
122 SkPaint butt;
123 butt.setAntiAlias(antialias);
124 butt.setStyle(SkPaint::kStroke_Style);
125 butt.setStrokeWidth(width);
126 drawPaths(butt, -1);
46 127
47 SkPaint round(butt); 128 SkPaint round(butt);
48 round.setStrokeCap(SkPaint::kRound_Cap); 129 round.setStrokeCap(SkPaint::kRound_Cap);
49 drawPaths(round); 130 drawPaths(round, -1);
50 131
51 SkPaint square(butt); 132 SkPaint square(butt);
52 square.setStrokeCap(SkPaint::kSquare_Cap); 133 square.setStrokeCap(SkPaint::kSquare_Cap);
53 drawPaths(square); 134 drawPaths(square, -1);
54 } 135 canvas->restore();
136 canvas->translate(220, 0);
137 }
138 canvas->restore();
139 canvas->translate(0, 210);
140 }
141 }
142
143 private:
144 void drawFat(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, int index) {
145 const SkScalar scale = 10;
146 SkRect bounds = path.getBounds();
147 SkBitmap offscreen;
148 offscreen.allocN32Pixels(SkScalarRoundToInt(bounds.width() + 4),
149 SkScalarRoundToInt(bounds.height() + 4));
150 SkScalar pathX = bounds.fLeft - 2;
151 SkScalar pathY = bounds.fTop - 2;
152 SkMatrix cMatrix = canvas->getTotalMatrix();
153 if (!canvas->readPixels(&offscreen, SkScalarRoundToInt(pathX + cMatrix.g etTranslateX()),
154 SkScalarRoundToInt(pathY + cMatrix.getTranslateY()))) {
155 return;
156 }
157
158 canvas->save();
159 SkMatrix clipM;
160 clipM.reset();
161 clipM.preScale(scale, scale);
162 clipM.postTranslate(bounds.fLeft - 17, bounds.fTop - 24.5f + 420);
163 SkPath clip;
164 if (index < 2) {
165 fClipL.transform(clipM, &clip);
166 } else {
167 fClipS.transform(clipM, &clip);
168 }
169 canvas->clipPath(clip, SkRegion::kIntersect_Op, true);
170 canvas->scale(scale, scale);
171 canvas->drawBitmap(offscreen, (bounds.fLeft - 17) / scale,
172 (bounds.fTop - 20 + 420) / scale);
173 canvas->restore();
174
175 if (bounds.width() > 20) {
176 canvas->save();
177 clipM.reset();
178 clipM.preScale(scale, scale);
179 clipM.postTranslate(bounds.fLeft - 17 - 275, bounds.fTop - 24.5f + 4 20);
180 SkPath clip;
181 fClipR.transform(clipM, &clip);
182 canvas->clipPath(clip, SkRegion::kIntersect_Op, true);
183 canvas->scale(10.f, 10.f);
184 canvas->drawBitmap(offscreen, (bounds.fLeft - 17 - 275
185 + (index >= 5 ? 5 : 0)) / scale, (bounds.fTop - 20 + 420) / scale);
186 canvas->restore();
187 }
188 }
189
190 };
191
192 ///////////////////////////////////////////////////////////////////////////////
193
194 DEF_GM( return new StrokeZeroGM(); )
195
OLDNEW
« no previous file with comments | « no previous file | src/core/SkScan_Hairline.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698