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
isValidVisitedLinkProperty(CSSPropertyID id)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
applyProperty(CSSPropertyID id,StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyColor(StyleResolverState & state)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
applyInheritCSSPropertyColor(StyleResolverState & state)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
applyValueCSSPropertyColor(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyJustifyItems(StyleResolverState & state)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
applyInheritCSSPropertyJustifyItems(StyleResolverState & state)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
applyValueCSSPropertyJustifyItems(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyCursor(StyleResolverState & state)192 void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state)
193 {
194 state.style()->clearCursorList();
195 state.style()->setCursor(RenderStyle::initialCursor());
196 }
197
applyInheritCSSPropertyCursor(StyleResolverState & state)198 void StyleBuilderFunctions::applyInheritCSSPropertyCursor(StyleResolverState& state)
199 {
200 state.style()->setCursor(state.parentStyle()->cursor());
201 state.style()->setCursorList(state.parentStyle()->cursors());
202 }
203
applyValueCSSPropertyCursor(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyDirection(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyFontFamily(StyleResolverState & state)235 void StyleBuilderFunctions::applyInitialCSSPropertyFontFamily(StyleResolverState& state)
236 {
237 state.fontBuilder().setFontFamilyInitial();
238 }
239
applyInheritCSSPropertyFontFamily(StyleResolverState & state)240 void StyleBuilderFunctions::applyInheritCSSPropertyFontFamily(StyleResolverState& state)
241 {
242 state.fontBuilder().setFontFamilyInherit(state.parentFontDescription());
243 }
244
applyValueCSSPropertyFontFamily(StyleResolverState & state,CSSValue * value)245 void StyleBuilderFunctions::applyValueCSSPropertyFontFamily(StyleResolverState& state, CSSValue* value)
246 {
247 state.fontBuilder().setFontFamilyValue(value);
248 }
249
applyValueCSSPropertyGlyphOrientationVertical(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyGridTemplateAreas(StyleResolverState & state)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
applyInheritCSSPropertyGridTemplateAreas(StyleResolverState & state)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
applyValueCSSPropertyGridTemplateAreas(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyLineHeight(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyListStyleImage(StyleResolverState & state,CSSValue * value)323 void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(StyleResolverState& state, CSSValue* value)
324 {
325 state.style()->setListStyleImage(state.styleImage(CSSPropertyListStyleImage, value));
326 }
327
applyInitialCSSPropertyOutlineStyle(StyleResolverState & state)328 void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(StyleResolverState& state)
329 {
330 state.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto());
331 state.style()->setOutlineStyle(RenderStyle::initialBorderStyle());
332 }
333
applyInheritCSSPropertyOutlineStyle(StyleResolverState & state)334 void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(StyleResolverState& state)
335 {
336 state.style()->setOutlineStyleIsAuto(state.parentStyle()->outlineStyleIsAuto());
337 state.style()->setOutlineStyle(state.parentStyle()->outlineStyle());
338 }
339
applyValueCSSPropertyOutlineStyle(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyResize(StyleResolverState & state,CSSValue * value)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
mmLength(double mm)361 static Length mmLength(double mm) { return Length(mm * cssPixelsPerMillimeter, Fixed); }
inchLength(double inch)362 static Length inchLength(double inch) { return Length(inch * cssPixelsPerInch, Fixed); }
getPageSizeFromName(CSSPrimitiveValue * pageSizeName,CSSPrimitiveValue * pageOrientation,Length & width,Length & height)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
applyInitialCSSPropertySize(StyleResolverState &)437 void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) { }
applyInheritCSSPropertySize(StyleResolverState &)438 void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) { }
applyValueCSSPropertySize(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyTextAlign(StyleResolverState & state,CSSValue * value)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
applyInheritCSSPropertyTextIndent(StyleResolverState & state)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
applyInitialCSSPropertyTextIndent(StyleResolverState & state)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
applyValueCSSPropertyTextIndent(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyTransform(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyTransformOrigin(StyleResolverState & state)574 void StyleBuilderFunctions::applyInitialCSSPropertyTransformOrigin(StyleResolverState& state)
575 {
576 applyInitialCSSPropertyWebkitTransformOriginX(state);
577 applyInitialCSSPropertyWebkitTransformOriginY(state);
578 applyInitialCSSPropertyWebkitTransformOriginZ(state);
579 }
580
applyInheritCSSPropertyTransformOrigin(StyleResolverState & state)581 void StyleBuilderFunctions::applyInheritCSSPropertyTransformOrigin(StyleResolverState& state)
582 {
583 applyInheritCSSPropertyWebkitTransformOriginX(state);
584 applyInheritCSSPropertyWebkitTransformOriginY(state);
585 applyInheritCSSPropertyWebkitTransformOriginZ(state);
586 }
587
applyValueCSSPropertyTransformOrigin(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState & state)634 void StyleBuilderFunctions::applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState& state)
635 {
636 applyInitialCSSPropertyWebkitPerspectiveOriginX(state);
637 applyInitialCSSPropertyWebkitPerspectiveOriginY(state);
638 }
639
applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState & state)640 void StyleBuilderFunctions::applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState& state)
641 {
642 applyInheritCSSPropertyWebkitPerspectiveOriginX(state);
643 applyInheritCSSPropertyWebkitPerspectiveOriginY(state);
644 }
645
applyValueCSSPropertyPerspectiveOrigin(StyleResolverState & state,CSSValue * value)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
applyInheritCSSPropertyVerticalAlign(StyleResolverState & state)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
applyValueCSSPropertyVerticalAlign(StyleResolverState & state,CSSValue * value)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
resetEffectiveZoom(StyleResolverState & state)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
applyInitialCSSPropertyZoom(StyleResolverState & state)718 void StyleBuilderFunctions::applyInitialCSSPropertyZoom(StyleResolverState& state)
719 {
720 resetEffectiveZoom(state);
721 state.setZoom(RenderStyle::initialZoom());
722 }
723
applyInheritCSSPropertyZoom(StyleResolverState & state)724 void StyleBuilderFunctions::applyInheritCSSPropertyZoom(StyleResolverState& state)
725 {
726 resetEffectiveZoom(state);
727 state.setZoom(state.parentStyle()->zoom());
728 }
729
applyValueCSSPropertyZoom(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyWebkitAspectRatio(StyleResolverState & state)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
applyInheritCSSPropertyWebkitAspectRatio(StyleResolverState & state)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
applyValueCSSPropertyWebkitAspectRatio(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyWebkitBorderImage(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyWebkitClipPath(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyWebkitFilter(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyWebkitTextEmphasisStyle(StyleResolverState & state)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
applyInheritCSSPropertyWebkitTextEmphasisStyle(StyleResolverState & state)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
applyValueCSSPropertyWebkitTextEmphasisStyle(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyWillChange(StyleResolverState & state)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
applyInheritCSSPropertyWillChange(StyleResolverState & state)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
applyValueCSSPropertyWillChange(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyContent(StyleResolverState & state)913 void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state)
914 {
915 state.style()->clearContent();
916 }
917
applyInheritCSSPropertyContent(StyleResolverState &)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
applyValueCSSPropertyContent(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyFont(StyleResolverState &)1008 void StyleBuilderFunctions::applyInitialCSSPropertyFont(StyleResolverState&)
1009 {
1010 ASSERT_NOT_REACHED();
1011 }
1012
applyInheritCSSPropertyFont(StyleResolverState &)1013 void StyleBuilderFunctions::applyInheritCSSPropertyFont(StyleResolverState&)
1014 {
1015 ASSERT_NOT_REACHED();
1016 }
1017
applyValueCSSPropertyFont(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyWebkitLocale(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyWebkitAppRegion(StyleResolverState &)1042 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&)
1043 {
1044 }
1045
applyInheritCSSPropertyWebkitAppRegion(StyleResolverState &)1046 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&)
1047 {
1048 }
1049
applyValueCSSPropertyWebkitAppRegion(StyleResolverState & state,CSSValue * value)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
applyInitialCSSPropertyWebkitPerspective(StyleResolverState & state)1061 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspective(StyleResolverState& state)
1062 {
1063 applyInitialCSSPropertyPerspective(state);
1064 }
1065
applyInheritCSSPropertyWebkitPerspective(StyleResolverState & state)1066 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspective(StyleResolverState& state)
1067 {
1068 applyInheritCSSPropertyPerspective(state);
1069 }
1070
applyValueCSSPropertyWebkitPerspective(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyPerspective(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyWebkitWritingMode(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyWebkitTextOrientation(StyleResolverState & state,CSSValue * value)1112 void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value)
1113 {
1114 if (value->isPrimitiveValue())
1115 state.setTextOrientation(*toCSSPrimitiveValue(value));
1116 }
1117
applyInheritCSSPropertyBaselineShift(StyleResolverState & state)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
applyValueCSSPropertyBaselineShift(StyleResolverState & state,CSSValue * value)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
applyValueCSSPropertyGridAutoFlow(StyleResolverState & state,CSSValue * value)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
1209