| 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" |
| 11 #include "base/strings/string_split.h" |
| 10 #include "third_party/skia/include/core/SkPath.h" | 12 #include "third_party/skia/include/core/SkPath.h" |
| 11 #include "ui/gfx/canvas.h" | 13 #include "ui/gfx/canvas.h" |
| 12 #include "ui/gfx/image/canvas_image_source.h" | 14 #include "ui/gfx/image/canvas_image_source.h" |
| 13 #include "ui/gfx/vector_icon_types.h" | 15 #include "ui/gfx/vector_icon_types.h" |
| 14 #include "ui/gfx/vector_icons2.h" | 16 #include "ui/gfx/vector_icons2.h" |
| 15 | 17 |
| 16 namespace gfx { | 18 namespace gfx { |
| 17 | 19 |
| 18 namespace { | 20 namespace { |
| 19 | 21 |
| 20 class VectorIconSource : public CanvasImageSource { | 22 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO. |
| 21 public: | 23 CommandType CommandFromString(const std::string& source) { |
| 22 VectorIconSource(VectorIconId id, size_t dip_size, SkColor color) | 24 #define RETURN_IF_IS(command) \ |
| 23 : CanvasImageSource( | 25 if (source == #command) \ |
| 24 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)), | 26 return command; |
| 25 false), | |
| 26 id_(id), | |
| 27 color_(color) {} | |
| 28 | 27 |
| 29 ~VectorIconSource() override {} | 28 RETURN_IF_IS(MOVE_TO); |
| 29 RETURN_IF_IS(R_MOVE_TO); |
| 30 RETURN_IF_IS(R_LINE_TO); |
| 31 RETURN_IF_IS(H_LINE_TO); |
| 32 RETURN_IF_IS(R_H_LINE_TO); |
| 33 RETURN_IF_IS(V_LINE_TO); |
| 34 RETURN_IF_IS(R_V_LINE_TO); |
| 35 RETURN_IF_IS(CUBIC_TO); |
| 36 RETURN_IF_IS(R_CUBIC_TO); |
| 37 RETURN_IF_IS(CIRCLE); |
| 38 RETURN_IF_IS(CLOSE); |
| 39 RETURN_IF_IS(END); |
| 40 #undef RETURN_IF_IS |
| 30 | 41 |
| 31 // CanvasImageSource: | 42 NOTREACHED(); |
| 32 void Draw(gfx::Canvas* canvas) override { | 43 return CLOSE; |
| 33 PaintVectorIcon(canvas, id_, size_.width(), color_); | 44 } |
| 45 |
| 46 std::vector<PathElement> PathFromSource(const std::string& source) { |
| 47 std::vector<PathElement> path; |
| 48 std::vector<std::string> pieces = base::SplitString( |
| 49 source, "\n ,f", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 50 for (const auto& piece : pieces) { |
| 51 double value; |
| 52 if (base::StringToDouble(piece, &value)) |
| 53 path.push_back(PathElement(SkDoubleToScalar(value))); |
| 54 else |
| 55 path.push_back(PathElement(CommandFromString(piece))); |
| 34 } | 56 } |
| 57 return path; |
| 58 } |
| 35 | 59 |
| 36 private: | 60 void PaintPath(Canvas* canvas, |
| 37 const VectorIconId id_; | 61 const PathElement* path_elements, |
| 38 const SkColor color_; | 62 size_t dip_size, |
| 39 | 63 SkColor color) { |
| 40 DISALLOW_COPY_AND_ASSIGN(VectorIconSource); | 64 SkPath path; |
| 41 }; | 65 path.setFillType(SkPath::kEvenOdd_FillType); |
| 42 | |
| 43 // This class caches vector icons (as ImageSkia) so they don't have to be drawn | |
| 44 // more than once. This also guarantees the backing data for the images returned | |
| 45 // by CreateVectorIcon will persist in memory until program termination. | |
| 46 class VectorIconCache { | |
| 47 public: | |
| 48 VectorIconCache() {} | |
| 49 ~VectorIconCache() {} | |
| 50 | |
| 51 ImageSkia GetOrCreateIcon(VectorIconId id, size_t dip_size, SkColor color) { | |
| 52 IconDescription description(id, dip_size, color); | |
| 53 auto iter = images_.find(description); | |
| 54 if (iter != images_.end()) | |
| 55 return iter->second; | |
| 56 | |
| 57 ImageSkia icon( | |
| 58 new VectorIconSource(id, dip_size, color), | |
| 59 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size))); | |
| 60 images_.insert(std::make_pair(description, icon)); | |
| 61 return icon; | |
| 62 } | |
| 63 | |
| 64 private: | |
| 65 struct IconDescription { | |
| 66 IconDescription(VectorIconId id, size_t dip_size, SkColor color) | |
| 67 : id(id), dip_size(dip_size), color(color) {} | |
| 68 | |
| 69 bool operator<(const IconDescription& other) const { | |
| 70 if (id != other.id) | |
| 71 return id < other.id; | |
| 72 if (dip_size != other.dip_size) | |
| 73 return dip_size < other.dip_size; | |
| 74 return color < other.color; | |
| 75 } | |
| 76 | |
| 77 VectorIconId id; | |
| 78 size_t dip_size; | |
| 79 SkColor color; | |
| 80 }; | |
| 81 | |
| 82 std::map<IconDescription, ImageSkia> images_; | |
| 83 | |
| 84 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); | |
| 85 }; | |
| 86 | |
| 87 static base::LazyInstance<VectorIconCache> g_icon_cache = | |
| 88 LAZY_INSTANCE_INITIALIZER; | |
| 89 | |
| 90 } // namespace | |
| 91 | |
| 92 void PaintVectorIcon(Canvas* canvas, | |
| 93 VectorIconId id, | |
| 94 size_t dip_size, | |
| 95 SkColor color) { | |
| 96 DCHECK(VectorIconId::VECTOR_ICON_NONE != id); | |
| 97 const PathElement* path_elements = GetPathForVectorIcon(id); | |
| 98 | 66 |
| 99 std::vector<SkPath> paths; | 67 std::vector<SkPath> paths; |
| 100 paths.push_back(SkPath()); | 68 paths.push_back(SkPath()); |
| 101 paths.back().setFillType(SkPath::kEvenOdd_FillType); | 69 paths.back().setFillType(SkPath::kEvenOdd_FillType); |
| 102 size_t canvas_size = kReferenceSizeDip; | 70 size_t canvas_size = kReferenceSizeDip; |
| 103 | 71 |
| 104 for (size_t i = 0; path_elements[i].type != END; i++) { | 72 for (size_t i = 0; path_elements[i].type != END; i++) { |
| 105 SkPath& path = paths.back(); | 73 SkPath& path = paths.back(); |
| 106 switch (path_elements[i].type) { | 74 switch (path_elements[i].type) { |
| 107 case NEW_PATH: { | 75 case NEW_PATH: { |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 | 188 |
| 221 if (dip_size != canvas_size) { | 189 if (dip_size != canvas_size) { |
| 222 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); | 190 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); |
| 223 canvas->sk_canvas()->scale(scale, scale); | 191 canvas->sk_canvas()->scale(scale, scale); |
| 224 } | 192 } |
| 225 | 193 |
| 226 for (const auto& path : paths) | 194 for (const auto& path : paths) |
| 227 canvas->DrawPath(path, paint); | 195 canvas->DrawPath(path, paint); |
| 228 } | 196 } |
| 229 | 197 |
| 198 class VectorIconSource : public CanvasImageSource { |
| 199 public: |
| 200 VectorIconSource(VectorIconId id, size_t dip_size, SkColor color) |
| 201 : CanvasImageSource( |
| 202 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)), |
| 203 false), |
| 204 id_(id), |
| 205 color_(color) {} |
| 206 |
| 207 VectorIconSource(const std::string& definition, |
| 208 size_t dip_size, |
| 209 SkColor color) |
| 210 : CanvasImageSource( |
| 211 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)), |
| 212 false), |
| 213 id_(VectorIconId::VECTOR_ICON_NONE), |
| 214 path_(PathFromSource(definition)), |
| 215 color_(color) {} |
| 216 |
| 217 ~VectorIconSource() override {} |
| 218 |
| 219 // CanvasImageSource: |
| 220 void Draw(gfx::Canvas* canvas) override { |
| 221 if (path_.empty()) |
| 222 PaintVectorIcon(canvas, id_, size_.width(), color_); |
| 223 else |
| 224 PaintPath(canvas, path_.data(), size_.width(), color_); |
| 225 } |
| 226 |
| 227 private: |
| 228 const VectorIconId id_; |
| 229 const std::vector<PathElement> path_; |
| 230 const SkColor color_; |
| 231 |
| 232 DISALLOW_COPY_AND_ASSIGN(VectorIconSource); |
| 233 }; |
| 234 |
| 235 // This class caches vector icons (as ImageSkia) so they don't have to be drawn |
| 236 // more than once. This also guarantees the backing data for the images returned |
| 237 // by CreateVectorIcon will persist in memory until program termination. |
| 238 class VectorIconCache { |
| 239 public: |
| 240 VectorIconCache() {} |
| 241 ~VectorIconCache() {} |
| 242 |
| 243 ImageSkia GetOrCreateIcon(VectorIconId id, size_t dip_size, SkColor color) { |
| 244 IconDescription description(id, dip_size, color); |
| 245 auto iter = images_.find(description); |
| 246 if (iter != images_.end()) |
| 247 return iter->second; |
| 248 |
| 249 ImageSkia icon( |
| 250 new VectorIconSource(id, dip_size, color), |
| 251 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size))); |
| 252 images_.insert(std::make_pair(description, icon)); |
| 253 return icon; |
| 254 } |
| 255 |
| 256 private: |
| 257 struct IconDescription { |
| 258 IconDescription(VectorIconId id, size_t dip_size, SkColor color) |
| 259 : id(id), dip_size(dip_size), color(color) {} |
| 260 |
| 261 bool operator<(const IconDescription& other) const { |
| 262 if (id != other.id) |
| 263 return id < other.id; |
| 264 if (dip_size != other.dip_size) |
| 265 return dip_size < other.dip_size; |
| 266 return color < other.color; |
| 267 } |
| 268 |
| 269 VectorIconId id; |
| 270 size_t dip_size; |
| 271 SkColor color; |
| 272 }; |
| 273 |
| 274 std::map<IconDescription, ImageSkia> images_; |
| 275 |
| 276 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); |
| 277 }; |
| 278 |
| 279 static base::LazyInstance<VectorIconCache> g_icon_cache = |
| 280 LAZY_INSTANCE_INITIALIZER; |
| 281 |
| 282 } // namespace |
| 283 |
| 284 void PaintVectorIcon(Canvas* canvas, |
| 285 VectorIconId id, |
| 286 size_t dip_size, |
| 287 SkColor color) { |
| 288 DCHECK(VectorIconId::VECTOR_ICON_NONE != id); |
| 289 PaintPath(canvas, GetPathForVectorIcon(id), dip_size, color); |
| 290 } |
| 291 |
| 230 ImageSkia CreateVectorIcon(VectorIconId id, size_t dip_size, SkColor color) { | 292 ImageSkia CreateVectorIcon(VectorIconId id, size_t dip_size, SkColor color) { |
| 231 return g_icon_cache.Get().GetOrCreateIcon(id, dip_size, color); | 293 return g_icon_cache.Get().GetOrCreateIcon(id, dip_size, color); |
| 232 } | 294 } |
| 233 | 295 |
| 296 ImageSkia CreateVectorIconFromSource(const std::string& source, |
| 297 size_t dip_size, |
| 298 SkColor color) { |
| 299 return ImageSkia( |
| 300 new VectorIconSource(source, dip_size, color), |
| 301 gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size))); |
| 302 } |
| 303 |
| 234 } // namespace gfx | 304 } // namespace gfx |
| OLD | NEW |