bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSValue& value) { // FIXME: should not require resolving styles for inherit/initial/unset. if (value.isCSSWideKeyword()) return true; if (value.isBasicShapeCircleValue()) return interpolationRequiresStyleResolve(toCSSBasicShapeCircleValue(value)); if (value.isBasicShapeEllipseValue()) return interpolationRequiresStyleResolve(toCSSBasicShapeEllipseValue(value)); if (value.isBasicShapePolygonValue()) return interpolationRequiresStyleResolve(toCSSBasicShapePolygonValue(value)); if (value.isBasicShapeInsetValue()) return interpolationRequiresStyleResolve(toCSSBasicShapeInsetValue(value)); if (value.isPrimitiveValue()) return interpolationRequiresStyleResolve(toCSSPrimitiveValue(value)); if (value.isQuadValue()) return interpolationRequiresStyleResolve(toCSSQuadValue(value)); if (value.isValueList()) return interpolationRequiresStyleResolve(toCSSValueList(value)); if (value.isValuePair()) return interpolationRequiresStyleResolve(toCSSValuePair(value)); if (value.isImageValue()) return interpolationRequiresStyleResolve(toCSSImageValue(value)); if (value.isShadowValue()) return interpolationRequiresStyleResolve(toCSSShadowValue(value)); if (value.isSVGDocumentValue()) return interpolationRequiresStyleResolve(toCSSSVGDocumentValue(value)); // FIXME: consider other custom types. return true; }
bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSValue& value) { switch (value.cssValueType()) { case CSSValue::CSS_INHERIT: return true; case CSSValue::CSS_PRIMITIVE_VALUE: return interpolationRequiresStyleResolve(toCSSPrimitiveValue(value)); case CSSValue::CSS_VALUE_LIST: return interpolationRequiresStyleResolve(toCSSValueList(value)); case CSSValue::CSS_CUSTOM: if (value.isImageValue()) return interpolationRequiresStyleResolve(toCSSImageValue(value)); if (value.isShadowValue()) return interpolationRequiresStyleResolve(toCSSShadowValue(value)); if (value.isSVGDocumentValue()) return interpolationRequiresStyleResolve(toCSSSVGDocumentValue(value)); // FIXME: consider other custom types. return true; case CSSValue::CSS_INITIAL: // FIXME: should not require resolving styles for initial. return true; default: ASSERT_NOT_REACHED(); return true; } }
void CSSValue::finalizeGarbageCollectedObject() { switch (classType()) { case BorderImageSliceClass: toCSSBorderImageSliceValue(this)->~CSSBorderImageSliceValue(); return; case CanvasClass: toCSSCanvasValue(this)->~CSSCanvasValue(); return; case CounterClass: toCSSCounterValue(this)->~CSSCounterValue(); return; case CursorImageClass: toCSSCursorImageValue(this)->~CSSCursorImageValue(); return; case FontFaceSrcClass: toCSSFontFaceSrcValue(this)->~CSSFontFaceSrcValue(); return; case FontFeatureClass: toCSSFontFeatureValue(this)->~CSSFontFeatureValue(); return; case FunctionClass: toCSSFunctionValue(this)->~CSSFunctionValue(); return; case LinearGradientClass: toCSSLinearGradientValue(this)->~CSSLinearGradientValue(); return; case RadialGradientClass: toCSSRadialGradientValue(this)->~CSSRadialGradientValue(); return; case CrossfadeClass: toCSSCrossfadeValue(this)->~CSSCrossfadeValue(); return; case ImageClass: toCSSImageValue(this)->~CSSImageValue(); return; case InheritedClass: toCSSInheritedValue(this)->~CSSInheritedValue(); return; case InitialClass: toCSSInitialValue(this)->~CSSInitialValue(); return; case UnsetClass: toCSSUnsetValue(this)->~CSSUnsetValue(); return; case GridLineNamesClass: toCSSGridLineNamesValue(this)->~CSSGridLineNamesValue(); return; case GridTemplateAreasClass: toCSSGridTemplateAreasValue(this)->~CSSGridTemplateAreasValue(); return; case PathClass: toCSSPathValue(this)->~CSSPathValue(); return; case PrimitiveClass: toCSSPrimitiveValue(this)->~CSSPrimitiveValue(); return; case QuadClass: toCSSQuadValue(this)->~CSSQuadValue(); return; case ReflectClass: toCSSReflectValue(this)->~CSSReflectValue(); return; case ShadowClass: toCSSShadowValue(this)->~CSSShadowValue(); return; case CubicBezierTimingFunctionClass: toCSSCubicBezierTimingFunctionValue(this)->~CSSCubicBezierTimingFunctionValue(); return; case StepsTimingFunctionClass: toCSSStepsTimingFunctionValue(this)->~CSSStepsTimingFunctionValue(); return; case UnicodeRangeClass: toCSSUnicodeRangeValue(this)->~CSSUnicodeRangeValue(); return; case ValueListClass: toCSSValueList(this)->~CSSValueList(); return; case ValuePairClass: toCSSValuePair(this)->~CSSValuePair(); return; case ImageSetClass: toCSSImageSetValue(this)->~CSSImageSetValue(); return; case CSSSVGDocumentClass: toCSSSVGDocumentValue(this)->~CSSSVGDocumentValue(); return; case CSSContentDistributionClass: toCSSContentDistributionValue(this)->~CSSContentDistributionValue(); return; } ASSERT_NOT_REACHED(); }
bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CSSToLengthConversionData& unadjustedConversionData, 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 = unadjustedConversionData.zoom() * state.elementStyleResources().deviceScaleFactor(); const CSSToLengthConversionData& conversionData = unadjustedConversionData.copyWithAdjustedZoom(zoomFactor); FilterOperations operations; for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { CSSValue* currValue = i.value(); if (!currValue->isFilterValue()) continue; CSSFilterValue* filterValue = toCSSFilterValue(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->isSVGDocumentValue()) continue; CSSSVGDocumentValue* svgDocumentValue = toCSSSVGDocumentValue(argument); KURL url = state.document().completeURL(svgDocumentValue->url()); RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(svgDocumentValue->url(), url.fragmentIdentifier()); if (SVGURIReference::isExternalURIReference(svgDocumentValue->url(), state.document())) { if (!svgDocumentValue->loadRequested()) state.elementStyleResources().addPendingSVGDocument(operation.get(), svgDocumentValue); else if (svgDocumentValue->cachedSVGDocument()) ReferenceFilterBuilder::setDocumentResourceReference(operation.get(), 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 CSSShadowValue 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 = firstValue->convertToLength<FixedConversion | PercentConversion>(conversionData); if (stdDeviation.isUndefined()) return false; operations.operations().append(BlurFilterOperation::create(stdDeviation)); break; } case CSSFilterValue::DropShadowFilterOperation: { if (filterValue->length() != 1) return false; CSSValue* cssValue = filterValue->itemWithoutBoundsCheck(0); if (!cssValue->isShadowValue()) continue; CSSShadowValue* item = toCSSShadowValue(cssValue); IntPoint location(item->x->computeLength<int>(conversionData), item->y->computeLength<int>(conversionData)); int blur = item->blur ? item->blur->computeLength<int>(conversionData) : 0; Color shadowColor; if (item->color) shadowColor = state.document().textLinkColors().colorFromPrimitiveValue(item->color.get(), state.style()->color()); operations.operations().append(DropShadowFilterOperation::create(location, blur, shadowColor.isValid() ? shadowColor : Color::transparent)); break; } case CSSFilterValue::UnknownFilterOperation: default: ASSERT_NOT_REACHED(); break; } } outOperations = operations; return true; }
FilterOperations FilterOperationResolver::createFilterOperations(StyleResolverState& state, const CSSValue& inValue) { FilterOperations operations; if (inValue.isPrimitiveValue()) { ASSERT(toCSSPrimitiveValue(inValue).getValueID() == CSSValueNone); return operations; } const CSSToLengthConversionData& conversionData = state.cssToLengthConversionData(); for (auto& currValue : toCSSValueList(inValue)) { const CSSFunctionValue* filterValue = toCSSFunctionValue(currValue.get()); FilterOperation::OperationType operationType = filterOperationForType(filterValue->functionType()); countFilterUse(operationType, state.document()); ASSERT(filterValue->length() <= 1); if (operationType == FilterOperation::REFERENCE) { const CSSSVGDocumentValue& svgDocumentValue = toCSSSVGDocumentValue(filterValue->item(0)); KURL url = state.document().completeURL(svgDocumentValue.url()); ReferenceFilterOperation* operation = ReferenceFilterOperation::create(svgDocumentValue.url(), AtomicString(url.fragmentIdentifier())); if (SVGURIReference::isExternalURIReference(svgDocumentValue.url(), state.document())) { if (!svgDocumentValue.loadRequested()) state.elementStyleResources().addPendingSVGDocument(operation, &svgDocumentValue); else if (svgDocumentValue.cachedSVGDocument()) ReferenceFilterBuilder::setDocumentResourceReference(operation, new DocumentResourceReference(svgDocumentValue.cachedSVGDocument())); } operations.operations().append(operation); continue; } const CSSPrimitiveValue* firstValue = filterValue->length() && filterValue->item(0).isPrimitiveValue() ? &toCSSPrimitiveValue(filterValue->item(0)) : nullptr; switch (filterValue->functionType()) { case CSSValueGrayscale: case CSSValueSepia: case CSSValueSaturate: { double amount = 1; if (filterValue->length() == 1) { amount = firstValue->getDoubleValue(); if (firstValue->isPercentage()) amount /= 100; } operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType)); break; } case CSSValueHueRotate: { double angle = 0; if (filterValue->length() == 1) angle = firstValue->computeDegrees(); operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType)); break; } case CSSValueInvert: case CSSValueBrightness: case CSSValueContrast: case CSSValueOpacity: { double amount = (filterValue->functionType() == CSSValueBrightness) ? 0 : 1; if (filterValue->length() == 1) { amount = firstValue->getDoubleValue(); if (firstValue->isPercentage()) amount /= 100; } operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType)); break; } case CSSValueBlur: { Length stdDeviation = Length(0, Fixed); if (filterValue->length() >= 1) stdDeviation = firstValue->convertToLength(conversionData); operations.operations().append(BlurFilterOperation::create(stdDeviation)); break; } case CSSValueDropShadow: { const CSSShadowValue& item = toCSSShadowValue(filterValue->item(0)); IntPoint location(item.x->computeLength<int>(conversionData), item.y->computeLength<int>(conversionData)); int blur = item.blur ? item.blur->computeLength<int>(conversionData) : 0; Color shadowColor = Color::black; if (item.color) shadowColor = state.document().textLinkColors().colorFromCSSValue(*item.color, state.style()->color()); operations.operations().append(DropShadowFilterOperation::create(location, blur, shadowColor)); break; } default: ASSERT_NOT_REACHED(); break; } } return operations; }