コード例 #1
0
TEST(TransformationMatrixTest, NonInvertableBlendTest) {
  TransformationMatrix from;
  TransformationMatrix to(2.7133590938, 0.0, 0.0, 0.0, 0.0, 2.4645137761, 0.0,
                          0.0, 0.0, 0.0, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05);
  TransformationMatrix result;

  result = to;
  result.blend(from, 0.25);
  EXPECT_EQ(result, from);

  result = to;
  result.blend(from, 0.75);
  EXPECT_EQ(result, to);
}
コード例 #2
0
Ref<TransformOperation> PerspectiveTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
{
    if (from && !from->isSameType(*this))
        return *this;
    
    if (blendToIdentity) {
        double p = floatValueForLength(m_p, 1);
        p = WebCore::blend(p, 1.0, progress); // FIXME: this seems wrong. https://bugs.webkit.org/show_bug.cgi?id=52700
        return PerspectiveTransformOperation::create(Length(clampToPositiveInteger(p), Fixed));
    }
    
    const PerspectiveTransformOperation* fromOp = downcast<PerspectiveTransformOperation>(from);
    Length fromP = fromOp ? fromOp->m_p : Length(m_p.type());
    Length toP = m_p;

    TransformationMatrix fromT;
    TransformationMatrix toT;
    fromT.applyPerspective(floatValueForLength(fromP, 1));
    toT.applyPerspective(floatValueForLength(toP, 1));
    toT.blend(fromT, progress);
    TransformationMatrix::Decomposed4Type decomp;
    if (toT.decompose4(decomp)) {
        if (decomp.perspectiveZ) {
            double val = -1.0 / decomp.perspectiveZ;
            return PerspectiveTransformOperation::create(Length(clampToPositiveInteger(val), Fixed));
        }
    }
    return PerspectiveTransformOperation::create(Length(0, Fixed));
}
コード例 #3
0
PassRefPtr<TransformOperation> PerspectiveTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
{
    if (from && !from->isSameType(*this))
        return this;

    if (blendToIdentity) {
        double p = WebCore::blend(m_p, 1., progress); // FIXME: this seems wrong. https://bugs.webkit.org/show_bug.cgi?id=52700
        return PerspectiveTransformOperation::create(clampToPositiveInteger(p));
    }

    const PerspectiveTransformOperation* fromOp = static_cast<const PerspectiveTransformOperation*>(from);

    TransformationMatrix fromT;
    TransformationMatrix toT;
    fromT.applyPerspective(fromOp ? fromOp->m_p : 0);
    toT.applyPerspective(m_p);
    toT.blend(fromT, progress);
    TransformationMatrix::DecomposedType decomp;
    toT.decompose(decomp);

    if (decomp.perspectiveZ) {
        double val = -1.0 / decomp.perspectiveZ;
        return PerspectiveTransformOperation::create(clampToPositiveInteger(val));
    }
    return PerspectiveTransformOperation::create(0);
}
コード例 #4
0
void AndroidTransformAnimation::applyForProgress(LayerAndroid* layer, float progress)
{
    // First, we need to get the from and to values
    int from, to;
    pickValues(progress, &from, &to);

    TransformAnimationValue* fromValue = (TransformAnimationValue*) m_operations->at(from);
    TransformAnimationValue* toValue = (TransformAnimationValue*) m_operations->at(to);

    ALOGV("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f",
          layer->uniqueId(),
          fromValue, fromValue->keyTime(),
          toValue, toValue->keyTime(), progress);

    // We now have the correct two values to work with, let's compute the
    // progress value

    const TimingFunction* timingFunction = fromValue->timingFunction();
    float p = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(),
                                  progress, timingFunction);
    ALOGV("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(),
          toValue->keyTime());
    progress = p;

    // With both values and the progress, we also need to check out that
    // the operations are compatible (i.e. we are animating the same number
    // of values; if not we do a matrix blend)

    TransformationMatrix transformMatrix;
    bool valid = true;
    unsigned int fromSize = fromValue->value()->size();
    if (fromSize) {
        if (toValue->value()->size() != fromSize)
            valid = false;
        else {
            for (unsigned int j = 0; j < fromSize && valid; j++) {
                if (!fromValue->value()->operations()[j]->isSameType(
                    *toValue->value()->operations()[j]))
                    valid = false;
            }
        }
    }

    IntSize size(layer->getSize().width(), layer->getSize().height());
    if (valid) {
        for (size_t i = 0; i < toValue->value()->size(); ++i)
            toValue->value()->operations()[i]->blend(fromValue->value()->at(i),
                                                     progress)->apply(transformMatrix, size);
    } else {
        TransformationMatrix source;

        fromValue->value()->apply(size, source);
        toValue->value()->apply(size, transformMatrix);

        transformMatrix.blend(source, progress);
    }

    // Set the final transform on the layer
    layer->setTransform(transformMatrix);
}
コード例 #5
0
void InterpolatedTransformOperation::apply(TransformationMatrix& transform, const FloatSize& borderBoxSize) const
{
    TransformationMatrix fromTransform;
    TransformationMatrix toTransform;
    from.apply(borderBoxSize, fromTransform);
    to.apply(borderBoxSize, toTransform);

    toTransform.blend(fromTransform, progress);
    transform.multiply(toTransform);
}
コード例 #6
0
static TransformationMatrix applyTransformAnimation(const TransformOperations& from, const TransformOperations& to, double progress, const FloatSize& boxSize, bool listsMatch)
{
    TransformationMatrix matrix;

    // First frame of an animation.
    if (!progress) {
        from.apply(boxSize, matrix);
        return matrix;
    }

    // Last frame of an animation.
    if (progress == 1) {
        to.apply(boxSize, matrix);
        return matrix;
    }

    // If we have incompatible operation lists, we blend the resulting matrices.
    if (!listsMatch) {
        TransformationMatrix fromMatrix;
        to.apply(boxSize, matrix);
        from.apply(boxSize, fromMatrix);
        matrix.blend(fromMatrix, progress);
        return matrix;
    }

    // Animation to "-webkit-transform: none".
    if (!to.size()) {
        TransformOperations blended(from);
        for (auto& operation : blended.operations())
            operation->blend(nullptr, progress, true)->apply(matrix, boxSize);
        return matrix;
    }

    // Animation from "-webkit-transform: none".
    if (!from.size()) {
        TransformOperations blended(to);
        for (auto& operation : blended.operations())
            operation->blend(nullptr, 1 - progress, true)->apply(matrix, boxSize);
        return matrix;
    }

    // Normal animation with a matching operation list.
    TransformOperations blended(to);
    for (size_t i = 0; i < blended.operations().size(); ++i)
        blended.operations()[i]->blend(from.at(i), progress, !from.at(i))->apply(matrix, boxSize);
    return matrix;
}
コード例 #7
0
TransformOperations TransformOperations::blendByUsingMatrixInterpolation(const TransformOperations& from, double progress, const LayoutSize& size) const
{
    TransformOperations result;

    // Convert the TransformOperations into matrices
    TransformationMatrix fromTransform;
    TransformationMatrix toTransform;
    from.apply(size, fromTransform);
    apply(size, toTransform);

    toTransform.blend(fromTransform, progress);

    // Append the result
    result.operations().append(Matrix3DTransformOperation::create(toTransform));

    return result;
}
コード例 #8
0
PassRefPtr<TransformOperation> Matrix3DTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
{
    if (from && !from->isSameType(*this))
        return this;

    // Convert the TransformOperations into matrices
    FloatSize size;
    TransformationMatrix fromT;
    TransformationMatrix toT;
    if (from)
        from->apply(fromT, size);

    apply(toT, size);

    if (blendToIdentity)
        std::swap(fromT, toT);

    toT.blend(fromT, progress);
    return Matrix3DTransformOperation::create(toT);
}
コード例 #9
0
PassRefPtr<TransformOperation> PerspectiveTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
{
    if (from && !from->isSameType(*this))
        return this;
    
    if (blendToIdentity)
        return PerspectiveTransformOperation::create(m_p + (1. - m_p) * progress);
    
    const PerspectiveTransformOperation* fromOp = static_cast<const PerspectiveTransformOperation*>(from);
    double fromP = fromOp ? fromOp->m_p : 0;
    double toP = m_p;

    TransformationMatrix fromT;
    TransformationMatrix toT;
    fromT.applyPerspective(fromP);
    toT.applyPerspective(toP);
    toT.blend(fromT, progress);
    TransformationMatrix::DecomposedType decomp;
    toT.decompose(decomp);
    
    return PerspectiveTransformOperation::create(decomp.perspectiveZ ? -1.0 / decomp.perspectiveZ : 0.0);
}
コード例 #10
0
TransformationMatrix CCKeyframedTransformAnimationCurve::getValue(double t, const IntSize& layerSize) const
{
    TransformationMatrix transformMatrix;

    if (t <= m_keyframes.first()->time()) {
        m_keyframes.first()->value().apply(layerSize, transformMatrix);
        return transformMatrix;
    }

    if (t >= m_keyframes.last()->time()) {
        m_keyframes.last()->value().apply(layerSize, transformMatrix);
        return transformMatrix;
    }

    size_t i = 0;
    for (; i < m_keyframes.size() - 1; ++i) {
        if (t < m_keyframes[i+1]->time())
            break;
    }

    double progress = (t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time());

    if (m_keyframes[i]->timingFunction())
        progress = m_keyframes[i]->timingFunction()->getValue(progress);

    if (m_keyframes[i]->value().operationsMatch(m_keyframes[i+1]->value())) {
        for (size_t j = 0; j < m_keyframes[i+1]->value().size(); ++j)
            m_keyframes[i+1]->value().operations()[j]->blend(m_keyframes[i]->value().at(j), progress)->apply(transformMatrix, layerSize);
    } else {
        TransformationMatrix source;

        m_keyframes[i]->value().apply(layerSize, source);
        m_keyframes[i+1]->value().apply(layerSize, transformMatrix);

        transformMatrix.blend(source, progress);
    }

    return transformMatrix;
}
コード例 #11
0
PassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
{
    if (from && !from->isSameType(*this))
        return this;
    
    if (blendToIdentity)
        return RotateTransformOperation::create(m_x, m_y, m_z, m_angle - m_angle * progress, m_type);
    
    const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from);
    
    // Optimize for single axis rotation
    if (!fromOp || (fromOp->m_x == 0 && fromOp->m_y == 0 && fromOp->m_z == 1) || 
                   (fromOp->m_x == 0 && fromOp->m_y == 1 && fromOp->m_z == 0) || 
                   (fromOp->m_x == 1 && fromOp->m_y == 0 && fromOp->m_z == 0)) {
        double fromAngle = fromOp ? fromOp->m_angle : 0;
        return RotateTransformOperation::create(fromOp ? fromOp->m_x : m_x, 
                                                fromOp ? fromOp->m_y : m_y, 
                                                fromOp ? fromOp->m_z : m_z, 
                                                UI::blend(fromAngle, m_angle, progress), m_type);
    }

    const RotateTransformOperation* toOp = this;

    // Create the 2 rotation matrices
    TransformationMatrix fromT;
    TransformationMatrix toT;
    fromT.rotate3d((float)(fromOp ? fromOp->m_x : 0),
                   (float)(fromOp ? fromOp->m_y : 0),
                   (float)(fromOp ? fromOp->m_z : 1),
                   (float)(fromOp ? fromOp->m_angle : 0));

    toT.rotate3d((float)(toOp ? toOp->m_x : 0),
                 (float)(toOp ? toOp->m_y : 0),
                 (float)(toOp ? toOp->m_z : 1),
                 (float)(toOp ? toOp->m_angle : 0));
    
    // Blend them
    toT.blend(fromT, progress);
    
    // Extract the result as a quaternion
    TransformationMatrix::DecomposedType decomp;
    toT.decompose(decomp);
    
    // Convert that to Axis/Angle form
    double x = -decomp.quaternionX;
    double y = -decomp.quaternionY;
    double z = -decomp.quaternionZ;
    double length = sqrt(x * x + y * y + z * z);
    double angle = 0;
    
    if (length > 0.00001) {
        x /= length;
        y /= length;
        z /= length;
        angle = rad2deg(acos(decomp.quaternionW) * 2);
    } else {
        x = 0;
        y = 0;
        z = 1;
    }
    return RotateTransformOperation::create(x, y, z, angle, ROTATE_3D);
}
コード例 #12
0
static Ref<TransformOperation> createOperation(TransformationMatrix& to, TransformationMatrix& from, double progress)
{
    to.blend(from, progress);
    return Matrix3DTransformOperation::create(to);
}