static PassRefPtr<CustomFilterProgram> createCustomFilterProgram(CSSShaderValue* vertexShader, CSSShaderValue* fragmentShader, CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType, StyleResolverState& state) { ResourceFetcher* fetcher = state.document()->fetcher(); KURL vertexShaderURL = vertexShader ? vertexShader->completeURL(fetcher) : KURL(); KURL fragmentShaderURL = fragmentShader ? fragmentShader->completeURL(fetcher) : KURL(); RefPtr<StyleCustomFilterProgram> program = StyleCustomFilterProgram::create(vertexShaderURL, vertexShader ? styleShader(vertexShader, state) : 0, fragmentShaderURL, fragmentShader ? styleShader(fragmentShader, state) : 0, programType, mixSettings, meshType); // FIXME // FIXME: Find out what the fixme above means. return program.release(); }
void StyleBuilderFunctions::applyValueCSSPropertyResize(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); EResize r = RESIZE_NONE; if (primitiveValue->getValueID() == CSSValueAuto) { if (Settings* settings = state.document().settings()) r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE; } else { r = *primitiveValue; } state.style()->setResize(r); }
static PassRefPtr<CustomFilterProgram> createCustomFilterProgram(CSSShaderValue* vertexShader, CSSShaderValue* fragmentShader, CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType, StyleResolverState& state) { ResourceFetcher* fetcher = state.document().fetcher(); KURL vertexShaderURL = vertexShader ? vertexShader->completeURL(fetcher) : KURL(); KURL fragmentShaderURL = fragmentShader ? fragmentShader->completeURL(fetcher) : KURL(); // We re-resolve the custom filter style after the shaders are loaded. // We always create a StyleCustomFilterProgram here, and later replace it with a program from the StyleCustomFilterProgramCache, if available. StyleShader* styleVertexShader = vertexShader ? styleShader(vertexShader) : 0; StyleShader* styleFragmentShader = fragmentShader ? styleShader(fragmentShader) : 0; RefPtr<StyleCustomFilterProgram> program = StyleCustomFilterProgram::create(vertexShaderURL, styleVertexShader, fragmentShaderURL, styleFragmentShader, programType, mixSettings, meshType); state.elementStyleResources().setHasNewCustomFilterProgram(true); return program.release(); }
void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverState& state, CSSValue* value) { if (value->isBasicShapeValue()) { state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, *value))); } if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueNone) { state.style()->setClipPath(nullptr); } else if (primitiveValue->isURI()) { String cssURLValue = primitiveValue->getStringValue(); KURL url = state.document().completeURL(cssURLValue); // FIXME: It doesn't work with forward or external SVG references (see https://bugs.webkit.org/show_bug.cgi?id=90405) state.style()->setClipPath(ReferenceClipPathOperation::create(cssURLValue, AtomicString(url.fragmentIdentifier()))); } } }
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)); }
Color StyleBuilderConverter::convertColor(StyleResolverState& state, CSSValue* value, bool forVisitedLink) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); return state.document().textLinkColors().colorFromPrimitiveValue(primitiveValue, state.style()->color(), forVisitedLink); }
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; }
void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(StyleResolverState& state, CSSValue* value) { const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag); state.document().setHasAnnotatedRegions(true); }
void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value) { // list of string, uri, counter, attr, i bool didSet = false; for (auto& item : toCSSValueList(*value)) { if (item->isImageGeneratorValue()) { state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item.get())), didSet); didSet = true; } else if (item->isImageSetValue()) { state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item.get())), didSet); didSet = true; } if (item->isImageValue()) { state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item.get())), didSet); didSet = true; continue; } if (item->isCounterValue()) { CSSCounterValue* counterValue = toCSSCounterValue(item.get()); EListStyleType listStyleType = NoneListStyle; CSSValueID listStyleIdent = counterValue->listStyle(); if (listStyleIdent != CSSValueNone) listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc); OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(AtomicString(counterValue->identifier()), listStyleType, AtomicString(counterValue->separator()))); state.style()->setContent(counter.release(), didSet); didSet = true; } if (item->isFunctionValue()) { CSSFunctionValue* functionValue = toCSSFunctionValue(item.get()); ASSERT(functionValue->functionType() == CSSValueAttr); // FIXME: Can a namespace be specified for an attr(foo)? if (state.style()->styleType() == NOPSEUDO) state.style()->setUnique(); else state.parentStyle()->setUnique(); QualifiedName attr(nullAtom, AtomicString(toCSSPrimitiveValue(functionValue->item(0))->getStringValue()), nullAtom); const AtomicString& value = state.element()->getAttribute(attr); state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet); didSet = true; } if (!item->isPrimitiveValue()) continue; CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item.get()); if (contentValue->isString()) { state.style()->setContent(contentValue->getStringValue().impl(), didSet); didSet = true; } else { switch (contentValue->getValueID()) { case CSSValueOpenQuote: state.style()->setContent(OPEN_QUOTE, didSet); didSet = true; break; case CSSValueCloseQuote: state.style()->setContent(CLOSE_QUOTE, didSet); didSet = true; break; case CSSValueNoOpenQuote: state.style()->setContent(NO_OPEN_QUOTE, didSet); didSet = true; break; case CSSValueNoCloseQuote: state.style()->setContent(NO_CLOSE_QUOTE, didSet); didSet = true; break; default: // normal and none do not have any effect. { } } } } if (!didSet) state.style()->clearContent(); }