| 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 #include <tuple> | 8 #include <tuple> |
| 9 | 9 |
| 10 #include "base/i18n/rtl.h" | 10 #include "base/i18n/rtl.h" |
| 11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_split.h" | 15 #include "base/strings/string_split.h" |
| 16 #include "cc/paint/paint_canvas.h" | 16 #include "cc/paint/paint_canvas.h" |
| 17 #include "cc/paint/paint_flags.h" | 17 #include "cc/paint/paint_flags.h" |
| 18 #include "third_party/skia/include/core/SkPath.h" | 18 #include "third_party/skia/include/core/SkPath.h" |
| 19 #include "ui/gfx/animation/tween.h" |
| 19 #include "ui/gfx/canvas.h" | 20 #include "ui/gfx/canvas.h" |
| 20 #include "ui/gfx/image/canvas_image_source.h" | 21 #include "ui/gfx/image/canvas_image_source.h" |
| 21 #include "ui/gfx/scoped_canvas.h" | 22 #include "ui/gfx/scoped_canvas.h" |
| 22 #include "ui/gfx/vector_icon_types.h" | 23 #include "ui/gfx/vector_icon_types.h" |
| 23 | 24 |
| 24 namespace gfx { | 25 namespace gfx { |
| 25 | 26 |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 29 class PathParser { |
| 30 public: |
| 31 PathParser(const PathElement* path_elements) |
| 32 : path_elements_(path_elements) {} |
| 33 ~PathParser() {} |
| 34 |
| 35 bool Advance() { |
| 36 if (command_index_ < 0) |
| 37 command_index_ = 0; |
| 38 else if (CurrentCommand() != END) |
| 39 command_index_ += GetArgumentCount() + 1; |
| 40 return CurrentCommand() != END; |
| 41 } |
| 42 |
| 43 CommandType CurrentCommand() const { |
| 44 return path_elements_[command_index_].command; |
| 45 } |
| 46 |
| 47 SkScalar GetArgument(int index) const { |
| 48 DCHECK_LT(index, GetArgumentCount()); |
| 49 return path_elements_[command_index_ + 1 + index].arg; |
| 50 } |
| 51 |
| 52 private: |
| 53 int GetArgumentCount() const { |
| 54 switch (CurrentCommand()) { |
| 55 case STROKE: |
| 56 case H_LINE_TO: |
| 57 case R_H_LINE_TO: |
| 58 case V_LINE_TO: |
| 59 case R_V_LINE_TO: |
| 60 case CANVAS_DIMENSIONS: |
| 61 return 1; |
| 62 |
| 63 case MOVE_TO: |
| 64 case R_MOVE_TO: |
| 65 case LINE_TO: |
| 66 case R_LINE_TO: |
| 67 return 2; |
| 68 |
| 69 case CIRCLE: |
| 70 return 3; |
| 71 |
| 72 case PATH_COLOR_ARGB: |
| 73 case CUBIC_TO_SHORTHAND: |
| 74 case CLIP: |
| 75 return 4; |
| 76 |
| 77 case ROUND_RECT: |
| 78 return 5; |
| 79 |
| 80 case CUBIC_TO: |
| 81 case R_CUBIC_TO: |
| 82 return 6; |
| 83 |
| 84 case ARC_TO: |
| 85 case R_ARC_TO: |
| 86 return 7; |
| 87 |
| 88 case NEW_PATH: |
| 89 case PATH_MODE_CLEAR: |
| 90 case CAP_SQUARE: |
| 91 case CLOSE: |
| 92 case DISABLE_AA: |
| 93 case FLIPS_IN_RTL: |
| 94 case END: |
| 95 return 0; |
| 96 } |
| 97 } |
| 98 |
| 99 const PathElement* path_elements_; |
| 100 int command_index_ = -1; |
| 101 }; |
| 102 |
| 28 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO. | 103 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO. |
| 29 CommandType CommandFromString(const std::string& source) { | 104 CommandType CommandFromString(const std::string& source) { |
| 30 #define RETURN_IF_IS(command) \ | 105 #define RETURN_IF_IS(command) \ |
| 31 if (source == #command) \ | 106 if (source == #command) \ |
| 32 return command; | 107 return command; |
| 33 | 108 |
| 34 RETURN_IF_IS(NEW_PATH); | 109 RETURN_IF_IS(NEW_PATH); |
| 35 RETURN_IF_IS(PATH_COLOR_ARGB); | 110 RETURN_IF_IS(PATH_COLOR_ARGB); |
| 36 RETURN_IF_IS(PATH_MODE_CLEAR); | 111 RETURN_IF_IS(PATH_MODE_CLEAR); |
| 37 RETURN_IF_IS(STROKE); | 112 RETURN_IF_IS(STROKE); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 path.push_back(PathElement(SkIntToScalar(hex_value))); | 151 path.push_back(PathElement(SkIntToScalar(hex_value))); |
| 77 else | 152 else |
| 78 path.push_back(PathElement(CommandFromString(piece))); | 153 path.push_back(PathElement(CommandFromString(piece))); |
| 79 } | 154 } |
| 80 return path; | 155 return path; |
| 81 } | 156 } |
| 82 | 157 |
| 83 void PaintPath(Canvas* canvas, | 158 void PaintPath(Canvas* canvas, |
| 84 const PathElement* path_elements, | 159 const PathElement* path_elements, |
| 85 int dip_size, | 160 int dip_size, |
| 86 SkColor color) { | 161 SkColor color, |
| 162 const base::TimeDelta* elapsed_time = nullptr) { |
| 87 SkPath path; | 163 SkPath path; |
| 88 path.setFillType(SkPath::kEvenOdd_FillType); | 164 path.setFillType(SkPath::kEvenOdd_FillType); |
| 89 | 165 |
| 90 int canvas_size = kReferenceSizeDip; | 166 int canvas_size = kReferenceSizeDip; |
| 91 std::vector<SkPath> paths; | 167 std::vector<SkPath> paths; |
| 92 std::vector<cc::PaintFlags> flags_array; | 168 std::vector<cc::PaintFlags> flags_array; |
| 93 SkRect clip_rect = SkRect::MakeEmpty(); | 169 SkRect clip_rect = SkRect::MakeEmpty(); |
| 94 bool flips_in_rtl = false; | 170 bool flips_in_rtl = false; |
| 95 CommandType previous_command_type = NEW_PATH; | 171 CommandType previous_command_type = NEW_PATH; |
| 96 | 172 |
| 97 for (size_t i = 0; path_elements[i].type != END; i++) { | 173 PathParser parser(path_elements); |
| 98 if (paths.empty() || path_elements[i].type == NEW_PATH) { | 174 auto arg = [&parser](int i) { return parser.GetArgument(i); }; |
| 175 |
| 176 while (parser.Advance()) { |
| 177 const CommandType command_type = parser.CurrentCommand(); |
| 178 |
| 179 auto start_new_path = [&paths]() { |
| 99 paths.push_back(SkPath()); | 180 paths.push_back(SkPath()); |
| 100 paths.back().setFillType(SkPath::kEvenOdd_FillType); | 181 paths.back().setFillType(SkPath::kEvenOdd_FillType); |
| 101 | 182 }; |
| 183 auto start_new_flags = [&flags_array, &color]() { |
| 102 flags_array.push_back(cc::PaintFlags()); | 184 flags_array.push_back(cc::PaintFlags()); |
| 103 flags_array.back().setColor(color); | 185 flags_array.back().setColor(color); |
| 104 flags_array.back().setAntiAlias(true); | 186 flags_array.back().setAntiAlias(true); |
| 105 flags_array.back().setStrokeCap(cc::PaintFlags::kRound_Cap); | 187 flags_array.back().setStrokeCap(cc::PaintFlags::kRound_Cap); |
| 188 }; |
| 189 |
| 190 if (paths.empty() || command_type == NEW_PATH) { |
| 191 start_new_path(); |
| 192 start_new_flags(); |
| 106 } | 193 } |
| 107 | 194 |
| 108 SkPath& path = paths.back(); | 195 SkPath& path = paths.back(); |
| 109 cc::PaintFlags& flags = flags_array.back(); | 196 cc::PaintFlags& flags = flags_array.back(); |
| 110 CommandType command_type = path_elements[i].type; | |
| 111 switch (command_type) { | 197 switch (command_type) { |
| 112 // Handled above. | 198 // Handled above. |
| 113 case NEW_PATH: | 199 case NEW_PATH: |
| 114 continue; | 200 break; |
| 201 |
| 202 case TRANSITION_FROM: { |
| 203 start_new_path(); |
| 204 break; |
| 205 } |
| 206 |
| 207 case TRANSITION_TO: { |
| 208 start_new_path(); |
| 209 start_new_flags(); |
| 210 break; |
| 211 } |
| 212 |
| 213 case TRANSITION_END: { |
| 214 DCHECK_GT(paths.size(), 2U); |
| 215 |
| 216 base::TimeDelta delay = base::TimeDelta::FromMillisecondsD( |
| 217 SkScalarToDouble(path_elements[++i].arg)); |
| 218 base::TimeDelta duration = base::TimeDelta::FromMillisecondsD( |
| 219 SkScalarToDouble(path_elements[++i].arg)); |
| 220 |
| 221 const base::TimeDelta current_time = |
| 222 elapsed_time ? *elapsed_time : base::TimeDelta(); |
| 223 |
| 224 double state = 0; |
| 225 if (current_time >= delay + duration) { |
| 226 state = 1; |
| 227 } else if (current_time > delay) { |
| 228 state = (current_time - delay).ToInternalValue() / |
| 229 static_cast<double>(duration.ToInternalValue()); |
| 230 } |
| 231 |
| 232 auto weight = Tween::CalculateValue(Tween::FAST_OUT_SLOW_IN, state); |
| 233 |
| 234 SkPath path1, path2; |
| 235 path1.swap(paths.back()); |
| 236 paths.pop_back(); |
| 237 path2.swap(paths.back()); |
| 238 paths.pop_back(); |
| 239 |
| 240 SkPath interpolated_path; |
| 241 bool could_interpolate = |
| 242 path1.interpolate(path2, weight, &interpolated_path); |
| 243 DCHECK(could_interpolate); |
| 244 paths.back().addPath(interpolated_path); |
| 245 |
| 246 // Manual interpolation of flags properties. |
| 247 DCHECK_GT(flags_array.size(), 1U); |
| 248 cc::PaintFlags& end_flags = flags_array.back(); |
| 249 cc::PaintFlags& start_flags = flags_array[flags_array.size() - 2]; |
| 250 |
| 251 start_flags.setColor(Tween::ColorValueBetween( |
| 252 weight, start_flags.getColor(), end_flags.getColor())); |
| 253 start_flags.setStrokeWidth(Tween::FloatValueBetween( |
| 254 weight, start_flags.getStrokeWidth(), end_flags.getStrokeWidth())); |
| 255 |
| 256 flags_array.pop_back(); |
| 257 break; |
| 258 } |
| 115 | 259 |
| 116 case PATH_COLOR_ARGB: { | 260 case PATH_COLOR_ARGB: { |
| 117 int a = SkScalarFloorToInt(path_elements[++i].arg); | 261 int a = SkScalarFloorToInt(path_elements[++i].arg); |
| 118 int r = SkScalarFloorToInt(path_elements[++i].arg); | 262 int r = SkScalarFloorToInt(path_elements[++i].arg); |
| 119 int g = SkScalarFloorToInt(path_elements[++i].arg); | 263 int g = SkScalarFloorToInt(path_elements[++i].arg); |
| 120 int b = SkScalarFloorToInt(path_elements[++i].arg); | 264 int b = SkScalarFloorToInt(path_elements[++i].arg); |
| 121 flags.setColor(SkColorSetARGB(a, r, g, b)); | 265 flags.setColor(SkColorSetARGB(a, r, g, b)); |
| 266 ======= |
| 267 >>>>>>> vectorriconparser |
| 122 break; | 268 break; |
| 123 } | |
| 124 | 269 |
| 125 case PATH_MODE_CLEAR: { | 270 case PATH_COLOR_ARGB: |
| 271 flags.setColor(SkColorSetARGB( |
| 272 SkScalarFloorToInt(arg(0)), SkScalarFloorToInt(arg(1)), |
| 273 SkScalarFloorToInt(arg(2)), SkScalarFloorToInt(arg(3)))); |
| 274 break; |
| 275 |
| 276 case PATH_MODE_CLEAR: |
| 126 flags.setBlendMode(SkBlendMode::kClear); | 277 flags.setBlendMode(SkBlendMode::kClear); |
| 127 break; | 278 break; |
| 128 }; | |
| 129 | 279 |
| 130 case STROKE: { | 280 case STROKE: |
| 131 flags.setStyle(cc::PaintFlags::kStroke_Style); | 281 flags.setStyle(cc::PaintFlags::kStroke_Style); |
| 132 SkScalar width = path_elements[++i].arg; | 282 flags.setStrokeWidth(arg(0)); |
| 133 flags.setStrokeWidth(width); | |
| 134 break; | 283 break; |
| 135 } | |
| 136 | 284 |
| 137 case CAP_SQUARE: { | 285 case CAP_SQUARE: |
| 138 flags.setStrokeCap(cc::PaintFlags::kSquare_Cap); | 286 flags.setStrokeCap(cc::PaintFlags::kSquare_Cap); |
| 139 break; | 287 break; |
| 140 } | |
| 141 | 288 |
| 142 case MOVE_TO: { | 289 case MOVE_TO: |
| 143 SkScalar x = path_elements[++i].arg; | 290 path.moveTo(arg(0), arg(1)); |
| 144 SkScalar y = path_elements[++i].arg; | |
| 145 path.moveTo(x, y); | |
| 146 break; | 291 break; |
| 147 } | |
| 148 | 292 |
| 149 case R_MOVE_TO: { | 293 case R_MOVE_TO: |
| 150 if (previous_command_type == CLOSE) { | 294 if (previous_command_type == CLOSE) { |
| 151 // This triggers injectMoveToIfNeeded() so that the next subpath | 295 // This triggers injectMoveToIfNeeded() so that the next subpath |
| 152 // will start at the correct place. See [ | 296 // will start at the correct place. See [ |
| 153 // https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand ]. | 297 // https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand ]. |
| 154 path.rLineTo(0, 0); | 298 path.rLineTo(0, 0); |
| 155 } | 299 } |
| 156 | 300 |
| 157 SkScalar x = path_elements[++i].arg; | 301 path.rMoveTo(arg(0), arg(1)); |
| 158 SkScalar y = path_elements[++i].arg; | |
| 159 path.rMoveTo(x, y); | |
| 160 break; | 302 break; |
| 161 } | |
| 162 | 303 |
| 163 case ARC_TO: | 304 case ARC_TO: |
| 164 case R_ARC_TO: { | 305 case R_ARC_TO: { |
| 165 SkScalar rx = path_elements[++i].arg; | 306 SkScalar rx = arg(0); |
| 166 SkScalar ry = path_elements[++i].arg; | 307 SkScalar ry = arg(1); |
| 167 SkScalar angle = path_elements[++i].arg; | 308 SkScalar angle = arg(2); |
| 168 SkScalar large_arc_flag = path_elements[++i].arg; | 309 SkScalar large_arc_flag = arg(3); |
| 169 SkScalar arc_sweep_flag = path_elements[++i].arg; | 310 SkScalar arc_sweep_flag = arg(4); |
| 170 SkScalar x = path_elements[++i].arg; | 311 SkScalar x = arg(5); |
| 171 SkScalar y = path_elements[++i].arg; | 312 SkScalar y = arg(6); |
| 172 | 313 |
| 173 auto path_fn = | 314 auto path_fn = |
| 174 command_type == ARC_TO | 315 command_type == ARC_TO |
| 175 ? static_cast<void (SkPath::*)( | 316 ? static_cast<void (SkPath::*)( |
| 176 SkScalar, SkScalar, SkScalar, SkPath::ArcSize, | 317 SkScalar, SkScalar, SkScalar, SkPath::ArcSize, |
| 177 SkPath::Direction, SkScalar, SkScalar)>(&SkPath::arcTo) | 318 SkPath::Direction, SkScalar, SkScalar)>(&SkPath::arcTo) |
| 178 : &SkPath::rArcTo; | 319 : &SkPath::rArcTo; |
| 179 (path.*path_fn)( | 320 (path.*path_fn)( |
| 180 rx, ry, angle, | 321 rx, ry, angle, |
| 181 large_arc_flag ? SkPath::kLarge_ArcSize : SkPath::kSmall_ArcSize, | 322 large_arc_flag ? SkPath::kLarge_ArcSize : SkPath::kSmall_ArcSize, |
| 182 arc_sweep_flag ? SkPath::kCW_Direction : SkPath::kCCW_Direction, x, | 323 arc_sweep_flag ? SkPath::kCW_Direction : SkPath::kCCW_Direction, x, |
| 183 y); | 324 y); |
| 184 break; | 325 break; |
| 185 } | 326 } |
| 186 | 327 |
| 187 case LINE_TO: { | 328 case LINE_TO: |
| 188 SkScalar x = path_elements[++i].arg; | 329 path.lineTo(arg(0), arg(1)); |
| 189 SkScalar y = path_elements[++i].arg; | |
| 190 path.lineTo(x, y); | |
| 191 break; | 330 break; |
| 192 } | |
| 193 | 331 |
| 194 case R_LINE_TO: { | 332 case R_LINE_TO: |
| 195 SkScalar x = path_elements[++i].arg; | 333 path.rLineTo(arg(0), arg(1)); |
| 196 SkScalar y = path_elements[++i].arg; | |
| 197 path.rLineTo(x, y); | |
| 198 break; | 334 break; |
| 199 } | |
| 200 | 335 |
| 201 case H_LINE_TO: { | 336 case H_LINE_TO: { |
| 202 SkPoint last_point; | 337 SkPoint last_point; |
| 203 path.getLastPt(&last_point); | 338 path.getLastPt(&last_point); |
| 204 SkScalar x = path_elements[++i].arg; | 339 path.lineTo(arg(0), last_point.fY); |
| 205 path.lineTo(x, last_point.fY); | |
| 206 break; | 340 break; |
| 207 } | 341 } |
| 208 | 342 |
| 209 case R_H_LINE_TO: { | 343 case R_H_LINE_TO: |
| 210 SkScalar x = path_elements[++i].arg; | 344 path.rLineTo(arg(0), 0); |
| 211 path.rLineTo(x, 0); | |
| 212 break; | 345 break; |
| 213 } | |
| 214 | 346 |
| 215 case V_LINE_TO: { | 347 case V_LINE_TO: { |
| 216 SkPoint last_point; | 348 SkPoint last_point; |
| 217 path.getLastPt(&last_point); | 349 path.getLastPt(&last_point); |
| 218 SkScalar y = path_elements[++i].arg; | 350 path.lineTo(last_point.fX, arg(0)); |
| 219 path.lineTo(last_point.fX, y); | |
| 220 break; | 351 break; |
| 221 } | 352 } |
| 222 | 353 |
| 223 case R_V_LINE_TO: { | 354 case R_V_LINE_TO: |
| 224 SkScalar y = path_elements[++i].arg; | 355 path.rLineTo(0, arg(0)); |
| 225 path.rLineTo(0, y); | |
| 226 break; | 356 break; |
| 227 } | |
| 228 | 357 |
| 229 case CUBIC_TO: { | 358 case CUBIC_TO: |
| 230 SkScalar x1 = path_elements[++i].arg; | 359 path.cubicTo(arg(0), arg(1), arg(2), arg(3), arg(4), arg(5)); |
| 231 SkScalar y1 = path_elements[++i].arg; | |
| 232 SkScalar x2 = path_elements[++i].arg; | |
| 233 SkScalar y2 = path_elements[++i].arg; | |
| 234 SkScalar x3 = path_elements[++i].arg; | |
| 235 SkScalar y3 = path_elements[++i].arg; | |
| 236 path.cubicTo(x1, y1, x2, y2, x3, y3); | |
| 237 break; | 360 break; |
| 238 } | |
| 239 | 361 |
| 240 case R_CUBIC_TO: { | 362 case R_CUBIC_TO: |
| 241 SkScalar x1 = path_elements[++i].arg; | 363 path.rCubicTo(arg(0), arg(1), arg(2), arg(3), arg(4), arg(5)); |
| 242 SkScalar y1 = path_elements[++i].arg; | |
| 243 SkScalar x2 = path_elements[++i].arg; | |
| 244 SkScalar y2 = path_elements[++i].arg; | |
| 245 SkScalar x3 = path_elements[++i].arg; | |
| 246 SkScalar y3 = path_elements[++i].arg; | |
| 247 path.rCubicTo(x1, y1, x2, y2, x3, y3); | |
| 248 break; | 364 break; |
| 249 } | |
| 250 | 365 |
| 251 case CUBIC_TO_SHORTHAND: { | 366 case CUBIC_TO_SHORTHAND: { |
| 252 // Compute the first control point (|x1| and |y1|) as the reflection | 367 // Compute the first control point (|x1| and |y1|) as the reflection |
| 253 // of the second control point on the previous command relative to | 368 // of the second control point on the previous command relative to |
| 254 // the current point. If there is no previous command or if the | 369 // the current point. If there is no previous command or if the |
| 255 // previous command is not a cubic Bezier curve, the first control | 370 // previous command is not a cubic Bezier curve, the first control |
| 256 // point is coincident with the current point. Refer to the SVG | 371 // point is coincident with the current point. Refer to the SVG |
| 257 // path specs for further details. | 372 // path specs for further details. |
| 258 SkPoint last_point; | 373 SkPoint last_point; |
| 259 path.getLastPt(&last_point); | 374 path.getLastPt(&last_point); |
| 260 SkScalar delta_x = 0; | 375 SkScalar delta_x = 0; |
| 261 SkScalar delta_y = 0; | 376 SkScalar delta_y = 0; |
| 262 if (previous_command_type == CUBIC_TO || | 377 if (previous_command_type == CUBIC_TO || |
| 263 previous_command_type == R_CUBIC_TO || | 378 previous_command_type == R_CUBIC_TO || |
| 264 previous_command_type == CUBIC_TO_SHORTHAND) { | 379 previous_command_type == CUBIC_TO_SHORTHAND) { |
| 265 SkPoint last_control_point = path.getPoint(path.countPoints() - 2); | 380 SkPoint last_control_point = path.getPoint(path.countPoints() - 2); |
| 266 delta_x = last_point.fX - last_control_point.fX; | 381 delta_x = last_point.fX - last_control_point.fX; |
| 267 delta_y = last_point.fY - last_control_point.fY; | 382 delta_y = last_point.fY - last_control_point.fY; |
| 268 } | 383 } |
| 269 | 384 |
| 270 SkScalar x1 = last_point.fX + delta_x; | 385 SkScalar x1 = last_point.fX + delta_x; |
| 271 SkScalar y1 = last_point.fY + delta_y; | 386 SkScalar y1 = last_point.fY + delta_y; |
| 272 SkScalar x2 = path_elements[++i].arg; | 387 path.cubicTo(x1, y1, arg(0), arg(1), arg(2), arg(3)); |
| 273 SkScalar y2 = path_elements[++i].arg; | |
| 274 SkScalar x3 = path_elements[++i].arg; | |
| 275 SkScalar y3 = path_elements[++i].arg; | |
| 276 path.cubicTo(x1, y1, x2, y2, x3, y3); | |
| 277 break; | 388 break; |
| 278 } | 389 } |
| 279 | 390 |
| 280 case CIRCLE: { | 391 case CIRCLE: |
| 281 SkScalar x = path_elements[++i].arg; | 392 path.addCircle(arg(0), arg(1), arg(2)); |
| 282 SkScalar y = path_elements[++i].arg; | |
| 283 SkScalar r = path_elements[++i].arg; | |
| 284 path.addCircle(x, y, r); | |
| 285 break; | 393 break; |
| 286 } | |
| 287 | 394 |
| 288 case ROUND_RECT: { | 395 case ROUND_RECT: |
| 289 SkScalar x = path_elements[++i].arg; | 396 path.addRoundRect(SkRect::MakeXYWH(arg(0), arg(1), arg(2), arg(3)), |
| 290 SkScalar y = path_elements[++i].arg; | 397 arg(4), arg(4)); |
| 291 SkScalar w = path_elements[++i].arg; | |
| 292 SkScalar h = path_elements[++i].arg; | |
| 293 SkScalar radius = path_elements[++i].arg; | |
| 294 path.addRoundRect(SkRect::MakeXYWH(x, y, w, h), radius, radius); | |
| 295 break; | 398 break; |
| 296 } | |
| 297 | 399 |
| 298 case CLOSE: { | 400 case CLOSE: |
| 299 path.close(); | 401 path.close(); |
| 300 break; | 402 break; |
| 301 } | |
| 302 | 403 |
| 303 case CANVAS_DIMENSIONS: { | 404 case CANVAS_DIMENSIONS: |
| 304 SkScalar width = path_elements[++i].arg; | 405 canvas_size = SkScalarTruncToInt(arg(0)); |
| 305 canvas_size = SkScalarTruncToInt(width); | |
| 306 break; | 406 break; |
| 307 } | |
| 308 | 407 |
| 309 case CLIP: { | 408 case CLIP: |
| 310 SkScalar x = path_elements[++i].arg; | 409 clip_rect = SkRect::MakeXYWH(arg(0), arg(1), arg(2), arg(3)); |
| 311 SkScalar y = path_elements[++i].arg; | |
| 312 SkScalar w = path_elements[++i].arg; | |
| 313 SkScalar h = path_elements[++i].arg; | |
| 314 clip_rect = SkRect::MakeXYWH(x, y, w, h); | |
| 315 break; | 410 break; |
| 316 } | |
| 317 | 411 |
| 318 case DISABLE_AA: { | 412 case DISABLE_AA: |
| 319 flags.setAntiAlias(false); | 413 flags.setAntiAlias(false); |
| 320 break; | 414 break; |
| 321 } | |
| 322 | 415 |
| 323 case FLIPS_IN_RTL: { | 416 case FLIPS_IN_RTL: |
| 324 flips_in_rtl = true; | 417 flips_in_rtl = true; |
| 325 break; | 418 break; |
| 326 } | |
| 327 | 419 |
| 328 case END: | 420 case END: |
| 329 NOTREACHED(); | 421 NOTREACHED(); |
| 330 break; | 422 break; |
| 331 } | 423 } |
| 332 | 424 |
| 333 previous_command_type = command_type; | 425 previous_command_type = command_type; |
| 334 } | 426 } |
| 335 | 427 |
| 336 gfx::ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, | 428 ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, flips_in_rtl); |
| 337 flips_in_rtl); | |
| 338 | 429 |
| 339 if (dip_size != canvas_size) { | 430 if (dip_size != canvas_size) { |
| 340 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); | 431 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); |
| 341 canvas->sk_canvas()->scale(scale, scale); | 432 canvas->sk_canvas()->scale(scale, scale); |
| 342 } | 433 } |
| 343 | 434 |
| 344 if (!clip_rect.isEmpty()) | 435 if (!clip_rect.isEmpty()) |
| 345 canvas->sk_canvas()->clipRect(clip_rect); | 436 canvas->sk_canvas()->clipRect(clip_rect); |
| 346 | 437 |
| 347 DCHECK_EQ(flags_array.size(), paths.size()); | 438 DCHECK_EQ(flags_array.size(), paths.size()); |
| 348 for (size_t i = 0; i < paths.size(); ++i) | 439 for (size_t i = 0; i < paths.size(); ++i) |
| 349 canvas->DrawPath(paths[i], flags_array[i]); | 440 canvas->DrawPath(paths[i], flags_array[i]); |
| 350 } | 441 } |
| 351 | 442 |
| 352 class VectorIconSource : public CanvasImageSource { | 443 class VectorIconSource : public CanvasImageSource { |
| 353 public: | 444 public: |
| 354 VectorIconSource(const VectorIcon& icon, | 445 VectorIconSource(const VectorIcon& icon, |
| 355 int dip_size, | 446 int dip_size, |
| 356 SkColor color, | 447 SkColor color, |
| 357 const VectorIcon& badge_icon) | 448 const VectorIcon& badge_icon) |
| 358 : CanvasImageSource(gfx::Size(dip_size, dip_size), false), | 449 : CanvasImageSource(Size(dip_size, dip_size), false), |
| 359 color_(color), | 450 color_(color), |
| 360 icon_(icon), | 451 icon_(icon), |
| 361 badge_(badge_icon) {} | 452 badge_(badge_icon) {} |
| 362 | 453 |
| 363 VectorIconSource(const std::string& definition, int dip_size, SkColor color) | 454 VectorIconSource(const std::string& definition, int dip_size, SkColor color) |
| 364 : CanvasImageSource(gfx::Size(dip_size, dip_size), false), | 455 : CanvasImageSource(Size(dip_size, dip_size), false), |
| 365 color_(color), | 456 color_(color), |
| 366 icon_(kNoneIcon), | 457 icon_(kNoneIcon), |
| 367 badge_(kNoneIcon), | 458 badge_(kNoneIcon), |
| 368 path_(PathFromSource(definition)) {} | 459 path_(PathFromSource(definition)) {} |
| 369 | 460 |
| 370 ~VectorIconSource() override {} | 461 ~VectorIconSource() override {} |
| 371 | 462 |
| 372 // CanvasImageSource: | 463 // CanvasImageSource: |
| 373 bool HasRepresentationAtAllScales() const override { | 464 bool HasRepresentationAtAllScales() const override { |
| 374 return !icon_.is_empty(); | 465 return !icon_.is_empty(); |
| 375 } | 466 } |
| 376 | 467 |
| 377 void Draw(gfx::Canvas* canvas) override { | 468 void Draw(Canvas* canvas) override { |
| 378 if (path_.empty()) { | 469 if (path_.empty()) { |
| 379 PaintVectorIcon(canvas, icon_, size_.width(), color_); | 470 PaintVectorIcon(canvas, icon_, size_.width(), color_); |
| 380 if (!badge_.is_empty()) | 471 if (!badge_.is_empty()) |
| 381 PaintVectorIcon(canvas, badge_, size_.width(), color_); | 472 PaintVectorIcon(canvas, badge_, size_.width(), color_); |
| 382 } else { | 473 } else { |
| 383 PaintPath(canvas, path_.data(), size_.width(), color_); | 474 PaintPath(canvas, path_.data(), size_.width(), color_); |
| 384 } | 475 } |
| 385 } | 476 } |
| 386 | 477 |
| 387 private: | 478 private: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 405 int dip_size, | 496 int dip_size, |
| 406 SkColor color, | 497 SkColor color, |
| 407 const VectorIcon& badge_icon) { | 498 const VectorIcon& badge_icon) { |
| 408 IconDescription description(&icon, dip_size, color, &badge_icon); | 499 IconDescription description(&icon, dip_size, color, &badge_icon); |
| 409 auto iter = images_.find(description); | 500 auto iter = images_.find(description); |
| 410 if (iter != images_.end()) | 501 if (iter != images_.end()) |
| 411 return iter->second; | 502 return iter->second; |
| 412 | 503 |
| 413 ImageSkia icon_image( | 504 ImageSkia icon_image( |
| 414 new VectorIconSource(icon, dip_size, color, badge_icon), | 505 new VectorIconSource(icon, dip_size, color, badge_icon), |
| 415 gfx::Size(dip_size, dip_size)); | 506 Size(dip_size, dip_size)); |
| 416 images_.insert(std::make_pair(description, icon_image)); | 507 images_.insert(std::make_pair(description, icon_image)); |
| 417 return icon_image; | 508 return icon_image; |
| 418 } | 509 } |
| 419 | 510 |
| 420 private: | 511 private: |
| 421 struct IconDescription { | 512 struct IconDescription { |
| 422 IconDescription(const VectorIcon* icon, | 513 IconDescription(const VectorIcon* icon, |
| 423 int dip_size, | 514 int dip_size, |
| 424 SkColor color, | 515 SkColor color, |
| 425 const VectorIcon* badge_icon) | 516 const VectorIcon* badge_icon) |
| 426 : icon(icon), | 517 : icon(icon), |
| 427 dip_size(dip_size), | 518 dip_size(dip_size), |
| 428 color(color), | 519 color(color), |
| 429 badge_icon(badge_icon) {} | 520 badge_icon(badge_icon) {} |
| 430 | 521 |
| 431 bool operator<(const IconDescription& other) const { | 522 bool operator<(const IconDescription& other) const { |
| 432 return std::tie(icon, dip_size, color, badge_icon) < | 523 return std::tie(icon, dip_size, color, badge_icon) < |
| 433 std::tie(other.icon, other.dip_size, other.color, | 524 std::tie(other.icon, other.dip_size, other.color, |
| 434 other.badge_icon); | 525 other.badge_icon); |
| 435 } | 526 } |
| 436 | 527 |
| 437 const gfx::VectorIcon* icon; | 528 const VectorIcon* icon; |
| 438 int dip_size; | 529 int dip_size; |
| 439 SkColor color; | 530 SkColor color; |
| 440 const gfx::VectorIcon* badge_icon; | 531 const VectorIcon* badge_icon; |
| 441 }; | 532 }; |
| 442 | 533 |
| 443 std::map<IconDescription, ImageSkia> images_; | 534 std::map<IconDescription, ImageSkia> images_; |
| 444 | 535 |
| 445 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); | 536 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); |
| 446 }; | 537 }; |
| 447 | 538 |
| 448 static base::LazyInstance<VectorIconCache>::DestructorAtExit g_icon_cache = | 539 static base::LazyInstance<VectorIconCache>::DestructorAtExit g_icon_cache = |
| 449 LAZY_INSTANCE_INITIALIZER; | 540 LAZY_INSTANCE_INITIALIZER; |
| 450 | 541 |
| 451 } // namespace | 542 } // namespace |
| 452 | 543 |
| 453 const VectorIcon kNoneIcon = {}; | 544 const VectorIcon kNoneIcon = {}; |
| 454 | 545 |
| 455 void PaintVectorIcon(Canvas* canvas, const VectorIcon& icon, SkColor color) { | 546 void PaintVectorIcon(Canvas* canvas, |
| 456 PaintVectorIcon(canvas, icon, GetDefaultSizeOfVectorIcon(icon), color); | 547 const VectorIcon& icon, |
| 548 SkColor color, |
| 549 const base::TimeDelta* elapsed_time) { |
| 550 PaintVectorIcon(canvas, icon, GetDefaultSizeOfVectorIcon(icon), color, |
| 551 elapsed_time); |
| 457 } | 552 } |
| 458 | 553 |
| 459 void PaintVectorIcon(Canvas* canvas, | 554 void PaintVectorIcon(Canvas* canvas, |
| 460 const VectorIcon& icon, | 555 const VectorIcon& icon, |
| 461 int dip_size, | 556 int dip_size, |
| 462 SkColor color) { | 557 SkColor color, |
| 558 const base::TimeDelta* elapsed_time) { |
| 463 DCHECK(!icon.is_empty()); | 559 DCHECK(!icon.is_empty()); |
| 464 const PathElement* path = (canvas->image_scale() == 1.f && icon.path_1x_) | 560 const PathElement* path = (canvas->image_scale() == 1.f && icon.path_1x_) |
| 465 ? icon.path_1x_ | 561 ? icon.path_1x_ |
| 466 : icon.path_; | 562 : icon.path_; |
| 467 PaintPath(canvas, path, dip_size, color); | 563 PaintPath(canvas, path, dip_size, color, elapsed_time); |
| 468 } | 564 } |
| 469 | 565 |
| 470 ImageSkia CreateVectorIcon(const VectorIcon& icon, SkColor color) { | 566 ImageSkia CreateVectorIcon(const VectorIcon& icon, SkColor color) { |
| 471 return CreateVectorIcon(icon, GetDefaultSizeOfVectorIcon(icon), color); | 567 return CreateVectorIcon(icon, GetDefaultSizeOfVectorIcon(icon), color); |
| 472 } | 568 } |
| 473 | 569 |
| 474 ImageSkia CreateVectorIcon(const VectorIcon& icon, | 570 ImageSkia CreateVectorIcon(const VectorIcon& icon, |
| 475 int dip_size, | 571 int dip_size, |
| 476 SkColor color) { | 572 SkColor color) { |
| 477 return CreateVectorIconWithBadge(icon, dip_size, color, kNoneIcon); | 573 return CreateVectorIconWithBadge(icon, dip_size, color, kNoneIcon); |
| 478 } | 574 } |
| 479 | 575 |
| 480 ImageSkia CreateVectorIconWithBadge(const VectorIcon& icon, | 576 ImageSkia CreateVectorIconWithBadge(const VectorIcon& icon, |
| 481 int dip_size, | 577 int dip_size, |
| 482 SkColor color, | 578 SkColor color, |
| 483 const VectorIcon& badge_icon) { | 579 const VectorIcon& badge_icon) { |
| 484 return icon.is_empty() ? gfx::ImageSkia() | 580 return icon.is_empty() ? ImageSkia() |
| 485 : g_icon_cache.Get().GetOrCreateIcon( | 581 : g_icon_cache.Get().GetOrCreateIcon( |
| 486 icon, dip_size, color, badge_icon); | 582 icon, dip_size, color, badge_icon); |
| 487 } | 583 } |
| 488 | 584 |
| 489 ImageSkia CreateVectorIconFromSource(const std::string& source, | 585 ImageSkia CreateVectorIconFromSource(const std::string& source, |
| 490 int dip_size, | 586 int dip_size, |
| 491 SkColor color) { | 587 SkColor color) { |
| 492 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size, | 588 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size, |
| 493 color); | 589 color); |
| 494 } | 590 } |
| 495 | 591 |
| 496 int GetDefaultSizeOfVectorIcon(const gfx::VectorIcon& icon) { | 592 int GetDefaultSizeOfVectorIcon(const VectorIcon& icon) { |
| 497 const PathElement* one_x_path = icon.path_1x_ ? icon.path_1x_ : icon.path_; | 593 const PathElement* one_x_path = icon.path_1x_ ? icon.path_1x_ : icon.path_; |
| 498 return one_x_path[0].type == CANVAS_DIMENSIONS ? one_x_path[1].arg | 594 return one_x_path[0].command == CANVAS_DIMENSIONS ? one_x_path[1].arg |
| 499 : kReferenceSizeDip; | 595 : kReferenceSizeDip; |
| 596 } |
| 597 |
| 598 base::TimeDelta GetDurationOfAnimation(const VectorIcon& icon) { |
| 599 base::TimeDelta last_motion; |
| 600 PathParser parser(icon.path_); |
| 601 while (parser.Advance()) { |
| 602 if (parser.CurrentCommand() != TRANSITION_END) |
| 603 continue; |
| 604 |
| 605 auto end_time = base::TimeDelta::FromMillisecondsD(parser.GetArgument(0)) + |
| 606 base::TimeDelta::FromMillisecondsD(parser.GetArgument(1)); |
| 607 if (end_time > last_motion) |
| 608 last_motion = end_time; |
| 609 } |
| 610 return last_motion; |
| 500 } | 611 } |
| 501 | 612 |
| 502 } // namespace gfx | 613 } // namespace gfx |
| OLD | NEW |