bool ListInterpolationFunctions::equalValues(const InterpolationValue& a, const InterpolationValue& b, EqualNonInterpolableValuesCallback equalNonInterpolableValues) { if (!a && !b) return true; if (!a || !b) return false; const InterpolableList& interpolableListA = toInterpolableList(*a.interpolableValue); const InterpolableList& interpolableListB = toInterpolableList(*b.interpolableValue); if (interpolableListA.length() != interpolableListB.length()) return false; size_t length = interpolableListA.length(); if (length == 0) return true; const NonInterpolableList& nonInterpolableListA = toNonInterpolableList(*a.nonInterpolableValue); const NonInterpolableList& nonInterpolableListB = toNonInterpolableList(*b.nonInterpolableValue); for (size_t i = 0; i < length; i++) { if (!equalNonInterpolableValues(nonInterpolableListA.get(i), nonInterpolableListB.get(i))) return false; } return true; }
PassOwnPtr<PairwisePrimitiveInterpolation> SVGNumberListInterpolationType::mergeSingleConversions(InterpolationValue& startValue, InterpolationValue& endValue) const { size_t startLength = toInterpolableList(startValue.interpolableValue()).length(); size_t endLength = toInterpolableList(endValue.interpolableValue()).length(); if (startLength != endLength) return nullptr; return InterpolationType::mergeSingleConversions(startValue, endValue); }
PairwiseInterpolationValue SVGNumberListInterpolationType::maybeMergeSingles( InterpolationValue&& start, InterpolationValue&& end) const { size_t startLength = toInterpolableList(*start.interpolableValue).length(); size_t endLength = toInterpolableList(*end.interpolableValue).length(); if (startLength != endLength) return nullptr; return InterpolationType::maybeMergeSingles(std::move(start), std::move(end)); }
PassRefPtr<SVGPathByteStream> PathInterpolationFunctions::appliedValue(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue) { RefPtr<SVGPathByteStream> pathByteStream = SVGPathByteStream::create(); InterpolatedSVGPathSource source( toInterpolableList(*toInterpolableList(interpolableValue).get(PathArgsIndex)), toSVGPathNonInterpolableValue(nonInterpolableValue)->pathSegTypes()); SVGPathByteStreamBuilder builder(*pathByteStream); SVGPathParser(&source, &builder).parsePathDataFromSource(false); return pathByteStream.release(); }
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGPathInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue) const { OwnPtr<SVGPathByteStream> pathByteStream = SVGPathByteStream::create(); InterpolatedSVGPathSource source( toInterpolableList(*toInterpolableList(interpolableValue).get(PathArgsIndex)), toSVGPathNonInterpolableValue(nonInterpolableValue)->pathSegTypes()); SVGPathByteStreamBuilder builder(*pathByteStream); SVGPathParser(&source, &builder).parsePathDataFromSource(UnalteredParsing, false); return SVGPath::create(CSSPathValue::create(pathByteStream.release())); }
PairwiseInterpolationValue ListInterpolationFunctions::mergeSingleConversions(InterpolationValue& start, InterpolationValue& end, MergeSingleItemConversionsCallback mergeSingleItemConversions) { size_t startLength = toInterpolableList(*start.interpolableValue).length(); size_t endLength = toInterpolableList(*end.interpolableValue).length(); if (startLength == 0 && endLength == 0) { return PairwiseInterpolationValue( start.interpolableValue.release(), end.interpolableValue.release(), nullptr); } if (startLength == 0) { OwnPtr<InterpolableValue> startInterpolableValue = end.interpolableValue->cloneAndZero(); return PairwiseInterpolationValue( startInterpolableValue.release(), end.interpolableValue.release(), end.nonInterpolableValue.release()); } if (endLength == 0) { OwnPtr<InterpolableValue> endInterpolableValue = start.interpolableValue->cloneAndZero(); return PairwiseInterpolationValue( start.interpolableValue.release(), endInterpolableValue.release(), start.nonInterpolableValue.release()); } size_t finalLength = lowestCommonMultiple(startLength, endLength); OwnPtr<InterpolableList> resultStartInterpolableList = InterpolableList::create(finalLength); OwnPtr<InterpolableList> resultEndInterpolableList = InterpolableList::create(finalLength); Vector<RefPtr<NonInterpolableValue>> resultNonInterpolableValues(finalLength); InterpolableList& startInterpolableList = toInterpolableList(*start.interpolableValue); InterpolableList& endInterpolableList = toInterpolableList(*end.interpolableValue); NonInterpolableList& startNonInterpolableList = toNonInterpolableList(*start.nonInterpolableValue); NonInterpolableList& endNonInterpolableList = toNonInterpolableList(*end.nonInterpolableValue); for (size_t i = 0; i < finalLength; i++) { InterpolationValue start(startInterpolableList.get(i % startLength)->clone(), startNonInterpolableList.get(i % startLength)); InterpolationValue end(endInterpolableList.get(i % endLength)->clone(), endNonInterpolableList.get(i % endLength)); PairwiseInterpolationValue result = mergeSingleItemConversions(start, end); if (!result) return nullptr; resultStartInterpolableList->set(i, result.startInterpolableValue.release()); resultEndInterpolableList->set(i, result.endInterpolableValue.release()); resultNonInterpolableValues[i] = result.nonInterpolableValue.release(); } return PairwiseInterpolationValue( resultStartInterpolableList.release(), resultEndInterpolableList.release(), NonInterpolableList::create(resultNonInterpolableValues)); }
std::unique_ptr<SVGPathByteStream> PathInterpolationFunctions::appliedValue( const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue) { std::unique_ptr<SVGPathByteStream> pathByteStream = SVGPathByteStream::create(); InterpolatedSVGPathSource source( toInterpolableList( *toInterpolableList(interpolableValue).get(PathArgsIndex)), toSVGPathNonInterpolableValue(nonInterpolableValue)->pathSegTypes()); SVGPathByteStreamBuilder builder(*pathByteStream); SVGPathParser::parsePath(source, builder); return pathByteStream; }
void InterpolableList::interpolate(const InterpolableValue& to, const double progress, InterpolableValue& result) const { const InterpolableList& toList = toInterpolableList(to); InterpolableList& resultList = toInterpolableList(result); ASSERT(toList.m_size == m_size); ASSERT(resultList.m_size == m_size); for (size_t i = 0; i < m_size; i++) { ASSERT(m_values[i]); ASSERT(toList.m_values[i]); m_values[i]->interpolate(*(toList.m_values[i]), progress, *(resultList.m_values[i])); } }
void CSSFilterListInterpolationType::composite( UnderlyingValueOwner& underlyingValueOwner, double underlyingFraction, const InterpolationValue& value, double interpolationFraction) const { const NonInterpolableList& underlyingNonInterpolableList = toNonInterpolableList(*underlyingValueOwner.value().nonInterpolableValue); const NonInterpolableList& nonInterpolableList = toNonInterpolableList(*value.nonInterpolableValue); size_t underlyingLength = underlyingNonInterpolableList.length(); size_t length = nonInterpolableList.length(); for (size_t i = 0; i < underlyingLength && i < length; i++) { if (!FilterInterpolationFunctions::filtersAreCompatible( *underlyingNonInterpolableList.get(i), *nonInterpolableList.get(i))) { underlyingValueOwner.set(*this, value); return; } } InterpolableList& underlyingInterpolableList = toInterpolableList( *underlyingValueOwner.mutableValue().interpolableValue); const InterpolableList& interpolableList = toInterpolableList(*value.interpolableValue); DCHECK_EQ(underlyingLength, underlyingInterpolableList.length()); DCHECK_EQ(length, interpolableList.length()); for (size_t i = 0; i < length && i < underlyingLength; i++) underlyingInterpolableList.getMutable(i)->scaleAndAdd( underlyingFraction, *interpolableList.get(i)); if (length <= underlyingLength) return; std::unique_ptr<InterpolableList> extendedInterpolableList = InterpolableList::create(length); for (size_t i = 0; i < length; i++) { if (i < underlyingLength) extendedInterpolableList->set( i, std::move(underlyingInterpolableList.getMutable(i))); else extendedInterpolableList->set(i, interpolableList.get(i)->clone()); } underlyingValueOwner.mutableValue().interpolableValue = std::move(extendedInterpolableList); // const_cast to take a ref. underlyingValueOwner.mutableValue().nonInterpolableValue = const_cast<NonInterpolableValue*>(value.nonInterpolableValue.get()); }
void SVGPointListInterpolationType::composite( UnderlyingValueOwner& underlyingValueOwner, double underlyingFraction, const InterpolationValue& value, double interpolationFraction) const { size_t startLength = toInterpolableList(*underlyingValueOwner.value().interpolableValue) .length(); size_t endLength = toInterpolableList(*value.interpolableValue).length(); if (startLength == endLength) InterpolationType::composite(underlyingValueOwner, underlyingFraction, value, interpolationFraction); else underlyingValueOwner.set(*this, value); }
PassRefPtr<CSSValue> LengthStyleInterpolation::interpolableValueToLength(InterpolableValue* value, ValueRange range) { InterpolableList* listValue = toInterpolableList(value); unsigned unitCount = 0; for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { const InterpolableNumber* subValue = toInterpolableNumber(listValue->get(i)); if (subValue->value()) { unitCount++; } } switch (unitCount) { case 0: return CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX); case 1: for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { const InterpolableNumber* subValue = toInterpolableNumber(listValue->get(i)); double value = subValue->value(); if (value) { if (range == ValueRangeNonNegative && value < 0) value = 0; return CSSPrimitiveValue::create(value, toUnitType(i)); } } ASSERT_NOT_REACHED(); default: return CSSPrimitiveValue::create(CSSCalcValue::create(constructCalcExpression(nullptr, listValue, 0), range)); } }
PassRefPtrWillBeRawPtr<CSSFunctionValue> FilterStyleInterpolation::fromInterpolableValue(const InterpolableValue& value, CSSValueID functionType, InterpolationRange) { const InterpolableList& list = toInterpolableList(value); size_t length = list.length(); RefPtrWillBeRawPtr<CSSFunctionValue> result = CSSFunctionValue::create(functionType); for (size_t i = 0; i < length; ++i) { switch (functionType) { case CSSValueGrayscale: case CSSValueInvert: case CSSValueOpacity: case CSSValueSepia: result->append(CSSPrimitiveValue::create(clampTo<double>(toInterpolableNumber(list.get(i))->value(), 0, 1), CSSPrimitiveValue::UnitType::Number)); break; case CSSValueBrightness: case CSSValueContrast: case CSSValueSaturate: result->append(CSSPrimitiveValue::create(clampTo<double>(toInterpolableNumber(list.get(i))->value(), 0), CSSPrimitiveValue::UnitType::Number)); break; case CSSValueHueRotate: result->append(CSSPrimitiveValue::create(toInterpolableNumber(list.get(i))->value(), CSSPrimitiveValue::UnitType::Degrees)); break; case CSSValueBlur: result->append(LengthStyleInterpolation::fromInterpolableValue(*list.get(i), RangeNonNegative)); break; case CSSValueDropShadow: case CSSValueUrl: default: ASSERT_NOT_REACHED(); break; } } return result.release(); }
void InterpolableList::scaleAndAdd(double scale, const InterpolableValue& other) { const InterpolableList& otherList = toInterpolableList(other); ASSERT(otherList.m_size == m_size); for (size_t i = 0; i < m_size; i++) m_values[i]->scaleAndAdd(scale, *otherList.m_values[i]); }
PassRefPtrWillBeRawPtr<CSSValue> LengthPairStyleInterpolation::interpolableValueToLengthPair(InterpolableValue* value, InterpolationRange range) { InterpolableList* lengthPair = toInterpolableList(value); RefPtrWillBeRawPtr<CSSPrimitiveValue> first = LengthStyleInterpolation::fromInterpolableValue(*lengthPair->get(0), range); RefPtrWillBeRawPtr<CSSPrimitiveValue> second = LengthStyleInterpolation::fromInterpolableValue(*lengthPair->get(1), range); return CSSValuePair::create(first.release(), second.release(), CSSValuePair::KeepIdenticalValues); }
void CSSBorderImageLengthBoxInterpolationType::apply( const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, InterpolationEnvironment& environment) const { const SideNumbers& sideNumbers = toCSSBorderImageLengthBoxNonInterpolableValue(nonInterpolableValue) ->sideNumbers(); const Vector<RefPtr<NonInterpolableValue>>& nonInterpolableValues = toCSSBorderImageLengthBoxNonInterpolableValue(nonInterpolableValue) ->sideNonInterpolableValues(); const InterpolableList& list = toInterpolableList(interpolableValue); const auto& convertSide = [&sideNumbers, &list, &environment, &nonInterpolableValues](size_t index) -> BorderImageLength { if (sideNumbers.isNumber[index]) return clampTo<double>(toInterpolableNumber(list.get(index))->value(), 0); return LengthInterpolationFunctions::createLength( *list.get(index), nonInterpolableValues[index].get(), environment.state().cssToLengthConversionData(), ValueRangeNonNegative); }; BorderImageLengthBox box(convertSide(SideTop), convertSide(SideRight), convertSide(SideBottom), convertSide(SideLeft)); BorderImageLengthBoxPropertyFunctions::setBorderImageLengthBox( cssProperty(), *environment.state().style(), box); }
void PathInterpolationFunctions::composite( UnderlyingValueOwner& underlyingValueOwner, double underlyingFraction, const InterpolationType& type, const InterpolationValue& value) { const InterpolableList& list = toInterpolableList(*value.interpolableValue); double neutralComponent = toInterpolableNumber(list.get(PathNeutralIndex))->value(); if (neutralComponent == 0) { underlyingValueOwner.set(type, value); return; } DCHECK(pathSegTypesMatch( toSVGPathNonInterpolableValue( *underlyingValueOwner.value().nonInterpolableValue) .pathSegTypes(), toSVGPathNonInterpolableValue(*value.nonInterpolableValue) .pathSegTypes())); underlyingValueOwner.mutableValue().interpolableValue->scaleAndAdd( neutralComponent, *value.interpolableValue); underlyingValueOwner.mutableValue().nonInterpolableValue = value.nonInterpolableValue.get(); }
void SVGNumberListInterpolationType::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value) const { const InterpolableList& list = toInterpolableList(value.interpolableValue()); if (toInterpolableList(underlyingValue->interpolableValue()).length() <= list.length()) padWithZeroes(underlyingValue.mutableComponent().interpolableValue, list.length()); InterpolableList& underlyingList = *toInterpolableList(underlyingValue.mutableComponent().interpolableValue.get()); ASSERT(underlyingList.length() >= list.length()); size_t i = 0; for (; i < list.length(); i++) underlyingList.getMutable(i)->scaleAndAdd(underlyingFraction, *list.get(i)); for (; i < underlyingList.length(); i++) underlyingList.getMutable(i)->scale(underlyingFraction); }
PassRefPtrWillBeRawPtr<SVGIntegerOptionalInteger> IntegerOptionalIntegerSVGInterpolation::fromInterpolableValue(const InterpolableValue& value, int min) { const InterpolableList& list = toInterpolableList(value); return SVGIntegerOptionalInteger::create( toPositiveInteger(list.get(0), min), toPositiveInteger(list.get(1), min)); }
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGIntegerOptionalIntegerInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const { const InterpolableList& list = toInterpolableList(interpolableValue); return SVGIntegerOptionalInteger::create( toPositiveInteger(list.get(0)), toPositiveInteger(list.get(1))); }
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGNumberListInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const { RefPtrWillBeRawPtr<SVGNumberList> result = SVGNumberList::create(); const InterpolableList& list = toInterpolableList(interpolableValue); for (size_t i = 0; i < list.length(); i++) result->append(SVGNumber::create(toInterpolableNumber(list.get(i))->value())); return result.release(); }
PassOwnPtr<InterpolationValue> PathInterpolationFunctions::maybeConvertNeutral(const InterpolationType& type, const UnderlyingValue& underlyingValue, InterpolationType::ConversionCheckers& conversionCheckers) { conversionCheckers.append(UnderlyingPathSegTypesChecker::create(type, underlyingValue)); OwnPtr<InterpolableList> result = InterpolableList::create(PathComponentIndexCount); result->set(PathArgsIndex, toInterpolableList(underlyingValue->interpolableValue()).get(PathArgsIndex)->cloneAndZero()); result->set(PathNeutralIndex, InterpolableNumber::create(1)); return InterpolationValue::create(type, result.release(), const_cast<NonInterpolableValue*>(underlyingValue->nonInterpolableValue())); // Take ref. }
PassRefPtrWillBeRawPtr<SVGPropertyBase> PathSVGInterpolation::fromInterpolableValue(const InterpolableValue& value, const Vector<SVGPathSegType>& pathSegTypes, SVGPathElement* element) { const InterpolableList& listValue = toInterpolableList(value); RefPtrWillBeRawPtr<SVGPathSegList> result = SVGPathSegList::create(element); SubPathCoordinates coordinates; for (size_t i = 0; i < listValue.length(); i++) result->append(pathSegFromInterpolableValue(*listValue.get(i), pathSegTypes.at(i), coordinates, element)); return result.release(); }
void CSSColorInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue*, InterpolationEnvironment& environment) const { const InterpolableList& colorPair = toInterpolableList(interpolableValue); ASSERT(colorPair.length() == InterpolableColorPairIndexCount); ColorPropertyFunctions::setUnvisitedColor(cssProperty(), *environment.state().style(), resolveInterpolableColor(*colorPair.get(Unvisited), environment.state(), false, cssProperty() == CSSPropertyTextDecorationColor)); ColorPropertyFunctions::setVisitedColor(cssProperty(), *environment.state().style(), resolveInterpolableColor(*colorPair.get(Visited), environment.state(), true, cssProperty() == CSSPropertyTextDecorationColor)); }
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGTransformListInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue) const { RefPtrWillBeRawPtr<SVGTransformList> result = SVGTransformList::create(); const InterpolableList& list = toInterpolableList(interpolableValue); const Vector<SVGTransformType>& transformTypes = toSVGTransformNonInterpolableValue(nonInterpolableValue)->transformTypes(); for (size_t i = 0; i < list.length(); ++i) result->append(fromInterpolableValue(*list.get(i), transformTypes.at(i))); return result.release(); }
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGRectInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const { const InterpolableList& list = toInterpolableList(interpolableValue); RefPtrWillBeRawPtr<SVGRect> result = SVGRect::create(); result->setX(toInterpolableNumber(list.get(RectX))->value()); result->setY(toInterpolableNumber(list.get(RectY))->value()); result->setWidth(toInterpolableNumber(list.get(RectWidth))->value()); result->setHeight(toInterpolableNumber(list.get(RectHeight))->value()); return result; }
SVGPropertyBase* SVGNumberListInterpolationType::appliedSVGValue( const InterpolableValue& interpolableValue, const NonInterpolableValue*) const { SVGNumberList* result = SVGNumberList::create(); const InterpolableList& list = toInterpolableList(interpolableValue); for (size_t i = 0; i < list.length(); i++) result->append( SVGNumber::create(toInterpolableNumber(list.get(i))->value())); return result; }
PassRefPtrWillBeRawPtr<SVGRect> RectSVGInterpolation::fromInterpolableValue(const InterpolableValue& value) { const InterpolableList& list = toInterpolableList(value); RefPtrWillBeRawPtr<SVGRect> result = SVGRect::create(); result->setX(toInterpolableNumber(list.get(0))->value()); result->setY(toInterpolableNumber(list.get(1))->value()); result->setWidth(toInterpolableNumber(list.get(2))->value()); result->setHeight(toInterpolableNumber(list.get(3))->value()); return result; }
void LengthInterpolationFunctions::subtractFromOneHundredPercent( InterpolationValue& result) { InterpolableList& list = toInterpolableList(*result.interpolableValue); for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { double value = -toInterpolableNumber(*list.get(i)).value(); if (i == CSSPrimitiveValue::UnitTypePercentage) value += 100; toInterpolableNumber(*list.getMutable(i)).set(value); } result.nonInterpolableValue = CSSLengthNonInterpolableValue::create(true); }
static PassRefPtr<ShadowList> createShadowList(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, const StyleResolverState& state) { const InterpolableList& interpolableList = toInterpolableList(interpolableValue); size_t length = interpolableList.length(); if (length == 0) return nullptr; const NonInterpolableList& nonInterpolableList = toNonInterpolableList(*nonInterpolableValue); ShadowDataVector shadows; for (size_t i = 0; i < length; i++) shadows.append(ShadowInterpolationFunctions::createShadowData(*interpolableList.get(i), nonInterpolableList.get(i), state)); return ShadowList::adopt(shadows); }
void CSSImageListInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, InterpolationEnvironment& environment) const { const InterpolableList& interpolableList = toInterpolableList(interpolableValue); const size_t length = interpolableList.length(); ASSERT(length > 0); const NonInterpolableList& nonInterpolableList = toNonInterpolableList(*nonInterpolableValue); ASSERT(nonInterpolableList.length() == length); StyleImageList imageList(length); for (size_t i = 0; i < length; i++) imageList[i] = CSSImageInterpolationType::resolveStyleImage(cssProperty(), *interpolableList.get(i), nonInterpolableList.get(i), environment.state()); ImageListPropertyFunctions::setImageList(cssProperty(), *environment.state().style(), imageList); }