void SVGAnimatedColorAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType* from, SVGAnimatedType* to, SVGAnimatedType* toAtEndOfDuration, SVGAnimatedType* animated) { ASSERT(m_animationElement); ASSERT(m_contextElement); StyleColor fromStyleColor = m_animationElement->animationMode() == ToAnimation ? animated->color() : from->color(); StyleColor toStyleColor = to->color(); StyleColor toAtEndOfDurationStyleColor = toAtEndOfDuration->color(); StyleColor& animatedStyleColor = animated->color(); // Apply CSS inheritance rules. m_animationElement->adjustForInheritance<StyleColor>(parseColorFromString, m_animationElement->fromPropertyValueType(), fromStyleColor, m_contextElement); m_animationElement->adjustForInheritance<StyleColor>(parseColorFromString, m_animationElement->toPropertyValueType(), toStyleColor, m_contextElement); // Apply currentColor rules. Color fallbackColor = fallbackColorForCurrentColor(m_contextElement); Color fromColor = fromStyleColor.resolve(fallbackColor); Color toColor = toStyleColor.resolve(fallbackColor); Color toAtEndOfDurationColor = toAtEndOfDurationStyleColor.resolve(fallbackColor); Color animatedColor = animatedStyleColor.resolve(fallbackColor); float animatedRed = animatedColor.red(); m_animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.red(), toColor.red(), toAtEndOfDurationColor.red(), animatedRed); float animatedGreen = animatedColor.green(); m_animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.green(), toColor.green(), toAtEndOfDurationColor.green(), animatedGreen); float animatedBlue = animatedColor.blue(); m_animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.blue(), toColor.blue(), toAtEndOfDurationColor.blue(), animatedBlue); float animatedAlpha = animatedColor.alpha(); m_animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.alpha(), toColor.alpha(), toAtEndOfDurationColor.alpha(), animatedAlpha); animatedStyleColor = StyleColor(makeRGBA(roundf(animatedRed), roundf(animatedGreen), roundf(animatedBlue), roundf(animatedAlpha))); }
void SVGColorProperty::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtr<NewSVGPropertyBase> fromValue, PassRefPtr<NewSVGPropertyBase> toValue, PassRefPtr<NewSVGPropertyBase> toAtEndOfDurationValue, SVGElement* contextElement) { StyleColor fromStyleColor = toSVGColorProperty(fromValue)->m_styleColor; StyleColor toStyleColor = toSVGColorProperty(toValue)->m_styleColor; StyleColor toAtEndOfDurationStyleColor = toSVGColorProperty(toAtEndOfDurationValue)->m_styleColor; // Apply currentColor rules. ASSERT(contextElement); Color fallbackColor = fallbackColorForCurrentColor(contextElement); Color fromColor = fromStyleColor.resolve(fallbackColor); Color toColor = toStyleColor.resolve(fallbackColor); Color toAtEndOfDurationColor = toAtEndOfDurationStyleColor.resolve(fallbackColor); Color animatedColor = m_styleColor.resolve(fallbackColor); ASSERT(animationElement); float animatedRed = animatedColor.red(); animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.red(), toColor.red(), toAtEndOfDurationColor.red(), animatedRed); float animatedGreen = animatedColor.green(); animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.green(), toColor.green(), toAtEndOfDurationColor.green(), animatedGreen); float animatedBlue = animatedColor.blue(); animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.blue(), toColor.blue(), toAtEndOfDurationColor.blue(), animatedBlue); float animatedAlpha = animatedColor.alpha(); animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.alpha(), toColor.alpha(), toAtEndOfDurationColor.alpha(), animatedAlpha); m_styleColor = StyleColor(makeRGBA(roundf(animatedRed), roundf(animatedGreen), roundf(animatedBlue), roundf(animatedAlpha))); }
Color CSSColorInterpolationType::resolveInterpolableColor(const InterpolableValue& interpolableColor, const StyleResolverState& state, bool isVisited, bool isTextDecoration) { const InterpolableList& list = toInterpolableList(interpolableColor); ASSERT(list.length() == InterpolableColorIndexCount); double red = toInterpolableNumber(list.get(Red))->value(); double green = toInterpolableNumber(list.get(Green))->value(); double blue = toInterpolableNumber(list.get(Blue))->value(); double alpha = toInterpolableNumber(list.get(Alpha))->value(); if (double currentcolorFraction = toInterpolableNumber(list.get(Currentcolor))->value()) { auto currentColorGetter = isVisited ? ColorPropertyFunctions::getVisitedColor : ColorPropertyFunctions::getUnvisitedColor; StyleColor currentStyleColor = StyleColor::currentColor(); if (isTextDecoration) currentStyleColor = currentColorGetter(CSSPropertyWebkitTextFillColor, *state.style()); if (currentStyleColor.isCurrentColor()) currentStyleColor = currentColorGetter(CSSPropertyColor, *state.style()); addPremultipliedColor(red, green, blue, alpha, currentcolorFraction, currentStyleColor.getColor()); } const TextLinkColors& colors = state.document().textLinkColors(); if (double webkitActivelinkFraction = toInterpolableNumber(list.get(WebkitActivelink))->value()) addPremultipliedColor(red, green, blue, alpha, webkitActivelinkFraction, colors.activeLinkColor()); if (double webkitLinkFraction = toInterpolableNumber(list.get(WebkitLink))->value()) addPremultipliedColor(red, green, blue, alpha, webkitLinkFraction, isVisited ? colors.visitedLinkColor() : colors.linkColor()); if (double quirkInheritFraction = toInterpolableNumber(list.get(QuirkInherit))->value()) addPremultipliedColor(red, green, blue, alpha, quirkInheritFraction, colors.textColor()); alpha = clampTo<double>(alpha, 0, 255); if (alpha == 0) return Color::transparent; return makeRGBA( round(red / alpha), round(green / alpha), round(blue / alpha), round(alpha)); }
float SVGAnimatedColorAnimator::calculateDistance(const String& fromString, const String& toString) { // FIXME: currentColor should be resolved ASSERT(m_contextElement); StyleColor from = SVGColor::colorFromRGBColorString(fromString); if (from.isCurrentColor()) return -1; StyleColor to = SVGColor::colorFromRGBColorString(toString); if (to.isCurrentColor()) return -1; return ColorDistance::distance(from.color(), to.color()); }
std::unique_ptr<InterpolableValue> CSSColorInterpolationType::createInterpolableColor(const StyleColor& color) { if (color.isCurrentColor()) return createInterpolableColorForIndex(Currentcolor); return createInterpolableColor(color.getColor()); }
bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const RenderStyle* style, const RenderStyle* rootStyle, FilterOperations& outOperations, StyleResolverState& state) { ASSERT(outOperations.isEmpty()); if (!inValue) return false; if (inValue->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inValue); if (primitiveValue->getValueID() == CSSValueNone) return true; } if (!inValue->isValueList()) return false; float zoomFactor = (style ? style->effectiveZoom() : 1) * state.elementStyleResources().deviceScaleFactor(); FilterOperations operations; for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { CSSValue* currValue = i.value(); if (!currValue->isCSSFilterValue()) continue; CSSFilterValue* filterValue = static_cast<CSSFilterValue*>(i.value()); FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType()); if (operationType == FilterOperation::VALIDATED_CUSTOM) { // ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle. ASSERT_NOT_REACHED(); continue; } if (operationType == FilterOperation::CUSTOM) { RefPtr<CustomFilterOperation> operation = createCustomFilterOperation(filterValue, state); if (!operation) return false; operations.operations().append(operation); continue; } if (operationType == FilterOperation::REFERENCE) { if (filterValue->length() != 1) continue; CSSValue* argument = filterValue->itemWithoutBoundsCheck(0); if (!argument->isCSSSVGDocumentValue()) continue; CSSSVGDocumentValue* svgDocumentValue = static_cast<CSSSVGDocumentValue*>(argument); KURL url = state.document()->completeURL(svgDocumentValue->url()); RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(svgDocumentValue->url(), url.fragmentIdentifier(), operationType); if (SVGURIReference::isExternalURIReference(svgDocumentValue->url(), state.document())) { if (!svgDocumentValue->loadRequested()) state.elementStyleResources().addPendingSVGDocument(operation.get(), svgDocumentValue); else if (svgDocumentValue->cachedSVGDocument()) operation->setDocumentResourceReference(adoptPtr(new DocumentResourceReference(svgDocumentValue->cachedSVGDocument()))); } operations.operations().append(operation); continue; } // Check that all parameters are primitive values, with the // exception of drop shadow which has a ShadowValue parameter. if (operationType != FilterOperation::DROP_SHADOW) { bool haveNonPrimitiveValue = false; for (unsigned j = 0; j < filterValue->length(); ++j) { if (!filterValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) { haveNonPrimitiveValue = true; break; } } if (haveNonPrimitiveValue) continue; } CSSPrimitiveValue* firstValue = filterValue->length() && filterValue->itemWithoutBoundsCheck(0)->isPrimitiveValue() ? toCSSPrimitiveValue(filterValue->itemWithoutBoundsCheck(0)) : 0; switch (filterValue->operationType()) { case CSSFilterValue::GrayscaleFilterOperation: case CSSFilterValue::SepiaFilterOperation: case CSSFilterValue::SaturateFilterOperation: { double amount = 1; if (filterValue->length() == 1) { amount = firstValue->getDoubleValue(); if (firstValue->isPercentage()) amount /= 100; } operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType)); break; } case CSSFilterValue::HueRotateFilterOperation: { double angle = 0; if (filterValue->length() == 1) angle = firstValue->computeDegrees(); operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType)); break; } case CSSFilterValue::InvertFilterOperation: case CSSFilterValue::BrightnessFilterOperation: case CSSFilterValue::ContrastFilterOperation: case CSSFilterValue::OpacityFilterOperation: { double amount = (filterValue->operationType() == CSSFilterValue::BrightnessFilterOperation) ? 0 : 1; if (filterValue->length() == 1) { amount = firstValue->getDoubleValue(); if (firstValue->isPercentage()) amount /= 100; } operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType)); break; } case CSSFilterValue::BlurFilterOperation: { Length stdDeviation = Length(0, Fixed); if (filterValue->length() >= 1) stdDeviation = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); if (stdDeviation.isUndefined()) return false; operations.operations().append(BlurFilterOperation::create(stdDeviation, operationType)); break; } case CSSFilterValue::DropShadowFilterOperation: { if (filterValue->length() != 1) return false; CSSValue* cssValue = filterValue->itemWithoutBoundsCheck(0); if (!cssValue->isShadowValue()) continue; ShadowValue* item = static_cast<ShadowValue*>(cssValue); IntPoint location(item->x->computeLength<int>(style, rootStyle, zoomFactor), item->y->computeLength<int>(style, rootStyle, zoomFactor)); int blur = item->blur ? item->blur->computeLength<int>(style, rootStyle, zoomFactor) : 0; StyleColor shadowColor; if (item->color) shadowColor = state.document()->textLinkColors().colorFromPrimitiveValue(item->color.get()); operations.operations().append(DropShadowFilterOperation::create(location, blur, shadowColor.isValid() ? shadowColor.color() : Color::transparent, operationType)); break; } case CSSFilterValue::UnknownFilterOperation: default: ASSERT_NOT_REACHED(); break; } } outOperations = operations; return true; }