Commit 43696b7f authored by Patti's avatar Patti Committed by Commit Bot

Vector Icons: Add VectorIconRep for a sized representation of a VectorIcon.

VectorIcons currently have two representations - a version used at 100% scale
(its |path_1x|) and a version used at all other scale factors (|path|). This
isn't scaleable and can't support having more than two icon representations per
VectorIcon, so add gfx::VectorIconRep to prepare for this.

Bug: 647286
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_vr;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Iff59deb2064ce0f0995016fee9dcdeda16999605
Reviewed-on: https://chromium-review.googlesource.com/942647
Commit-Queue: Patti <patricialor@chromium.org>
Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Reviewed-by: default avatarChristopher Grant <cjgrant@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542703}
parent 125cd9f3
......@@ -23,8 +23,7 @@ class VectorIconTexture : public UiTexture {
SkColor GetColor() const { return color_; }
void SetIcon(const gfx::VectorIcon& icon) {
SetAndDirty(&icon_no_1x_.path, icon.path);
SetAndDirty(&icon_no_1x_.path_size, icon.path_size);
SetAndDirty(&icon_no_1x_.rep, icon.rep);
}
private:
......@@ -90,7 +89,7 @@ void VectorIcon::DrawVectorIcon(gfx::Canvas* canvas,
// 1x version if device scale factor isn't set. See crbug.com/749146. If all
// icons end up being drawn via VectorIcon instances, this will not be
// required (the 1x version is automatically elided by this class).
gfx::VectorIcon icon_no_1x{icon.path, icon.path_size};
gfx::VectorIcon icon_no_1x{icon.rep};
PaintVectorIcon(canvas, icon_no_1x, size_px, color);
}
......
......@@ -21,6 +21,18 @@ def CamelCase(name, suffix):
return 'k' + ''.join(words) + suffix
def GetPathName(name, append_1x = False):
return CamelCase(name, "Path1x" if append_1x else "Path");
def GetRepName(name, append_1x = False):
return CamelCase(name, "Rep1x" if append_1x else "Rep");
def GetIconName(name):
return CamelCase(name, "Icon");
def AggregateVectorIcons(working_directory, file_list, output_cc, output_h):
"""Compiles all .icon files in a directory into two C++ files.
......@@ -82,8 +94,8 @@ def AggregateVectorIcons(working_directory, file_list, output_cc, output_h):
(icon_name, extension) = os.path.splitext(
os.path.basename(path_map[icon]))
(icon_name, scale_factor) = os.path.splitext(icon_name)
output_header.write(
"VECTOR_ICON_TEMPLATE_H({})\n".format(CamelCase(icon_name, "Icon")))
output_header.write("VECTOR_ICON_TEMPLATE_H({})\n".format(
GetIconName(icon_name)))
output_header.close()
# Copy the vector icon drawing commands from the .icon and .1x.icon files
......@@ -110,8 +122,8 @@ def AggregateVectorIcons(working_directory, file_list, output_cc, output_h):
icon_file = open(path_map[icon])
vector_commands = "".join(icon_file.readlines())
icon_file.close()
output_cc.write("PATH_ELEMENT_TEMPLATE({}, {})\n".format(
CamelCase(icon_name, "Path"), vector_commands))
output_cc.write("VECTOR_ICON_REP_TEMPLATE({}, {}, {})\n".format(
GetPathName(icon_name), GetRepName(icon_name), vector_commands))
# Store the vector-drawing commands for foo_bar.1x.icon in the temporary
# variable kFooBarPath1x, if the file exists.
......@@ -120,17 +132,18 @@ def AggregateVectorIcons(working_directory, file_list, output_cc, output_h):
icon_file = open(path_map_1x[icon])
vector_commands_1x = "".join(icon_file.readlines())
icon_file.close()
output_cc.write("PATH_ELEMENT_TEMPLATE({}, {})\n".format(
CamelCase(icon_name, "Path1x"), vector_commands_1x))
output_cc.write("VECTOR_ICON_REP_TEMPLATE({}, {}, {})\n".format(
GetPathName(icon_name, True), GetRepName(icon_name, True),
vector_commands_1x))
# Define the value of kFooBarIcon.
if vector_commands_1x is None:
output_cc.write("VECTOR_ICON_TEMPLATE({}, {})\n".format(CamelCase(
icon_name, "Icon"), CamelCase(icon_name, "Path")))
output_cc.write("VECTOR_ICON_TEMPLATE({}, {})\n".format(
GetIconName(icon_name), GetRepName(icon_name)))
else:
output_cc.write("VECTOR_ICON_TEMPLATE2({}, {}, {})\n".format(CamelCase(
icon_name, "Icon"), CamelCase(icon_name, "Path"), CamelCase(
icon_name, "Path1x")))
output_cc.write("VECTOR_ICON_TEMPLATE2({}, {}, {})\n".format(
GetIconName(icon_name), GetRepName(icon_name),
GetRepName(icon_name, True)))
output_cc.close()
......
......@@ -15,21 +15,19 @@
#define VECTOR_ICON_ID_PREFIX ""
#endif
#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
#define VECTOR_ICON_REP_TEMPLATE(path_name, rep_name, ...) \
static constexpr gfx::PathElement path_name[] = {__VA_ARGS__}; \
constexpr gfx::VectorIconRep rep_name = {path_name, arraysize(path_name)};
// The VectorIcon will be called kMyIcon, and the identifier for the icon might
// be "my_namespace::kMyIconId".
#define VECTOR_ICON_TEMPLATE(icon_name, path_name) \
const char icon_name##Id[] = VECTOR_ICON_ID_PREFIX #icon_name; \
const gfx::VectorIcon icon_name = {path_name, arraysize(path_name), nullptr, \
0u, icon_name##Id};
#define VECTOR_ICON_TEMPLATE(icon_name, rep_name) \
const char icon_name##Id[] = VECTOR_ICON_ID_PREFIX #icon_name; \
const gfx::VectorIcon icon_name = {&rep_name, nullptr, icon_name##Id};
#define VECTOR_ICON_TEMPLATE2(icon_name, path_name, path_name_1x) \
const char icon_name##Id[] = VECTOR_ICON_ID_PREFIX #icon_name; \
const gfx::VectorIcon icon_name = {path_name, arraysize(path_name), \
path_name_1x, arraysize(path_name_1x), \
icon_name##Id};
#define VECTOR_ICON_TEMPLATE2(icon_name, rep_name, rep_name_1x) \
const char icon_name##Id[] = VECTOR_ICON_ID_PREFIX #icon_name; \
const gfx::VectorIcon icon_name = {&rep_name, &rep_name_1x, icon_name##Id};
#else // !COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
#error This file should only be included once.
......
......@@ -540,7 +540,7 @@ IconDescription::IconDescription(const VectorIcon& icon,
// If an icon has a .1x.icon version, it should only be rendered at the size
// specified in that definition.
if (icon.path_1x)
if (icon.rep_1x)
DCHECK_EQ(this->dip_size, GetDefaultSizeOfVectorIcon(icon));
}
......@@ -562,16 +562,19 @@ void PaintVectorIcon(Canvas* canvas,
SkColor color,
const base::TimeDelta& elapsed_time) {
DCHECK(!icon.is_empty());
if (icon.path) {
DCHECK(icon.path_size > 0);
DCHECK_EQ(END, icon.path[icon.path_size - 1].command) << icon.name;
if (icon.rep) {
DCHECK(icon.rep->path_size > 0);
DCHECK_EQ(END, icon.rep->path[icon.rep->path_size - 1].command)
<< icon.name;
}
if (icon.path_1x) {
DCHECK(icon.path_1x_size > 0);
DCHECK_EQ(END, icon.path_1x[icon.path_1x_size - 1].command) << icon.name;
if (icon.rep_1x) {
DCHECK(icon.rep_1x->path_size > 0);
DCHECK_EQ(END, icon.rep_1x->path[icon.rep_1x->path_size - 1].command)
<< icon.name;
}
const PathElement* path =
(canvas->image_scale() == 1.f && icon.path_1x) ? icon.path_1x : icon.path;
const PathElement* path = (canvas->image_scale() == 1.f && icon.rep_1x)
? icon.rep_1x->path
: icon.rep->path;
PaintPath(canvas, path, dip_size, color, elapsed_time);
}
......@@ -609,14 +612,15 @@ ImageSkia CreateVectorIconFromSource(const std::string& source,
}
int GetDefaultSizeOfVectorIcon(const VectorIcon& icon) {
const PathElement* one_x_path = icon.path_1x ? icon.path_1x : icon.path;
const PathElement* one_x_path =
icon.rep_1x ? icon.rep_1x->path : icon.rep->path;
return one_x_path[0].command == CANVAS_DIMENSIONS ? one_x_path[1].arg
: kReferenceSizeDip;
}
base::TimeDelta GetDurationOfAnimation(const VectorIcon& icon) {
base::TimeDelta last_motion;
for (PathParser parser(icon.path); parser.CurrentCommand() != END;
for (PathParser parser(icon.rep->path); parser.CurrentCommand() != END;
parser.Advance()) {
if (parser.CurrentCommand() != TRANSITION_END)
continue;
......
......@@ -51,7 +51,8 @@ TEST(VectorIconTest, RelativeMoveToAfterClose) {
R_LINE_TO, 50, 51,
END,
};
const VectorIcon icon = {elements, arraysize(elements)};
const VectorIconRep icon_rep = {elements, arraysize(elements)};
const VectorIcon icon = {&icon_rep};
PaintVectorIcon(&canvas, icon, 100, SK_ColorMAGENTA);
sk_sp<cc::PaintRecord> record = recorder.finishRecordingAsPicture();
......@@ -88,7 +89,8 @@ TEST(VectorIconTest, FlipsInRtl) {
CLOSE,
END,
};
const VectorIcon icon = {elements, arraysize(elements)};
const VectorIconRep icon_rep = {elements, arraysize(elements)};
const VectorIcon icon = {&icon_rep};
PaintVectorIcon(&canvas, icon, canvas_size, color);
// Count the number of pixels in the canvas.
......
......@@ -79,18 +79,29 @@ struct PathElement {
};
};
struct VectorIcon {
VectorIcon() = default;
// Describes the drawing commands for a single vector icon at a particular pixel
// size or range of sizes.
struct VectorIconRep {
VectorIconRep() = default;
bool is_empty() const { return !path; }
const PathElement* path = nullptr;
const gfx::PathElement* path = nullptr;
// The length of |path|.
size_t path_size = 0u;
const gfx::PathElement* path_1x = nullptr;
// The length of |path_1x|.
size_t path_1x_size = 0u;
private:
DISALLOW_COPY_AND_ASSIGN(VectorIconRep);
};
// A vector icon that stores one or more representations to be used for various
// scale factors and pixel dimensions.
struct VectorIcon {
VectorIcon() = default;
bool is_empty() const { return !rep; }
const VectorIconRep* rep = nullptr;
const VectorIconRep* rep_1x = nullptr;
// A human-readable name, useful for debugging, derived from the name of the
// icon file. This can also be used as an identifier, but vector icon targets
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment