~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2012 Google Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 * 1.  Redistributions of source code must retain the above copyright
 
8
 *     notice, this list of conditions and the following disclaimer.
 
9
 * 2.  Redistributions in binary form must reproduce the above copyright
 
10
 *     notice, this list of conditions and the following disclaimer in the
 
11
 *     documentation and/or other materials provided with the distribution.
 
12
 *
 
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
 
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
15
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
16
 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 
17
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
18
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
19
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 
20
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
22
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
23
 */
 
24
 
 
25
#include "config.h"
 
26
 
 
27
#include "AnimationTranslationUtil.h"
 
28
 
 
29
#include "FloatSize.h"
 
30
#include "GraphicsLayer.h"
 
31
#include "IdentityTransformOperation.h"
 
32
#include "Length.h"
 
33
#include "LengthFunctions.h"
 
34
#include "Matrix3DTransformOperation.h"
 
35
#include "MatrixTransformOperation.h"
 
36
#include "PerspectiveTransformOperation.h"
 
37
#include "RotateTransformOperation.h"
 
38
#include "ScaleTransformOperation.h"
 
39
#include "SkewTransformOperation.h"
 
40
#include "TransformOperations.h"
 
41
#include "TranslateTransformOperation.h"
 
42
 
 
43
#include <public/Platform.h>
 
44
#include <public/WebAnimation.h>
 
45
#include <public/WebAnimationCurve.h>
 
46
#include <public/WebCompositorSupport.h>
 
47
#include <public/WebFloatAnimationCurve.h>
 
48
#include <public/WebTransformAnimationCurve.h>
 
49
#include <public/WebTransformOperations.h>
 
50
#include <public/WebTransformationMatrix.h>
 
51
 
 
52
#include <wtf/OwnPtr.h>
 
53
#include <wtf/text/CString.h>
 
54
 
 
55
using namespace std;
 
56
using namespace WebKit;
 
57
 
 
58
namespace WebCore {
 
59
 
 
60
WebTransformOperations toWebTransformOperations(const TransformOperations& transformOperations, const FloatSize& boxSize)
 
61
{
 
62
    // We need to do a deep copy the transformOperations may contain ref pointers to TransformOperation objects.
 
63
    WebTransformOperations webTransformOperations;
 
64
    for (size_t j = 0; j < transformOperations.size(); ++j) {
 
65
        TransformOperation::OperationType operationType = transformOperations.operations()[j]->getOperationType();
 
66
        switch (operationType) {
 
67
        case TransformOperation::SCALE_X:
 
68
        case TransformOperation::SCALE_Y:
 
69
        case TransformOperation::SCALE_Z:
 
70
        case TransformOperation::SCALE_3D:
 
71
        case TransformOperation::SCALE: {
 
72
            ScaleTransformOperation* transform = static_cast<ScaleTransformOperation*>(transformOperations.operations()[j].get());
 
73
            webTransformOperations.appendScale(transform->x(), transform->y(), transform->z());
 
74
            break;
 
75
        }
 
76
        case TransformOperation::TRANSLATE_X:
 
77
        case TransformOperation::TRANSLATE_Y:
 
78
        case TransformOperation::TRANSLATE_Z:
 
79
        case TransformOperation::TRANSLATE_3D:
 
80
        case TransformOperation::TRANSLATE: {
 
81
            TranslateTransformOperation* transform = static_cast<TranslateTransformOperation*>(transformOperations.operations()[j].get());
 
82
            webTransformOperations.appendTranslate(floatValueForLength(transform->x(), boxSize.width()), floatValueForLength(transform->y(), boxSize.height()), floatValueForLength(transform->z(), 1));
 
83
            break;
 
84
        }
 
85
        case TransformOperation::ROTATE_X:
 
86
        case TransformOperation::ROTATE_Y:
 
87
        case TransformOperation::ROTATE_3D:
 
88
        case TransformOperation::ROTATE: {
 
89
            RotateTransformOperation* transform = static_cast<RotateTransformOperation*>(transformOperations.operations()[j].get());
 
90
            webTransformOperations.appendRotate(transform->x(), transform->y(), transform->z(), transform->angle());
 
91
            break;
 
92
        }
 
93
        case TransformOperation::SKEW_X:
 
94
        case TransformOperation::SKEW_Y:
 
95
        case TransformOperation::SKEW: {
 
96
            SkewTransformOperation* transform = static_cast<SkewTransformOperation*>(transformOperations.operations()[j].get());
 
97
            webTransformOperations.appendSkew(transform->angleX(), transform->angleY());
 
98
            break;
 
99
        }
 
100
        case TransformOperation::MATRIX: {
 
101
            MatrixTransformOperation* transform = static_cast<MatrixTransformOperation*>(transformOperations.operations()[j].get());
 
102
            TransformationMatrix m = transform->matrix();
 
103
            webTransformOperations.appendMatrix(WebTransformationMatrix(m));
 
104
            break;
 
105
        }
 
106
        case TransformOperation::MATRIX_3D: {
 
107
            Matrix3DTransformOperation* transform = static_cast<Matrix3DTransformOperation*>(transformOperations.operations()[j].get());
 
108
            TransformationMatrix m = transform->matrix();
 
109
            webTransformOperations.appendMatrix(WebTransformationMatrix(m));
 
110
            break;
 
111
        }
 
112
        case TransformOperation::PERSPECTIVE: {
 
113
            PerspectiveTransformOperation* transform = static_cast<PerspectiveTransformOperation*>(transformOperations.operations()[j].get());
 
114
            webTransformOperations.appendPerspective(floatValueForLength(transform->perspective(), 0));
 
115
            break;
 
116
        }
 
117
        case TransformOperation::IDENTITY:
 
118
            webTransformOperations.appendIdentity();
 
119
            break;
 
120
        case TransformOperation::NONE:
 
121
            // Do nothing.
 
122
            break;
 
123
        } // switch
 
124
    } // for each operation
 
125
 
 
126
    return webTransformOperations;
 
127
}
 
128
 
 
129
template <class Value, class Keyframe, class Curve>
 
130
bool appendKeyframeWithStandardTimingFunction(Curve* curve, double keyTime, const Value* value, const Value* lastValue, WebKit::WebAnimationCurve::TimingFunctionType timingFunctionType, const FloatSize&)
 
131
{
 
132
    curve->add(Keyframe(keyTime, value->value()), timingFunctionType);
 
133
    return true;
 
134
}
 
135
 
 
136
template <class Value, class Keyframe, class Curve>
 
137
bool appendKeyframeWithCustomBezierTimingFunction(Curve* curve, double keyTime, const Value* value, const Value* lastValue, double x1, double y1, double x2, double y2, const FloatSize&)
 
138
{
 
139
    curve->add(Keyframe(keyTime, value->value()), x1, y1, x2, y2);
 
140
    return true;
 
141
}
 
142
 
 
143
bool isRotationType(TransformOperation::OperationType transformType)
 
144
{
 
145
    return transformType == TransformOperation::ROTATE
 
146
        || transformType == TransformOperation::ROTATE_X
 
147
        || transformType == TransformOperation::ROTATE_Y
 
148
        || transformType == TransformOperation::ROTATE_Z
 
149
        || transformType == TransformOperation::ROTATE_3D;
 
150
}
 
151
 
 
152
template <>
 
153
bool appendKeyframeWithStandardTimingFunction<TransformAnimationValue, WebTransformKeyframe, WebTransformAnimationCurve>(WebTransformAnimationCurve* curve, double keyTime, const TransformAnimationValue* value, const TransformAnimationValue* lastValue, WebKit::WebAnimationCurve::TimingFunctionType timingFunctionType, const FloatSize& boxSize)
 
154
{
 
155
    bool canBlend = !lastValue;
 
156
    WebTransformOperations operations = toWebTransformOperations(*value->value(), boxSize);
 
157
    if (!canBlend) {
 
158
        WebTransformOperations lastOperations = toWebTransformOperations(*lastValue->value(), boxSize);
 
159
        canBlend = lastOperations.canBlendWith(operations);
 
160
    }
 
161
    if (canBlend) {
 
162
        curve->add(WebTransformKeyframe(keyTime, operations), timingFunctionType);
 
163
        return true;
 
164
    }
 
165
    return false;
 
166
}
 
167
 
 
168
template <>
 
169
bool appendKeyframeWithCustomBezierTimingFunction<TransformAnimationValue, WebTransformKeyframe, WebTransformAnimationCurve>(WebTransformAnimationCurve* curve, double keyTime, const TransformAnimationValue* value, const TransformAnimationValue* lastValue, double x1, double y1, double x2, double y2, const FloatSize& boxSize)
 
170
{
 
171
    bool canBlend = !lastValue;
 
172
    WebTransformOperations operations = toWebTransformOperations(*value->value(), boxSize);
 
173
    if (!canBlend) {
 
174
        WebTransformOperations lastOperations = toWebTransformOperations(*lastValue->value(), boxSize);
 
175
        canBlend = lastOperations.canBlendWith(operations);
 
176
    }
 
177
    if (canBlend) {
 
178
        curve->add(WebTransformKeyframe(keyTime, operations), x1, y1, x2, y2);
 
179
        return true;
 
180
    }
 
181
    return false;
 
182
}
 
183
 
 
184
template <class Value, class Keyframe, class Curve>
 
185
PassOwnPtr<WebKit::WebAnimation> createWebAnimation(const KeyframeValueList& valueList, const Animation* animation, int animationId, double timeOffset, Curve* curve, WebKit::WebAnimation::TargetProperty targetProperty, const FloatSize& boxSize)
 
186
{
 
187
    bool alternate = false;
 
188
    bool reverse = false;
 
189
    if (animation && animation->isDirectionSet()) {
 
190
        Animation::AnimationDirection direction = animation->direction();
 
191
        if (direction == Animation::AnimationDirectionAlternate || direction == Animation::AnimationDirectionAlternateReverse)
 
192
            alternate = true;
 
193
        if (direction == Animation::AnimationDirectionReverse || direction == Animation::AnimationDirectionAlternateReverse)
 
194
            reverse = true;
 
195
    }
 
196
 
 
197
    for (size_t i = 0; i < valueList.size(); i++) {
 
198
        size_t index = reverse ? valueList.size() - i - 1 : i;
 
199
        const Value* originalValue = static_cast<const Value*>(valueList.at(index));
 
200
        const Value* lastOriginalValue = 0;
 
201
        if (valueList.size() > 1 && ((reverse && index + 1 < valueList.size()) || (!reverse && index > 0)))
 
202
            lastOriginalValue = static_cast<const Value*>(valueList.at(reverse ? index + 1 : index - 1));
 
203
 
 
204
        const TimingFunction* originalTimingFunction = originalValue->timingFunction();
 
205
 
 
206
        // If there hasn't been a timing function associated with this keyframe, use the
 
207
        // animation's timing function, if we have one.
 
208
        if (!originalTimingFunction && animation->isTimingFunctionSet())
 
209
            originalTimingFunction = animation->timingFunction().get();
 
210
 
 
211
        // Ease is the default timing function.
 
212
        WebKit::WebAnimationCurve::TimingFunctionType timingFunctionType = WebKit::WebAnimationCurve::TimingFunctionTypeEase;
 
213
 
 
214
        bool isUsingCustomBezierTimingFunction = false;
 
215
        double x1 = 0;
 
216
        double y1 = 0;
 
217
        double x2 = 1;
 
218
        double y2 = 1;
 
219
 
 
220
        if (originalTimingFunction) {
 
221
            switch (originalTimingFunction->type()) {
 
222
            case TimingFunction::StepsFunction:
 
223
                // FIXME: add support for steps timing function.
 
224
                return nullptr;
 
225
            case TimingFunction::LinearFunction:
 
226
                timingFunctionType = WebKit::WebAnimationCurve::TimingFunctionTypeLinear;
 
227
                break;
 
228
            case TimingFunction::CubicBezierFunction:
 
229
                const CubicBezierTimingFunction* originalBezierTimingFunction = static_cast<const CubicBezierTimingFunction*>(originalTimingFunction);
 
230
                isUsingCustomBezierTimingFunction = true;
 
231
                x1 = originalBezierTimingFunction->x1();
 
232
                y1 = originalBezierTimingFunction->y1();
 
233
                x2 = originalBezierTimingFunction->x2();
 
234
                y2 = originalBezierTimingFunction->y2();
 
235
                break;
 
236
            } // switch
 
237
        }
 
238
 
 
239
        double duration = (animation && animation->isDurationSet()) ? animation->duration() : 1;
 
240
        double keyTime = originalValue->keyTime() * duration;
 
241
 
 
242
        if (reverse)
 
243
            keyTime = duration - keyTime;
 
244
 
 
245
        bool addedKeyframe = false;
 
246
        if (isUsingCustomBezierTimingFunction)
 
247
            addedKeyframe = appendKeyframeWithCustomBezierTimingFunction<Value, Keyframe, Curve>(curve, keyTime, originalValue, lastOriginalValue, x1, y1, x2, y2, boxSize);
 
248
        else
 
249
            addedKeyframe = appendKeyframeWithStandardTimingFunction<Value, Keyframe, Curve>(curve, keyTime, originalValue, lastOriginalValue, timingFunctionType, boxSize);
 
250
        if (!addedKeyframe)
 
251
            return nullptr;
 
252
    }
 
253
 
 
254
    OwnPtr<WebKit::WebAnimation> webAnimation = adoptPtr(Platform::current()->compositorSupport()->createAnimation(*curve, targetProperty, animationId));
 
255
 
 
256
    int iterations = (animation && animation->isIterationCountSet()) ? animation->iterationCount() : 1;
 
257
    webAnimation->setIterations(iterations);
 
258
    webAnimation->setAlternatesDirection(alternate);
 
259
 
 
260
    // If timeOffset > 0, then the animation has started in the past.
 
261
    webAnimation->setTimeOffset(timeOffset);
 
262
 
 
263
    return webAnimation.release();
 
264
}
 
265
 
 
266
PassOwnPtr<WebKit::WebAnimation> createWebAnimation(const KeyframeValueList& values, const Animation* animation, int animationId, double timeOffset, const FloatSize& boxSize)
 
267
{
 
268
 
 
269
 
 
270
    if (values.property() == AnimatedPropertyWebkitTransform) {
 
271
        OwnPtr<WebTransformAnimationCurve> curve = adoptPtr(Platform::current()->compositorSupport()->createTransformAnimationCurve());
 
272
        return createWebAnimation<TransformAnimationValue, WebTransformKeyframe, WebTransformAnimationCurve>(values, animation, animationId, timeOffset, curve.get(), WebKit::WebAnimation::TargetPropertyTransform, FloatSize(boxSize));
 
273
    }
 
274
 
 
275
    if (values.property() == AnimatedPropertyOpacity) {
 
276
        OwnPtr<WebFloatAnimationCurve> curve = adoptPtr(Platform::current()->compositorSupport()->createFloatAnimationCurve());
 
277
        return createWebAnimation<FloatAnimationValue, WebFloatKeyframe, WebFloatAnimationCurve>(values, animation, animationId, timeOffset, curve.get(), WebKit::WebAnimation::TargetPropertyOpacity, FloatSize());
 
278
    }
 
279
 
 
280
    return nullptr;
 
281
}
 
282
 
 
283
} // namespace WebCore