1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 6 * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org> 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 11 * 12 * This library is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU Library General Public 14 * License as published by the Free Software Foundation; either 15 * version 2 of the License, or (at your option) any later version. 16 * 17 * This library is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * Library General Public License for more details. 21 * 22 * You should have received a copy of the GNU Library General Public License 23 * along with this library; see the file COPYING.LIB. If not, write to 24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 25 * Boston, MA 02110-1301, USA. 26 */ 27 28 #include "config.h" 29 #include "core/css/CSSToStyleMap.h" 30 31 #include "CSSValueKeywords.h" 32 #include "core/css/CSSBorderImageSliceValue.h" 33 #include "core/css/CSSPrimitiveValue.h" 34 #include "core/css/CSSPrimitiveValueMappings.h" 35 #include "core/css/CSSTimingFunctionValue.h" 36 #include "core/css/Pair.h" 37 #include "core/css/Rect.h" 38 #include "core/css/resolver/StyleResolverState.h" 39 #include "core/platform/animation/CSSAnimationData.h" 40 #include "core/rendering/style/FillLayer.h" 41 42 namespace WebCore { 43 44 const RenderStyle* CSSToStyleMap::style() const 45 { 46 return m_state.style(); 47 } 48 49 const RenderStyle* CSSToStyleMap::rootElementStyle() const 50 { 51 return m_state.rootElementStyle(); 52 } 53 54 bool CSSToStyleMap::useSVGZoomRules() const 55 { 56 return m_state.useSVGZoomRules(); 57 } 58 59 PassRefPtr<StyleImage> CSSToStyleMap::styleImage(CSSPropertyID propertyId, CSSValue* value) 60 { 61 return m_elementStyleResources.styleImage(m_state.document()->textLinkColors(), propertyId, value); 62 } 63 64 void CSSToStyleMap::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value) const 65 { 66 if (value->isInitialValue()) { 67 layer->setAttachment(FillLayer::initialFillAttachment(layer->type())); 68 return; 69 } 70 71 if (!value->isPrimitiveValue()) 72 return; 73 74 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 75 switch (primitiveValue->getValueID()) { 76 case CSSValueFixed: 77 layer->setAttachment(FixedBackgroundAttachment); 78 break; 79 case CSSValueScroll: 80 layer->setAttachment(ScrollBackgroundAttachment); 81 break; 82 case CSSValueLocal: 83 layer->setAttachment(LocalBackgroundAttachment); 84 break; 85 default: 86 return; 87 } 88 } 89 90 void CSSToStyleMap::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value) const 91 { 92 if (value->isInitialValue()) { 93 layer->setClip(FillLayer::initialFillClip(layer->type())); 94 return; 95 } 96 97 if (!value->isPrimitiveValue()) 98 return; 99 100 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 101 layer->setClip(*primitiveValue); 102 } 103 104 void CSSToStyleMap::mapFillComposite(CSSPropertyID, FillLayer* layer, CSSValue* value) const 105 { 106 if (value->isInitialValue()) { 107 layer->setComposite(FillLayer::initialFillComposite(layer->type())); 108 return; 109 } 110 111 if (!value->isPrimitiveValue()) 112 return; 113 114 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 115 layer->setComposite(*primitiveValue); 116 } 117 118 void CSSToStyleMap::mapFillBlendMode(CSSPropertyID, FillLayer* layer, CSSValue* value) const 119 { 120 if (value->isInitialValue()) { 121 layer->setBlendMode(FillLayer::initialFillBlendMode(layer->type())); 122 return; 123 } 124 125 if (!value->isPrimitiveValue()) 126 return; 127 128 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 129 layer->setBlendMode(*primitiveValue); 130 } 131 132 void CSSToStyleMap::mapFillOrigin(CSSPropertyID, FillLayer* layer, CSSValue* value) const 133 { 134 if (value->isInitialValue()) { 135 layer->setOrigin(FillLayer::initialFillOrigin(layer->type())); 136 return; 137 } 138 139 if (!value->isPrimitiveValue()) 140 return; 141 142 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 143 layer->setOrigin(*primitiveValue); 144 } 145 146 147 void CSSToStyleMap::mapFillImage(CSSPropertyID property, FillLayer* layer, CSSValue* value) 148 { 149 if (value->isInitialValue()) { 150 layer->setImage(FillLayer::initialFillImage(layer->type())); 151 return; 152 } 153 154 layer->setImage(styleImage(property, value)); 155 } 156 157 void CSSToStyleMap::mapFillRepeatX(CSSPropertyID, FillLayer* layer, CSSValue* value) const 158 { 159 if (value->isInitialValue()) { 160 layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type())); 161 return; 162 } 163 164 if (!value->isPrimitiveValue()) 165 return; 166 167 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 168 layer->setRepeatX(*primitiveValue); 169 } 170 171 void CSSToStyleMap::mapFillRepeatY(CSSPropertyID, FillLayer* layer, CSSValue* value) const 172 { 173 if (value->isInitialValue()) { 174 layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type())); 175 return; 176 } 177 178 if (!value->isPrimitiveValue()) 179 return; 180 181 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 182 layer->setRepeatY(*primitiveValue); 183 } 184 185 void CSSToStyleMap::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value) const 186 { 187 if (!value->isPrimitiveValue()) { 188 layer->setSizeType(SizeNone); 189 return; 190 } 191 192 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 193 if (primitiveValue->getValueID() == CSSValueContain) 194 layer->setSizeType(Contain); 195 else if (primitiveValue->getValueID() == CSSValueCover) 196 layer->setSizeType(Cover); 197 else 198 layer->setSizeType(SizeLength); 199 200 LengthSize b = FillLayer::initialFillSizeLength(layer->type()); 201 202 if (value->isInitialValue() || primitiveValue->getValueID() == CSSValueContain || primitiveValue->getValueID() == CSSValueCover) { 203 layer->setSizeLength(b); 204 return; 205 } 206 207 float zoomFactor = style()->effectiveZoom(); 208 209 Length firstLength; 210 Length secondLength; 211 212 if (Pair* pair = primitiveValue->getPairValue()) { 213 firstLength = pair->first()->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor); 214 secondLength = pair->second()->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor); 215 } else { 216 firstLength = primitiveValue->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor); 217 secondLength = Length(); 218 } 219 220 if (firstLength.isUndefined() || secondLength.isUndefined()) 221 return; 222 223 b.setWidth(firstLength); 224 b.setHeight(secondLength); 225 layer->setSizeLength(b); 226 } 227 228 void CSSToStyleMap::mapFillXPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value) const 229 { 230 if (value->isInitialValue()) { 231 layer->setXPosition(FillLayer::initialFillXPosition(layer->type())); 232 return; 233 } 234 235 if (!value->isPrimitiveValue()) 236 return; 237 238 float zoomFactor = style()->effectiveZoom(); 239 240 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 241 Pair* pair = primitiveValue->getPairValue(); 242 if (pair) { 243 ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionX || propertyID == CSSPropertyWebkitMaskPositionX); 244 primitiveValue = pair->second(); 245 } 246 247 Length length; 248 if (primitiveValue->isLength()) 249 length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor); 250 else if (primitiveValue->isPercentage()) 251 length = Length(primitiveValue->getDoubleValue(), Percent); 252 else if (primitiveValue->isCalculatedPercentageWithLength()) 253 length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor)); 254 else if (primitiveValue->isViewportPercentageLength()) 255 length = primitiveValue->viewportPercentageLength(); 256 else 257 return; 258 259 layer->setXPosition(length); 260 if (pair) 261 layer->setBackgroundXOrigin(*(pair->first())); 262 } 263 264 void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value) const 265 { 266 if (value->isInitialValue()) { 267 layer->setYPosition(FillLayer::initialFillYPosition(layer->type())); 268 return; 269 } 270 271 if (!value->isPrimitiveValue()) 272 return; 273 274 float zoomFactor = style()->effectiveZoom(); 275 276 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 277 Pair* pair = primitiveValue->getPairValue(); 278 if (pair) { 279 ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionY || propertyID == CSSPropertyWebkitMaskPositionY); 280 primitiveValue = pair->second(); 281 } 282 283 Length length; 284 if (primitiveValue->isLength()) 285 length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor); 286 else if (primitiveValue->isPercentage()) 287 length = Length(primitiveValue->getDoubleValue(), Percent); 288 else if (primitiveValue->isCalculatedPercentageWithLength()) 289 length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor)); 290 else if (primitiveValue->isViewportPercentageLength()) 291 length = primitiveValue->viewportPercentageLength(); 292 else 293 return; 294 295 layer->setYPosition(length); 296 if (pair) 297 layer->setBackgroundYOrigin(*(pair->first())); 298 } 299 300 void CSSToStyleMap::mapAnimationDelay(CSSAnimationData* animation, CSSValue* value) const 301 { 302 if (value->isInitialValue()) { 303 animation->setDelay(CSSAnimationData::initialAnimationDelay()); 304 return; 305 } 306 307 if (!value->isPrimitiveValue()) 308 return; 309 310 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 311 animation->setDelay(primitiveValue->computeTime<double, CSSPrimitiveValue::Seconds>()); 312 } 313 314 void CSSToStyleMap::mapAnimationDirection(CSSAnimationData* layer, CSSValue* value) const 315 { 316 if (value->isInitialValue()) { 317 layer->setDirection(CSSAnimationData::initialAnimationDirection()); 318 return; 319 } 320 321 if (!value->isPrimitiveValue()) 322 return; 323 324 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 325 switch (primitiveValue->getValueID()) { 326 case CSSValueNormal: 327 layer->setDirection(CSSAnimationData::AnimationDirectionNormal); 328 break; 329 case CSSValueAlternate: 330 layer->setDirection(CSSAnimationData::AnimationDirectionAlternate); 331 break; 332 case CSSValueReverse: 333 layer->setDirection(CSSAnimationData::AnimationDirectionReverse); 334 break; 335 case CSSValueAlternateReverse: 336 layer->setDirection(CSSAnimationData::AnimationDirectionAlternateReverse); 337 break; 338 default: 339 break; 340 } 341 } 342 343 void CSSToStyleMap::mapAnimationDuration(CSSAnimationData* animation, CSSValue* value) const 344 { 345 if (value->isInitialValue()) { 346 animation->setDuration(CSSAnimationData::initialAnimationDuration()); 347 return; 348 } 349 350 if (!value->isPrimitiveValue()) 351 return; 352 353 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 354 animation->setDuration(primitiveValue->computeTime<double, CSSPrimitiveValue::Seconds>()); 355 } 356 357 void CSSToStyleMap::mapAnimationFillMode(CSSAnimationData* layer, CSSValue* value) const 358 { 359 if (value->isInitialValue()) { 360 layer->setFillMode(CSSAnimationData::initialAnimationFillMode()); 361 return; 362 } 363 364 if (!value->isPrimitiveValue()) 365 return; 366 367 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 368 switch (primitiveValue->getValueID()) { 369 case CSSValueNone: 370 layer->setFillMode(AnimationFillModeNone); 371 break; 372 case CSSValueForwards: 373 layer->setFillMode(AnimationFillModeForwards); 374 break; 375 case CSSValueBackwards: 376 layer->setFillMode(AnimationFillModeBackwards); 377 break; 378 case CSSValueBoth: 379 layer->setFillMode(AnimationFillModeBoth); 380 break; 381 default: 382 break; 383 } 384 } 385 386 void CSSToStyleMap::mapAnimationIterationCount(CSSAnimationData* animation, CSSValue* value) const 387 { 388 if (value->isInitialValue()) { 389 animation->setIterationCount(CSSAnimationData::initialAnimationIterationCount()); 390 return; 391 } 392 393 if (!value->isPrimitiveValue()) 394 return; 395 396 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 397 if (primitiveValue->getValueID() == CSSValueInfinite) 398 animation->setIterationCount(CSSAnimationData::IterationCountInfinite); 399 else 400 animation->setIterationCount(primitiveValue->getFloatValue()); 401 } 402 403 void CSSToStyleMap::mapAnimationName(CSSAnimationData* layer, CSSValue* value) const 404 { 405 if (value->isInitialValue()) { 406 layer->setName(CSSAnimationData::initialAnimationName()); 407 return; 408 } 409 410 if (!value->isPrimitiveValue()) 411 return; 412 413 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 414 if (primitiveValue->getValueID() == CSSValueNone) 415 layer->setIsNoneAnimation(true); 416 else 417 layer->setName(primitiveValue->getStringValue()); 418 } 419 420 void CSSToStyleMap::mapAnimationPlayState(CSSAnimationData* layer, CSSValue* value) const 421 { 422 if (value->isInitialValue()) { 423 layer->setPlayState(CSSAnimationData::initialAnimationPlayState()); 424 return; 425 } 426 427 if (!value->isPrimitiveValue()) 428 return; 429 430 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 431 EAnimPlayState playState = (primitiveValue->getValueID() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying; 432 layer->setPlayState(playState); 433 } 434 435 void CSSToStyleMap::mapAnimationProperty(CSSAnimationData* animation, CSSValue* value) const 436 { 437 if (value->isInitialValue()) { 438 animation->setAnimationMode(CSSAnimationData::AnimateAll); 439 animation->setProperty(CSSPropertyInvalid); 440 return; 441 } 442 443 if (!value->isPrimitiveValue()) 444 return; 445 446 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 447 if (primitiveValue->getValueID() == CSSValueAll) { 448 animation->setAnimationMode(CSSAnimationData::AnimateAll); 449 animation->setProperty(CSSPropertyInvalid); 450 } else if (primitiveValue->getValueID() == CSSValueNone) { 451 animation->setAnimationMode(CSSAnimationData::AnimateNone); 452 animation->setProperty(CSSPropertyInvalid); 453 } else { 454 animation->setAnimationMode(CSSAnimationData::AnimateSingleProperty); 455 animation->setProperty(primitiveValue->getPropertyID()); 456 } 457 } 458 459 void CSSToStyleMap::mapAnimationTimingFunction(CSSAnimationData* animation, CSSValue* value) const 460 { 461 if (value->isInitialValue()) { 462 animation->setTimingFunction(CSSAnimationData::initialAnimationTimingFunction()); 463 return; 464 } 465 466 if (value->isPrimitiveValue()) { 467 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 468 switch (primitiveValue->getValueID()) { 469 case CSSValueLinear: 470 animation->setTimingFunction(LinearTimingFunction::create()); 471 break; 472 case CSSValueEase: 473 animation->setTimingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease)); 474 break; 475 case CSSValueEaseIn: 476 animation->setTimingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseIn)); 477 break; 478 case CSSValueEaseOut: 479 animation->setTimingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseOut)); 480 break; 481 case CSSValueEaseInOut: 482 animation->setTimingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut)); 483 break; 484 case CSSValueStepStart: 485 animation->setTimingFunction(StepsTimingFunction::create(1, true)); 486 break; 487 case CSSValueStepEnd: 488 animation->setTimingFunction(StepsTimingFunction::create(1, false)); 489 break; 490 default: 491 break; 492 } 493 return; 494 } 495 496 if (value->isCubicBezierTimingFunctionValue()) { 497 CSSCubicBezierTimingFunctionValue* cubicTimingFunction = static_cast<CSSCubicBezierTimingFunctionValue*>(value); 498 animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2())); 499 } else if (value->isStepsTimingFunctionValue()) { 500 CSSStepsTimingFunctionValue* stepsTimingFunction = static_cast<CSSStepsTimingFunctionValue*>(value); 501 animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart())); 502 } else if (value->isLinearTimingFunctionValue()) 503 animation->setTimingFunction(LinearTimingFunction::create()); 504 } 505 506 void CSSToStyleMap::mapNinePieceImage(RenderStyle* mutableStyle, CSSPropertyID property, CSSValue* value, NinePieceImage& image) 507 { 508 // If we're not a value list, then we are "none" and don't need to alter the empty image at all. 509 if (!value || !value->isValueList()) 510 return; 511 512 // Retrieve the border image value. 513 CSSValueList* borderImage = toCSSValueList(value); 514 515 // Set the image (this kicks off the load). 516 CSSPropertyID imageProperty; 517 if (property == CSSPropertyWebkitBorderImage) 518 imageProperty = CSSPropertyBorderImageSource; 519 else if (property == CSSPropertyWebkitMaskBoxImage) 520 imageProperty = CSSPropertyWebkitMaskBoxImageSource; 521 else 522 imageProperty = property; 523 524 for (unsigned i = 0 ; i < borderImage->length() ; ++i) { 525 CSSValue* current = borderImage->item(i); 526 527 if (current->isImageValue() || current->isImageGeneratorValue() || current->isImageSetValue()) 528 image.setImage(styleImage(imageProperty, current)); 529 else if (current->isBorderImageSliceValue()) 530 mapNinePieceImageSlice(current, image); 531 else if (current->isValueList()) { 532 CSSValueList* slashList = toCSSValueList(current); 533 // Map in the image slices. 534 if (slashList->item(0) && slashList->item(0)->isBorderImageSliceValue()) 535 mapNinePieceImageSlice(slashList->item(0), image); 536 537 // Map in the border slices. 538 if (slashList->item(1)) 539 image.setBorderSlices(mapNinePieceImageQuad(slashList->item(1))); 540 541 // Map in the outset. 542 if (slashList->item(2)) 543 image.setOutset(mapNinePieceImageQuad(slashList->item(2))); 544 } else if (current->isPrimitiveValue()) { 545 // Set the appropriate rules for stretch/round/repeat of the slices. 546 mapNinePieceImageRepeat(current, image); 547 } 548 } 549 550 if (property == CSSPropertyWebkitBorderImage) { 551 // We have to preserve the legacy behavior of -webkit-border-image and make the border slices 552 // also set the border widths. We don't need to worry about percentages, since we don't even support 553 // those on real borders yet. 554 if (image.borderSlices().top().isFixed()) 555 mutableStyle->setBorderTopWidth(image.borderSlices().top().value()); 556 if (image.borderSlices().right().isFixed()) 557 mutableStyle->setBorderRightWidth(image.borderSlices().right().value()); 558 if (image.borderSlices().bottom().isFixed()) 559 mutableStyle->setBorderBottomWidth(image.borderSlices().bottom().value()); 560 if (image.borderSlices().left().isFixed()) 561 mutableStyle->setBorderLeftWidth(image.borderSlices().left().value()); 562 } 563 } 564 565 void CSSToStyleMap::mapNinePieceImageSlice(CSSValue* value, NinePieceImage& image) const 566 { 567 if (!value || !value->isBorderImageSliceValue()) 568 return; 569 570 // Retrieve the border image value. 571 CSSBorderImageSliceValue* borderImageSlice = static_cast<CSSBorderImageSliceValue*>(value); 572 573 // Set up a length box to represent our image slices. 574 LengthBox box; 575 Quad* slices = borderImageSlice->slices(); 576 if (slices->top()->isPercentage()) 577 box.m_top = Length(slices->top()->getDoubleValue(), Percent); 578 else 579 box.m_top = Length(slices->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); 580 if (slices->bottom()->isPercentage()) 581 box.m_bottom = Length(slices->bottom()->getDoubleValue(), Percent); 582 else 583 box.m_bottom = Length((int)slices->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); 584 if (slices->left()->isPercentage()) 585 box.m_left = Length(slices->left()->getDoubleValue(), Percent); 586 else 587 box.m_left = Length(slices->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); 588 if (slices->right()->isPercentage()) 589 box.m_right = Length(slices->right()->getDoubleValue(), Percent); 590 else 591 box.m_right = Length(slices->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); 592 image.setImageSlices(box); 593 594 // Set our fill mode. 595 image.setFill(borderImageSlice->m_fill); 596 } 597 598 LengthBox CSSToStyleMap::mapNinePieceImageQuad(CSSValue* value) const 599 { 600 if (!value || !value->isPrimitiveValue()) 601 return LengthBox(); 602 603 // Get our zoom value. 604 float zoom = useSVGZoomRules() ? 1.0f : style()->effectiveZoom(); 605 606 // Retrieve the primitive value. 607 CSSPrimitiveValue* borderWidths = toCSSPrimitiveValue(value); 608 609 // Set up a length box to represent our image slices. 610 LengthBox box; // Defaults to 'auto' so we don't have to handle that explicitly below. 611 Quad* slices = borderWidths->getQuadValue(); 612 if (slices->top()->isNumber()) 613 box.m_top = Length(slices->top()->getIntValue(), Relative); 614 else if (slices->top()->isPercentage()) 615 box.m_top = Length(slices->top()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); 616 else if (slices->top()->getValueID() != CSSValueAuto) 617 box.m_top = slices->top()->computeLength<Length>(style(), rootElementStyle(), zoom); 618 619 if (slices->right()->isNumber()) 620 box.m_right = Length(slices->right()->getIntValue(), Relative); 621 else if (slices->right()->isPercentage()) 622 box.m_right = Length(slices->right()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); 623 else if (slices->right()->getValueID() != CSSValueAuto) 624 box.m_right = slices->right()->computeLength<Length>(style(), rootElementStyle(), zoom); 625 626 if (slices->bottom()->isNumber()) 627 box.m_bottom = Length(slices->bottom()->getIntValue(), Relative); 628 else if (slices->bottom()->isPercentage()) 629 box.m_bottom = Length(slices->bottom()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); 630 else if (slices->bottom()->getValueID() != CSSValueAuto) 631 box.m_bottom = slices->bottom()->computeLength<Length>(style(), rootElementStyle(), zoom); 632 633 if (slices->left()->isNumber()) 634 box.m_left = Length(slices->left()->getIntValue(), Relative); 635 else if (slices->left()->isPercentage()) 636 box.m_left = Length(slices->left()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); 637 else if (slices->left()->getValueID() != CSSValueAuto) 638 box.m_left = slices->left()->computeLength<Length>(style(), rootElementStyle(), zoom); 639 640 return box; 641 } 642 643 void CSSToStyleMap::mapNinePieceImageRepeat(CSSValue* value, NinePieceImage& image) const 644 { 645 if (!value || !value->isPrimitiveValue()) 646 return; 647 648 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); 649 Pair* pair = primitiveValue->getPairValue(); 650 if (!pair || !pair->first() || !pair->second()) 651 return; 652 653 CSSValueID firstIdentifier = pair->first()->getValueID(); 654 CSSValueID secondIdentifier = pair->second()->getValueID(); 655 656 ENinePieceImageRule horizontalRule; 657 switch (firstIdentifier) { 658 case CSSValueStretch: 659 horizontalRule = StretchImageRule; 660 break; 661 case CSSValueRound: 662 horizontalRule = RoundImageRule; 663 break; 664 case CSSValueSpace: 665 horizontalRule = SpaceImageRule; 666 break; 667 default: // CSSValueRepeat 668 horizontalRule = RepeatImageRule; 669 break; 670 } 671 image.setHorizontalRule(horizontalRule); 672 673 ENinePieceImageRule verticalRule; 674 switch (secondIdentifier) { 675 case CSSValueStretch: 676 verticalRule = StretchImageRule; 677 break; 678 case CSSValueRound: 679 verticalRule = RoundImageRule; 680 break; 681 case CSSValueSpace: 682 verticalRule = SpaceImageRule; 683 break; 684 default: // CSSValueRepeat 685 verticalRule = RepeatImageRule; 686 break; 687 } 688 image.setVerticalRule(verticalRule); 689 } 690 691 }; 692