PassRefPtr<AnimatableValue> AnimatableTransform::interpolateTo(const AnimatableValue* value, double fraction) const { const AnimatableTransform* transform = toAnimatableTransform(value); return AnimatableTransform::create(transform->m_transform.blend(m_transform, fraction)); }
bool AnimatableTransform::equalTo(const AnimatableValue* value) const { return m_transform == toAnimatableTransform(value)->m_transform; }
// FIXME: Generate this function. void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverState& state, const AnimatableValue* value) { ASSERT(CSSPropertyMetadata::isInterpolableProperty(property)); if (value->isUnknown()) { StyleBuilder::applyProperty(property, state, toAnimatableUnknown(value)->toCSSValue().get()); return; } ComputedStyle* style = state.style(); switch (property) { case CSSPropertyBackgroundColor: style->setBackgroundColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkBackgroundColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBackgroundImage: setOnFillLayers<CSSPropertyBackgroundImage>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyBackgroundPositionX: setOnFillLayers<CSSPropertyBackgroundPositionX>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyBackgroundPositionY: setOnFillLayers<CSSPropertyBackgroundPositionY>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyBackgroundSize: setOnFillLayers<CSSPropertyBackgroundSize>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyBaselineShift: style->accessSVGStyle().setBaselineShift(BS_LENGTH); style->accessSVGStyle().setBaselineShiftValue(animatableValueToLength(value, state)); return; case CSSPropertyBorderBottomColor: style->setBorderBottomColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkBorderBottomColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderBottomLeftRadius: style->setBorderBottomLeftRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderBottomRightRadius: style->setBorderBottomRightRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderBottomWidth: style->setBorderBottomWidth(animatableLineWidthClamp<unsigned>(value)); return; case CSSPropertyBorderImageOutset: style->setBorderImageOutset(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyBorderImageSlice: style->setBorderImageSlices(animatableValueToLengthBox(toAnimatableLengthBoxAndBool(value)->box(), state, ValueRangeNonNegative)); style->setBorderImageSlicesFill(toAnimatableLengthBoxAndBool(value)->flag()); return; case CSSPropertyBorderImageSource: style->setBorderImageSource(state.styleImage(property, *toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyBorderImageWidth: style->setBorderImageWidth(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyBorderLeftColor: style->setBorderLeftColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkBorderLeftColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderLeftWidth: style->setBorderLeftWidth(animatableLineWidthClamp<unsigned>(value)); return; case CSSPropertyBorderRightColor: style->setBorderRightColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkBorderRightColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderRightWidth: style->setBorderRightWidth(animatableLineWidthClamp<unsigned>(value)); return; case CSSPropertyBorderTopColor: style->setBorderTopColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkBorderTopColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderTopLeftRadius: style->setBorderTopLeftRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderTopRightRadius: style->setBorderTopRightRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderTopWidth: style->setBorderTopWidth(animatableLineWidthClamp<unsigned>(value)); return; case CSSPropertyBottom: style->setBottom(animatableValueToLength(value, state)); return; case CSSPropertyBoxShadow: style->setBoxShadow(toAnimatableShadow(value)->shadowList()); return; case CSSPropertyClip: style->setClip(animatableValueToLengthBox(value, state)); return; case CSSPropertyColor: style->setColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyFillOpacity: style->setFillOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyFill: { const AnimatableSVGPaint* svgPaint = toAnimatableSVGPaint(value); style->accessSVGStyle().setFillPaint(svgPaint->paintType(), svgPaint->getColor(), svgPaint->uri(), true, false); style->accessSVGStyle().setFillPaint(svgPaint->visitedLinkPaintType(), svgPaint->visitedLinkColor(), svgPaint->visitedLinkURI(), false, true); } return; case CSSPropertyFlexGrow: style->setFlexGrow(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyFlexShrink: style->setFlexShrink(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyFlexBasis: style->setFlexBasis(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyFloodColor: style->setFloodColor(toAnimatableColor(value)->getColor()); return; case CSSPropertyFloodOpacity: style->setFloodOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyFontSize: state.fontBuilder().setSize(animatableValueToFontSize(value)); return; case CSSPropertyFontSizeAdjust: state.fontBuilder().setSizeAdjust(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyFontStretch: state.fontBuilder().setStretch(animatableValueToFontStretch(value)); return; case CSSPropertyFontWeight: state.fontBuilder().setWeight(animatableValueToFontWeight(value)); return; case CSSPropertyHeight: style->setHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyLeft: style->setLeft(animatableValueToLength(value, state)); return; case CSSPropertyLightingColor: style->setLightingColor(toAnimatableColor(value)->getColor()); return; case CSSPropertyLineHeight: if (value->isLength()) style->setLineHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); else style->setLineHeight(Length(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0), Percent)); return; case CSSPropertyListStyleImage: style->setListStyleImage(state.styleImage(property, *toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyLetterSpacing: style->setLetterSpacing(clampTo<float>(toAnimatableDouble(value)->toDouble())); return; case CSSPropertyMarginBottom: style->setMarginBottom(animatableValueToLength(value, state)); return; case CSSPropertyMarginLeft: style->setMarginLeft(animatableValueToLength(value, state)); return; case CSSPropertyMarginRight: style->setMarginRight(animatableValueToLength(value, state)); return; case CSSPropertyMarginTop: style->setMarginTop(animatableValueToLength(value, state)); return; case CSSPropertyMaxHeight: style->setMaxHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMaxWidth: style->setMaxWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMinHeight: style->setMinHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMinWidth: style->setMinWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyObjectPosition: style->setObjectPosition(animatableValueToLengthPoint(value, state)); return; case CSSPropertyOpacity: // Avoiding a value of 1 forces a layer to be created. style->setOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, nextafterf(1, 0))); return; case CSSPropertyOrphans: style->setOrphans(clampTo<short>(round(toAnimatableDouble(value)->toDouble()), 1)); return; case CSSPropertyOutlineColor: style->setOutlineColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkOutlineColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyOutlineOffset: style->setOutlineOffset(animatableValueClampTo<int>(value)); return; case CSSPropertyOutlineWidth: style->setOutlineWidth(animatableLineWidthClamp<unsigned short>(value)); return; case CSSPropertyPaddingBottom: style->setPaddingBottom(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingLeft: style->setPaddingLeft(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingRight: style->setPaddingRight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingTop: style->setPaddingTop(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyRight: style->setRight(animatableValueToLength(value, state)); return; case CSSPropertyStrokeWidth: style->setStrokeWidth(animatableValueToUnzoomedLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyStopColor: style->setStopColor(toAnimatableColor(value)->getColor()); return; case CSSPropertyStopOpacity: style->setStopOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyStrokeDasharray: style->setStrokeDashArray(toAnimatableStrokeDasharrayList(value)->toSVGDashArray(style->effectiveZoom())); return; case CSSPropertyStrokeDashoffset: style->setStrokeDashOffset(animatableValueToLength(value, state)); return; case CSSPropertyStrokeMiterlimit: style->setStrokeMiterLimit(clampTo<float>(toAnimatableDouble(value)->toDouble(), 1)); return; case CSSPropertyStrokeOpacity: style->setStrokeOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyStroke: { const AnimatableSVGPaint* svgPaint = toAnimatableSVGPaint(value); style->accessSVGStyle().setStrokePaint(svgPaint->paintType(), svgPaint->getColor(), svgPaint->uri(), true, false); style->accessSVGStyle().setStrokePaint(svgPaint->visitedLinkPaintType(), svgPaint->visitedLinkColor(), svgPaint->visitedLinkURI(), false, true); } return; case CSSPropertyTextDecorationColor: style->setTextDecorationColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkTextDecorationColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyTextIndent: style->setTextIndent(animatableValueToLength(value, state)); return; case CSSPropertyTextShadow: style->setTextShadow(toAnimatableShadow(value)->shadowList()); return; case CSSPropertyTop: style->setTop(animatableValueToLength(value, state)); return; case CSSPropertyWebkitBorderHorizontalSpacing: style->setHorizontalBorderSpacing(animatableValueClampTo<unsigned short>(value)); return; case CSSPropertyWebkitBorderVerticalSpacing: style->setVerticalBorderSpacing(animatableValueClampTo<unsigned short>(value)); return; case CSSPropertyWebkitClipPath: style->setClipPath(toAnimatableClipPathOperation(value)->clipPathOperation()); return; case CSSPropertyColumnCount: style->setColumnCount(clampTo<unsigned short>(round(toAnimatableDouble(value)->toDouble()), 1)); return; case CSSPropertyColumnGap: style->setColumnGap(clampTo(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyColumnRuleColor: style->setColumnRuleColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkColumnRuleColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyColumnWidth: style->setColumnWidth(clampTo(toAnimatableDouble(value)->toDouble(), std::numeric_limits<float>::epsilon())); return; case CSSPropertyColumnRuleWidth: style->setColumnRuleWidth(animatableLineWidthClamp<unsigned short>(value)); return; case CSSPropertyWebkitFilter: style->setFilter(toAnimatableFilterOperations(value)->operations()); return; case CSSPropertyBackdropFilter: style->setBackdropFilter(toAnimatableFilterOperations(value)->operations()); return; case CSSPropertyWebkitMaskBoxImageOutset: style->setMaskBoxImageOutset(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyWebkitMaskBoxImageSlice: style->setMaskBoxImageSlices(animatableValueToLengthBox(toAnimatableLengthBoxAndBool(value)->box(), state, ValueRangeNonNegative)); style->setMaskBoxImageSlicesFill(toAnimatableLengthBoxAndBool(value)->flag()); return; case CSSPropertyWebkitMaskBoxImageSource: style->setMaskBoxImageSource(state.styleImage(property, *toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyWebkitMaskBoxImageWidth: style->setMaskBoxImageWidth(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyWebkitMaskImage: setOnFillLayers<CSSPropertyWebkitMaskImage>(style->accessMaskLayers(), value, state); return; case CSSPropertyWebkitMaskPositionX: setOnFillLayers<CSSPropertyWebkitMaskPositionX>(style->accessMaskLayers(), value, state); return; case CSSPropertyWebkitMaskPositionY: setOnFillLayers<CSSPropertyWebkitMaskPositionY>(style->accessMaskLayers(), value, state); return; case CSSPropertyWebkitMaskSize: setOnFillLayers<CSSPropertyWebkitMaskSize>(style->accessMaskLayers(), value, state); return; case CSSPropertyPerspective: style->setPerspective(value->isDouble() ? clampTo<float>(toAnimatableDouble(value)->toDouble()) : 0); return; case CSSPropertyPerspectiveOrigin: style->setPerspectiveOrigin(animatableValueToLengthPoint(value, state)); return; case CSSPropertyShapeOutside: style->setShapeOutside(toAnimatableShapeValue(value)->shapeValue()); return; case CSSPropertyShapeMargin: style->setShapeMargin(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyShapeImageThreshold: style->setShapeImageThreshold(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyWebkitTextStrokeColor: style->setTextStrokeColor(toAnimatableColor(value)->getColor()); style->setVisitedLinkTextStrokeColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyTransform: { const TransformOperations& operations = toAnimatableTransform(value)->transformOperations(); // FIXME: This normalization (handling of 'none') should be performed at input in AnimatableValueFactory. if (operations.size() == 0) { style->setTransform(TransformOperations(true)); return; } double sourceZoom = toAnimatableTransform(value)->zoom(); double destinationZoom = style->effectiveZoom(); style->setTransform(sourceZoom == destinationZoom ? operations : operations.zoom(destinationZoom / sourceZoom)); return; } case CSSPropertyTranslate: { TranslateTransformOperation* translate = toTranslateTransformOperation(animatableValueToTransformOperation(value, TransformOperation::Translate3D)); double sourceZoom = toAnimatableTransform(value)->zoom(); double destinationZoom = style->effectiveZoom(); style->setTranslate(sourceZoom == destinationZoom ? translate : translate->zoomTranslate(destinationZoom / sourceZoom)); return; } case CSSPropertyRotate: { style->setRotate(toRotateTransformOperation(animatableValueToTransformOperation(value, TransformOperation::Rotate3D))); return; } case CSSPropertyScale: { style->setScale(toScaleTransformOperation(animatableValueToTransformOperation(value, TransformOperation::Scale3D))); return; } case CSSPropertyTransformOrigin: style->setTransformOrigin(animatableValueToTransformOrigin(value, state)); return; case CSSPropertyMotionOffset: style->setMotionOffset(animatableValueToLength(value, state)); return; case CSSPropertyMotionRotation: style->setMotionRotation(StyleMotionRotation( toAnimatableDoubleAndBool(value)->toDouble(), toAnimatableDoubleAndBool(value)->flag() ? MotionRotationAuto : MotionRotationFixed)); return; case CSSPropertyWebkitPerspectiveOriginX: style->setPerspectiveOriginX(animatableValueToLength(value, state)); return; case CSSPropertyWebkitPerspectiveOriginY: style->setPerspectiveOriginY(animatableValueToLength(value, state)); return; case CSSPropertyWebkitTransformOriginX: style->setTransformOriginX(animatableValueToLength(value, state)); return; case CSSPropertyWebkitTransformOriginY: style->setTransformOriginY(animatableValueToLength(value, state)); return; case CSSPropertyWebkitTransformOriginZ: style->setTransformOriginZ(toAnimatableDouble(value)->toDouble()); return; case CSSPropertyWidows: style->setWidows(clampTo<short>(round(toAnimatableDouble(value)->toDouble()), 1)); return; case CSSPropertyWidth: style->setWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyWordSpacing: style->setWordSpacing(clampTo<float>(toAnimatableDouble(value)->toDouble())); return; case CSSPropertyVerticalAlign: style->setVerticalAlignLength(animatableValueToLength(value, state)); return; case CSSPropertyVisibility: style->setVisibility(toAnimatableVisibility(value)->visibility()); return; case CSSPropertyZIndex: style->setZIndex(clampTo<int>(round(toAnimatableDouble(value)->toDouble()))); return; case CSSPropertyD: style->setD(toAnimatablePath(value)->path()); return; case CSSPropertyCx: style->setCx(animatableValueToLength(value, state)); return; case CSSPropertyCy: style->setCy(animatableValueToLength(value, state)); return; case CSSPropertyX: style->setX(animatableValueToLength(value, state)); return; case CSSPropertyY: style->setY(animatableValueToLength(value, state)); return; case CSSPropertyR: style->setR(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyRx: style->setRx(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyRy: style->setRy(animatableValueToLength(value, state, ValueRangeNonNegative)); return; default: ASSERT_NOT_REACHED(); } }
// FIXME: Generate this function. void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverState& state, const AnimatableValue* value) { ASSERT(CSSAnimations::isAnimatableProperty(property)); if (value->isUnknown()) { StyleBuilder::applyProperty(property, state, toAnimatableUnknown(value)->toCSSValue().get()); return; } RenderStyle* style = state.style(); switch (property) { case CSSPropertyBackgroundColor: style->setBackgroundColor(toAnimatableColor(value)->color()); style->setVisitedLinkBackgroundColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBackgroundImage: setOnFillLayers<CSSPropertyBackgroundImage>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyBackgroundPositionX: setOnFillLayers<CSSPropertyBackgroundPositionX>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyBackgroundPositionY: setOnFillLayers<CSSPropertyBackgroundPositionY>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyBackgroundSize: setOnFillLayers<CSSPropertyBackgroundSize>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyBaselineShift: style->setBaselineShiftValue(toAnimatableSVGLength(value)->toSVGLength()); return; case CSSPropertyBorderBottomColor: style->setBorderBottomColor(toAnimatableColor(value)->color()); style->setVisitedLinkBorderBottomColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderBottomLeftRadius: style->setBorderBottomLeftRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderBottomRightRadius: style->setBorderBottomRightRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderBottomWidth: style->setBorderBottomWidth(animatableValueRoundClampTo<unsigned>(value)); return; case CSSPropertyBorderImageOutset: style->setBorderImageOutset(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyBorderImageSlice: style->setBorderImageSlices(animatableValueToLengthBox(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderImageSource: style->setBorderImageSource(state.styleImage(property, toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyBorderImageWidth: style->setBorderImageWidth(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyBorderLeftColor: style->setBorderLeftColor(toAnimatableColor(value)->color()); style->setVisitedLinkBorderLeftColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderLeftWidth: style->setBorderLeftWidth(animatableValueRoundClampTo<unsigned>(value)); return; case CSSPropertyBorderRightColor: style->setBorderRightColor(toAnimatableColor(value)->color()); style->setVisitedLinkBorderRightColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderRightWidth: style->setBorderRightWidth(animatableValueRoundClampTo<unsigned>(value)); return; case CSSPropertyBorderTopColor: style->setBorderTopColor(toAnimatableColor(value)->color()); style->setVisitedLinkBorderTopColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderTopLeftRadius: style->setBorderTopLeftRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderTopRightRadius: style->setBorderTopRightRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderTopWidth: style->setBorderTopWidth(animatableValueRoundClampTo<unsigned>(value)); return; case CSSPropertyBottom: style->setBottom(animatableValueToLength(value, state)); return; case CSSPropertyBoxShadow: case CSSPropertyWebkitBoxShadow: style->setBoxShadow(toAnimatableShadow(value)->shadowList()); return; case CSSPropertyClip: style->setClip(animatableValueToLengthBox(value, state)); style->setHasClip(true); return; case CSSPropertyColor: style->setColor(toAnimatableColor(value)->color()); style->setVisitedLinkColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyFillOpacity: style->setFillOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyFill: { const AnimatableSVGPaint* svgPaint = toAnimatableSVGPaint(value); style->accessSVGStyle()->setFillPaint(svgPaint->paintType(), svgPaint->color(), svgPaint->uri(), true, false); style->accessSVGStyle()->setFillPaint(svgPaint->visitedLinkPaintType(), svgPaint->visitedLinkColor(), svgPaint->visitedLinkURI(), false, true); } return; case CSSPropertyFlexGrow: style->setFlexGrow(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyFlexShrink: style->setFlexShrink(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyFlexBasis: style->setFlexBasis(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyFloodColor: style->setFloodColor(toAnimatableColor(value)->color()); return; case CSSPropertyFloodOpacity: style->setFloodOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyFontSize: style->setFontSize(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyFontWeight: style->setFontWeight(animatableValueToFontWeight(value)); return; case CSSPropertyHeight: style->setHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyLeft: style->setLeft(animatableValueToLength(value, state)); return; case CSSPropertyLightingColor: style->setLightingColor(toAnimatableColor(value)->color()); return; case CSSPropertyLineHeight: if (value->isLength()) style->setLineHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); else style->setLineHeight(Length(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0), Percent)); return; case CSSPropertyListStyleImage: style->setListStyleImage(state.styleImage(property, toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyLetterSpacing: style->setLetterSpacing(clampTo<float>(toAnimatableDouble(value)->toDouble())); return; case CSSPropertyMarginBottom: style->setMarginBottom(animatableValueToLength(value, state)); return; case CSSPropertyMarginLeft: style->setMarginLeft(animatableValueToLength(value, state)); return; case CSSPropertyMarginRight: style->setMarginRight(animatableValueToLength(value, state)); return; case CSSPropertyMarginTop: style->setMarginTop(animatableValueToLength(value, state)); return; case CSSPropertyMaxHeight: style->setMaxHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMaxWidth: style->setMaxWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMinHeight: style->setMinHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMinWidth: style->setMinWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyObjectPosition: style->setObjectPosition(animatableValueToLengthPoint(value, state)); return; case CSSPropertyOpacity: // Avoiding a value of 1 forces a layer to be created. style->setOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, nextafterf(1, 0))); return; case CSSPropertyOrphans: style->setOrphans(animatableValueRoundClampTo<unsigned short>(value, 1)); return; case CSSPropertyOutlineColor: style->setOutlineColor(toAnimatableColor(value)->color()); style->setVisitedLinkOutlineColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyOutlineOffset: style->setOutlineOffset(animatableValueRoundClampTo<int>(value)); return; case CSSPropertyOutlineWidth: style->setOutlineWidth(animatableValueRoundClampTo<unsigned short>(value)); return; case CSSPropertyPaddingBottom: style->setPaddingBottom(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingLeft: style->setPaddingLeft(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingRight: style->setPaddingRight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingTop: style->setPaddingTop(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyRight: style->setRight(animatableValueToLength(value, state)); return; case CSSPropertyStrokeWidth: style->setStrokeWidth(animatableValueToNonNegativeSVGLength(value)); return; case CSSPropertyStopColor: style->setStopColor(toAnimatableColor(value)->color()); return; case CSSPropertyStopOpacity: style->setStopOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyStrokeDasharray: style->setStrokeDashArray(toAnimatableStrokeDasharrayList(value)->toSVGLengthList()); return; case CSSPropertyStrokeDashoffset: style->setStrokeDashOffset(toAnimatableSVGLength(value)->toSVGLength()); return; case CSSPropertyStrokeMiterlimit: style->setStrokeMiterLimit(clampTo<float>(toAnimatableDouble(value)->toDouble(), 1)); return; case CSSPropertyStrokeOpacity: style->setStrokeOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyStroke: { const AnimatableSVGPaint* svgPaint = toAnimatableSVGPaint(value); style->accessSVGStyle()->setStrokePaint(svgPaint->paintType(), svgPaint->color(), svgPaint->uri(), true, false); style->accessSVGStyle()->setStrokePaint(svgPaint->visitedLinkPaintType(), svgPaint->visitedLinkColor(), svgPaint->visitedLinkURI(), false, true); } return; case CSSPropertyTextDecorationColor: style->setTextDecorationColor(toAnimatableColor(value)->color()); style->setVisitedLinkTextDecorationColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyTextIndent: style->setTextIndent(animatableValueToLength(value, state)); return; case CSSPropertyTextShadow: style->setTextShadow(toAnimatableShadow(value)->shadowList()); return; case CSSPropertyTop: style->setTop(animatableValueToLength(value, state)); return; case CSSPropertyWebkitBackgroundSize: setOnFillLayers<CSSPropertyWebkitBackgroundSize>(style->accessBackgroundLayers(), value, state); return; case CSSPropertyWebkitBorderHorizontalSpacing: style->setHorizontalBorderSpacing(animatableValueRoundClampTo<unsigned short>(value)); return; case CSSPropertyWebkitBorderVerticalSpacing: style->setVerticalBorderSpacing(animatableValueRoundClampTo<unsigned short>(value)); return; case CSSPropertyWebkitClipPath: style->setClipPath(toAnimatableClipPathOperation(value)->clipPathOperation()); return; case CSSPropertyWebkitColumnCount: style->setColumnCount(animatableValueRoundClampTo<unsigned short>(value, 1)); return; case CSSPropertyWebkitColumnGap: style->setColumnGap(clampTo(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyWebkitColumnRuleColor: style->setColumnRuleColor(toAnimatableColor(value)->color()); style->setVisitedLinkColumnRuleColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyWebkitColumnWidth: style->setColumnWidth(clampTo(toAnimatableDouble(value)->toDouble(), std::numeric_limits<float>::epsilon())); return; case CSSPropertyWebkitColumnRuleWidth: style->setColumnRuleWidth(animatableValueRoundClampTo<unsigned short>(value)); return; case CSSPropertyWebkitFilter: style->setFilter(toAnimatableFilterOperations(value)->operations()); return; case CSSPropertyWebkitMaskBoxImageOutset: style->setMaskBoxImageOutset(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyWebkitMaskBoxImageSlice: style->setMaskBoxImageSlices(animatableValueToLengthBox(toAnimatableLengthBoxAndBool(value)->box(), state, ValueRangeNonNegative)); style->setMaskBoxImageSlicesFill(toAnimatableLengthBoxAndBool(value)->flag()); return; case CSSPropertyWebkitMaskBoxImageSource: style->setMaskBoxImageSource(state.styleImage(property, toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyWebkitMaskBoxImageWidth: style->setMaskBoxImageWidth(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyWebkitMaskImage: setOnFillLayers<CSSPropertyWebkitMaskImage>(style->accessMaskLayers(), value, state); return; case CSSPropertyWebkitMaskPositionX: setOnFillLayers<CSSPropertyWebkitMaskPositionX>(style->accessMaskLayers(), value, state); return; case CSSPropertyWebkitMaskPositionY: setOnFillLayers<CSSPropertyWebkitMaskPositionY>(style->accessMaskLayers(), value, state); return; case CSSPropertyWebkitMaskSize: setOnFillLayers<CSSPropertyWebkitMaskSize>(style->accessMaskLayers(), value, state); return; case CSSPropertyPerspective: style->setPerspective(clampTo<float>(toAnimatableDouble(value)->toDouble())); return; case CSSPropertyPerspectiveOrigin: { ASSERT(RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); const AnimatableLengthPoint* animatableLengthPoint = toAnimatableLengthPoint(value); style->setPerspectiveOriginX(animatableValueToLength(animatableLengthPoint->x(), state)); style->setPerspectiveOriginY(animatableValueToLength(animatableLengthPoint->y(), state)); return; } case CSSPropertyWebkitPerspectiveOriginX: ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setPerspectiveOriginX(animatableValueToLength(value, state)); return; case CSSPropertyWebkitPerspectiveOriginY: ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setPerspectiveOriginY(animatableValueToLength(value, state)); return; case CSSPropertyShapeOutside: style->setShapeOutside(toAnimatableShapeValue(value)->shapeValue()); return; case CSSPropertyShapeMargin: style->setShapeMargin(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyShapeImageThreshold: style->setShapeImageThreshold(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyWebkitTextStrokeColor: style->setTextStrokeColor(toAnimatableColor(value)->color()); style->setVisitedLinkTextStrokeColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyTransform: { const TransformOperations& operations = toAnimatableTransform(value)->transformOperations(); // FIXME: This normalization (handling of 'none') should be performed at input in AnimatableValueFactory. style->setTransform(operations.size() ? operations : TransformOperations(true)); return; } case CSSPropertyTransformOrigin: { ASSERT(RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); const AnimatableLengthPoint3D* animatableLengthPoint3D = toAnimatableLengthPoint3D(value); style->setTransformOriginX(animatableValueToLength(animatableLengthPoint3D->x(), state)); style->setTransformOriginY(animatableValueToLength(animatableLengthPoint3D->y(), state)); style->setTransformOriginZ(clampTo<float>(toAnimatableDouble(animatableLengthPoint3D->z())->toDouble())); return; } case CSSPropertyWebkitTransformOriginX: ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setTransformOriginX(animatableValueToLength(value, state)); return; case CSSPropertyWebkitTransformOriginY: ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setTransformOriginY(animatableValueToLength(value, state)); return; case CSSPropertyWebkitTransformOriginZ: ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setTransformOriginZ(toAnimatableDouble(value)->toDouble()); return; case CSSPropertyWidows: style->setWidows(animatableValueRoundClampTo<unsigned short>(value, 1)); return; case CSSPropertyWidth: style->setWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyWordSpacing: style->setWordSpacing(clampTo<float>(toAnimatableDouble(value)->toDouble())); return; case CSSPropertyVerticalAlign: style->setVerticalAlignLength(animatableValueToLength(value, state)); return; case CSSPropertyVisibility: style->setVisibility(toAnimatableVisibility(value)->visibility()); return; case CSSPropertyZIndex: style->setZIndex(animatableValueRoundClampTo<int>(value)); return; case CSSPropertyZoom: style->setZoom(clampTo<float>(toAnimatableDouble(value)->toDouble(), std::numeric_limits<float>::denorm_min())); return; default: ASSERT_NOT_REACHED(); } }
bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& timing, const AnimationEffect& effect) { const KeyframeEffectModel& keyframeEffect = *toKeyframeEffectModel(&effect); // Are the keyframes convertible? const KeyframeEffectModel::KeyframeVector frames = keyframeEffect.getFrames(); for (size_t i = 0; i < frames.size(); ++i) { // Only replace mode can be accelerated if (frames[i]->composite() != AnimationEffect::CompositeReplace) return false; // Check all the properties can be accelerated const PropertySet properties = frames[i]->properties(); // FIXME: properties creates a whole new PropertySet! if (properties.isEmpty()) return false; for (PropertySet::const_iterator it = properties.begin(); it != properties.end(); ++it) { switch (*it) { case CSSPropertyOpacity: continue; case CSSPropertyWebkitTransform: if (toAnimatableTransform(frames[i]->propertyValue(CSSPropertyWebkitTransform))->transformOperations().dependsOnBoxSize()) return false; continue; case CSSPropertyWebkitFilter: { const FilterOperations& operations = toAnimatableFilterOperations(frames[i]->propertyValue(CSSPropertyWebkitFilter))->operations(); if (operations.hasFilterThatMovesPixels()) return false; for (size_t i = 0; i < operations.size(); i++) { const FilterOperation& op = *operations.at(i); if (op.type() == FilterOperation::VALIDATED_CUSTOM || op.type() == FilterOperation::CUSTOM) return false; } continue; } default: return false; } } } // Is the timing object convertible? CompositorAnimationsImpl::CompositorTiming out; if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, out)) return false; // Is the timing function convertible? switch (timing.timingFunction->type()) { case TimingFunction::LinearFunction: break; case TimingFunction::CubicBezierFunction: // Can have a cubic if we don't have to split it (IE only have two frames). if (frames.size() != 2) return false; ASSERT(frames[0]->offset() == 0.0 && frames[1]->offset() == 1.0); break; case TimingFunction::StepsFunction: return false; case TimingFunction::ChainedFunction: { // Currently we only support chained segments in the form the CSS code // generates. These chained segments are only one level deep and have // one timing function per frame. const ChainedTimingFunction* chained = static_cast<const ChainedTimingFunction*>(timing.timingFunction.get()); if (!chained->m_segments.size()) return false; if (frames.size() != chained->m_segments.size() + 1) return false; for (size_t timeIndex = 0; timeIndex < chained->m_segments.size(); timeIndex++) { const ChainedTimingFunction::Segment& segment = chained->m_segments[timeIndex]; if (frames[timeIndex]->offset() != segment.m_min || frames[timeIndex + 1]->offset() != segment.m_max) return false; switch (segment.m_timingFunction->type()) { case TimingFunction::LinearFunction: case TimingFunction::CubicBezierFunction: continue; case TimingFunction::StepsFunction: case TimingFunction::ChainedFunction: default: return false; } } break; } default: ASSERT_NOT_REACHED(); return false; } return true; }
bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& timing, const Element& targetElement, const Animation* animationToAdd, const EffectModel& effect, double animationPlaybackRate) { const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(effect); PropertyHandleSet properties = keyframeEffect.properties(); if (properties.isEmpty()) return false; unsigned transformPropertyCount = 0; for (const auto& property : properties) { if (!property.isCSSProperty()) return false; if (isTransformRelatedCSSProperty(property)) { if (targetElement.layoutObject() && targetElement.layoutObject()->isInline()) { return false; } transformPropertyCount++; } const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getPropertySpecificKeyframes(property); ASSERT(keyframes.size() >= 2); for (const auto& keyframe : keyframes) { // FIXME: Determine candidacy based on the CSSValue instead of a snapshot AnimatableValue. bool isNeutralKeyframe = keyframe->isCSSPropertySpecificKeyframe() && !toCSSPropertySpecificKeyframe(keyframe.get())->value() && keyframe->composite() == EffectModel::CompositeAdd; if ((keyframe->composite() != EffectModel::CompositeReplace && !isNeutralKeyframe) || !keyframe->getAnimatableValue()) return false; switch (property.cssProperty()) { case CSSPropertyOpacity: break; case CSSPropertyRotate: case CSSPropertyScale: case CSSPropertyTranslate: case CSSPropertyTransform: if (toAnimatableTransform(keyframe->getAnimatableValue().get())->transformOperations().dependsOnBoxSize()) return false; break; case CSSPropertyWebkitFilter: case CSSPropertyBackdropFilter: { const FilterOperations& operations = toAnimatableFilterOperations(keyframe->getAnimatableValue().get())->operations(); if (operations.hasFilterThatMovesPixels()) return false; break; } default: // any other types are not allowed to run on compositor. return false; } } } // TODO: Support multiple transform property animations on the compositor if (transformPropertyCount > 1) return false; if (animationToAdd && hasIncompatibleAnimations(targetElement, *animationToAdd, effect)) return false; CompositorAnimationsImpl::CompositorTiming out; if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, animationPlaybackRate)) return false; return true; }
bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const EffectModel& effect, double minValue, double maxValue) const { const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(effect); PropertyHandleSet properties = keyframeEffect.properties(); if (properties.isEmpty()) return true; minValue = std::min(minValue, 0.0); maxValue = std::max(maxValue, 1.0); for (const auto& property : properties) { if (!property.isCSSProperty()) continue; // TODO: Add the ability to get expanded bounds for filters as well. if (!isTransformRelatedCSSProperty(property)) continue; const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropertySpecificKeyframes(property); if (frames.isEmpty() || frames.size() < 2) continue; FloatBox originalBox(box); for (size_t j = 0; j < frames.size() - 1; ++j) { const AnimatableTransform* startTransform = toAnimatableTransform(frames[j]->getAnimatableValue().get()); const AnimatableTransform* endTransform = toAnimatableTransform(frames[j+1]->getAnimatableValue().get()); if (!startTransform || !endTransform) return false; // TODO: Add support for inflating modes other than Replace. if (frames[j]->composite() != EffectModel::CompositeReplace) return false; const TimingFunction& timing = frames[j]->easing(); double min = 0; double max = 1; if (j == 0) { float frameLength = frames[j+1]->offset(); if (frameLength > 0) { min = minValue / frameLength; } } if (j == frames.size() - 2) { float frameLength = frames[j+1]->offset() - frames[j]->offset(); if (frameLength > 0) { max = 1 + (maxValue - 1) / frameLength; } } FloatBox bounds; timing.range(&min, &max); if (!endTransform->transformOperations().blendedBoundsForBox(originalBox, startTransform->transformOperations(), min, max, &bounds)) return false; box.expandTo(bounds); } } return true; }