Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(462)

Unified Diff: Source/core/animation/LengthInterpolationType.cpp

Issue 1248093002: Move interpolated Length unit types out of InterpolableValue into NonInterpolableValue (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase again Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/animation/LengthInterpolationType.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/animation/LengthInterpolationType.cpp
diff --git a/Source/core/animation/LengthInterpolationType.cpp b/Source/core/animation/LengthInterpolationType.cpp
index a872f1de65dbf55429c1c549c8cc90fd829c380e..21214df6aaa246417095aa397b9a21fc56ef643f 100644
--- a/Source/core/animation/LengthInterpolationType.cpp
+++ b/Source/core/animation/LengthInterpolationType.cpp
@@ -6,30 +6,55 @@
#include "core/animation/LengthInterpolationType.h"
#include "core/animation/LengthPropertyFunctions.h"
-#include "core/animation/LengthStyleInterpolation.h"
+#include "core/animation/css/CSSAnimatableValueFactory.h"
+#include "core/css/CSSCalculationValue.h"
+#include "core/css/resolver/StyleBuilder.h"
#include "core/css/resolver/StyleResolverState.h"
namespace blink {
+// This class is implemented as a singleton whose instance represents the presence of percentages being used in a Length value
+// while nullptr represents the absence of any percentages.
+class LengthNonInterpolableValue : public NonInterpolableValue {
+public:
+ ~LengthNonInterpolableValue() override { ASSERT_NOT_REACHED(); }
+ static PassRefPtr<LengthNonInterpolableValue> create(bool hasPercentage)
+ {
+ DEFINE_STATIC_REF_WILL_BE_PERSISTENT(LengthNonInterpolableValue, singleton, adoptRef(new LengthNonInterpolableValue()));
+ ASSERT(singleton);
+ return hasPercentage ? singleton : nullptr;
+ }
+ static PassRefPtr<LengthNonInterpolableValue> merge(const NonInterpolableValue* a, const NonInterpolableValue* b)
+ {
+ return create(hasPercentage(a) || hasPercentage(b));
+ }
+ static bool hasPercentage(const NonInterpolableValue* nonInterpolableValue)
+ {
+ ASSERT(!nonInterpolableValue || nonInterpolableValue->type() == LengthNonInterpolableValue::staticType);
+ return static_cast<bool>(nonInterpolableValue);
+ }
+ DEFINE_INLINE_VIRTUAL_TRACE() { NonInterpolableValue::trace(visitor); }
+ DECLARE_NON_INTERPOLABLE_VALUE_TYPE();
+
+private:
+ LengthNonInterpolableValue() { }
+};
+
+DEFINE_NON_INTERPOLABLE_VALUE_TYPE(LengthNonInterpolableValue);
+DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(LengthNonInterpolableValue);
+
LengthInterpolationType::LengthInterpolationType(CSSPropertyID property)
: InterpolationType(property)
, m_valueRange(LengthPropertyFunctions::valueRange(property))
{ }
-static PassOwnPtr<InterpolableList> createNeutralValue()
+static PassOwnPtr<InterpolableList> createNeutralInterpolableValue()
{
- OwnPtr<InterpolableList> listOfValuesAndTypes = InterpolableList::create(2);
const size_t length = CSSPrimitiveValue::LengthUnitTypeCount;
- OwnPtr<InterpolableList> listOfValues = InterpolableList::create(length);
- // TODO(alancutter): Use a NonInterpolableValue to represent the list of types.
- OwnPtr<InterpolableList> listOfTypes = InterpolableList::create(length);
- for (size_t i = 0; i < length; i++) {
- listOfValues->set(i, InterpolableNumber::create(0));
- listOfTypes->set(i, InterpolableNumber::create(0));
- }
- listOfValuesAndTypes->set(0, listOfValues.release());
- listOfValuesAndTypes->set(1, listOfTypes.release());
- return listOfValuesAndTypes.release();
+ OwnPtr<InterpolableList> values = InterpolableList::create(length);
+ for (size_t i = 0; i < length; i++)
+ values->set(i, InterpolableNumber::create(0));
+ return values.release();
}
float LengthInterpolationType::effectiveZoom(const ComputedStyle& style) const
@@ -43,17 +68,11 @@ PassOwnPtr<InterpolationValue> LengthInterpolationType::maybeConvertLength(const
return nullptr;
PixelsAndPercent pixelsAndPercent = length.pixelsAndPercent();
- OwnPtr<InterpolableList> valuesAndTypes = createNeutralValue();
-
- InterpolableList& values = toInterpolableList(*valuesAndTypes->get(0));
- values.set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber::create(pixelsAndPercent.pixels / zoom));
- values.set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNumber::create(pixelsAndPercent.percent));
+ OwnPtr<InterpolableList> values = createNeutralInterpolableValue();
+ values->set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber::create(pixelsAndPercent.pixels / zoom));
+ values->set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNumber::create(pixelsAndPercent.percent));
- InterpolableList& types = toInterpolableList(*valuesAndTypes->get(1));
- types.set(CSSPrimitiveValue::UnitTypePixels, InterpolableNumber::create(pixelsAndPercent.pixels != 0));
- types.set(CSSPrimitiveValue::UnitTypePercentage, InterpolableNumber::create(length.hasPercent()));
-
- return InterpolationValue::create(*this, valuesAndTypes.release());
+ return InterpolationValue::create(*this, values.release(), LengthNonInterpolableValue::create(length.hasPercent()));
}
class ParentLengthChecker : public InterpolationType::ConversionChecker {
@@ -83,7 +102,7 @@ private:
PassOwnPtr<InterpolationValue> LengthInterpolationType::maybeConvertNeutral() const
{
- return InterpolationValue::create(*this, createNeutralValue());
+ return InterpolationValue::create(*this, createNeutralInterpolableValue());
}
PassOwnPtr<InterpolationValue> LengthInterpolationType::maybeConvertInitial() const
@@ -112,38 +131,31 @@ PassOwnPtr<InterpolationValue> LengthInterpolationType::maybeConvertValue(const
const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
- OwnPtr<InterpolableList> listOfValuesAndTypes = InterpolableList::create(2);
- OwnPtr<InterpolableList> listOfValues = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
- OwnPtr<InterpolableList> listOfTypes = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
-
- CSSLengthArray arrayOfValues;
- CSSLengthTypeArray arrayOfTypes;
+ CSSLengthArray valueArray;
for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++)
- arrayOfValues.append(0);
- arrayOfTypes.ensureSize(CSSPrimitiveValue::LengthUnitTypeCount);
+ valueArray.append(0);
+ bool hasPercentage = false;
if (primitiveValue.isValueID()) {
CSSValueID valueID = primitiveValue.getValueID();
double pixels;
if (!LengthPropertyFunctions::getPixelsForKeyword(m_property, valueID, pixels))
return nullptr;
- arrayOfTypes.set(CSSPrimitiveValue::UnitTypePixels);
- arrayOfValues[CSSPrimitiveValue::UnitTypePixels] = pixels;
+ valueArray[CSSPrimitiveValue::UnitTypePixels] = pixels;
} else {
if (!primitiveValue.isLength() && !primitiveValue.isPercentage() && !primitiveValue.isCalculatedPercentageWithLength())
return nullptr;
- primitiveValue.accumulateLengthArray(arrayOfValues, arrayOfTypes);
+ CSSLengthTypeArray hasType;
+ hasType.ensureSize(CSSPrimitiveValue::LengthUnitTypeCount);
+ primitiveValue.accumulateLengthArray(valueArray, hasType);
+ hasPercentage = hasType.get(CSSPrimitiveValue::UnitTypePercentage);
}
- for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
- listOfValues->set(i, InterpolableNumber::create(arrayOfValues.at(i)));
- listOfTypes->set(i, InterpolableNumber::create(arrayOfTypes.get(i)));
- }
-
- listOfValuesAndTypes->set(0, listOfValues.release());
- listOfValuesAndTypes->set(1, listOfTypes.release());
+ OwnPtr<InterpolableList> values = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
+ for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++)
+ values->set(i, InterpolableNumber::create(valueArray.at(i)));
- return InterpolationValue::create(*this, listOfValuesAndTypes.release());
+ return InterpolationValue::create(*this, values.release(), LengthNonInterpolableValue::create(hasPercentage));
}
PassOwnPtr<InterpolationValue> LengthInterpolationType::maybeConvertUnderlyingValue(const StyleResolverState& state) const
@@ -154,12 +166,113 @@ PassOwnPtr<InterpolationValue> LengthInterpolationType::maybeConvertUnderlyingVa
return maybeConvertLength(underlyingLength, effectiveZoom(*state.style()));
}
-void LengthInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue*, StyleResolverState& state) const
+PassOwnPtr<PairwisePrimitiveInterpolation> LengthInterpolationType::mergeSingleConversions(InterpolationValue& startValue, InterpolationValue& endValue) const
+{
+ return PairwisePrimitiveInterpolation::create(*this,
+ startValue.mutableComponent().interpolableValue.release(),
+ endValue.mutableComponent().interpolableValue.release(),
+ LengthNonInterpolableValue::merge(startValue.nonInterpolableValue(), endValue.nonInterpolableValue()));
+}
+
+void LengthInterpolationType::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value) const
{
- // TODO(alancutter): Make all length interpolation functions operate on ValueRanges instead of InterpolationRanges.
- InterpolationRange range = m_valueRange == ValueRangeNonNegative ? RangeNonNegative : RangeAll;
- // TODO(alancutter): Set arbitrary property Lengths on ComputedStyle without using cross compilation unit member function getters (Windows runtime doesn't like it).
- LengthStyleInterpolation::applyInterpolableValue(m_property, interpolableValue, range, state);
+ InterpolationComponentValue& underlyingComponent = underlyingValue.mutableComponent();
+ underlyingComponent.interpolableValue->scaleAndAdd(underlyingFraction, value.interpolableValue());
+ underlyingComponent.nonInterpolableValue = LengthNonInterpolableValue::merge(underlyingValue->nonInterpolableValue(), value.nonInterpolableValue());
+}
+
+static bool isPixelsOrPercentOnly(const InterpolableList& values)
+{
+ for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
+ if (i == CSSPrimitiveValue::UnitTypePixels || i == CSSPrimitiveValue::UnitTypePercentage)
+ continue;
+ if (toInterpolableNumber(values.get(i))->value())
+ return false;
+ }
+ return true;
+}
+
+// TODO(alancutter): Move this to Length.h.
+static double clampToRange(double x, ValueRange range)
+{
+ return (range == ValueRangeNonNegative && x < 0) ? 0 : x;
+}
+
+static Length createLength(const InterpolableList& values, bool hasPercentage, ValueRange range, double zoom)
+{
+ ASSERT(isPixelsOrPercentOnly(values));
+ double pixels = toInterpolableNumber(values.get(CSSPrimitiveValue::UnitTypePixels))->value() * zoom;
+ double percentage = toInterpolableNumber(values.get(CSSPrimitiveValue::UnitTypePercentage))->value();
+ ASSERT(hasPercentage || percentage == 0);
+
+ if (pixels && hasPercentage)
+ return Length(CalculationValue::create(PixelsAndPercent(pixels, percentage), range));
+ if (hasPercentage)
+ return Length(clampToRange(percentage, range), Percent);
+ return Length(CSSPrimitiveValue::clampToCSSLengthRange(clampToRange(pixels, range)), Fixed);
+}
+
+static CSSPrimitiveValue::UnitType toUnitType(int lengthUnitType)
+{
+ return static_cast<CSSPrimitiveValue::UnitType>(CSSPrimitiveValue::lengthUnitTypeToUnitType(static_cast<CSSPrimitiveValue::LengthUnitType>(lengthUnitType)));
+}
+
+static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> createCalcExpression(const InterpolableList& values, bool hasPercentage)
+{
+ RefPtrWillBeRawPtr<CSSCalcExpressionNode> result = nullptr;
+ for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
+ double value = toInterpolableNumber(values.get(i))->value();
+ if (value || (i == CSSPrimitiveValue::UnitTypePercentage && hasPercentage)) {
+ RefPtrWillBeRawPtr<CSSCalcExpressionNode> node = CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(value, toUnitType(i)));
+ result = result ? CSSCalcValue::createExpressionNode(result.release(), node.release(), CalcAdd) : node.release();
+ }
+ }
+ ASSERT(result);
+ return result.release();
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> createCSSValue(const InterpolableList& values, bool hasPercentage, ValueRange range)
+{
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> result;
+ size_t firstUnitIndex = CSSPrimitiveValue::LengthUnitTypeCount;
+ size_t unitTypeCount = 0;
+ for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
+ if ((hasPercentage && i == CSSPrimitiveValue::UnitTypePercentage) || toInterpolableNumber(values.get(i))->value()) {
+ unitTypeCount++;
+ if (unitTypeCount == 1)
+ firstUnitIndex = i;
+ }
+ }
+ switch (unitTypeCount) {
+ case 0:
+ return CSSPrimitiveValue::create(0, CSSPrimitiveValue::UnitType::Pixels);
+ case 1: {
+ double value = clampToRange(toInterpolableNumber(values.get(firstUnitIndex))->value(), range);
+ return CSSPrimitiveValue::create(value, toUnitType(firstUnitIndex));
+ }
+ default:
+ return CSSPrimitiveValue::create(CSSCalcValue::create(createCalcExpression(values, hasPercentage), range));
+ }
+}
+
+void LengthInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, StyleResolverState& state) const
+{
+ const InterpolableList& values = toInterpolableList(interpolableValue);
+ bool hasPercentage = LengthNonInterpolableValue::hasPercentage(nonInterpolableValue);
+ if (isPixelsOrPercentOnly(values)) {
+ Length length = createLength(values, hasPercentage, m_valueRange, effectiveZoom(*state.style()));
+ if (LengthPropertyFunctions::setLength(m_property, *state.style(), length)) {
+#if ENABLE(ASSERT)
+ // Assert that setting the length on ComputedStyle directly is identical to the AnimatableValue code path.
+ RefPtr<AnimatableValue> before = CSSAnimatableValueFactory::create(m_property, *state.style());
+ StyleBuilder::applyProperty(m_property, state, createCSSValue(values, hasPercentage, m_valueRange).get());
+ RefPtr<AnimatableValue> after = CSSAnimatableValueFactory::create(m_property, *state.style());
+ ASSERT(before->equals(*after));
+#endif
+ return;
+ }
+ }
+ StyleBuilder::applyProperty(m_property, state, createCSSValue(values, hasPercentage, m_valueRange).get());
}
} // namespace blink
« no previous file with comments | « Source/core/animation/LengthInterpolationType.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698