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/. */
8 * A class representing three matrices that can be used for style transforms.
11 #ifndef nsStyleTransformMatrix_h_
12 #define nsStyleTransformMatrix_h_
14 #include "mozilla/gfx/Matrix.h"
15 #include "mozilla/EnumeratedArray.h"
16 #include "mozilla/ServoStyleConsts.h"
18 #include "Units.h" // for CSSPoint
27 struct ResolvedMotionPathData
;
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
};
38 * This class provides on-demand access to the 'reference box' for CSS
39 * transforms (needed to resolve percentage values in 'transform',
40 * 'transform-origin', etc.):
42 * http://dev.w3.org/csswg/css-transforms/#reference-box
44 * This class helps us to avoid calculating the reference box unless and
45 * until it is actually needed. This is important for performance when
46 * transforms are applied to SVG elements since the reference box for SVG is
47 * much more expensive to calculate (than for elements with a CSS layout box
48 * where we can use the nsIFrame's cached mRect), much more common (than on
49 * HTML), and yet very rarely have percentage values that require the
50 * reference box to be resolved. We also don't want to cause SVG frames to
51 * cache lots of ObjectBoundingBoxProperty objects that aren't needed.
53 * If UNIFIED_CONTINUATIONS (experimental, and currently broke) is defined,
54 * we consider the reference box for non-SVG frames to be the smallest
55 * rectangle containing a frame and all of its continuations. For example,
56 * if there is a <span> element with several continuations split over
57 * several lines, this function will return the rectangle containing all of
58 * those continuations. (This behavior is not currently in a spec.)
60 class MOZ_STACK_CLASS TransformReferenceBox final
{
62 typedef nscoord (TransformReferenceBox::*DimensionGetter
)();
64 explicit TransformReferenceBox()
72 explicit TransformReferenceBox(const nsIFrame
* aFrame
)
73 : mFrame(aFrame
), mX(0), mY(0), mWidth(0), mHeight(0), mIsCached(false) {
77 explicit TransformReferenceBox(const nsIFrame
* aFrame
,
78 const nsRect
& aFallbackDimensions
)
79 : mX(0), mY(0), mWidth(0), mHeight(0) {
83 Init(aFallbackDimensions
);
87 void Init(const nsIFrame
* aFrame
) {
88 MOZ_ASSERT(!mFrame
&& !mIsCached
);
92 void Init(const nsRect
& aDimensions
);
95 * The offset of the reference box from the nsIFrame's TopLeft(). This
96 * is non-zero only in the case of SVG content. If we can successfully
97 * implement UNIFIED_CONTINUATIONS at some point in the future then it
98 * may also be non-zero for non-SVG content.
101 EnsureDimensionsAreCached();
105 EnsureDimensionsAreCached();
110 * The size of the reference box.
113 EnsureDimensionsAreCached();
117 EnsureDimensionsAreCached();
121 bool IsEmpty() { return !mFrame
; }
124 // We don't really need to prevent copying, but since none of our consumers
125 // currently need to copy, preventing copying may allow us to catch some
126 // cases where we use pass-by-value instead of pass-by-reference.
127 TransformReferenceBox(const TransformReferenceBox
&) = delete;
129 void EnsureDimensionsAreCached();
131 const nsIFrame
* mFrame
;
132 nscoord mX
, mY
, mWidth
, mHeight
;
136 float ProcessTranslatePart(
137 const mozilla::LengthPercentage
& aValue
, TransformReferenceBox
* aRefBox
,
138 TransformReferenceBox::DimensionGetter aDimensionGetter
= nullptr);
140 void ProcessInterpolateMatrix(mozilla::gfx::Matrix4x4
& aMatrix
,
141 const mozilla::StyleTransformOperation
& aOp
,
142 TransformReferenceBox
& aBounds
);
144 void ProcessAccumulateMatrix(mozilla::gfx::Matrix4x4
& aMatrix
,
145 const mozilla::StyleTransformOperation
& aOp
,
146 TransformReferenceBox
& aBounds
);
149 * Given a StyleTransform containing transform functions, returns a matrix
150 * containing the value of those functions.
152 * @param aList the transform operation list.
153 * @param aBounds The frame's bounding rectangle.
154 * @param aAppUnitsPerMatrixUnit The number of app units per device pixel.
156 mozilla::gfx::Matrix4x4
ReadTransforms(const mozilla::StyleTransform
& aList
,
157 TransformReferenceBox
& aBounds
,
158 float aAppUnitsPerMatrixUnit
);
160 // Generate the gfx::Matrix for CSS Transform Module Level 2.
161 // https://drafts.csswg.org/css-transforms-2/#ctm
162 mozilla::gfx::Matrix4x4
ReadTransforms(
163 const mozilla::StyleTranslate
&, const mozilla::StyleRotate
&,
164 const mozilla::StyleScale
&,
165 const mozilla::Maybe
<mozilla::ResolvedMotionPathData
>& aMotion
,
166 const mozilla::StyleTransform
&, TransformReferenceBox
& aRefBox
,
167 float aAppUnitsPerMatrixUnit
);
170 * Given the x and y values, compute the 2d position with respect to the given
171 * a reference box size that these values describe, in CSS pixels.
173 mozilla::CSSPoint
Convert2DPosition(const mozilla::LengthPercentage
& aX
,
174 const mozilla::LengthPercentage
& aY
,
175 const mozilla::CSSSize
& aSize
);
178 * Given the x and y values, compute the 2d position with respect to the given
179 * TransformReferenceBox that these values describe, in CSS pixels.
181 mozilla::CSSPoint
Convert2DPosition(const mozilla::LengthPercentage
& aX
,
182 const mozilla::LengthPercentage
& aY
,
183 TransformReferenceBox
& aRefBox
);
186 * Given the x and y values, compute the 2d position with respect to the given
187 * TransformReferenceBox that these values describe, in device pixels.
189 mozilla::gfx::Point
Convert2DPosition(const mozilla::LengthPercentage
& aX
,
190 const mozilla::LengthPercentage
& aY
,
191 TransformReferenceBox
& aRefBox
,
192 int32_t aAppUnitsPerDevPixel
);
194 // Shear type for decomposition.
195 enum class ShearType
{ XY
, XZ
, YZ
, Count
};
196 using ShearArray
= mozilla::EnumeratedArray
<ShearType
, ShearType::Count
, float>;
199 * Implements the 2d transform matrix decomposition algorithm.
201 bool Decompose2DMatrix(const mozilla::gfx::Matrix
& aMatrix
,
202 mozilla::gfx::Point3D
& aScale
, ShearArray
& aShear
,
203 gfxQuaternion
& aRotate
,
204 mozilla::gfx::Point3D
& aTranslate
);
206 * Implements the 3d transform matrix decomposition algorithm.
208 bool Decompose3DMatrix(const mozilla::gfx::Matrix4x4
& aMatrix
,
209 mozilla::gfx::Point3D
& aScale
, ShearArray
& aShear
,
210 gfxQuaternion
& aRotate
,
211 mozilla::gfx::Point3D
& aTranslate
,
212 mozilla::gfx::Point4D
& aPerspective
);
214 } // namespace nsStyleTransformMatrix