Update To 11.40.268.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/CSSContentDistributionValue.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(!isShorthandProperty(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::applyInitialCSSPropertyJustifyContent(StyleResolverState& state)
193 {
194     state.style()->setJustifyContent(RenderStyle::initialJustifyContent());
195     state.style()->setJustifyContentOverflowAlignment(RenderStyle::initialJustifyContentOverflowAlignment());
196     state.style()->setJustifyContentDistribution(RenderStyle::initialJustifyContentDistribution());
197 }
198
199 void StyleBuilderFunctions::applyInheritCSSPropertyJustifyContent(StyleResolverState& state)
200 {
201     state.style()->setJustifyContent(state.parentStyle()->justifyContent());
202     state.style()->setJustifyContentOverflowAlignment(state.parentStyle()->justifyContentOverflowAlignment());
203     state.style()->setJustifyContentDistribution(state.parentStyle()->justifyContentDistribution());
204 }
205
206 void StyleBuilderFunctions::applyValueCSSPropertyJustifyContent(StyleResolverState& state, CSSValue* value)
207 {
208     CSSContentDistributionValue* contentValue = toCSSContentDistributionValue(value);
209     if (contentValue->distribution()->getValueID() != CSSValueInvalid)
210         state.style()->setJustifyContentDistribution(*contentValue->distribution());
211     if (contentValue->position()->getValueID() != CSSValueInvalid)
212         state.style()->setJustifyContent(*contentValue->position());
213     if (contentValue->overflow()->getValueID() != CSSValueInvalid)
214         state.style()->setJustifyContentOverflowAlignment(*contentValue->overflow());
215 }
216
217 void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state)
218 {
219     state.style()->clearCursorList();
220     state.style()->setCursor(RenderStyle::initialCursor());
221 }
222
223 void StyleBuilderFunctions::applyInheritCSSPropertyCursor(StyleResolverState& state)
224 {
225     state.style()->setCursor(state.parentStyle()->cursor());
226     state.style()->setCursorList(state.parentStyle()->cursors());
227 }
228
229 void StyleBuilderFunctions::applyValueCSSPropertyCursor(StyleResolverState& state, CSSValue* value)
230 {
231     state.style()->clearCursorList();
232     if (value->isValueList()) {
233         CSSValueList* list = toCSSValueList(value);
234         int len = list->length();
235         state.style()->setCursor(CURSOR_AUTO);
236         for (int i = 0; i < len; i++) {
237             CSSValue* item = list->item(i);
238             if (item->isCursorImageValue()) {
239                 CSSCursorImageValue* image = toCSSCursorImageValue(item);
240                 if (image->updateIfSVGCursorIsUsed(state.element())) // Elements with SVG cursors are not allowed to share style.
241                     state.style()->setUnique();
242                 state.style()->addCursor(state.styleImage(CSSPropertyCursor, image), image->hotSpot());
243             } else {
244                 state.style()->setCursor(*toCSSPrimitiveValue(item));
245             }
246         }
247     } else {
248         state.style()->setCursor(*toCSSPrimitiveValue(value));
249     }
250 }
251
252 void StyleBuilderFunctions::applyValueCSSPropertyDirection(StyleResolverState& state, CSSValue* value)
253 {
254     state.style()->setDirection(*toCSSPrimitiveValue(value));
255     Element* element = state.element();
256     if (element && element == element->document().documentElement())
257         element->document().setDirectionSetOnDocumentElement(true);
258 }
259
260 void StyleBuilderFunctions::applyValueCSSPropertyGlyphOrientationVertical(StyleResolverState& state, CSSValue* value)
261 {
262     if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueAuto)
263         state.style()->accessSVGStyle().setGlyphOrientationVertical(GO_AUTO);
264     else
265         state.style()->accessSVGStyle().setGlyphOrientationVertical(StyleBuilderConverter::convertGlyphOrientation(state, value));
266 }
267
268 void StyleBuilderFunctions::applyInitialCSSPropertyGridTemplateAreas(StyleResolverState& state)
269 {
270     state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
271     state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
272     state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
273 }
274
275 void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(StyleResolverState& state)
276 {
277     state.style()->setNamedGridArea(state.parentStyle()->namedGridArea());
278     state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount());
279     state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount());
280 }
281
282 void StyleBuilderFunctions::applyValueCSSPropertyGridTemplateAreas(StyleResolverState& state, CSSValue* value)
283 {
284     if (value->isPrimitiveValue()) {
285         // FIXME: Shouldn't we clear the grid-area values
286         ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
287         return;
288     }
289
290     CSSGridTemplateAreasValue* gridTemplateAreasValue = toCSSGridTemplateAreasValue(value);
291     const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue->gridAreaMap();
292
293     NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines();
294     NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines();
295     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns);
296     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows);
297     state.style()->setNamedGridColumnLines(namedGridColumnLines);
298     state.style()->setNamedGridRowLines(namedGridRowLines);
299
300     state.style()->setNamedGridArea(newNamedGridAreas);
301     state.style()->setNamedGridAreaRowCount(gridTemplateAreasValue->rowCount());
302     state.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue->columnCount());
303 }
304
305 void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value)
306 {
307     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
308     Length lineHeight;
309
310     if (primitiveValue->getValueID() == CSSValueNormal) {
311         lineHeight = RenderStyle::initialLineHeight();
312     } else if (primitiveValue->isLength()) {
313         float multiplier = state.style()->effectiveZoom();
314         if (LocalFrame* frame = state.document().frame())
315             multiplier *= frame->textZoomFactor();
316         lineHeight = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier));
317     } else if (primitiveValue->isPercentage()) {
318         lineHeight = Length((state.style()->computedFontSize() * primitiveValue->getIntValue()) / 100.0, Fixed);
319     } else if (primitiveValue->isNumber()) {
320         lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
321     } else if (primitiveValue->isCalculated()) {
322         double multiplier = state.style()->effectiveZoom();
323         if (LocalFrame* frame = state.document().frame())
324             multiplier *= frame->textZoomFactor();
325         Length zoomedLength = Length(primitiveValue->cssCalcValue()->toCalcValue(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier)));
326         lineHeight = Length(valueForLength(zoomedLength, state.style()->fontSize()), Fixed);
327     } else {
328         return;
329     }
330     state.style()->setLineHeight(lineHeight);
331 }
332
333 void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(StyleResolverState& state, CSSValue* value)
334 {
335     state.style()->setListStyleImage(state.styleImage(CSSPropertyListStyleImage, value));
336 }
337
338 void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(StyleResolverState& state)
339 {
340     state.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto());
341     state.style()->setOutlineStyle(RenderStyle::initialBorderStyle());
342 }
343
344 void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(StyleResolverState& state)
345 {
346     state.style()->setOutlineStyleIsAuto(state.parentStyle()->outlineStyleIsAuto());
347     state.style()->setOutlineStyle(state.parentStyle()->outlineStyle());
348 }
349
350 void StyleBuilderFunctions::applyValueCSSPropertyOutlineStyle(StyleResolverState& state, CSSValue* value)
351 {
352     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
353     state.style()->setOutlineStyleIsAuto(*primitiveValue);
354     state.style()->setOutlineStyle(*primitiveValue);
355 }
356
357 void StyleBuilderFunctions::applyValueCSSPropertyResize(StyleResolverState& state, CSSValue* value)
358 {
359     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
360
361     EResize r = RESIZE_NONE;
362     if (primitiveValue->getValueID() == CSSValueAuto) {
363         if (Settings* settings = state.document().settings())
364             r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
365     } else {
366         r = *primitiveValue;
367     }
368     state.style()->setResize(r);
369 }
370
371 static Length mmLength(double mm) { return Length(mm * cssPixelsPerMillimeter, Fixed); }
372 static Length inchLength(double inch) { return Length(inch * cssPixelsPerInch, Fixed); }
373 static bool getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
374 {
375     DEFINE_STATIC_LOCAL(Length, a5Width, (mmLength(148)));
376     DEFINE_STATIC_LOCAL(Length, a5Height, (mmLength(210)));
377     DEFINE_STATIC_LOCAL(Length, a4Width, (mmLength(210)));
378     DEFINE_STATIC_LOCAL(Length, a4Height, (mmLength(297)));
379     DEFINE_STATIC_LOCAL(Length, a3Width, (mmLength(297)));
380     DEFINE_STATIC_LOCAL(Length, a3Height, (mmLength(420)));
381     DEFINE_STATIC_LOCAL(Length, b5Width, (mmLength(176)));
382     DEFINE_STATIC_LOCAL(Length, b5Height, (mmLength(250)));
383     DEFINE_STATIC_LOCAL(Length, b4Width, (mmLength(250)));
384     DEFINE_STATIC_LOCAL(Length, b4Height, (mmLength(353)));
385     DEFINE_STATIC_LOCAL(Length, letterWidth, (inchLength(8.5)));
386     DEFINE_STATIC_LOCAL(Length, letterHeight, (inchLength(11)));
387     DEFINE_STATIC_LOCAL(Length, legalWidth, (inchLength(8.5)));
388     DEFINE_STATIC_LOCAL(Length, legalHeight, (inchLength(14)));
389     DEFINE_STATIC_LOCAL(Length, ledgerWidth, (inchLength(11)));
390     DEFINE_STATIC_LOCAL(Length, ledgerHeight, (inchLength(17)));
391
392     if (!pageSizeName)
393         return false;
394
395     switch (pageSizeName->getValueID()) {
396     case CSSValueA5:
397         width = a5Width;
398         height = a5Height;
399         break;
400     case CSSValueA4:
401         width = a4Width;
402         height = a4Height;
403         break;
404     case CSSValueA3:
405         width = a3Width;
406         height = a3Height;
407         break;
408     case CSSValueB5:
409         width = b5Width;
410         height = b5Height;
411         break;
412     case CSSValueB4:
413         width = b4Width;
414         height = b4Height;
415         break;
416     case CSSValueLetter:
417         width = letterWidth;
418         height = letterHeight;
419         break;
420     case CSSValueLegal:
421         width = legalWidth;
422         height = legalHeight;
423         break;
424     case CSSValueLedger:
425         width = ledgerWidth;
426         height = ledgerHeight;
427         break;
428     default:
429         return false;
430     }
431
432     if (pageOrientation) {
433         switch (pageOrientation->getValueID()) {
434         case CSSValueLandscape:
435             std::swap(width, height);
436             break;
437         case CSSValuePortrait:
438             // Nothing to do.
439             break;
440         default:
441             return false;
442         }
443     }
444     return true;
445 }
446
447 void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) { }
448 void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) { }
449 void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state, CSSValue* value)
450 {
451     state.style()->resetPageSizeType();
452     Length width;
453     Length height;
454     PageSizeType pageSizeType = PAGE_SIZE_AUTO;
455     CSSValueList* list = toCSSValueList(value);
456     switch (list->length()) {
457     case 2: {
458         // <length>{2} | <page-size> <orientation>
459         CSSPrimitiveValue* first = toCSSPrimitiveValue(list->item(0));
460         CSSPrimitiveValue* second = toCSSPrimitiveValue(list->item(1));
461         if (first->isLength()) {
462             // <length>{2}
463             if (!second->isLength())
464                 return;
465             width = first->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
466             height = second->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
467         } else {
468             // <page-size> <orientation>
469             // The value order is guaranteed. See BisonCSSParser::parseSizeParameter.
470             if (!getPageSizeFromName(first, second, width, height))
471                 return;
472         }
473         pageSizeType = PAGE_SIZE_RESOLVED;
474         break;
475     }
476     case 1: {
477         // <length> | auto | <page-size> | [ portrait | landscape]
478         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0));
479         if (primitiveValue->isLength()) {
480             // <length>
481             pageSizeType = PAGE_SIZE_RESOLVED;
482             width = height = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
483         } else {
484             switch (primitiveValue->getValueID()) {
485             case 0:
486                 return;
487             case CSSValueAuto:
488                 pageSizeType = PAGE_SIZE_AUTO;
489                 break;
490             case CSSValuePortrait:
491                 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
492                 break;
493             case CSSValueLandscape:
494                 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
495                 break;
496             default:
497                 // <page-size>
498                 pageSizeType = PAGE_SIZE_RESOLVED;
499                 if (!getPageSizeFromName(primitiveValue, 0, width, height))
500                     return;
501             }
502         }
503         break;
504     }
505     default:
506         return;
507     }
508     state.style()->setPageSizeType(pageSizeType);
509     state.style()->setPageSize(LengthSize(width, height));
510 }
511
512 void StyleBuilderFunctions::applyValueCSSPropertyTextAlign(StyleResolverState& state, CSSValue* value)
513 {
514     if (!value->isPrimitiveValue())
515         return;
516
517     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
518     // FIXME : Per http://www.w3.org/TR/css3-text/#text-align0 can now take <string> but this is not implemented in the
519     // rendering code.
520     if (primitiveValue->isString())
521         return;
522
523     if (primitiveValue->isValueID() && primitiveValue->getValueID() != CSSValueWebkitMatchParent)
524         state.style()->setTextAlign(*primitiveValue);
525     else if (state.parentStyle()->textAlign() == TASTART)
526         state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? LEFT : RIGHT);
527     else if (state.parentStyle()->textAlign() == TAEND)
528         state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? RIGHT : LEFT);
529     else
530         state.style()->setTextAlign(state.parentStyle()->textAlign());
531 }
532
533 void StyleBuilderFunctions::applyInheritCSSPropertyTextIndent(StyleResolverState& state)
534 {
535     state.style()->setTextIndent(state.parentStyle()->textIndent());
536     state.style()->setTextIndentLine(state.parentStyle()->textIndentLine());
537     state.style()->setTextIndentType(state.parentStyle()->textIndentType());
538 }
539
540 void StyleBuilderFunctions::applyInitialCSSPropertyTextIndent(StyleResolverState& state)
541 {
542     state.style()->setTextIndent(RenderStyle::initialTextIndent());
543     state.style()->setTextIndentLine(RenderStyle::initialTextIndentLine());
544     state.style()->setTextIndentType(RenderStyle::initialTextIndentType());
545 }
546
547 void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(StyleResolverState& state, CSSValue* value)
548 {
549     if (!value->isValueList())
550         return;
551
552     Length lengthOrPercentageValue;
553     TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine();
554     TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType();
555
556     for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
557         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value());
558         if (!primitiveValue->getValueID())
559             lengthOrPercentageValue = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
560         else if (primitiveValue->getValueID() == CSSValueEachLine)
561             textIndentLineValue = TextIndentEachLine;
562         else if (primitiveValue->getValueID() == CSSValueHanging)
563             textIndentTypeValue = TextIndentHanging;
564         else
565             ASSERT_NOT_REACHED();
566     }
567
568     state.style()->setTextIndent(lengthOrPercentageValue);
569     state.style()->setTextIndentLine(textIndentLineValue);
570     state.style()->setTextIndentType(textIndentTypeValue);
571 }
572
573 void StyleBuilderFunctions::applyValueCSSPropertyTransform(StyleResolverState& state, CSSValue* value)
574 {
575     TransformOperations operations;
576     TransformBuilder::createTransformOperations(value, state.cssToLengthConversionData(), operations);
577     state.style()->setTransform(operations);
578 }
579
580 void StyleBuilderFunctions::applyInheritCSSPropertyVerticalAlign(StyleResolverState& state)
581 {
582     EVerticalAlign verticalAlign = state.parentStyle()->verticalAlign();
583     state.style()->setVerticalAlign(verticalAlign);
584     if (verticalAlign == LENGTH)
585         state.style()->setVerticalAlignLength(state.parentStyle()->verticalAlignLength());
586 }
587
588 void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverState& state, CSSValue* value)
589 {
590     if (!value->isPrimitiveValue())
591         return;
592
593     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
594
595     if (primitiveValue->getValueID()) {
596         state.style()->setVerticalAlign(*primitiveValue);
597         return;
598     }
599
600     state.style()->setVerticalAlignLength(primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()));
601 }
602
603 static void resetEffectiveZoom(StyleResolverState& state)
604 {
605     // Reset the zoom in effect. This allows the setZoom method to accurately compute a new zoom in effect.
606     state.setEffectiveZoom(state.parentStyle() ? state.parentStyle()->effectiveZoom() : RenderStyle::initialZoom());
607 }
608
609 void StyleBuilderFunctions::applyInitialCSSPropertyZoom(StyleResolverState& state)
610 {
611     resetEffectiveZoom(state);
612     state.setZoom(RenderStyle::initialZoom());
613 }
614
615 void StyleBuilderFunctions::applyInheritCSSPropertyZoom(StyleResolverState& state)
616 {
617     resetEffectiveZoom(state);
618     state.setZoom(state.parentStyle()->zoom());
619 }
620
621 void StyleBuilderFunctions::applyValueCSSPropertyZoom(StyleResolverState& state, CSSValue* value)
622 {
623     ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue());
624     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
625
626     if (primitiveValue->getValueID() == CSSValueNormal) {
627         resetEffectiveZoom(state);
628         state.setZoom(RenderStyle::initialZoom());
629     } else if (primitiveValue->getValueID() == CSSValueReset) {
630         state.setEffectiveZoom(RenderStyle::initialZoom());
631         state.setZoom(RenderStyle::initialZoom());
632     } else if (primitiveValue->getValueID() == CSSValueDocument) {
633         float docZoom = state.rootElementStyle() ? state.rootElementStyle()->zoom() : RenderStyle::initialZoom();
634         state.setEffectiveZoom(docZoom);
635         state.setZoom(docZoom);
636     } else if (primitiveValue->isPercentage()) {
637         resetEffectiveZoom(state);
638         if (float percent = primitiveValue->getFloatValue())
639             state.setZoom(percent / 100.0f);
640     } else if (primitiveValue->isNumber()) {
641         resetEffectiveZoom(state);
642         if (float number = primitiveValue->getFloatValue())
643             state.setZoom(number);
644     }
645 }
646
647 void StyleBuilderFunctions::applyValueCSSPropertyWebkitBorderImage(StyleResolverState& state, CSSValue* value)
648 {
649     NinePieceImage image;
650     state.styleMap().mapNinePieceImage(state.style(), CSSPropertyWebkitBorderImage, value, image);
651     state.style()->setBorderImage(image);
652 }
653
654 void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverState& state, CSSValue* value)
655 {
656     if (value->isPrimitiveValue()) {
657         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
658         if (primitiveValue->getValueID() == CSSValueNone) {
659             state.style()->setClipPath(nullptr);
660         } else if (primitiveValue->isShape()) {
661             state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, primitiveValue->getShapeValue())));
662         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_URI) {
663             String cssURLValue = primitiveValue->getStringValue();
664             KURL url = state.document().completeURL(cssURLValue);
665             // FIXME: It doesn't work with forward or external SVG references (see https://bugs.webkit.org/show_bug.cgi?id=90405)
666             state.style()->setClipPath(ReferenceClipPathOperation::create(cssURLValue, AtomicString(url.fragmentIdentifier())));
667         }
668     }
669 }
670
671 void StyleBuilderFunctions::applyValueCSSPropertyWebkitFilter(StyleResolverState& state, CSSValue* value)
672 {
673     FilterOperations operations;
674     if (FilterOperationResolver::createFilterOperations(value, state.cssToLengthConversionData(), operations, state))
675         state.style()->setFilter(operations);
676 }
677
678 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state)
679 {
680     state.style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill());
681     state.style()->setTextEmphasisMark(RenderStyle::initialTextEmphasisMark());
682     state.style()->setTextEmphasisCustomMark(RenderStyle::initialTextEmphasisCustomMark());
683 }
684
685 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state)
686 {
687     state.style()->setTextEmphasisFill(state.parentStyle()->textEmphasisFill());
688     state.style()->setTextEmphasisMark(state.parentStyle()->textEmphasisMark());
689     state.style()->setTextEmphasisCustomMark(state.parentStyle()->textEmphasisCustomMark());
690 }
691
692 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state, CSSValue* value)
693 {
694     if (value->isValueList()) {
695         CSSValueList* list = toCSSValueList(value);
696         ASSERT(list->length() == 2);
697         if (list->length() != 2)
698             return;
699         for (unsigned i = 0; i < 2; ++i) {
700             CSSValue* item = list->item(i);
701             if (!item->isPrimitiveValue())
702                 continue;
703
704             CSSPrimitiveValue* value = toCSSPrimitiveValue(item);
705             if (value->getValueID() == CSSValueFilled || value->getValueID() == CSSValueOpen)
706                 state.style()->setTextEmphasisFill(*value);
707             else
708                 state.style()->setTextEmphasisMark(*value);
709         }
710         state.style()->setTextEmphasisCustomMark(nullAtom);
711         return;
712     }
713
714     if (!value->isPrimitiveValue())
715         return;
716     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
717
718     if (primitiveValue->isString()) {
719         state.style()->setTextEmphasisFill(TextEmphasisFillFilled);
720         state.style()->setTextEmphasisMark(TextEmphasisMarkCustom);
721         state.style()->setTextEmphasisCustomMark(AtomicString(primitiveValue->getStringValue()));
722         return;
723     }
724
725     state.style()->setTextEmphasisCustomMark(nullAtom);
726
727     if (primitiveValue->getValueID() == CSSValueFilled || primitiveValue->getValueID() == CSSValueOpen) {
728         state.style()->setTextEmphasisFill(*primitiveValue);
729         state.style()->setTextEmphasisMark(TextEmphasisMarkAuto);
730     } else {
731         state.style()->setTextEmphasisFill(TextEmphasisFillFilled);
732         state.style()->setTextEmphasisMark(*primitiveValue);
733     }
734 }
735
736 void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState& state)
737 {
738     state.style()->setWillChangeContents(false);
739     state.style()->setWillChangeScrollPosition(false);
740     state.style()->setWillChangeProperties(Vector<CSSPropertyID>());
741     state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
742 }
743
744 void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state)
745 {
746     state.style()->setWillChangeContents(state.parentStyle()->willChangeContents());
747     state.style()->setWillChangeScrollPosition(state.parentStyle()->willChangeScrollPosition());
748     state.style()->setWillChangeProperties(state.parentStyle()->willChangeProperties());
749     state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
750 }
751
752 void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value)
753 {
754     ASSERT(value->isValueList());
755     bool willChangeContents = false;
756     bool willChangeScrollPosition = false;
757     Vector<CSSPropertyID> willChangeProperties;
758
759     for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
760         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value());
761         if (CSSPropertyID propertyID = primitiveValue->getPropertyID())
762             willChangeProperties.append(propertyID);
763         else if (primitiveValue->getValueID() == CSSValueContents)
764             willChangeContents = true;
765         else if (primitiveValue->getValueID() == CSSValueScrollPosition)
766             willChangeScrollPosition = true;
767         else
768             ASSERT_NOT_REACHED();
769     }
770     state.style()->setWillChangeContents(willChangeContents);
771     state.style()->setWillChangeScrollPosition(willChangeScrollPosition);
772     state.style()->setWillChangeProperties(willChangeProperties);
773     state.style()->setSubtreeWillChangeContents(willChangeContents || state.parentStyle()->subtreeWillChangeContents());
774 }
775
776 void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state)
777 {
778     state.style()->clearContent();
779 }
780
781 void StyleBuilderFunctions::applyInheritCSSPropertyContent(StyleResolverState&)
782 {
783     // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
784     // note is a reminder that eventually "inherit" needs to be supported.
785 }
786
787 void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value)
788 {
789     // list of string, uri, counter, attr, i
790
791     if (!value->isValueList())
792         return;
793
794     bool didSet = false;
795     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
796         CSSValue* item = i.value();
797         if (item->isImageGeneratorValue()) {
798             if (item->isGradientValue())
799                 state.style()->setContent(StyleGeneratedImage::create(toCSSGradientValue(item)->gradientWithStylesResolved(state.document().textLinkColors(), state.style()->color()).get()), didSet);
800             else
801                 state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item)), didSet);
802             didSet = true;
803         } else if (item->isImageSetValue()) {
804             state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet);
805             didSet = true;
806         }
807
808         if (item->isImageValue()) {
809             state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item)), didSet);
810             didSet = true;
811             continue;
812         }
813
814         if (!item->isPrimitiveValue())
815             continue;
816
817         CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item);
818
819         if (contentValue->isString()) {
820             state.style()->setContent(contentValue->getStringValue().impl(), didSet);
821             didSet = true;
822         } else if (contentValue->isAttr()) {
823             // FIXME: Can a namespace be specified for an attr(foo)?
824             if (state.style()->styleType() == NOPSEUDO)
825                 state.style()->setUnique();
826             else
827                 state.parentStyle()->setUnique();
828             QualifiedName attr(nullAtom, AtomicString(contentValue->getStringValue()), nullAtom);
829             const AtomicString& value = state.element()->getAttribute(attr);
830             state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet);
831             didSet = true;
832             // register the fact that the attribute value affects the style
833             state.contentAttrValues().append(attr.localName());
834         } else if (contentValue->isCounter()) {
835             Counter* counterValue = contentValue->getCounterValue();
836             EListStyleType listStyleType = NoneListStyle;
837             CSSValueID listStyleIdent = counterValue->listStyleIdent();
838             if (listStyleIdent != CSSValueNone)
839                 listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
840             OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(AtomicString(counterValue->identifier()), listStyleType, AtomicString(counterValue->separator())));
841             state.style()->setContent(counter.release(), didSet);
842             didSet = true;
843         } else {
844             switch (contentValue->getValueID()) {
845             case CSSValueOpenQuote:
846                 state.style()->setContent(OPEN_QUOTE, didSet);
847                 didSet = true;
848                 break;
849             case CSSValueCloseQuote:
850                 state.style()->setContent(CLOSE_QUOTE, didSet);
851                 didSet = true;
852                 break;
853             case CSSValueNoOpenQuote:
854                 state.style()->setContent(NO_OPEN_QUOTE, didSet);
855                 didSet = true;
856                 break;
857             case CSSValueNoCloseQuote:
858                 state.style()->setContent(NO_CLOSE_QUOTE, didSet);
859                 didSet = true;
860                 break;
861             default:
862                 // normal and none do not have any effect.
863                 { }
864             }
865         }
866     }
867     if (!didSet)
868         state.style()->clearContent();
869 }
870
871 void StyleBuilderFunctions::applyValueCSSPropertyWebkitLocale(StyleResolverState& state, CSSValue* value)
872 {
873     if (!value->isPrimitiveValue())
874         return;
875     const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
876     if (primitiveValue->getValueID() == CSSValueAuto)
877         state.style()->setLocale(nullAtom);
878     else
879         state.style()->setLocale(AtomicString(primitiveValue->getStringValue()));
880     state.fontBuilder().setScript(state.style()->locale());
881 }
882
883 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&)
884 {
885 }
886
887 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&)
888 {
889 }
890
891 void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(StyleResolverState& state, CSSValue* value)
892 {
893     if (!value->isPrimitiveValue())
894         return;
895     const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
896     if (!primitiveValue->getValueID())
897         return;
898     state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
899     state.document().setHasAnnotatedRegions(true);
900 }
901
902 void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(StyleResolverState& state, CSSValue* value)
903 {
904     if (value->isPrimitiveValue()) {
905         WritingMode writingMode = *toCSSPrimitiveValue(value);
906         state.setWritingMode(writingMode);
907         if (writingMode != TopToBottomWritingMode)
908             state.document().setContainsAnyRareWritingMode(true);
909     }
910
911     // FIXME: It is not ok to modify document state while applying style.
912     if (state.element() && state.element() == state.document().documentElement())
913         state.document().setWritingModeSetOnDocumentElement(true);
914 }
915
916 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value)
917 {
918     if (value->isPrimitiveValue())
919         state.setTextOrientation(*toCSSPrimitiveValue(value));
920 }
921
922 void StyleBuilderFunctions::applyInheritCSSPropertyBaselineShift(StyleResolverState& state)
923 {
924     const SVGRenderStyle& parentSvgStyle = state.parentStyle()->svgStyle();
925     EBaselineShift baselineShift = parentSvgStyle.baselineShift();
926     SVGRenderStyle& svgStyle = state.style()->accessSVGStyle();
927     svgStyle.setBaselineShift(baselineShift);
928     if (baselineShift == BS_LENGTH)
929         svgStyle.setBaselineShiftValue(parentSvgStyle.baselineShiftValue());
930 }
931
932 void StyleBuilderFunctions::applyValueCSSPropertyBaselineShift(StyleResolverState& state, CSSValue* value)
933 {
934     SVGRenderStyle& svgStyle = state.style()->accessSVGStyle();
935     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
936     if (!primitiveValue->isValueID()) {
937         svgStyle.setBaselineShift(BS_LENGTH);
938         svgStyle.setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue));
939         return;
940     }
941     switch (primitiveValue->getValueID()) {
942     case CSSValueBaseline:
943         svgStyle.setBaselineShift(BS_BASELINE);
944         return;
945     case CSSValueSub:
946         svgStyle.setBaselineShift(BS_SUB);
947         return;
948     case CSSValueSuper:
949         svgStyle.setBaselineShift(BS_SUPER);
950         return;
951     default:
952         ASSERT_NOT_REACHED();
953     }
954 }
955
956 } // namespace blink