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

« back to all changes in this revision

Viewing changes to Source/WebCore/platform/graphics/transforms/AffineTransform.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) 2005, 2006 Apple Computer, Inc.  All rights reserved.
 
3
 *               2010 Dirk Schulze <krit@webkit.org>
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 *
 
14
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 
15
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
17
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 
18
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
19
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
20
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
21
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 
22
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 
25
 */
 
26
 
 
27
#include "config.h"
 
28
#include "AffineTransform.h"
 
29
 
 
30
#include "FloatConversion.h"
 
31
#include "FloatQuad.h"
 
32
#include "FloatRect.h"
 
33
#include "IntRect.h"
 
34
 
 
35
#include <wtf/MathExtras.h>
 
36
 
 
37
namespace WebCore {
 
38
 
 
39
AffineTransform::AffineTransform()
 
40
{
 
41
    setMatrix(1, 0, 0, 1, 0, 0);
 
42
}
 
43
 
 
44
AffineTransform::AffineTransform(double a, double b, double c, double d, double e, double f)
 
45
{
 
46
    setMatrix(a, b, c, d, e, f);
 
47
}
 
48
 
 
49
void AffineTransform::makeIdentity()
 
50
{
 
51
    setMatrix(1, 0, 0, 1, 0, 0);
 
52
}
 
53
 
 
54
void AffineTransform::setMatrix(double a, double b, double c, double d, double e, double f)
 
55
{
 
56
    m_transform[0] = a;
 
57
    m_transform[1] = b;
 
58
    m_transform[2] = c;
 
59
    m_transform[3] = d;
 
60
    m_transform[4] = e;
 
61
    m_transform[5] = f;
 
62
}
 
63
 
 
64
bool AffineTransform::isIdentity() const
 
65
{
 
66
    return (m_transform[0] == 1 && m_transform[1] == 0
 
67
         && m_transform[2] == 0 && m_transform[3] == 1
 
68
         && m_transform[4] == 0 && m_transform[5] == 0);
 
69
}
 
70
 
 
71
double AffineTransform::xScale() const
 
72
{
 
73
    return sqrt(m_transform[0] * m_transform[0] + m_transform[1] * m_transform[1]);
 
74
}
 
75
 
 
76
double AffineTransform::yScale() const
 
77
{
 
78
    return sqrt(m_transform[2] * m_transform[2] + m_transform[3] * m_transform[3]);
 
79
}
 
80
 
 
81
double AffineTransform::det() const
 
82
{
 
83
    return m_transform[0] * m_transform[3] - m_transform[1] * m_transform[2];
 
84
}
 
85
 
 
86
bool AffineTransform::isInvertible() const
 
87
{
 
88
    return det() != 0.0;
 
89
}
 
90
 
 
91
AffineTransform AffineTransform::inverse() const
 
92
{
 
93
    double determinant = det();
 
94
    if (determinant == 0.0)
 
95
        return AffineTransform();
 
96
 
 
97
    AffineTransform result;
 
98
    if (isIdentityOrTranslation()) {
 
99
        result.m_transform[4] = -m_transform[4];
 
100
        result.m_transform[5] = -m_transform[5];
 
101
        return result;
 
102
    }
 
103
 
 
104
    result.m_transform[0] = m_transform[3] / determinant;
 
105
    result.m_transform[1] = -m_transform[1] / determinant;
 
106
    result.m_transform[2] = -m_transform[2] / determinant;
 
107
    result.m_transform[3] = m_transform[0] / determinant;
 
108
    result.m_transform[4] = (m_transform[2] * m_transform[5]
 
109
                           - m_transform[3] * m_transform[4]) / determinant;
 
110
    result.m_transform[5] = (m_transform[1] * m_transform[4]
 
111
                           - m_transform[0] * m_transform[5]) / determinant;
 
112
 
 
113
    return result;
 
114
}
 
115
 
 
116
 
 
117
// Multiplies this AffineTransform by the provided AffineTransform - i.e.
 
118
// this = this * other;
 
119
AffineTransform& AffineTransform::multiply(const AffineTransform& other)
 
120
{
 
121
    AffineTransform trans;
 
122
    
 
123
    trans.m_transform[0] = other.m_transform[0] * m_transform[0] + other.m_transform[1] * m_transform[2];
 
124
    trans.m_transform[1] = other.m_transform[0] * m_transform[1] + other.m_transform[1] * m_transform[3];
 
125
    trans.m_transform[2] = other.m_transform[2] * m_transform[0] + other.m_transform[3] * m_transform[2];
 
126
    trans.m_transform[3] = other.m_transform[2] * m_transform[1] + other.m_transform[3] * m_transform[3];
 
127
    trans.m_transform[4] = other.m_transform[4] * m_transform[0] + other.m_transform[5] * m_transform[2] + m_transform[4];
 
128
    trans.m_transform[5] = other.m_transform[4] * m_transform[1] + other.m_transform[5] * m_transform[3] + m_transform[5];
 
129
 
 
130
    setMatrix(trans.m_transform);
 
131
    return *this;
 
132
}
 
133
 
 
134
AffineTransform& AffineTransform::rotate(double a)
 
135
{
 
136
    // angle is in degree. Switch to radian
 
137
    a = deg2rad(a);
 
138
    double cosAngle = cos(a);
 
139
    double sinAngle = sin(a);
 
140
    AffineTransform rot(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0);
 
141
 
 
142
    multiply(rot);
 
143
    return *this;
 
144
}
 
145
 
 
146
AffineTransform& AffineTransform::scale(double s)
 
147
{
 
148
    return scale(s, s);
 
149
}
 
150
 
 
151
AffineTransform& AffineTransform::scale(double sx, double sy)
 
152
{
 
153
    m_transform[0] *= sx;
 
154
    m_transform[1] *= sx;
 
155
    m_transform[2] *= sy;
 
156
    m_transform[3] *= sy;
 
157
    return *this;
 
158
}
 
159
 
 
160
// *this = *this * translation
 
161
AffineTransform& AffineTransform::translate(double tx, double ty)
 
162
{
 
163
    if (isIdentityOrTranslation()) {
 
164
        m_transform[4] += tx;
 
165
        m_transform[5] += ty;
 
166
        return *this;
 
167
    }
 
168
        
 
169
    m_transform[4] += tx * m_transform[0] + ty * m_transform[2];
 
170
    m_transform[5] += tx * m_transform[1] + ty * m_transform[3];
 
171
    return *this;
 
172
}
 
173
 
 
174
AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
 
175
{
 
176
    return scale(sx, sy);
 
177
}
 
178
 
 
179
AffineTransform& AffineTransform::rotateFromVector(double x, double y)
 
180
{
 
181
    return rotate(rad2deg(atan2(y, x)));
 
182
}
 
183
 
 
184
AffineTransform& AffineTransform::flipX()
 
185
{
 
186
    return scale(-1, 1);
 
187
}
 
188
 
 
189
AffineTransform& AffineTransform::flipY()
 
190
{
 
191
    return scale(1, -1);
 
192
}
 
193
 
 
194
AffineTransform& AffineTransform::shear(double sx, double sy)
 
195
{
 
196
    double a = m_transform[0];
 
197
    double b = m_transform[1];
 
198
 
 
199
    m_transform[0] += sy * m_transform[2];
 
200
    m_transform[1] += sy * m_transform[3];
 
201
    m_transform[2] += sx * a;
 
202
    m_transform[3] += sx * b;
 
203
 
 
204
    return *this;
 
205
}
 
206
 
 
207
AffineTransform& AffineTransform::skew(double angleX, double angleY)
 
208
{
 
209
    return shear(tan(deg2rad(angleX)), tan(deg2rad(angleY)));
 
210
}
 
211
 
 
212
AffineTransform& AffineTransform::skewX(double angle)
 
213
{
 
214
    return shear(tan(deg2rad(angle)), 0);
 
215
}
 
216
 
 
217
AffineTransform& AffineTransform::skewY(double angle)
 
218
{
 
219
    return shear(0, tan(deg2rad(angle)));
 
220
}
 
221
 
 
222
AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest)
 
223
{
 
224
    AffineTransform transform;
 
225
    transform.translate(dest.x() - source.x(), dest.y() - source.y());
 
226
    transform.scale(dest.width() / source.width(), dest.height() / source.height());
 
227
    return transform;
 
228
}
 
229
 
 
230
void AffineTransform::map(double x, double y, double& x2, double& y2) const
 
231
{
 
232
    x2 = (m_transform[0] * x + m_transform[2] * y + m_transform[4]);
 
233
    y2 = (m_transform[1] * x + m_transform[3] * y + m_transform[5]);
 
234
}
 
235
 
 
236
IntPoint AffineTransform::mapPoint(const IntPoint& point) const
 
237
{
 
238
    double x2, y2;
 
239
    map(point.x(), point.y(), x2, y2);
 
240
    
 
241
    // Round the point.
 
242
    return IntPoint(lround(x2), lround(y2));
 
243
}
 
244
 
 
245
FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const
 
246
{
 
247
    double x2, y2;
 
248
    map(point.x(), point.y(), x2, y2);
 
249
 
 
250
    return FloatPoint(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2));
 
251
}
 
252
 
 
253
IntSize AffineTransform::mapSize(const IntSize& size) const
 
254
{
 
255
    double width2 = size.width() * xScale();
 
256
    double height2 = size.height() * yScale();
 
257
 
 
258
    return IntSize(lround(width2), lround(height2));
 
259
}
 
260
 
 
261
FloatSize AffineTransform::mapSize(const FloatSize& size) const
 
262
{
 
263
    double width2 = size.width() * xScale();
 
264
    double height2 = size.height() * yScale();
 
265
 
 
266
    return FloatSize(narrowPrecisionToFloat(width2), narrowPrecisionToFloat(height2));
 
267
}
 
268
 
 
269
IntRect AffineTransform::mapRect(const IntRect &rect) const
 
270
{
 
271
    return enclosingIntRect(mapRect(FloatRect(rect)));
 
272
}
 
273
 
 
274
FloatRect AffineTransform::mapRect(const FloatRect& rect) const
 
275
{
 
276
    if (isIdentityOrTranslation()) {
 
277
        FloatRect mappedRect(rect);
 
278
        mappedRect.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5]));
 
279
        return mappedRect;
 
280
    }
 
281
 
 
282
    FloatQuad result;
 
283
    result.setP1(mapPoint(rect.location()));
 
284
    result.setP2(mapPoint(FloatPoint(rect.maxX(), rect.y())));
 
285
    result.setP3(mapPoint(FloatPoint(rect.maxX(), rect.maxY())));
 
286
    result.setP4(mapPoint(FloatPoint(rect.x(), rect.maxY())));
 
287
    return result.boundingBox();
 
288
}
 
289
 
 
290
FloatQuad AffineTransform::mapQuad(const FloatQuad& q) const
 
291
{
 
292
    if (isIdentityOrTranslation()) {
 
293
        FloatQuad mappedQuad(q);
 
294
        mappedQuad.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5]));
 
295
        return mappedQuad;
 
296
    }
 
297
 
 
298
    FloatQuad result;
 
299
    result.setP1(mapPoint(q.p1()));
 
300
    result.setP2(mapPoint(q.p2()));
 
301
    result.setP3(mapPoint(q.p3()));
 
302
    result.setP4(mapPoint(q.p4()));
 
303
    return result;
 
304
}
 
305
 
 
306
void AffineTransform::blend(const AffineTransform& from, double progress)
 
307
{
 
308
    DecomposedType srA, srB;
 
309
 
 
310
    from.decompose(srA);
 
311
    this->decompose(srB);
 
312
 
 
313
    // If x-axis of one is flipped, and y-axis of the other, convert to an unflipped rotation.
 
314
    if ((srA.scaleX < 0 && srB.scaleY < 0) || (srA.scaleY < 0 &&  srB.scaleX < 0)) {
 
315
        srA.scaleX = -srA.scaleX;
 
316
        srA.scaleY = -srA.scaleY;
 
317
        srA.angle += srA.angle < 0 ? piDouble : -piDouble;
 
318
    }
 
319
 
 
320
    // Don't rotate the long way around.
 
321
    srA.angle = fmod(srA.angle, 2 * piDouble);
 
322
    srB.angle = fmod(srB.angle, 2 * piDouble);
 
323
 
 
324
    if (fabs(srA.angle - srB.angle) > piDouble) {
 
325
        if (srA.angle > srB.angle)
 
326
            srA.angle -= piDouble * 2;
 
327
        else
 
328
            srB.angle -= piDouble * 2;
 
329
    }
 
330
    
 
331
    srA.scaleX += progress * (srB.scaleX - srA.scaleX);
 
332
    srA.scaleY += progress * (srB.scaleY - srA.scaleY);
 
333
    srA.angle += progress * (srB.angle - srA.angle);
 
334
    srA.remainderA += progress * (srB.remainderA - srA.remainderA);
 
335
    srA.remainderB += progress * (srB.remainderB - srA.remainderB);
 
336
    srA.remainderC += progress * (srB.remainderC - srA.remainderC);
 
337
    srA.remainderD += progress * (srB.remainderD - srA.remainderD);
 
338
    srA.translateX += progress * (srB.translateX - srA.translateX);
 
339
    srA.translateY += progress * (srB.translateY - srA.translateY);
 
340
 
 
341
    this->recompose(srA);
 
342
}
 
343
 
 
344
TransformationMatrix AffineTransform::toTransformationMatrix() const
 
345
{
 
346
    return TransformationMatrix(m_transform[0], m_transform[1], m_transform[2],
 
347
                                m_transform[3], m_transform[4], m_transform[5]);
 
348
}
 
349
 
 
350
bool AffineTransform::decompose(DecomposedType& decomp) const
 
351
{
 
352
    AffineTransform m(*this);
 
353
    
 
354
    // Compute scaling factors
 
355
    double sx = xScale();
 
356
    double sy = yScale();
 
357
    
 
358
    // Compute cross product of transformed unit vectors. If negative,
 
359
    // one axis was flipped.
 
360
    if (m.a() * m.d() - m.c() * m.b() < 0) {
 
361
        // Flip axis with minimum unit vector dot product
 
362
        if (m.a() < m.d())
 
363
            sx = -sx;
 
364
        else
 
365
            sy = -sy;
 
366
    }
 
367
    
 
368
    // Remove scale from matrix
 
369
    m.scale(1 / sx, 1 / sy);
 
370
    
 
371
    // Compute rotation
 
372
    double angle = atan2(m.b(), m.a());
 
373
    
 
374
    // Remove rotation from matrix
 
375
    m.rotate(rad2deg(-angle));
 
376
    
 
377
    // Return results    
 
378
    decomp.scaleX = sx;
 
379
    decomp.scaleY = sy;
 
380
    decomp.angle = angle;
 
381
    decomp.remainderA = m.a();
 
382
    decomp.remainderB = m.b();
 
383
    decomp.remainderC = m.c();
 
384
    decomp.remainderD = m.d();
 
385
    decomp.translateX = m.e();
 
386
    decomp.translateY = m.f();
 
387
    
 
388
    return true;
 
389
}
 
390
 
 
391
void AffineTransform::recompose(const DecomposedType& decomp)
 
392
{
 
393
    this->setA(decomp.remainderA);
 
394
    this->setB(decomp.remainderB);
 
395
    this->setC(decomp.remainderC);
 
396
    this->setD(decomp.remainderD);
 
397
    this->setE(decomp.translateX);
 
398
    this->setF(decomp.translateY);
 
399
    this->rotate(rad2deg(decomp.angle));
 
400
    this->scale(decomp.scaleX, decomp.scaleY);
 
401
}
 
402
 
 
403
}