Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / layout / style / nsStyleTransformMatrix.h
blob57e2742aa381059b26d8883b86ce8282f1f45006
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;
28 } // namespace mozilla
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 /**
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 {
61 public:
62 typedef nscoord (TransformReferenceBox::*DimensionGetter)();
64 TransformReferenceBox() = default;
66 explicit TransformReferenceBox(const nsIFrame* aFrame) : mFrame(aFrame) {
67 MOZ_ASSERT(mFrame);
70 TransformReferenceBox(const nsIFrame* aFrame,
71 const nsRect& aFallbackDimensions) {
72 mFrame = aFrame;
73 if (!mFrame) {
74 Init(aFallbackDimensions);
78 void Init(const nsIFrame* aFrame) {
79 MOZ_ASSERT(!mFrame && !mIsCached);
80 mFrame = aFrame;
83 void Init(const nsRect& aDimensions) {
84 MOZ_ASSERT(!mFrame && !mIsCached);
85 mBox = aDimensions;
86 mIsCached = true;
89 /**
90 * The offset of the reference box from the nsIFrame's TopLeft(). This
91 * is non-zero only in the case of SVG content. If we can successfully
92 * implement UNIFIED_CONTINUATIONS at some point in the future then it
93 * may also be non-zero for non-SVG content.
95 nscoord X() {
96 EnsureDimensionsAreCached();
97 return mBox.X();
99 nscoord Y() {
100 EnsureDimensionsAreCached();
101 return mBox.Y();
105 * The size of the reference box.
107 nscoord Width() {
108 EnsureDimensionsAreCached();
109 return mBox.Width();
111 nscoord Height() {
112 EnsureDimensionsAreCached();
113 return mBox.Height();
116 bool IsEmpty() { return !mFrame; }
118 private:
119 // We don't really need to prevent copying, but since none of our consumers
120 // currently need to copy, preventing copying may allow us to catch some
121 // cases where we use pass-by-value instead of pass-by-reference.
122 TransformReferenceBox(const TransformReferenceBox&) = delete;
124 void EnsureDimensionsAreCached();
126 const nsIFrame* mFrame = nullptr;
127 nsRect mBox;
128 bool mIsCached = false;
131 float ProcessTranslatePart(
132 const mozilla::LengthPercentage& aValue, TransformReferenceBox* aRefBox,
133 TransformReferenceBox::DimensionGetter aDimensionGetter = nullptr);
135 void ProcessInterpolateMatrix(mozilla::gfx::Matrix4x4& aMatrix,
136 const mozilla::StyleTransformOperation& aOp,
137 TransformReferenceBox& aBounds);
139 void ProcessAccumulateMatrix(mozilla::gfx::Matrix4x4& aMatrix,
140 const mozilla::StyleTransformOperation& aOp,
141 TransformReferenceBox& aBounds);
144 * Given a StyleTransform containing transform functions, returns a matrix
145 * containing the value of those functions.
147 * @param aList the transform operation list.
148 * @param aBounds The frame's bounding rectangle.
149 * @param aAppUnitsPerMatrixUnit The number of app units per device pixel.
151 mozilla::gfx::Matrix4x4 ReadTransforms(const mozilla::StyleTransform& aList,
152 TransformReferenceBox& aBounds,
153 float aAppUnitsPerMatrixUnit);
155 // Generate the gfx::Matrix for CSS Transform Module Level 2.
156 // https://drafts.csswg.org/css-transforms-2/#ctm
157 mozilla::gfx::Matrix4x4 ReadTransforms(
158 const mozilla::StyleTranslate&, const mozilla::StyleRotate&,
159 const mozilla::StyleScale&, const mozilla::ResolvedMotionPathData* aMotion,
160 const mozilla::StyleTransform&, TransformReferenceBox& aRefBox,
161 float aAppUnitsPerMatrixUnit);
164 * Given the x and y values, compute the 2d position with respect to the given
165 * a reference box size that these values describe, in CSS pixels.
167 mozilla::CSSPoint Convert2DPosition(const mozilla::LengthPercentage& aX,
168 const mozilla::LengthPercentage& aY,
169 const mozilla::CSSSize& aSize);
172 * Given the x and y values, compute the 2d position with respect to the given
173 * TransformReferenceBox that these values describe, in CSS pixels.
175 mozilla::CSSPoint Convert2DPosition(const mozilla::LengthPercentage& aX,
176 const mozilla::LengthPercentage& aY,
177 TransformReferenceBox& aRefBox);
180 * Given the x and y values, compute the 2d position with respect to the given
181 * TransformReferenceBox that these values describe, in device pixels.
183 mozilla::gfx::Point Convert2DPosition(const mozilla::LengthPercentage& aX,
184 const mozilla::LengthPercentage& aY,
185 TransformReferenceBox& aRefBox,
186 int32_t aAppUnitsPerDevPixel);
188 } // namespace nsStyleTransformMatrix
190 #endif