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
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
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.
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.
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"
82 static inline bool isValidVisitedLinkProperty(CSSPropertyID id)
85 case CSSPropertyBackgroundColor:
86 case CSSPropertyBorderLeftColor:
87 case CSSPropertyBorderRightColor:
88 case CSSPropertyBorderTopColor:
89 case CSSPropertyBorderBottomColor:
90 case CSSPropertyColor:
92 case CSSPropertyOutlineColor:
93 case CSSPropertyStroke:
94 case CSSPropertyTextDecorationColor:
95 case CSSPropertyWebkitColumnRuleColor:
96 case CSSPropertyWebkitTextEmphasisColor:
97 case CSSPropertyWebkitTextFillColor:
98 case CSSPropertyWebkitTextStrokeColor:
107 void StyleBuilder::applyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value)
109 ASSERT_WITH_MESSAGE(!isShorthandProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
111 bool isInherit = state.parentNode() && value->isInheritedValue();
112 bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
114 ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
115 ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
117 if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
118 // Limit the properties that can be applied to only the ones honored by :visited.
122 if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSPropertyMetadata::isInheritedProperty(id))
123 state.parentStyle()->setHasExplicitlyInheritedProperties();
125 StyleBuilder::applyProperty(id, state, value, isInitial, isInherit);
128 void StyleBuilderFunctions::applyInitialCSSPropertyColor(StyleResolverState& state)
130 Color color = RenderStyle::initialColor();
131 if (state.applyPropertyToRegularStyle())
132 state.style()->setColor(color);
133 if (state.applyPropertyToVisitedLinkStyle())
134 state.style()->setVisitedLinkColor(color);
137 void StyleBuilderFunctions::applyInheritCSSPropertyColor(StyleResolverState& state)
139 Color color = state.parentStyle()->color();
140 if (state.applyPropertyToRegularStyle())
141 state.style()->setColor(color);
142 if (state.applyPropertyToVisitedLinkStyle())
143 state.style()->setVisitedLinkColor(color);
146 void StyleBuilderFunctions::applyValueCSSPropertyColor(StyleResolverState& state, CSSValue* value)
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);
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));
161 void StyleBuilderFunctions::applyInitialCSSPropertyJustifyItems(StyleResolverState& state)
163 state.style()->setJustifyItems(RenderStyle::initialJustifyItems());
164 state.style()->setJustifyItemsOverflowAlignment(RenderStyle::initialJustifyItemsOverflowAlignment());
165 state.style()->setJustifyItemsPositionType(RenderStyle::initialJustifyItemsPositionType());
168 void StyleBuilderFunctions::applyInheritCSSPropertyJustifyItems(StyleResolverState& state)
170 state.style()->setJustifyItems(state.parentStyle()->justifyItems());
171 state.style()->setJustifyItemsOverflowAlignment(state.parentStyle()->justifyItemsOverflowAlignment());
172 state.style()->setJustifyItemsPositionType(state.parentStyle()->justifyItemsPositionType());
175 void StyleBuilderFunctions::applyValueCSSPropertyJustifyItems(StyleResolverState& state, CSSValue* value)
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());
184 state.style()->setJustifyItems(*pairValue->first());
185 state.style()->setJustifyItemsOverflowAlignment(*pairValue->second());
188 state.style()->setJustifyItems(*primitiveValue);
192 void StyleBuilderFunctions::applyInitialCSSPropertyJustifyContent(StyleResolverState& state)
194 state.style()->setJustifyContent(RenderStyle::initialJustifyContent());
195 state.style()->setJustifyContentOverflowAlignment(RenderStyle::initialJustifyContentOverflowAlignment());
196 state.style()->setJustifyContentDistribution(RenderStyle::initialJustifyContentDistribution());
199 void StyleBuilderFunctions::applyInheritCSSPropertyJustifyContent(StyleResolverState& state)
201 state.style()->setJustifyContent(state.parentStyle()->justifyContent());
202 state.style()->setJustifyContentOverflowAlignment(state.parentStyle()->justifyContentOverflowAlignment());
203 state.style()->setJustifyContentDistribution(state.parentStyle()->justifyContentDistribution());
206 void StyleBuilderFunctions::applyValueCSSPropertyJustifyContent(StyleResolverState& state, CSSValue* value)
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());
217 void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state)
219 state.style()->clearCursorList();
220 state.style()->setCursor(RenderStyle::initialCursor());
223 void StyleBuilderFunctions::applyInheritCSSPropertyCursor(StyleResolverState& state)
225 state.style()->setCursor(state.parentStyle()->cursor());
226 state.style()->setCursorList(state.parentStyle()->cursors());
229 void StyleBuilderFunctions::applyValueCSSPropertyCursor(StyleResolverState& state, CSSValue* value)
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());
244 state.style()->setCursor(*toCSSPrimitiveValue(item));
248 state.style()->setCursor(*toCSSPrimitiveValue(value));
252 void StyleBuilderFunctions::applyValueCSSPropertyDirection(StyleResolverState& state, CSSValue* value)
254 state.style()->setDirection(*toCSSPrimitiveValue(value));
255 Element* element = state.element();
256 if (element && element == element->document().documentElement())
257 element->document().setDirectionSetOnDocumentElement(true);
260 void StyleBuilderFunctions::applyValueCSSPropertyGlyphOrientationVertical(StyleResolverState& state, CSSValue* value)
262 if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueAuto)
263 state.style()->accessSVGStyle().setGlyphOrientationVertical(GO_AUTO);
265 state.style()->accessSVGStyle().setGlyphOrientationVertical(StyleBuilderConverter::convertGlyphOrientation(state, value));
268 void StyleBuilderFunctions::applyInitialCSSPropertyGridTemplateAreas(StyleResolverState& state)
270 state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
271 state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
272 state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
275 void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(StyleResolverState& state)
277 state.style()->setNamedGridArea(state.parentStyle()->namedGridArea());
278 state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount());
279 state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount());
282 void StyleBuilderFunctions::applyValueCSSPropertyGridTemplateAreas(StyleResolverState& state, CSSValue* value)
284 if (value->isPrimitiveValue()) {
285 // FIXME: Shouldn't we clear the grid-area values
286 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
290 CSSGridTemplateAreasValue* gridTemplateAreasValue = toCSSGridTemplateAreasValue(value);
291 const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue->gridAreaMap();
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);
300 state.style()->setNamedGridArea(newNamedGridAreas);
301 state.style()->setNamedGridAreaRowCount(gridTemplateAreasValue->rowCount());
302 state.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue->columnCount());
305 void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value)
307 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
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);
330 state.style()->setLineHeight(lineHeight);
333 void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(StyleResolverState& state, CSSValue* value)
335 state.style()->setListStyleImage(state.styleImage(CSSPropertyListStyleImage, value));
338 void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(StyleResolverState& state)
340 state.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto());
341 state.style()->setOutlineStyle(RenderStyle::initialBorderStyle());
344 void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(StyleResolverState& state)
346 state.style()->setOutlineStyleIsAuto(state.parentStyle()->outlineStyleIsAuto());
347 state.style()->setOutlineStyle(state.parentStyle()->outlineStyle());
350 void StyleBuilderFunctions::applyValueCSSPropertyOutlineStyle(StyleResolverState& state, CSSValue* value)
352 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
353 state.style()->setOutlineStyleIsAuto(*primitiveValue);
354 state.style()->setOutlineStyle(*primitiveValue);
357 void StyleBuilderFunctions::applyValueCSSPropertyResize(StyleResolverState& state, CSSValue* value)
359 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
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;
368 state.style()->setResize(r);
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)
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)));
395 switch (pageSizeName->getValueID()) {
418 height = letterHeight;
422 height = legalHeight;
426 height = ledgerHeight;
432 if (pageOrientation) {
433 switch (pageOrientation->getValueID()) {
434 case CSSValueLandscape:
435 std::swap(width, height);
437 case CSSValuePortrait:
447 void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) { }
448 void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) { }
449 void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state, CSSValue* value)
451 state.style()->resetPageSizeType();
454 PageSizeType pageSizeType = PAGE_SIZE_AUTO;
455 CSSValueList* list = toCSSValueList(value);
456 switch (list->length()) {
458 // <length>{2} | <page-size> <orientation>
459 CSSPrimitiveValue* first = toCSSPrimitiveValue(list->item(0));
460 CSSPrimitiveValue* second = toCSSPrimitiveValue(list->item(1));
461 if (first->isLength()) {
463 if (!second->isLength())
465 width = first->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
466 height = second->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
468 // <page-size> <orientation>
469 // The value order is guaranteed. See BisonCSSParser::parseSizeParameter.
470 if (!getPageSizeFromName(first, second, width, height))
473 pageSizeType = PAGE_SIZE_RESOLVED;
477 // <length> | auto | <page-size> | [ portrait | landscape]
478 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0));
479 if (primitiveValue->isLength()) {
481 pageSizeType = PAGE_SIZE_RESOLVED;
482 width = height = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
484 switch (primitiveValue->getValueID()) {
488 pageSizeType = PAGE_SIZE_AUTO;
490 case CSSValuePortrait:
491 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
493 case CSSValueLandscape:
494 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
498 pageSizeType = PAGE_SIZE_RESOLVED;
499 if (!getPageSizeFromName(primitiveValue, 0, width, height))
508 state.style()->setPageSizeType(pageSizeType);
509 state.style()->setPageSize(LengthSize(width, height));
512 void StyleBuilderFunctions::applyValueCSSPropertyTextAlign(StyleResolverState& state, CSSValue* value)
514 if (!value->isPrimitiveValue())
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
520 if (primitiveValue->isString())
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);
530 state.style()->setTextAlign(state.parentStyle()->textAlign());
533 void StyleBuilderFunctions::applyInheritCSSPropertyTextIndent(StyleResolverState& state)
535 state.style()->setTextIndent(state.parentStyle()->textIndent());
536 state.style()->setTextIndentLine(state.parentStyle()->textIndentLine());
537 state.style()->setTextIndentType(state.parentStyle()->textIndentType());
540 void StyleBuilderFunctions::applyInitialCSSPropertyTextIndent(StyleResolverState& state)
542 state.style()->setTextIndent(RenderStyle::initialTextIndent());
543 state.style()->setTextIndentLine(RenderStyle::initialTextIndentLine());
544 state.style()->setTextIndentType(RenderStyle::initialTextIndentType());
547 void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(StyleResolverState& state, CSSValue* value)
549 if (!value->isValueList())
552 Length lengthOrPercentageValue;
553 TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine();
554 TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType();
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;
565 ASSERT_NOT_REACHED();
568 state.style()->setTextIndent(lengthOrPercentageValue);
569 state.style()->setTextIndentLine(textIndentLineValue);
570 state.style()->setTextIndentType(textIndentTypeValue);
573 void StyleBuilderFunctions::applyValueCSSPropertyTransform(StyleResolverState& state, CSSValue* value)
575 TransformOperations operations;
576 TransformBuilder::createTransformOperations(value, state.cssToLengthConversionData(), operations);
577 state.style()->setTransform(operations);
580 void StyleBuilderFunctions::applyInheritCSSPropertyVerticalAlign(StyleResolverState& state)
582 EVerticalAlign verticalAlign = state.parentStyle()->verticalAlign();
583 state.style()->setVerticalAlign(verticalAlign);
584 if (verticalAlign == LENGTH)
585 state.style()->setVerticalAlignLength(state.parentStyle()->verticalAlignLength());
588 void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverState& state, CSSValue* value)
590 if (!value->isPrimitiveValue())
593 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
595 if (primitiveValue->getValueID()) {
596 state.style()->setVerticalAlign(*primitiveValue);
600 state.style()->setVerticalAlignLength(primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()));
603 static void resetEffectiveZoom(StyleResolverState& state)
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());
609 void StyleBuilderFunctions::applyInitialCSSPropertyZoom(StyleResolverState& state)
611 resetEffectiveZoom(state);
612 state.setZoom(RenderStyle::initialZoom());
615 void StyleBuilderFunctions::applyInheritCSSPropertyZoom(StyleResolverState& state)
617 resetEffectiveZoom(state);
618 state.setZoom(state.parentStyle()->zoom());
621 void StyleBuilderFunctions::applyValueCSSPropertyZoom(StyleResolverState& state, CSSValue* value)
623 ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue());
624 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
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);
647 void StyleBuilderFunctions::applyValueCSSPropertyWebkitBorderImage(StyleResolverState& state, CSSValue* value)
649 NinePieceImage image;
650 state.styleMap().mapNinePieceImage(state.style(), CSSPropertyWebkitBorderImage, value, image);
651 state.style()->setBorderImage(image);
654 void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverState& state, CSSValue* value)
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())));
671 void StyleBuilderFunctions::applyValueCSSPropertyWebkitFilter(StyleResolverState& state, CSSValue* value)
673 FilterOperations operations;
674 if (FilterOperationResolver::createFilterOperations(value, state.cssToLengthConversionData(), operations, state))
675 state.style()->setFilter(operations);
678 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state)
680 state.style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill());
681 state.style()->setTextEmphasisMark(RenderStyle::initialTextEmphasisMark());
682 state.style()->setTextEmphasisCustomMark(RenderStyle::initialTextEmphasisCustomMark());
685 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state)
687 state.style()->setTextEmphasisFill(state.parentStyle()->textEmphasisFill());
688 state.style()->setTextEmphasisMark(state.parentStyle()->textEmphasisMark());
689 state.style()->setTextEmphasisCustomMark(state.parentStyle()->textEmphasisCustomMark());
692 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state, CSSValue* value)
694 if (value->isValueList()) {
695 CSSValueList* list = toCSSValueList(value);
696 ASSERT(list->length() == 2);
697 if (list->length() != 2)
699 for (unsigned i = 0; i < 2; ++i) {
700 CSSValue* item = list->item(i);
701 if (!item->isPrimitiveValue())
704 CSSPrimitiveValue* value = toCSSPrimitiveValue(item);
705 if (value->getValueID() == CSSValueFilled || value->getValueID() == CSSValueOpen)
706 state.style()->setTextEmphasisFill(*value);
708 state.style()->setTextEmphasisMark(*value);
710 state.style()->setTextEmphasisCustomMark(nullAtom);
714 if (!value->isPrimitiveValue())
716 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
718 if (primitiveValue->isString()) {
719 state.style()->setTextEmphasisFill(TextEmphasisFillFilled);
720 state.style()->setTextEmphasisMark(TextEmphasisMarkCustom);
721 state.style()->setTextEmphasisCustomMark(AtomicString(primitiveValue->getStringValue()));
725 state.style()->setTextEmphasisCustomMark(nullAtom);
727 if (primitiveValue->getValueID() == CSSValueFilled || primitiveValue->getValueID() == CSSValueOpen) {
728 state.style()->setTextEmphasisFill(*primitiveValue);
729 state.style()->setTextEmphasisMark(TextEmphasisMarkAuto);
731 state.style()->setTextEmphasisFill(TextEmphasisFillFilled);
732 state.style()->setTextEmphasisMark(*primitiveValue);
736 void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState& state)
738 state.style()->setWillChangeContents(false);
739 state.style()->setWillChangeScrollPosition(false);
740 state.style()->setWillChangeProperties(Vector<CSSPropertyID>());
741 state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
744 void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state)
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());
752 void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value)
754 ASSERT(value->isValueList());
755 bool willChangeContents = false;
756 bool willChangeScrollPosition = false;
757 Vector<CSSPropertyID> willChangeProperties;
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;
768 ASSERT_NOT_REACHED();
770 state.style()->setWillChangeContents(willChangeContents);
771 state.style()->setWillChangeScrollPosition(willChangeScrollPosition);
772 state.style()->setWillChangeProperties(willChangeProperties);
773 state.style()->setSubtreeWillChangeContents(willChangeContents || state.parentStyle()->subtreeWillChangeContents());
776 void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state)
778 state.style()->clearContent();
781 void StyleBuilderFunctions::applyInheritCSSPropertyContent(StyleResolverState&)
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.
787 void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value)
789 // list of string, uri, counter, attr, i
791 if (!value->isValueList())
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);
801 state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item)), didSet);
803 } else if (item->isImageSetValue()) {
804 state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet);
808 if (item->isImageValue()) {
809 state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item)), didSet);
814 if (!item->isPrimitiveValue())
817 CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item);
819 if (contentValue->isString()) {
820 state.style()->setContent(contentValue->getStringValue().impl(), didSet);
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();
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);
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);
844 switch (contentValue->getValueID()) {
845 case CSSValueOpenQuote:
846 state.style()->setContent(OPEN_QUOTE, didSet);
849 case CSSValueCloseQuote:
850 state.style()->setContent(CLOSE_QUOTE, didSet);
853 case CSSValueNoOpenQuote:
854 state.style()->setContent(NO_OPEN_QUOTE, didSet);
857 case CSSValueNoCloseQuote:
858 state.style()->setContent(NO_CLOSE_QUOTE, didSet);
862 // normal and none do not have any effect.
868 state.style()->clearContent();
871 void StyleBuilderFunctions::applyValueCSSPropertyWebkitLocale(StyleResolverState& state, CSSValue* value)
873 if (!value->isPrimitiveValue())
875 const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
876 if (primitiveValue->getValueID() == CSSValueAuto)
877 state.style()->setLocale(nullAtom);
879 state.style()->setLocale(AtomicString(primitiveValue->getStringValue()));
880 state.fontBuilder().setScript(state.style()->locale());
883 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&)
887 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&)
891 void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(StyleResolverState& state, CSSValue* value)
893 if (!value->isPrimitiveValue())
895 const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
896 if (!primitiveValue->getValueID())
898 state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
899 state.document().setHasAnnotatedRegions(true);
902 void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(StyleResolverState& state, CSSValue* value)
904 if (value->isPrimitiveValue()) {
905 WritingMode writingMode = *toCSSPrimitiveValue(value);
906 state.setWritingMode(writingMode);
907 if (writingMode != TopToBottomWritingMode)
908 state.document().setContainsAnyRareWritingMode(true);
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);
916 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value)
918 if (value->isPrimitiveValue())
919 state.setTextOrientation(*toCSSPrimitiveValue(value));
922 void StyleBuilderFunctions::applyInheritCSSPropertyBaselineShift(StyleResolverState& state)
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());
932 void StyleBuilderFunctions::applyValueCSSPropertyBaselineShift(StyleResolverState& state, CSSValue* value)
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));
941 switch (primitiveValue->getValueID()) {
942 case CSSValueBaseline:
943 svgStyle.setBaselineShift(BS_BASELINE);
946 svgStyle.setBaselineShift(BS_SUB);
949 svgStyle.setBaselineShift(BS_SUPER);
952 ASSERT_NOT_REACHED();