/* * Copyright (C) 2013 Google Inc. All rights reserved. * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007 Alexey Proskuryakov * Copyright (C) 2007, 2008 Eric Seidel * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (c) 2011, Code Aurora Forum. All rights reserved. * Copyright (C) Research In Motion Limited 2011. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "core/CSSPropertyNames.h" #include "core/CSSValueKeywords.h" #include "core/StyleBuilderFunctions.h" #include "core/StylePropertyShorthand.h" #include "core/css/BasicShapeFunctions.h" #include "core/css/CSSAspectRatioValue.h" #include "core/css/CSSCursorImageValue.h" #include "core/css/CSSFontValue.h" #include "core/css/CSSGradientValue.h" #include "core/css/CSSHelper.h" #include "core/css/CSSImageSetValue.h" #include "core/css/CSSLineBoxContainValue.h" #include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSPrimitiveValueMappings.h" #include "core/css/CSSPropertyMetadata.h" #include "core/css/Pair.h" #include "core/css/StylePropertySet.h" #include "core/css/StyleRule.h" #include "core/css/resolver/ElementStyleResources.h" #include "core/css/resolver/FilterOperationResolver.h" #include "core/css/resolver/FontBuilder.h" #include "core/css/resolver/StyleBuilder.h" #include "core/css/resolver/TransformBuilder.h" #include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" #include "core/rendering/style/QuotesData.h" #include "core/rendering/style/RenderStyle.h" #include "core/rendering/style/RenderStyleConstants.h" #include "core/rendering/style/StyleGeneratedImage.h" #include "platform/fonts/FontDescription.h" #include "wtf/MathExtras.h" #include "wtf/StdLibExtras.h" #include "wtf/Vector.h" namespace blink { void StyleBuilder::applyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value) { ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id); bool isInherit = state.parentNode() && value->isInheritedValue(); bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue()); ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle()) CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0; if (primitiveValue && primitiveValue->getValueID() == CSSValueCurrentcolor) state.style()->setHasCurrentColor(); if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSPropertyMetadata::isInheritedProperty(id)) state.parentStyle()->setHasExplicitlyInheritedProperties(); StyleBuilder::applyProperty(id, state, value, isInitial, isInherit); } void StyleBuilderFunctions::applyInitialCSSPropertyColor(StyleResolverState& state) { Color color = RenderStyle::initialColor(); state.style()->setColor(color); } void StyleBuilderFunctions::applyInheritCSSPropertyColor(StyleResolverState& state) { Color color = state.parentStyle()->color(); state.style()->setColor(color); } void StyleBuilderFunctions::applyValueCSSPropertyColor(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); // As per the spec, 'color: currentColor' is treated as 'color: inherit' if (primitiveValue->getValueID() == CSSValueCurrentcolor) { applyInheritCSSPropertyColor(state); return; } state.style()->setColor(StyleBuilderConverter::convertColor(state, value)); } void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state) { state.style()->clearCursorList(); state.style()->setCursor(RenderStyle::initialCursor()); } void StyleBuilderFunctions::applyInheritCSSPropertyCursor(StyleResolverState& state) { state.style()->setCursor(state.parentStyle()->cursor()); state.style()->setCursorList(state.parentStyle()->cursors()); } void StyleBuilderFunctions::applyValueCSSPropertyCursor(StyleResolverState& state, CSSValue* value) { state.style()->clearCursorList(); if (value->isValueList()) { CSSValueList* list = toCSSValueList(value); int len = list->length(); state.style()->setCursor(CURSOR_AUTO); for (int i = 0; i < len; i++) { CSSValue* item = list->item(i); if (item->isCursorImageValue()) { CSSCursorImageValue* image = toCSSCursorImageValue(item); state.style()->addCursor(state.styleImage(CSSPropertyCursor, image), image->hotSpot()); } else { state.style()->setCursor(*toCSSPrimitiveValue(item)); } } } else { state.style()->setCursor(*toCSSPrimitiveValue(value)); } } void StyleBuilderFunctions::applyValueCSSPropertyDirection(StyleResolverState& state, CSSValue* value) { state.style()->setDirection(*toCSSPrimitiveValue(value)); Element* element = state.element(); if (element && element == element->document().documentElement()) element->document().setDirectionSetOnDocumentElement(true); } void StyleBuilderFunctions::applyInitialCSSPropertyFontFamily(StyleResolverState& state) { state.fontBuilder().setFontFamilyInitial(); } void StyleBuilderFunctions::applyInheritCSSPropertyFontFamily(StyleResolverState& state) { state.fontBuilder().setFontFamilyInherit(state.parentFontDescription()); } void StyleBuilderFunctions::applyValueCSSPropertyFontFamily(StyleResolverState& state, CSSValue* value) { state.fontBuilder().setFontFamilyValue(value); } void StyleBuilderFunctions::applyInitialCSSPropertyFontSize(StyleResolverState& state) { state.fontBuilder().setFontSizeInitial(); } void StyleBuilderFunctions::applyInheritCSSPropertyFontSize(StyleResolverState& state) { state.fontBuilder().setFontSizeInherit(state.parentFontDescription()); } void StyleBuilderFunctions::applyValueCSSPropertyFontSize(StyleResolverState& state, CSSValue* value) { state.fontBuilder().setFontSizeValue(value, state.parentStyle(), state.rootElementStyle()); } 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(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); } void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(StyleResolverState& state, CSSValue* value) { state.style()->setListStyleImage(state.styleImage(CSSPropertyListStyleImage, value)); } void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(StyleResolverState& state) { state.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto()); state.style()->setOutlineStyle(RenderStyle::initialBorderStyle()); } void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(StyleResolverState& state) { state.style()->setOutlineStyleIsAuto(state.parentStyle()->outlineStyleIsAuto()); state.style()->setOutlineStyle(state.parentStyle()->outlineStyle()); } void StyleBuilderFunctions::applyValueCSSPropertyOutlineStyle(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); state.style()->setOutlineStyleIsAuto(*primitiveValue); state.style()->setOutlineStyle(*primitiveValue); } static Length mmLength(double mm) { return Length(mm * cssPixelsPerMillimeter, Fixed); } static Length inchLength(double inch) { return Length(inch * cssPixelsPerInch, Fixed); } static bool getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height) { DEFINE_STATIC_LOCAL(Length, a5Width, (mmLength(148))); DEFINE_STATIC_LOCAL(Length, a5Height, (mmLength(210))); DEFINE_STATIC_LOCAL(Length, a4Width, (mmLength(210))); DEFINE_STATIC_LOCAL(Length, a4Height, (mmLength(297))); DEFINE_STATIC_LOCAL(Length, a3Width, (mmLength(297))); DEFINE_STATIC_LOCAL(Length, a3Height, (mmLength(420))); DEFINE_STATIC_LOCAL(Length, b5Width, (mmLength(176))); DEFINE_STATIC_LOCAL(Length, b5Height, (mmLength(250))); DEFINE_STATIC_LOCAL(Length, b4Width, (mmLength(250))); DEFINE_STATIC_LOCAL(Length, b4Height, (mmLength(353))); DEFINE_STATIC_LOCAL(Length, letterWidth, (inchLength(8.5))); DEFINE_STATIC_LOCAL(Length, letterHeight, (inchLength(11))); DEFINE_STATIC_LOCAL(Length, legalWidth, (inchLength(8.5))); DEFINE_STATIC_LOCAL(Length, legalHeight, (inchLength(14))); DEFINE_STATIC_LOCAL(Length, ledgerWidth, (inchLength(11))); DEFINE_STATIC_LOCAL(Length, ledgerHeight, (inchLength(17))); if (!pageSizeName) return false; switch (pageSizeName->getValueID()) { case CSSValueA5: width = a5Width; height = a5Height; break; case CSSValueA4: width = a4Width; height = a4Height; break; case CSSValueA3: width = a3Width; height = a3Height; break; case CSSValueB5: width = b5Width; height = b5Height; break; case CSSValueB4: width = b4Width; height = b4Height; break; case CSSValueLetter: width = letterWidth; height = letterHeight; break; case CSSValueLegal: width = legalWidth; height = legalHeight; break; case CSSValueLedger: width = ledgerWidth; height = ledgerHeight; break; default: return false; } if (pageOrientation) { switch (pageOrientation->getValueID()) { case CSSValueLandscape: std::swap(width, height); break; case CSSValuePortrait: // Nothing to do. break; default: return false; } } return true; } void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) { } void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) { } void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state, CSSValue* value) { state.style()->resetPageSizeType(); Length width; Length height; PageSizeType pageSizeType = PAGE_SIZE_AUTO; CSSValueListInspector inspector(value); switch (inspector.length()) { case 2: { // {2} | if (!inspector.first()->isPrimitiveValue() || !inspector.second()->isPrimitiveValue()) return; CSSPrimitiveValue* first = toCSSPrimitiveValue(inspector.first()); CSSPrimitiveValue* second = toCSSPrimitiveValue(inspector.second()); if (first->isLength()) { // {2} if (!second->isLength()) return; width = first->computeLength(state.cssToLengthConversionData()); height = second->computeLength(state.cssToLengthConversionData()); } else { // // The value order is guaranteed. See BisonCSSParser::parseSizeParameter. if (!getPageSizeFromName(first, second, width, height)) return; } pageSizeType = PAGE_SIZE_RESOLVED; break; } case 1: { // | auto | | [ portrait | landscape] if (!inspector.first()->isPrimitiveValue()) return; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inspector.first()); if (primitiveValue->isLength()) { // pageSizeType = PAGE_SIZE_RESOLVED; width = height = primitiveValue->computeLength(state.cssToLengthConversionData()); } else { switch (primitiveValue->getValueID()) { case 0: return; case CSSValueAuto: pageSizeType = PAGE_SIZE_AUTO; break; case CSSValuePortrait: pageSizeType = PAGE_SIZE_AUTO_PORTRAIT; break; case CSSValueLandscape: pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE; break; default: // pageSizeType = PAGE_SIZE_RESOLVED; if (!getPageSizeFromName(primitiveValue, 0, width, height)) return; } } break; } default: return; } state.style()->setPageSizeType(pageSizeType); state.style()->setPageSize(LengthSize(width, height)); } void StyleBuilderFunctions::applyValueCSSPropertyTextAlign(StyleResolverState& state, CSSValue* value) { if (!value->isPrimitiveValue()) return; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); // FIXME : Per http://www.w3.org/TR/css3-text/#text-align0 can now take but this is not implemented in the // rendering code. if (primitiveValue->isString()) return; if (primitiveValue->isValueID() && primitiveValue->getValueID() != CSSValueWebkitMatchParent) state.style()->setTextAlign(*primitiveValue); else if (state.parentStyle()->textAlign() == TASTART) state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? LEFT : RIGHT); else if (state.parentStyle()->textAlign() == TAEND) state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? RIGHT : LEFT); else state.style()->setTextAlign(state.parentStyle()->textAlign()); } void StyleBuilderFunctions::applyInheritCSSPropertyTextIndent(StyleResolverState& state) { state.style()->setTextIndent(state.parentStyle()->textIndent()); state.style()->setTextIndentLine(state.parentStyle()->textIndentLine()); state.style()->setTextIndentType(state.parentStyle()->textIndentType()); } void StyleBuilderFunctions::applyInitialCSSPropertyTextIndent(StyleResolverState& state) { state.style()->setTextIndent(RenderStyle::initialTextIndent()); state.style()->setTextIndentLine(RenderStyle::initialTextIndentLine()); state.style()->setTextIndentType(RenderStyle::initialTextIndentType()); } void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(StyleResolverState& state, CSSValue* value) { if (!value->isValueList()) return; Length lengthOrPercentageValue; TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine(); TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType(); for (CSSValueListIterator i(value); i.hasMore(); i.advance()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value()); if (!primitiveValue->getValueID()) lengthOrPercentageValue = primitiveValue->convertToLength(state.cssToLengthConversionData()); else if (primitiveValue->getValueID() == CSSValueEachLine) textIndentLineValue = TextIndentEachLine; else if (primitiveValue->getValueID() == CSSValueHanging) textIndentTypeValue = TextIndentHanging; else ASSERT_NOT_REACHED(); } state.style()->setTextIndent(lengthOrPercentageValue); state.style()->setTextIndentLine(textIndentLineValue); state.style()->setTextIndentType(textIndentTypeValue); } void StyleBuilderFunctions::applyValueCSSPropertyTransform(StyleResolverState& state, CSSValue* value) { TransformOperations operations; TransformBuilder::createTransformOperations(value, state.cssToLengthConversionData(), operations); state.style()->setTransform(operations); } void StyleBuilderFunctions::applyInitialCSSPropertyTransformOrigin(StyleResolverState& state) { applyInitialCSSPropertyWebkitTransformOriginX(state); applyInitialCSSPropertyWebkitTransformOriginY(state); applyInitialCSSPropertyWebkitTransformOriginZ(state); } void StyleBuilderFunctions::applyInheritCSSPropertyTransformOrigin(StyleResolverState& state) { applyInheritCSSPropertyWebkitTransformOriginX(state); applyInheritCSSPropertyWebkitTransformOriginY(state); applyInheritCSSPropertyWebkitTransformOriginZ(state); } void StyleBuilderFunctions::applyValueCSSPropertyTransformOrigin(StyleResolverState& state, CSSValue* value) { CSSValueList* list = toCSSValueList(value); ASSERT(list->length() == 3); CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0)); if (primitiveValue->isValueID()) { switch (primitiveValue->getValueID()) { case CSSValueLeft: state.style()->setTransformOriginX(Length(0, Percent)); break; case CSSValueRight: state.style()->setTransformOriginX(Length(100, Percent)); break; case CSSValueCenter: state.style()->setTransformOriginX(Length(50, Percent)); break; default: ASSERT_NOT_REACHED(); } } else { state.style()->setTransformOriginX(StyleBuilderConverter::convertLength(state, primitiveValue)); } primitiveValue = toCSSPrimitiveValue(list->item(1)); if (primitiveValue->isValueID()) { switch (primitiveValue->getValueID()) { case CSSValueTop: state.style()->setTransformOriginY(Length(0, Percent)); break; case CSSValueBottom: state.style()->setTransformOriginY(Length(100, Percent)); break; case CSSValueCenter: state.style()->setTransformOriginY(Length(50, Percent)); break; default: ASSERT_NOT_REACHED(); } } else { state.style()->setTransformOriginY(StyleBuilderConverter::convertLength(state, primitiveValue)); } primitiveValue = toCSSPrimitiveValue(list->item(2)); state.style()->setTransformOriginZ(StyleBuilderConverter::convertComputedLength(state, primitiveValue)); } void StyleBuilderFunctions::applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState& state) { applyInitialCSSPropertyWebkitPerspectiveOriginX(state); applyInitialCSSPropertyWebkitPerspectiveOriginY(state); } void StyleBuilderFunctions::applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState& state) { applyInheritCSSPropertyWebkitPerspectiveOriginX(state); applyInheritCSSPropertyWebkitPerspectiveOriginY(state); } void StyleBuilderFunctions::applyValueCSSPropertyPerspectiveOrigin(StyleResolverState& state, CSSValue* value) { CSSValueList* list = toCSSValueList(value); ASSERT(list->length() == 2); CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0)); if (primitiveValue->isValueID()) { switch (primitiveValue->getValueID()) { case CSSValueLeft: state.style()->setPerspectiveOriginX(Length(0, Percent)); break; case CSSValueRight: state.style()->setPerspectiveOriginX(Length(100, Percent)); break; case CSSValueCenter: state.style()->setPerspectiveOriginX(Length(50, Percent)); break; default: ASSERT_NOT_REACHED(); } } else { state.style()->setPerspectiveOriginX(StyleBuilderConverter::convertLength(state, primitiveValue)); } primitiveValue = toCSSPrimitiveValue(list->item(1)); if (primitiveValue->isValueID()) { switch (primitiveValue->getValueID()) { case CSSValueTop: state.style()->setPerspectiveOriginY(Length(0, Percent)); break; case CSSValueBottom: state.style()->setPerspectiveOriginY(Length(100, Percent)); break; case CSSValueCenter: state.style()->setPerspectiveOriginY(Length(50, Percent)); break; default: ASSERT_NOT_REACHED(); } } else { state.style()->setPerspectiveOriginY(StyleBuilderConverter::convertLength(state, primitiveValue)); } } void StyleBuilderFunctions::applyInheritCSSPropertyVerticalAlign(StyleResolverState& state) { EVerticalAlign verticalAlign = state.parentStyle()->verticalAlign(); state.style()->setVerticalAlign(verticalAlign); if (verticalAlign == LENGTH) state.style()->setVerticalAlignLength(state.parentStyle()->verticalAlignLength()); } void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverState& state, CSSValue* value) { if (!value->isPrimitiveValue()) return; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID()) { state.style()->setVerticalAlign(*primitiveValue); return; } state.style()->setVerticalAlignLength(primitiveValue->convertToLength(state.cssToLengthConversionData())); } void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAspectRatio(StyleResolverState& state) { state.style()->setHasAspectRatio(RenderStyle::initialHasAspectRatio()); state.style()->setAspectRatioDenominator(RenderStyle::initialAspectRatioDenominator()); state.style()->setAspectRatioNumerator(RenderStyle::initialAspectRatioNumerator()); } void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAspectRatio(StyleResolverState& state) { if (!state.parentStyle()->hasAspectRatio()) return; state.style()->setHasAspectRatio(true); state.style()->setAspectRatioDenominator(state.parentStyle()->aspectRatioDenominator()); state.style()->setAspectRatioNumerator(state.parentStyle()->aspectRatioNumerator()); } void StyleBuilderFunctions::applyValueCSSPropertyWebkitAspectRatio(StyleResolverState& state, CSSValue* value) { if (!value->isAspectRatioValue()) { state.style()->setHasAspectRatio(false); return; } CSSAspectRatioValue* aspectRatioValue = toCSSAspectRatioValue(value); state.style()->setHasAspectRatio(true); state.style()->setAspectRatioDenominator(aspectRatioValue->denominatorValue()); state.style()->setAspectRatioNumerator(aspectRatioValue->numeratorValue()); } void StyleBuilderFunctions::applyValueCSSPropertyWebkitBorderImage(StyleResolverState& state, CSSValue* value) { NinePieceImage image; state.styleMap().mapNinePieceImage(state.style(), CSSPropertyWebkitBorderImage, value, image); state.style()->setBorderImage(image); } void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverState& state, CSSValue* value) { if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueNone) { state.style()->setClipPath(nullptr); } else if (primitiveValue->isShape()) { state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, primitiveValue->getShapeValue()))); } } } void StyleBuilderFunctions::applyValueCSSPropertyWebkitFilter(StyleResolverState& state, CSSValue* value) { FilterOperations operations; if (FilterOperationResolver::createFilterOperations(value, state.cssToLengthConversionData(), operations, state)) state.style()->setFilter(operations); } // FIXME: We should use the same system for this as the rest of the pseudo-shorthands (e.g. background-position) void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspectiveOrigin(StyleResolverState& state) { applyInitialCSSPropertyWebkitPerspectiveOriginX(state); applyInitialCSSPropertyWebkitPerspectiveOriginY(state); } void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspectiveOrigin(StyleResolverState& state) { applyInheritCSSPropertyWebkitPerspectiveOriginX(state); applyInheritCSSPropertyWebkitPerspectiveOriginY(state); } void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspectiveOrigin(StyleResolverState&, CSSValue* value) { // This is expanded in the parser ASSERT_NOT_REACHED(); } void StyleBuilderFunctions::applyInitialCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state) { state.style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill()); state.style()->setTextEmphasisMark(RenderStyle::initialTextEmphasisMark()); state.style()->setTextEmphasisCustomMark(RenderStyle::initialTextEmphasisCustomMark()); } void StyleBuilderFunctions::applyInheritCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state) { state.style()->setTextEmphasisFill(state.parentStyle()->textEmphasisFill()); state.style()->setTextEmphasisMark(state.parentStyle()->textEmphasisMark()); state.style()->setTextEmphasisCustomMark(state.parentStyle()->textEmphasisCustomMark()); } void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state, CSSValue* value) { if (value->isValueList()) { CSSValueList* list = toCSSValueList(value); ASSERT(list->length() == 2); if (list->length() != 2) return; for (unsigned i = 0; i < 2; ++i) { CSSValue* item = list->item(i); if (!item->isPrimitiveValue()) continue; CSSPrimitiveValue* value = toCSSPrimitiveValue(item); if (value->getValueID() == CSSValueFilled || value->getValueID() == CSSValueOpen) state.style()->setTextEmphasisFill(*value); else state.style()->setTextEmphasisMark(*value); } state.style()->setTextEmphasisCustomMark(nullAtom); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->isString()) { state.style()->setTextEmphasisFill(TextEmphasisFillFilled); state.style()->setTextEmphasisMark(TextEmphasisMarkCustom); state.style()->setTextEmphasisCustomMark(AtomicString(primitiveValue->getStringValue())); return; } state.style()->setTextEmphasisCustomMark(nullAtom); if (primitiveValue->getValueID() == CSSValueFilled || primitiveValue->getValueID() == CSSValueOpen) { state.style()->setTextEmphasisFill(*primitiveValue); state.style()->setTextEmphasisMark(TextEmphasisMarkAuto); } else { state.style()->setTextEmphasisFill(TextEmphasisFillFilled); state.style()->setTextEmphasisMark(*primitiveValue); } } void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState& state) { state.style()->setWillChangeContents(false); state.style()->setWillChangeScrollPosition(false); state.style()->setWillChangeProperties(Vector()); state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents()); } void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state) { state.style()->setWillChangeContents(state.parentStyle()->willChangeContents()); state.style()->setWillChangeScrollPosition(state.parentStyle()->willChangeScrollPosition()); state.style()->setWillChangeProperties(state.parentStyle()->willChangeProperties()); state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents()); } void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value) { ASSERT(value->isValueList()); bool willChangeContents = false; bool willChangeScrollPosition = false; Vector willChangeProperties; for (CSSValueListIterator i(value); i.hasMore(); i.advance()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value()); if (CSSPropertyID propertyID = primitiveValue->getPropertyID()) willChangeProperties.append(propertyID); else if (primitiveValue->getValueID() == CSSValueContents) willChangeContents = true; else if (primitiveValue->getValueID() == CSSValueScrollPosition) willChangeScrollPosition = true; else ASSERT_NOT_REACHED(); } state.style()->setWillChangeContents(willChangeContents); state.style()->setWillChangeScrollPosition(willChangeScrollPosition); state.style()->setWillChangeProperties(willChangeProperties); state.style()->setSubtreeWillChangeContents(willChangeContents || state.parentStyle()->subtreeWillChangeContents()); } void StyleBuilderFunctions::applyInitialCSSPropertyFont(StyleResolverState&) { ASSERT_NOT_REACHED(); } void StyleBuilderFunctions::applyInheritCSSPropertyFont(StyleResolverState&) { ASSERT_NOT_REACHED(); } void StyleBuilderFunctions::applyValueCSSPropertyFont(StyleResolverState& state, CSSValue* value) { // Only System Font identifiers should come through this method // all other values should have been handled when the shorthand // was expanded by the parser. // FIXME: System Font identifiers should not hijack this // short-hand CSSProperty like this (crbug.com/353932) state.style()->setLineHeight(RenderStyle::initialLineHeight()); state.setLineHeightValue(0); state.fontBuilder().fromSystemFont(toCSSPrimitiveValue(value)->getValueID()); } void StyleBuilderFunctions::applyValueCSSPropertyWebkitLocale(StyleResolverState& state, CSSValue* value) { if (!value->isPrimitiveValue()) return; const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueAuto) state.style()->setLocale(nullAtom); else state.style()->setLocale(AtomicString(primitiveValue->getStringValue())); state.fontBuilder().setScript(state.style()->locale()); } void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspective(StyleResolverState& state) { applyInitialCSSPropertyPerspective(state); } void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspective(StyleResolverState& state) { applyInheritCSSPropertyPerspective(state); } 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(state.cssToLengthConversionData()); if (perspectiveValue >= 0.0f) state.style()->setPerspective(perspectiveValue); } else { applyValueCSSPropertyPerspective(state, value); } } void StyleBuilderFunctions::applyValueCSSPropertyPerspective(StyleResolverState& state, CSSValue* value) { if (!value->isPrimitiveValue()) return; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueNone) { state.style()->setPerspective(0); return; } if (!primitiveValue->isLength()) return; float perspectiveValue = primitiveValue->computeLength(state.cssToLengthConversionData()); if (perspectiveValue >= 0.0f) state.style()->setPerspective(perspectiveValue); } void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value) { if (value->isPrimitiveValue()) state.setTextOrientation(*toCSSPrimitiveValue(value)); } } // namespace blink