SVGMatrix.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* -*- Mode: C++; tab-width: 8; 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. * Notes on transforms in Mozilla and the SVG code.
  7. *
  8. * It's important to note that the matrix convention used in the SVG standard
  9. * is the opposite convention to the one used in the Mozilla code or, more
  10. * specifically, the convention used in Thebes code (code using gfxMatrix).
  11. * Whereas the SVG standard uses the column vector convention, Thebes code uses
  12. * the row vector convention. Thus, whereas in the SVG standard you have
  13. * [M1][M2][M3]|p|, in Thebes you have |p|'[M3]'[M2]'[M1]'. In other words, the
  14. * following are equivalent:
  15. *
  16. * / a1 c1 tx1 \ / a2 c2 tx2 \ / a3 c3 tx3 \ / x \
  17. * SVG: | b1 d1 ty1 | | b2 d2 ty2 | | b3 d3 ty3 | | y |
  18. * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / \ 1 /
  19. *
  20. * / a3 b3 0 \ / a2 b2 0 \ / a1 b1 0 \
  21. * Thebes: [ x y 1 ] | c3 d3 0 | | c2 d2 0 | | c1 d1 0 |
  22. * \ tx3 ty3 1 / \ tx2 ty2 1 / \ tx1 ty1 1 /
  23. *
  24. * Because the Thebes representation of a transform is the transpose of the SVG
  25. * representation, our transform order must be reversed when representing SVG
  26. * transforms using gfxMatrix in the SVG code. Since the SVG implementation
  27. * stores and obtains matrices in SVG order, to do this we must pre-multiply
  28. * gfxMatrix objects that represent SVG transforms instead of post-multiplying
  29. * them as we would for matrices using SVG's column vector convention.
  30. * Pre-multiplying may look wrong if you're only familiar with the SVG
  31. * convention, but in that case hopefully the above explanation clears things
  32. * up.
  33. */
  34. #ifndef mozilla_dom_SVGMatrix_h
  35. #define mozilla_dom_SVGMatrix_h
  36. #include "mozilla/dom/SVGTransform.h"
  37. #include "gfxMatrix.h"
  38. #include "nsCycleCollectionParticipant.h"
  39. #include "nsWrapperCache.h"
  40. #include "mozilla/Attributes.h"
  41. namespace mozilla {
  42. namespace dom {
  43. /**
  44. * DOM wrapper for an SVG matrix.
  45. */
  46. class SVGMatrix final : public nsWrapperCache
  47. {
  48. public:
  49. NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SVGMatrix)
  50. NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(SVGMatrix)
  51. /**
  52. * Ctor for SVGMatrix objects that belong to a SVGTransform.
  53. */
  54. explicit SVGMatrix(SVGTransform& aTransform) : mTransform(&aTransform) {}
  55. /**
  56. * Ctors for SVGMatrix objects created independently of a SVGTransform.
  57. */
  58. // Default ctor for gfxMatrix will produce identity mx
  59. SVGMatrix() {}
  60. explicit SVGMatrix(const gfxMatrix &aMatrix) : mMatrix(aMatrix) {}
  61. const gfxMatrix& GetMatrix() const {
  62. return mTransform ? mTransform->Matrixgfx() : mMatrix;
  63. }
  64. // WebIDL
  65. SVGTransform* GetParentObject() const;
  66. virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
  67. float A() const { return static_cast<float>(GetMatrix()._11); }
  68. void SetA(float aA, ErrorResult& rv);
  69. float B() const { return static_cast<float>(GetMatrix()._12); }
  70. void SetB(float aB, ErrorResult& rv);
  71. float C() const { return static_cast<float>(GetMatrix()._21); }
  72. void SetC(float aC, ErrorResult& rv);
  73. float D() const { return static_cast<float>(GetMatrix()._22); }
  74. void SetD(float aD, ErrorResult& rv);
  75. float E() const { return static_cast<float>(GetMatrix()._31); }
  76. void SetE(float aE, ErrorResult& rv);
  77. float F() const { return static_cast<float>(GetMatrix()._32); }
  78. void SetF(float aF, ErrorResult& rv);
  79. already_AddRefed<SVGMatrix> Multiply(SVGMatrix& aMatrix);
  80. already_AddRefed<SVGMatrix> Inverse(ErrorResult& aRv);
  81. already_AddRefed<SVGMatrix> Translate(float x, float y);
  82. already_AddRefed<SVGMatrix> Scale(float scaleFactor);
  83. already_AddRefed<SVGMatrix> ScaleNonUniform(float scaleFactorX,
  84. float scaleFactorY);
  85. already_AddRefed<SVGMatrix> Rotate(float angle);
  86. already_AddRefed<SVGMatrix> RotateFromVector(float x,
  87. float y,
  88. ErrorResult& aRv);
  89. already_AddRefed<SVGMatrix> FlipX();
  90. already_AddRefed<SVGMatrix> FlipY();
  91. already_AddRefed<SVGMatrix> SkewX(float angle, ErrorResult& rv);
  92. already_AddRefed<SVGMatrix> SkewY(float angle, ErrorResult& rv);
  93. private:
  94. ~SVGMatrix() {}
  95. void SetMatrix(const gfxMatrix& aMatrix) {
  96. if (mTransform) {
  97. mTransform->SetMatrix(aMatrix);
  98. } else {
  99. mMatrix = aMatrix;
  100. }
  101. }
  102. bool IsAnimVal() const {
  103. return mTransform ? mTransform->IsAnimVal() : false;
  104. }
  105. RefPtr<SVGTransform> mTransform;
  106. // Typically we operate on the matrix data accessed via mTransform but for
  107. // matrices that exist independently of an SVGTransform we use mMatrix below.
  108. gfxMatrix mMatrix;
  109. };
  110. } // namespace dom
  111. } // namespace mozilla
  112. #endif // mozilla_dom_SVGMatrix_h