bool RotateTransformOperation::operator==(const TransformOperation& other) const { if (!isSameType(other)) return false; const Rotation& otherRotation = toRotateTransformOperation(other).m_rotation; return m_rotation.axis == otherRotation.axis && m_rotation.angle == otherRotation.angle; }
PassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) { if (from && !from->isSameType(*this)) return this; if (blendToIdentity) return RotateTransformOperation::create(Rotation(axis(), angle() * (1 - progress)), m_type); // Optimize for single axis rotation if (!from) return RotateTransformOperation::create(Rotation(axis(), angle() * progress), m_type); const RotateTransformOperation& fromRotate = toRotateTransformOperation(*from); if (type() == Rotate3D) { return RotateTransformOperation::create( Rotation::slerp(fromRotate.m_rotation, m_rotation, progress), Rotate3D); } ASSERT(axis() == fromRotate.axis()); return RotateTransformOperation::create(Rotation(axis(), blink::blend(fromRotate.angle(), angle(), progress)), m_type); }
// 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(); } }
int GraphicsLayer::validateTransformOperations(const KeyframeValueList& valueList, bool& hasBigRotation) { ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); hasBigRotation = false; if (valueList.size() < 2) return -1; // Empty transforms match anything, so find the first non-empty entry as the reference. size_t firstIndex = 0; for ( ; firstIndex < valueList.size(); ++firstIndex) { if (!operationsAt(valueList, firstIndex).operations().isEmpty()) break; } if (firstIndex >= valueList.size()) return -1; const TransformOperations& firstVal = operationsAt(valueList, firstIndex); // See if the keyframes are valid. for (size_t i = firstIndex + 1; i < valueList.size(); ++i) { const TransformOperations& val = operationsAt(valueList, i); // An empty transform list matches anything. if (val.operations().isEmpty()) continue; if (!firstVal.operationsMatch(val)) return -1; } // Keyframes are valid, check for big rotations. double lastRotAngle = 0.0; double maxRotAngle = -1.0; for (size_t j = 0; j < firstVal.operations().size(); ++j) { TransformOperation::OperationType type = firstVal.operations().at(j)->type(); // if this is a rotation entry, we need to see if any angle differences are >= 180 deg if (type == TransformOperation::ROTATE_X || type == TransformOperation::ROTATE_Y || type == TransformOperation::ROTATE_Z || type == TransformOperation::ROTATE_3D) { lastRotAngle = toRotateTransformOperation(firstVal.operations().at(j).get())->angle(); if (maxRotAngle < 0) maxRotAngle = fabs(lastRotAngle); for (size_t i = firstIndex + 1; i < valueList.size(); ++i) { const TransformOperations& val = operationsAt(valueList, i); double rotAngle = val.operations().isEmpty() ? 0 : (toRotateTransformOperation(val.operations().at(j).get())->angle()); double diffAngle = fabs(rotAngle - lastRotAngle); if (diffAngle > maxRotAngle) maxRotAngle = diffAngle; lastRotAngle = rotAngle; } } } hasBigRotation = maxRotAngle >= 180.0; return firstIndex; }