[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / platform / graphics / transforms / TransformState.h
1 /*
2  * Copyright (C) 2011 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 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 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 #ifndef TransformState_h
27 #define TransformState_h
28
29 #include "AffineTransform.h"
30 #include "FloatPoint.h"
31 #include "FloatQuad.h"
32 #include "LayoutSize.h"
33 #include "TransformationMatrix.h"
34
35 namespace WebCore {
36
37 class TransformState {
38 public:
39     enum TransformDirection { ApplyTransformDirection, UnapplyInverseTransformDirection };
40     enum TransformAccumulation { FlattenTransform, AccumulateTransform };
41
42     TransformState(TransformDirection mappingDirection, const FloatPoint& p, const FloatQuad& quad)
43         : m_lastPlanarPoint(p)
44         , m_lastPlanarQuad(quad)
45         , m_accumulatingTransform(false)
46         , m_mapPoint(true)
47         , m_mapQuad(true)
48         , m_direction(mappingDirection)
49     {
50     }
51     
52     TransformState(TransformDirection mappingDirection, const FloatPoint& p)
53         : m_lastPlanarPoint(p)
54         , m_accumulatingTransform(false)
55         , m_mapPoint(true)
56         , m_mapQuad(false)
57         , m_direction(mappingDirection)
58     {
59     }
60     
61     TransformState(TransformDirection mappingDirection, const FloatQuad& quad)
62         : m_lastPlanarQuad(quad)
63         , m_accumulatingTransform(false)
64         , m_mapPoint(false)
65         , m_mapQuad(true)
66         , m_direction(mappingDirection)
67     {
68     }
69     
70     TransformState(const TransformState& other) { *this = other; }
71
72     TransformState& operator=(const TransformState&);
73     
74     void setQuad(const FloatQuad& quad)
75     {
76         // We must be in a flattened state (no accumulated offset) when setting this quad.
77         ASSERT(m_accumulatedOffset == LayoutSize());
78         m_lastPlanarQuad = quad;
79     }
80
81     // FIXME: webkit.org/b/144226 use Optional<FloatQuad>. 
82     void setSecondaryQuad(const FloatQuad* quad)
83     {
84         // We must be in a flattened state (no accumulated offset) when setting this secondary quad.
85         ASSERT(m_accumulatedOffset == LayoutSize());
86         if (quad)
87             m_lastPlanarSecondaryQuad = makeUnique<FloatQuad>(*quad);
88         else
89             m_lastPlanarSecondaryQuad = nullptr;
90     }
91
92     // FIXME: webkit.org/b/144226 use Optional<FloatQuad>.
93     void setLastPlanarSecondaryQuad(const FloatQuad*);
94
95     void move(LayoutUnit x, LayoutUnit y, TransformAccumulation accumulate = FlattenTransform)
96     {
97         move(LayoutSize(x, y), accumulate);
98     }
99
100     void move(const LayoutSize&, TransformAccumulation = FlattenTransform);
101     void applyTransform(const AffineTransform& transformFromContainer, TransformAccumulation = FlattenTransform, bool* wasClamped = nullptr);
102     void applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation = FlattenTransform, bool* wasClamped = nullptr);
103     void flatten(bool* wasClamped = nullptr);
104
105     // Return the coords of the point or quad in the last flattened layer
106     FloatPoint lastPlanarPoint() const { return m_lastPlanarPoint; }
107     FloatQuad lastPlanarQuad() const { return m_lastPlanarQuad; }
108     FloatQuad* lastPlanarSecondaryQuad() const { return m_lastPlanarSecondaryQuad.get(); }
109     bool isMappingSecondaryQuad() const { return m_lastPlanarSecondaryQuad.get(); }
110
111     // Return the point or quad mapped through the current transform
112     FloatPoint mappedPoint(bool* wasClamped = nullptr) const;
113     FloatQuad mappedQuad(bool* wasClamped = nullptr) const;
114     Optional<FloatQuad> mappedSecondaryQuad(bool* wasClamped = nullptr) const;
115
116 private:
117     void translateTransform(const LayoutSize&);
118     void translateMappedCoordinates(const LayoutSize&);
119     void flattenWithTransform(const TransformationMatrix&, bool* wasClamped);
120     void applyAccumulatedOffset();
121     
122     TransformDirection direction() const { return m_direction; }
123     TransformDirection inverseDirection() const;
124
125     void mapQuad(FloatQuad&, TransformDirection, bool* clamped = nullptr) const;
126     
127     FloatPoint m_lastPlanarPoint;
128     FloatQuad m_lastPlanarQuad;
129     std::unique_ptr<FloatQuad> m_lastPlanarSecondaryQuad; // Optional second quad to map.
130
131     // We only allocate the transform if we need to
132     std::unique_ptr<TransformationMatrix> m_accumulatedTransform;
133     LayoutSize m_accumulatedOffset;
134     bool m_accumulatingTransform;
135     bool m_mapPoint;
136     bool m_mapQuad;
137     TransformDirection m_direction;
138 };
139
140 inline TransformState::TransformDirection TransformState::inverseDirection() const
141 {
142     return m_direction == ApplyTransformDirection ? UnapplyInverseTransformDirection : ApplyTransformDirection;
143 }
144
145 } // namespace WebCore
146
147 #endif // TransformState_h