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