| Index: ui/gfx/paint_vector_icon.cc
|
| diff --git a/ui/gfx/paint_vector_icon.cc b/ui/gfx/paint_vector_icon.cc
|
| index fed63bdc4c7b3a12504405170364d1ae476f2b68..0d178d860ca2d6d5fdf3b15569078b18277d64fd 100644
|
| --- a/ui/gfx/paint_vector_icon.cc
|
| +++ b/ui/gfx/paint_vector_icon.cc
|
| @@ -7,6 +7,8 @@
|
| #include <map>
|
|
|
| #include "base/lazy_instance.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_split.h"
|
| #include "third_party/skia/include/core/SkPath.h"
|
| #include "ui/gfx/canvas.h"
|
| #include "ui/gfx/image/canvas_image_source.h"
|
| @@ -17,84 +19,50 @@ namespace gfx {
|
|
|
| namespace {
|
|
|
| -class VectorIconSource : public CanvasImageSource {
|
| - public:
|
| - VectorIconSource(VectorIconId id, size_t dip_size, SkColor color)
|
| - : CanvasImageSource(
|
| - gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)),
|
| - false),
|
| - id_(id),
|
| - color_(color) {}
|
| -
|
| - ~VectorIconSource() override {}
|
| -
|
| - // CanvasImageSource:
|
| - void Draw(gfx::Canvas* canvas) override {
|
| - PaintVectorIcon(canvas, id_, size_.width(), color_);
|
| - }
|
| -
|
| - private:
|
| - const VectorIconId id_;
|
| - const SkColor color_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(VectorIconSource);
|
| -};
|
| -
|
| -// This class caches vector icons (as ImageSkia) so they don't have to be drawn
|
| -// more than once. This also guarantees the backing data for the images returned
|
| -// by CreateVectorIcon will persist in memory until program termination.
|
| -class VectorIconCache {
|
| - public:
|
| - VectorIconCache() {}
|
| - ~VectorIconCache() {}
|
| -
|
| - ImageSkia GetOrCreateIcon(VectorIconId id, size_t dip_size, SkColor color) {
|
| - IconDescription description(id, dip_size, color);
|
| - auto iter = images_.find(description);
|
| - if (iter != images_.end())
|
| - return iter->second;
|
| +// Translates a string such as "MOVE_TO" into a command such as MOVE_TO.
|
| +CommandType CommandFromString(const std::string& source) {
|
| +#define RETURN_IF_IS(command) \
|
| + if (source == #command) \
|
| + return command;
|
| +
|
| + RETURN_IF_IS(MOVE_TO);
|
| + RETURN_IF_IS(R_MOVE_TO);
|
| + RETURN_IF_IS(R_LINE_TO);
|
| + RETURN_IF_IS(H_LINE_TO);
|
| + RETURN_IF_IS(R_H_LINE_TO);
|
| + RETURN_IF_IS(V_LINE_TO);
|
| + RETURN_IF_IS(R_V_LINE_TO);
|
| + RETURN_IF_IS(CUBIC_TO);
|
| + RETURN_IF_IS(R_CUBIC_TO);
|
| + RETURN_IF_IS(CIRCLE);
|
| + RETURN_IF_IS(CLOSE);
|
| + RETURN_IF_IS(END);
|
| +#undef RETURN_IF_IS
|
| +
|
| + NOTREACHED();
|
| + return CLOSE;
|
| +}
|
|
|
| - ImageSkia icon(
|
| - new VectorIconSource(id, dip_size, color),
|
| - gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)));
|
| - images_.insert(std::make_pair(description, icon));
|
| - return icon;
|
| +std::vector<PathElement> PathFromSource(const std::string& source) {
|
| + std::vector<PathElement> path;
|
| + std::vector<std::string> pieces = base::SplitString(
|
| + source, "\n ,f", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
| + for (const auto& piece : pieces) {
|
| + double value;
|
| + if (base::StringToDouble(piece, &value))
|
| + path.push_back(PathElement(SkDoubleToScalar(value)));
|
| + else
|
| + path.push_back(PathElement(CommandFromString(piece)));
|
| }
|
| + return path;
|
| +}
|
|
|
| - private:
|
| - struct IconDescription {
|
| - IconDescription(VectorIconId id, size_t dip_size, SkColor color)
|
| - : id(id), dip_size(dip_size), color(color) {}
|
| -
|
| - bool operator<(const IconDescription& other) const {
|
| - if (id != other.id)
|
| - return id < other.id;
|
| - if (dip_size != other.dip_size)
|
| - return dip_size < other.dip_size;
|
| - return color < other.color;
|
| - }
|
| -
|
| - VectorIconId id;
|
| - size_t dip_size;
|
| - SkColor color;
|
| - };
|
| -
|
| - std::map<IconDescription, ImageSkia> images_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(VectorIconCache);
|
| -};
|
| -
|
| -static base::LazyInstance<VectorIconCache> g_icon_cache =
|
| - LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -} // namespace
|
| -
|
| -void PaintVectorIcon(Canvas* canvas,
|
| - VectorIconId id,
|
| - size_t dip_size,
|
| - SkColor color) {
|
| - DCHECK(VectorIconId::VECTOR_ICON_NONE != id);
|
| - const PathElement* path_elements = GetPathForVectorIcon(id);
|
| +void PaintPath(Canvas* canvas,
|
| + const PathElement* path_elements,
|
| + size_t dip_size,
|
| + SkColor color) {
|
| + SkPath path;
|
| + path.setFillType(SkPath::kEvenOdd_FillType);
|
|
|
| std::vector<SkPath> paths;
|
| paths.push_back(SkPath());
|
| @@ -227,8 +195,110 @@ void PaintVectorIcon(Canvas* canvas,
|
| canvas->DrawPath(path, paint);
|
| }
|
|
|
| +class VectorIconSource : public CanvasImageSource {
|
| + public:
|
| + VectorIconSource(VectorIconId id, size_t dip_size, SkColor color)
|
| + : CanvasImageSource(
|
| + gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)),
|
| + false),
|
| + id_(id),
|
| + color_(color) {}
|
| +
|
| + VectorIconSource(const std::string& definition,
|
| + size_t dip_size,
|
| + SkColor color)
|
| + : CanvasImageSource(
|
| + gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)),
|
| + false),
|
| + id_(VectorIconId::VECTOR_ICON_NONE),
|
| + path_(PathFromSource(definition)),
|
| + color_(color) {}
|
| +
|
| + ~VectorIconSource() override {}
|
| +
|
| + // CanvasImageSource:
|
| + void Draw(gfx::Canvas* canvas) override {
|
| + if (path_.empty())
|
| + PaintVectorIcon(canvas, id_, size_.width(), color_);
|
| + else
|
| + PaintPath(canvas, path_.data(), size_.width(), color_);
|
| + }
|
| +
|
| + private:
|
| + const VectorIconId id_;
|
| + const std::vector<PathElement> path_;
|
| + const SkColor color_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(VectorIconSource);
|
| +};
|
| +
|
| +// This class caches vector icons (as ImageSkia) so they don't have to be drawn
|
| +// more than once. This also guarantees the backing data for the images returned
|
| +// by CreateVectorIcon will persist in memory until program termination.
|
| +class VectorIconCache {
|
| + public:
|
| + VectorIconCache() {}
|
| + ~VectorIconCache() {}
|
| +
|
| + ImageSkia GetOrCreateIcon(VectorIconId id, size_t dip_size, SkColor color) {
|
| + IconDescription description(id, dip_size, color);
|
| + auto iter = images_.find(description);
|
| + if (iter != images_.end())
|
| + return iter->second;
|
| +
|
| + ImageSkia icon(
|
| + new VectorIconSource(id, dip_size, color),
|
| + gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)));
|
| + images_.insert(std::make_pair(description, icon));
|
| + return icon;
|
| + }
|
| +
|
| + private:
|
| + struct IconDescription {
|
| + IconDescription(VectorIconId id, size_t dip_size, SkColor color)
|
| + : id(id), dip_size(dip_size), color(color) {}
|
| +
|
| + bool operator<(const IconDescription& other) const {
|
| + if (id != other.id)
|
| + return id < other.id;
|
| + if (dip_size != other.dip_size)
|
| + return dip_size < other.dip_size;
|
| + return color < other.color;
|
| + }
|
| +
|
| + VectorIconId id;
|
| + size_t dip_size;
|
| + SkColor color;
|
| + };
|
| +
|
| + std::map<IconDescription, ImageSkia> images_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(VectorIconCache);
|
| +};
|
| +
|
| +static base::LazyInstance<VectorIconCache> g_icon_cache =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +} // namespace
|
| +
|
| +void PaintVectorIcon(Canvas* canvas,
|
| + VectorIconId id,
|
| + size_t dip_size,
|
| + SkColor color) {
|
| + DCHECK(VectorIconId::VECTOR_ICON_NONE != id);
|
| + PaintPath(canvas, GetPathForVectorIcon(id), dip_size, color);
|
| +}
|
| +
|
| ImageSkia CreateVectorIcon(VectorIconId id, size_t dip_size, SkColor color) {
|
| return g_icon_cache.Get().GetOrCreateIcon(id, dip_size, color);
|
| }
|
|
|
| +ImageSkia CreateVectorIconFromSource(const std::string& source,
|
| + size_t dip_size,
|
| + SkColor color) {
|
| + return ImageSkia(
|
| + new VectorIconSource(source, dip_size, color),
|
| + gfx::Size(static_cast<int>(dip_size), static_cast<int>(dip_size)));
|
| +}
|
| +
|
| } // namespace gfx
|
|
|