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()); }
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.color()); } 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 webkitTextFraction = toInterpolableNumber(list.get(WebkitText))->value()) addPremultipliedColor(red, green, blue, alpha, webkitTextFraction, 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)); }
PassOwnPtr<InterpolableValue> CSSColorInterpolationType::createInterpolableColor(const StyleColor& color) { if (color.isCurrentColor()) return createInterpolableColorForIndex(Currentcolor); return createInterpolableColor(color.color()); }
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; }