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