summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/blink/renderer/core/animation/svg_length_interpolation_type.cc
blob: dc82ebe01ca1b5632a0243d962c51d60763374cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/animation/svg_length_interpolation_type.h"

#include <memory>
#include <utility>

#include "third_party/blink/renderer/core/animation/interpolable_length.h"
#include "third_party/blink/renderer/core/animation/string_keyframe.h"
#include "third_party/blink/renderer/core/animation/svg_interpolation_environment.h"
#include "third_party/blink/renderer/core/css/css_resolution_units.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_length.h"
#include "third_party/blink/renderer/core/svg/svg_length_context.h"
#include "third_party/blink/renderer/platform/heap/heap.h"

namespace blink {

std::unique_ptr<InterpolableValue>
SVGLengthInterpolationType::NeutralInterpolableValue() {
  return InterpolableLength::CreateNeutral();
}

InterpolationValue SVGLengthInterpolationType::MaybeConvertSVGLength(
    const SVGLength& length) {
  // TODO(crbug.com/991672): This doesn't work on calculated lengths with
  // unitless values, e.g., calc(1 + 1px). Note that unitless values in math
  // expressions remain numbers instead of being converted into |kUserUnit|
  // dimension values. Revisit this later.
  return InterpolationValue(
      InterpolableLength::MaybeConvertCSSValue(length.AsCSSPrimitiveValue()));
}

SVGLength* SVGLengthInterpolationType::ResolveInterpolableSVGLength(
    const InterpolableValue& interpolable_value,
    const SVGLengthContext& length_context,
    SVGLengthMode unit_mode,
    bool negative_values_forbidden) {
  const InterpolableLength& length = To<InterpolableLength>(interpolable_value);
  const CSSPrimitiveValue* primitive_value = length.CreateCSSValue(
      negative_values_forbidden ? kValueRangeNonNegative : kValueRangeAll);

  // We optimise for the common case where only one unit type is involved.
  if (primitive_value->IsNumericLiteralValue())
    return MakeGarbageCollected<SVGLength>(*primitive_value, unit_mode);

  // SVGLength does not support calc expressions, so we convert to canonical
  // units.
  // TODO(crbug.com/991672): This code path uses |primitive_value| as a
  // temporary object to calculate the pixel values. Try to avoid that.
  const auto unit_type = CSSPrimitiveValue::UnitType::kUserUnits;
  const double value = length_context.ResolveValue(*primitive_value, unit_mode);

  auto* result =
      MakeGarbageCollected<SVGLength>(unit_mode);  // defaults to the length 0
  result->NewValueSpecifiedUnits(unit_type, value);
  return result;
}

InterpolationValue SVGLengthInterpolationType::MaybeConvertNeutral(
    const InterpolationValue&,
    ConversionCheckers&) const {
  return InterpolationValue(NeutralInterpolableValue());
}

InterpolationValue SVGLengthInterpolationType::MaybeConvertSVGValue(
    const SVGPropertyBase& svg_value) const {
  if (svg_value.GetType() != kAnimatedLength)
    return nullptr;

  return MaybeConvertSVGLength(To<SVGLength>(svg_value));
}

SVGPropertyBase* SVGLengthInterpolationType::AppliedSVGValue(
    const InterpolableValue& interpolable_value,
    const NonInterpolableValue*) const {
  NOTREACHED();
  // This function is no longer called, because apply has been overridden.
  return nullptr;
}

void SVGLengthInterpolationType::Apply(
    const InterpolableValue& interpolable_value,
    const NonInterpolableValue* non_interpolable_value,
    InterpolationEnvironment& environment) const {
  auto& element = To<SVGInterpolationEnvironment>(environment).SvgElement();
  SVGLengthContext length_context(&element);
  element.SetWebAnimatedAttribute(
      Attribute(),
      ResolveInterpolableSVGLength(interpolable_value, length_context,
                                   unit_mode_, negative_values_forbidden_));
}

}  // namespace blink