nsStyleTransformMatrix.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. * A class representing three matrices that can be used for style transforms.
  7. */
  8. #ifndef nsStyleTransformMatrix_h_
  9. #define nsStyleTransformMatrix_h_
  10. #include "mozilla/EnumeratedArray.h"
  11. #include "nsCSSValue.h"
  12. #include <limits>
  13. class nsIFrame;
  14. class nsStyleContext;
  15. class nsPresContext;
  16. struct gfxQuaternion;
  17. struct nsRect;
  18. namespace mozilla {
  19. class RuleNodeCacheConditions;
  20. } // namespace mozilla
  21. /**
  22. * A helper to generate gfxMatrixes from css transform functions.
  23. */
  24. namespace nsStyleTransformMatrix {
  25. // Function for applying perspective() transform function. We treat
  26. // any value smaller than epsilon as perspective(infinity), which
  27. // follows CSSWG's resolution on perspective(0). See bug 1316236.
  28. inline void ApplyPerspectiveToMatrix(mozilla::gfx::Matrix4x4& aMatrix,
  29. float aDepth)
  30. {
  31. if (aDepth >= std::numeric_limits<float>::epsilon()) {
  32. aMatrix.Perspective(aDepth);
  33. }
  34. }
  35. /**
  36. * This class provides on-demand access to the 'reference box' for CSS
  37. * transforms (needed to resolve percentage values in 'transform',
  38. * 'transform-origin', etc.):
  39. *
  40. * http://dev.w3.org/csswg/css-transforms/#reference-box
  41. *
  42. * This class helps us to avoid calculating the reference box unless and
  43. * until it is actually needed. This is important for performance when
  44. * transforms are applied to SVG elements since the reference box for SVG is
  45. * much more expensive to calculate (than for elements with a CSS layout box
  46. * where we can use the nsIFrame's cached mRect), much more common (than on
  47. * HTML), and yet very rarely have percentage values that require the
  48. * reference box to be resolved. We also don't want to cause SVG frames to
  49. * cache lots of ObjectBoundingBoxProperty objects that aren't needed.
  50. *
  51. * If UNIFIED_CONTINUATIONS (experimental, and currently broke) is defined,
  52. * we consider the reference box for non-SVG frames to be the smallest
  53. * rectangle containing a frame and all of its continuations. For example,
  54. * if there is a <span> element with several continuations split over
  55. * several lines, this function will return the rectangle containing all of
  56. * those continuations. (This behavior is not currently in a spec.)
  57. */
  58. class MOZ_STACK_CLASS TransformReferenceBox final {
  59. public:
  60. typedef nscoord (TransformReferenceBox::*DimensionGetter)();
  61. explicit TransformReferenceBox()
  62. : mFrame(nullptr)
  63. , mIsCached(false)
  64. {}
  65. explicit TransformReferenceBox(const nsIFrame* aFrame)
  66. : mFrame(aFrame)
  67. , mIsCached(false)
  68. {
  69. MOZ_ASSERT(mFrame);
  70. }
  71. explicit TransformReferenceBox(const nsIFrame* aFrame,
  72. const nsSize& aFallbackDimensions)
  73. {
  74. mFrame = aFrame;
  75. mIsCached = false;
  76. if (!mFrame) {
  77. Init(aFallbackDimensions);
  78. }
  79. }
  80. void Init(const nsIFrame* aFrame) {
  81. MOZ_ASSERT(!mFrame && !mIsCached);
  82. mFrame = aFrame;
  83. }
  84. void Init(const nsSize& aDimensions);
  85. /**
  86. * The offset of the reference box from the nsIFrame's TopLeft(). This
  87. * is non-zero only in the case of SVG content. If we can successfully
  88. * implement UNIFIED_CONTINUATIONS at some point in the future then it
  89. * may also be non-zero for non-SVG content.
  90. */
  91. nscoord X() {
  92. EnsureDimensionsAreCached();
  93. return mX;
  94. }
  95. nscoord Y() {
  96. EnsureDimensionsAreCached();
  97. return mY;
  98. }
  99. /**
  100. * The size of the reference box.
  101. */
  102. nscoord Width() {
  103. EnsureDimensionsAreCached();
  104. return mWidth;
  105. }
  106. nscoord Height() {
  107. EnsureDimensionsAreCached();
  108. return mHeight;
  109. }
  110. bool IsEmpty() {
  111. return !mFrame;
  112. }
  113. private:
  114. // We don't really need to prevent copying, but since none of our consumers
  115. // currently need to copy, preventing copying may allow us to catch some
  116. // cases where we use pass-by-value instead of pass-by-reference.
  117. TransformReferenceBox(const TransformReferenceBox&) = delete;
  118. void EnsureDimensionsAreCached();
  119. const nsIFrame* mFrame;
  120. nscoord mX, mY, mWidth, mHeight;
  121. bool mIsCached;
  122. };
  123. /**
  124. * Return the transform function, as an nsCSSKeyword, for the given
  125. * nsCSSValue::Array from a transform list.
  126. */
  127. nsCSSKeyword TransformFunctionOf(const nsCSSValue::Array* aData);
  128. void SetIdentityMatrix(nsCSSValue::Array* aMatrix);
  129. float ProcessTranslatePart(const nsCSSValue& aValue,
  130. nsStyleContext* aContext,
  131. nsPresContext* aPresContext,
  132. mozilla::RuleNodeCacheConditions& aConditions,
  133. TransformReferenceBox* aRefBox,
  134. TransformReferenceBox::DimensionGetter aDimensionGetter = nullptr);
  135. void
  136. ProcessInterpolateMatrix(mozilla::gfx::Matrix4x4& aMatrix,
  137. const nsCSSValue::Array* aData,
  138. nsStyleContext* aContext,
  139. nsPresContext* aPresContext,
  140. mozilla::RuleNodeCacheConditions& aConditions,
  141. TransformReferenceBox& aBounds,
  142. bool* aContains3dTransform);
  143. /**
  144. * Given an nsCSSValueList containing -moz-transform functions,
  145. * returns a matrix containing the value of those functions.
  146. *
  147. * @param aData The nsCSSValueList containing the transform functions
  148. * @param aContext The style context, used for unit conversion.
  149. * @param aPresContext The presentation context, used for unit conversion.
  150. * @param aConditions Set to uncachable (by calling SetUncacheable()) if the
  151. * result cannot be cached in the rule tree, otherwise untouched.
  152. * @param aBounds The frame's bounding rectangle.
  153. * @param aAppUnitsPerMatrixUnit The number of app units per device pixel.
  154. * @param aContains3dTransform [out] Set to true if aList contains at least
  155. * one 3d transform function (as defined in the CSS transforms
  156. * specification), false otherwise.
  157. *
  158. * aContext and aPresContext may be null if all of the (non-percent)
  159. * length values in aData are already known to have been converted to
  160. * eCSSUnit_Pixel (as they are in an StyleAnimationValue)
  161. */
  162. mozilla::gfx::Matrix4x4 ReadTransforms(const nsCSSValueList* aList,
  163. nsStyleContext* aContext,
  164. nsPresContext* aPresContext,
  165. mozilla::RuleNodeCacheConditions& aConditions,
  166. TransformReferenceBox& aBounds,
  167. float aAppUnitsPerMatrixUnit,
  168. bool* aContains3dTransform);
  169. // Shear type for decomposition.
  170. enum class ShearType {
  171. XYSHEAR,
  172. XZSHEAR,
  173. YZSHEAR,
  174. Count
  175. };
  176. using ShearArray =
  177. mozilla::EnumeratedArray<ShearType, ShearType::Count, float>;
  178. /*
  179. * Implements the 2d transform matrix decomposition algorithm.
  180. */
  181. bool Decompose2DMatrix(const mozilla::gfx::Matrix& aMatrix,
  182. mozilla::gfx::Point3D& aScale,
  183. ShearArray& aShear,
  184. gfxQuaternion& aRotate,
  185. mozilla::gfx::Point3D& aTranslate);
  186. /*
  187. * Implements the 3d transform matrix decomposition algorithm.
  188. */
  189. bool Decompose3DMatrix(const mozilla::gfx::Matrix4x4& aMatrix,
  190. mozilla::gfx::Point3D& aScale,
  191. ShearArray& aShear,
  192. gfxQuaternion& aRotate,
  193. mozilla::gfx::Point3D& aTranslate,
  194. mozilla::gfx::Point4D& aPerspective);
  195. mozilla::gfx::Matrix CSSValueArrayTo2DMatrix(nsCSSValue::Array* aArray);
  196. mozilla::gfx::Matrix4x4 CSSValueArrayTo3DMatrix(nsCSSValue::Array* aArray);
  197. } // namespace nsStyleTransformMatrix
  198. #endif