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