1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@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@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@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 "CSSToStyleMap.h" 30 31#include "Animation.h" 32#include "CSSBorderImageSliceValue.h" 33#include "CSSPrimitiveValue.h" 34#include "CSSPrimitiveValueMappings.h" 35#include "CSSTimingFunctionValue.h" 36#include "CSSValueKeywords.h" 37#include "FillLayer.h" 38#include "Pair.h" 39#include "Rect.h" 40#include "StyleResolver.h" 41 42namespace WebCore { 43 44RenderStyle* CSSToStyleMap::style() const 45{ 46 return m_resolver->style(); 47} 48 49RenderStyle* CSSToStyleMap::rootElementStyle() const 50{ 51 return m_resolver->rootElementStyle(); 52} 53 54bool CSSToStyleMap::useSVGZoomRules() const 55{ 56 return m_resolver->useSVGZoomRules(); 57} 58 59PassRefPtr<StyleImage> CSSToStyleMap::styleImage(CSSPropertyID propertyId, CSSValue* value) 60{ 61 return m_resolver->styleImage(propertyId, value); 62} 63 64void CSSToStyleMap::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value) 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 = static_cast<CSSPrimitiveValue*>(value); 75 switch (primitiveValue->getIdent()) { 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 90void CSSToStyleMap::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value) 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 = static_cast<CSSPrimitiveValue*>(value); 101 layer->setClip(*primitiveValue); 102} 103 104void CSSToStyleMap::mapFillComposite(CSSPropertyID, FillLayer* layer, CSSValue* value) 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 = static_cast<CSSPrimitiveValue*>(value); 115 layer->setComposite(*primitiveValue); 116} 117 118void CSSToStyleMap::mapFillBlendMode(CSSPropertyID, FillLayer* layer, CSSValue* value) 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 = static_cast<CSSPrimitiveValue*>(value); 129 layer->setBlendMode(*primitiveValue); 130} 131 132void CSSToStyleMap::mapFillOrigin(CSSPropertyID, FillLayer* layer, CSSValue* value) 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 = static_cast<CSSPrimitiveValue*>(value); 143 layer->setOrigin(*primitiveValue); 144} 145 146 147void 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 157void CSSToStyleMap::mapFillRepeatX(CSSPropertyID, FillLayer* layer, CSSValue* value) 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 = static_cast<CSSPrimitiveValue*>(value); 168 layer->setRepeatX(*primitiveValue); 169} 170 171void CSSToStyleMap::mapFillRepeatY(CSSPropertyID, FillLayer* layer, CSSValue* value) 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 = static_cast<CSSPrimitiveValue*>(value); 182 layer->setRepeatY(*primitiveValue); 183} 184 185void CSSToStyleMap::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value) 186{ 187 if (!value->isPrimitiveValue()) { 188 layer->setSizeType(SizeNone); 189 return; 190 } 191 192 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 193 if (primitiveValue->getIdent() == CSSValueContain) 194 layer->setSizeType(Contain); 195 else if (primitiveValue->getIdent() == 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->getIdent() == CSSValueContain || primitiveValue->getIdent() == 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 CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first()); 214 CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second()); 215 firstLength = first->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor); 216 secondLength = second->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor); 217 } else { 218 firstLength = primitiveValue->convertToLength<AnyConversion>(style(), rootElementStyle(), zoomFactor); 219 secondLength = Length(); 220 } 221 222 if (firstLength.isUndefined() || secondLength.isUndefined()) 223 return; 224 225 b.setWidth(firstLength); 226 b.setHeight(secondLength); 227 layer->setSizeLength(b); 228} 229 230void CSSToStyleMap::mapFillXPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value) 231{ 232 if (value->isInitialValue()) { 233 layer->setXPosition(FillLayer::initialFillXPosition(layer->type())); 234 return; 235 } 236 237 if (!value->isPrimitiveValue()) 238 return; 239 240 float zoomFactor = style()->effectiveZoom(); 241 242 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 243 Pair* pair = primitiveValue->getPairValue(); 244 if (pair) { 245 ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionX || propertyID == CSSPropertyWebkitMaskPositionX); 246 primitiveValue = pair->second(); 247 } 248 249 Length length; 250 if (primitiveValue->isLength()) 251 length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor); 252 else if (primitiveValue->isPercentage()) 253 length = Length(primitiveValue->getDoubleValue(), Percent); 254 else if (primitiveValue->isCalculatedPercentageWithLength()) 255 length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor)); 256 else if (primitiveValue->isViewportPercentageLength()) 257 length = primitiveValue->viewportPercentageLength(); 258 else 259 return; 260 261 layer->setXPosition(length); 262 if (pair) 263 layer->setBackgroundXOrigin(*(pair->first())); 264} 265 266void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value) 267{ 268 if (value->isInitialValue()) { 269 layer->setYPosition(FillLayer::initialFillYPosition(layer->type())); 270 return; 271 } 272 273 if (!value->isPrimitiveValue()) 274 return; 275 276 float zoomFactor = style()->effectiveZoom(); 277 278 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 279 Pair* pair = primitiveValue->getPairValue(); 280 if (pair) { 281 ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionY || propertyID == CSSPropertyWebkitMaskPositionY); 282 primitiveValue = pair->second(); 283 } 284 285 Length length; 286 if (primitiveValue->isLength()) 287 length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor); 288 else if (primitiveValue->isPercentage()) 289 length = Length(primitiveValue->getDoubleValue(), Percent); 290 else if (primitiveValue->isCalculatedPercentageWithLength()) 291 length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor)); 292 else if (primitiveValue->isViewportPercentageLength()) 293 length = primitiveValue->viewportPercentageLength(); 294 else 295 return; 296 297 layer->setYPosition(length); 298 if (pair) 299 layer->setBackgroundYOrigin(*(pair->first())); 300} 301 302void CSSToStyleMap::mapAnimationDelay(Animation* animation, CSSValue* value) 303{ 304 if (value->isInitialValue()) { 305 animation->setDelay(Animation::initialAnimationDelay()); 306 return; 307 } 308 309 if (!value->isPrimitiveValue()) 310 return; 311 312 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 313 animation->setDelay(primitiveValue->computeTime<double, CSSPrimitiveValue::Seconds>()); 314} 315 316void CSSToStyleMap::mapAnimationDirection(Animation* layer, CSSValue* value) 317{ 318 if (value->isInitialValue()) { 319 layer->setDirection(Animation::initialAnimationDirection()); 320 return; 321 } 322 323 if (!value->isPrimitiveValue()) 324 return; 325 326 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 327 switch (primitiveValue->getIdent()) { 328 case CSSValueNormal: 329 layer->setDirection(Animation::AnimationDirectionNormal); 330 break; 331 case CSSValueAlternate: 332 layer->setDirection(Animation::AnimationDirectionAlternate); 333 break; 334 case CSSValueReverse: 335 layer->setDirection(Animation::AnimationDirectionReverse); 336 break; 337 case CSSValueAlternateReverse: 338 layer->setDirection(Animation::AnimationDirectionAlternateReverse); 339 break; 340 } 341} 342 343void CSSToStyleMap::mapAnimationDuration(Animation* animation, CSSValue* value) 344{ 345 if (value->isInitialValue()) { 346 animation->setDuration(Animation::initialAnimationDuration()); 347 return; 348 } 349 350 if (!value->isPrimitiveValue()) 351 return; 352 353 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 354 animation->setDuration(primitiveValue->computeTime<double, CSSPrimitiveValue::Seconds>()); 355} 356 357void CSSToStyleMap::mapAnimationFillMode(Animation* layer, CSSValue* value) 358{ 359 if (value->isInitialValue()) { 360 layer->setFillMode(Animation::initialAnimationFillMode()); 361 return; 362 } 363 364 if (!value->isPrimitiveValue()) 365 return; 366 367 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 368 switch (primitiveValue->getIdent()) { 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 } 382} 383 384void CSSToStyleMap::mapAnimationIterationCount(Animation* animation, CSSValue* value) 385{ 386 if (value->isInitialValue()) { 387 animation->setIterationCount(Animation::initialAnimationIterationCount()); 388 return; 389 } 390 391 if (!value->isPrimitiveValue()) 392 return; 393 394 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 395 if (primitiveValue->getIdent() == CSSValueInfinite) 396 animation->setIterationCount(Animation::IterationCountInfinite); 397 else 398 animation->setIterationCount(primitiveValue->getFloatValue()); 399} 400 401void CSSToStyleMap::mapAnimationName(Animation* layer, CSSValue* value) 402{ 403 if (value->isInitialValue()) { 404 layer->setName(Animation::initialAnimationName()); 405 return; 406 } 407 408 if (!value->isPrimitiveValue()) 409 return; 410 411 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 412 if (primitiveValue->getIdent() == CSSValueNone) 413 layer->setIsNoneAnimation(true); 414 else 415 layer->setName(primitiveValue->getStringValue()); 416} 417 418void CSSToStyleMap::mapAnimationPlayState(Animation* layer, CSSValue* value) 419{ 420 if (value->isInitialValue()) { 421 layer->setPlayState(Animation::initialAnimationPlayState()); 422 return; 423 } 424 425 if (!value->isPrimitiveValue()) 426 return; 427 428 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 429 EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying; 430 layer->setPlayState(playState); 431} 432 433void CSSToStyleMap::mapAnimationProperty(Animation* animation, CSSValue* value) 434{ 435 if (value->isInitialValue()) { 436 animation->setAnimationMode(Animation::AnimateAll); 437 animation->setProperty(CSSPropertyInvalid); 438 return; 439 } 440 441 if (!value->isPrimitiveValue()) 442 return; 443 444 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 445 if (primitiveValue->getIdent() == CSSValueAll) { 446 animation->setAnimationMode(Animation::AnimateAll); 447 animation->setProperty(CSSPropertyInvalid); 448 } else if (primitiveValue->getIdent() == CSSValueNone) { 449 animation->setAnimationMode(Animation::AnimateNone); 450 animation->setProperty(CSSPropertyInvalid); 451 } else { 452 animation->setAnimationMode(Animation::AnimateSingleProperty); 453 animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent())); 454 } 455} 456 457void CSSToStyleMap::mapAnimationTimingFunction(Animation* animation, CSSValue* value) 458{ 459 if (value->isInitialValue()) { 460 animation->setTimingFunction(Animation::initialAnimationTimingFunction()); 461 return; 462 } 463 464 if (value->isPrimitiveValue()) { 465 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 466 switch (primitiveValue->getIdent()) { 467 case CSSValueLinear: 468 animation->setTimingFunction(LinearTimingFunction::create()); 469 break; 470 case CSSValueEase: 471 animation->setTimingFunction(CubicBezierTimingFunction::create()); 472 break; 473 case CSSValueEaseIn: 474 animation->setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseIn)); 475 break; 476 case CSSValueEaseOut: 477 animation->setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseOut)); 478 break; 479 case CSSValueEaseInOut: 480 animation->setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseInOut)); 481 break; 482 case CSSValueStepStart: 483 animation->setTimingFunction(StepsTimingFunction::create(1, true)); 484 break; 485 case CSSValueStepEnd: 486 animation->setTimingFunction(StepsTimingFunction::create(1, false)); 487 break; 488 } 489 return; 490 } 491 492 if (value->isCubicBezierTimingFunctionValue()) { 493 CSSCubicBezierTimingFunctionValue* cubicTimingFunction = static_cast<CSSCubicBezierTimingFunctionValue*>(value); 494 animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2())); 495 } else if (value->isStepsTimingFunctionValue()) { 496 CSSStepsTimingFunctionValue* stepsTimingFunction = static_cast<CSSStepsTimingFunctionValue*>(value); 497 animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart())); 498 } else if (value->isLinearTimingFunctionValue()) 499 animation->setTimingFunction(LinearTimingFunction::create()); 500} 501 502void CSSToStyleMap::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image) 503{ 504 // If we're not a value list, then we are "none" and don't need to alter the empty image at all. 505 if (!value || !value->isValueList()) 506 return; 507 508 // Retrieve the border image value. 509 CSSValueList* borderImage = static_cast<CSSValueList*>(value); 510 511 // Set the image (this kicks off the load). 512 CSSPropertyID imageProperty; 513 if (property == CSSPropertyWebkitBorderImage) 514 imageProperty = CSSPropertyBorderImageSource; 515 else if (property == CSSPropertyWebkitMaskBoxImage) 516 imageProperty = CSSPropertyWebkitMaskBoxImageSource; 517 else 518 imageProperty = property; 519 520 for (unsigned i = 0 ; i < borderImage->length() ; ++i) { 521 CSSValue* current = borderImage->item(i); 522 523 if (current->isImageValue() || current->isImageGeneratorValue() 524#if ENABLE(CSS_IMAGE_SET) 525 || current->isImageSetValue() 526#endif 527 ) 528 image.setImage(styleImage(imageProperty, current)); 529 else if (current->isBorderImageSliceValue()) 530 mapNinePieceImageSlice(current, image); 531 else if (current->isValueList()) { 532 CSSValueList* slashList = static_cast<CSSValueList*>(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 style()->setBorderTopWidth(image.borderSlices().top().value()); 556 if (image.borderSlices().right().isFixed()) 557 style()->setBorderRightWidth(image.borderSlices().right().value()); 558 if (image.borderSlices().bottom().isFixed()) 559 style()->setBorderBottomWidth(image.borderSlices().bottom().value()); 560 if (image.borderSlices().left().isFixed()) 561 style()->setBorderLeftWidth(image.borderSlices().left().value()); 562 } 563} 564 565void CSSToStyleMap::mapNinePieceImageSlice(CSSValue* value, NinePieceImage& image) 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 598LengthBox CSSToStyleMap::mapNinePieceImageQuad(CSSValue* value) 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 = static_cast<CSSPrimitiveValue*>(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()->getIdent() != 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()->getIdent() != 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()->getIdent() != 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()->getIdent() != CSSValueAuto) 638 box.m_left = slices->left()->computeLength<Length>(style(), rootElementStyle(), zoom); 639 640 return box; 641} 642 643void CSSToStyleMap::mapNinePieceImageRepeat(CSSValue* value, NinePieceImage& image) 644{ 645 if (!value || !value->isPrimitiveValue()) 646 return; 647 648 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 649 Pair* pair = primitiveValue->getPairValue(); 650 if (!pair || !pair->first() || !pair->second()) 651 return; 652 653 int firstIdentifier = pair->first()->getIdent(); 654 int secondIdentifier = pair->second()->getIdent(); 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