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

Side by Side Diff: ui/gfx/paint_vector_icon.cc

Issue 2861203002: Refactor some vector icon parsing code for reuse (Closed)
Patch Set: probably unnecessary rebase Created 3 years, 7 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 | ui/gfx/vector_icon_types.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/paint_vector_icon.h" 5 #include "ui/gfx/paint_vector_icon.h"
6 6
7 #include <map> 7 #include <map>
8 #include <tuple> 8 #include <tuple>
9 9
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
16 #include "cc/paint/paint_canvas.h" 16 #include "cc/paint/paint_canvas.h"
17 #include "cc/paint/paint_flags.h" 17 #include "cc/paint/paint_flags.h"
18 #include "third_party/skia/include/core/SkPath.h" 18 #include "third_party/skia/include/core/SkPath.h"
19 #include "ui/gfx/canvas.h" 19 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/image/canvas_image_source.h" 20 #include "ui/gfx/image/canvas_image_source.h"
21 #include "ui/gfx/scoped_canvas.h" 21 #include "ui/gfx/scoped_canvas.h"
22 #include "ui/gfx/vector_icon_types.h" 22 #include "ui/gfx/vector_icon_types.h"
23 23
24 namespace gfx { 24 namespace gfx {
25 25
26 namespace { 26 namespace {
27 27
28 // Helper that simplifies iterating over a sequence of PathElements.
29 class PathParser {
30 public:
31 PathParser(const PathElement* path_elements)
32 : path_elements_(path_elements) {}
33 ~PathParser() {}
34
35 void Advance() { command_index_ += GetArgumentCount() + 1; }
36
37 CommandType CurrentCommand() const {
38 return path_elements_[command_index_].command;
39 }
40
41 SkScalar GetArgument(int index) const {
42 DCHECK_LT(index, GetArgumentCount());
43 return path_elements_[command_index_ + 1 + index].arg;
44 }
45
46 private:
47 int GetArgumentCount() const {
48 switch (CurrentCommand()) {
49 case STROKE:
50 case H_LINE_TO:
51 case R_H_LINE_TO:
52 case V_LINE_TO:
53 case R_V_LINE_TO:
54 case CANVAS_DIMENSIONS:
55 return 1;
56
57 case MOVE_TO:
58 case R_MOVE_TO:
59 case LINE_TO:
60 case R_LINE_TO:
61 return 2;
62
63 case CIRCLE:
64 return 3;
65
66 case PATH_COLOR_ARGB:
67 case CUBIC_TO_SHORTHAND:
68 case CLIP:
69 return 4;
70
71 case ROUND_RECT:
72 return 5;
73
74 case CUBIC_TO:
75 case R_CUBIC_TO:
76 return 6;
77
78 case ARC_TO:
79 case R_ARC_TO:
80 return 7;
81
82 case NEW_PATH:
83 case PATH_MODE_CLEAR:
84 case CAP_SQUARE:
85 case CLOSE:
86 case DISABLE_AA:
87 case FLIPS_IN_RTL:
88 case END:
89 return 0;
90 }
91
92 NOTREACHED();
93 return 0;
94 }
95
96 const PathElement* path_elements_;
97 int command_index_ = 0;
98
99 DISALLOW_COPY_AND_ASSIGN(PathParser);
100 };
101
28 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO. 102 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO.
29 CommandType CommandFromString(const std::string& source) { 103 CommandType CommandFromString(const std::string& source) {
30 #define RETURN_IF_IS(command) \ 104 #define RETURN_IF_IS(command) \
31 if (source == #command) \ 105 if (source == #command) \
32 return command; 106 return command;
33 107
34 RETURN_IF_IS(NEW_PATH); 108 RETURN_IF_IS(NEW_PATH);
35 RETURN_IF_IS(PATH_COLOR_ARGB); 109 RETURN_IF_IS(PATH_COLOR_ARGB);
36 RETURN_IF_IS(PATH_MODE_CLEAR); 110 RETURN_IF_IS(PATH_MODE_CLEAR);
37 RETURN_IF_IS(STROKE); 111 RETURN_IF_IS(STROKE);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 SkPath path; 161 SkPath path;
88 path.setFillType(SkPath::kEvenOdd_FillType); 162 path.setFillType(SkPath::kEvenOdd_FillType);
89 163
90 int canvas_size = kReferenceSizeDip; 164 int canvas_size = kReferenceSizeDip;
91 std::vector<SkPath> paths; 165 std::vector<SkPath> paths;
92 std::vector<cc::PaintFlags> flags_array; 166 std::vector<cc::PaintFlags> flags_array;
93 SkRect clip_rect = SkRect::MakeEmpty(); 167 SkRect clip_rect = SkRect::MakeEmpty();
94 bool flips_in_rtl = false; 168 bool flips_in_rtl = false;
95 CommandType previous_command_type = NEW_PATH; 169 CommandType previous_command_type = NEW_PATH;
96 170
97 for (size_t i = 0; path_elements[i].type != END; i++) { 171 for (PathParser parser(path_elements); parser.CurrentCommand() != END;
98 if (paths.empty() || path_elements[i].type == NEW_PATH) { 172 parser.Advance()) {
173 auto arg = [&parser](int i) { return parser.GetArgument(i); };
174 const CommandType command_type = parser.CurrentCommand();
175 if (paths.empty() || command_type == NEW_PATH) {
99 paths.push_back(SkPath()); 176 paths.push_back(SkPath());
100 paths.back().setFillType(SkPath::kEvenOdd_FillType); 177 paths.back().setFillType(SkPath::kEvenOdd_FillType);
101 178
102 flags_array.push_back(cc::PaintFlags()); 179 flags_array.push_back(cc::PaintFlags());
103 flags_array.back().setColor(color); 180 flags_array.back().setColor(color);
104 flags_array.back().setAntiAlias(true); 181 flags_array.back().setAntiAlias(true);
105 flags_array.back().setStrokeCap(cc::PaintFlags::kRound_Cap); 182 flags_array.back().setStrokeCap(cc::PaintFlags::kRound_Cap);
106 } 183 }
107 184
108 SkPath& path = paths.back(); 185 SkPath& path = paths.back();
109 cc::PaintFlags& flags = flags_array.back(); 186 cc::PaintFlags& flags = flags_array.back();
110 CommandType command_type = path_elements[i].type;
111 switch (command_type) { 187 switch (command_type) {
112 // Handled above. 188 // Handled above.
113 case NEW_PATH: 189 case NEW_PATH:
114 continue; 190 break;
115 191
116 case PATH_COLOR_ARGB: { 192 case PATH_COLOR_ARGB:
117 int a = SkScalarFloorToInt(path_elements[++i].arg); 193 flags.setColor(SkColorSetARGB(
118 int r = SkScalarFloorToInt(path_elements[++i].arg); 194 SkScalarFloorToInt(arg(0)), SkScalarFloorToInt(arg(1)),
119 int g = SkScalarFloorToInt(path_elements[++i].arg); 195 SkScalarFloorToInt(arg(2)), SkScalarFloorToInt(arg(3))));
120 int b = SkScalarFloorToInt(path_elements[++i].arg);
121 flags.setColor(SkColorSetARGB(a, r, g, b));
122 break; 196 break;
123 }
124 197
125 case PATH_MODE_CLEAR: { 198 case PATH_MODE_CLEAR:
126 flags.setBlendMode(SkBlendMode::kClear); 199 flags.setBlendMode(SkBlendMode::kClear);
127 break; 200 break;
128 };
129 201
130 case STROKE: { 202 case STROKE:
131 flags.setStyle(cc::PaintFlags::kStroke_Style); 203 flags.setStyle(cc::PaintFlags::kStroke_Style);
132 SkScalar width = path_elements[++i].arg; 204 flags.setStrokeWidth(arg(0));
133 flags.setStrokeWidth(width);
134 break; 205 break;
135 }
136 206
137 case CAP_SQUARE: { 207 case CAP_SQUARE:
138 flags.setStrokeCap(cc::PaintFlags::kSquare_Cap); 208 flags.setStrokeCap(cc::PaintFlags::kSquare_Cap);
139 break; 209 break;
140 }
141 210
142 case MOVE_TO: { 211 case MOVE_TO:
143 SkScalar x = path_elements[++i].arg; 212 path.moveTo(arg(0), arg(1));
144 SkScalar y = path_elements[++i].arg;
145 path.moveTo(x, y);
146 break; 213 break;
147 }
148 214
149 case R_MOVE_TO: { 215 case R_MOVE_TO:
150 if (previous_command_type == CLOSE) { 216 if (previous_command_type == CLOSE) {
151 // This triggers injectMoveToIfNeeded() so that the next subpath 217 // This triggers injectMoveToIfNeeded() so that the next subpath
152 // will start at the correct place. See [ 218 // will start at the correct place. See [
153 // https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand ]. 219 // https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand ].
154 path.rLineTo(0, 0); 220 path.rLineTo(0, 0);
155 } 221 }
156 222
157 SkScalar x = path_elements[++i].arg; 223 path.rMoveTo(arg(0), arg(1));
158 SkScalar y = path_elements[++i].arg;
159 path.rMoveTo(x, y);
160 break; 224 break;
161 }
162 225
163 case ARC_TO: 226 case ARC_TO:
164 case R_ARC_TO: { 227 case R_ARC_TO: {
165 SkScalar rx = path_elements[++i].arg; 228 SkScalar rx = arg(0);
166 SkScalar ry = path_elements[++i].arg; 229 SkScalar ry = arg(1);
167 SkScalar angle = path_elements[++i].arg; 230 SkScalar angle = arg(2);
168 SkScalar large_arc_flag = path_elements[++i].arg; 231 SkScalar large_arc_flag = arg(3);
169 SkScalar arc_sweep_flag = path_elements[++i].arg; 232 SkScalar arc_sweep_flag = arg(4);
170 SkScalar x = path_elements[++i].arg; 233 SkScalar x = arg(5);
171 SkScalar y = path_elements[++i].arg; 234 SkScalar y = arg(6);
172 235
173 auto path_fn = 236 auto path_fn =
174 command_type == ARC_TO 237 command_type == ARC_TO
175 ? static_cast<void (SkPath::*)( 238 ? static_cast<void (SkPath::*)(
176 SkScalar, SkScalar, SkScalar, SkPath::ArcSize, 239 SkScalar, SkScalar, SkScalar, SkPath::ArcSize,
177 SkPath::Direction, SkScalar, SkScalar)>(&SkPath::arcTo) 240 SkPath::Direction, SkScalar, SkScalar)>(&SkPath::arcTo)
178 : &SkPath::rArcTo; 241 : &SkPath::rArcTo;
179 (path.*path_fn)( 242 (path.*path_fn)(
180 rx, ry, angle, 243 rx, ry, angle,
181 large_arc_flag ? SkPath::kLarge_ArcSize : SkPath::kSmall_ArcSize, 244 large_arc_flag ? SkPath::kLarge_ArcSize : SkPath::kSmall_ArcSize,
182 arc_sweep_flag ? SkPath::kCW_Direction : SkPath::kCCW_Direction, x, 245 arc_sweep_flag ? SkPath::kCW_Direction : SkPath::kCCW_Direction, x,
183 y); 246 y);
184 break; 247 break;
185 } 248 }
186 249
187 case LINE_TO: { 250 case LINE_TO:
188 SkScalar x = path_elements[++i].arg; 251 path.lineTo(arg(0), arg(1));
189 SkScalar y = path_elements[++i].arg;
190 path.lineTo(x, y);
191 break; 252 break;
192 }
193 253
194 case R_LINE_TO: { 254 case R_LINE_TO:
195 SkScalar x = path_elements[++i].arg; 255 path.rLineTo(arg(0), arg(1));
196 SkScalar y = path_elements[++i].arg;
197 path.rLineTo(x, y);
198 break; 256 break;
199 }
200 257
201 case H_LINE_TO: { 258 case H_LINE_TO: {
202 SkPoint last_point; 259 SkPoint last_point;
203 path.getLastPt(&last_point); 260 path.getLastPt(&last_point);
204 SkScalar x = path_elements[++i].arg; 261 path.lineTo(arg(0), last_point.fY);
205 path.lineTo(x, last_point.fY);
206 break; 262 break;
207 } 263 }
208 264
209 case R_H_LINE_TO: { 265 case R_H_LINE_TO:
210 SkScalar x = path_elements[++i].arg; 266 path.rLineTo(arg(0), 0);
211 path.rLineTo(x, 0);
212 break; 267 break;
213 }
214 268
215 case V_LINE_TO: { 269 case V_LINE_TO: {
216 SkPoint last_point; 270 SkPoint last_point;
217 path.getLastPt(&last_point); 271 path.getLastPt(&last_point);
218 SkScalar y = path_elements[++i].arg; 272 path.lineTo(last_point.fX, arg(0));
219 path.lineTo(last_point.fX, y);
220 break; 273 break;
221 } 274 }
222 275
223 case R_V_LINE_TO: { 276 case R_V_LINE_TO:
224 SkScalar y = path_elements[++i].arg; 277 path.rLineTo(0, arg(0));
225 path.rLineTo(0, y);
226 break; 278 break;
227 }
228 279
229 case CUBIC_TO: { 280 case CUBIC_TO:
230 SkScalar x1 = path_elements[++i].arg; 281 path.cubicTo(arg(0), arg(1), arg(2), arg(3), arg(4), arg(5));
231 SkScalar y1 = path_elements[++i].arg;
232 SkScalar x2 = path_elements[++i].arg;
233 SkScalar y2 = path_elements[++i].arg;
234 SkScalar x3 = path_elements[++i].arg;
235 SkScalar y3 = path_elements[++i].arg;
236 path.cubicTo(x1, y1, x2, y2, x3, y3);
237 break; 282 break;
238 }
239 283
240 case R_CUBIC_TO: { 284 case R_CUBIC_TO:
241 SkScalar x1 = path_elements[++i].arg; 285 path.rCubicTo(arg(0), arg(1), arg(2), arg(3), arg(4), arg(5));
242 SkScalar y1 = path_elements[++i].arg;
243 SkScalar x2 = path_elements[++i].arg;
244 SkScalar y2 = path_elements[++i].arg;
245 SkScalar x3 = path_elements[++i].arg;
246 SkScalar y3 = path_elements[++i].arg;
247 path.rCubicTo(x1, y1, x2, y2, x3, y3);
248 break; 286 break;
249 }
250 287
251 case CUBIC_TO_SHORTHAND: { 288 case CUBIC_TO_SHORTHAND: {
252 // Compute the first control point (|x1| and |y1|) as the reflection 289 // Compute the first control point (|x1| and |y1|) as the reflection
253 // of the second control point on the previous command relative to 290 // of the second control point on the previous command relative to
254 // the current point. If there is no previous command or if the 291 // the current point. If there is no previous command or if the
255 // previous command is not a cubic Bezier curve, the first control 292 // previous command is not a cubic Bezier curve, the first control
256 // point is coincident with the current point. Refer to the SVG 293 // point is coincident with the current point. Refer to the SVG
257 // path specs for further details. 294 // path specs for further details.
258 SkPoint last_point; 295 SkPoint last_point;
259 path.getLastPt(&last_point); 296 path.getLastPt(&last_point);
260 SkScalar delta_x = 0; 297 SkScalar delta_x = 0;
261 SkScalar delta_y = 0; 298 SkScalar delta_y = 0;
262 if (previous_command_type == CUBIC_TO || 299 if (previous_command_type == CUBIC_TO ||
263 previous_command_type == R_CUBIC_TO || 300 previous_command_type == R_CUBIC_TO ||
264 previous_command_type == CUBIC_TO_SHORTHAND) { 301 previous_command_type == CUBIC_TO_SHORTHAND) {
265 SkPoint last_control_point = path.getPoint(path.countPoints() - 2); 302 SkPoint last_control_point = path.getPoint(path.countPoints() - 2);
266 delta_x = last_point.fX - last_control_point.fX; 303 delta_x = last_point.fX - last_control_point.fX;
267 delta_y = last_point.fY - last_control_point.fY; 304 delta_y = last_point.fY - last_control_point.fY;
268 } 305 }
269 306
270 SkScalar x1 = last_point.fX + delta_x; 307 SkScalar x1 = last_point.fX + delta_x;
271 SkScalar y1 = last_point.fY + delta_y; 308 SkScalar y1 = last_point.fY + delta_y;
272 SkScalar x2 = path_elements[++i].arg; 309 path.cubicTo(x1, y1, arg(0), arg(1), arg(2), arg(3));
273 SkScalar y2 = path_elements[++i].arg;
274 SkScalar x3 = path_elements[++i].arg;
275 SkScalar y3 = path_elements[++i].arg;
276 path.cubicTo(x1, y1, x2, y2, x3, y3);
277 break; 310 break;
278 } 311 }
279 312
280 case CIRCLE: { 313 case CIRCLE:
281 SkScalar x = path_elements[++i].arg; 314 path.addCircle(arg(0), arg(1), arg(2));
282 SkScalar y = path_elements[++i].arg;
283 SkScalar r = path_elements[++i].arg;
284 path.addCircle(x, y, r);
285 break; 315 break;
286 }
287 316
288 case ROUND_RECT: { 317 case ROUND_RECT:
289 SkScalar x = path_elements[++i].arg; 318 path.addRoundRect(SkRect::MakeXYWH(arg(0), arg(1), arg(2), arg(3)),
290 SkScalar y = path_elements[++i].arg; 319 arg(4), arg(4));
291 SkScalar w = path_elements[++i].arg;
292 SkScalar h = path_elements[++i].arg;
293 SkScalar radius = path_elements[++i].arg;
294 path.addRoundRect(SkRect::MakeXYWH(x, y, w, h), radius, radius);
295 break; 320 break;
296 }
297 321
298 case CLOSE: { 322 case CLOSE:
299 path.close(); 323 path.close();
300 break; 324 break;
301 }
302 325
303 case CANVAS_DIMENSIONS: { 326 case CANVAS_DIMENSIONS:
304 SkScalar width = path_elements[++i].arg; 327 canvas_size = SkScalarTruncToInt(arg(0));
305 canvas_size = SkScalarTruncToInt(width);
306 break; 328 break;
307 }
308 329
309 case CLIP: { 330 case CLIP:
310 SkScalar x = path_elements[++i].arg; 331 clip_rect = SkRect::MakeXYWH(arg(0), arg(1), arg(2), arg(3));
311 SkScalar y = path_elements[++i].arg;
312 SkScalar w = path_elements[++i].arg;
313 SkScalar h = path_elements[++i].arg;
314 clip_rect = SkRect::MakeXYWH(x, y, w, h);
315 break; 332 break;
316 }
317 333
318 case DISABLE_AA: { 334 case DISABLE_AA:
319 flags.setAntiAlias(false); 335 flags.setAntiAlias(false);
320 break; 336 break;
321 }
322 337
323 case FLIPS_IN_RTL: { 338 case FLIPS_IN_RTL:
324 flips_in_rtl = true; 339 flips_in_rtl = true;
325 break; 340 break;
326 }
327 341
328 case END: 342 case END:
329 NOTREACHED(); 343 NOTREACHED();
330 break; 344 break;
331 } 345 }
332 346
333 previous_command_type = command_type; 347 previous_command_type = command_type;
334 } 348 }
335 349
336 gfx::ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, 350 gfx::ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size,
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 502
489 ImageSkia CreateVectorIconFromSource(const std::string& source, 503 ImageSkia CreateVectorIconFromSource(const std::string& source,
490 int dip_size, 504 int dip_size,
491 SkColor color) { 505 SkColor color) {
492 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size, 506 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size,
493 color); 507 color);
494 } 508 }
495 509
496 int GetDefaultSizeOfVectorIcon(const gfx::VectorIcon& icon) { 510 int GetDefaultSizeOfVectorIcon(const gfx::VectorIcon& icon) {
497 const PathElement* one_x_path = icon.path_1x_ ? icon.path_1x_ : icon.path_; 511 const PathElement* one_x_path = icon.path_1x_ ? icon.path_1x_ : icon.path_;
498 return one_x_path[0].type == CANVAS_DIMENSIONS ? one_x_path[1].arg 512 return one_x_path[0].command == CANVAS_DIMENSIONS ? one_x_path[1].arg
499 : kReferenceSizeDip; 513 : kReferenceSizeDip;
500 } 514 }
501 515
502 } // namespace gfx 516 } // namespace gfx
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/vector_icon_types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698