Querying transition-timing-function value on the computed style does not return keywo...
[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     Pair* pair = primitiveValue->getPairValue();
230     if (pair) {
231         ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionX || propertyID == CSSPropertyWebkitMaskPositionX);
232         primitiveValue = pair->second();
233     }
234
235     Length length;
236     if (primitiveValue->isLength())
237         length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor);
238     else if (primitiveValue->isPercentage())
239         length = Length(primitiveValue->getDoubleValue(), Percent);
240     else if (primitiveValue->isCalculatedPercentageWithLength())
241         length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor));
242     else if (primitiveValue->isViewportPercentageLength())
243         length = primitiveValue->viewportPercentageLength();
244     else
245         return;
246
247     layer->setXPosition(length);
248     if (pair)
249         layer->setBackgroundXOrigin(*(pair->first()));
250 }
251
252 void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value)
253 {
254     if (value->isInitialValue()) {
255         layer->setYPosition(FillLayer::initialFillYPosition(layer->type()));
256         return;
257     }
258
259     if (!value->isPrimitiveValue())
260         return;
261
262     float zoomFactor = style()->effectiveZoom();
263
264     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
265     Pair* pair = primitiveValue->getPairValue();
266     if (pair) {
267         ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionY || propertyID == CSSPropertyWebkitMaskPositionY);
268         primitiveValue = pair->second();
269     }
270
271     Length length;
272     if (primitiveValue->isLength())
273         length = primitiveValue->computeLength<Length>(style(), rootElementStyle(), zoomFactor);
274     else if (primitiveValue->isPercentage())
275         length = Length(primitiveValue->getDoubleValue(), Percent);
276     else if (primitiveValue->isCalculatedPercentageWithLength())
277         length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor));
278     else if (primitiveValue->isViewportPercentageLength())
279         length = primitiveValue->viewportPercentageLength();
280     else
281         return;
282
283     layer->setYPosition(length);
284     if (pair)
285         layer->setBackgroundYOrigin(*(pair->first()));
286 }
287
288 void CSSToStyleMap::mapAnimationDelay(Animation* animation, CSSValue* value)
289 {
290     if (value->isInitialValue()) {
291         animation->setDelay(Animation::initialAnimationDelay());
292         return;
293     }
294
295     if (!value->isPrimitiveValue())
296         return;
297
298     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
299     animation->setDelay(primitiveValue->computeTime<float, CSSPrimitiveValue::Seconds>());
300 }
301
302 void CSSToStyleMap::mapAnimationDirection(Animation* layer, CSSValue* value)
303 {
304     if (value->isInitialValue()) {
305         layer->setDirection(Animation::initialAnimationDirection());
306         return;
307     }
308
309     if (!value->isPrimitiveValue())
310         return;
311
312     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
313     switch (primitiveValue->getIdent()) {
314     case CSSValueNormal:
315         layer->setDirection(Animation::AnimationDirectionNormal);
316         break;
317     case CSSValueAlternate:
318         layer->setDirection(Animation::AnimationDirectionAlternate);
319         break;
320     case CSSValueReverse:
321         layer->setDirection(Animation::AnimationDirectionReverse);
322         break;
323     case CSSValueAlternateReverse:
324         layer->setDirection(Animation::AnimationDirectionAlternateReverse);
325         break;
326     }
327 }
328
329 void CSSToStyleMap::mapAnimationDuration(Animation* animation, CSSValue* value)
330 {
331     if (value->isInitialValue()) {
332         animation->setDuration(Animation::initialAnimationDuration());
333         return;
334     }
335
336     if (!value->isPrimitiveValue())
337         return;
338
339     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
340     animation->setDuration(primitiveValue->computeTime<float, CSSPrimitiveValue::Seconds>());
341 }
342
343 void CSSToStyleMap::mapAnimationFillMode(Animation* layer, CSSValue* value)
344 {
345     if (value->isInitialValue()) {
346         layer->setFillMode(Animation::initialAnimationFillMode());
347         return;
348     }
349
350     if (!value->isPrimitiveValue())
351         return;
352
353     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
354     switch (primitiveValue->getIdent()) {
355     case CSSValueNone:
356         layer->setFillMode(AnimationFillModeNone);
357         break;
358     case CSSValueForwards:
359         layer->setFillMode(AnimationFillModeForwards);
360         break;
361     case CSSValueBackwards:
362         layer->setFillMode(AnimationFillModeBackwards);
363         break;
364     case CSSValueBoth:
365         layer->setFillMode(AnimationFillModeBoth);
366         break;
367     }
368 }
369
370 void CSSToStyleMap::mapAnimationIterationCount(Animation* animation, CSSValue* value)
371 {
372     if (value->isInitialValue()) {
373         animation->setIterationCount(Animation::initialAnimationIterationCount());
374         return;
375     }
376
377     if (!value->isPrimitiveValue())
378         return;
379
380     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
381     if (primitiveValue->getIdent() == CSSValueInfinite)
382         animation->setIterationCount(Animation::IterationCountInfinite);
383     else
384         animation->setIterationCount(primitiveValue->getFloatValue());
385 }
386
387 void CSSToStyleMap::mapAnimationName(Animation* layer, CSSValue* value)
388 {
389     if (value->isInitialValue()) {
390         layer->setName(Animation::initialAnimationName());
391         return;
392     }
393
394     if (!value->isPrimitiveValue())
395         return;
396
397     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
398     if (primitiveValue->getIdent() == CSSValueNone)
399         layer->setIsNoneAnimation(true);
400     else
401         layer->setName(primitiveValue->getStringValue());
402 }
403
404 void CSSToStyleMap::mapAnimationPlayState(Animation* layer, CSSValue* value)
405 {
406     if (value->isInitialValue()) {
407         layer->setPlayState(Animation::initialAnimationPlayState());
408         return;
409     }
410
411     if (!value->isPrimitiveValue())
412         return;
413
414     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
415     EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying;
416     layer->setPlayState(playState);
417 }
418
419 void CSSToStyleMap::mapAnimationProperty(Animation* animation, CSSValue* value)
420 {
421     if (value->isInitialValue()) {
422         animation->setAnimationMode(Animation::AnimateAll);
423         animation->setProperty(CSSPropertyInvalid);
424         return;
425     }
426
427     if (!value->isPrimitiveValue())
428         return;
429
430     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
431     if (primitiveValue->getIdent() == CSSValueAll) {
432         animation->setAnimationMode(Animation::AnimateAll);
433         animation->setProperty(CSSPropertyInvalid);
434     } else if (primitiveValue->getIdent() == CSSValueNone) {
435         animation->setAnimationMode(Animation::AnimateNone);
436         animation->setProperty(CSSPropertyInvalid);
437     } else {
438         animation->setAnimationMode(Animation::AnimateSingleProperty);
439         animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent()));
440     }
441 }
442
443 void CSSToStyleMap::mapAnimationTimingFunction(Animation* animation, CSSValue* value)
444 {
445     if (value->isInitialValue()) {
446         animation->setTimingFunction(Animation::initialAnimationTimingFunction());
447         return;
448     }
449
450     if (value->isPrimitiveValue()) {
451         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
452         switch (primitiveValue->getIdent()) {
453         case CSSValueLinear:
454             animation->setTimingFunction(LinearTimingFunction::create());
455             break;
456         case CSSValueEase:
457             animation->setTimingFunction(CubicBezierTimingFunction::create());
458             break;
459         case CSSValueEaseIn:
460             animation->setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseIn));
461             break;
462         case CSSValueEaseOut:
463             animation->setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseOut));
464             break;
465         case CSSValueEaseInOut:
466             animation->setTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::EaseInOut));
467             break;
468         case CSSValueStepStart:
469             animation->setTimingFunction(StepsTimingFunction::create(1, true));
470             break;
471         case CSSValueStepEnd:
472             animation->setTimingFunction(StepsTimingFunction::create(1, false));
473             break;
474         }
475         return;
476     }
477
478     if (value->isCubicBezierTimingFunctionValue()) {
479         CSSCubicBezierTimingFunctionValue* cubicTimingFunction = static_cast<CSSCubicBezierTimingFunctionValue*>(value);
480         animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2()));
481     } else if (value->isStepsTimingFunctionValue()) {
482         CSSStepsTimingFunctionValue* stepsTimingFunction = static_cast<CSSStepsTimingFunctionValue*>(value);
483         animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart()));
484     } else if (value->isLinearTimingFunctionValue())
485         animation->setTimingFunction(LinearTimingFunction::create());
486 }
487
488 void CSSToStyleMap::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image)
489 {
490     // If we're not a value list, then we are "none" and don't need to alter the empty image at all.
491     if (!value || !value->isValueList())
492         return;
493
494     // Retrieve the border image value.
495     CSSValueList* borderImage = static_cast<CSSValueList*>(value);
496
497     // Set the image (this kicks off the load).
498     CSSPropertyID imageProperty;
499     if (property == CSSPropertyWebkitBorderImage)
500         imageProperty = CSSPropertyBorderImageSource;
501     else if (property == CSSPropertyWebkitMaskBoxImage)
502         imageProperty = CSSPropertyWebkitMaskBoxImageSource;
503     else
504         imageProperty = property;
505
506     for (unsigned i = 0 ; i < borderImage->length() ; ++i) {
507         CSSValue* current = borderImage->item(i);
508
509         if (current->isImageValue() || current->isImageGeneratorValue()
510 #if ENABLE(CSS_IMAGE_SET)
511             || current->isImageSetValue()
512 #endif
513             )
514             image.setImage(styleImage(imageProperty, current));
515         else if (current->isBorderImageSliceValue())
516             mapNinePieceImageSlice(current, image);
517         else if (current->isValueList()) {
518             CSSValueList* slashList = static_cast<CSSValueList*>(current);
519             // Map in the image slices.
520             if (slashList->item(0) && slashList->item(0)->isBorderImageSliceValue())
521                 mapNinePieceImageSlice(slashList->item(0), image);
522
523             // Map in the border slices.
524             if (slashList->item(1))
525                 image.setBorderSlices(mapNinePieceImageQuad(slashList->item(1)));
526
527             // Map in the outset.
528             if (slashList->item(2))
529                 image.setOutset(mapNinePieceImageQuad(slashList->item(2)));
530         } else if (current->isPrimitiveValue()) {
531             // Set the appropriate rules for stretch/round/repeat of the slices.
532             mapNinePieceImageRepeat(current, image);
533         }
534     }
535
536     if (property == CSSPropertyWebkitBorderImage) {
537         // We have to preserve the legacy behavior of -webkit-border-image and make the border slices
538         // also set the border widths. We don't need to worry about percentages, since we don't even support
539         // those on real borders yet.
540         if (image.borderSlices().top().isFixed())
541             style()->setBorderTopWidth(image.borderSlices().top().value());
542         if (image.borderSlices().right().isFixed())
543             style()->setBorderRightWidth(image.borderSlices().right().value());
544         if (image.borderSlices().bottom().isFixed())
545             style()->setBorderBottomWidth(image.borderSlices().bottom().value());
546         if (image.borderSlices().left().isFixed())
547             style()->setBorderLeftWidth(image.borderSlices().left().value());
548     }
549 }
550
551 void CSSToStyleMap::mapNinePieceImageSlice(CSSValue* value, NinePieceImage& image)
552 {
553     if (!value || !value->isBorderImageSliceValue())
554         return;
555
556     // Retrieve the border image value.
557     CSSBorderImageSliceValue* borderImageSlice = static_cast<CSSBorderImageSliceValue*>(value);
558
559     // Set up a length box to represent our image slices.
560     LengthBox box;
561     Quad* slices = borderImageSlice->slices();
562     if (slices->top()->isPercentage())
563         box.m_top = Length(slices->top()->getDoubleValue(), Percent);
564     else
565         box.m_top = Length(slices->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
566     if (slices->bottom()->isPercentage())
567         box.m_bottom = Length(slices->bottom()->getDoubleValue(), Percent);
568     else
569         box.m_bottom = Length((int)slices->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
570     if (slices->left()->isPercentage())
571         box.m_left = Length(slices->left()->getDoubleValue(), Percent);
572     else
573         box.m_left = Length(slices->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
574     if (slices->right()->isPercentage())
575         box.m_right = Length(slices->right()->getDoubleValue(), Percent);
576     else
577         box.m_right = Length(slices->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
578     image.setImageSlices(box);
579
580     // Set our fill mode.
581     image.setFill(borderImageSlice->m_fill);
582 }
583
584 LengthBox CSSToStyleMap::mapNinePieceImageQuad(CSSValue* value)
585 {
586     if (!value || !value->isPrimitiveValue())
587         return LengthBox();
588
589     // Get our zoom value.
590     float zoom = useSVGZoomRules() ? 1.0f : style()->effectiveZoom();
591
592     // Retrieve the primitive value.
593     CSSPrimitiveValue* borderWidths = static_cast<CSSPrimitiveValue*>(value);
594
595     // Set up a length box to represent our image slices.
596     LengthBox box; // Defaults to 'auto' so we don't have to handle that explicitly below.
597     Quad* slices = borderWidths->getQuadValue();
598     if (slices->top()->isNumber())
599         box.m_top = Length(slices->top()->getIntValue(), Relative);
600     else if (slices->top()->isPercentage())
601         box.m_top = Length(slices->top()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
602     else if (slices->top()->getIdent() != CSSValueAuto)
603         box.m_top = slices->top()->computeLength<Length>(style(), rootElementStyle(), zoom);
604
605     if (slices->right()->isNumber())
606         box.m_right = Length(slices->right()->getIntValue(), Relative);
607     else if (slices->right()->isPercentage())
608         box.m_right = Length(slices->right()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
609     else if (slices->right()->getIdent() != CSSValueAuto)
610         box.m_right = slices->right()->computeLength<Length>(style(), rootElementStyle(), zoom);
611
612     if (slices->bottom()->isNumber())
613         box.m_bottom = Length(slices->bottom()->getIntValue(), Relative);
614     else if (slices->bottom()->isPercentage())
615         box.m_bottom = Length(slices->bottom()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
616     else if (slices->bottom()->getIdent() != CSSValueAuto)
617         box.m_bottom = slices->bottom()->computeLength<Length>(style(), rootElementStyle(), zoom);
618
619     if (slices->left()->isNumber())
620         box.m_left = Length(slices->left()->getIntValue(), Relative);
621     else if (slices->left()->isPercentage())
622         box.m_left = Length(slices->left()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
623     else if (slices->left()->getIdent() != CSSValueAuto)
624         box.m_left = slices->left()->computeLength<Length>(style(), rootElementStyle(), zoom);
625
626     return box;
627 }
628
629 void CSSToStyleMap::mapNinePieceImageRepeat(CSSValue* value, NinePieceImage& image)
630 {
631     if (!value || !value->isPrimitiveValue())
632         return;
633
634     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
635     Pair* pair = primitiveValue->getPairValue();
636     if (!pair || !pair->first() || !pair->second())
637         return;
638
639     int firstIdentifier = pair->first()->getIdent();
640     int secondIdentifier = pair->second()->getIdent();
641
642     ENinePieceImageRule horizontalRule;
643     switch (firstIdentifier) {
644     case CSSValueStretch:
645         horizontalRule = StretchImageRule;
646         break;
647     case CSSValueRound:
648         horizontalRule = RoundImageRule;
649         break;
650     case CSSValueSpace:
651         horizontalRule = SpaceImageRule;
652         break;
653     default: // CSSValueRepeat
654         horizontalRule = RepeatImageRule;
655         break;
656     }
657     image.setHorizontalRule(horizontalRule);
658
659     ENinePieceImageRule verticalRule;
660     switch (secondIdentifier) {
661     case CSSValueStretch:
662         verticalRule = StretchImageRule;
663         break;
664     case CSSValueRound:
665         verticalRule = RoundImageRule;
666         break;
667     case CSSValueSpace:
668         verticalRule = SpaceImageRule;
669         break;
670     default: // CSSValueRepeat
671         verticalRule = RepeatImageRule;
672         break;
673     }
674     image.setVerticalRule(verticalRule);
675 }
676
677 };