| /* |
| * 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 <ap@webkit.org> |
| * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> |
| * 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/CSSGridTemplateAreasValue.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/Counter.h" |
| #include "core/css/Pair.h" |
| #include "core/css/Rect.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/CounterContent.h" |
| #include "core/rendering/style/QuotesData.h" |
| #include "core/rendering/style/RenderStyle.h" |
| #include "core/rendering/style/RenderStyleConstants.h" |
| #include "core/rendering/style/SVGRenderStyle.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 { |
| |
| namespace { |
| |
| static inline bool isValidVisitedLinkProperty(CSSPropertyID id) |
| { |
| switch (id) { |
| case CSSPropertyBackgroundColor: |
| case CSSPropertyBorderLeftColor: |
| case CSSPropertyBorderRightColor: |
| case CSSPropertyBorderTopColor: |
| case CSSPropertyBorderBottomColor: |
| case CSSPropertyColor: |
| case CSSPropertyFill: |
| case CSSPropertyOutlineColor: |
| case CSSPropertyStroke: |
| case CSSPropertyTextDecorationColor: |
| case CSSPropertyWebkitColumnRuleColor: |
| case CSSPropertyWebkitTextEmphasisColor: |
| case CSSPropertyWebkitTextFillColor: |
| case CSSPropertyWebkitTextStrokeColor: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| } // namespace |
| |
| 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()) |
| |
| if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) { |
| // Limit the properties that can be applied to only the ones honored by :visited. |
| return; |
| } |
| |
| 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); |
| } |
| |
| static Length clipConvertToLength(StyleResolverState& state, CSSPrimitiveValue* value) |
| { |
| return value->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData()); |
| } |
| |
| void StyleBuilderFunctions::applyInitialCSSPropertyClip(StyleResolverState& state) |
| { |
| state.style()->setClip(Length(), Length(), Length(), Length()); |
| state.style()->setHasClip(false); |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyClip(StyleResolverState& state) |
| { |
| RenderStyle* parentStyle = state.parentStyle(); |
| if (!parentStyle->hasClip()) |
| return applyInitialCSSPropertyClip(state); |
| state.style()->setClip(parentStyle->clipTop(), parentStyle->clipRight(), parentStyle->clipBottom(), parentStyle->clipLeft()); |
| state.style()->setHasClip(true); |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyClip(StyleResolverState& state, CSSValue* value) |
| { |
| CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); |
| |
| if (primitiveValue->getValueID() == CSSValueAuto) { |
| state.style()->setClip(Length(), Length(), Length(), Length()); |
| state.style()->setHasClip(false); |
| return; |
| } |
| |
| Rect* rect = primitiveValue->getRectValue(); |
| Length top = clipConvertToLength(state, rect->top()); |
| Length right = clipConvertToLength(state, rect->right()); |
| Length bottom = clipConvertToLength(state, rect->bottom()); |
| Length left = clipConvertToLength(state, rect->left()); |
| state.style()->setClip(top, right, bottom, left); |
| state.style()->setHasClip(true); |
| } |
| |
| void StyleBuilderFunctions::applyInitialCSSPropertyColor(StyleResolverState& state) |
| { |
| Color color = RenderStyle::initialColor(); |
| if (state.applyPropertyToRegularStyle()) |
| state.style()->setColor(color); |
| if (state.applyPropertyToVisitedLinkStyle()) |
| state.style()->setVisitedLinkColor(color); |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyColor(StyleResolverState& state) |
| { |
| Color color = state.parentStyle()->color(); |
| if (state.applyPropertyToRegularStyle()) |
| state.style()->setColor(color); |
| if (state.applyPropertyToVisitedLinkStyle()) |
| state.style()->setVisitedLinkColor(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; |
| } |
| |
| if (state.applyPropertyToRegularStyle()) |
| state.style()->setColor(StyleBuilderConverter::convertColor(state, value)); |
| if (state.applyPropertyToVisitedLinkStyle()) |
| state.style()->setVisitedLinkColor(StyleBuilderConverter::convertColor(state, value, true)); |
| } |
| |
| void StyleBuilderFunctions::applyInitialCSSPropertyJustifyItems(StyleResolverState& state) |
| { |
| state.style()->setJustifyItems(RenderStyle::initialJustifyItems()); |
| state.style()->setJustifyItemsOverflowAlignment(RenderStyle::initialJustifyItemsOverflowAlignment()); |
| state.style()->setJustifyItemsPositionType(RenderStyle::initialJustifyItemsPositionType()); |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyJustifyItems(StyleResolverState& state) |
| { |
| state.style()->setJustifyItems(state.parentStyle()->justifyItems()); |
| state.style()->setJustifyItemsOverflowAlignment(state.parentStyle()->justifyItemsOverflowAlignment()); |
| state.style()->setJustifyItemsPositionType(state.parentStyle()->justifyItemsPositionType()); |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyJustifyItems(StyleResolverState& state, CSSValue* value) |
| { |
| |
| CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); |
| if (Pair* pairValue = primitiveValue->getPairValue()) { |
| if (pairValue->first()->getValueID() == CSSValueLegacy) { |
| state.style()->setJustifyItemsPositionType(LegacyPosition); |
| state.style()->setJustifyItems(*pairValue->second()); |
| } else { |
| state.style()->setJustifyItems(*pairValue->first()); |
| state.style()->setJustifyItemsOverflowAlignment(*pairValue->second()); |
| } |
| } else { |
| state.style()->setJustifyItems(*primitiveValue); |
| } |
| } |
| |
| 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); |
| if (image->updateIfSVGCursorIsUsed(state.element())) // Elements with SVG cursors are not allowed to share style. |
| state.style()->setUnique(); |
| 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::applyValueCSSPropertyGlyphOrientationVertical(StyleResolverState& state, CSSValue* value) |
| { |
| if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueAuto) |
| state.style()->accessSVGStyle().setGlyphOrientationVertical(GO_AUTO); |
| else |
| state.style()->accessSVGStyle().setGlyphOrientationVertical(StyleBuilderConverter::convertGlyphOrientation(state, value)); |
| } |
| |
| void StyleBuilderFunctions::applyInitialCSSPropertyGridTemplateAreas(StyleResolverState& state) |
| { |
| state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea()); |
| state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount()); |
| state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount()); |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(StyleResolverState& state) |
| { |
| state.style()->setNamedGridArea(state.parentStyle()->namedGridArea()); |
| state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount()); |
| state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount()); |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyGridTemplateAreas(StyleResolverState& state, CSSValue* value) |
| { |
| if (value->isPrimitiveValue()) { |
| // FIXME: Shouldn't we clear the grid-area values |
| ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone); |
| return; |
| } |
| |
| CSSGridTemplateAreasValue* gridTemplateAreasValue = toCSSGridTemplateAreasValue(value); |
| const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue->gridAreaMap(); |
| |
| NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines(); |
| NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines(); |
| StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns); |
| StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows); |
| state.style()->setNamedGridColumnLines(namedGridColumnLines); |
| state.style()->setNamedGridRowLines(namedGridRowLines); |
| |
| state.style()->setNamedGridArea(newNamedGridAreas); |
| state.style()->setNamedGridAreaRowCount(gridTemplateAreasValue->rowCount()); |
| state.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue->columnCount()); |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value) |
| { |
| CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); |
| Length lineHeight; |
| |
| if (primitiveValue->getValueID() == CSSValueNormal) { |
| lineHeight = RenderStyle::initialLineHeight(); |
| } else if (primitiveValue->isLength()) { |
| float multiplier = state.style()->effectiveZoom(); |
| if (LocalFrame* frame = state.document().frame()) |
| multiplier *= frame->textZoomFactor(); |
| lineHeight = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier)); |
| } 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()) { |
| double multiplier = state.style()->effectiveZoom(); |
| if (LocalFrame* frame = state.document().frame()) |
| multiplier *= frame->textZoomFactor(); |
| Length zoomedLength = Length(primitiveValue->cssCalcValue()->toCalcValue(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier))); |
| lineHeight = Length(valueForLength(zoomedLength, 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); |
| } |
| |
| 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 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: { |
| // <length>{2} | <page-size> <orientation> |
| if (!inspector.first()->isPrimitiveValue() || !inspector.second()->isPrimitiveValue()) |
| return; |
| CSSPrimitiveValue* first = toCSSPrimitiveValue(inspector.first()); |
| CSSPrimitiveValue* second = toCSSPrimitiveValue(inspector.second()); |
| if (first->isLength()) { |
| // <length>{2} |
| if (!second->isLength()) |
| return; |
| width = first->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)); |
| height = second->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)); |
| } else { |
| // <page-size> <orientation> |
| // The value order is guaranteed. See BisonCSSParser::parseSizeParameter. |
| if (!getPageSizeFromName(first, second, width, height)) |
| return; |
| } |
| pageSizeType = PAGE_SIZE_RESOLVED; |
| break; |
| } |
| case 1: { |
| // <length> | auto | <page-size> | [ portrait | landscape] |
| if (!inspector.first()->isPrimitiveValue()) |
| return; |
| CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inspector.first()); |
| if (primitiveValue->isLength()) { |
| // <length> |
| pageSizeType = PAGE_SIZE_RESOLVED; |
| width = height = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)); |
| } 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: |
| // <page-size> |
| 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 <string> 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<FixedConversion | PercentConversion>(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<float>(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<FixedConversion | PercentConversion>(state.cssToLengthConversionData())); |
| } |
| |
| static void resetEffectiveZoom(StyleResolverState& state) |
| { |
| // Reset the zoom in effect. This allows the setZoom method to accurately compute a new zoom in effect. |
| state.setEffectiveZoom(state.parentStyle() ? state.parentStyle()->effectiveZoom() : RenderStyle::initialZoom()); |
| } |
| |
| void StyleBuilderFunctions::applyInitialCSSPropertyZoom(StyleResolverState& state) |
| { |
| resetEffectiveZoom(state); |
| state.setZoom(RenderStyle::initialZoom()); |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyZoom(StyleResolverState& state) |
| { |
| resetEffectiveZoom(state); |
| state.setZoom(state.parentStyle()->zoom()); |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyZoom(StyleResolverState& state, CSSValue* value) |
| { |
| ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue()); |
| CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); |
| |
| if (primitiveValue->getValueID() == CSSValueNormal) { |
| resetEffectiveZoom(state); |
| state.setZoom(RenderStyle::initialZoom()); |
| } else if (primitiveValue->getValueID() == CSSValueReset) { |
| state.setEffectiveZoom(RenderStyle::initialZoom()); |
| state.setZoom(RenderStyle::initialZoom()); |
| } else if (primitiveValue->getValueID() == CSSValueDocument) { |
| float docZoom = state.rootElementStyle() ? state.rootElementStyle()->zoom() : RenderStyle::initialZoom(); |
| state.setEffectiveZoom(docZoom); |
| state.setZoom(docZoom); |
| } else if (primitiveValue->isPercentage()) { |
| resetEffectiveZoom(state); |
| if (float percent = primitiveValue->getFloatValue()) |
| state.setZoom(percent / 100.0f); |
| } else if (primitiveValue->isNumber()) { |
| resetEffectiveZoom(state); |
| if (float number = primitiveValue->getFloatValue()) |
| state.setZoom(number); |
| } |
| } |
| |
| 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()))); |
| } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_URI) { |
| 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()))); |
| } |
| } |
| } |
| |
| 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<CSSPropertyID>()); |
| 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<CSSPropertyID> 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::applyInitialCSSPropertyContent(StyleResolverState& state) |
| { |
| state.style()->clearContent(); |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyContent(StyleResolverState&) |
| { |
| // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This |
| // note is a reminder that eventually "inherit" needs to be supported. |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value) |
| { |
| // list of string, uri, counter, attr, i |
| |
| if (!value->isValueList()) |
| return; |
| |
| bool didSet = false; |
| for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { |
| CSSValue* item = i.value(); |
| if (item->isImageGeneratorValue()) { |
| if (item->isGradientValue()) |
| state.style()->setContent(StyleGeneratedImage::create(toCSSGradientValue(item)->gradientWithStylesResolved(state.document().textLinkColors(), state.style()->color()).get()), didSet); |
| else |
| state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item)), didSet); |
| didSet = true; |
| } else if (item->isImageSetValue()) { |
| state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet); |
| didSet = true; |
| } |
| |
| if (item->isImageValue()) { |
| state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item)), didSet); |
| didSet = true; |
| continue; |
| } |
| |
| if (!item->isPrimitiveValue()) |
| continue; |
| |
| CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item); |
| |
| if (contentValue->isString()) { |
| state.style()->setContent(contentValue->getStringValue().impl(), didSet); |
| didSet = true; |
| } else if (contentValue->isAttr()) { |
| // 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(contentValue->getStringValue()), nullAtom); |
| const AtomicString& value = state.element()->getAttribute(attr); |
| state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet); |
| didSet = true; |
| // register the fact that the attribute value affects the style |
| state.contentAttrValues().append(attr.localName()); |
| } else if (contentValue->isCounter()) { |
| Counter* counterValue = contentValue->getCounterValue(); |
| EListStyleType listStyleType = NoneListStyle; |
| CSSValueID listStyleIdent = counterValue->listStyleIdent(); |
| 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; |
| } 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(); |
| } |
| |
| 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(), state.style()->effectiveZoom()); |
| } |
| |
| 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::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&) |
| { |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&) |
| { |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(StyleResolverState& state, CSSValue* value) |
| { |
| if (!value->isPrimitiveValue()) |
| return; |
| const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); |
| if (!primitiveValue->getValueID()) |
| return; |
| state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag); |
| state.document().setHasAnnotatedRegions(true); |
| } |
| |
| 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<float>(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<float>(state.cssToLengthConversionData()); |
| if (perspectiveValue >= 0.0f) |
| state.style()->setPerspective(perspectiveValue); |
| } |
| |
| void StyleBuilderFunctions::applyInitialCSSPropertyInternalCallback(StyleResolverState& state) |
| { |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyInternalCallback(StyleResolverState& state) |
| { |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyInternalCallback(StyleResolverState& state, CSSValue* value) |
| { |
| if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueInternalPresence) |
| state.style()->addCallbackSelector(state.currentRule()->selectorList().selectorsText()); |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(StyleResolverState& state, CSSValue* value) |
| { |
| if (value->isPrimitiveValue()) |
| state.setWritingMode(*toCSSPrimitiveValue(value)); |
| |
| // FIXME: It is not ok to modify document state while applying style. |
| if (state.element() && state.element() == state.document().documentElement()) |
| state.document().setWritingModeSetOnDocumentElement(true); |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value) |
| { |
| if (value->isPrimitiveValue()) |
| state.setTextOrientation(*toCSSPrimitiveValue(value)); |
| } |
| |
| void StyleBuilderFunctions::applyInheritCSSPropertyBaselineShift(StyleResolverState& state) |
| { |
| const SVGRenderStyle& parentSvgStyle = state.parentStyle()->svgStyle(); |
| EBaselineShift baselineShift = parentSvgStyle.baselineShift(); |
| SVGRenderStyle& svgStyle = state.style()->accessSVGStyle(); |
| svgStyle.setBaselineShift(baselineShift); |
| if (baselineShift == BS_LENGTH) |
| svgStyle.setBaselineShiftValue(parentSvgStyle.baselineShiftValue()); |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyBaselineShift(StyleResolverState& state, CSSValue* value) |
| { |
| if (!value->isPrimitiveValue()) |
| return; |
| |
| SVGRenderStyle& svgStyle = state.style()->accessSVGStyle(); |
| CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); |
| if (primitiveValue->getValueID()) { |
| switch (primitiveValue->getValueID()) { |
| case CSSValueBaseline: |
| svgStyle.setBaselineShift(BS_BASELINE); |
| break; |
| case CSSValueSub: |
| svgStyle.setBaselineShift(BS_SUB); |
| break; |
| case CSSValueSuper: |
| svgStyle.setBaselineShift(BS_SUPER); |
| break; |
| default: |
| break; |
| } |
| } else { |
| svgStyle.setBaselineShift(BS_LENGTH); |
| svgStyle.setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue)); |
| } |
| } |
| |
| void StyleBuilderFunctions::applyValueCSSPropertyGridAutoFlow(StyleResolverState& state, CSSValue* value) |
| { |
| ASSERT(value->isValueList()); |
| CSSValueList* list = toCSSValueList(value); |
| |
| CSSPrimitiveValue* first = list->length() >= 1 ? toCSSPrimitiveValue(list->item(0)) : nullptr; |
| |
| if (!first) { |
| applyInitialCSSPropertyGridAutoFlow(state); |
| return; |
| } |
| |
| CSSPrimitiveValue* second = list->length() == 2 ? toCSSPrimitiveValue(list->item(1)) : nullptr; |
| |
| GridAutoFlow autoFlow = RenderStyle::initialGridAutoFlow(); |
| switch (first->getValueID()) { |
| case CSSValueRow: |
| if (second) { |
| if (second->getValueID() == CSSValueDense) |
| autoFlow = AutoFlowRowDense; |
| else |
| autoFlow = AutoFlowStackRow; |
| } else { |
| autoFlow = AutoFlowRow; |
| } |
| break; |
| case CSSValueColumn: |
| if (second) { |
| if (second->getValueID() == CSSValueDense) |
| autoFlow = AutoFlowColumnDense; |
| else |
| autoFlow = AutoFlowStackColumn; |
| } else { |
| autoFlow = AutoFlowColumn; |
| } |
| break; |
| case CSSValueDense: |
| if (second && second->getValueID() == CSSValueColumn) |
| autoFlow = AutoFlowColumnDense; |
| else |
| autoFlow = AutoFlowRowDense; |
| break; |
| case CSSValueStack: |
| if (second && second->getValueID() == CSSValueColumn) |
| autoFlow = AutoFlowStackColumn; |
| else |
| autoFlow = AutoFlowStackRow; |
| break; |
| default: |
| ASSERT_NOT_REACHED(); |
| break; |
| } |
| |
| state.style()->setGridAutoFlow(autoFlow); |
| } |
| |
| } // namespace blink |