void SVGAnimatedTransformListAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, OwnPtr<SVGAnimatedType>& animated)
{
    ASSERT(m_animationElement);

    // Spec: To animations provide specific functionality to get a smooth change from the underlying value to the
    // ‘to’ attribute value, which conflicts mathematically with the requirement for additive transform animations
    // to be post-multiplied. As a consequence, in SVG 1.1 the behavior of to animations for ‘animateTransform’ is undefined.
    // FIXME: This is not taken into account yet.
    SVGTransformList& fromTransformList = from->transformList();
    SVGTransformList& toTransformList = to->transformList();
    SVGTransformList& animatedTransformList = animated->transformList();

    // Pass false to 'resizeAnimatedListIfNeeded' here, as the special post-multiplication behavior of <animateTransform> needs to be respected below.
    if (!m_animationElement->adjustFromToListValues<SVGTransformList>(0, fromTransformList, toTransformList, animatedTransformList, percentage, m_contextElement, false))
        return;

    // Never resize the animatedTransformList to the toTransformList size, instead either clear the list or append to it.
    if (!animatedTransformList.isEmpty() && !m_animationElement->isAdditive())
        animatedTransformList.clear();

    unsigned fromTransformListSize = fromTransformList.size();
    SVGTransform& toTransform = toTransformList[0];
    SVGTransform effectiveFrom = fromTransformListSize ? fromTransformList[0] : SVGTransform(toTransform.type());
    SVGTransform currentTransform = SVGTransformDistance(effectiveFrom, toTransform).scaledDistance(percentage).addToSVGTransform(effectiveFrom);
    if (m_animationElement->isAccumulated() && repeatCount)
        animatedTransformList.append(SVGTransformDistance::addSVGTransforms(currentTransform, toTransform, repeatCount));
    else
        animatedTransformList.append(currentTransform);
}
SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform& transform) const
{
    ASSERT(m_type == transform.type() || transform == SVGTransform());
    
    SVGTransform newTransform(transform);
    
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return SVGTransform();
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        return SVGTransform(transform.matrix() * m_transform);
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        FloatPoint translation = transform.translate();
        translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f());
        newTransform.setTranslate(translation.x(), translation.y());
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        FloatSize scale = transform.scale();
        scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d());
        newTransform.setScale(scale.width(), scale.height());
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_ROTATE:
    {
        // FIXME: I'm not certain the translation is calculated correctly here
        FloatPoint center = transform.rotationCenter();
        newTransform.setRotate(transform.angle() + m_angle,
                               center.x() + m_cx,
                               center.y() + m_cy);
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
        newTransform.setSkewX(transform.angle() + m_angle);
        return newTransform;
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        newTransform.setSkewY(transform.angle() + m_angle);
        return newTransform;
    }
    
    ASSERT_NOT_REACHED();
    return SVGTransform();
}
SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform& first, const SVGTransform& second)
{
    ASSERT(first.type() == second.type());
    
    SVGTransform transform;
    
    switch (first.type()) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return SVGTransform();
    case SVGTransform::SVG_TRANSFORM_ROTATE:
    {
        transform.setRotate(first.angle() + second.angle(), first.rotationCenter().x() + second.rotationCenter().x(),
                            first.rotationCenter().y() + second.rotationCenter().y());
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        transform.setMatrix(first.matrix() * second.matrix());
        return transform;
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        float dx = first.translate().x() + second.translate().x();
        float dy = first.translate().y() + second.translate().y();
        transform.setTranslate(dx, dy);
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        FloatSize scale = first.scale() + second.scale();
        transform.setScale(scale.width(), scale.height());
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
        transform.setSkewX(first.angle() + second.angle());
        return transform;
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        transform.setSkewY(first.angle() + second.angle());
        return transform;
    }
    
    ASSERT_NOT_REACHED();
    return SVGTransform();
}
Beispiel #4
0
SVGTransform SVGTransformList::consolidate()
{
    AffineTransform matrix;
    if (!concatenate(matrix))
        return SVGTransform();

    SVGTransform transform(matrix);
    clear();
    append(transform);
    return transform;
}
Beispiel #5
0
SVGTransform SVGAnimateTransformElement::parseTransformValue(const String& value) const
{
    if (value.isEmpty())
        return SVGTransform(m_type);
    SVGTransform result;
    // FIXME: This is pretty dumb but parseTransformValue() wants those parenthesis.
    String parseString("(" + value + ")");
    const UChar* ptr = parseString.characters();
    SVGTransformable::parseTransformValue(m_type, ptr, ptr + parseString.length(), result); // ignoring return value
    return result;
}
SVGTransform SVGSVGElement::createSVGTransformFromMatrix(const AffineTransform& matrix)
{
    return SVGTransform(matrix);
}
SVGTransform SVGSVGElement::createSVGTransform()
{
    return SVGTransform();
}
SVGTransform SVGSVGElement::createSVGTransform()
{
    return SVGTransform(SVGTransform::SVG_TRANSFORM_MATRIX);
}
Beispiel #9
0
SVGTransform SVGSVGElement::createSVGTransformFromMatrix(const SVGMatrix& matrix)
{
    return SVGTransform(static_cast<const AffineTransform&>(matrix));
}
Beispiel #10
0
SVGTransform SVGSVGElement::createSVGTransformFromMatrix(const TransformationMatrix& matrix)
{
    return SVGTransform(matrix);
}
Beispiel #11
0
void SVGAnimateTransformElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
{
    if (!hasValidTarget())
        return;
    SVGElement* targetElement = resultElement->targetElement();
    RefPtr<SVGTransformList> transformList = transformListFor(targetElement);
    ASSERT(transformList);

    ExceptionCode ec;
    if (!isAdditive())
        transformList->clear(ec);
    if (isAccumulated() && repeat) {
        SVGTransform accumulatedTransform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(repeat).addToSVGTransform(SVGTransform());
        transformList->appendItem(accumulatedTransform, ec);
    }
    SVGTransform transform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(percentage).addToSVGTransform(m_fromTransform);
    transformList->appendItem(transform, ec);
}
void SVGAnimatedTransformListAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType* from, SVGAnimatedType* to, SVGAnimatedType* toAtEndOfDuration, SVGAnimatedType* animated)
{
    ASSERT(m_animationElement);

    // Spec: To animations provide specific functionality to get a smooth change from the underlying value to the
    // ‘to’ attribute value, which conflicts mathematically with the requirement for additive transform animations
    // to be post-multiplied. As a consequence, in SVG 1.1 the behavior of to animations for ‘animateTransform’ is undefined.
    const SVGTransformList& fromTransformList = from->transformList();
    const SVGTransformList& toTransformList = to->transformList();
    const SVGTransformList& toAtEndOfDurationTransformList = toAtEndOfDuration->transformList();
    SVGTransformList& animatedTransformList = animated->transformList();

    // Pass false to 'resizeAnimatedListIfNeeded' here, as the special post-multiplication behavior of <animateTransform> needs to be respected below.
    if (!m_animationElement->adjustFromToListValues<SVGTransformList>(fromTransformList, toTransformList, animatedTransformList, percentage, false))
        return;

    // Never resize the animatedTransformList to the toTransformList size, instead either clear the list or append to it.
    if (!animatedTransformList.isEmpty() && (!m_animationElement->isAdditive() || m_animationElement->animationMode() == ToAnimation))
        animatedTransformList.clear();

    unsigned fromTransformListSize = fromTransformList.size();
    const SVGTransform& toTransform = toTransformList[0];
    const SVGTransform effectiveFrom = fromTransformListSize ? fromTransformList[0] : SVGTransform(toTransform.type(), SVGTransform::ConstructZeroTransform);
    SVGTransform currentTransform = SVGTransformDistance(effectiveFrom, toTransform).scaledDistance(percentage).addToSVGTransform(effectiveFrom);
    if (m_animationElement->isAccumulated() && repeatCount) {
        const SVGTransform effectiveToAtEnd = toAtEndOfDurationTransformList.size() ? toAtEndOfDurationTransformList[0] : SVGTransform(toTransform.type(), SVGTransform::ConstructZeroTransform);
        animatedTransformList.append(SVGTransformDistance::addSVGTransforms(currentTransform, effectiveToAtEnd, repeatCount));
    } else
        animatedTransformList.append(currentTransform);
}