1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 4 * (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com) 5 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) 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 (at) webkit.org> 8 * Copyright (C) 2007, 2008 Eric Seidel <eric (at) 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 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 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 134 static Length clipConvertToLength(StyleResolverState& state, CSSPrimitiveValue* value) 135 { 136 return value->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData()); 137 } 138 139 void StyleBuilderFunctions::applyInitialCSSPropertyClip(StyleResolverState& state) 140 { 141 state.style()->setClip(Length(), Length(), Length(), Length()); 142 state.style()->setHasClip(false); 143 } 144 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 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 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 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 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 206 void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state) 207 { 208 state.style()->clearCursorList(); 209 state.style()->setCursor(RenderStyle::initialCursor()); 210 } 211 212 void StyleBuilderFunctions::applyInheritCSSPropertyCursor(StyleResolverState& state) 213 { 214 state.style()->setCursor(state.parentStyle()->cursor()); 215 state.style()->setCursorList(state.parentStyle()->cursors()); 216 } 217 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 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 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 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 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 272 void StyleBuilderFunctions::applyInitialCSSPropertyFontFamily(StyleResolverState& state) 273 { 274 state.fontBuilder().setFontFamilyInitial(); 275 } 276 277 void StyleBuilderFunctions::applyInheritCSSPropertyFontFamily(StyleResolverState& state) 278 { 279 state.fontBuilder().setFontFamilyInherit(state.parentFontDescription()); 280 } 281 282 void StyleBuilderFunctions::applyValueCSSPropertyFontFamily(StyleResolverState& state, CSSValue* value) 283 { 284 state.fontBuilder().setFontFamilyValue(value); 285 } 286 287 void StyleBuilderFunctions::applyInitialCSSPropertyFontSize(StyleResolverState& state) 288 { 289 state.fontBuilder().setFontSizeInitial(); 290 } 291 292 void StyleBuilderFunctions::applyInheritCSSPropertyFontSize(StyleResolverState& state) 293 { 294 state.fontBuilder().setFontSizeInherit(state.parentFontDescription()); 295 } 296 297 void StyleBuilderFunctions::applyValueCSSPropertyFontSize(StyleResolverState& state, CSSValue* value) 298 { 299 state.fontBuilder().setFontSizeValue(value, state.parentStyle(), state.rootElementStyle()); 300 } 301 302 void StyleBuilderFunctions::applyInitialCSSPropertyFontWeight(StyleResolverState& state) 303 { 304 state.fontBuilder().setWeight(FontWeightNormal); 305 } 306 307 void StyleBuilderFunctions::applyInheritCSSPropertyFontWeight(StyleResolverState& state) 308 { 309 state.fontBuilder().setWeight(state.parentFontDescription().weight()); 310 } 311 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 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 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 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 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 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 405 void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(StyleResolverState& state, CSSValue* value) 406 { 407 state.style()->setListStyleImage(state.styleImage(CSSPropertyListStyleImage, value)); 408 } 409 410 void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(StyleResolverState& state) 411 { 412 state.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto()); 413 state.style()->setOutlineStyle(RenderStyle::initialBorderStyle()); 414 } 415 416 void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(StyleResolverState& state) 417 { 418 state.style()->setOutlineStyleIsAuto(state.parentStyle()->outlineStyleIsAuto()); 419 state.style()->setOutlineStyle(state.parentStyle()->outlineStyle()); 420 } 421 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 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 443 static Length mmLength(double mm) { return Length(mm * cssPixelsPerMillimeter, Fixed); } 444 static Length inchLength(double inch) { return Length(inch * cssPixelsPerInch, Fixed); } 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 519 void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) { } 520 void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) { } 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 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 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 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 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 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 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 666 void StyleBuilderFunctions::applyInitialCSSPropertyTransformOrigin(StyleResolverState& state) 667 { 668 applyInitialCSSPropertyWebkitTransformOriginX(state); 669 applyInitialCSSPropertyWebkitTransformOriginY(state); 670 applyInitialCSSPropertyWebkitTransformOriginZ(state); 671 } 672 673 void StyleBuilderFunctions::applyInheritCSSPropertyTransformOrigin(StyleResolverState& state) 674 { 675 applyInheritCSSPropertyWebkitTransformOriginX(state); 676 applyInheritCSSPropertyWebkitTransformOriginY(state); 677 applyInheritCSSPropertyWebkitTransformOriginZ(state); 678 } 679 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 726 void StyleBuilderFunctions::applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState& state) 727 { 728 applyInitialCSSPropertyWebkitPerspectiveOriginX(state); 729 applyInitialCSSPropertyWebkitPerspectiveOriginY(state); 730 } 731 732 void StyleBuilderFunctions::applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState& state) 733 { 734 applyInheritCSSPropertyWebkitPerspectiveOriginX(state); 735 applyInheritCSSPropertyWebkitPerspectiveOriginY(state); 736 } 737 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 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 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 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 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 819 void StyleBuilderFunctions::applyInitialCSSPropertyZoom(StyleResolverState& state) 820 { 821 resetEffectiveZoom(state); 822 state.setZoom(RenderStyle::initialZoom()); 823 } 824 825 void StyleBuilderFunctions::applyInheritCSSPropertyZoom(StyleResolverState& state) 826 { 827 resetEffectiveZoom(state); 828 state.setZoom(state.parentStyle()->zoom()); 829 } 830 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 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 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 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 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 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 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 916 void StyleBuilderFunctions::applyInitialCSSPropertyFontVariantLigatures(StyleResolverState& state) 917 { 918 state.fontBuilder().setFontVariantLigaturesInitial(); 919 } 920 921 void StyleBuilderFunctions::applyInheritCSSPropertyFontVariantLigatures(StyleResolverState& state) 922 { 923 state.fontBuilder().setFontVariantLigaturesInherit(state.parentFontDescription()); 924 } 925 926 void StyleBuilderFunctions::applyValueCSSPropertyFontVariantLigatures(StyleResolverState& state, CSSValue* value) 927 { 928 state.fontBuilder().setFontVariantLigaturesValue(value); 929 } 930 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 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) 985 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspectiveOrigin(StyleResolverState& state) 986 { 987 applyInitialCSSPropertyWebkitPerspectiveOriginX(state); 988 applyInitialCSSPropertyWebkitPerspectiveOriginY(state); 989 } 990 991 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspectiveOrigin(StyleResolverState& state) 992 { 993 applyInheritCSSPropertyWebkitPerspectiveOriginX(state); 994 applyInheritCSSPropertyWebkitPerspectiveOriginY(state); 995 } 996 997 void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspectiveOrigin(StyleResolverState&, CSSValue* value) 998 { 999 // This is expanded in the parser 1000 ASSERT_NOT_REACHED(); 1001 } 1002 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 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 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 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 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 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 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 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 1127 void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state) 1128 { 1129 state.style()->clearContent(); 1130 } 1131 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 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 1222 void StyleBuilderFunctions::applyInitialCSSPropertyFont(StyleResolverState&) 1223 { 1224 ASSERT_NOT_REACHED(); 1225 } 1226 1227 void StyleBuilderFunctions::applyInheritCSSPropertyFont(StyleResolverState&) 1228 { 1229 ASSERT_NOT_REACHED(); 1230 } 1231 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 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 1256 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&) 1257 { 1258 } 1259 1260 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&) 1261 { 1262 } 1263 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 1275 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspective(StyleResolverState& state) 1276 { 1277 applyInitialCSSPropertyPerspective(state); 1278 } 1279 1280 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspective(StyleResolverState& state) 1281 { 1282 applyInheritCSSPropertyPerspective(state); 1283 } 1284 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 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 1316 void StyleBuilderFunctions::applyInitialCSSPropertyInternalCallback(StyleResolverState& state) 1317 { 1318 } 1319 1320 void StyleBuilderFunctions::applyInheritCSSPropertyInternalCallback(StyleResolverState& state) 1321 { 1322 } 1323 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 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 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 1347 void StyleBuilderFunctions::applyInitialCSSPropertyWebkitFontFeatureSettings(StyleResolverState& state) 1348 { 1349 } 1350 1351 void StyleBuilderFunctions::applyInheritCSSPropertyWebkitFontFeatureSettings(StyleResolverState& state) 1352 { 1353 } 1354 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 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