static BorderImageLength toBorderImageLength(CSSPrimitiveValue& value, const CSSToLengthConversionData& conversionData) { if (value.isNumber()) return value.getDoubleValue(); if (value.isPercentage()) return Length(value.getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); if (value.getValueID() != CSSValueAuto) return value.computeLength<Length>(conversionData); return Length(Auto); }
virtual void applyValue(CSSStyleSelector* selector, CSSValue* value) const { if (!value->isPrimitiveValue()) return; CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); if (noneEnabled && primitiveValue->getIdent() == CSSValueNone) if (noneUndefined) setValue(selector->style(), Length(undefinedLength, Fixed)); else setValue(selector->style(), Length()); else if (intrinsicEnabled && primitiveValue->getIdent() == CSSValueIntrinsic) setValue(selector->style(), Length(Intrinsic)); else if (minIntrinsicEnabled && primitiveValue->getIdent() == CSSValueMinIntrinsic) setValue(selector->style(), Length(MinIntrinsic)); else if (autoEnabled && primitiveValue->getIdent() == CSSValueAuto) setValue(selector->style(), Length()); else { int type = primitiveValue->primitiveType(); if (CSSPrimitiveValue::isUnitTypeLength(type)) setValue(selector->style(), Length(primitiveValue->computeLengthIntForLength(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom()), Fixed, primitiveValue->isQuirkValue())); else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) setValue(selector->style(), Length(primitiveValue->getDoubleValue(), Percent)); } }
static bool parseHSLParameters(CSSParserTokenRange& range, RGBA32& result, bool parseAlpha) { ASSERT(range.peek().functionId() == CSSValueHsl || range.peek().functionId() == CSSValueHsla); CSSParserTokenRange args = consumeFunction(range); CSSPrimitiveValue* hslValue = consumeNumber(args, ValueRangeAll); if (!hslValue) return false; double colorArray[3]; colorArray[0] = (((hslValue->getIntValue() % 360) + 360) % 360) / 360.0; for (int i = 1; i < 3; i++) { if (!consumeCommaIncludingWhitespace(args)) return false; hslValue = consumePercent(args, ValueRangeAll); if (!hslValue) return false; double doubleValue = hslValue->getDoubleValue(); colorArray[i] = clampTo<double>(doubleValue, 0.0, 100.0) / 100.0; // Needs to be value between 0 and 1.0. } double alpha = 1.0; if (parseAlpha) { if (!consumeCommaIncludingWhitespace(args)) return false; if (!consumeNumberRaw(args, alpha)) return false; alpha = clampTo<double>(alpha, 0.0, 1.0); } result = makeRGBAFromHSLA(colorArray[0], colorArray[1], colorArray[2], alpha); return args.atEnd(); }
void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value) { if (value->isInitialValue()) { layer->setYPosition(FillLayer::initialFillYPosition(layer->type())); return; } if (!is<CSSPrimitiveValue>(*value)) return; CSSPrimitiveValue* primitiveValue = downcast<CSSPrimitiveValue>(value); Pair* pair = primitiveValue->getPairValue(); if (pair) { ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionY || propertyID == CSSPropertyWebkitMaskPositionY); primitiveValue = pair->second(); } Length length; if (primitiveValue->isLength()) length = primitiveValue->computeLength<Length>(m_resolver->state().cssToLengthConversionData()); else if (primitiveValue->isPercentage()) length = Length(primitiveValue->getDoubleValue(), Percent); else if (primitiveValue->isCalculatedPercentageWithLength()) length = Length(primitiveValue->cssCalcValue()->createCalculationValue(m_resolver->state().cssToLengthConversionData())); else return; layer->setYPosition(length); if (pair) layer->setBackgroundYOrigin(*(pair->first())); }
void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value) { if (value->isInitialValue()) { layer->setYPosition(FillLayer::initialFillYPosition(layer->type())); return; } if (!value->isPrimitiveValue()) return; float zoomFactor = style()->effectiveZoom(); CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); Pair* pair = primitiveValue->getPairValue(); if (pair) { ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionY || propertyID == CSSPropertyWebkitMaskPositionY); primitiveValue = pair->second(); } Length length; if (primitiveValue->isLength()) length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor); else if (primitiveValue->isPercentage()) length = Length(primitiveValue->getDoubleValue(), Percent); else if (primitiveValue->isCalculatedPercentageWithLength()) length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor)); else if (primitiveValue->isViewportPercentageLength()) length = primitiveValue->viewportPercentageLength(); else return; layer->setYPosition(length); if (pair) layer->setBackgroundYOrigin(*(pair->first())); }
void CSSToStyleMap::mapFillYPosition(CSSPropertyID, FillLayer* layer, CSSValue* value) { if (value->isInitialValue()) { layer->setYPosition(FillLayer::initialFillYPosition(layer->type())); return; } if (!value->isPrimitiveValue()) return; float zoomFactor = style()->effectiveZoom(); CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); Length length; if (primitiveValue->isLength()) length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor); else if (primitiveValue->isPercentage()) length = Length(primitiveValue->getDoubleValue(), Percent); else if (primitiveValue->isCalculatedPercentageWithLength()) length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor)); else if (primitiveValue->isViewportPercentageLength()) length = primitiveValue->viewportPercentageLength(); else return; layer->setYPosition(length); }
static int clampRGBComponent(const CSSPrimitiveValue& value) { double result = value.getDoubleValue(); // TODO(timloh): Multiply by 2.55 and round instead of floor. if (value.isPercentage()) result *= 2.56; return clampTo<int>(result, 0, 255); }
void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspective(StyleResolverState& state, CSSValue* value) { if (!value->isPrimitiveValue()) return; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->isNumber()) { float perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.cssToLengthConversionData()); if (perspectiveValue >= 0.0f) state.style()->setPerspective(perspectiveValue); } else { applyValueCSSPropertyPerspective(state, value); } }
static PassRefPtr<CustomFilterParameter> parseCustomFilterArrayParameter(const String& name, CSSValueList* values) { RefPtr<CustomFilterArrayParameter> arrayParameter = CustomFilterArrayParameter::create(name); for (unsigned i = 0, length = values->length(); i < length; ++i) { CSSValue* value = values->itemWithoutBoundsCheck(i); if (!value->isPrimitiveValue()) return 0; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) return 0; arrayParameter->addValue(primitiveValue->getDoubleValue()); } return arrayParameter.release(); }
void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); Length lineHeight; if (primitiveValue->getValueID() == CSSValueNormal) { lineHeight = RenderStyle::initialLineHeight(); } else if (primitiveValue->isLength()) { lineHeight = primitiveValue->computeLength<Length>(state.cssToLengthConversionData()); } else if (primitiveValue->isPercentage()) { lineHeight = Length((state.style()->computedFontSize() * primitiveValue->getIntValue()) / 100.0, Fixed); } else if (primitiveValue->isNumber()) { lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent); } else if (primitiveValue->isCalculated()) { Length length = Length(primitiveValue->cssCalcValue()->toCalcValue(state.cssToLengthConversionData())); lineHeight = Length(valueForLength(length, state.style()->fontSize()), Fixed); } else { return; } state.style()->setLineHeight(lineHeight); }
PassRefPtrWillBeRawPtr<AnimatableLength> AnimatableLength::create(CSSValue* value) { ASSERT(canCreateFrom(value)); if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = WebCore::toCSSPrimitiveValue(value); const CSSCalcValue* calcValue = primitiveValue->cssCalcValue(); if (calcValue) return create(calcValue->expressionNode(), primitiveValue); CSSPrimitiveValue::LengthUnitType unitType; bool isPrimitiveLength = CSSPrimitiveValue::unitTypeToLengthUnitType(primitiveValue->primitiveType(), unitType); ASSERT_UNUSED(isPrimitiveLength, isPrimitiveLength); const double scale = CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(primitiveValue->primitiveType()); return create(primitiveValue->getDoubleValue() * scale, unitType, primitiveValue); } if (value->isCalcValue()) return create(toCSSCalcValue(value)->expressionNode()); ASSERT_NOT_REACHED(); return nullptr; }
bool TransformBuilder::createTransformOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, TransformOperations& outOperations) { if (!inValue || !inValue->isValueList()) { outOperations.clear(); return false; } float zoomFactor = style ? style->effectiveZoom() : 1; TransformOperations operations; for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { CSSValue* currValue = i.value(); if (!currValue->isCSSTransformValue()) continue; CSSTransformValue* transformValue = static_cast<CSSTransformValue*>(i.value()); if (!transformValue->length()) continue; bool haveNonPrimitiveValue = false; for (unsigned j = 0; j < transformValue->length(); ++j) { if (!transformValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) { haveNonPrimitiveValue = true; break; } } if (haveNonPrimitiveValue) continue; CSSPrimitiveValue* firstValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(0)); switch (transformValue->operationType()) { case CSSTransformValue::ScaleTransformOperation: case CSSTransformValue::ScaleXTransformOperation: case CSSTransformValue::ScaleYTransformOperation: { double sx = 1.0; double sy = 1.0; if (transformValue->operationType() == CSSTransformValue::ScaleYTransformOperation) sy = firstValue->getDoubleValue(); else { sx = firstValue->getDoubleValue(); if (transformValue->operationType() != CSSTransformValue::ScaleXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); sy = secondValue->getDoubleValue(); } else sy = sx; } } operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::ScaleZTransformOperation: case CSSTransformValue::Scale3DTransformOperation: { double sx = 1.0; double sy = 1.0; double sz = 1.0; if (transformValue->operationType() == CSSTransformValue::ScaleZTransformOperation) sz = firstValue->getDoubleValue(); else if (transformValue->operationType() == CSSTransformValue::ScaleYTransformOperation) sy = firstValue->getDoubleValue(); else { sx = firstValue->getDoubleValue(); if (transformValue->operationType() != CSSTransformValue::ScaleXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2)); sz = thirdValue->getDoubleValue(); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); sy = secondValue->getDoubleValue(); } else sy = sx; } } operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateTransformOperation: case CSSTransformValue::TranslateXTransformOperation: case CSSTransformValue::TranslateYTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); else { tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor); } } } if (tx.isUndefined() || ty.isUndefined()) return false; operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateZTransformOperation: case CSSTransformValue::Translate3DTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); Length tz = Length(0, Fixed); if (transformValue->operationType() == CSSTransformValue::TranslateZTransformOperation) tz = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); else if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); else { tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2)); tz = convertToFloatLength(thirdValue, style, rootStyle, zoomFactor); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor); } } } if (tx.isUndefined() || ty.isUndefined() || tz.isUndefined()) return false; operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::RotateTransformOperation: { double angle = firstValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::RotateXTransformOperation: case CSSTransformValue::RotateYTransformOperation: case CSSTransformValue::RotateZTransformOperation: { double x = 0; double y = 0; double z = 0; double angle = firstValue->computeDegrees(); if (transformValue->operationType() == CSSTransformValue::RotateXTransformOperation) x = 1; else if (transformValue->operationType() == CSSTransformValue::RotateYTransformOperation) y = 1; else z = 1; operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::Rotate3DTransformOperation: { if (transformValue->length() < 4) break; CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2)); CSSPrimitiveValue* fourthValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(3)); double x = firstValue->getDoubleValue(); double y = secondValue->getDoubleValue(); double z = thirdValue->getDoubleValue(); double angle = fourthValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::SkewTransformOperation: case CSSTransformValue::SkewXTransformOperation: case CSSTransformValue::SkewYTransformOperation: { double angleX = 0; double angleY = 0; double angle = firstValue->computeDegrees(); if (transformValue->operationType() == CSSTransformValue::SkewYTransformOperation) angleY = angle; else { angleX = angle; if (transformValue->operationType() == CSSTransformValue::SkewTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); angleY = secondValue->computeDegrees(); } } } operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::MatrixTransformOperation: { if (transformValue->length() < 6) break; double a = firstValue->getDoubleValue(); double b = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(); double c = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(); double d = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(); double e = zoomFactor * toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(); double f = zoomFactor * toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(); operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f)); break; } case CSSTransformValue::Matrix3DTransformOperation: { if (transformValue->length() < 16) break; TransformationMatrix matrix(toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(0))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(6))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(7))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(8))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(9))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(10))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(11))->getDoubleValue(), zoomFactor * toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(12))->getDoubleValue(), zoomFactor * toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(13))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(14))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(15))->getDoubleValue()); operations.operations().append(Matrix3DTransformOperation::create(matrix)); break; } case CSSTransformValue::PerspectiveTransformOperation: { Length p = Length(0, Fixed); if (firstValue->isLength()) p = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); else { // This is a quirk that should go away when 3d transforms are finalized. double val = firstValue->getDoubleValue(); p = val >= 0 ? Length(clampToPositiveInteger(val), Fixed) : Length(Undefined); } if (p.isUndefined()) return false; operations.operations().append(PerspectiveTransformOperation::create(p)); break; } case CSSTransformValue::UnknownTransformOperation: ASSERT_NOT_REACHED(); break; } } outOperations = operations; return true; }
static Length convertBorderImageSliceSide(const CSSPrimitiveValue& value) { if (value.isPercentage()) return Length(value.getDoubleValue(), Percent); return Length(round(value.getDoubleValue()), Fixed); }
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)) { CSSFunctionValue* filterValue = toCSSFunctionValue(currValue.get()); FilterOperation::OperationType operationType = filterOperationForType(filterValue->functionType()); countFilterUse(operationType, state.document()); ASSERT(filterValue->length() <= 1); if (operationType == FilterOperation::REFERENCE) { CSSSVGDocumentValue* svgDocumentValue = toCSSSVGDocumentValue(filterValue->item(0)); KURL url = state.document().completeURL(svgDocumentValue->url()); RawPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(svgDocumentValue->url(), AtomicString(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; } 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: { 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; }
bool TransformBuilder::createTransformOperations(CSSValue* inValue, const CSSToLengthConversionData& conversionData, TransformOperations& outOperations) { if (!inValue || !inValue->isValueList()) { outOperations.clear(); return false; } TransformOperations operations; for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { CSSValue* currValue = i.value(); if (!currValue->isTransformValue()) continue; CSSTransformValue* transformValue = toCSSTransformValue(i.value()); if (!transformValue->length()) continue; bool haveNonPrimitiveValue = false; for (unsigned j = 0; j < transformValue->length(); ++j) { if (!transformValue->item(j)->isPrimitiveValue()) { haveNonPrimitiveValue = true; break; } } if (haveNonPrimitiveValue) continue; CSSPrimitiveValue* firstValue = toCSSPrimitiveValue(transformValue->item(0)); switch (transformValue->operationType()) { case CSSTransformValue::ScaleTransformOperation: case CSSTransformValue::ScaleXTransformOperation: case CSSTransformValue::ScaleYTransformOperation: { double sx = 1.0; double sy = 1.0; if (transformValue->operationType() == CSSTransformValue::ScaleYTransformOperation) sy = firstValue->getDoubleValue(); else { sx = firstValue->getDoubleValue(); if (transformValue->operationType() != CSSTransformValue::ScaleXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); sy = secondValue->getDoubleValue(); } else sy = sx; } } operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::ScaleZTransformOperation: case CSSTransformValue::Scale3DTransformOperation: { double sx = 1.0; double sy = 1.0; double sz = 1.0; if (transformValue->operationType() == CSSTransformValue::ScaleZTransformOperation) sz = firstValue->getDoubleValue(); else if (transformValue->operationType() == CSSTransformValue::ScaleYTransformOperation) sy = firstValue->getDoubleValue(); else { sx = firstValue->getDoubleValue(); if (transformValue->operationType() != CSSTransformValue::ScaleXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->item(2)); sz = thirdValue->getDoubleValue(); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); sy = secondValue->getDoubleValue(); } else sy = sx; } } operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateTransformOperation: case CSSTransformValue::TranslateXTransformOperation: case CSSTransformValue::TranslateYTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, conversionData); else { tx = convertToFloatLength(firstValue, conversionData); if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); ty = convertToFloatLength(secondValue, conversionData); } } } operations.operations().append(TranslateTransformOperation::create(tx, ty, 0, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateZTransformOperation: case CSSTransformValue::Translate3DTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); double tz = 0; if (transformValue->operationType() == CSSTransformValue::TranslateZTransformOperation) tz = firstValue->computeLength<double>(conversionData); else if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, conversionData); else { tx = convertToFloatLength(firstValue, conversionData); if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->item(2)); tz = thirdValue->computeLength<double>(conversionData); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); ty = convertToFloatLength(secondValue, conversionData); } } } operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::RotateTransformOperation: { double angle = firstValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::RotateXTransformOperation: case CSSTransformValue::RotateYTransformOperation: case CSSTransformValue::RotateZTransformOperation: { double x = 0; double y = 0; double z = 0; double angle = firstValue->computeDegrees(); if (transformValue->operationType() == CSSTransformValue::RotateXTransformOperation) x = 1; else if (transformValue->operationType() == CSSTransformValue::RotateYTransformOperation) y = 1; else z = 1; operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::Rotate3DTransformOperation: { if (transformValue->length() < 4) break; CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->item(2)); CSSPrimitiveValue* fourthValue = toCSSPrimitiveValue(transformValue->item(3)); double x = firstValue->getDoubleValue(); double y = secondValue->getDoubleValue(); double z = thirdValue->getDoubleValue(); double angle = fourthValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::SkewTransformOperation: case CSSTransformValue::SkewXTransformOperation: case CSSTransformValue::SkewYTransformOperation: { double angleX = 0; double angleY = 0; double angle = firstValue->computeDegrees(); if (transformValue->operationType() == CSSTransformValue::SkewYTransformOperation) angleY = angle; else { angleX = angle; if (transformValue->operationType() == CSSTransformValue::SkewTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); angleY = secondValue->computeDegrees(); } } } operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::MatrixTransformOperation: { if (transformValue->length() < 6) break; double a = firstValue->getDoubleValue(); double b = toCSSPrimitiveValue(transformValue->item(1))->getDoubleValue(); double c = toCSSPrimitiveValue(transformValue->item(2))->getDoubleValue(); double d = toCSSPrimitiveValue(transformValue->item(3))->getDoubleValue(); double e = toCSSPrimitiveValue(transformValue->item(4))->getDoubleValue(); double f = toCSSPrimitiveValue(transformValue->item(5))->getDoubleValue(); operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f)); break; } case CSSTransformValue::Matrix3DTransformOperation: { if (transformValue->length() < 16) break; TransformationMatrix matrix(toCSSPrimitiveValue(transformValue->item(0))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(1))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(2))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(3))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(4))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(5))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(6))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(7))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(8))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(9))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(10))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(11))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(12))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(13))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(14))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(15))->getDoubleValue()); operations.operations().append(Matrix3DTransformOperation::create(matrix)); break; } case CSSTransformValue::PerspectiveTransformOperation: { double p; if (firstValue->isLength()) p = firstValue->computeLength<double>(conversionData); else { // This is a quirk that should go away when 3d transforms are finalized. double val = firstValue->getDoubleValue(); if (val < 0) return false; p = clampToPositiveInteger(val); } operations.operations().append(PerspectiveTransformOperation::create(p)); break; } case CSSTransformValue::UnknownTransformOperation: ASSERT_NOT_REACHED(); break; } } outOperations = operations; return true; }