1/* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 4 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 5 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 7 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 8 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> 9 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 10 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 11 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions are 14 * met: 15 * 16 * * Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * * Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following disclaimer 20 * in the documentation and/or other materials provided with the 21 * distribution. 22 * * Neither the name of Google Inc. nor the names of its 23 * contributors may be used to endorse or promote products derived from 24 * this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39#include "config.h" 40 41#include "core/CSSPropertyNames.h" 42#include "core/CSSValueKeywords.h" 43#include "core/StyleBuilderFunctions.h" 44#include "core/StylePropertyShorthand.h" 45#include "core/css/BasicShapeFunctions.h" 46#include "core/css/CSSAspectRatioValue.h" 47#include "core/css/CSSCursorImageValue.h" 48#include "core/css/CSSFontValue.h" 49#include "core/css/CSSGradientValue.h" 50#include "core/css/CSSGridTemplateAreasValue.h" 51#include "core/css/CSSHelper.h" 52#include "core/css/CSSImageSetValue.h" 53#include "core/css/CSSLineBoxContainValue.h" 54#include "core/css/CSSPrimitiveValueMappings.h" 55#include "core/css/CSSPropertyMetadata.h" 56#include "core/css/Counter.h" 57#include "core/css/Pair.h" 58#include "core/css/StylePropertySet.h" 59#include "core/css/StyleRule.h" 60#include "core/css/resolver/ElementStyleResources.h" 61#include "core/css/resolver/FilterOperationResolver.h" 62#include "core/css/resolver/FontBuilder.h" 63#include "core/css/resolver/StyleBuilder.h" 64#include "core/css/resolver/TransformBuilder.h" 65#include "core/frame/LocalFrame.h" 66#include "core/frame/Settings.h" 67#include "core/rendering/style/CounterContent.h" 68#include "core/rendering/style/QuotesData.h" 69#include "core/rendering/style/RenderStyle.h" 70#include "core/rendering/style/RenderStyleConstants.h" 71#include "core/rendering/style/SVGRenderStyle.h" 72#include "core/rendering/style/StyleGeneratedImage.h" 73#include "platform/fonts/FontDescription.h" 74#include "wtf/MathExtras.h" 75#include "wtf/StdLibExtras.h" 76#include "wtf/Vector.h" 77 78namespace blink { 79 80namespace { 81 82static inline bool isValidVisitedLinkProperty(CSSPropertyID id) 83{ 84 switch (id) { 85 case CSSPropertyBackgroundColor: 86 case CSSPropertyBorderLeftColor: 87 case CSSPropertyBorderRightColor: 88 case CSSPropertyBorderTopColor: 89 case CSSPropertyBorderBottomColor: 90 case CSSPropertyColor: 91 case CSSPropertyFill: 92 case CSSPropertyOutlineColor: 93 case CSSPropertyStroke: 94 case CSSPropertyTextDecorationColor: 95 case CSSPropertyWebkitColumnRuleColor: 96 case CSSPropertyWebkitTextEmphasisColor: 97 case CSSPropertyWebkitTextFillColor: 98 case CSSPropertyWebkitTextStrokeColor: 99 return true; 100 default: 101 return false; 102 } 103} 104 105} // namespace 106 107void StyleBuilder::applyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value) 108{ 109 ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id); 110 111 bool isInherit = state.parentNode() && value->isInheritedValue(); 112 bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue()); 113 114 ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit 115 ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle()) 116 117 if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) { 118 // Limit the properties that can be applied to only the ones honored by :visited. 119 return; 120 } 121 122 if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSPropertyMetadata::isInheritedProperty(id)) 123 state.parentStyle()->setHasExplicitlyInheritedProperties(); 124 125 StyleBuilder::applyProperty(id, state, value, isInitial, isInherit); 126} 127 128void StyleBuilderFunctions::applyInitialCSSPropertyColor(StyleResolverState& state) 129{ 130 Color color = RenderStyle::initialColor(); 131 if (state.applyPropertyToRegularStyle()) 132 state.style()->setColor(color); 133 if (state.applyPropertyToVisitedLinkStyle()) 134 state.style()->setVisitedLinkColor(color); 135} 136 137void StyleBuilderFunctions::applyInheritCSSPropertyColor(StyleResolverState& state) 138{ 139 Color color = state.parentStyle()->color(); 140 if (state.applyPropertyToRegularStyle()) 141 state.style()->setColor(color); 142 if (state.applyPropertyToVisitedLinkStyle()) 143 state.style()->setVisitedLinkColor(color); 144} 145 146void StyleBuilderFunctions::applyValueCSSPropertyColor(StyleResolverState& state, CSSValue* value) 147{ 148 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 149 // As per the spec, 'color: currentColor' is treated as 'color: inherit' 150 if (primitiveValue->getValueID() == CSSValueCurrentcolor) { 151 applyInheritCSSPropertyColor(state); 152 return; 153 } 154 155 if (state.applyPropertyToRegularStyle()) 156 state.style()->setColor(StyleBuilderConverter::convertColor(state, value)); 157 if (state.applyPropertyToVisitedLinkStyle()) 158 state.style()->setVisitedLinkColor(StyleBuilderConverter::convertColor(state, value, true)); 159} 160 161void StyleBuilderFunctions::applyInitialCSSPropertyJustifyItems(StyleResolverState& state) 162{ 163 state.style()->setJustifyItems(RenderStyle::initialJustifyItems()); 164 state.style()->setJustifyItemsOverflowAlignment(RenderStyle::initialJustifyItemsOverflowAlignment()); 165 state.style()->setJustifyItemsPositionType(RenderStyle::initialJustifyItemsPositionType()); 166} 167 168void StyleBuilderFunctions::applyInheritCSSPropertyJustifyItems(StyleResolverState& state) 169{ 170 state.style()->setJustifyItems(state.parentStyle()->justifyItems()); 171 state.style()->setJustifyItemsOverflowAlignment(state.parentStyle()->justifyItemsOverflowAlignment()); 172 state.style()->setJustifyItemsPositionType(state.parentStyle()->justifyItemsPositionType()); 173} 174 175void StyleBuilderFunctions::applyValueCSSPropertyJustifyItems(StyleResolverState& state, CSSValue* value) 176{ 177 178 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 179 if (Pair* pairValue = primitiveValue->getPairValue()) { 180 if (pairValue->first()->getValueID() == CSSValueLegacy) { 181 state.style()->setJustifyItemsPositionType(LegacyPosition); 182 state.style()->setJustifyItems(*pairValue->second()); 183 } else { 184 state.style()->setJustifyItems(*pairValue->first()); 185 state.style()->setJustifyItemsOverflowAlignment(*pairValue->second()); 186 } 187 } else { 188 state.style()->setJustifyItems(*primitiveValue); 189 } 190} 191 192void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state) 193{ 194 state.style()->clearCursorList(); 195 state.style()->setCursor(RenderStyle::initialCursor()); 196} 197 198void StyleBuilderFunctions::applyInheritCSSPropertyCursor(StyleResolverState& state) 199{ 200 state.style()->setCursor(state.parentStyle()->cursor()); 201 state.style()->setCursorList(state.parentStyle()->cursors()); 202} 203 204void StyleBuilderFunctions::applyValueCSSPropertyCursor(StyleResolverState& state, CSSValue* value) 205{ 206 state.style()->clearCursorList(); 207 if (value->isValueList()) { 208 CSSValueList* list = toCSSValueList(value); 209 int len = list->length(); 210 state.style()->setCursor(CURSOR_AUTO); 211 for (int i = 0; i < len; i++) { 212 CSSValue* item = list->item(i); 213 if (item->isCursorImageValue()) { 214 CSSCursorImageValue* image = toCSSCursorImageValue(item); 215 if (image->updateIfSVGCursorIsUsed(state.element())) // Elements with SVG cursors are not allowed to share style. 216 state.style()->setUnique(); 217 state.style()->addCursor(state.styleImage(CSSPropertyCursor, image), image->hotSpot()); 218 } else { 219 state.style()->setCursor(*toCSSPrimitiveValue(item)); 220 } 221 } 222 } else { 223 state.style()->setCursor(*toCSSPrimitiveValue(value)); 224 } 225} 226 227void StyleBuilderFunctions::applyValueCSSPropertyDirection(StyleResolverState& state, CSSValue* value) 228{ 229 state.style()->setDirection(*toCSSPrimitiveValue(value)); 230 Element* element = state.element(); 231 if (element && element == element->document().documentElement()) 232 element->document().setDirectionSetOnDocumentElement(true); 233} 234 235void StyleBuilderFunctions::applyInitialCSSPropertyFontFamily(StyleResolverState& state) 236{ 237 state.fontBuilder().setFontFamilyInitial(); 238} 239 240void StyleBuilderFunctions::applyInheritCSSPropertyFontFamily(StyleResolverState& state) 241{ 242 state.fontBuilder().setFontFamilyInherit(state.parentFontDescription()); 243} 244 245void StyleBuilderFunctions::applyValueCSSPropertyFontFamily(StyleResolverState& state, CSSValue* value) 246{ 247 state.fontBuilder().setFontFamilyValue(value); 248} 249 250void StyleBuilderFunctions::applyValueCSSPropertyGlyphOrientationVertical(StyleResolverState& state, CSSValue* value) 251{ 252 if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueAuto) 253 state.style()->accessSVGStyle().setGlyphOrientationVertical(GO_AUTO); 254 else 255 state.style()->accessSVGStyle().setGlyphOrientationVertical(StyleBuilderConverter::convertGlyphOrientation(state, value)); 256} 257 258void StyleBuilderFunctions::applyInitialCSSPropertyGridTemplateAreas(StyleResolverState& state) 259{ 260 state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea()); 261 state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount()); 262 state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount()); 263} 264 265void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(StyleResolverState& state) 266{ 267 state.style()->setNamedGridArea(state.parentStyle()->namedGridArea()); 268 state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount()); 269 state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount()); 270} 271 272void StyleBuilderFunctions::applyValueCSSPropertyGridTemplateAreas(StyleResolverState& state, CSSValue* value) 273{ 274 if (value->isPrimitiveValue()) { 275 // FIXME: Shouldn't we clear the grid-area values 276 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone); 277 return; 278 } 279 280 CSSGridTemplateAreasValue* gridTemplateAreasValue = toCSSGridTemplateAreasValue(value); 281 const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue->gridAreaMap(); 282 283 NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines(); 284 NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines(); 285 StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns); 286 StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows); 287 state.style()->setNamedGridColumnLines(namedGridColumnLines); 288 state.style()->setNamedGridRowLines(namedGridRowLines); 289 290 state.style()->setNamedGridArea(newNamedGridAreas); 291 state.style()->setNamedGridAreaRowCount(gridTemplateAreasValue->rowCount()); 292 state.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue->columnCount()); 293} 294 295void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value) 296{ 297 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 298 Length lineHeight; 299 300 if (primitiveValue->getValueID() == CSSValueNormal) { 301 lineHeight = RenderStyle::initialLineHeight(); 302 } else if (primitiveValue->isLength()) { 303 float multiplier = state.style()->effectiveZoom(); 304 if (LocalFrame* frame = state.document().frame()) 305 multiplier *= frame->textZoomFactor(); 306 lineHeight = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier)); 307 } else if (primitiveValue->isPercentage()) { 308 lineHeight = Length((state.style()->computedFontSize() * primitiveValue->getIntValue()) / 100.0, Fixed); 309 } else if (primitiveValue->isNumber()) { 310 lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent); 311 } else if (primitiveValue->isCalculated()) { 312 double multiplier = state.style()->effectiveZoom(); 313 if (LocalFrame* frame = state.document().frame()) 314 multiplier *= frame->textZoomFactor(); 315 Length zoomedLength = Length(primitiveValue->cssCalcValue()->toCalcValue(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier))); 316 lineHeight = Length(valueForLength(zoomedLength, state.style()->fontSize()), Fixed); 317 } else { 318 return; 319 } 320 state.style()->setLineHeight(lineHeight); 321} 322 323void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(StyleResolverState& state, CSSValue* value) 324{ 325 state.style()->setListStyleImage(state.styleImage(CSSPropertyListStyleImage, value)); 326} 327 328void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(StyleResolverState& state) 329{ 330 state.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto()); 331 state.style()->setOutlineStyle(RenderStyle::initialBorderStyle()); 332} 333 334void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(StyleResolverState& state) 335{ 336 state.style()->setOutlineStyleIsAuto(state.parentStyle()->outlineStyleIsAuto()); 337 state.style()->setOutlineStyle(state.parentStyle()->outlineStyle()); 338} 339 340void StyleBuilderFunctions::applyValueCSSPropertyOutlineStyle(StyleResolverState& state, CSSValue* value) 341{ 342 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 343 state.style()->setOutlineStyleIsAuto(*primitiveValue); 344 state.style()->setOutlineStyle(*primitiveValue); 345} 346 347void StyleBuilderFunctions::applyValueCSSPropertyResize(StyleResolverState& state, CSSValue* value) 348{ 349 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 350 351 EResize r = RESIZE_NONE; 352 if (primitiveValue->getValueID() == CSSValueAuto) { 353 if (Settings* settings = state.document().settings()) 354 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE; 355 } else { 356 r = *primitiveValue; 357 } 358 state.style()->setResize(r); 359} 360 361static Length mmLength(double mm) { return Length(mm * cssPixelsPerMillimeter, Fixed); } 362static Length inchLength(double inch) { return Length(inch * cssPixelsPerInch, Fixed); } 363static bool getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height) 364{ 365 DEFINE_STATIC_LOCAL(Length, a5Width, (mmLength(148))); 366 DEFINE_STATIC_LOCAL(Length, a5Height, (mmLength(210))); 367 DEFINE_STATIC_LOCAL(Length, a4Width, (mmLength(210))); 368 DEFINE_STATIC_LOCAL(Length, a4Height, (mmLength(297))); 369 DEFINE_STATIC_LOCAL(Length, a3Width, (mmLength(297))); 370 DEFINE_STATIC_LOCAL(Length, a3Height, (mmLength(420))); 371 DEFINE_STATIC_LOCAL(Length, b5Width, (mmLength(176))); 372 DEFINE_STATIC_LOCAL(Length, b5Height, (mmLength(250))); 373 DEFINE_STATIC_LOCAL(Length, b4Width, (mmLength(250))); 374 DEFINE_STATIC_LOCAL(Length, b4Height, (mmLength(353))); 375 DEFINE_STATIC_LOCAL(Length, letterWidth, (inchLength(8.5))); 376 DEFINE_STATIC_LOCAL(Length, letterHeight, (inchLength(11))); 377 DEFINE_STATIC_LOCAL(Length, legalWidth, (inchLength(8.5))); 378 DEFINE_STATIC_LOCAL(Length, legalHeight, (inchLength(14))); 379 DEFINE_STATIC_LOCAL(Length, ledgerWidth, (inchLength(11))); 380 DEFINE_STATIC_LOCAL(Length, ledgerHeight, (inchLength(17))); 381 382 if (!pageSizeName) 383 return false; 384 385 switch (pageSizeName->getValueID()) { 386 case CSSValueA5: 387 width = a5Width; 388 height = a5Height; 389 break; 390 case CSSValueA4: 391 width = a4Width; 392 height = a4Height; 393 break; 394 case CSSValueA3: 395 width = a3Width; 396 height = a3Height; 397 break; 398 case CSSValueB5: 399 width = b5Width; 400 height = b5Height; 401 break; 402 case CSSValueB4: 403 width = b4Width; 404 height = b4Height; 405 break; 406 case CSSValueLetter: 407 width = letterWidth; 408 height = letterHeight; 409 break; 410 case CSSValueLegal: 411 width = legalWidth; 412 height = legalHeight; 413 break; 414 case CSSValueLedger: 415 width = ledgerWidth; 416 height = ledgerHeight; 417 break; 418 default: 419 return false; 420 } 421 422 if (pageOrientation) { 423 switch (pageOrientation->getValueID()) { 424 case CSSValueLandscape: 425 std::swap(width, height); 426 break; 427 case CSSValuePortrait: 428 // Nothing to do. 429 break; 430 default: 431 return false; 432 } 433 } 434 return true; 435} 436 437void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) { } 438void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) { } 439void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state, CSSValue* value) 440{ 441 state.style()->resetPageSizeType(); 442 Length width; 443 Length height; 444 PageSizeType pageSizeType = PAGE_SIZE_AUTO; 445 CSSValueListInspector inspector(value); 446 switch (inspector.length()) { 447 case 2: { 448 // <length>{2} | <page-size> <orientation> 449 if (!inspector.first()->isPrimitiveValue() || !inspector.second()->isPrimitiveValue()) 450 return; 451 CSSPrimitiveValue* first = toCSSPrimitiveValue(inspector.first()); 452 CSSPrimitiveValue* second = toCSSPrimitiveValue(inspector.second()); 453 if (first->isLength()) { 454 // <length>{2} 455 if (!second->isLength()) 456 return; 457 width = first->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)); 458 height = second->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)); 459 } else { 460 // <page-size> <orientation> 461 // The value order is guaranteed. See BisonCSSParser::parseSizeParameter. 462 if (!getPageSizeFromName(first, second, width, height)) 463 return; 464 } 465 pageSizeType = PAGE_SIZE_RESOLVED; 466 break; 467 } 468 case 1: { 469 // <length> | auto | <page-size> | [ portrait | landscape] 470 if (!inspector.first()->isPrimitiveValue()) 471 return; 472 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inspector.first()); 473 if (primitiveValue->isLength()) { 474 // <length> 475 pageSizeType = PAGE_SIZE_RESOLVED; 476 width = height = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)); 477 } else { 478 switch (primitiveValue->getValueID()) { 479 case 0: 480 return; 481 case CSSValueAuto: 482 pageSizeType = PAGE_SIZE_AUTO; 483 break; 484 case CSSValuePortrait: 485 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT; 486 break; 487 case CSSValueLandscape: 488 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE; 489 break; 490 default: 491 // <page-size> 492 pageSizeType = PAGE_SIZE_RESOLVED; 493 if (!getPageSizeFromName(primitiveValue, 0, width, height)) 494 return; 495 } 496 } 497 break; 498 } 499 default: 500 return; 501 } 502 state.style()->setPageSizeType(pageSizeType); 503 state.style()->setPageSize(LengthSize(width, height)); 504} 505 506void StyleBuilderFunctions::applyValueCSSPropertyTextAlign(StyleResolverState& state, CSSValue* value) 507{ 508 if (!value->isPrimitiveValue()) 509 return; 510 511 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 512 // FIXME : Per http://www.w3.org/TR/css3-text/#text-align0 can now take <string> but this is not implemented in the 513 // rendering code. 514 if (primitiveValue->isString()) 515 return; 516 517 if (primitiveValue->isValueID() && primitiveValue->getValueID() != CSSValueWebkitMatchParent) 518 state.style()->setTextAlign(*primitiveValue); 519 else if (state.parentStyle()->textAlign() == TASTART) 520 state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? LEFT : RIGHT); 521 else if (state.parentStyle()->textAlign() == TAEND) 522 state.style()->setTextAlign(state.parentStyle()->isLeftToRightDirection() ? RIGHT : LEFT); 523 else 524 state.style()->setTextAlign(state.parentStyle()->textAlign()); 525} 526 527void StyleBuilderFunctions::applyInheritCSSPropertyTextIndent(StyleResolverState& state) 528{ 529 state.style()->setTextIndent(state.parentStyle()->textIndent()); 530 state.style()->setTextIndentLine(state.parentStyle()->textIndentLine()); 531 state.style()->setTextIndentType(state.parentStyle()->textIndentType()); 532} 533 534void StyleBuilderFunctions::applyInitialCSSPropertyTextIndent(StyleResolverState& state) 535{ 536 state.style()->setTextIndent(RenderStyle::initialTextIndent()); 537 state.style()->setTextIndentLine(RenderStyle::initialTextIndentLine()); 538 state.style()->setTextIndentType(RenderStyle::initialTextIndentType()); 539} 540 541void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(StyleResolverState& state, CSSValue* value) 542{ 543 if (!value->isValueList()) 544 return; 545 546 Length lengthOrPercentageValue; 547 TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine(); 548 TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType(); 549 550 for (CSSValueListIterator i(value); i.hasMore(); i.advance()) { 551 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value()); 552 if (!primitiveValue->getValueID()) 553 lengthOrPercentageValue = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()); 554 else if (primitiveValue->getValueID() == CSSValueEachLine) 555 textIndentLineValue = TextIndentEachLine; 556 else if (primitiveValue->getValueID() == CSSValueHanging) 557 textIndentTypeValue = TextIndentHanging; 558 else 559 ASSERT_NOT_REACHED(); 560 } 561 562 state.style()->setTextIndent(lengthOrPercentageValue); 563 state.style()->setTextIndentLine(textIndentLineValue); 564 state.style()->setTextIndentType(textIndentTypeValue); 565} 566 567void StyleBuilderFunctions::applyValueCSSPropertyTransform(StyleResolverState& state, CSSValue* value) 568{ 569 TransformOperations operations; 570 TransformBuilder::createTransformOperations(value, state.cssToLengthConversionData(), operations); 571 state.style()->setTransform(operations); 572} 573 574void StyleBuilderFunctions::applyInitialCSSPropertyTransformOrigin(StyleResolverState& state) 575{ 576 applyInitialCSSPropertyWebkitTransformOriginX(state); 577 applyInitialCSSPropertyWebkitTransformOriginY(state); 578 applyInitialCSSPropertyWebkitTransformOriginZ(state); 579} 580 581void StyleBuilderFunctions::applyInheritCSSPropertyTransformOrigin(StyleResolverState& state) 582{ 583 applyInheritCSSPropertyWebkitTransformOriginX(state); 584 applyInheritCSSPropertyWebkitTransformOriginY(state); 585 applyInheritCSSPropertyWebkitTransformOriginZ(state); 586} 587 588void StyleBuilderFunctions::applyValueCSSPropertyTransformOrigin(StyleResolverState& state, CSSValue* value) 589{ 590 CSSValueList* list = toCSSValueList(value); 591 ASSERT(list->length() == 3); 592 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0)); 593 if (primitiveValue->isValueID()) { 594 switch (primitiveValue->getValueID()) { 595 case CSSValueLeft: 596 state.style()->setTransformOriginX(Length(0, Percent)); 597 break; 598 case CSSValueRight: 599 state.style()->setTransformOriginX(Length(100, Percent)); 600 break; 601 case CSSValueCenter: 602 state.style()->setTransformOriginX(Length(50, Percent)); 603 break; 604 default: 605 ASSERT_NOT_REACHED(); 606 } 607 } else { 608 state.style()->setTransformOriginX(StyleBuilderConverter::convertLength(state, primitiveValue)); 609 } 610 611 primitiveValue = toCSSPrimitiveValue(list->item(1)); 612 if (primitiveValue->isValueID()) { 613 switch (primitiveValue->getValueID()) { 614 case CSSValueTop: 615 state.style()->setTransformOriginY(Length(0, Percent)); 616 break; 617 case CSSValueBottom: 618 state.style()->setTransformOriginY(Length(100, Percent)); 619 break; 620 case CSSValueCenter: 621 state.style()->setTransformOriginY(Length(50, Percent)); 622 break; 623 default: 624 ASSERT_NOT_REACHED(); 625 } 626 } else { 627 state.style()->setTransformOriginY(StyleBuilderConverter::convertLength(state, primitiveValue)); 628 } 629 630 primitiveValue = toCSSPrimitiveValue(list->item(2)); 631 state.style()->setTransformOriginZ(StyleBuilderConverter::convertComputedLength<float>(state, primitiveValue)); 632} 633 634void StyleBuilderFunctions::applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState& state) 635{ 636 applyInitialCSSPropertyWebkitPerspectiveOriginX(state); 637 applyInitialCSSPropertyWebkitPerspectiveOriginY(state); 638} 639 640void StyleBuilderFunctions::applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState& state) 641{ 642 applyInheritCSSPropertyWebkitPerspectiveOriginX(state); 643 applyInheritCSSPropertyWebkitPerspectiveOriginY(state); 644} 645 646void StyleBuilderFunctions::applyValueCSSPropertyPerspectiveOrigin(StyleResolverState& state, CSSValue* value) 647{ 648 CSSValueList* list = toCSSValueList(value); 649 ASSERT(list->length() == 2); 650 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0)); 651 if (primitiveValue->isValueID()) { 652 switch (primitiveValue->getValueID()) { 653 case CSSValueLeft: 654 state.style()->setPerspectiveOriginX(Length(0, Percent)); 655 break; 656 case CSSValueRight: 657 state.style()->setPerspectiveOriginX(Length(100, Percent)); 658 break; 659 case CSSValueCenter: 660 state.style()->setPerspectiveOriginX(Length(50, Percent)); 661 break; 662 default: 663 ASSERT_NOT_REACHED(); 664 } 665 } else { 666 state.style()->setPerspectiveOriginX(StyleBuilderConverter::convertLength(state, primitiveValue)); 667 } 668 669 primitiveValue = toCSSPrimitiveValue(list->item(1)); 670 if (primitiveValue->isValueID()) { 671 switch (primitiveValue->getValueID()) { 672 case CSSValueTop: 673 state.style()->setPerspectiveOriginY(Length(0, Percent)); 674 break; 675 case CSSValueBottom: 676 state.style()->setPerspectiveOriginY(Length(100, Percent)); 677 break; 678 case CSSValueCenter: 679 state.style()->setPerspectiveOriginY(Length(50, Percent)); 680 break; 681 default: 682 ASSERT_NOT_REACHED(); 683 } 684 } else { 685 state.style()->setPerspectiveOriginY(StyleBuilderConverter::convertLength(state, primitiveValue)); 686 } 687} 688 689void StyleBuilderFunctions::applyInheritCSSPropertyVerticalAlign(StyleResolverState& state) 690{ 691 EVerticalAlign verticalAlign = state.parentStyle()->verticalAlign(); 692 state.style()->setVerticalAlign(verticalAlign); 693 if (verticalAlign == LENGTH) 694 state.style()->setVerticalAlignLength(state.parentStyle()->verticalAlignLength()); 695} 696 697void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverState& state, CSSValue* value) 698{ 699 if (!value->isPrimitiveValue()) 700 return; 701 702 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 703 704 if (primitiveValue->getValueID()) { 705 state.style()->setVerticalAlign(*primitiveValue); 706 return; 707 } 708 709 state.style()->setVerticalAlignLength(primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData())); 710} 711 712static void resetEffectiveZoom(StyleResolverState& state) 713{ 714 // Reset the zoom in effect. This allows the setZoom method to accurately compute a new zoom in effect. 715 state.setEffectiveZoom(state.parentStyle() ? state.parentStyle()->effectiveZoom() : RenderStyle::initialZoom()); 716} 717 718void StyleBuilderFunctions::applyInitialCSSPropertyZoom(StyleResolverState& state) 719{ 720 resetEffectiveZoom(state); 721 state.setZoom(RenderStyle::initialZoom()); 722} 723 724void StyleBuilderFunctions::applyInheritCSSPropertyZoom(StyleResolverState& state) 725{ 726 resetEffectiveZoom(state); 727 state.setZoom(state.parentStyle()->zoom()); 728} 729 730void StyleBuilderFunctions::applyValueCSSPropertyZoom(StyleResolverState& state, CSSValue* value) 731{ 732 ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue()); 733 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 734 735 if (primitiveValue->getValueID() == CSSValueNormal) { 736 resetEffectiveZoom(state); 737 state.setZoom(RenderStyle::initialZoom()); 738 } else if (primitiveValue->getValueID() == CSSValueReset) { 739 state.setEffectiveZoom(RenderStyle::initialZoom()); 740 state.setZoom(RenderStyle::initialZoom()); 741 } else if (primitiveValue->getValueID() == CSSValueDocument) { 742 float docZoom = state.rootElementStyle() ? state.rootElementStyle()->zoom() : RenderStyle::initialZoom(); 743 state.setEffectiveZoom(docZoom); 744 state.setZoom(docZoom); 745 } else if (primitiveValue->isPercentage()) { 746 resetEffectiveZoom(state); 747 if (float percent = primitiveValue->getFloatValue()) 748 state.setZoom(percent / 100.0f); 749 } else if (primitiveValue->isNumber()) { 750 resetEffectiveZoom(state); 751 if (float number = primitiveValue->getFloatValue()) 752 state.setZoom(number); 753 } 754} 755 756void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAspectRatio(StyleResolverState& state) 757{ 758 state.style()->setHasAspectRatio(RenderStyle::initialHasAspectRatio()); 759 state.style()->setAspectRatioDenominator(RenderStyle::initialAspectRatioDenominator()); 760 state.style()->setAspectRatioNumerator(RenderStyle::initialAspectRatioNumerator()); 761} 762 763void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAspectRatio(StyleResolverState& state) 764{ 765 if (!state.parentStyle()->hasAspectRatio()) 766 return; 767 state.style()->setHasAspectRatio(true); 768 state.style()->setAspectRatioDenominator(state.parentStyle()->aspectRatioDenominator()); 769 state.style()->setAspectRatioNumerator(state.parentStyle()->aspectRatioNumerator()); 770} 771 772void StyleBuilderFunctions::applyValueCSSPropertyWebkitAspectRatio(StyleResolverState& state, CSSValue* value) 773{ 774 if (!value->isAspectRatioValue()) { 775 state.style()->setHasAspectRatio(false); 776 return; 777 } 778 CSSAspectRatioValue* aspectRatioValue = toCSSAspectRatioValue(value); 779 state.style()->setHasAspectRatio(true); 780 state.style()->setAspectRatioDenominator(aspectRatioValue->denominatorValue()); 781 state.style()->setAspectRatioNumerator(aspectRatioValue->numeratorValue()); 782} 783 784void StyleBuilderFunctions::applyValueCSSPropertyWebkitBorderImage(StyleResolverState& state, CSSValue* value) 785{ 786 NinePieceImage image; 787 state.styleMap().mapNinePieceImage(state.style(), CSSPropertyWebkitBorderImage, value, image); 788 state.style()->setBorderImage(image); 789} 790 791void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverState& state, CSSValue* value) 792{ 793 if (value->isPrimitiveValue()) { 794 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 795 if (primitiveValue->getValueID() == CSSValueNone) { 796 state.style()->setClipPath(nullptr); 797 } else if (primitiveValue->isShape()) { 798 state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, primitiveValue->getShapeValue()))); 799 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_URI) { 800 String cssURLValue = primitiveValue->getStringValue(); 801 KURL url = state.document().completeURL(cssURLValue); 802 // FIXME: It doesn't work with forward or external SVG references (see https://bugs.webkit.org/show_bug.cgi?id=90405) 803 state.style()->setClipPath(ReferenceClipPathOperation::create(cssURLValue, AtomicString(url.fragmentIdentifier()))); 804 } 805 } 806} 807 808void StyleBuilderFunctions::applyValueCSSPropertyWebkitFilter(StyleResolverState& state, CSSValue* value) 809{ 810 FilterOperations operations; 811 if (FilterOperationResolver::createFilterOperations(value, state.cssToLengthConversionData(), operations, state)) 812 state.style()->setFilter(operations); 813} 814 815void StyleBuilderFunctions::applyInitialCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state) 816{ 817 state.style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill()); 818 state.style()->setTextEmphasisMark(RenderStyle::initialTextEmphasisMark()); 819 state.style()->setTextEmphasisCustomMark(RenderStyle::initialTextEmphasisCustomMark()); 820} 821 822void StyleBuilderFunctions::applyInheritCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state) 823{ 824 state.style()->setTextEmphasisFill(state.parentStyle()->textEmphasisFill()); 825 state.style()->setTextEmphasisMark(state.parentStyle()->textEmphasisMark()); 826 state.style()->setTextEmphasisCustomMark(state.parentStyle()->textEmphasisCustomMark()); 827} 828 829void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state, CSSValue* value) 830{ 831 if (value->isValueList()) { 832 CSSValueList* list = toCSSValueList(value); 833 ASSERT(list->length() == 2); 834 if (list->length() != 2) 835 return; 836 for (unsigned i = 0; i < 2; ++i) { 837 CSSValue* item = list->item(i); 838 if (!item->isPrimitiveValue()) 839 continue; 840 841 CSSPrimitiveValue* value = toCSSPrimitiveValue(item); 842 if (value->getValueID() == CSSValueFilled || value->getValueID() == CSSValueOpen) 843 state.style()->setTextEmphasisFill(*value); 844 else 845 state.style()->setTextEmphasisMark(*value); 846 } 847 state.style()->setTextEmphasisCustomMark(nullAtom); 848 return; 849 } 850 851 if (!value->isPrimitiveValue()) 852 return; 853 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 854 855 if (primitiveValue->isString()) { 856 state.style()->setTextEmphasisFill(TextEmphasisFillFilled); 857 state.style()->setTextEmphasisMark(TextEmphasisMarkCustom); 858 state.style()->setTextEmphasisCustomMark(AtomicString(primitiveValue->getStringValue())); 859 return; 860 } 861 862 state.style()->setTextEmphasisCustomMark(nullAtom); 863 864 if (primitiveValue->getValueID() == CSSValueFilled || primitiveValue->getValueID() == CSSValueOpen) { 865 state.style()->setTextEmphasisFill(*primitiveValue); 866 state.style()->setTextEmphasisMark(TextEmphasisMarkAuto); 867 } else { 868 state.style()->setTextEmphasisFill(TextEmphasisFillFilled); 869 state.style()->setTextEmphasisMark(*primitiveValue); 870 } 871} 872 873void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState& state) 874{ 875 state.style()->setWillChangeContents(false); 876 state.style()->setWillChangeScrollPosition(false); 877 state.style()->setWillChangeProperties(Vector<CSSPropertyID>()); 878 state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents()); 879} 880 881void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state) 882{ 883 state.style()->setWillChangeContents(state.parentStyle()->willChangeContents()); 884 state.style()->setWillChangeScrollPosition(state.parentStyle()->willChangeScrollPosition()); 885 state.style()->setWillChangeProperties(state.parentStyle()->willChangeProperties()); 886 state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents()); 887} 888 889void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value) 890{ 891 ASSERT(value->isValueList()); 892 bool willChangeContents = false; 893 bool willChangeScrollPosition = false; 894 Vector<CSSPropertyID> willChangeProperties; 895 896 for (CSSValueListIterator i(value); i.hasMore(); i.advance()) { 897 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value()); 898 if (CSSPropertyID propertyID = primitiveValue->getPropertyID()) 899 willChangeProperties.append(propertyID); 900 else if (primitiveValue->getValueID() == CSSValueContents) 901 willChangeContents = true; 902 else if (primitiveValue->getValueID() == CSSValueScrollPosition) 903 willChangeScrollPosition = true; 904 else 905 ASSERT_NOT_REACHED(); 906 } 907 state.style()->setWillChangeContents(willChangeContents); 908 state.style()->setWillChangeScrollPosition(willChangeScrollPosition); 909 state.style()->setWillChangeProperties(willChangeProperties); 910 state.style()->setSubtreeWillChangeContents(willChangeContents || state.parentStyle()->subtreeWillChangeContents()); 911} 912 913void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state) 914{ 915 state.style()->clearContent(); 916} 917 918void StyleBuilderFunctions::applyInheritCSSPropertyContent(StyleResolverState&) 919{ 920 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This 921 // note is a reminder that eventually "inherit" needs to be supported. 922} 923 924void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value) 925{ 926 // list of string, uri, counter, attr, i 927 928 if (!value->isValueList()) 929 return; 930 931 bool didSet = false; 932 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { 933 CSSValue* item = i.value(); 934 if (item->isImageGeneratorValue()) { 935 if (item->isGradientValue()) 936 state.style()->setContent(StyleGeneratedImage::create(toCSSGradientValue(item)->gradientWithStylesResolved(state.document().textLinkColors(), state.style()->color()).get()), didSet); 937 else 938 state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item)), didSet); 939 didSet = true; 940 } else if (item->isImageSetValue()) { 941 state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet); 942 didSet = true; 943 } 944 945 if (item->isImageValue()) { 946 state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item)), didSet); 947 didSet = true; 948 continue; 949 } 950 951 if (!item->isPrimitiveValue()) 952 continue; 953 954 CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item); 955 956 if (contentValue->isString()) { 957 state.style()->setContent(contentValue->getStringValue().impl(), didSet); 958 didSet = true; 959 } else if (contentValue->isAttr()) { 960 // FIXME: Can a namespace be specified for an attr(foo)? 961 if (state.style()->styleType() == NOPSEUDO) 962 state.style()->setUnique(); 963 else 964 state.parentStyle()->setUnique(); 965 QualifiedName attr(nullAtom, AtomicString(contentValue->getStringValue()), nullAtom); 966 const AtomicString& value = state.element()->getAttribute(attr); 967 state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet); 968 didSet = true; 969 // register the fact that the attribute value affects the style 970 state.contentAttrValues().append(attr.localName()); 971 } else if (contentValue->isCounter()) { 972 Counter* counterValue = contentValue->getCounterValue(); 973 EListStyleType listStyleType = NoneListStyle; 974 CSSValueID listStyleIdent = counterValue->listStyleIdent(); 975 if (listStyleIdent != CSSValueNone) 976 listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc); 977 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(AtomicString(counterValue->identifier()), listStyleType, AtomicString(counterValue->separator()))); 978 state.style()->setContent(counter.release(), didSet); 979 didSet = true; 980 } else { 981 switch (contentValue->getValueID()) { 982 case CSSValueOpenQuote: 983 state.style()->setContent(OPEN_QUOTE, didSet); 984 didSet = true; 985 break; 986 case CSSValueCloseQuote: 987 state.style()->setContent(CLOSE_QUOTE, didSet); 988 didSet = true; 989 break; 990 case CSSValueNoOpenQuote: 991 state.style()->setContent(NO_OPEN_QUOTE, didSet); 992 didSet = true; 993 break; 994 case CSSValueNoCloseQuote: 995 state.style()->setContent(NO_CLOSE_QUOTE, didSet); 996 didSet = true; 997 break; 998 default: 999 // normal and none do not have any effect. 1000 { } 1001 } 1002 } 1003 } 1004 if (!didSet) 1005 state.style()->clearContent(); 1006} 1007 1008void StyleBuilderFunctions::applyInitialCSSPropertyFont(StyleResolverState&) 1009{ 1010 ASSERT_NOT_REACHED(); 1011} 1012 1013void StyleBuilderFunctions::applyInheritCSSPropertyFont(StyleResolverState&) 1014{ 1015 ASSERT_NOT_REACHED(); 1016} 1017 1018void StyleBuilderFunctions::applyValueCSSPropertyFont(StyleResolverState& state, CSSValue* value) 1019{ 1020 // Only System Font identifiers should come through this method 1021 // all other values should have been handled when the shorthand 1022 // was expanded by the parser. 1023 // FIXME: System Font identifiers should not hijack this 1024 // short-hand CSSProperty like this (crbug.com/353932) 1025 state.style()->setLineHeight(RenderStyle::initialLineHeight()); 1026 state.setLineHeightValue(0); 1027 state.fontBuilder().fromSystemFont(toCSSPrimitiveValue(value)->getValueID(), state.style()->effectiveZoom()); 1028} 1029 1030void StyleBuilderFunctions::applyValueCSSPropertyWebkitLocale(StyleResolverState& state, CSSValue* value) 1031{ 1032 if (!value->isPrimitiveValue()) 1033 return; 1034 const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 1035 if (primitiveValue->getValueID() == CSSValueAuto) 1036 state.style()->setLocale(nullAtom); 1037 else 1038 state.style()->setLocale(AtomicString(primitiveValue->getStringValue())); 1039 state.fontBuilder().setScript(state.style()->locale()); 1040} 1041 1042void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&) 1043{ 1044} 1045 1046void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&) 1047{ 1048} 1049 1050void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(StyleResolverState& state, CSSValue* value) 1051{ 1052 if (!value->isPrimitiveValue()) 1053 return; 1054 const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 1055 if (!primitiveValue->getValueID()) 1056 return; 1057 state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag); 1058 state.document().setHasAnnotatedRegions(true); 1059} 1060 1061void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspective(StyleResolverState& state) 1062{ 1063 applyInitialCSSPropertyPerspective(state); 1064} 1065 1066void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspective(StyleResolverState& state) 1067{ 1068 applyInheritCSSPropertyPerspective(state); 1069} 1070 1071void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspective(StyleResolverState& state, CSSValue* value) 1072{ 1073 if (!value->isPrimitiveValue()) 1074 return; 1075 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 1076 if (primitiveValue->isNumber()) { 1077 float perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.cssToLengthConversionData()); 1078 if (perspectiveValue >= 0.0f) 1079 state.style()->setPerspective(perspectiveValue); 1080 } else { 1081 applyValueCSSPropertyPerspective(state, value); 1082 } 1083} 1084 1085void StyleBuilderFunctions::applyValueCSSPropertyPerspective(StyleResolverState& state, CSSValue* value) 1086{ 1087 if (!value->isPrimitiveValue()) 1088 return; 1089 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 1090 if (primitiveValue->getValueID() == CSSValueNone) { 1091 state.style()->setPerspective(0); 1092 return; 1093 } 1094 1095 if (!primitiveValue->isLength()) 1096 return; 1097 float perspectiveValue = primitiveValue->computeLength<float>(state.cssToLengthConversionData()); 1098 if (perspectiveValue >= 0.0f) 1099 state.style()->setPerspective(perspectiveValue); 1100} 1101 1102void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(StyleResolverState& state, CSSValue* value) 1103{ 1104 if (value->isPrimitiveValue()) 1105 state.setWritingMode(*toCSSPrimitiveValue(value)); 1106 1107 // FIXME: It is not ok to modify document state while applying style. 1108 if (state.element() && state.element() == state.document().documentElement()) 1109 state.document().setWritingModeSetOnDocumentElement(true); 1110} 1111 1112void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value) 1113{ 1114 if (value->isPrimitiveValue()) 1115 state.setTextOrientation(*toCSSPrimitiveValue(value)); 1116} 1117 1118void StyleBuilderFunctions::applyInheritCSSPropertyBaselineShift(StyleResolverState& state) 1119{ 1120 const SVGRenderStyle& parentSvgStyle = state.parentStyle()->svgStyle(); 1121 EBaselineShift baselineShift = parentSvgStyle.baselineShift(); 1122 SVGRenderStyle& svgStyle = state.style()->accessSVGStyle(); 1123 svgStyle.setBaselineShift(baselineShift); 1124 if (baselineShift == BS_LENGTH) 1125 svgStyle.setBaselineShiftValue(parentSvgStyle.baselineShiftValue()); 1126} 1127 1128void StyleBuilderFunctions::applyValueCSSPropertyBaselineShift(StyleResolverState& state, CSSValue* value) 1129{ 1130 SVGRenderStyle& svgStyle = state.style()->accessSVGStyle(); 1131 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 1132 if (!primitiveValue->isValueID()) { 1133 svgStyle.setBaselineShift(BS_LENGTH); 1134 svgStyle.setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue)); 1135 return; 1136 } 1137 switch (primitiveValue->getValueID()) { 1138 case CSSValueBaseline: 1139 svgStyle.setBaselineShift(BS_BASELINE); 1140 return; 1141 case CSSValueSub: 1142 svgStyle.setBaselineShift(BS_SUB); 1143 return; 1144 case CSSValueSuper: 1145 svgStyle.setBaselineShift(BS_SUPER); 1146 return; 1147 default: 1148 ASSERT_NOT_REACHED(); 1149 } 1150} 1151 1152void StyleBuilderFunctions::applyValueCSSPropertyGridAutoFlow(StyleResolverState& state, CSSValue* value) 1153{ 1154 ASSERT(value->isValueList()); 1155 CSSValueList* list = toCSSValueList(value); 1156 1157 CSSPrimitiveValue* first = list->length() >= 1 ? toCSSPrimitiveValue(list->item(0)) : nullptr; 1158 1159 if (!first) { 1160 applyInitialCSSPropertyGridAutoFlow(state); 1161 return; 1162 } 1163 1164 CSSPrimitiveValue* second = list->length() == 2 ? toCSSPrimitiveValue(list->item(1)) : nullptr; 1165 1166 GridAutoFlow autoFlow = RenderStyle::initialGridAutoFlow(); 1167 switch (first->getValueID()) { 1168 case CSSValueRow: 1169 if (second) { 1170 if (second->getValueID() == CSSValueDense) 1171 autoFlow = AutoFlowRowDense; 1172 else 1173 autoFlow = AutoFlowStackRow; 1174 } else { 1175 autoFlow = AutoFlowRow; 1176 } 1177 break; 1178 case CSSValueColumn: 1179 if (second) { 1180 if (second->getValueID() == CSSValueDense) 1181 autoFlow = AutoFlowColumnDense; 1182 else 1183 autoFlow = AutoFlowStackColumn; 1184 } else { 1185 autoFlow = AutoFlowColumn; 1186 } 1187 break; 1188 case CSSValueDense: 1189 if (second && second->getValueID() == CSSValueColumn) 1190 autoFlow = AutoFlowColumnDense; 1191 else 1192 autoFlow = AutoFlowRowDense; 1193 break; 1194 case CSSValueStack: 1195 if (second && second->getValueID() == CSSValueColumn) 1196 autoFlow = AutoFlowStackColumn; 1197 else 1198 autoFlow = AutoFlowStackRow; 1199 break; 1200 default: 1201 ASSERT_NOT_REACHED(); 1202 break; 1203 } 1204 1205 state.style()->setGridAutoFlow(autoFlow); 1206} 1207 1208} // namespace blink 1209