diff options
Diffstat (limited to 'dom/svg/SVGMatrix.h')
-rw-r--r-- | dom/svg/SVGMatrix.h | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/dom/svg/SVGMatrix.h b/dom/svg/SVGMatrix.h new file mode 100644 index 000000000..14646b5fa --- /dev/null +++ b/dom/svg/SVGMatrix.h @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Notes on transforms in Mozilla and the SVG code. + * + * It's important to note that the matrix convention used in the SVG standard + * is the opposite convention to the one used in the Mozilla code or, more + * specifically, the convention used in Thebes code (code using gfxMatrix). + * Whereas the SVG standard uses the column vector convention, Thebes code uses + * the row vector convention. Thus, whereas in the SVG standard you have + * [M1][M2][M3]|p|, in Thebes you have |p|'[M3]'[M2]'[M1]'. In other words, the + * following are equivalent: + * + * / a1 c1 tx1 \ / a2 c2 tx2 \ / a3 c3 tx3 \ / x \ + * SVG: | b1 d1 ty1 | | b2 d2 ty2 | | b3 d3 ty3 | | y | + * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / \ 1 / + * + * / a3 b3 0 \ / a2 b2 0 \ / a1 b1 0 \ + * Thebes: [ x y 1 ] | c3 d3 0 | | c2 d2 0 | | c1 d1 0 | + * \ tx3 ty3 1 / \ tx2 ty2 1 / \ tx1 ty1 1 / + * + * Because the Thebes representation of a transform is the transpose of the SVG + * representation, our transform order must be reversed when representing SVG + * transforms using gfxMatrix in the SVG code. Since the SVG implementation + * stores and obtains matrices in SVG order, to do this we must pre-multiply + * gfxMatrix objects that represent SVG transforms instead of post-multiplying + * them as we would for matrices using SVG's column vector convention. + * Pre-multiplying may look wrong if you're only familiar with the SVG + * convention, but in that case hopefully the above explanation clears things + * up. + */ + +#ifndef mozilla_dom_SVGMatrix_h +#define mozilla_dom_SVGMatrix_h + +#include "mozilla/dom/SVGTransform.h" +#include "gfxMatrix.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" +#include "mozilla/Attributes.h" + +namespace mozilla { +namespace dom { + +/** + * DOM wrapper for an SVG matrix. + */ +class SVGMatrix final : public nsWrapperCache +{ +public: + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SVGMatrix) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(SVGMatrix) + + /** + * Ctor for SVGMatrix objects that belong to a SVGTransform. + */ + explicit SVGMatrix(SVGTransform& aTransform) : mTransform(&aTransform) {} + + /** + * Ctors for SVGMatrix objects created independently of a SVGTransform. + */ + // Default ctor for gfxMatrix will produce identity mx + SVGMatrix() {} + + explicit SVGMatrix(const gfxMatrix &aMatrix) : mMatrix(aMatrix) {} + + const gfxMatrix& GetMatrix() const { + return mTransform ? mTransform->Matrixgfx() : mMatrix; + } + + // WebIDL + SVGTransform* GetParentObject() const; + virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + + float A() const { return static_cast<float>(GetMatrix()._11); } + void SetA(float aA, ErrorResult& rv); + float B() const { return static_cast<float>(GetMatrix()._12); } + void SetB(float aB, ErrorResult& rv); + float C() const { return static_cast<float>(GetMatrix()._21); } + void SetC(float aC, ErrorResult& rv); + float D() const { return static_cast<float>(GetMatrix()._22); } + void SetD(float aD, ErrorResult& rv); + float E() const { return static_cast<float>(GetMatrix()._31); } + void SetE(float aE, ErrorResult& rv); + float F() const { return static_cast<float>(GetMatrix()._32); } + void SetF(float aF, ErrorResult& rv); + already_AddRefed<SVGMatrix> Multiply(SVGMatrix& aMatrix); + already_AddRefed<SVGMatrix> Inverse(ErrorResult& aRv); + already_AddRefed<SVGMatrix> Translate(float x, float y); + already_AddRefed<SVGMatrix> Scale(float scaleFactor); + already_AddRefed<SVGMatrix> ScaleNonUniform(float scaleFactorX, + float scaleFactorY); + already_AddRefed<SVGMatrix> Rotate(float angle); + already_AddRefed<SVGMatrix> RotateFromVector(float x, + float y, + ErrorResult& aRv); + already_AddRefed<SVGMatrix> FlipX(); + already_AddRefed<SVGMatrix> FlipY(); + already_AddRefed<SVGMatrix> SkewX(float angle, ErrorResult& rv); + already_AddRefed<SVGMatrix> SkewY(float angle, ErrorResult& rv); + +private: + ~SVGMatrix() {} + + void SetMatrix(const gfxMatrix& aMatrix) { + if (mTransform) { + mTransform->SetMatrix(aMatrix); + } else { + mMatrix = aMatrix; + } + } + + bool IsAnimVal() const { + return mTransform ? mTransform->IsAnimVal() : false; + } + + RefPtr<SVGTransform> mTransform; + + // Typically we operate on the matrix data accessed via mTransform but for + // matrices that exist independently of an SVGTransform we use mMatrix below. + gfxMatrix mMatrix; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_SVGMatrix_h |