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