2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "core/animation/css/CSSAnimatableValueFactory.h"
34 #include "core/CSSValueKeywords.h"
35 #include "core/animation/animatable/AnimatableClipPathOperation.h"
36 #include "core/animation/animatable/AnimatableColor.h"
37 #include "core/animation/animatable/AnimatableDouble.h"
38 #include "core/animation/animatable/AnimatableFilterOperations.h"
39 #include "core/animation/animatable/AnimatableImage.h"
40 #include "core/animation/animatable/AnimatableLength.h"
41 #include "core/animation/animatable/AnimatableLengthBox.h"
42 #include "core/animation/animatable/AnimatableLengthBoxAndBool.h"
43 #include "core/animation/animatable/AnimatableLengthPoint.h"
44 #include "core/animation/animatable/AnimatableLengthPoint3D.h"
45 #include "core/animation/animatable/AnimatableLengthSize.h"
46 #include "core/animation/animatable/AnimatableRepeatable.h"
47 #include "core/animation/animatable/AnimatableSVGLength.h"
48 #include "core/animation/animatable/AnimatableSVGPaint.h"
49 #include "core/animation/animatable/AnimatableShadow.h"
50 #include "core/animation/animatable/AnimatableShapeValue.h"
51 #include "core/animation/animatable/AnimatableStrokeDasharrayList.h"
52 #include "core/animation/animatable/AnimatableTransform.h"
53 #include "core/animation/animatable/AnimatableUnknown.h"
54 #include "core/animation/animatable/AnimatableVisibility.h"
55 #include "core/css/CSSCalculationValue.h"
56 #include "core/css/CSSPrimitiveValue.h"
57 #include "core/css/CSSPrimitiveValueMappings.h"
58 #include "core/css/CSSPropertyMetadata.h"
59 #include "core/rendering/style/RenderStyle.h"
60 #include "platform/Length.h"
61 #include "platform/LengthBox.h"
65 static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLength(const Length& length, const RenderStyle& style)
67 switch (length.type()) {
71 return AnimatableLength::create(length, style.effectiveZoom());
79 return AnimatableUnknown::create(CSSPrimitiveValue::create(length, 1));
81 return AnimatableUnknown::create(CSSValueNone);
82 case ExtendToZoom: // Does not apply to elements.
92 static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLineHeight(const Length& length, const RenderStyle& style)
94 if (length.type() == Percent) {
95 double value = length.value();
96 // -100% is used to represent "normal" line height.
98 return AnimatableUnknown::create(CSSValueNormal);
99 return AnimatableDouble::create(value);
101 return createFromLength(length, style);
104 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromDouble(double value, AnimatableDouble::Constraint constraint = AnimatableDouble::Unconstrained)
106 return AnimatableDouble::create(value, constraint);
109 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLengthBox(const LengthBox& lengthBox, const RenderStyle& style)
111 return AnimatableLengthBox::create(
112 createFromLength(lengthBox.left(), style),
113 createFromLength(lengthBox.right(), style),
114 createFromLength(lengthBox.top(), style),
115 createFromLength(lengthBox.bottom(), style));
118 static PassRefPtrWillBeRawPtr<AnimatableValue> createFromBorderImageLength(const BorderImageLength& borderImageLength, const RenderStyle& style)
120 if (borderImageLength.isNumber())
121 return createFromDouble(borderImageLength.number());
122 return createFromLength(borderImageLength.length(), style);
125 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromBorderImageLengthBox(const BorderImageLengthBox& borderImageLengthBox, const RenderStyle& style)
127 return AnimatableLengthBox::create(
128 createFromBorderImageLength(borderImageLengthBox.left(), style),
129 createFromBorderImageLength(borderImageLengthBox.right(), style),
130 createFromBorderImageLength(borderImageLengthBox.top(), style),
131 createFromBorderImageLength(borderImageLengthBox.bottom(), style));
134 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLengthBoxAndBool(const LengthBox lengthBox, const bool flag, const RenderStyle& style)
136 return AnimatableLengthBoxAndBool::create(
137 createFromLengthBox(lengthBox, style),
141 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLengthPoint(const LengthPoint& lengthPoint, const RenderStyle& style)
143 return AnimatableLengthPoint::create(
144 createFromLength(lengthPoint.x(), style),
145 createFromLength(lengthPoint.y(), style));
148 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLengthSize(const LengthSize& lengthSize, const RenderStyle& style)
150 return AnimatableLengthSize::create(
151 createFromLength(lengthSize.width(), style),
152 createFromLength(lengthSize.height(), style));
155 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromStyleImage(StyleImage* image)
158 if (RefPtrWillBeRawPtr<CSSValue> cssValue = image->cssValue())
159 return AnimatableImage::create(cssValue.release());
161 return AnimatableUnknown::create(CSSValueNone);
164 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromFillSize(const FillSize& fillSize, const RenderStyle& style)
166 switch (fillSize.type) {
168 return createFromLengthSize(fillSize.size, style);
172 return AnimatableUnknown::create(CSSPrimitiveValue::create(fillSize.type));
174 ASSERT_NOT_REACHED();
179 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromBackgroundPosition(const Length& length, bool originIsSet, BackgroundEdgeOrigin origin, const RenderStyle& style)
181 if (!originIsSet || origin == LeftEdge || origin == TopEdge)
182 return createFromLength(length, style);
183 return createFromLength(length.subtractFromOneHundredPercent(), style);
186 template<CSSPropertyID property>
187 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromFillLayers(const FillLayer& fillLayers, const RenderStyle& style)
189 WillBeHeapVector<RefPtrWillBeMember<AnimatableValue> > values;
190 for (const FillLayer* fillLayer = &fillLayers; fillLayer; fillLayer = fillLayer->next()) {
191 if (property == CSSPropertyBackgroundImage || property == CSSPropertyWebkitMaskImage) {
192 if (!fillLayer->isImageSet())
194 values.append(createFromStyleImage(fillLayer->image()));
195 } else if (property == CSSPropertyBackgroundPositionX || property == CSSPropertyWebkitMaskPositionX) {
196 if (!fillLayer->isXPositionSet())
198 values.append(createFromBackgroundPosition(fillLayer->xPosition(), fillLayer->isBackgroundXOriginSet(), fillLayer->backgroundXOrigin(), style));
199 } else if (property == CSSPropertyBackgroundPositionY || property == CSSPropertyWebkitMaskPositionY) {
200 if (!fillLayer->isYPositionSet())
202 values.append(createFromBackgroundPosition(fillLayer->yPosition(), fillLayer->isBackgroundYOriginSet(), fillLayer->backgroundYOrigin(), style));
203 } else if (property == CSSPropertyBackgroundSize || property == CSSPropertyWebkitMaskSize) {
204 if (!fillLayer->isSizeSet())
206 values.append(createFromFillSize(fillLayer->size(), style));
208 ASSERT_NOT_REACHED();
211 return AnimatableRepeatable::create(values);
214 PassRefPtrWillBeRawPtr<AnimatableValue> CSSAnimatableValueFactory::createFromColor(CSSPropertyID property, const RenderStyle& style)
216 Color color = style.colorIncludingFallback(property, false);
217 Color visitedLinkColor = style.colorIncludingFallback(property, true);
218 return AnimatableColor::create(color, visitedLinkColor);
221 inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromShapeValue(ShapeValue* value)
224 return AnimatableShapeValue::create(value);
225 return AnimatableUnknown::create(CSSValueNone);
228 static double fontStretchToDouble(FontStretch fontStretch)
230 return static_cast<unsigned>(fontStretch);
233 static PassRefPtrWillBeRawPtr<AnimatableValue> createFromFontStretch(FontStretch fontStretch)
235 return createFromDouble(fontStretchToDouble(fontStretch));
238 static double fontWeightToDouble(FontWeight fontWeight)
240 switch (fontWeight) {
261 ASSERT_NOT_REACHED();
265 static PassRefPtrWillBeRawPtr<AnimatableValue> createFromFontWeight(FontWeight fontWeight)
267 return createFromDouble(fontWeightToDouble(fontWeight));
270 // FIXME: Generate this function.
271 PassRefPtrWillBeRawPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID property, const RenderStyle& style)
273 ASSERT(CSSPropertyMetadata::isAnimatableProperty(property));
275 case CSSPropertyBackgroundColor:
276 return createFromColor(property, style);
277 case CSSPropertyBackgroundImage:
278 return createFromFillLayers<CSSPropertyBackgroundImage>(style.backgroundLayers(), style);
279 case CSSPropertyBackgroundPositionX:
280 return createFromFillLayers<CSSPropertyBackgroundPositionX>(style.backgroundLayers(), style);
281 case CSSPropertyBackgroundPositionY:
282 return createFromFillLayers<CSSPropertyBackgroundPositionY>(style.backgroundLayers(), style);
283 case CSSPropertyBackgroundSize:
284 case CSSPropertyWebkitBackgroundSize:
285 return createFromFillLayers<CSSPropertyBackgroundSize>(style.backgroundLayers(), style);
286 case CSSPropertyBaselineShift:
287 return AnimatableSVGLength::create(style.baselineShiftValue());
288 case CSSPropertyBorderBottomColor:
289 return createFromColor(property, style);
290 case CSSPropertyBorderBottomLeftRadius:
291 return createFromLengthSize(style.borderBottomLeftRadius(), style);
292 case CSSPropertyBorderBottomRightRadius:
293 return createFromLengthSize(style.borderBottomRightRadius(), style);
294 case CSSPropertyBorderBottomWidth:
295 return createFromDouble(style.borderBottomWidth());
296 case CSSPropertyBorderImageOutset:
297 return createFromBorderImageLengthBox(style.borderImageOutset(), style);
298 case CSSPropertyBorderImageSlice:
299 return createFromLengthBox(style.borderImageSlices(), style);
300 case CSSPropertyBorderImageSource:
301 return createFromStyleImage(style.borderImageSource());
302 case CSSPropertyBorderImageWidth:
303 return createFromBorderImageLengthBox(style.borderImageWidth(), style);
304 case CSSPropertyBorderLeftColor:
305 return createFromColor(property, style);
306 case CSSPropertyBorderLeftWidth:
307 return createFromDouble(style.borderLeftWidth());
308 case CSSPropertyBorderRightColor:
309 return createFromColor(property, style);
310 case CSSPropertyBorderRightWidth:
311 return createFromDouble(style.borderRightWidth());
312 case CSSPropertyBorderTopColor:
313 return createFromColor(property, style);
314 case CSSPropertyBorderTopLeftRadius:
315 return createFromLengthSize(style.borderTopLeftRadius(), style);
316 case CSSPropertyBorderTopRightRadius:
317 return createFromLengthSize(style.borderTopRightRadius(), style);
318 case CSSPropertyBorderTopWidth:
319 return createFromDouble(style.borderTopWidth());
320 case CSSPropertyBottom:
321 return createFromLength(style.bottom(), style);
322 case CSSPropertyBoxShadow:
323 case CSSPropertyWebkitBoxShadow:
324 return AnimatableShadow::create(style.boxShadow());
325 case CSSPropertyClip:
327 return createFromLengthBox(style.clip(), style);
328 return AnimatableUnknown::create(CSSPrimitiveValue::create(CSSValueAuto));
329 case CSSPropertyColor:
330 return createFromColor(property, style);
331 case CSSPropertyFillOpacity:
332 return createFromDouble(style.fillOpacity());
333 case CSSPropertyFill:
334 return AnimatableSVGPaint::create(
335 style.svgStyle().fillPaintType(), style.svgStyle().visitedLinkFillPaintType(),
336 style.svgStyle().fillPaintColor(), style.svgStyle().visitedLinkFillPaintColor(),
337 style.svgStyle().fillPaintUri(), style.svgStyle().visitedLinkFillPaintUri());
338 case CSSPropertyFlexGrow:
339 return createFromDouble(style.flexGrow(), AnimatableDouble::InterpolationIsNonContinuousWithZero);
340 case CSSPropertyFlexShrink:
341 return createFromDouble(style.flexShrink(), AnimatableDouble::InterpolationIsNonContinuousWithZero);
342 case CSSPropertyFlexBasis:
343 return createFromLength(style.flexBasis(), style);
344 case CSSPropertyFloodColor:
345 return createFromColor(property, style);
346 case CSSPropertyFloodOpacity:
347 return createFromDouble(style.floodOpacity());
348 case CSSPropertyFontSize:
349 // Must pass a specified size to setFontSize if Text Autosizing is enabled, but a computed size
350 // if text zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
351 // FIXME: Should we introduce an option to pass the computed font size here, allowing consumers to
352 // enable text zoom rather than Text Autosizing? See http://crbug.com/227545.
353 return createFromDouble(style.specifiedFontSize());
354 case CSSPropertyFontStretch:
355 return createFromFontStretch(style.fontStretch());
356 case CSSPropertyFontWeight:
357 return createFromFontWeight(style.fontWeight());
358 case CSSPropertyHeight:
359 return createFromLength(style.height(), style);
360 case CSSPropertyLightingColor:
361 return createFromColor(property, style);
362 case CSSPropertyListStyleImage:
363 return createFromStyleImage(style.listStyleImage());
364 case CSSPropertyLeft:
365 return createFromLength(style.left(), style);
366 case CSSPropertyLetterSpacing:
367 return createFromDouble(style.letterSpacing());
368 case CSSPropertyLineHeight:
369 return createFromLineHeight(style.specifiedLineHeight(), style);
370 case CSSPropertyMarginBottom:
371 return createFromLength(style.marginBottom(), style);
372 case CSSPropertyMarginLeft:
373 return createFromLength(style.marginLeft(), style);
374 case CSSPropertyMarginRight:
375 return createFromLength(style.marginRight(), style);
376 case CSSPropertyMarginTop:
377 return createFromLength(style.marginTop(), style);
378 case CSSPropertyMaxHeight:
379 return createFromLength(style.maxHeight(), style);
380 case CSSPropertyMaxWidth:
381 return createFromLength(style.maxWidth(), style);
382 case CSSPropertyMinHeight:
383 return createFromLength(style.minHeight(), style);
384 case CSSPropertyMinWidth:
385 return createFromLength(style.minWidth(), style);
386 case CSSPropertyObjectPosition:
387 return createFromLengthPoint(style.objectPosition(), style);
388 case CSSPropertyOpacity:
389 return createFromDouble(style.opacity());
390 case CSSPropertyOrphans:
391 return createFromDouble(style.orphans());
392 case CSSPropertyOutlineColor:
393 return createFromColor(property, style);
394 case CSSPropertyOutlineOffset:
395 return createFromDouble(style.outlineOffset());
396 case CSSPropertyOutlineWidth:
397 return createFromDouble(style.outlineWidth());
398 case CSSPropertyPaddingBottom:
399 return createFromLength(style.paddingBottom(), style);
400 case CSSPropertyPaddingLeft:
401 return createFromLength(style.paddingLeft(), style);
402 case CSSPropertyPaddingRight:
403 return createFromLength(style.paddingRight(), style);
404 case CSSPropertyPaddingTop:
405 return createFromLength(style.paddingTop(), style);
406 case CSSPropertyRight:
407 return createFromLength(style.right(), style);
408 case CSSPropertyStrokeWidth:
409 return AnimatableSVGLength::create(style.strokeWidth());
410 case CSSPropertyStopColor:
411 return createFromColor(property, style);
412 case CSSPropertyStopOpacity:
413 return createFromDouble(style.stopOpacity());
414 case CSSPropertyStrokeDasharray:
415 return AnimatableStrokeDasharrayList::create(style.strokeDashArray());
416 case CSSPropertyStrokeDashoffset:
417 return AnimatableSVGLength::create(style.strokeDashOffset());
418 case CSSPropertyStrokeMiterlimit:
419 return createFromDouble(style.strokeMiterLimit());
420 case CSSPropertyStrokeOpacity:
421 return createFromDouble(style.strokeOpacity());
422 case CSSPropertyStroke:
423 return AnimatableSVGPaint::create(
424 style.svgStyle().strokePaintType(), style.svgStyle().visitedLinkStrokePaintType(),
425 style.svgStyle().strokePaintColor(), style.svgStyle().visitedLinkStrokePaintColor(),
426 style.svgStyle().strokePaintUri(), style.svgStyle().visitedLinkStrokePaintUri());
427 case CSSPropertyTextDecorationColor:
428 return AnimatableColor::create(style.textDecorationColor().resolve(style.color()), style.visitedLinkTextDecorationColor().resolve(style.visitedLinkColor()));
429 case CSSPropertyTextIndent:
430 return createFromLength(style.textIndent(), style);
431 case CSSPropertyTextShadow:
432 return AnimatableShadow::create(style.textShadow());
434 return createFromLength(style.top(), style);
435 case CSSPropertyWebkitBorderHorizontalSpacing:
436 return createFromDouble(style.horizontalBorderSpacing());
437 case CSSPropertyWebkitBorderVerticalSpacing:
438 return createFromDouble(style.verticalBorderSpacing());
439 case CSSPropertyWebkitClipPath:
440 if (ClipPathOperation* operation = style.clipPath())
441 return AnimatableClipPathOperation::create(operation);
442 return AnimatableUnknown::create(CSSValueNone);
443 case CSSPropertyWebkitColumnCount:
444 return createFromDouble(style.columnCount());
445 case CSSPropertyWebkitColumnGap:
446 return createFromDouble(style.columnGap());
447 case CSSPropertyWebkitColumnRuleColor:
448 return createFromColor(property, style);
449 case CSSPropertyWebkitColumnRuleWidth:
450 return createFromDouble(style.columnRuleWidth());
451 case CSSPropertyWebkitColumnWidth:
452 return createFromDouble(style.columnWidth());
453 case CSSPropertyWebkitFilter:
454 return AnimatableFilterOperations::create(style.filter());
455 case CSSPropertyWebkitMaskBoxImageOutset:
456 return createFromBorderImageLengthBox(style.maskBoxImageOutset(), style);
457 case CSSPropertyWebkitMaskBoxImageSlice:
458 return createFromLengthBoxAndBool(style.maskBoxImageSlices(), style.maskBoxImageSlicesFill(), style);
459 case CSSPropertyWebkitMaskBoxImageSource:
460 return createFromStyleImage(style.maskBoxImageSource());
461 case CSSPropertyWebkitMaskBoxImageWidth:
462 return createFromBorderImageLengthBox(style.maskBoxImageWidth(), style);
463 case CSSPropertyWebkitMaskImage:
464 return createFromFillLayers<CSSPropertyWebkitMaskImage>(style.maskLayers(), style);
465 case CSSPropertyWebkitMaskPositionX:
466 return createFromFillLayers<CSSPropertyWebkitMaskPositionX>(style.maskLayers(), style);
467 case CSSPropertyWebkitMaskPositionY:
468 return createFromFillLayers<CSSPropertyWebkitMaskPositionY>(style.maskLayers(), style);
469 case CSSPropertyWebkitMaskSize:
470 return createFromFillLayers<CSSPropertyWebkitMaskSize>(style.maskLayers(), style);
471 case CSSPropertyPerspective:
472 return createFromDouble(style.perspective());
473 case CSSPropertyPerspectiveOrigin:
474 return AnimatableLengthPoint::create(
475 createFromLength(style.perspectiveOriginX(), style),
476 createFromLength(style.perspectiveOriginY(), style));
477 case CSSPropertyShapeOutside:
478 return createFromShapeValue(style.shapeOutside());
479 case CSSPropertyShapeMargin:
480 return createFromLength(style.shapeMargin(), style);
481 case CSSPropertyShapeImageThreshold:
482 return createFromDouble(style.shapeImageThreshold());
483 case CSSPropertyWebkitTextStrokeColor:
484 return createFromColor(property, style);
485 case CSSPropertyTransform:
486 return AnimatableTransform::create(style.transform());
487 case CSSPropertyTransformOrigin:
488 return AnimatableLengthPoint3D::create(
489 createFromLength(style.transformOriginX(), style),
490 createFromLength(style.transformOriginY(), style),
491 createFromDouble(style.transformOriginZ()));
492 case CSSPropertyWidows:
493 return createFromDouble(style.widows());
494 case CSSPropertyWidth:
495 return createFromLength(style.width(), style);
496 case CSSPropertyWordSpacing:
497 return createFromDouble(style.wordSpacing());
498 case CSSPropertyVerticalAlign:
499 if (style.verticalAlign() == LENGTH)
500 return createFromLength(style.verticalAlignLength(), style);
501 return AnimatableUnknown::create(CSSPrimitiveValue::create(style.verticalAlign()));
502 case CSSPropertyVisibility:
503 return AnimatableVisibility::create(style.visibility());
504 case CSSPropertyZIndex:
505 return createFromDouble(style.zIndex());
506 case CSSPropertyZoom:
507 return createFromDouble(style.zoom());
509 ASSERT_NOT_REACHED();
510 // This return value is to avoid a release crash if possible.
511 return AnimatableUnknown::create(nullptr);