Home | History | Annotate | Download | only in resolver
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      4  *           (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      5  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com)
      6  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
      7  * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org>
      8  * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org>
      9  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
     10  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
     11  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions are
     14  * met:
     15  *
     16  *     * Redistributions of source code must retain the above copyright
     17  * notice, this list of conditions and the following disclaimer.
     18  *     * Redistributions in binary form must reproduce the above
     19  * copyright notice, this list of conditions and the following disclaimer
     20  * in the documentation and/or other materials provided with the
     21  * distribution.
     22  *     * Neither the name of Google Inc. nor the names of its
     23  * contributors may be used to endorse or promote products derived from
     24  * this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     27  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     28  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     29  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     30  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     31  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     32  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     33  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     34  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     36  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include "config.h"
     40 
     41 #include "core/CSSPropertyNames.h"
     42 #include "core/CSSValueKeywords.h"
     43 #include "core/StyleBuilderFunctions.h"
     44 #include "core/StylePropertyShorthand.h"
     45 #include "core/css/BasicShapeFunctions.h"
     46 #include "core/css/CSSAspectRatioValue.h"
     47 #include "core/css/CSSCursorImageValue.h"
     48 #include "core/css/CSSFontValue.h"
     49 #include "core/css/CSSGradientValue.h"
     50 #include "core/css/CSSGridTemplateAreasValue.h"
     51 #include "core/css/CSSHelper.h"
     52 #include "core/css/CSSImageSetValue.h"
     53 #include "core/css/CSSLineBoxContainValue.h"
     54 #include "core/css/parser/BisonCSSParser.h"
     55 #include "core/css/CSSPrimitiveValueMappings.h"
     56 #include "core/css/CSSProperty.h"
     57 #include "core/css/Counter.h"
     58 #include "core/css/Pair.h"
     59 #include "core/css/Rect.h"
     60 #include "core/css/StylePropertySet.h"
     61 #include "core/css/StyleRule.h"
     62 #include "core/css/resolver/ElementStyleResources.h"
     63 #include "core/css/resolver/FilterOperationResolver.h"
     64 #include "core/css/resolver/FontBuilder.h"
     65 #include "core/css/resolver/StyleBuilder.h"
     66 #include "core/css/resolver/TransformBuilder.h"
     67 #include "core/frame/LocalFrame.h"
     68 #include "core/frame/Settings.h"
     69 #include "core/rendering/style/CounterContent.h"
     70 #include "core/rendering/style/QuotesData.h"
     71 #include "core/rendering/style/RenderStyle.h"
     72 #include "core/rendering/style/RenderStyleConstants.h"
     73 #include "core/rendering/style/SVGRenderStyle.h"
     74 #include "core/rendering/style/StyleGeneratedImage.h"
     75 #include "platform/fonts/FontDescription.h"
     76 #include "wtf/MathExtras.h"
     77 #include "wtf/StdLibExtras.h"
     78 #include "wtf/Vector.h"
     79 
     80 namespace WebCore {
     81 
     82 namespace {
     83 
     84 static inline bool isValidVisitedLinkProperty(CSSPropertyID id)
     85 {
     86     switch (id) {
     87     case CSSPropertyBackgroundColor:
     88     case CSSPropertyBorderLeftColor:
     89     case CSSPropertyBorderRightColor:
     90     case CSSPropertyBorderTopColor:
     91     case CSSPropertyBorderBottomColor:
     92     case CSSPropertyColor:
     93     case CSSPropertyFill:
     94     case CSSPropertyOutlineColor:
     95     case CSSPropertyStroke:
     96     case CSSPropertyTextDecorationColor:
     97     case CSSPropertyWebkitColumnRuleColor:
     98     case CSSPropertyWebkitTextEmphasisColor:
     99     case CSSPropertyWebkitTextFillColor:
    100     case CSSPropertyWebkitTextStrokeColor:
    101         return true;
    102     default:
    103         return false;
    104     }
    105 }
    106 
    107 } // namespace
    108 
    109 void StyleBuilder::applyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value)
    110 {
    111     ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
    112 
    113     bool isInherit = state.parentNode() && value->isInheritedValue();
    114     bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
    115 
    116     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
    117     ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
    118 
    119     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
    120         // Limit the properties that can be applied to only the ones honored by :visited.
    121         return;
    122     }
    123 
    124     CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0;
    125     if (primitiveValue && primitiveValue->getValueID() == CSSValueCurrentcolor)
    126         state.style()->setHasCurrentColor();
    127 
    128     if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
    129         state.parentStyle()->setHasExplicitlyInheritedProperties();
    130 
    131     StyleBuilder::applyProperty(id, state, value, isInitial, isInherit);
    132 }
    133 
    134 static Length clipConvertToLength(StyleResolverState& state, CSSPrimitiveValue* value)
    135 {
    136     return value->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData());
    137 }
    138 
    139 void StyleBuilderFunctions::applyInitialCSSPropertyClip(StyleResolverState& state)
    140 {
    141     state.style()->setClip(Length(), Length(), Length(), Length());
    142     state.style()->setHasClip(false);
    143 }
    144 
    145 void StyleBuilderFunctions::applyInheritCSSPropertyClip(StyleResolverState& state)
    146 {
    147     RenderStyle* parentStyle = state.parentStyle();
    148     if (!parentStyle->hasClip())
    149         return applyInitialCSSPropertyClip(state);
    150     state.style()->setClip(parentStyle->clipTop(), parentStyle->clipRight(), parentStyle->clipBottom(), parentStyle->clipLeft());
    151     state.style()->setHasClip(true);
    152 }
    153 
    154 void StyleBuilderFunctions::applyValueCSSPropertyClip(StyleResolverState& state, CSSValue* value)
    155 {
    156     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    157 
    158     if (primitiveValue->getValueID() == CSSValueAuto) {
    159         state.style()->setClip(Length(), Length(), Length(), Length());
    160         state.style()->setHasClip(false);
    161         return;
    162     }
    163 
    164     Rect* rect = primitiveValue->getRectValue();
    165     Length top = clipConvertToLength(state, rect->top());
    166     Length right = clipConvertToLength(state, rect->right());
    167     Length bottom = clipConvertToLength(state, rect->bottom());
    168     Length left = clipConvertToLength(state, rect->left());
    169     state.style()->setClip(top, right, bottom, left);
    170     state.style()->setHasClip(true);
    171 }
    172 
    173 void StyleBuilderFunctions::applyInitialCSSPropertyColor(StyleResolverState& state)
    174 {
    175     Color color = RenderStyle::initialColor();
    176     if (state.applyPropertyToRegularStyle())
    177         state.style()->setColor(color);
    178     if (state.applyPropertyToVisitedLinkStyle())
    179         state.style()->setVisitedLinkColor(color);
    180 }
    181 
    182 void StyleBuilderFunctions::applyInheritCSSPropertyColor(StyleResolverState& state)
    183 {
    184     Color color = state.parentStyle()->color();
    185     if (state.applyPropertyToRegularStyle())
    186         state.style()->setColor(color);
    187     if (state.applyPropertyToVisitedLinkStyle())
    188         state.style()->setVisitedLinkColor(color);
    189 }
    190 
    191 void StyleBuilderFunctions::applyValueCSSPropertyColor(StyleResolverState& state, CSSValue* value)
    192 {
    193     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    194     // As per the spec, 'color: currentColor' is treated as 'color: inherit'
    195     if (primitiveValue->getValueID() == CSSValueCurrentcolor) {
    196         applyInheritCSSPropertyColor(state);
    197         return;
    198     }
    199 
    200     if (state.applyPropertyToRegularStyle())
    201         state.style()->setColor(state.document().textLinkColors().colorFromPrimitiveValue(primitiveValue, state.style()->color()));
    202     if (state.applyPropertyToVisitedLinkStyle())
    203         state.style()->setVisitedLinkColor(state.document().textLinkColors().colorFromPrimitiveValue(primitiveValue, state.style()->color(), true));
    204 }
    205 
    206 void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state)
    207 {
    208     state.style()->clearCursorList();
    209     state.style()->setCursor(RenderStyle::initialCursor());
    210 }
    211 
    212 void StyleBuilderFunctions::applyInheritCSSPropertyCursor(StyleResolverState& state)
    213 {
    214     state.style()->setCursor(state.parentStyle()->cursor());
    215     state.style()->setCursorList(state.parentStyle()->cursors());
    216 }
    217 
    218 void StyleBuilderFunctions::applyValueCSSPropertyCursor(StyleResolverState& state, CSSValue* value)
    219 {
    220     state.style()->clearCursorList();
    221     if (value->isValueList()) {
    222         CSSValueList* list = toCSSValueList(value);
    223         int len = list->length();
    224         state.style()->setCursor(CURSOR_AUTO);
    225         for (int i = 0; i < len; i++) {
    226             CSSValue* item = list->itemWithoutBoundsCheck(i);
    227             if (item->isCursorImageValue()) {
    228                 CSSCursorImageValue* image = toCSSCursorImageValue(item);
    229                 if (image->updateIfSVGCursorIsUsed(state.element())) // Elements with SVG cursors are not allowed to share style.
    230                     state.style()->setUnique();
    231                 state.style()->addCursor(state.styleImage(CSSPropertyCursor, image), image->hotSpot());
    232             } else {
    233                 state.style()->setCursor(*toCSSPrimitiveValue(item));
    234             }
    235         }
    236     } else {
    237         state.style()->setCursor(*toCSSPrimitiveValue(value));
    238     }
    239 }
    240 
    241 void StyleBuilderFunctions::applyValueCSSPropertyDirection(StyleResolverState& state, CSSValue* value)
    242 {
    243     state.style()->setDirection(*toCSSPrimitiveValue(value));
    244     Element* element = state.element();
    245     if (element && element == element->document().documentElement())
    246         element->document().setDirectionSetOnDocumentElement(true);
    247 }
    248 
    249 static inline bool isValidDisplayValue(StyleResolverState& state, EDisplay displayPropertyValue)
    250 {
    251     if (state.element() && state.element()->isSVGElement() && state.style()->styleType() == NOPSEUDO)
    252         return (displayPropertyValue == INLINE || displayPropertyValue == BLOCK || displayPropertyValue == NONE);
    253     return true;
    254 }
    255 
    256 void StyleBuilderFunctions::applyInheritCSSPropertyDisplay(StyleResolverState& state)
    257 {
    258     EDisplay display = state.parentStyle()->display();
    259     if (!isValidDisplayValue(state, display))
    260         return;
    261     state.style()->setDisplay(display);
    262 }
    263 
    264 void StyleBuilderFunctions::applyValueCSSPropertyDisplay(StyleResolverState& state, CSSValue* value)
    265 {
    266     EDisplay display = *toCSSPrimitiveValue(value);
    267     if (!isValidDisplayValue(state, display))
    268         return;
    269     state.style()->setDisplay(display);
    270 }
    271 
    272 void StyleBuilderFunctions::applyInitialCSSPropertyFontFamily(StyleResolverState& state)
    273 {
    274     state.fontBuilder().setFontFamilyInitial();
    275 }
    276 
    277 void StyleBuilderFunctions::applyInheritCSSPropertyFontFamily(StyleResolverState& state)
    278 {
    279     state.fontBuilder().setFontFamilyInherit(state.parentFontDescription());
    280 }
    281 
    282 void StyleBuilderFunctions::applyValueCSSPropertyFontFamily(StyleResolverState& state, CSSValue* value)
    283 {
    284     state.fontBuilder().setFontFamilyValue(value);
    285 }
    286 
    287 void StyleBuilderFunctions::applyInitialCSSPropertyFontSize(StyleResolverState& state)
    288 {
    289     state.fontBuilder().setFontSizeInitial();
    290 }
    291 
    292 void StyleBuilderFunctions::applyInheritCSSPropertyFontSize(StyleResolverState& state)
    293 {
    294     state.fontBuilder().setFontSizeInherit(state.parentFontDescription());
    295 }
    296 
    297 void StyleBuilderFunctions::applyValueCSSPropertyFontSize(StyleResolverState& state, CSSValue* value)
    298 {
    299     state.fontBuilder().setFontSizeValue(value, state.parentStyle(), state.rootElementStyle());
    300 }
    301 
    302 void StyleBuilderFunctions::applyInitialCSSPropertyFontWeight(StyleResolverState& state)
    303 {
    304     state.fontBuilder().setWeight(FontWeightNormal);
    305 }
    306 
    307 void StyleBuilderFunctions::applyInheritCSSPropertyFontWeight(StyleResolverState& state)
    308 {
    309     state.fontBuilder().setWeight(state.parentFontDescription().weight());
    310 }
    311 
    312 void StyleBuilderFunctions::applyValueCSSPropertyFontWeight(StyleResolverState& state, CSSValue* value)
    313 {
    314     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    315     switch (primitiveValue->getValueID()) {
    316     case CSSValueInvalid:
    317         ASSERT_NOT_REACHED();
    318         break;
    319     case CSSValueBolder:
    320         state.fontBuilder().setWeight(state.parentStyle()->fontDescription().weight());
    321         state.fontBuilder().setWeightBolder();
    322         break;
    323     case CSSValueLighter:
    324         state.fontBuilder().setWeight(state.parentStyle()->fontDescription().weight());
    325         state.fontBuilder().setWeightLighter();
    326         break;
    327     default:
    328         state.fontBuilder().setWeight(*primitiveValue);
    329     }
    330 }
    331 
    332 void StyleBuilderFunctions::applyValueCSSPropertyGlyphOrientationVertical(StyleResolverState& state, CSSValue* value)
    333 {
    334     if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueAuto)
    335         state.style()->accessSVGStyle()->setGlyphOrientationVertical(GO_AUTO);
    336     else
    337         state.style()->accessSVGStyle()->setGlyphOrientationVertical(StyleBuilderConverter::convertGlyphOrientation(state, value));
    338 }
    339 
    340 void StyleBuilderFunctions::applyInitialCSSPropertyGridTemplateAreas(StyleResolverState& state)
    341 {
    342     state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
    343     state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
    344     state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
    345 }
    346 
    347 void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(StyleResolverState& state)
    348 {
    349     state.style()->setNamedGridArea(state.parentStyle()->namedGridArea());
    350     state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount());
    351     state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount());
    352 }
    353 
    354 void StyleBuilderFunctions::applyValueCSSPropertyGridTemplateAreas(StyleResolverState& state, CSSValue* value)
    355 {
    356     if (value->isPrimitiveValue()) {
    357         // FIXME: Shouldn't we clear the grid-area values
    358         ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
    359         return;
    360     }
    361 
    362     CSSGridTemplateAreasValue* gridTemplateAreasValue = toCSSGridTemplateAreasValue(value);
    363     const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue->gridAreaMap();
    364 
    365     NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines();
    366     NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines();
    367     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns);
    368     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows);
    369     state.style()->setNamedGridColumnLines(namedGridColumnLines);
    370     state.style()->setNamedGridRowLines(namedGridRowLines);
    371 
    372     state.style()->setNamedGridArea(newNamedGridAreas);
    373     state.style()->setNamedGridAreaRowCount(gridTemplateAreasValue->rowCount());
    374     state.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue->columnCount());
    375 }
    376 
    377 void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value)
    378 {
    379     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    380     Length lineHeight;
    381 
    382     if (primitiveValue->getValueID() == CSSValueNormal) {
    383         lineHeight = RenderStyle::initialLineHeight();
    384     } else if (primitiveValue->isLength()) {
    385         float multiplier = state.style()->effectiveZoom();
    386         if (LocalFrame* frame = state.document().frame())
    387             multiplier *= frame->textZoomFactor();
    388         lineHeight = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier));
    389     } else if (primitiveValue->isPercentage()) {
    390         lineHeight = Length((state.style()->computedFontSize() * primitiveValue->getIntValue()) / 100.0, Fixed);
    391     } else if (primitiveValue->isNumber()) {
    392         lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
    393     } else if (primitiveValue->isCalculated()) {
    394         double multiplier = state.style()->effectiveZoom();
    395         if (LocalFrame* frame = state.document().frame())
    396             multiplier *= frame->textZoomFactor();
    397         Length zoomedLength = Length(primitiveValue->cssCalcValue()->toCalcValue(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier)));
    398         lineHeight = Length(valueForLength(zoomedLength, state.style()->fontSize()), Fixed);
    399     } else {
    400         return;
    401     }
    402     state.style()->setLineHeight(lineHeight);
    403 }
    404 
    405 void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(StyleResolverState& state, CSSValue* value)
    406 {
    407     state.style()->setListStyleImage(state.styleImage(CSSPropertyListStyleImage, value));
    408 }
    409 
    410 void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(StyleResolverState& state)
    411 {
    412     state.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto());
    413     state.style()->setOutlineStyle(RenderStyle::initialBorderStyle());
    414 }
    415 
    416 void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(StyleResolverState& state)
    417 {
    418     state.style()->setOutlineStyleIsAuto(state.parentStyle()->outlineStyleIsAuto());
    419     state.style()->setOutlineStyle(state.parentStyle()->outlineStyle());
    420 }
    421 
    422 void StyleBuilderFunctions::applyValueCSSPropertyOutlineStyle(StyleResolverState& state, CSSValue* value)
    423 {
    424     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    425     state.style()->setOutlineStyleIsAuto(*primitiveValue);
    426     state.style()->setOutlineStyle(*primitiveValue);
    427 }
    428 
    429 void StyleBuilderFunctions::applyValueCSSPropertyResize(StyleResolverState& state, CSSValue* value)
    430 {
    431     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    432 
    433     EResize r = RESIZE_NONE;
    434     if (primitiveValue->getValueID() == CSSValueAuto) {
    435         if (Settings* settings = state.document().settings())
    436             r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
    437     } else {
    438         r = *primitiveValue;
    439     }
    440     state.style()->setResize(r);
    441 }
    442 
    443 static Length mmLength(double mm) { return Length(mm * cssPixelsPerMillimeter, Fixed); }
    444 static Length inchLength(double inch) { return Length(inch * cssPixelsPerInch, Fixed); }
    445 static bool getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
    446 {
    447     DEFINE_STATIC_LOCAL(Length, a5Width, (mmLength(148)));
    448     DEFINE_STATIC_LOCAL(Length, a5Height, (mmLength(210)));
    449     DEFINE_STATIC_LOCAL(Length, a4Width, (mmLength(210)));
    450     DEFINE_STATIC_LOCAL(Length, a4Height, (mmLength(297)));
    451     DEFINE_STATIC_LOCAL(Length, a3Width, (mmLength(297)));
    452     DEFINE_STATIC_LOCAL(Length, a3Height, (mmLength(420)));
    453     DEFINE_STATIC_LOCAL(Length, b5Width, (mmLength(176)));
    454     DEFINE_STATIC_LOCAL(Length, b5Height, (mmLength(250)));
    455     DEFINE_STATIC_LOCAL(Length, b4Width, (mmLength(250)));
    456     DEFINE_STATIC_LOCAL(Length, b4Height, (mmLength(353)));
    457     DEFINE_STATIC_LOCAL(Length, letterWidth, (inchLength(8.5)));
    458     DEFINE_STATIC_LOCAL(Length, letterHeight, (inchLength(11)));
    459     DEFINE_STATIC_LOCAL(Length, legalWidth, (inchLength(8.5)));
    460     DEFINE_STATIC_LOCAL(Length, legalHeight, (inchLength(14)));
    461     DEFINE_STATIC_LOCAL(Length, ledgerWidth, (inchLength(11)));
    462     DEFINE_STATIC_LOCAL(Length, ledgerHeight, (inchLength(17)));
    463 
    464     if (!pageSizeName)
    465         return false;
    466 
    467     switch (pageSizeName->getValueID()) {
    468     case CSSValueA5:
    469         width = a5Width;
    470         height = a5Height;
    471         break;
    472     case CSSValueA4:
    473         width = a4Width;
    474         height = a4Height;
    475         break;
    476     case CSSValueA3:
    477         width = a3Width;
    478         height = a3Height;
    479         break;
    480     case CSSValueB5:
    481         width = b5Width;
    482         height = b5Height;
    483         break;
    484     case CSSValueB4:
    485         width = b4Width;
    486         height = b4Height;
    487         break;
    488     case CSSValueLetter:
    489         width = letterWidth;
    490         height = letterHeight;
    491         break;
    492     case CSSValueLegal:
    493         width = legalWidth;
    494         height = legalHeight;
    495         break;
    496     case CSSValueLedger:
    497         width = ledgerWidth;
    498         height = ledgerHeight;
    499         break;
    500     default:
    501         return false;
    502     }
    503 
    504     if (pageOrientation) {
    505         switch (pageOrientation->getValueID()) {
    506         case CSSValueLandscape:
    507             std::swap(width, height);
    508             break;
    509         case CSSValuePortrait:
    510             // Nothing to do.
    511             break;
    512         default:
    513             return false;
    514         }
    515     }
    516     return true;
    517 }
    518 
    519 void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) { }
    520 void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) { }
    521 void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state, CSSValue* value)
    522 {
    523     state.style()->resetPageSizeType();
    524     Length width;
    525     Length height;
    526     PageSizeType pageSizeType = PAGE_SIZE_AUTO;
    527     CSSValueListInspector inspector(value);
    528     switch (inspector.length()) {
    529     case 2: {
    530         // <length>{2} | <page-size> <orientation>
    531         if (!inspector.first()->isPrimitiveValue() || !inspector.second()->isPrimitiveValue())
    532             return;
    533         CSSPrimitiveValue* first = toCSSPrimitiveValue(inspector.first());
    534         CSSPrimitiveValue* second = toCSSPrimitiveValue(inspector.second());
    535         if (first->isLength()) {
    536             // <length>{2}
    537             if (!second->isLength())
    538                 return;
    539             width = first->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
    540             height = second->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
    541         } else {
    542             // <page-size> <orientation>
    543             // The value order is guaranteed. See BisonCSSParser::parseSizeParameter.
    544             if (!getPageSizeFromName(first, second, width, height))
    545                 return;
    546         }
    547         pageSizeType = PAGE_SIZE_RESOLVED;
    548         break;
    549     }
    550     case 1: {
    551         // <length> | auto | <page-size> | [ portrait | landscape]
    552         if (!inspector.first()->isPrimitiveValue())
    553             return;
    554         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inspector.first());
    555         if (primitiveValue->isLength()) {
    556             // <length>
    557             pageSizeType = PAGE_SIZE_RESOLVED;
    558             width = height = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
    559         } else {
    560             switch (primitiveValue->getValueID()) {
    561             case 0:
    562                 return;
    563             case CSSValueAuto:
    564                 pageSizeType = PAGE_SIZE_AUTO;
    565                 break;
    566             case CSSValuePortrait:
    567                 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
    568                 break;
    569             case CSSValueLandscape:
    570                 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
    571                 break;
    572             default:
    573                 // <page-size>
    574                 pageSizeType = PAGE_SIZE_RESOLVED;
    575                 if (!getPageSizeFromName(primitiveValue, 0, width, height))
    576                     return;
    577             }
    578         }
    579         break;
    580     }
    581     default:
    582         return;
    583     }
    584     state.style()->setPageSizeType(pageSizeType);
    585     state.style()->setPageSize(LengthSize(width, height));
    586 }
    587 
    588 void StyleBuilderFunctions::applyValueCSSPropertyTextAlign(StyleResolverState& state, CSSValue* value)
    589 {
    590     if (!value->isPrimitiveValue())
    591         return;
    592 
    593     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    594     // FIXME : Per http://www.w3.org/TR/css3-text/#text-align0 can now take <string> but this is not implemented in the
    595     // rendering code.
    596     if (primitiveValue->isString())
    597         return;
    598 
    599     if (primitiveValue->isValueID() && primitiveValue->getValueID() != CSSValueWebkitMatchParent)
    600         state.style()->setTextAlign(*primitiveValue);
    601     else if (state.parentStyle()->textAlign() == TASTART)
    602         state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? LEFT : RIGHT);
    603     else if (state.parentStyle()->textAlign() == TAEND)
    604         state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? RIGHT : LEFT);
    605     else
    606         state.style()->setTextAlign(state.parentStyle()->textAlign());
    607 }
    608 
    609 void StyleBuilderFunctions::applyValueCSSPropertyTextDecoration(StyleResolverState& state, CSSValue* value)
    610 {
    611     TextDecoration t = RenderStyle::initialTextDecoration();
    612     for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
    613         CSSValue* item = i.value();
    614         t |= *toCSSPrimitiveValue(item);
    615     }
    616     state.style()->setTextDecoration(t);
    617 }
    618 
    619 void StyleBuilderFunctions::applyInheritCSSPropertyTextIndent(StyleResolverState& state)
    620 {
    621     state.style()->setTextIndent(state.parentStyle()->textIndent());
    622     state.style()->setTextIndentLine(state.parentStyle()->textIndentLine());
    623     state.style()->setTextIndentType(state.parentStyle()->textIndentType());
    624 }
    625 
    626 void StyleBuilderFunctions::applyInitialCSSPropertyTextIndent(StyleResolverState& state)
    627 {
    628     state.style()->setTextIndent(RenderStyle::initialTextIndent());
    629     state.style()->setTextIndentLine(RenderStyle::initialTextIndentLine());
    630     state.style()->setTextIndentType(RenderStyle::initialTextIndentType());
    631 }
    632 
    633 void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(StyleResolverState& state, CSSValue* value)
    634 {
    635     if (!value->isValueList())
    636         return;
    637 
    638     Length lengthOrPercentageValue;
    639     TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine();
    640     TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType();
    641 
    642     for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
    643         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value());
    644         if (!primitiveValue->getValueID())
    645             lengthOrPercentageValue = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
    646         else if (primitiveValue->getValueID() == CSSValueEachLine)
    647             textIndentLineValue = TextIndentEachLine;
    648         else if (primitiveValue->getValueID() == CSSValueHanging)
    649             textIndentTypeValue = TextIndentHanging;
    650         else
    651             ASSERT_NOT_REACHED();
    652     }
    653 
    654     state.style()->setTextIndent(lengthOrPercentageValue);
    655     state.style()->setTextIndentLine(textIndentLineValue);
    656     state.style()->setTextIndentType(textIndentTypeValue);
    657 }
    658 
    659 void StyleBuilderFunctions::applyValueCSSPropertyTransform(StyleResolverState& state, CSSValue* value)
    660 {
    661     TransformOperations operations;
    662     TransformBuilder::createTransformOperations(value, state.cssToLengthConversionData(), operations);
    663     state.style()->setTransform(operations);
    664 }
    665 
    666 void StyleBuilderFunctions::applyInitialCSSPropertyTransformOrigin(StyleResolverState& state)
    667 {
    668     applyInitialCSSPropertyWebkitTransformOriginX(state);
    669     applyInitialCSSPropertyWebkitTransformOriginY(state);
    670     applyInitialCSSPropertyWebkitTransformOriginZ(state);
    671 }
    672 
    673 void StyleBuilderFunctions::applyInheritCSSPropertyTransformOrigin(StyleResolverState& state)
    674 {
    675     applyInheritCSSPropertyWebkitTransformOriginX(state);
    676     applyInheritCSSPropertyWebkitTransformOriginY(state);
    677     applyInheritCSSPropertyWebkitTransformOriginZ(state);
    678 }
    679 
    680 void StyleBuilderFunctions::applyValueCSSPropertyTransformOrigin(StyleResolverState& state, CSSValue* value)
    681 {
    682     CSSValueList* list = toCSSValueList(value);
    683     ASSERT(list->length() == 3);
    684     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0));
    685     if (primitiveValue->isValueID()) {
    686         switch (primitiveValue->getValueID()) {
    687         case CSSValueLeft:
    688             state.style()->setTransformOriginX(Length(0, Percent));
    689             break;
    690         case CSSValueRight:
    691             state.style()->setTransformOriginX(Length(100, Percent));
    692             break;
    693         case CSSValueCenter:
    694             state.style()->setTransformOriginX(Length(50, Percent));
    695             break;
    696         default:
    697             ASSERT_NOT_REACHED();
    698         }
    699     } else {
    700         state.style()->setTransformOriginX(StyleBuilderConverter::convertLength(state, primitiveValue));
    701     }
    702 
    703     primitiveValue = toCSSPrimitiveValue(list->item(1));
    704     if (primitiveValue->isValueID()) {
    705         switch (primitiveValue->getValueID()) {
    706         case CSSValueTop:
    707             state.style()->setTransformOriginY(Length(0, Percent));
    708             break;
    709         case CSSValueBottom:
    710             state.style()->setTransformOriginY(Length(100, Percent));
    711             break;
    712         case CSSValueCenter:
    713             state.style()->setTransformOriginY(Length(50, Percent));
    714             break;
    715         default:
    716             ASSERT_NOT_REACHED();
    717         }
    718     } else {
    719         state.style()->setTransformOriginY(StyleBuilderConverter::convertLength(state, primitiveValue));
    720     }
    721 
    722     primitiveValue = toCSSPrimitiveValue(list->item(2));
    723     state.style()->setTransformOriginZ(StyleBuilderConverter::convertComputedLength<float>(state, primitiveValue));
    724 }
    725 
    726 void StyleBuilderFunctions::applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState& state)
    727 {
    728     applyInitialCSSPropertyWebkitPerspectiveOriginX(state);
    729     applyInitialCSSPropertyWebkitPerspectiveOriginY(state);
    730 }
    731 
    732 void StyleBuilderFunctions::applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState& state)
    733 {
    734     applyInheritCSSPropertyWebkitPerspectiveOriginX(state);
    735     applyInheritCSSPropertyWebkitPerspectiveOriginY(state);
    736 }
    737 
    738 void StyleBuilderFunctions::applyValueCSSPropertyPerspectiveOrigin(StyleResolverState& state, CSSValue* value)
    739 {
    740     CSSValueList* list = toCSSValueList(value);
    741     ASSERT(list->length() == 2);
    742     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0));
    743     if (primitiveValue->isValueID()) {
    744         switch (primitiveValue->getValueID()) {
    745         case CSSValueLeft:
    746             state.style()->setPerspectiveOriginX(Length(0, Percent));
    747             break;
    748         case CSSValueRight:
    749             state.style()->setPerspectiveOriginX(Length(100, Percent));
    750             break;
    751         case CSSValueCenter:
    752             state.style()->setPerspectiveOriginX(Length(50, Percent));
    753             break;
    754         default:
    755             ASSERT_NOT_REACHED();
    756         }
    757     } else {
    758         state.style()->setPerspectiveOriginX(StyleBuilderConverter::convertLength(state, primitiveValue));
    759     }
    760 
    761     primitiveValue = toCSSPrimitiveValue(list->item(1));
    762     if (primitiveValue->isValueID()) {
    763         switch (primitiveValue->getValueID()) {
    764         case CSSValueTop:
    765             state.style()->setPerspectiveOriginY(Length(0, Percent));
    766             break;
    767         case CSSValueBottom:
    768             state.style()->setPerspectiveOriginY(Length(100, Percent));
    769             break;
    770         case CSSValueCenter:
    771             state.style()->setPerspectiveOriginY(Length(50, Percent));
    772             break;
    773         default:
    774             ASSERT_NOT_REACHED();
    775         }
    776     } else {
    777         state.style()->setPerspectiveOriginY(StyleBuilderConverter::convertLength(state, primitiveValue));
    778     }
    779 }
    780 
    781 void StyleBuilderFunctions::applyInheritCSSPropertyVerticalAlign(StyleResolverState& state)
    782 {
    783     EVerticalAlign verticalAlign = state.parentStyle()->verticalAlign();
    784     state.style()->setVerticalAlign(verticalAlign);
    785     if (verticalAlign == LENGTH)
    786         state.style()->setVerticalAlignLength(state.parentStyle()->verticalAlignLength());
    787 }
    788 
    789 void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverState& state, CSSValue* value)
    790 {
    791     if (!value->isPrimitiveValue())
    792         return;
    793 
    794     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    795 
    796     if (primitiveValue->getValueID()) {
    797         state.style()->setVerticalAlign(*primitiveValue);
    798         return;
    799     }
    800 
    801     state.style()->setVerticalAlignLength(primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()));
    802 }
    803 
    804 void StyleBuilderFunctions::applyValueCSSPropertyTouchAction(StyleResolverState& state, CSSValue* value)
    805 {
    806     TouchAction action = RenderStyle::initialTouchAction();
    807     for (CSSValueListIterator i(value); i.hasMore(); i.advance())
    808         action |= *toCSSPrimitiveValue(i.value());
    809 
    810     state.style()->setTouchAction(action);
    811 }
    812 
    813 static void resetEffectiveZoom(StyleResolverState& state)
    814 {
    815     // Reset the zoom in effect. This allows the setZoom method to accurately compute a new zoom in effect.
    816     state.setEffectiveZoom(state.parentStyle() ? state.parentStyle()->effectiveZoom() : RenderStyle::initialZoom());
    817 }
    818 
    819 void StyleBuilderFunctions::applyInitialCSSPropertyZoom(StyleResolverState& state)
    820 {
    821     resetEffectiveZoom(state);
    822     state.setZoom(RenderStyle::initialZoom());
    823 }
    824 
    825 void StyleBuilderFunctions::applyInheritCSSPropertyZoom(StyleResolverState& state)
    826 {
    827     resetEffectiveZoom(state);
    828     state.setZoom(state.parentStyle()->zoom());
    829 }
    830 
    831 void StyleBuilderFunctions::applyValueCSSPropertyZoom(StyleResolverState& state, CSSValue* value)
    832 {
    833     ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue());
    834     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    835 
    836     if (primitiveValue->getValueID() == CSSValueNormal) {
    837         resetEffectiveZoom(state);
    838         state.setZoom(RenderStyle::initialZoom());
    839     } else if (primitiveValue->getValueID() == CSSValueReset) {
    840         state.setEffectiveZoom(RenderStyle::initialZoom());
    841         state.setZoom(RenderStyle::initialZoom());
    842     } else if (primitiveValue->getValueID() == CSSValueDocument) {
    843         float docZoom = state.rootElementStyle() ? state.rootElementStyle()->zoom() : RenderStyle::initialZoom();
    844         state.setEffectiveZoom(docZoom);
    845         state.setZoom(docZoom);
    846     } else if (primitiveValue->isPercentage()) {
    847         resetEffectiveZoom(state);
    848         if (float percent = primitiveValue->getFloatValue())
    849             state.setZoom(percent / 100.0f);
    850     } else if (primitiveValue->isNumber()) {
    851         resetEffectiveZoom(state);
    852         if (float number = primitiveValue->getFloatValue())
    853             state.setZoom(number);
    854     }
    855 }
    856 
    857 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAspectRatio(StyleResolverState& state)
    858 {
    859     state.style()->setHasAspectRatio(RenderStyle::initialHasAspectRatio());
    860     state.style()->setAspectRatioDenominator(RenderStyle::initialAspectRatioDenominator());
    861     state.style()->setAspectRatioNumerator(RenderStyle::initialAspectRatioNumerator());
    862 }
    863 
    864 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAspectRatio(StyleResolverState& state)
    865 {
    866     if (!state.parentStyle()->hasAspectRatio())
    867         return;
    868     state.style()->setHasAspectRatio(true);
    869     state.style()->setAspectRatioDenominator(state.parentStyle()->aspectRatioDenominator());
    870     state.style()->setAspectRatioNumerator(state.parentStyle()->aspectRatioNumerator());
    871 }
    872 
    873 void StyleBuilderFunctions::applyValueCSSPropertyWebkitAspectRatio(StyleResolverState& state, CSSValue* value)
    874 {
    875     if (!value->isAspectRatioValue()) {
    876         state.style()->setHasAspectRatio(false);
    877         return;
    878     }
    879     CSSAspectRatioValue* aspectRatioValue = toCSSAspectRatioValue(value);
    880     state.style()->setHasAspectRatio(true);
    881     state.style()->setAspectRatioDenominator(aspectRatioValue->denominatorValue());
    882     state.style()->setAspectRatioNumerator(aspectRatioValue->numeratorValue());
    883 }
    884 
    885 void StyleBuilderFunctions::applyValueCSSPropertyWebkitBorderImage(StyleResolverState& state, CSSValue* value)
    886 {
    887     NinePieceImage image;
    888     state.styleMap().mapNinePieceImage(state.style(), CSSPropertyWebkitBorderImage, value, image);
    889     state.style()->setBorderImage(image);
    890 }
    891 
    892 void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverState& state, CSSValue* value)
    893 {
    894     if (value->isPrimitiveValue()) {
    895         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    896         if (primitiveValue->getValueID() == CSSValueNone) {
    897             state.style()->setClipPath(nullptr);
    898         } else if (primitiveValue->isShape()) {
    899             state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, primitiveValue->getShapeValue())));
    900         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_URI) {
    901             String cssURLValue = primitiveValue->getStringValue();
    902             KURL url = state.document().completeURL(cssURLValue);
    903             // FIXME: It doesn't work with forward or external SVG references (see https://bugs.webkit.org/show_bug.cgi?id=90405)
    904             state.style()->setClipPath(ReferenceClipPathOperation::create(cssURLValue, AtomicString(url.fragmentIdentifier())));
    905         }
    906     }
    907 }
    908 
    909 void StyleBuilderFunctions::applyValueCSSPropertyWebkitFilter(StyleResolverState& state, CSSValue* value)
    910 {
    911     FilterOperations operations;
    912     if (FilterOperationResolver::createFilterOperations(value, state.cssToLengthConversionData(), operations, state))
    913         state.style()->setFilter(operations);
    914 }
    915 
    916 void StyleBuilderFunctions::applyInitialCSSPropertyFontVariantLigatures(StyleResolverState& state)
    917 {
    918     state.fontBuilder().setFontVariantLigaturesInitial();
    919 }
    920 
    921 void StyleBuilderFunctions::applyInheritCSSPropertyFontVariantLigatures(StyleResolverState& state)
    922 {
    923     state.fontBuilder().setFontVariantLigaturesInherit(state.parentFontDescription());
    924 }
    925 
    926 void StyleBuilderFunctions::applyValueCSSPropertyFontVariantLigatures(StyleResolverState& state, CSSValue* value)
    927 {
    928     state.fontBuilder().setFontVariantLigaturesValue(value);
    929 }
    930 
    931 void StyleBuilderFunctions::applyValueCSSPropertyInternalMarqueeIncrement(StyleResolverState& state, CSSValue* value)
    932 {
    933     if (!value->isPrimitiveValue())
    934         return;
    935 
    936     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    937     if (primitiveValue->getValueID()) {
    938         switch (primitiveValue->getValueID()) {
    939         case CSSValueSmall:
    940             state.style()->setMarqueeIncrement(Length(1, Fixed)); // 1px.
    941             break;
    942         case CSSValueNormal:
    943             state.style()->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
    944             break;
    945         case CSSValueLarge:
    946             state.style()->setMarqueeIncrement(Length(36, Fixed)); // 36px.
    947             break;
    948         default:
    949             break;
    950         }
    951     } else {
    952         Length marqueeLength = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
    953         state.style()->setMarqueeIncrement(marqueeLength);
    954     }
    955 }
    956 
    957 void StyleBuilderFunctions::applyValueCSSPropertyInternalMarqueeSpeed(StyleResolverState& state, CSSValue* value)
    958 {
    959     if (!value->isPrimitiveValue())
    960         return;
    961 
    962     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
    963     if (CSSValueID valueID = primitiveValue->getValueID()) {
    964         switch (valueID) {
    965         case CSSValueSlow:
    966             state.style()->setMarqueeSpeed(500); // 500 msec.
    967             break;
    968         case CSSValueNormal:
    969             state.style()->setMarqueeSpeed(85); // 85msec. The WinIE default.
    970             break;
    971         case CSSValueFast:
    972             state.style()->setMarqueeSpeed(10); // 10msec. Super fast.
    973             break;
    974         default:
    975             break;
    976         }
    977     } else if (primitiveValue->isTime()) {
    978         state.style()->setMarqueeSpeed(primitiveValue->computeTime<int, CSSPrimitiveValue::Milliseconds>());
    979     } else if (primitiveValue->isNumber()) { // For scrollamount support.
    980         state.style()->setMarqueeSpeed(primitiveValue->getIntValue());
    981     }
    982 }
    983 
    984 // FIXME: We should use the same system for this as the rest of the pseudo-shorthands (e.g. background-position)
    985 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspectiveOrigin(StyleResolverState& state)
    986 {
    987     applyInitialCSSPropertyWebkitPerspectiveOriginX(state);
    988     applyInitialCSSPropertyWebkitPerspectiveOriginY(state);
    989 }
    990 
    991 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspectiveOrigin(StyleResolverState& state)
    992 {
    993     applyInheritCSSPropertyWebkitPerspectiveOriginX(state);
    994     applyInheritCSSPropertyWebkitPerspectiveOriginY(state);
    995 }
    996 
    997 void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspectiveOrigin(StyleResolverState&, CSSValue* value)
    998 {
    999     // This is expanded in the parser
   1000     ASSERT_NOT_REACHED();
   1001 }
   1002 
   1003 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTapHighlightColor(StyleResolverState& state, CSSValue* value)
   1004 {
   1005     if (!value->isPrimitiveValue())
   1006         return;
   1007     Color color = state.document().textLinkColors().colorFromPrimitiveValue(toCSSPrimitiveValue(value), state.style()->color());
   1008     state.style()->setTapHighlightColor(color);
   1009 }
   1010 
   1011 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state)
   1012 {
   1013     state.style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill());
   1014     state.style()->setTextEmphasisMark(RenderStyle::initialTextEmphasisMark());
   1015     state.style()->setTextEmphasisCustomMark(RenderStyle::initialTextEmphasisCustomMark());
   1016 }
   1017 
   1018 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state)
   1019 {
   1020     state.style()->setTextEmphasisFill(state.parentStyle()->textEmphasisFill());
   1021     state.style()->setTextEmphasisMark(state.parentStyle()->textEmphasisMark());
   1022     state.style()->setTextEmphasisCustomMark(state.parentStyle()->textEmphasisCustomMark());
   1023 }
   1024 
   1025 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state, CSSValue* value)
   1026 {
   1027     if (value->isValueList()) {
   1028         CSSValueList* list = toCSSValueList(value);
   1029         ASSERT(list->length() == 2);
   1030         if (list->length() != 2)
   1031             return;
   1032         for (unsigned i = 0; i < 2; ++i) {
   1033             CSSValue* item = list->itemWithoutBoundsCheck(i);
   1034             if (!item->isPrimitiveValue())
   1035                 continue;
   1036 
   1037             CSSPrimitiveValue* value = toCSSPrimitiveValue(item);
   1038             if (value->getValueID() == CSSValueFilled || value->getValueID() == CSSValueOpen)
   1039                 state.style()->setTextEmphasisFill(*value);
   1040             else
   1041                 state.style()->setTextEmphasisMark(*value);
   1042         }
   1043         state.style()->setTextEmphasisCustomMark(nullAtom);
   1044         return;
   1045     }
   1046 
   1047     if (!value->isPrimitiveValue())
   1048         return;
   1049     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
   1050 
   1051     if (primitiveValue->isString()) {
   1052         state.style()->setTextEmphasisFill(TextEmphasisFillFilled);
   1053         state.style()->setTextEmphasisMark(TextEmphasisMarkCustom);
   1054         state.style()->setTextEmphasisCustomMark(AtomicString(primitiveValue->getStringValue()));
   1055         return;
   1056     }
   1057 
   1058     state.style()->setTextEmphasisCustomMark(nullAtom);
   1059 
   1060     if (primitiveValue->getValueID() == CSSValueFilled || primitiveValue->getValueID() == CSSValueOpen) {
   1061         state.style()->setTextEmphasisFill(*primitiveValue);
   1062         state.style()->setTextEmphasisMark(TextEmphasisMarkAuto);
   1063     } else {
   1064         state.style()->setTextEmphasisFill(TextEmphasisFillFilled);
   1065         state.style()->setTextEmphasisMark(*primitiveValue);
   1066     }
   1067 }
   1068 
   1069 void StyleBuilderFunctions::applyValueCSSPropertyTextUnderlinePosition(StyleResolverState& state, CSSValue* value)
   1070 {
   1071     // This is true if value is 'auto' or 'alphabetic'.
   1072     if (value->isPrimitiveValue()) {
   1073         TextUnderlinePosition t = *toCSSPrimitiveValue(value);
   1074         state.style()->setTextUnderlinePosition(t);
   1075         return;
   1076     }
   1077 
   1078     unsigned t = 0;
   1079     for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
   1080         CSSValue* item = i.value();
   1081         TextUnderlinePosition t2 = *toCSSPrimitiveValue(item);
   1082         t |= t2;
   1083     }
   1084     state.style()->setTextUnderlinePosition(static_cast<TextUnderlinePosition>(t));
   1085 }
   1086 
   1087 void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState& state)
   1088 {
   1089     state.style()->setWillChangeContents(false);
   1090     state.style()->setWillChangeScrollPosition(false);
   1091     state.style()->setWillChangeProperties(Vector<CSSPropertyID>());
   1092     state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
   1093 }
   1094 
   1095 void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state)
   1096 {
   1097     state.style()->setWillChangeContents(state.parentStyle()->willChangeContents());
   1098     state.style()->setWillChangeScrollPosition(state.parentStyle()->willChangeScrollPosition());
   1099     state.style()->setWillChangeProperties(state.parentStyle()->willChangeProperties());
   1100     state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
   1101 }
   1102 
   1103 void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value)
   1104 {
   1105     ASSERT(value->isValueList());
   1106     bool willChangeContents = false;
   1107     bool willChangeScrollPosition = false;
   1108     Vector<CSSPropertyID> willChangeProperties;
   1109 
   1110     for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
   1111         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value());
   1112         if (CSSPropertyID propertyID = primitiveValue->getPropertyID())
   1113             willChangeProperties.append(propertyID);
   1114         else if (primitiveValue->getValueID() == CSSValueContents)
   1115             willChangeContents = true;
   1116         else if (primitiveValue->getValueID() == CSSValueScrollPosition)
   1117             willChangeScrollPosition = true;
   1118         else
   1119             ASSERT_NOT_REACHED();
   1120     }
   1121     state.style()->setWillChangeContents(willChangeContents);
   1122     state.style()->setWillChangeScrollPosition(willChangeScrollPosition);
   1123     state.style()->setWillChangeProperties(willChangeProperties);
   1124     state.style()->setSubtreeWillChangeContents(willChangeContents || state.parentStyle()->subtreeWillChangeContents());
   1125 }
   1126 
   1127 void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state)
   1128 {
   1129     state.style()->clearContent();
   1130 }
   1131 
   1132 void StyleBuilderFunctions::applyInheritCSSPropertyContent(StyleResolverState&)
   1133 {
   1134     // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
   1135     // note is a reminder that eventually "inherit" needs to be supported.
   1136 }
   1137 
   1138 void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value)
   1139 {
   1140     // list of string, uri, counter, attr, i
   1141 
   1142     if (!value->isValueList())
   1143         return;
   1144 
   1145     bool didSet = false;
   1146     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
   1147         CSSValue* item = i.value();
   1148         if (item->isImageGeneratorValue()) {
   1149             if (item->isGradientValue())
   1150                 state.style()->setContent(StyleGeneratedImage::create(toCSSGradientValue(item)->gradientWithStylesResolved(state.document().textLinkColors(), state.style()->color()).get()), didSet);
   1151             else
   1152                 state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item)), didSet);
   1153             didSet = true;
   1154         } else if (item->isImageSetValue()) {
   1155             state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet);
   1156             didSet = true;
   1157         }
   1158 
   1159         if (item->isImageValue()) {
   1160             state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item)), didSet);
   1161             didSet = true;
   1162             continue;
   1163         }
   1164 
   1165         if (!item->isPrimitiveValue())
   1166             continue;
   1167 
   1168         CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item);
   1169 
   1170         if (contentValue->isString()) {
   1171             state.style()->setContent(contentValue->getStringValue().impl(), didSet);
   1172             didSet = true;
   1173         } else if (contentValue->isAttr()) {
   1174             // FIXME: Can a namespace be specified for an attr(foo)?
   1175             if (state.style()->styleType() == NOPSEUDO)
   1176                 state.style()->setUnique();
   1177             else
   1178                 state.parentStyle()->setUnique();
   1179             QualifiedName attr(nullAtom, AtomicString(contentValue->getStringValue()), nullAtom);
   1180             const AtomicString& value = state.element()->getAttribute(attr);
   1181             state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet);
   1182             didSet = true;
   1183             // register the fact that the attribute value affects the style
   1184             state.contentAttrValues().append(attr.localName());
   1185         } else if (contentValue->isCounter()) {
   1186             Counter* counterValue = contentValue->getCounterValue();
   1187             EListStyleType listStyleType = NoneListStyle;
   1188             CSSValueID listStyleIdent = counterValue->listStyleIdent();
   1189             if (listStyleIdent != CSSValueNone)
   1190                 listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
   1191             OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(AtomicString(counterValue->identifier()), listStyleType, AtomicString(counterValue->separator())));
   1192             state.style()->setContent(counter.release(), didSet);
   1193             didSet = true;
   1194         } else {
   1195             switch (contentValue->getValueID()) {
   1196             case CSSValueOpenQuote:
   1197                 state.style()->setContent(OPEN_QUOTE, didSet);
   1198                 didSet = true;
   1199                 break;
   1200             case CSSValueCloseQuote:
   1201                 state.style()->setContent(CLOSE_QUOTE, didSet);
   1202                 didSet = true;
   1203                 break;
   1204             case CSSValueNoOpenQuote:
   1205                 state.style()->setContent(NO_OPEN_QUOTE, didSet);
   1206                 didSet = true;
   1207                 break;
   1208             case CSSValueNoCloseQuote:
   1209                 state.style()->setContent(NO_CLOSE_QUOTE, didSet);
   1210                 didSet = true;
   1211                 break;
   1212             default:
   1213                 // normal and none do not have any effect.
   1214                 { }
   1215             }
   1216         }
   1217     }
   1218     if (!didSet)
   1219         state.style()->clearContent();
   1220 }
   1221 
   1222 void StyleBuilderFunctions::applyInitialCSSPropertyFont(StyleResolverState&)
   1223 {
   1224     ASSERT_NOT_REACHED();
   1225 }
   1226 
   1227 void StyleBuilderFunctions::applyInheritCSSPropertyFont(StyleResolverState&)
   1228 {
   1229     ASSERT_NOT_REACHED();
   1230 }
   1231 
   1232 void StyleBuilderFunctions::applyValueCSSPropertyFont(StyleResolverState& state, CSSValue* value)
   1233 {
   1234     // Only System Font identifiers should come through this method
   1235     // all other values should have been handled when the shorthand
   1236     // was expanded by the parser.
   1237     // FIXME: System Font identifiers should not hijack this
   1238     // short-hand CSSProperty like this (crbug.com/353932)
   1239     state.style()->setLineHeight(RenderStyle::initialLineHeight());
   1240     state.setLineHeightValue(0);
   1241     state.fontBuilder().fromSystemFont(toCSSPrimitiveValue(value)->getValueID(), state.style()->effectiveZoom());
   1242 }
   1243 
   1244 void StyleBuilderFunctions::applyValueCSSPropertyWebkitLocale(StyleResolverState& state, CSSValue* value)
   1245 {
   1246     if (!value->isPrimitiveValue())
   1247         return;
   1248     const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
   1249     if (primitiveValue->getValueID() == CSSValueAuto)
   1250         state.style()->setLocale(nullAtom);
   1251     else
   1252         state.style()->setLocale(AtomicString(primitiveValue->getStringValue()));
   1253     state.fontBuilder().setScript(state.style()->locale());
   1254 }
   1255 
   1256 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&)
   1257 {
   1258 }
   1259 
   1260 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&)
   1261 {
   1262 }
   1263 
   1264 void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(StyleResolverState& state, CSSValue* value)
   1265 {
   1266     if (!value->isPrimitiveValue())
   1267         return;
   1268     const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
   1269     if (!primitiveValue->getValueID())
   1270         return;
   1271     state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
   1272     state.document().setHasAnnotatedRegions(true);
   1273 }
   1274 
   1275 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspective(StyleResolverState& state)
   1276 {
   1277     applyInitialCSSPropertyPerspective(state);
   1278 }
   1279 
   1280 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspective(StyleResolverState& state)
   1281 {
   1282     applyInheritCSSPropertyPerspective(state);
   1283 }
   1284 
   1285 void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspective(StyleResolverState& state, CSSValue* value)
   1286 {
   1287     if (!value->isPrimitiveValue())
   1288         return;
   1289     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
   1290     if (primitiveValue->isNumber()) {
   1291         float perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.cssToLengthConversionData());
   1292         if (perspectiveValue >= 0.0f)
   1293             state.style()->setPerspective(perspectiveValue);
   1294     } else {
   1295         applyValueCSSPropertyPerspective(state, value);
   1296     }
   1297 }
   1298 
   1299 void StyleBuilderFunctions::applyValueCSSPropertyPerspective(StyleResolverState& state, CSSValue* value)
   1300 {
   1301     if (!value->isPrimitiveValue())
   1302         return;
   1303     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
   1304     if (primitiveValue->getValueID() == CSSValueNone) {
   1305         state.style()->setPerspective(0);
   1306         return;
   1307     }
   1308 
   1309     if (!primitiveValue->isLength())
   1310         return;
   1311     float perspectiveValue = primitiveValue->computeLength<float>(state.cssToLengthConversionData());
   1312     if (perspectiveValue >= 0.0f)
   1313         state.style()->setPerspective(perspectiveValue);
   1314 }
   1315 
   1316 void StyleBuilderFunctions::applyInitialCSSPropertyInternalCallback(StyleResolverState& state)
   1317 {
   1318 }
   1319 
   1320 void StyleBuilderFunctions::applyInheritCSSPropertyInternalCallback(StyleResolverState& state)
   1321 {
   1322 }
   1323 
   1324 void StyleBuilderFunctions::applyValueCSSPropertyInternalCallback(StyleResolverState& state, CSSValue* value)
   1325 {
   1326     if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueInternalPresence)
   1327         state.style()->addCallbackSelector(state.currentRule()->selectorList().selectorsText());
   1328 }
   1329 
   1330 void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(StyleResolverState& state, CSSValue* value)
   1331 {
   1332     if (value->isPrimitiveValue())
   1333         state.setWritingMode(*toCSSPrimitiveValue(value));
   1334 
   1335     // FIXME: It is not ok to modify document state while applying style.
   1336     if (state.element() && state.element() == state.document().documentElement())
   1337         state.document().setWritingModeSetOnDocumentElement(true);
   1338 }
   1339 
   1340 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value)
   1341 {
   1342     if (value->isPrimitiveValue())
   1343         state.setTextOrientation(*toCSSPrimitiveValue(value));
   1344 }
   1345 
   1346 // FIXME: We should handle initial and inherit for font-feature-settings
   1347 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitFontFeatureSettings(StyleResolverState& state)
   1348 {
   1349 }
   1350 
   1351 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitFontFeatureSettings(StyleResolverState& state)
   1352 {
   1353 }
   1354 
   1355 void StyleBuilderFunctions::applyValueCSSPropertyWebkitFontFeatureSettings(StyleResolverState& state, CSSValue* value)
   1356 {
   1357     if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueNormal) {
   1358         state.fontBuilder().setFeatureSettingsNormal();
   1359         return;
   1360     }
   1361 
   1362     if (value->isValueList())
   1363         state.fontBuilder().setFeatureSettingsValue(value);
   1364 }
   1365 
   1366 
   1367 void StyleBuilderFunctions::applyValueCSSPropertyBaselineShift(StyleResolverState& state, CSSValue* value)
   1368 {
   1369     if (!value->isPrimitiveValue())
   1370         return;
   1371 
   1372     SVGRenderStyle* svgStyle = state.style()->accessSVGStyle();
   1373     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
   1374     if (primitiveValue->getValueID()) {
   1375         switch (primitiveValue->getValueID()) {
   1376         case CSSValueBaseline:
   1377             svgStyle->setBaselineShift(BS_BASELINE);
   1378             break;
   1379         case CSSValueSub:
   1380             svgStyle->setBaselineShift(BS_SUB);
   1381             break;
   1382         case CSSValueSuper:
   1383             svgStyle->setBaselineShift(BS_SUPER);
   1384             break;
   1385         default:
   1386             break;
   1387         }
   1388     } else {
   1389         svgStyle->setBaselineShift(BS_LENGTH);
   1390         svgStyle->setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue));
   1391     }
   1392 }
   1393 
   1394 } // namespace WebCore
   1395