• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Apple 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 COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "TransformState.h"
28 
29 namespace WebCore {
30 
move(int x,int y,TransformAccumulation accumulate)31 void TransformState::move(int x, int y, TransformAccumulation accumulate)
32 {
33     if (m_accumulatingTransform && m_accumulatedTransform) {
34         // If we're accumulating into an existing transform, apply the translation.
35         if (m_direction == ApplyTransformDirection)
36             m_accumulatedTransform->translateRight(x, y);
37         else
38             m_accumulatedTransform->translate(-x, -y);  // We're unapplying, so negate
39 
40         // Then flatten if necessary.
41         if (accumulate == FlattenTransform)
42             flatten();
43     } else {
44         // Just move the point and, optionally, the quad.
45         m_lastPlanarPoint.move(x, y);
46         if (m_mapQuad)
47             m_lastPlanarQuad.move(x, y);
48     }
49     m_accumulatingTransform = accumulate == AccumulateTransform;
50 }
51 
applyTransform(const TransformationMatrix & transformFromContainer,TransformAccumulation accumulate)52 void TransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate)
53 {
54     // If we have an accumulated transform from last time, multiply in this transform
55     if (m_accumulatedTransform) {
56         if (m_direction == ApplyTransformDirection)
57             m_accumulatedTransform->multiply(transformFromContainer);
58         else
59             m_accumulatedTransform->multLeft(transformFromContainer);
60     } else if (accumulate == AccumulateTransform) {
61         // Make one if we started to accumulate
62         m_accumulatedTransform.set(new TransformationMatrix(transformFromContainer));
63     }
64 
65     if (accumulate == FlattenTransform) {
66         const TransformationMatrix* finalTransform = m_accumulatedTransform ? m_accumulatedTransform.get() : &transformFromContainer;
67         flattenWithTransform(*finalTransform);
68     }
69     m_accumulatingTransform = accumulate == AccumulateTransform;
70 }
71 
flatten()72 void TransformState::flatten()
73 {
74     if (!m_accumulatedTransform) {
75         m_accumulatingTransform = false;
76         return;
77     }
78 
79     flattenWithTransform(*m_accumulatedTransform);
80 }
81 
mappedPoint() const82 FloatPoint TransformState::mappedPoint() const
83 {
84     if (!m_accumulatedTransform)
85         return m_lastPlanarPoint;
86 
87     if (m_direction == ApplyTransformDirection)
88         return m_accumulatedTransform->mapPoint(m_lastPlanarPoint);
89 
90     return m_accumulatedTransform->inverse().projectPoint(m_lastPlanarPoint);
91 }
92 
mappedQuad() const93 FloatQuad TransformState::mappedQuad() const
94 {
95     if (!m_accumulatedTransform)
96         return m_lastPlanarQuad;
97 
98     if (m_direction == ApplyTransformDirection)
99         return m_accumulatedTransform->mapQuad(m_lastPlanarQuad);
100 
101     return m_accumulatedTransform->inverse().projectQuad(m_lastPlanarQuad);
102 }
103 
flattenWithTransform(const TransformationMatrix & t)104 void TransformState::flattenWithTransform(const TransformationMatrix& t)
105 {
106     if (m_direction == ApplyTransformDirection) {
107         m_lastPlanarPoint = t.mapPoint(m_lastPlanarPoint);
108         if (m_mapQuad)
109             m_lastPlanarQuad = t.mapQuad(m_lastPlanarQuad);
110     } else {
111         TransformationMatrix inverseTransform = t.inverse();
112         m_lastPlanarPoint = inverseTransform.projectPoint(m_lastPlanarPoint);
113         if (m_mapQuad)
114             m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad);
115     }
116 
117     // We could throw away m_accumulatedTransform if we wanted to here, but that
118     // would cause thrash when traversing hierarachies with alternating
119     // preserve-3d and flat elements.
120     if (m_accumulatedTransform)
121         m_accumulatedTransform->makeIdentity();
122     m_accumulatingTransform = false;
123 }
124 
125 // HitTestingTransformState methods
translate(int x,int y,TransformAccumulation accumulate)126 void HitTestingTransformState::translate(int x, int y, TransformAccumulation accumulate)
127 {
128     m_accumulatedTransform.translate(x, y);
129     if (accumulate == FlattenTransform)
130         flattenWithTransform(m_accumulatedTransform);
131 
132     m_accumulatingTransform = accumulate == AccumulateTransform;
133 }
134 
applyTransform(const TransformationMatrix & transformFromContainer,TransformAccumulation accumulate)135 void HitTestingTransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate)
136 {
137     m_accumulatedTransform.multLeft(transformFromContainer);
138     if (accumulate == FlattenTransform)
139         flattenWithTransform(m_accumulatedTransform);
140 
141     m_accumulatingTransform = accumulate == AccumulateTransform;
142 }
143 
flatten()144 void HitTestingTransformState::flatten()
145 {
146     flattenWithTransform(m_accumulatedTransform);
147 }
148 
flattenWithTransform(const TransformationMatrix & t)149 void HitTestingTransformState::flattenWithTransform(const TransformationMatrix& t)
150 {
151     TransformationMatrix inverseTransform = t.inverse();
152     m_lastPlanarPoint = inverseTransform.projectPoint(m_lastPlanarPoint);
153     m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad);
154 
155     m_accumulatedTransform.makeIdentity();
156     m_accumulatingTransform = false;
157 }
158 
mappedPoint() const159 FloatPoint HitTestingTransformState::mappedPoint() const
160 {
161     return m_accumulatedTransform.inverse().projectPoint(m_lastPlanarPoint);
162 }
163 
mappedQuad() const164 FloatQuad HitTestingTransformState::mappedQuad() const
165 {
166     return m_accumulatedTransform.inverse().projectQuad(m_lastPlanarQuad);
167 }
168 
169 } // namespace WebCore
170