| OLD | NEW |
| 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 | 8 |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/strings/string_split.h" | 11 #include "base/strings/string_split.h" |
| 12 #include "third_party/skia/include/core/SkPaint.h" |
| 12 #include "third_party/skia/include/core/SkPath.h" | 13 #include "third_party/skia/include/core/SkPath.h" |
| 14 #include "third_party/skia/include/core/SkXfermode.h" |
| 13 #include "ui/gfx/canvas.h" | 15 #include "ui/gfx/canvas.h" |
| 14 #include "ui/gfx/image/canvas_image_source.h" | 16 #include "ui/gfx/image/canvas_image_source.h" |
| 15 #include "ui/gfx/vector_icon_types.h" | 17 #include "ui/gfx/vector_icon_types.h" |
| 16 #include "ui/gfx/vector_icons2.h" | 18 #include "ui/gfx/vector_icons2.h" |
| 17 | 19 |
| 18 namespace gfx { | 20 namespace gfx { |
| 19 | 21 |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO. | 24 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO. |
| 23 CommandType CommandFromString(const std::string& source) { | 25 CommandType CommandFromString(const std::string& source) { |
| 24 #define RETURN_IF_IS(command) \ | 26 #define RETURN_IF_IS(command) \ |
| 25 if (source == #command) \ | 27 if (source == #command) \ |
| 26 return command; | 28 return command; |
| 27 | 29 |
| 28 RETURN_IF_IS(NEW_PATH); | 30 RETURN_IF_IS(NEW_PATH); |
| 29 RETURN_IF_IS(PATH_COLOR_ARGB); | 31 RETURN_IF_IS(PATH_COLOR_ARGB); |
| 32 RETURN_IF_IS(PATH_MODE_CLEAR); |
| 30 RETURN_IF_IS(STROKE); | 33 RETURN_IF_IS(STROKE); |
| 31 RETURN_IF_IS(MOVE_TO); | 34 RETURN_IF_IS(MOVE_TO); |
| 32 RETURN_IF_IS(R_MOVE_TO); | 35 RETURN_IF_IS(R_MOVE_TO); |
| 33 RETURN_IF_IS(LINE_TO); | 36 RETURN_IF_IS(LINE_TO); |
| 34 RETURN_IF_IS(R_LINE_TO); | 37 RETURN_IF_IS(R_LINE_TO); |
| 35 RETURN_IF_IS(H_LINE_TO); | 38 RETURN_IF_IS(H_LINE_TO); |
| 36 RETURN_IF_IS(R_H_LINE_TO); | 39 RETURN_IF_IS(R_H_LINE_TO); |
| 37 RETURN_IF_IS(V_LINE_TO); | 40 RETURN_IF_IS(V_LINE_TO); |
| 38 RETURN_IF_IS(R_V_LINE_TO); | 41 RETURN_IF_IS(R_V_LINE_TO); |
| 39 RETURN_IF_IS(CUBIC_TO); | 42 RETURN_IF_IS(CUBIC_TO); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 61 else | 64 else |
| 62 path.push_back(PathElement(CommandFromString(piece))); | 65 path.push_back(PathElement(CommandFromString(piece))); |
| 63 } | 66 } |
| 64 return path; | 67 return path; |
| 65 } | 68 } |
| 66 | 69 |
| 67 void PaintPath(Canvas* canvas, | 70 void PaintPath(Canvas* canvas, |
| 68 const PathElement* path_elements, | 71 const PathElement* path_elements, |
| 69 size_t dip_size, | 72 size_t dip_size, |
| 70 SkColor color) { | 73 SkColor color) { |
| 74 canvas->Save(); |
| 71 SkPath path; | 75 SkPath path; |
| 72 path.setFillType(SkPath::kEvenOdd_FillType); | 76 path.setFillType(SkPath::kEvenOdd_FillType); |
| 73 | 77 |
| 74 size_t canvas_size = kReferenceSizeDip; | 78 size_t canvas_size = kReferenceSizeDip; |
| 75 std::vector<SkPath> paths; | 79 std::vector<SkPath> paths; |
| 76 std::vector<SkPaint> paints; | 80 std::vector<SkPaint> paints; |
| 77 SkRect clip_rect = SkRect::MakeEmpty(); | 81 SkRect clip_rect = SkRect::MakeEmpty(); |
| 78 | 82 |
| 79 for (size_t i = 0; path_elements[i].type != END; i++) { | 83 for (size_t i = 0; path_elements[i].type != END; i++) { |
| 80 if (paths.empty() || path_elements[i].type == NEW_PATH) { | 84 if (paths.empty() || path_elements[i].type == NEW_PATH) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 96 | 100 |
| 97 case PATH_COLOR_ARGB: { | 101 case PATH_COLOR_ARGB: { |
| 98 int a = SkScalarFloorToInt(path_elements[++i].arg); | 102 int a = SkScalarFloorToInt(path_elements[++i].arg); |
| 99 int r = SkScalarFloorToInt(path_elements[++i].arg); | 103 int r = SkScalarFloorToInt(path_elements[++i].arg); |
| 100 int g = SkScalarFloorToInt(path_elements[++i].arg); | 104 int g = SkScalarFloorToInt(path_elements[++i].arg); |
| 101 int b = SkScalarFloorToInt(path_elements[++i].arg); | 105 int b = SkScalarFloorToInt(path_elements[++i].arg); |
| 102 paint.setColor(SkColorSetARGB(a, r, g, b)); | 106 paint.setColor(SkColorSetARGB(a, r, g, b)); |
| 103 break; | 107 break; |
| 104 } | 108 } |
| 105 | 109 |
| 110 case PATH_MODE_CLEAR: { |
| 111 paint.setXfermodeMode(SkXfermode::kClear_Mode); |
| 112 break; |
| 113 }; |
| 114 |
| 106 case STROKE: { | 115 case STROKE: { |
| 107 paint.setStyle(SkPaint::kStroke_Style); | 116 paint.setStyle(SkPaint::kStroke_Style); |
| 108 SkScalar width = path_elements[++i].arg; | 117 SkScalar width = path_elements[++i].arg; |
| 109 paint.setStrokeWidth(width); | 118 paint.setStrokeWidth(width); |
| 110 break; | 119 break; |
| 111 } | 120 } |
| 112 | 121 |
| 113 case MOVE_TO: { | 122 case MOVE_TO: { |
| 114 SkScalar x = path_elements[++i].arg; | 123 SkScalar x = path_elements[++i].arg; |
| 115 SkScalar y = path_elements[++i].arg; | 124 SkScalar y = path_elements[++i].arg; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); | 240 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); |
| 232 canvas->sk_canvas()->scale(scale, scale); | 241 canvas->sk_canvas()->scale(scale, scale); |
| 233 } | 242 } |
| 234 | 243 |
| 235 if (!clip_rect.isEmpty()) | 244 if (!clip_rect.isEmpty()) |
| 236 canvas->sk_canvas()->clipRect(clip_rect); | 245 canvas->sk_canvas()->clipRect(clip_rect); |
| 237 | 246 |
| 238 DCHECK_EQ(paints.size(), paths.size()); | 247 DCHECK_EQ(paints.size(), paths.size()); |
| 239 for (size_t i = 0; i < paths.size(); ++i) | 248 for (size_t i = 0; i < paths.size(); ++i) |
| 240 canvas->DrawPath(paths[i], paints[i]); | 249 canvas->DrawPath(paths[i], paints[i]); |
| 250 canvas->Restore(); |
| 241 } | 251 } |
| 242 | 252 |
| 243 class VectorIconSource : public CanvasImageSource { | 253 class VectorIconSource : public CanvasImageSource { |
| 244 public: | 254 public: |
| 245 VectorIconSource(VectorIconId id, size_t dip_size, SkColor color) | 255 VectorIconSource(VectorIconId id, |
| 256 size_t dip_size, |
| 257 SkColor color, |
| 258 VectorIconId badge_id) |
| 246 : CanvasImageSource( | 259 : CanvasImageSource( |
| 247 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)), | 260 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)), |
| 248 false), | 261 false), |
| 249 id_(id), | 262 id_(id), |
| 250 color_(color) {} | 263 color_(color), |
| 264 badge_id_(badge_id) {} |
| 251 | 265 |
| 252 VectorIconSource(const std::string& definition, | 266 VectorIconSource(const std::string& definition, |
| 253 size_t dip_size, | 267 size_t dip_size, |
| 254 SkColor color) | 268 SkColor color) |
| 255 : CanvasImageSource( | 269 : CanvasImageSource( |
| 256 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)), | 270 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)), |
| 257 false), | 271 false), |
| 258 id_(VectorIconId::VECTOR_ICON_NONE), | 272 id_(VectorIconId::VECTOR_ICON_NONE), |
| 259 path_(PathFromSource(definition)), | 273 path_(PathFromSource(definition)), |
| 260 color_(color) {} | 274 color_(color), |
| 275 badge_id_(VectorIconId::VECTOR_ICON_NONE) {} |
| 261 | 276 |
| 262 ~VectorIconSource() override {} | 277 ~VectorIconSource() override {} |
| 263 | 278 |
| 264 // CanvasImageSource: | 279 // CanvasImageSource: |
| 265 void Draw(gfx::Canvas* canvas) override { | 280 void Draw(gfx::Canvas* canvas) override { |
| 266 if (path_.empty()) | 281 if (path_.empty()) { |
| 267 PaintVectorIcon(canvas, id_, size_.width(), color_); | 282 PaintVectorIcon(canvas, id_, size_.width(), color_); |
| 268 else | 283 if (badge_id_ != VectorIconId::VECTOR_ICON_NONE) |
| 284 PaintVectorIcon(canvas, badge_id_, size_.width(), color_); |
| 285 } else { |
| 269 PaintPath(canvas, path_.data(), size_.width(), color_); | 286 PaintPath(canvas, path_.data(), size_.width(), color_); |
| 287 } |
| 270 } | 288 } |
| 271 | 289 |
| 272 private: | 290 private: |
| 273 const VectorIconId id_; | 291 const VectorIconId id_; |
| 274 const std::vector<PathElement> path_; | 292 const std::vector<PathElement> path_; |
| 275 const SkColor color_; | 293 const SkColor color_; |
| 294 const VectorIconId badge_id_; |
| 276 | 295 |
| 277 DISALLOW_COPY_AND_ASSIGN(VectorIconSource); | 296 DISALLOW_COPY_AND_ASSIGN(VectorIconSource); |
| 278 }; | 297 }; |
| 279 | 298 |
| 280 // This class caches vector icons (as ImageSkia) so they don't have to be drawn | 299 // This class caches vector icons (as ImageSkia) so they don't have to be drawn |
| 281 // more than once. This also guarantees the backing data for the images returned | 300 // more than once. This also guarantees the backing data for the images returned |
| 282 // by CreateVectorIcon will persist in memory until program termination. | 301 // by CreateVectorIcon will persist in memory until program termination. |
| 283 class VectorIconCache { | 302 class VectorIconCache { |
| 284 public: | 303 public: |
| 285 VectorIconCache() {} | 304 VectorIconCache() {} |
| 286 ~VectorIconCache() {} | 305 ~VectorIconCache() {} |
| 287 | 306 |
| 288 ImageSkia GetOrCreateIcon(VectorIconId id, size_t dip_size, SkColor color) { | 307 ImageSkia GetOrCreateIcon(VectorIconId id, |
| 289 IconDescription description(id, dip_size, color); | 308 size_t dip_size, |
| 309 SkColor color, |
| 310 VectorIconId badge_id) { |
| 311 IconDescription description(id, dip_size, color, badge_id); |
| 290 auto iter = images_.find(description); | 312 auto iter = images_.find(description); |
| 291 if (iter != images_.end()) | 313 if (iter != images_.end()) |
| 292 return iter->second; | 314 return iter->second; |
| 293 | 315 |
| 294 ImageSkia icon( | 316 ImageSkia icon( |
| 295 new VectorIconSource(id, dip_size, color), | 317 new VectorIconSource(id, dip_size, color, badge_id), |
| 296 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size))); | 318 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size))); |
| 297 images_.insert(std::make_pair(description, icon)); | 319 images_.insert(std::make_pair(description, icon)); |
| 298 return icon; | 320 return icon; |
| 299 } | 321 } |
| 300 | 322 |
| 301 private: | 323 private: |
| 302 struct IconDescription { | 324 struct IconDescription { |
| 303 IconDescription(VectorIconId id, size_t dip_size, SkColor color) | 325 IconDescription(VectorIconId id, |
| 304 : id(id), dip_size(dip_size), color(color) {} | 326 size_t dip_size, |
| 327 SkColor color, |
| 328 VectorIconId badge_id) |
| 329 : id(id), dip_size(dip_size), color(color), badge_id(badge_id) {} |
| 305 | 330 |
| 306 bool operator<(const IconDescription& other) const { | 331 bool operator<(const IconDescription& other) const { |
| 307 if (id != other.id) | 332 if (id != other.id) |
| 308 return id < other.id; | 333 return id < other.id; |
| 309 if (dip_size != other.dip_size) | 334 if (dip_size != other.dip_size) |
| 310 return dip_size < other.dip_size; | 335 return dip_size < other.dip_size; |
| 311 return color < other.color; | 336 if (color != other.color) |
| 337 return color < other.color; |
| 338 return badge_id < other.badge_id; |
| 312 } | 339 } |
| 313 | 340 |
| 314 VectorIconId id; | 341 VectorIconId id; |
| 315 size_t dip_size; | 342 size_t dip_size; |
| 316 SkColor color; | 343 SkColor color; |
| 344 VectorIconId badge_id; |
| 317 }; | 345 }; |
| 318 | 346 |
| 319 std::map<IconDescription, ImageSkia> images_; | 347 std::map<IconDescription, ImageSkia> images_; |
| 320 | 348 |
| 321 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); | 349 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); |
| 322 }; | 350 }; |
| 323 | 351 |
| 324 static base::LazyInstance<VectorIconCache> g_icon_cache = | 352 static base::LazyInstance<VectorIconCache> g_icon_cache = |
| 325 LAZY_INSTANCE_INITIALIZER; | 353 LAZY_INSTANCE_INITIALIZER; |
| 326 | 354 |
| 327 } // namespace | 355 } // namespace |
| 328 | 356 |
| 329 void PaintVectorIcon(Canvas* canvas, | 357 void PaintVectorIcon(Canvas* canvas, |
| 330 VectorIconId id, | 358 VectorIconId id, |
| 331 size_t dip_size, | 359 size_t dip_size, |
| 332 SkColor color) { | 360 SkColor color) { |
| 333 DCHECK(VectorIconId::VECTOR_ICON_NONE != id); | 361 DCHECK(VectorIconId::VECTOR_ICON_NONE != id); |
| 334 const PathElement* path = canvas->image_scale() == 1.f | 362 const PathElement* path = canvas->image_scale() == 1.f |
| 335 ? GetPathForVectorIconAt1xScale(id) | 363 ? GetPathForVectorIconAt1xScale(id) |
| 336 : GetPathForVectorIcon(id); | 364 : GetPathForVectorIcon(id); |
| 337 PaintPath(canvas, path, dip_size, color); | 365 PaintPath(canvas, path, dip_size, color); |
| 338 } | 366 } |
| 339 | 367 |
| 340 ImageSkia CreateVectorIcon(VectorIconId id, size_t dip_size, SkColor color) { | 368 ImageSkia CreateVectorIcon(VectorIconId id, size_t dip_size, SkColor color) { |
| 341 return g_icon_cache.Get().GetOrCreateIcon(id, dip_size, color); | 369 return CreateVectorIconWithBadge(id, dip_size, color, |
| 370 VectorIconId::VECTOR_ICON_NONE); |
| 371 } |
| 372 |
| 373 ImageSkia CreateVectorIconWithBadge(VectorIconId id, |
| 374 size_t dip_size, |
| 375 SkColor color, |
| 376 VectorIconId badge_id) { |
| 377 return g_icon_cache.Get().GetOrCreateIcon(id, dip_size, color, badge_id); |
| 342 } | 378 } |
| 343 | 379 |
| 344 ImageSkia CreateVectorIconFromSource(const std::string& source, | 380 ImageSkia CreateVectorIconFromSource(const std::string& source, |
| 345 size_t dip_size, | 381 size_t dip_size, |
| 346 SkColor color) { | 382 SkColor color) { |
| 347 return ImageSkia( | 383 return ImageSkia( |
| 348 new VectorIconSource(source, dip_size, color), | 384 new VectorIconSource(source, dip_size, color), |
| 349 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size))); | 385 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size))); |
| 350 } | 386 } |
| 351 | 387 |
| 352 } // namespace gfx | 388 } // namespace gfx |
| OLD | NEW |