Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / resolver / StyleBuilderCustom.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
4  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
5  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@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@webkit.org>
8  * Copyright (C) 2007, 2008 Eric Seidel <eric@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/CSSPrimitiveValueMappings.h"
55 #include "core/css/CSSPropertyMetadata.h"
56 #include "core/css/Counter.h"
57 #include "core/css/Pair.h"
58 #include "core/css/StylePropertySet.h"
59 #include "core/css/StyleRule.h"
60 #include "core/css/resolver/ElementStyleResources.h"
61 #include "core/css/resolver/FilterOperationResolver.h"
62 #include "core/css/resolver/FontBuilder.h"
63 #include "core/css/resolver/StyleBuilder.h"
64 #include "core/css/resolver/TransformBuilder.h"
65 #include "core/frame/LocalFrame.h"
66 #include "core/frame/Settings.h"
67 #include "core/rendering/style/CounterContent.h"
68 #include "core/rendering/style/QuotesData.h"
69 #include "core/rendering/style/RenderStyle.h"
70 #include "core/rendering/style/RenderStyleConstants.h"
71 #include "core/rendering/style/SVGRenderStyle.h"
72 #include "core/rendering/style/StyleGeneratedImage.h"
73 #include "platform/fonts/FontDescription.h"
74 #include "wtf/MathExtras.h"
75 #include "wtf/StdLibExtras.h"
76 #include "wtf/Vector.h"
77
78 namespace blink {
79
80 namespace {
81
82 static inline bool isValidVisitedLinkProperty(CSSPropertyID id)
83 {
84     switch (id) {
85     case CSSPropertyBackgroundColor:
86     case CSSPropertyBorderLeftColor:
87     case CSSPropertyBorderRightColor:
88     case CSSPropertyBorderTopColor:
89     case CSSPropertyBorderBottomColor:
90     case CSSPropertyColor:
91     case CSSPropertyFill:
92     case CSSPropertyOutlineColor:
93     case CSSPropertyStroke:
94     case CSSPropertyTextDecorationColor:
95     case CSSPropertyWebkitColumnRuleColor:
96     case CSSPropertyWebkitTextEmphasisColor:
97     case CSSPropertyWebkitTextFillColor:
98     case CSSPropertyWebkitTextStrokeColor:
99         return true;
100     default:
101         return false;
102     }
103 }
104
105 } // namespace
106
107 void StyleBuilder::applyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value)
108 {
109     ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
110
111     bool isInherit = state.parentNode() && value->isInheritedValue();
112     bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
113
114     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
115     ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
116
117     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
118         // Limit the properties that can be applied to only the ones honored by :visited.
119         return;
120     }
121
122     if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSPropertyMetadata::isInheritedProperty(id))
123         state.parentStyle()->setHasExplicitlyInheritedProperties();
124
125     StyleBuilder::applyProperty(id, state, value, isInitial, isInherit);
126 }
127
128 void StyleBuilderFunctions::applyInitialCSSPropertyColor(StyleResolverState& state)
129 {
130     Color color = RenderStyle::initialColor();
131     if (state.applyPropertyToRegularStyle())
132         state.style()->setColor(color);
133     if (state.applyPropertyToVisitedLinkStyle())
134         state.style()->setVisitedLinkColor(color);
135 }
136
137 void StyleBuilderFunctions::applyInheritCSSPropertyColor(StyleResolverState& state)
138 {
139     Color color = state.parentStyle()->color();
140     if (state.applyPropertyToRegularStyle())
141         state.style()->setColor(color);
142     if (state.applyPropertyToVisitedLinkStyle())
143         state.style()->setVisitedLinkColor(color);
144 }
145
146 void StyleBuilderFunctions::applyValueCSSPropertyColor(StyleResolverState& state, CSSValue* value)
147 {
148     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
149     // As per the spec, 'color: currentColor' is treated as 'color: inherit'
150     if (primitiveValue->getValueID() == CSSValueCurrentcolor) {
151         applyInheritCSSPropertyColor(state);
152         return;
153     }
154
155     if (state.applyPropertyToRegularStyle())
156         state.style()->setColor(StyleBuilderConverter::convertColor(state, value));
157     if (state.applyPropertyToVisitedLinkStyle())
158         state.style()->setVisitedLinkColor(StyleBuilderConverter::convertColor(state, value, true));
159 }
160
161 void StyleBuilderFunctions::applyInitialCSSPropertyJustifyItems(StyleResolverState& state)
162 {
163     state.style()->setJustifyItems(RenderStyle::initialJustifyItems());
164     state.style()->setJustifyItemsOverflowAlignment(RenderStyle::initialJustifyItemsOverflowAlignment());
165     state.style()->setJustifyItemsPositionType(RenderStyle::initialJustifyItemsPositionType());
166 }
167
168 void StyleBuilderFunctions::applyInheritCSSPropertyJustifyItems(StyleResolverState& state)
169 {
170     state.style()->setJustifyItems(state.parentStyle()->justifyItems());
171     state.style()->setJustifyItemsOverflowAlignment(state.parentStyle()->justifyItemsOverflowAlignment());
172     state.style()->setJustifyItemsPositionType(state.parentStyle()->justifyItemsPositionType());
173 }
174
175 void StyleBuilderFunctions::applyValueCSSPropertyJustifyItems(StyleResolverState& state, CSSValue* value)
176 {
177
178     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
179     if (Pair* pairValue = primitiveValue->getPairValue()) {
180         if (pairValue->first()->getValueID() == CSSValueLegacy) {
181             state.style()->setJustifyItemsPositionType(LegacyPosition);
182             state.style()->setJustifyItems(*pairValue->second());
183         } else {
184             state.style()->setJustifyItems(*pairValue->first());
185             state.style()->setJustifyItemsOverflowAlignment(*pairValue->second());
186         }
187     } else {
188         state.style()->setJustifyItems(*primitiveValue);
189     }
190 }
191
192 void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state)
193 {
194     state.style()->clearCursorList();
195     state.style()->setCursor(RenderStyle::initialCursor());
196 }
197
198 void StyleBuilderFunctions::applyInheritCSSPropertyCursor(StyleResolverState& state)
199 {
200     state.style()->setCursor(state.parentStyle()->cursor());
201     state.style()->setCursorList(state.parentStyle()->cursors());
202 }
203
204 void StyleBuilderFunctions::applyValueCSSPropertyCursor(StyleResolverState& state, CSSValue* value)
205 {
206     state.style()->clearCursorList();
207     if (value->isValueList()) {
208         CSSValueList* list = toCSSValueList(value);
209         int len = list->length();
210         state.style()->setCursor(CURSOR_AUTO);
211         for (int i = 0; i < len; i++) {
212             CSSValue* item = list->item(i);
213             if (item->isCursorImageValue()) {
214                 CSSCursorImageValue* image = toCSSCursorImageValue(item);
215                 if (image->updateIfSVGCursorIsUsed(state.element())) // Elements with SVG cursors are not allowed to share style.
216                     state.style()->setUnique();
217                 state.style()->addCursor(state.styleImage(CSSPropertyCursor, image), image->hotSpot());
218             } else {
219                 state.style()->setCursor(*toCSSPrimitiveValue(item));
220             }
221         }
222     } else {
223         state.style()->setCursor(*toCSSPrimitiveValue(value));
224     }
225 }
226
227 void StyleBuilderFunctions::applyValueCSSPropertyDirection(StyleResolverState& state, CSSValue* value)
228 {
229     state.style()->setDirection(*toCSSPrimitiveValue(value));
230     Element* element = state.element();
231     if (element && element == element->document().documentElement())
232         element->document().setDirectionSetOnDocumentElement(true);
233 }
234
235 void StyleBuilderFunctions::applyInitialCSSPropertyFontFamily(StyleResolverState& state)
236 {
237     state.fontBuilder().setFontFamilyInitial();
238 }
239
240 void StyleBuilderFunctions::applyInheritCSSPropertyFontFamily(StyleResolverState& state)
241 {
242     state.fontBuilder().setFontFamilyInherit(state.parentFontDescription());
243 }
244
245 void StyleBuilderFunctions::applyValueCSSPropertyFontFamily(StyleResolverState& state, CSSValue* value)
246 {
247     state.fontBuilder().setFontFamilyValue(value);
248 }
249
250 void StyleBuilderFunctions::applyValueCSSPropertyGlyphOrientationVertical(StyleResolverState& state, CSSValue* value)
251 {
252     if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueAuto)
253         state.style()->accessSVGStyle().setGlyphOrientationVertical(GO_AUTO);
254     else
255         state.style()->accessSVGStyle().setGlyphOrientationVertical(StyleBuilderConverter::convertGlyphOrientation(state, value));
256 }
257
258 void StyleBuilderFunctions::applyInitialCSSPropertyGridTemplateAreas(StyleResolverState& state)
259 {
260     state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
261     state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
262     state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
263 }
264
265 void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(StyleResolverState& state)
266 {
267     state.style()->setNamedGridArea(state.parentStyle()->namedGridArea());
268     state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount());
269     state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount());
270 }
271
272 void StyleBuilderFunctions::applyValueCSSPropertyGridTemplateAreas(StyleResolverState& state, CSSValue* value)
273 {
274     if (value->isPrimitiveValue()) {
275         // FIXME: Shouldn't we clear the grid-area values
276         ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
277         return;
278     }
279
280     CSSGridTemplateAreasValue* gridTemplateAreasValue = toCSSGridTemplateAreasValue(value);
281     const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue->gridAreaMap();
282
283     NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines();
284     NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines();
285     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns);
286     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows);
287     state.style()->setNamedGridColumnLines(namedGridColumnLines);
288     state.style()->setNamedGridRowLines(namedGridRowLines);
289
290     state.style()->setNamedGridArea(newNamedGridAreas);
291     state.style()->setNamedGridAreaRowCount(gridTemplateAreasValue->rowCount());
292     state.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue->columnCount());
293 }
294
295 void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value)
296 {
297     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
298     Length lineHeight;
299
300     if (primitiveValue->getValueID() == CSSValueNormal) {
301         lineHeight = RenderStyle::initialLineHeight();
302     } else if (primitiveValue->isLength()) {
303         float multiplier = state.style()->effectiveZoom();
304         if (LocalFrame* frame = state.document().frame())
305             multiplier *= frame->textZoomFactor();
306         lineHeight = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier));
307     } else if (primitiveValue->isPercentage()) {
308         lineHeight = Length((state.style()->computedFontSize() * primitiveValue->getIntValue()) / 100.0, Fixed);
309     } else if (primitiveValue->isNumber()) {
310         lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
311     } else if (primitiveValue->isCalculated()) {
312         double multiplier = state.style()->effectiveZoom();
313         if (LocalFrame* frame = state.document().frame())
314             multiplier *= frame->textZoomFactor();
315         Length zoomedLength = Length(primitiveValue->cssCalcValue()->toCalcValue(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier)));
316         lineHeight = Length(valueForLength(zoomedLength, state.style()->fontSize()), Fixed);
317     } else {
318         return;
319     }
320     state.style()->setLineHeight(lineHeight);
321 }
322
323 void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(StyleResolverState& state, CSSValue* value)
324 {
325     state.style()->setListStyleImage(state.styleImage(CSSPropertyListStyleImage, value));
326 }
327
328 void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(StyleResolverState& state)
329 {
330     state.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto());
331     state.style()->setOutlineStyle(RenderStyle::initialBorderStyle());
332 }
333
334 void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(StyleResolverState& state)
335 {
336     state.style()->setOutlineStyleIsAuto(state.parentStyle()->outlineStyleIsAuto());
337     state.style()->setOutlineStyle(state.parentStyle()->outlineStyle());
338 }
339
340 void StyleBuilderFunctions::applyValueCSSPropertyOutlineStyle(StyleResolverState& state, CSSValue* value)
341 {
342     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
343     state.style()->setOutlineStyleIsAuto(*primitiveValue);
344     state.style()->setOutlineStyle(*primitiveValue);
345 }
346
347 void StyleBuilderFunctions::applyValueCSSPropertyResize(StyleResolverState& state, CSSValue* value)
348 {
349     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
350
351     EResize r = RESIZE_NONE;
352     if (primitiveValue->getValueID() == CSSValueAuto) {
353         if (Settings* settings = state.document().settings())
354             r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
355     } else {
356         r = *primitiveValue;
357     }
358     state.style()->setResize(r);
359 }
360
361 static Length mmLength(double mm) { return Length(mm * cssPixelsPerMillimeter, Fixed); }
362 static Length inchLength(double inch) { return Length(inch * cssPixelsPerInch, Fixed); }
363 static bool getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
364 {
365     DEFINE_STATIC_LOCAL(Length, a5Width, (mmLength(148)));
366     DEFINE_STATIC_LOCAL(Length, a5Height, (mmLength(210)));
367     DEFINE_STATIC_LOCAL(Length, a4Width, (mmLength(210)));
368     DEFINE_STATIC_LOCAL(Length, a4Height, (mmLength(297)));
369     DEFINE_STATIC_LOCAL(Length, a3Width, (mmLength(297)));
370     DEFINE_STATIC_LOCAL(Length, a3Height, (mmLength(420)));
371     DEFINE_STATIC_LOCAL(Length, b5Width, (mmLength(176)));
372     DEFINE_STATIC_LOCAL(Length, b5Height, (mmLength(250)));
373     DEFINE_STATIC_LOCAL(Length, b4Width, (mmLength(250)));
374     DEFINE_STATIC_LOCAL(Length, b4Height, (mmLength(353)));
375     DEFINE_STATIC_LOCAL(Length, letterWidth, (inchLength(8.5)));
376     DEFINE_STATIC_LOCAL(Length, letterHeight, (inchLength(11)));
377     DEFINE_STATIC_LOCAL(Length, legalWidth, (inchLength(8.5)));
378     DEFINE_STATIC_LOCAL(Length, legalHeight, (inchLength(14)));
379     DEFINE_STATIC_LOCAL(Length, ledgerWidth, (inchLength(11)));
380     DEFINE_STATIC_LOCAL(Length, ledgerHeight, (inchLength(17)));
381
382     if (!pageSizeName)
383         return false;
384
385     switch (pageSizeName->getValueID()) {
386     case CSSValueA5:
387         width = a5Width;
388         height = a5Height;
389         break;
390     case CSSValueA4:
391         width = a4Width;
392         height = a4Height;
393         break;
394     case CSSValueA3:
395         width = a3Width;
396         height = a3Height;
397         break;
398     case CSSValueB5:
399         width = b5Width;
400         height = b5Height;
401         break;
402     case CSSValueB4:
403         width = b4Width;
404         height = b4Height;
405         break;
406     case CSSValueLetter:
407         width = letterWidth;
408         height = letterHeight;
409         break;
410     case CSSValueLegal:
411         width = legalWidth;
412         height = legalHeight;
413         break;
414     case CSSValueLedger:
415         width = ledgerWidth;
416         height = ledgerHeight;
417         break;
418     default:
419         return false;
420     }
421
422     if (pageOrientation) {
423         switch (pageOrientation->getValueID()) {
424         case CSSValueLandscape:
425             std::swap(width, height);
426             break;
427         case CSSValuePortrait:
428             // Nothing to do.
429             break;
430         default:
431             return false;
432         }
433     }
434     return true;
435 }
436
437 void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) { }
438 void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) { }
439 void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state, CSSValue* value)
440 {
441     state.style()->resetPageSizeType();
442     Length width;
443     Length height;
444     PageSizeType pageSizeType = PAGE_SIZE_AUTO;
445     CSSValueListInspector inspector(value);
446     switch (inspector.length()) {
447     case 2: {
448         // <length>{2} | <page-size> <orientation>
449         if (!inspector.first()->isPrimitiveValue() || !inspector.second()->isPrimitiveValue())
450             return;
451         CSSPrimitiveValue* first = toCSSPrimitiveValue(inspector.first());
452         CSSPrimitiveValue* second = toCSSPrimitiveValue(inspector.second());
453         if (first->isLength()) {
454             // <length>{2}
455             if (!second->isLength())
456                 return;
457             width = first->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
458             height = second->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
459         } else {
460             // <page-size> <orientation>
461             // The value order is guaranteed. See BisonCSSParser::parseSizeParameter.
462             if (!getPageSizeFromName(first, second, width, height))
463                 return;
464         }
465         pageSizeType = PAGE_SIZE_RESOLVED;
466         break;
467     }
468     case 1: {
469         // <length> | auto | <page-size> | [ portrait | landscape]
470         if (!inspector.first()->isPrimitiveValue())
471             return;
472         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inspector.first());
473         if (primitiveValue->isLength()) {
474             // <length>
475             pageSizeType = PAGE_SIZE_RESOLVED;
476             width = height = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
477         } else {
478             switch (primitiveValue->getValueID()) {
479             case 0:
480                 return;
481             case CSSValueAuto:
482                 pageSizeType = PAGE_SIZE_AUTO;
483                 break;
484             case CSSValuePortrait:
485                 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
486                 break;
487             case CSSValueLandscape:
488                 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
489                 break;
490             default:
491                 // <page-size>
492                 pageSizeType = PAGE_SIZE_RESOLVED;
493                 if (!getPageSizeFromName(primitiveValue, 0, width, height))
494                     return;
495             }
496         }
497         break;
498     }
499     default:
500         return;
501     }
502     state.style()->setPageSizeType(pageSizeType);
503     state.style()->setPageSize(LengthSize(width, height));
504 }
505
506 void StyleBuilderFunctions::applyValueCSSPropertyTextAlign(StyleResolverState& state, CSSValue* value)
507 {
508     if (!value->isPrimitiveValue())
509         return;
510
511     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
512     // FIXME : Per http://www.w3.org/TR/css3-text/#text-align0 can now take <string> but this is not implemented in the
513     // rendering code.
514     if (primitiveValue->isString())
515         return;
516
517     if (primitiveValue->isValueID() && primitiveValue->getValueID() != CSSValueWebkitMatchParent)
518         state.style()->setTextAlign(*primitiveValue);
519     else if (state.parentStyle()->textAlign() == TASTART)
520         state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? LEFT : RIGHT);
521     else if (state.parentStyle()->textAlign() == TAEND)
522         state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? RIGHT : LEFT);
523     else
524         state.style()->setTextAlign(state.parentStyle()->textAlign());
525 }
526
527 void StyleBuilderFunctions::applyInheritCSSPropertyTextIndent(StyleResolverState& state)
528 {
529     state.style()->setTextIndent(state.parentStyle()->textIndent());
530     state.style()->setTextIndentLine(state.parentStyle()->textIndentLine());
531     state.style()->setTextIndentType(state.parentStyle()->textIndentType());
532 }
533
534 void StyleBuilderFunctions::applyInitialCSSPropertyTextIndent(StyleResolverState& state)
535 {
536     state.style()->setTextIndent(RenderStyle::initialTextIndent());
537     state.style()->setTextIndentLine(RenderStyle::initialTextIndentLine());
538     state.style()->setTextIndentType(RenderStyle::initialTextIndentType());
539 }
540
541 void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(StyleResolverState& state, CSSValue* value)
542 {
543     if (!value->isValueList())
544         return;
545
546     Length lengthOrPercentageValue;
547     TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine();
548     TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType();
549
550     for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
551         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value());
552         if (!primitiveValue->getValueID())
553             lengthOrPercentageValue = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
554         else if (primitiveValue->getValueID() == CSSValueEachLine)
555             textIndentLineValue = TextIndentEachLine;
556         else if (primitiveValue->getValueID() == CSSValueHanging)
557             textIndentTypeValue = TextIndentHanging;
558         else
559             ASSERT_NOT_REACHED();
560     }
561
562     state.style()->setTextIndent(lengthOrPercentageValue);
563     state.style()->setTextIndentLine(textIndentLineValue);
564     state.style()->setTextIndentType(textIndentTypeValue);
565 }
566
567 void StyleBuilderFunctions::applyValueCSSPropertyTransform(StyleResolverState& state, CSSValue* value)
568 {
569     TransformOperations operations;
570     TransformBuilder::createTransformOperations(value, state.cssToLengthConversionData(), operations);
571     state.style()->setTransform(operations);
572 }
573
574 void StyleBuilderFunctions::applyInitialCSSPropertyTransformOrigin(StyleResolverState& state)
575 {
576     applyInitialCSSPropertyWebkitTransformOriginX(state);
577     applyInitialCSSPropertyWebkitTransformOriginY(state);
578     applyInitialCSSPropertyWebkitTransformOriginZ(state);
579 }
580
581 void StyleBuilderFunctions::applyInheritCSSPropertyTransformOrigin(StyleResolverState& state)
582 {
583     applyInheritCSSPropertyWebkitTransformOriginX(state);
584     applyInheritCSSPropertyWebkitTransformOriginY(state);
585     applyInheritCSSPropertyWebkitTransformOriginZ(state);
586 }
587
588 void StyleBuilderFunctions::applyValueCSSPropertyTransformOrigin(StyleResolverState& state, CSSValue* value)
589 {
590     CSSValueList* list = toCSSValueList(value);
591     ASSERT(list->length() == 3);
592     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0));
593     if (primitiveValue->isValueID()) {
594         switch (primitiveValue->getValueID()) {
595         case CSSValueLeft:
596             state.style()->setTransformOriginX(Length(0, Percent));
597             break;
598         case CSSValueRight:
599             state.style()->setTransformOriginX(Length(100, Percent));
600             break;
601         case CSSValueCenter:
602             state.style()->setTransformOriginX(Length(50, Percent));
603             break;
604         default:
605             ASSERT_NOT_REACHED();
606         }
607     } else {
608         state.style()->setTransformOriginX(StyleBuilderConverter::convertLength(state, primitiveValue));
609     }
610
611     primitiveValue = toCSSPrimitiveValue(list->item(1));
612     if (primitiveValue->isValueID()) {
613         switch (primitiveValue->getValueID()) {
614         case CSSValueTop:
615             state.style()->setTransformOriginY(Length(0, Percent));
616             break;
617         case CSSValueBottom:
618             state.style()->setTransformOriginY(Length(100, Percent));
619             break;
620         case CSSValueCenter:
621             state.style()->setTransformOriginY(Length(50, Percent));
622             break;
623         default:
624             ASSERT_NOT_REACHED();
625         }
626     } else {
627         state.style()->setTransformOriginY(StyleBuilderConverter::convertLength(state, primitiveValue));
628     }
629
630     primitiveValue = toCSSPrimitiveValue(list->item(2));
631     state.style()->setTransformOriginZ(StyleBuilderConverter::convertComputedLength<float>(state, primitiveValue));
632 }
633
634 void StyleBuilderFunctions::applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState& state)
635 {
636     applyInitialCSSPropertyWebkitPerspectiveOriginX(state);
637     applyInitialCSSPropertyWebkitPerspectiveOriginY(state);
638 }
639
640 void StyleBuilderFunctions::applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState& state)
641 {
642     applyInheritCSSPropertyWebkitPerspectiveOriginX(state);
643     applyInheritCSSPropertyWebkitPerspectiveOriginY(state);
644 }
645
646 void StyleBuilderFunctions::applyValueCSSPropertyPerspectiveOrigin(StyleResolverState& state, CSSValue* value)
647 {
648     CSSValueList* list = toCSSValueList(value);
649     ASSERT(list->length() == 2);
650     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0));
651     if (primitiveValue->isValueID()) {
652         switch (primitiveValue->getValueID()) {
653         case CSSValueLeft:
654             state.style()->setPerspectiveOriginX(Length(0, Percent));
655             break;
656         case CSSValueRight:
657             state.style()->setPerspectiveOriginX(Length(100, Percent));
658             break;
659         case CSSValueCenter:
660             state.style()->setPerspectiveOriginX(Length(50, Percent));
661             break;
662         default:
663             ASSERT_NOT_REACHED();
664         }
665     } else {
666         state.style()->setPerspectiveOriginX(StyleBuilderConverter::convertLength(state, primitiveValue));
667     }
668
669     primitiveValue = toCSSPrimitiveValue(list->item(1));
670     if (primitiveValue->isValueID()) {
671         switch (primitiveValue->getValueID()) {
672         case CSSValueTop:
673             state.style()->setPerspectiveOriginY(Length(0, Percent));
674             break;
675         case CSSValueBottom:
676             state.style()->setPerspectiveOriginY(Length(100, Percent));
677             break;
678         case CSSValueCenter:
679             state.style()->setPerspectiveOriginY(Length(50, Percent));
680             break;
681         default:
682             ASSERT_NOT_REACHED();
683         }
684     } else {
685         state.style()->setPerspectiveOriginY(StyleBuilderConverter::convertLength(state, primitiveValue));
686     }
687 }
688
689 void StyleBuilderFunctions::applyInheritCSSPropertyVerticalAlign(StyleResolverState& state)
690 {
691     EVerticalAlign verticalAlign = state.parentStyle()->verticalAlign();
692     state.style()->setVerticalAlign(verticalAlign);
693     if (verticalAlign == LENGTH)
694         state.style()->setVerticalAlignLength(state.parentStyle()->verticalAlignLength());
695 }
696
697 void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverState& state, CSSValue* value)
698 {
699     if (!value->isPrimitiveValue())
700         return;
701
702     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
703
704     if (primitiveValue->getValueID()) {
705         state.style()->setVerticalAlign(*primitiveValue);
706         return;
707     }
708
709     state.style()->setVerticalAlignLength(primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()));
710 }
711
712 static void resetEffectiveZoom(StyleResolverState& state)
713 {
714     // Reset the zoom in effect. This allows the setZoom method to accurately compute a new zoom in effect.
715     state.setEffectiveZoom(state.parentStyle() ? state.parentStyle()->effectiveZoom() : RenderStyle::initialZoom());
716 }
717
718 void StyleBuilderFunctions::applyInitialCSSPropertyZoom(StyleResolverState& state)
719 {
720     resetEffectiveZoom(state);
721     state.setZoom(RenderStyle::initialZoom());
722 }
723
724 void StyleBuilderFunctions::applyInheritCSSPropertyZoom(StyleResolverState& state)
725 {
726     resetEffectiveZoom(state);
727     state.setZoom(state.parentStyle()->zoom());
728 }
729
730 void StyleBuilderFunctions::applyValueCSSPropertyZoom(StyleResolverState& state, CSSValue* value)
731 {
732     ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue());
733     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
734
735     if (primitiveValue->getValueID() == CSSValueNormal) {
736         resetEffectiveZoom(state);
737         state.setZoom(RenderStyle::initialZoom());
738     } else if (primitiveValue->getValueID() == CSSValueReset) {
739         state.setEffectiveZoom(RenderStyle::initialZoom());
740         state.setZoom(RenderStyle::initialZoom());
741     } else if (primitiveValue->getValueID() == CSSValueDocument) {
742         float docZoom = state.rootElementStyle() ? state.rootElementStyle()->zoom() : RenderStyle::initialZoom();
743         state.setEffectiveZoom(docZoom);
744         state.setZoom(docZoom);
745     } else if (primitiveValue->isPercentage()) {
746         resetEffectiveZoom(state);
747         if (float percent = primitiveValue->getFloatValue())
748             state.setZoom(percent / 100.0f);
749     } else if (primitiveValue->isNumber()) {
750         resetEffectiveZoom(state);
751         if (float number = primitiveValue->getFloatValue())
752             state.setZoom(number);
753     }
754 }
755
756 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAspectRatio(StyleResolverState& state)
757 {
758     state.style()->setHasAspectRatio(RenderStyle::initialHasAspectRatio());
759     state.style()->setAspectRatioDenominator(RenderStyle::initialAspectRatioDenominator());
760     state.style()->setAspectRatioNumerator(RenderStyle::initialAspectRatioNumerator());
761 }
762
763 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAspectRatio(StyleResolverState& state)
764 {
765     if (!state.parentStyle()->hasAspectRatio())
766         return;
767     state.style()->setHasAspectRatio(true);
768     state.style()->setAspectRatioDenominator(state.parentStyle()->aspectRatioDenominator());
769     state.style()->setAspectRatioNumerator(state.parentStyle()->aspectRatioNumerator());
770 }
771
772 void StyleBuilderFunctions::applyValueCSSPropertyWebkitAspectRatio(StyleResolverState& state, CSSValue* value)
773 {
774     if (!value->isAspectRatioValue()) {
775         state.style()->setHasAspectRatio(false);
776         return;
777     }
778     CSSAspectRatioValue* aspectRatioValue = toCSSAspectRatioValue(value);
779     state.style()->setHasAspectRatio(true);
780     state.style()->setAspectRatioDenominator(aspectRatioValue->denominatorValue());
781     state.style()->setAspectRatioNumerator(aspectRatioValue->numeratorValue());
782 }
783
784 void StyleBuilderFunctions::applyValueCSSPropertyWebkitBorderImage(StyleResolverState& state, CSSValue* value)
785 {
786     NinePieceImage image;
787     state.styleMap().mapNinePieceImage(state.style(), CSSPropertyWebkitBorderImage, value, image);
788     state.style()->setBorderImage(image);
789 }
790
791 void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverState& state, CSSValue* value)
792 {
793     if (value->isPrimitiveValue()) {
794         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
795         if (primitiveValue->getValueID() == CSSValueNone) {
796             state.style()->setClipPath(nullptr);
797         } else if (primitiveValue->isShape()) {
798             state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, primitiveValue->getShapeValue())));
799         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_URI) {
800             String cssURLValue = primitiveValue->getStringValue();
801             KURL url = state.document().completeURL(cssURLValue);
802             // FIXME: It doesn't work with forward or external SVG references (see https://bugs.webkit.org/show_bug.cgi?id=90405)
803             state.style()->setClipPath(ReferenceClipPathOperation::create(cssURLValue, AtomicString(url.fragmentIdentifier())));
804         }
805     }
806 }
807
808 void StyleBuilderFunctions::applyValueCSSPropertyWebkitFilter(StyleResolverState& state, CSSValue* value)
809 {
810     FilterOperations operations;
811     if (FilterOperationResolver::createFilterOperations(value, state.cssToLengthConversionData(), operations, state))
812         state.style()->setFilter(operations);
813 }
814
815 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state)
816 {
817     state.style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill());
818     state.style()->setTextEmphasisMark(RenderStyle::initialTextEmphasisMark());
819     state.style()->setTextEmphasisCustomMark(RenderStyle::initialTextEmphasisCustomMark());
820 }
821
822 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state)
823 {
824     state.style()->setTextEmphasisFill(state.parentStyle()->textEmphasisFill());
825     state.style()->setTextEmphasisMark(state.parentStyle()->textEmphasisMark());
826     state.style()->setTextEmphasisCustomMark(state.parentStyle()->textEmphasisCustomMark());
827 }
828
829 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state, CSSValue* value)
830 {
831     if (value->isValueList()) {
832         CSSValueList* list = toCSSValueList(value);
833         ASSERT(list->length() == 2);
834         if (list->length() != 2)
835             return;
836         for (unsigned i = 0; i < 2; ++i) {
837             CSSValue* item = list->item(i);
838             if (!item->isPrimitiveValue())
839                 continue;
840
841             CSSPrimitiveValue* value = toCSSPrimitiveValue(item);
842             if (value->getValueID() == CSSValueFilled || value->getValueID() == CSSValueOpen)
843                 state.style()->setTextEmphasisFill(*value);
844             else
845                 state.style()->setTextEmphasisMark(*value);
846         }
847         state.style()->setTextEmphasisCustomMark(nullAtom);
848         return;
849     }
850
851     if (!value->isPrimitiveValue())
852         return;
853     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
854
855     if (primitiveValue->isString()) {
856         state.style()->setTextEmphasisFill(TextEmphasisFillFilled);
857         state.style()->setTextEmphasisMark(TextEmphasisMarkCustom);
858         state.style()->setTextEmphasisCustomMark(AtomicString(primitiveValue->getStringValue()));
859         return;
860     }
861
862     state.style()->setTextEmphasisCustomMark(nullAtom);
863
864     if (primitiveValue->getValueID() == CSSValueFilled || primitiveValue->getValueID() == CSSValueOpen) {
865         state.style()->setTextEmphasisFill(*primitiveValue);
866         state.style()->setTextEmphasisMark(TextEmphasisMarkAuto);
867     } else {
868         state.style()->setTextEmphasisFill(TextEmphasisFillFilled);
869         state.style()->setTextEmphasisMark(*primitiveValue);
870     }
871 }
872
873 void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState& state)
874 {
875     state.style()->setWillChangeContents(false);
876     state.style()->setWillChangeScrollPosition(false);
877     state.style()->setWillChangeProperties(Vector<CSSPropertyID>());
878     state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
879 }
880
881 void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state)
882 {
883     state.style()->setWillChangeContents(state.parentStyle()->willChangeContents());
884     state.style()->setWillChangeScrollPosition(state.parentStyle()->willChangeScrollPosition());
885     state.style()->setWillChangeProperties(state.parentStyle()->willChangeProperties());
886     state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
887 }
888
889 void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value)
890 {
891     ASSERT(value->isValueList());
892     bool willChangeContents = false;
893     bool willChangeScrollPosition = false;
894     Vector<CSSPropertyID> willChangeProperties;
895
896     for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
897         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value());
898         if (CSSPropertyID propertyID = primitiveValue->getPropertyID())
899             willChangeProperties.append(propertyID);
900         else if (primitiveValue->getValueID() == CSSValueContents)
901             willChangeContents = true;
902         else if (primitiveValue->getValueID() == CSSValueScrollPosition)
903             willChangeScrollPosition = true;
904         else
905             ASSERT_NOT_REACHED();
906     }
907     state.style()->setWillChangeContents(willChangeContents);
908     state.style()->setWillChangeScrollPosition(willChangeScrollPosition);
909     state.style()->setWillChangeProperties(willChangeProperties);
910     state.style()->setSubtreeWillChangeContents(willChangeContents || state.parentStyle()->subtreeWillChangeContents());
911 }
912
913 void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state)
914 {
915     state.style()->clearContent();
916 }
917
918 void StyleBuilderFunctions::applyInheritCSSPropertyContent(StyleResolverState&)
919 {
920     // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
921     // note is a reminder that eventually "inherit" needs to be supported.
922 }
923
924 void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value)
925 {
926     // list of string, uri, counter, attr, i
927
928     if (!value->isValueList())
929         return;
930
931     bool didSet = false;
932     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
933         CSSValue* item = i.value();
934         if (item->isImageGeneratorValue()) {
935             if (item->isGradientValue())
936                 state.style()->setContent(StyleGeneratedImage::create(toCSSGradientValue(item)->gradientWithStylesResolved(state.document().textLinkColors(), state.style()->color()).get()), didSet);
937             else
938                 state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item)), didSet);
939             didSet = true;
940         } else if (item->isImageSetValue()) {
941             state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet);
942             didSet = true;
943         }
944
945         if (item->isImageValue()) {
946             state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item)), didSet);
947             didSet = true;
948             continue;
949         }
950
951         if (!item->isPrimitiveValue())
952             continue;
953
954         CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item);
955
956         if (contentValue->isString()) {
957             state.style()->setContent(contentValue->getStringValue().impl(), didSet);
958             didSet = true;
959         } else if (contentValue->isAttr()) {
960             // FIXME: Can a namespace be specified for an attr(foo)?
961             if (state.style()->styleType() == NOPSEUDO)
962                 state.style()->setUnique();
963             else
964                 state.parentStyle()->setUnique();
965             QualifiedName attr(nullAtom, AtomicString(contentValue->getStringValue()), nullAtom);
966             const AtomicString& value = state.element()->getAttribute(attr);
967             state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet);
968             didSet = true;
969             // register the fact that the attribute value affects the style
970             state.contentAttrValues().append(attr.localName());
971         } else if (contentValue->isCounter()) {
972             Counter* counterValue = contentValue->getCounterValue();
973             EListStyleType listStyleType = NoneListStyle;
974             CSSValueID listStyleIdent = counterValue->listStyleIdent();
975             if (listStyleIdent != CSSValueNone)
976                 listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
977             OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(AtomicString(counterValue->identifier()), listStyleType, AtomicString(counterValue->separator())));
978             state.style()->setContent(counter.release(), didSet);
979             didSet = true;
980         } else {
981             switch (contentValue->getValueID()) {
982             case CSSValueOpenQuote:
983                 state.style()->setContent(OPEN_QUOTE, didSet);
984                 didSet = true;
985                 break;
986             case CSSValueCloseQuote:
987                 state.style()->setContent(CLOSE_QUOTE, didSet);
988                 didSet = true;
989                 break;
990             case CSSValueNoOpenQuote:
991                 state.style()->setContent(NO_OPEN_QUOTE, didSet);
992                 didSet = true;
993                 break;
994             case CSSValueNoCloseQuote:
995                 state.style()->setContent(NO_CLOSE_QUOTE, didSet);
996                 didSet = true;
997                 break;
998             default:
999                 // normal and none do not have any effect.
1000                 { }
1001             }
1002         }
1003     }
1004     if (!didSet)
1005         state.style()->clearContent();
1006 }
1007
1008 void StyleBuilderFunctions::applyInitialCSSPropertyFont(StyleResolverState&)
1009 {
1010     ASSERT_NOT_REACHED();
1011 }
1012
1013 void StyleBuilderFunctions::applyInheritCSSPropertyFont(StyleResolverState&)
1014 {
1015     ASSERT_NOT_REACHED();
1016 }
1017
1018 void StyleBuilderFunctions::applyValueCSSPropertyFont(StyleResolverState& state, CSSValue* value)
1019 {
1020     // Only System Font identifiers should come through this method
1021     // all other values should have been handled when the shorthand
1022     // was expanded by the parser.
1023     // FIXME: System Font identifiers should not hijack this
1024     // short-hand CSSProperty like this (crbug.com/353932)
1025     state.style()->setLineHeight(RenderStyle::initialLineHeight());
1026     state.setLineHeightValue(0);
1027     state.fontBuilder().fromSystemFont(toCSSPrimitiveValue(value)->getValueID(), state.style()->effectiveZoom());
1028 }
1029
1030 void StyleBuilderFunctions::applyValueCSSPropertyWebkitLocale(StyleResolverState& state, CSSValue* value)
1031 {
1032     if (!value->isPrimitiveValue())
1033         return;
1034     const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1035     if (primitiveValue->getValueID() == CSSValueAuto)
1036         state.style()->setLocale(nullAtom);
1037     else
1038         state.style()->setLocale(AtomicString(primitiveValue->getStringValue()));
1039     state.fontBuilder().setScript(state.style()->locale());
1040 }
1041
1042 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&)
1043 {
1044 }
1045
1046 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&)
1047 {
1048 }
1049
1050 void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(StyleResolverState& state, CSSValue* value)
1051 {
1052     if (!value->isPrimitiveValue())
1053         return;
1054     const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1055     if (!primitiveValue->getValueID())
1056         return;
1057     state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
1058     state.document().setHasAnnotatedRegions(true);
1059 }
1060
1061 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspective(StyleResolverState& state)
1062 {
1063     applyInitialCSSPropertyPerspective(state);
1064 }
1065
1066 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspective(StyleResolverState& state)
1067 {
1068     applyInheritCSSPropertyPerspective(state);
1069 }
1070
1071 void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspective(StyleResolverState& state, CSSValue* value)
1072 {
1073     if (!value->isPrimitiveValue())
1074         return;
1075     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1076     if (primitiveValue->isNumber()) {
1077         float perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.cssToLengthConversionData());
1078         if (perspectiveValue >= 0.0f)
1079             state.style()->setPerspective(perspectiveValue);
1080     } else {
1081         applyValueCSSPropertyPerspective(state, value);
1082     }
1083 }
1084
1085 void StyleBuilderFunctions::applyValueCSSPropertyPerspective(StyleResolverState& state, CSSValue* value)
1086 {
1087     if (!value->isPrimitiveValue())
1088         return;
1089     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1090     if (primitiveValue->getValueID() == CSSValueNone) {
1091         state.style()->setPerspective(0);
1092         return;
1093     }
1094
1095     if (!primitiveValue->isLength())
1096         return;
1097     float perspectiveValue = primitiveValue->computeLength<float>(state.cssToLengthConversionData());
1098     if (perspectiveValue >= 0.0f)
1099         state.style()->setPerspective(perspectiveValue);
1100 }
1101
1102 void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(StyleResolverState& state, CSSValue* value)
1103 {
1104     if (value->isPrimitiveValue())
1105         state.setWritingMode(*toCSSPrimitiveValue(value));
1106
1107     // FIXME: It is not ok to modify document state while applying style.
1108     if (state.element() && state.element() == state.document().documentElement())
1109         state.document().setWritingModeSetOnDocumentElement(true);
1110 }
1111
1112 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value)
1113 {
1114     if (value->isPrimitiveValue())
1115         state.setTextOrientation(*toCSSPrimitiveValue(value));
1116 }
1117
1118 void StyleBuilderFunctions::applyInheritCSSPropertyBaselineShift(StyleResolverState& state)
1119 {
1120     const SVGRenderStyle& parentSvgStyle = state.parentStyle()->svgStyle();
1121     EBaselineShift baselineShift = parentSvgStyle.baselineShift();
1122     SVGRenderStyle& svgStyle = state.style()->accessSVGStyle();
1123     svgStyle.setBaselineShift(baselineShift);
1124     if (baselineShift == BS_LENGTH)
1125         svgStyle.setBaselineShiftValue(parentSvgStyle.baselineShiftValue());
1126 }
1127
1128 void StyleBuilderFunctions::applyValueCSSPropertyBaselineShift(StyleResolverState& state, CSSValue* value)
1129 {
1130     SVGRenderStyle& svgStyle = state.style()->accessSVGStyle();
1131     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1132     if (!primitiveValue->isValueID()) {
1133         svgStyle.setBaselineShift(BS_LENGTH);
1134         svgStyle.setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue));
1135         return;
1136     }
1137     switch (primitiveValue->getValueID()) {
1138     case CSSValueBaseline:
1139         svgStyle.setBaselineShift(BS_BASELINE);
1140         return;
1141     case CSSValueSub:
1142         svgStyle.setBaselineShift(BS_SUB);
1143         return;
1144     case CSSValueSuper:
1145         svgStyle.setBaselineShift(BS_SUPER);
1146         return;
1147     default:
1148         ASSERT_NOT_REACHED();
1149     }
1150 }
1151
1152 void StyleBuilderFunctions::applyValueCSSPropertyGridAutoFlow(StyleResolverState& state, CSSValue* value)
1153 {
1154     ASSERT(value->isValueList());
1155     CSSValueList* list = toCSSValueList(value);
1156
1157     CSSPrimitiveValue* first = list->length() >= 1 ? toCSSPrimitiveValue(list->item(0)) : nullptr;
1158
1159     if (!first) {
1160         applyInitialCSSPropertyGridAutoFlow(state);
1161         return;
1162     }
1163
1164     CSSPrimitiveValue* second = list->length() == 2 ? toCSSPrimitiveValue(list->item(1)) : nullptr;
1165
1166     GridAutoFlow autoFlow = RenderStyle::initialGridAutoFlow();
1167     switch (first->getValueID()) {
1168     case CSSValueRow:
1169         if (second) {
1170             if (second->getValueID() == CSSValueDense)
1171                 autoFlow = AutoFlowRowDense;
1172             else
1173                 autoFlow = AutoFlowStackRow;
1174         } else {
1175             autoFlow = AutoFlowRow;
1176         }
1177         break;
1178     case CSSValueColumn:
1179         if (second) {
1180             if (second->getValueID() == CSSValueDense)
1181                 autoFlow = AutoFlowColumnDense;
1182             else
1183                 autoFlow = AutoFlowStackColumn;
1184         } else {
1185             autoFlow = AutoFlowColumn;
1186         }
1187         break;
1188     case CSSValueDense:
1189         if (second && second->getValueID() == CSSValueColumn)
1190             autoFlow = AutoFlowColumnDense;
1191         else
1192             autoFlow = AutoFlowRowDense;
1193         break;
1194     case CSSValueStack:
1195         if (second && second->getValueID() == CSSValueColumn)
1196             autoFlow = AutoFlowStackColumn;
1197         else
1198             autoFlow = AutoFlowStackRow;
1199         break;
1200     default:
1201         ASSERT_NOT_REACHED();
1202         break;
1203     }
1204
1205     state.style()->setGridAutoFlow(autoFlow);
1206 }
1207
1208 } // namespace blink