Bug 1637593 [wpt PR 23564] - Fix superclass calls in MarionetteRefTestExecutor, a...
[gecko.git] / layout / style / nsStyleTransformMatrix.h
blob0655ae9fe0a6e0f42711149f4e5abbadf290fcee
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
8 * A class representing three matrices that can be used for style transforms.
9 */
11 #ifndef nsStyleTransformMatrix_h_
12 #define nsStyleTransformMatrix_h_
14 #include "mozilla/gfx/Matrix.h"
15 #include "mozilla/EnumeratedArray.h"
16 #include "mozilla/ServoStyleConsts.h"
17 #include "nsSize.h"
18 #include "Units.h" // for CSSPoint
19 #include <limits>
21 class nsIFrame;
22 class nsPresContext;
23 struct gfxQuaternion;
24 struct nsRect;
26 namespace mozilla {
27 struct ResolvedMotionPathData;
30 /**
31 * A helper to generate gfxMatrixes from css transform functions.
33 namespace nsStyleTransformMatrix {
34 // The operator passed to Servo backend.
35 enum class MatrixTransformOperator : uint8_t { Interpolate, Accumulate };
37 // Function for applying perspective() transform function. We treat
38 // any value smaller than epsilon as perspective(infinity), which
39 // follows CSSWG's resolution on perspective(0). See bug 1316236.
40 inline void ApplyPerspectiveToMatrix(mozilla::gfx::Matrix4x4& aMatrix,
41 float aDepth) {
42 if (aDepth >= std::numeric_limits<float>::epsilon()) {
43 aMatrix.Perspective(aDepth);
47 /**
48 * This class provides on-demand access to the 'reference box' for CSS
49 * transforms (needed to resolve percentage values in 'transform',
50 * 'transform-origin', etc.):
52 * http://dev.w3.org/csswg/css-transforms/#reference-box
54 * This class helps us to avoid calculating the reference box unless and
55 * until it is actually needed. This is important for performance when
56 * transforms are applied to SVG elements since the reference box for SVG is
57 * much more expensive to calculate (than for elements with a CSS layout box
58 * where we can use the nsIFrame's cached mRect), much more common (than on
59 * HTML), and yet very rarely have percentage values that require the
60 * reference box to be resolved. We also don't want to cause SVG frames to
61 * cache lots of ObjectBoundingBoxProperty objects that aren't needed.
63 * If UNIFIED_CONTINUATIONS (experimental, and currently broke) is defined,
64 * we consider the reference box for non-SVG frames to be the smallest
65 * rectangle containing a frame and all of its continuations. For example,
66 * if there is a <span> element with several continuations split over
67 * several lines, this function will return the rectangle containing all of
68 * those continuations. (This behavior is not currently in a spec.)
70 class MOZ_STACK_CLASS TransformReferenceBox final {
71 public:
72 typedef nscoord (TransformReferenceBox::*DimensionGetter)();
74 explicit TransformReferenceBox()
75 : mFrame(nullptr),
76 mX(0),
77 mY(0),
78 mWidth(0),
79 mHeight(0),
80 mIsCached(false) {}
82 explicit TransformReferenceBox(const nsIFrame* aFrame)
83 : mFrame(aFrame), mX(0), mY(0), mWidth(0), mHeight(0), mIsCached(false) {
84 MOZ_ASSERT(mFrame);
87 explicit TransformReferenceBox(const nsIFrame* aFrame,
88 const nsRect& aFallbackDimensions)
89 : mX(0), mY(0), mWidth(0), mHeight(0) {
90 mFrame = aFrame;
91 mIsCached = false;
92 if (!mFrame) {
93 Init(aFallbackDimensions);
97 void Init(const nsIFrame* aFrame) {
98 MOZ_ASSERT(!mFrame && !mIsCached);
99 mFrame = aFrame;
102 void Init(const nsRect& aDimensions);
105 * The offset of the reference box from the nsIFrame's TopLeft(). This
106 * is non-zero only in the case of SVG content. If we can successfully
107 * implement UNIFIED_CONTINUATIONS at some point in the future then it
108 * may also be non-zero for non-SVG content.
110 nscoord X() {
111 EnsureDimensionsAreCached();
112 return mX;
114 nscoord Y() {
115 EnsureDimensionsAreCached();
116 return mY;
120 * The size of the reference box.
122 nscoord Width() {
123 EnsureDimensionsAreCached();
124 return mWidth;
126 nscoord Height() {
127 EnsureDimensionsAreCached();
128 return mHeight;
131 bool IsEmpty() { return !mFrame; }
133 private:
134 // We don't really need to prevent copying, but since none of our consumers
135 // currently need to copy, preventing copying may allow us to catch some
136 // cases where we use pass-by-value instead of pass-by-reference.
137 TransformReferenceBox(const TransformReferenceBox&) = delete;
139 void EnsureDimensionsAreCached();
141 const nsIFrame* mFrame;
142 nscoord mX, mY, mWidth, mHeight;
143 bool mIsCached;
146 float ProcessTranslatePart(
147 const mozilla::LengthPercentage& aValue, TransformReferenceBox* aRefBox,
148 TransformReferenceBox::DimensionGetter aDimensionGetter = nullptr);
150 void ProcessInterpolateMatrix(mozilla::gfx::Matrix4x4& aMatrix,
151 const mozilla::StyleTransformOperation& aOp,
152 TransformReferenceBox& aBounds);
154 void ProcessAccumulateMatrix(mozilla::gfx::Matrix4x4& aMatrix,
155 const mozilla::StyleTransformOperation& aOp,
156 TransformReferenceBox& aBounds);
159 * Given a StyleTransform containing transform functions, returns a matrix
160 * containing the value of those functions.
162 * @param aList the transform operation list.
163 * @param aBounds The frame's bounding rectangle.
164 * @param aAppUnitsPerMatrixUnit The number of app units per device pixel.
166 mozilla::gfx::Matrix4x4 ReadTransforms(const mozilla::StyleTransform& aList,
167 TransformReferenceBox& aBounds,
168 float aAppUnitsPerMatrixUnit);
170 // Generate the gfx::Matrix for CSS Transform Module Level 2.
171 // https://drafts.csswg.org/css-transforms-2/#ctm
172 mozilla::gfx::Matrix4x4 ReadTransforms(
173 const mozilla::StyleTranslate&, const mozilla::StyleRotate&,
174 const mozilla::StyleScale&,
175 const mozilla::Maybe<mozilla::ResolvedMotionPathData>& aMotion,
176 const mozilla::StyleTransform&, TransformReferenceBox& aRefBox,
177 float aAppUnitsPerMatrixUnit);
180 * Given the x and y values, compute the 2d position with respect to the given
181 * a reference box size that these values describe, in CSS pixels.
183 mozilla::CSSPoint Convert2DPosition(const mozilla::LengthPercentage& aX,
184 const mozilla::LengthPercentage& aY,
185 const mozilla::CSSSize& aSize);
188 * Given the x and y values, compute the 2d position with respect to the given
189 * TransformReferenceBox that these values describe, in CSS pixels.
191 mozilla::CSSPoint Convert2DPosition(const mozilla::LengthPercentage& aX,
192 const mozilla::LengthPercentage& aY,
193 TransformReferenceBox& aRefBox);
196 * Given the x and y values, compute the 2d position with respect to the given
197 * TransformReferenceBox that these values describe, in device pixels.
199 mozilla::gfx::Point Convert2DPosition(const mozilla::LengthPercentage& aX,
200 const mozilla::LengthPercentage& aY,
201 TransformReferenceBox& aRefBox,
202 int32_t aAppUnitsPerDevPixel);
204 // Shear type for decomposition.
205 enum class ShearType { XY, XZ, YZ, Count };
206 using ShearArray = mozilla::EnumeratedArray<ShearType, ShearType::Count, float>;
209 * Implements the 2d transform matrix decomposition algorithm.
211 bool Decompose2DMatrix(const mozilla::gfx::Matrix& aMatrix,
212 mozilla::gfx::Point3D& aScale, ShearArray& aShear,
213 gfxQuaternion& aRotate,
214 mozilla::gfx::Point3D& aTranslate);
216 * Implements the 3d transform matrix decomposition algorithm.
218 bool Decompose3DMatrix(const mozilla::gfx::Matrix4x4& aMatrix,
219 mozilla::gfx::Point3D& aScale, ShearArray& aShear,
220 gfxQuaternion& aRotate,
221 mozilla::gfx::Point3D& aTranslate,
222 mozilla::gfx::Point4D& aPerspective);
224 } // namespace nsStyleTransformMatrix
226 #endif