15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *               2010 Dirk Schulze <krit@webkit.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef AffineTransform_h
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define AffineTransform_h
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/transforms/TransformationMatrix.h"
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <string.h> // for memcpy
337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/FastAllocBase.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class FloatPoint;
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class FloatQuad;
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class FloatRect;
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class IntPoint;
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class IntRect;
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class TransformationMatrix;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class PLATFORM_EXPORT AffineTransform {
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WTF_MAKE_FAST_ALLOCATED;
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    typedef double Transform[6];
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform();
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform(double a, double b, double c, double d, double e, double f);
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setMatrix(double a, double b, double c, double d, double e, double f);
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void map(double x, double y, double& x2, double& y2) const;
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Rounds the mapped point to the nearest integer value.
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntPoint mapPoint(const IntPoint&) const;
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint mapPoint(const FloatPoint&) const;
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize mapSize(const IntSize&) const;
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize mapSize(const FloatSize&) const;
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Rounds the resulting mapped rectangle out. This is helpful for bounding
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // box computations but may not be what is wanted in other contexts.
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect mapRect(const IntRect&) const;
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect mapRect(const FloatRect&) const;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatQuad mapQuad(const FloatQuad&) const;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isIdentity() const;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double a() const { return m_transform[0]; }
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setA(double a) { m_transform[0] = a; }
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double b() const { return m_transform[1]; }
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setB(double b) { m_transform[1] = b; }
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double c() const { return m_transform[2]; }
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setC(double c) { m_transform[2] = c; }
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double d() const { return m_transform[3]; }
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setD(double d) { m_transform[3] = d; }
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double e() const { return m_transform[4]; }
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setE(double e) { m_transform[4] = e; }
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double f() const { return m_transform[5]; }
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setF(double f) { m_transform[5] = f; }
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void makeIdentity();
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& multiply(const AffineTransform& other);
9002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    AffineTransform& scale(double);
9102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    AffineTransform& scale(double sx, double sy);
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& scaleNonUniform(double sx, double sy);
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& rotate(double d);
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& rotateFromVector(double x, double y);
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& translate(double tx, double ty);
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& shear(double sx, double sy);
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& flipX();
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& flipY();
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& skew(double angleX, double angleY);
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& skewX(double angle);
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& skewY(double angle);
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double xScale() const;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double yScale() const;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double det() const;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isInvertible() const;
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform inverse() const;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void blend(const AffineTransform& from, double progress);
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TransformationMatrix toTransformationMatrix() const;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isIdentityOrTranslation() const
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && m_transform[3] == 1;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isIdentityOrTranslationOrFlipped() const
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && (m_transform[3] == 1 || m_transform[3] == -1);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool preservesAxisAlignment() const
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return (m_transform[1] == 0 && m_transform[2] == 0) || (m_transform[0] == 0 && m_transform[3] == 0);
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator== (const AffineTransform& m2) const
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return (m_transform[0] == m2.m_transform[0]
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)             && m_transform[1] == m2.m_transform[1]
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)             && m_transform[2] == m2.m_transform[2]
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)             && m_transform[3] == m2.m_transform[3]
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)             && m_transform[4] == m2.m_transform[4]
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)             && m_transform[5] == m2.m_transform[5]);
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator!=(const AffineTransform& other) const { return !(*this == other); }
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // *this = *this * t (i.e., a multRight)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform& operator*=(const AffineTransform& t)
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return multiply(t);
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // result = *this * t (i.e., a multRight)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform operator*(const AffineTransform& t) const
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        AffineTransform result = *this;
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result *= t;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static AffineTransform translation(double x, double y)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AffineTransform(1, 0, 0, 1, x, y);
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // decompose the matrix into its component parts
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    typedef struct {
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double scaleX, scaleY;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double angle;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double remainderA, remainderB, remainderC, remainderD;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double translateX, translateY;
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } DecomposedType;
16702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool decompose(DecomposedType&) const;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void recompose(const DecomposedType&);
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setMatrix(const Transform m)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m && m != m_transform)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            memcpy(m_transform, m, sizeof(Transform));
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Transform m_transform;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)PLATFORM_EXPORT AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest);
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
186