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 "core/css/resolver/CSSToStyleMap.h"
30
31 #include "core/CSSValueKeywords.h"
32 #include "core/animation/css/CSSAnimationData.h"
33 #include "core/css/CSSBorderImageSliceValue.h"
34 #include "core/css/CSSPrimitiveValue.h"
35 #include "core/css/CSSPrimitiveValueMappings.h"
36 #include "core/css/CSSTimingFunctionValue.h"
37 #include "core/css/Pair.h"
38 #include "core/css/Rect.h"
39 #include "core/css/resolver/StyleResolverState.h"
40 #include "core/rendering/style/BorderImageLengthBox.h"
41 #include "core/rendering/style/FillLayer.h"
42
43 namespace WebCore {
44
cssToLengthConversionData() const45 const CSSToLengthConversionData& CSSToStyleMap::cssToLengthConversionData() const
46 {
47 return m_state.cssToLengthConversionData();
48 }
49
styleImage(CSSPropertyID propertyId,CSSValue * value)50 PassRefPtr<StyleImage> CSSToStyleMap::styleImage(CSSPropertyID propertyId, CSSValue* value)
51 {
52 return m_elementStyleResources.styleImage(m_state.document(), m_state.document().textLinkColors(), m_state.style()->color(), propertyId, value);
53 }
54
mapFillAttachment(CSSPropertyID,FillLayer * layer,CSSValue * value) const55 void CSSToStyleMap::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value) const
56 {
57 if (value->isInitialValue()) {
58 layer->setAttachment(FillLayer::initialFillAttachment(layer->type()));
59 return;
60 }
61
62 if (!value->isPrimitiveValue())
63 return;
64
65 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
66 switch (primitiveValue->getValueID()) {
67 case CSSValueFixed:
68 layer->setAttachment(FixedBackgroundAttachment);
69 break;
70 case CSSValueScroll:
71 layer->setAttachment(ScrollBackgroundAttachment);
72 break;
73 case CSSValueLocal:
74 layer->setAttachment(LocalBackgroundAttachment);
75 break;
76 default:
77 return;
78 }
79 }
80
mapFillClip(CSSPropertyID,FillLayer * layer,CSSValue * value) const81 void CSSToStyleMap::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value) const
82 {
83 if (value->isInitialValue()) {
84 layer->setClip(FillLayer::initialFillClip(layer->type()));
85 return;
86 }
87
88 if (!value->isPrimitiveValue())
89 return;
90
91 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
92 layer->setClip(*primitiveValue);
93 }
94
mapFillComposite(CSSPropertyID,FillLayer * layer,CSSValue * value) const95 void CSSToStyleMap::mapFillComposite(CSSPropertyID, FillLayer* layer, CSSValue* value) const
96 {
97 if (value->isInitialValue()) {
98 layer->setComposite(FillLayer::initialFillComposite(layer->type()));
99 return;
100 }
101
102 if (!value->isPrimitiveValue())
103 return;
104
105 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
106 layer->setComposite(*primitiveValue);
107 }
108
mapFillBlendMode(CSSPropertyID,FillLayer * layer,CSSValue * value) const109 void CSSToStyleMap::mapFillBlendMode(CSSPropertyID, FillLayer* layer, CSSValue* value) const
110 {
111 if (value->isInitialValue()) {
112 layer->setBlendMode(FillLayer::initialFillBlendMode(layer->type()));
113 return;
114 }
115
116 if (!value->isPrimitiveValue())
117 return;
118
119 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
120 layer->setBlendMode(*primitiveValue);
121 }
122
mapFillOrigin(CSSPropertyID,FillLayer * layer,CSSValue * value) const123 void CSSToStyleMap::mapFillOrigin(CSSPropertyID, FillLayer* layer, CSSValue* value) const
124 {
125 if (value->isInitialValue()) {
126 layer->setOrigin(FillLayer::initialFillOrigin(layer->type()));
127 return;
128 }
129
130 if (!value->isPrimitiveValue())
131 return;
132
133 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
134 layer->setOrigin(*primitiveValue);
135 }
136
137
mapFillImage(CSSPropertyID property,FillLayer * layer,CSSValue * value)138 void CSSToStyleMap::mapFillImage(CSSPropertyID property, FillLayer* layer, CSSValue* value)
139 {
140 if (value->isInitialValue()) {
141 layer->setImage(FillLayer::initialFillImage(layer->type()));
142 return;
143 }
144
145 layer->setImage(styleImage(property, value));
146 }
147
mapFillRepeatX(CSSPropertyID,FillLayer * layer,CSSValue * value) const148 void CSSToStyleMap::mapFillRepeatX(CSSPropertyID, FillLayer* layer, CSSValue* value) const
149 {
150 if (value->isInitialValue()) {
151 layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type()));
152 return;
153 }
154
155 if (!value->isPrimitiveValue())
156 return;
157
158 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
159 layer->setRepeatX(*primitiveValue);
160 }
161
mapFillRepeatY(CSSPropertyID,FillLayer * layer,CSSValue * value) const162 void CSSToStyleMap::mapFillRepeatY(CSSPropertyID, FillLayer* layer, CSSValue* value) const
163 {
164 if (value->isInitialValue()) {
165 layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type()));
166 return;
167 }
168
169 if (!value->isPrimitiveValue())
170 return;
171
172 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
173 layer->setRepeatY(*primitiveValue);
174 }
175
mapFillSize(CSSPropertyID,FillLayer * layer,CSSValue * value) const176 void CSSToStyleMap::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value) const
177 {
178 if (value->isInitialValue()) {
179 layer->setSizeType(FillLayer::initialFillSizeType(layer->type()));
180 layer->setSizeLength(FillLayer::initialFillSizeLength(layer->type()));
181 return;
182 }
183
184 if (!value->isPrimitiveValue())
185 return;
186
187 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
188 if (primitiveValue->getValueID() == CSSValueContain)
189 layer->setSizeType(Contain);
190 else if (primitiveValue->getValueID() == CSSValueCover)
191 layer->setSizeType(Cover);
192 else
193 layer->setSizeType(SizeLength);
194
195 LengthSize b = FillLayer::initialFillSizeLength(layer->type());
196
197 if (primitiveValue->getValueID() == CSSValueContain || primitiveValue->getValueID() == CSSValueCover) {
198 layer->setSizeLength(b);
199 return;
200 }
201
202 Length firstLength;
203 Length secondLength;
204
205 if (Pair* pair = primitiveValue->getPairValue()) {
206 firstLength = pair->first()->convertToLength<AnyConversion>(cssToLengthConversionData());
207 secondLength = pair->second()->convertToLength<AnyConversion>(cssToLengthConversionData());
208 } else {
209 firstLength = primitiveValue->convertToLength<AnyConversion>(cssToLengthConversionData());
210 secondLength = Length();
211 }
212
213 b.setWidth(firstLength);
214 b.setHeight(secondLength);
215 layer->setSizeLength(b);
216 }
217
mapFillXPosition(CSSPropertyID propertyID,FillLayer * layer,CSSValue * value) const218 void CSSToStyleMap::mapFillXPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value) const
219 {
220 if (value->isInitialValue()) {
221 layer->setXPosition(FillLayer::initialFillXPosition(layer->type()));
222 return;
223 }
224
225 if (!value->isPrimitiveValue())
226 return;
227
228 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(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 = primitiveValue->convertToLength<FixedConversion | PercentConversion>(cssToLengthConversionData());
236
237 layer->setXPosition(length);
238 if (pair)
239 layer->setBackgroundXOrigin(*(pair->first()));
240 }
241
mapFillYPosition(CSSPropertyID propertyID,FillLayer * layer,CSSValue * value) const242 void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer* layer, CSSValue* value) const
243 {
244 if (value->isInitialValue()) {
245 layer->setYPosition(FillLayer::initialFillYPosition(layer->type()));
246 return;
247 }
248
249 if (!value->isPrimitiveValue())
250 return;
251
252 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
253 Pair* pair = primitiveValue->getPairValue();
254 if (pair) {
255 ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPositionY || propertyID == CSSPropertyWebkitMaskPositionY);
256 primitiveValue = pair->second();
257 }
258
259 Length length = primitiveValue->convertToLength<FixedConversion | PercentConversion>(cssToLengthConversionData());
260
261 layer->setYPosition(length);
262 if (pair)
263 layer->setBackgroundYOrigin(*(pair->first()));
264 }
265
mapFillMaskSourceType(CSSPropertyID,FillLayer * layer,CSSValue * value)266 void CSSToStyleMap::mapFillMaskSourceType(CSSPropertyID, FillLayer* layer, CSSValue* value)
267 {
268 EMaskSourceType type = FillLayer::initialFillMaskSourceType(layer->type());
269 if (value->isInitialValue()) {
270 layer->setMaskSourceType(type);
271 return;
272 }
273
274 if (!value->isPrimitiveValue())
275 return;
276
277 switch (toCSSPrimitiveValue(value)->getValueID()) {
278 case CSSValueAlpha:
279 type = MaskAlpha;
280 break;
281 case CSSValueLuminance:
282 type = MaskLuminance;
283 break;
284 case CSSValueAuto:
285 break;
286 default:
287 ASSERT_NOT_REACHED();
288 }
289
290 layer->setMaskSourceType(type);
291 }
292
mapAnimationDelay(CSSValue * value)293 double CSSToStyleMap::mapAnimationDelay(CSSValue* value)
294 {
295 if (value->isInitialValue())
296 return CSSTimingData::initialDelay();
297 return toCSSPrimitiveValue(value)->computeTime<double, CSSPrimitiveValue::Seconds>();
298 }
299
mapAnimationDirection(CSSValue * value)300 Timing::PlaybackDirection CSSToStyleMap::mapAnimationDirection(CSSValue* value)
301 {
302 if (value->isInitialValue())
303 return CSSAnimationData::initialDirection();
304
305 switch (toCSSPrimitiveValue(value)->getValueID()) {
306 case CSSValueNormal:
307 return Timing::PlaybackDirectionNormal;
308 case CSSValueAlternate:
309 return Timing::PlaybackDirectionAlternate;
310 case CSSValueReverse:
311 return Timing::PlaybackDirectionReverse;
312 case CSSValueAlternateReverse:
313 return Timing::PlaybackDirectionAlternateReverse;
314 default:
315 ASSERT_NOT_REACHED();
316 return CSSAnimationData::initialDirection();
317 }
318 }
319
mapAnimationDuration(CSSValue * value)320 double CSSToStyleMap::mapAnimationDuration(CSSValue* value)
321 {
322 if (value->isInitialValue())
323 return CSSTimingData::initialDuration();
324 return toCSSPrimitiveValue(value)->computeTime<double, CSSPrimitiveValue::Seconds>();
325 }
326
mapAnimationFillMode(CSSValue * value)327 Timing::FillMode CSSToStyleMap::mapAnimationFillMode(CSSValue* value)
328 {
329 if (value->isInitialValue())
330 return CSSAnimationData::initialFillMode();
331
332 switch (toCSSPrimitiveValue(value)->getValueID()) {
333 case CSSValueNone:
334 return Timing::FillModeNone;
335 case CSSValueForwards:
336 return Timing::FillModeForwards;
337 case CSSValueBackwards:
338 return Timing::FillModeBackwards;
339 case CSSValueBoth:
340 return Timing::FillModeBoth;
341 default:
342 ASSERT_NOT_REACHED();
343 return CSSAnimationData::initialFillMode();
344 }
345 }
346
mapAnimationIterationCount(CSSValue * value)347 double CSSToStyleMap::mapAnimationIterationCount(CSSValue* value)
348 {
349 if (value->isInitialValue())
350 return CSSAnimationData::initialIterationCount();
351 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
352 if (primitiveValue->getValueID() == CSSValueInfinite)
353 return std::numeric_limits<double>::infinity();
354 return primitiveValue->getFloatValue();
355 }
356
mapAnimationName(CSSValue * value)357 AtomicString CSSToStyleMap::mapAnimationName(CSSValue* value)
358 {
359 if (value->isInitialValue())
360 return CSSAnimationData::initialName();
361 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
362 if (primitiveValue->getValueID() == CSSValueNone)
363 return CSSAnimationData::initialName();
364 return AtomicString(primitiveValue->getStringValue());
365 }
366
mapAnimationPlayState(CSSValue * value)367 EAnimPlayState CSSToStyleMap::mapAnimationPlayState(CSSValue* value)
368 {
369 if (value->isInitialValue())
370 return CSSAnimationData::initialPlayState();
371 if (toCSSPrimitiveValue(value)->getValueID() == CSSValuePaused)
372 return AnimPlayStatePaused;
373 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueRunning);
374 return AnimPlayStatePlaying;
375 }
376
mapAnimationProperty(CSSValue * value)377 CSSTransitionData::TransitionProperty CSSToStyleMap::mapAnimationProperty(CSSValue* value)
378 {
379 if (value->isInitialValue())
380 return CSSTransitionData::initialProperty();
381 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
382 if (primitiveValue->isString())
383 return CSSTransitionData::TransitionProperty(primitiveValue->getStringValue());
384 if (primitiveValue->getValueID() == CSSValueAll)
385 return CSSTransitionData::TransitionProperty(CSSTransitionData::TransitionAll);
386 if (primitiveValue->getValueID() == CSSValueNone)
387 return CSSTransitionData::TransitionProperty(CSSTransitionData::TransitionNone);
388 return CSSTransitionData::TransitionProperty(primitiveValue->getPropertyID());
389 }
390
mapAnimationTimingFunction(CSSValue * value,bool allowStepMiddle)391 PassRefPtr<TimingFunction> CSSToStyleMap::mapAnimationTimingFunction(CSSValue* value, bool allowStepMiddle)
392 {
393 // FIXME: We should probably only call into this function with a valid
394 // single timing function value which isn't initial or inherit. We can
395 // currently get into here with initial since the parser expands unset
396 // properties in shorthands to initial.
397
398 if (value->isPrimitiveValue()) {
399 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
400 switch (primitiveValue->getValueID()) {
401 case CSSValueLinear:
402 return LinearTimingFunction::shared();
403 case CSSValueEase:
404 return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease);
405 case CSSValueEaseIn:
406 return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseIn);
407 case CSSValueEaseOut:
408 return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseOut);
409 case CSSValueEaseInOut:
410 return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut);
411 case CSSValueStepStart:
412 return StepsTimingFunction::preset(StepsTimingFunction::Start);
413 case CSSValueStepMiddle:
414 if (allowStepMiddle)
415 return StepsTimingFunction::preset(StepsTimingFunction::Middle);
416 return CSSTimingData::initialTimingFunction();
417 case CSSValueStepEnd:
418 return StepsTimingFunction::preset(StepsTimingFunction::End);
419 default:
420 ASSERT_NOT_REACHED();
421 return CSSTimingData::initialTimingFunction();
422 }
423 }
424
425 if (value->isCubicBezierTimingFunctionValue()) {
426 CSSCubicBezierTimingFunctionValue* cubicTimingFunction = toCSSCubicBezierTimingFunctionValue(value);
427 return CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2());
428 }
429
430 if (value->isInitialValue())
431 return CSSTimingData::initialTimingFunction();
432
433 CSSStepsTimingFunctionValue* stepsTimingFunction = toCSSStepsTimingFunctionValue(value);
434 if (stepsTimingFunction->stepAtPosition() == StepsTimingFunction::StepAtMiddle && !allowStepMiddle)
435 return CSSTimingData::initialTimingFunction();
436 return StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtPosition());
437 }
438
mapNinePieceImage(RenderStyle * mutableStyle,CSSPropertyID property,CSSValue * value,NinePieceImage & image)439 void CSSToStyleMap::mapNinePieceImage(RenderStyle* mutableStyle, CSSPropertyID property, CSSValue* value, NinePieceImage& image)
440 {
441 // If we're not a value list, then we are "none" and don't need to alter the empty image at all.
442 if (!value || !value->isValueList())
443 return;
444
445 // Retrieve the border image value.
446 CSSValueList* borderImage = toCSSValueList(value);
447
448 // Set the image (this kicks off the load).
449 CSSPropertyID imageProperty;
450 if (property == CSSPropertyWebkitBorderImage)
451 imageProperty = CSSPropertyBorderImageSource;
452 else if (property == CSSPropertyWebkitMaskBoxImage)
453 imageProperty = CSSPropertyWebkitMaskBoxImageSource;
454 else
455 imageProperty = property;
456
457 for (unsigned i = 0 ; i < borderImage->length() ; ++i) {
458 CSSValue* current = borderImage->item(i);
459
460 if (current->isImageValue() || current->isImageGeneratorValue() || current->isImageSetValue())
461 image.setImage(styleImage(imageProperty, current));
462 else if (current->isBorderImageSliceValue())
463 mapNinePieceImageSlice(current, image);
464 else if (current->isValueList()) {
465 CSSValueList* slashList = toCSSValueList(current);
466 // Map in the image slices.
467 if (slashList->item(0) && slashList->item(0)->isBorderImageSliceValue())
468 mapNinePieceImageSlice(slashList->item(0), image);
469
470 // Map in the border slices.
471 if (slashList->item(1))
472 image.setBorderSlices(mapNinePieceImageQuad(slashList->item(1)));
473
474 // Map in the outset.
475 if (slashList->item(2))
476 image.setOutset(mapNinePieceImageQuad(slashList->item(2)));
477 } else if (current->isPrimitiveValue()) {
478 // Set the appropriate rules for stretch/round/repeat of the slices.
479 mapNinePieceImageRepeat(current, image);
480 }
481 }
482
483 if (property == CSSPropertyWebkitBorderImage) {
484 // We have to preserve the legacy behavior of -webkit-border-image and make the border slices
485 // also set the border widths. We don't need to worry about percentages, since we don't even support
486 // those on real borders yet.
487 if (image.borderSlices().top().isLength() && image.borderSlices().top().length().isFixed())
488 mutableStyle->setBorderTopWidth(image.borderSlices().top().length().value());
489 if (image.borderSlices().right().isLength() && image.borderSlices().right().length().isFixed())
490 mutableStyle->setBorderRightWidth(image.borderSlices().right().length().value());
491 if (image.borderSlices().bottom().isLength() && image.borderSlices().bottom().length().isFixed())
492 mutableStyle->setBorderBottomWidth(image.borderSlices().bottom().length().value());
493 if (image.borderSlices().left().isLength() && image.borderSlices().left().length().isFixed())
494 mutableStyle->setBorderLeftWidth(image.borderSlices().left().length().value());
495 }
496 }
497
mapNinePieceImageSlice(CSSValue * value,NinePieceImage & image) const498 void CSSToStyleMap::mapNinePieceImageSlice(CSSValue* value, NinePieceImage& image) const
499 {
500 if (!value || !value->isBorderImageSliceValue())
501 return;
502
503 // Retrieve the border image value.
504 CSSBorderImageSliceValue* borderImageSlice = toCSSBorderImageSliceValue(value);
505
506 // Set up a length box to represent our image slices.
507 LengthBox box;
508 Quad* slices = borderImageSlice->slices();
509 if (slices->top()->isPercentage())
510 box.m_top = Length(slices->top()->getDoubleValue(), Percent);
511 else
512 box.m_top = Length(slices->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
513 if (slices->bottom()->isPercentage())
514 box.m_bottom = Length(slices->bottom()->getDoubleValue(), Percent);
515 else
516 box.m_bottom = Length((int)slices->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
517 if (slices->left()->isPercentage())
518 box.m_left = Length(slices->left()->getDoubleValue(), Percent);
519 else
520 box.m_left = Length(slices->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
521 if (slices->right()->isPercentage())
522 box.m_right = Length(slices->right()->getDoubleValue(), Percent);
523 else
524 box.m_right = Length(slices->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
525 image.setImageSlices(box);
526
527 // Set our fill mode.
528 image.setFill(borderImageSlice->m_fill);
529 }
530
toBorderImageLength(CSSPrimitiveValue & value,const CSSToLengthConversionData & conversionData)531 static BorderImageLength toBorderImageLength(CSSPrimitiveValue& value, const CSSToLengthConversionData& conversionData)
532 {
533 if (value.isNumber())
534 return value.getDoubleValue();
535 if (value.isPercentage())
536 return Length(value.getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
537 if (value.getValueID() != CSSValueAuto)
538 return value.computeLength<Length>(conversionData);
539 return Length(Auto);
540 }
541
mapNinePieceImageQuad(CSSValue * value) const542 BorderImageLengthBox CSSToStyleMap::mapNinePieceImageQuad(CSSValue* value) const
543 {
544 if (!value || !value->isPrimitiveValue())
545 return BorderImageLengthBox(Length(Auto));
546
547 Quad* slices = toCSSPrimitiveValue(value)->getQuadValue();
548
549 // Set up a border image length box to represent our image slices.
550 return BorderImageLengthBox(
551 toBorderImageLength(*slices->top(), cssToLengthConversionData()),
552 toBorderImageLength(*slices->right(), cssToLengthConversionData()),
553 toBorderImageLength(*slices->bottom(), cssToLengthConversionData()),
554 toBorderImageLength(*slices->left(), cssToLengthConversionData()));
555 }
556
mapNinePieceImageRepeat(CSSValue * value,NinePieceImage & image) const557 void CSSToStyleMap::mapNinePieceImageRepeat(CSSValue* value, NinePieceImage& image) const
558 {
559 if (!value || !value->isPrimitiveValue())
560 return;
561
562 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
563 Pair* pair = primitiveValue->getPairValue();
564 if (!pair || !pair->first() || !pair->second())
565 return;
566
567 CSSValueID firstIdentifier = pair->first()->getValueID();
568 CSSValueID secondIdentifier = pair->second()->getValueID();
569
570 ENinePieceImageRule horizontalRule;
571 switch (firstIdentifier) {
572 case CSSValueStretch:
573 horizontalRule = StretchImageRule;
574 break;
575 case CSSValueRound:
576 horizontalRule = RoundImageRule;
577 break;
578 case CSSValueSpace:
579 horizontalRule = SpaceImageRule;
580 break;
581 default: // CSSValueRepeat
582 horizontalRule = RepeatImageRule;
583 break;
584 }
585 image.setHorizontalRule(horizontalRule);
586
587 ENinePieceImageRule verticalRule;
588 switch (secondIdentifier) {
589 case CSSValueStretch:
590 verticalRule = StretchImageRule;
591 break;
592 case CSSValueRound:
593 verticalRule = RoundImageRule;
594 break;
595 case CSSValueSpace:
596 verticalRule = SpaceImageRule;
597 break;
598 default: // CSSValueRepeat
599 verticalRule = RepeatImageRule;
600 break;
601 }
602 image.setVerticalRule(verticalRule);
603 }
604
605 };
606