Home | History | Annotate | Download | only in css
      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