diff --git a/dom/canvas/CanvasPattern.h b/dom/canvas/CanvasPattern.h index a2eba2e79ec2..e627bf038dba 100644 --- a/dom/canvas/CanvasPattern.h +++ b/dom/canvas/CanvasPattern.h @@ -20,7 +20,7 @@ class SourceSurface; } // namespace gfx namespace dom { -class SVGMatrix; +struct DOMMatrix2DInit; class CanvasPattern final : public nsWrapperCache { ~CanvasPattern() = default; @@ -51,7 +51,7 @@ class CanvasPattern final : public nsWrapperCache { CanvasRenderingContext2D* GetParentObject() { return mContext; } // WebIDL - void SetTransform(SVGMatrix& matrix); + void SetTransform(const DOMMatrix2DInit& aInit, ErrorResult& aError); RefPtr mContext; RefPtr mSurface; diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 5153c714636d..5c5e53198535 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -104,9 +104,7 @@ #include "mozilla/dom/HTMLImageElement.h" #include "mozilla/dom/HTMLVideoElement.h" #include "mozilla/dom/SVGImageElement.h" -#include "mozilla/dom/SVGMatrix.h" #include "mozilla/dom/TextMetrics.h" -#include "mozilla/dom/SVGMatrix.h" #include "mozilla/FloatingPoint.h" #include "nsGlobalWindow.h" #include "nsFilterInstance.h" @@ -703,8 +701,18 @@ class AdjustedTarget { UniquePtr mFilterTarget; }; -void CanvasPattern::SetTransform(SVGMatrix& aMatrix) { - mTransform = ToMatrix(aMatrix.GetMatrix()); +void CanvasPattern::SetTransform(const DOMMatrix2DInit& aInit, + ErrorResult& aError) { + RefPtr matrix = + DOMMatrixReadOnly::FromMatrix(GetParentObject(), aInit, aError); + if (aError.Failed()) { + return; + } + const auto* matrix2D = matrix->GetInternal2D(); + if (!matrix2D->IsFinite()) { + return; + } + mTransform = Matrix(*matrix2D); } void CanvasGradient::AddColorStop(float aOffset, const nsACString& aColorstr, diff --git a/dom/canvas/test/test_2d_composite_canvaspattern_setTransform.html b/dom/canvas/test/test_2d_composite_canvaspattern_setTransform.html index 2c525c2362e8..21f15ae3d906 100644 --- a/dom/canvas/test/test_2d_composite_canvaspattern_setTransform.html +++ b/dom/canvas/test/test_2d_composite_canvaspattern_setTransform.html @@ -28,7 +28,6 @@ function isPixel(ctx, x,y, r,g,b,a, d) {

Canvas test: 2d.composite.canvaspattern.setTransform

FAIL (fallback content)

- @@ -42,8 +41,7 @@ function test_2d_canvaspattern_setTransform() { var img = document.getElementById("rgrg-256x256.png"); var pat = ctx.createPattern(img,"repeat"); - var svg = document.getElementById("svg1"); - var mtx = svg1.createSVGMatrix(); + var mtx = new DOMMatrix() pat.setTransform(mtx.rotate(-45).scale(0.1)); ctx.fillStyle = pat; ctx.fillRect(0, 0, 100, 50); diff --git a/dom/svg/SVGMatrix.h b/dom/svg/SVGMatrix.h index 23d8f794068f..7277ccfe97fd 100644 --- a/dom/svg/SVGMatrix.h +++ b/dom/svg/SVGMatrix.h @@ -67,10 +67,6 @@ class SVGMatrix final : public nsWrapperCache { explicit SVGMatrix(const gfxMatrix& aMatrix) : mMatrix(aMatrix) {} - const gfxMatrix& GetMatrix() const { - return mTransform ? mTransform->Matrixgfx() : mMatrix; - } - // WebIDL DOMSVGTransform* GetParentObject() const; virtual JSObject* WrapObject(JSContext* aCx, @@ -105,6 +101,10 @@ class SVGMatrix final : public nsWrapperCache { private: ~SVGMatrix() = default; + const gfxMatrix& GetMatrix() const { + return mTransform ? mTransform->Matrixgfx() : mMatrix; + } + void SetMatrix(const gfxMatrix& aMatrix) { if (mTransform) { mTransform->SetMatrix(aMatrix); diff --git a/dom/webidl/CanvasRenderingContext2D.webidl b/dom/webidl/CanvasRenderingContext2D.webidl index 705eb3a35208..f65d1aae6843 100644 --- a/dom/webidl/CanvasRenderingContext2D.webidl +++ b/dom/webidl/CanvasRenderingContext2D.webidl @@ -348,8 +348,8 @@ interface CanvasPattern { // [Throws, LenientFloat] - could not do this overload because of bug 1020975 // void setTransform(double a, double b, double c, double d, double e, double f); - // No throw necessary here - SVGMatrix is always good. - void setTransform(SVGMatrix matrix); + [Throws] + void setTransform(optional DOMMatrix2DInit matrix = {}); }; [Exposed=Window] diff --git a/testing/web-platform/meta/html/dom/idlharness.https.html.ini b/testing/web-platform/meta/html/dom/idlharness.https.html.ini index 47069467af68..2ec11ce00175 100644 --- a/testing/web-platform/meta/html/dom/idlharness.https.html.ini +++ b/testing/web-platform/meta/html/dom/idlharness.https.html.ini @@ -675,9 +675,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.expe [OffscreenCanvasRenderingContext2D interface: operation fillText(DOMString, unrestricted double, unrestricted double, optional unrestricted double)] expected: FAIL - [CanvasPattern interface: operation setTransform(optional DOMMatrix2DInit)] - expected: FAIL - [ElementInternals interface: operation setFormValue((File or USVString or FormData)?, optional (File or USVString or FormData)?)] expected: FAIL diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.identity.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.identity.html new file mode 100644 index 000000000000..56a44df86bd3 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.identity.html @@ -0,0 +1,42 @@ + + +Canvas test: 2d.pattern.transform.identity + + + + + + +

2d.pattern.transform.identity

+

+ + +

Actual output:

+

FAIL (fallback content)

+

Expected output:

+

    + + diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.infinity.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.infinity.html new file mode 100644 index 000000000000..d298d70c3505 --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.infinity.html @@ -0,0 +1,42 @@ + + +Canvas test: 2d.pattern.transform.infinity + + + + + + +

    2d.pattern.transform.infinity

    +

    + + +

    Actual output:

    +

    FAIL (fallback content)

    +

    Expected output:

    +

      + + diff --git a/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.invalid.html b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.invalid.html new file mode 100644 index 000000000000..ebd2801241ce --- /dev/null +++ b/testing/web-platform/tests/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.invalid.html @@ -0,0 +1,31 @@ + + +Canvas test: 2d.pattern.transform.invalid + + + + + + +

      2d.pattern.transform.invalid

      +

      + + +

      Actual output:

      +

      FAIL (fallback content)

      + +
        + + diff --git a/testing/web-platform/tests/html/canvas/tools/spec.yaml b/testing/web-platform/tests/html/canvas/tools/spec.yaml index be86c7fb6e1c..d4b1840a69f7 100644 --- a/testing/web-platform/tests/html/canvas/tools/spec.yaml +++ b/testing/web-platform/tests/html/canvas/tools/spec.yaml @@ -269,6 +269,8 @@ assertions: - id: 2d.pattern.modify text: "Modifying this image after calling the createPattern() method *must* not affect the pattern<^>." + - id: 2d.pattern.transform + text: "The setTransform(transform) method, when invoked, must run these steps:" - id: 2d.pattern.missing text: "If the empty string is specified, repeat *must* be assumed<^>." - id: 2d.pattern.unrecognised diff --git a/testing/web-platform/tests/html/canvas/tools/yaml/element/fill-and-stroke-styles.yaml b/testing/web-platform/tests/html/canvas/tools/yaml/element/fill-and-stroke-styles.yaml index 1483cadd4422..d05ae0911bd8 100644 --- a/testing/web-platform/tests/html/canvas/tools/yaml/element/fill-and-stroke-styles.yaml +++ b/testing/web-platform/tests/html/canvas/tools/yaml/element/fill-and-stroke-styles.yaml @@ -1284,6 +1284,60 @@ @assert pixel 98,48 == 0,255,0,255; expected: green +- name: 2d.pattern.transform.identity + testing: + - 2d.pattern.transform + code: | + var canvas2 = document.createElement('canvas'); + canvas2.width = 100; + canvas2.height = 50; + var pattern = ctx.createPattern(canvas2, 'no-repeat'); + pattern.setTransform(new DOMMatrix()); + + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#f00'; + ctx.fillStyle = pattern; + ctx.fillRect(0, 0, 100, 50); + + @assert pixel 1,1 == 0,255,0,255; + @assert pixel 98,1 == 0,255,0,255; + @assert pixel 1,48 == 0,255,0,255; + @assert pixel 98,48 == 0,255,0,255; + expected: green + +- name: 2d.pattern.transform.infinity + testing: + - 2d.pattern.transform + code: | + var canvas2 = document.createElement('canvas'); + canvas2.width = 100; + canvas2.height = 50; + var pattern = ctx.createPattern(canvas2, 'no-repeat'); + pattern.setTransform({a: Infinity}); + + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + ctx.fillStyle = '#f00'; + ctx.fillStyle = pattern; + ctx.fillRect(0, 0, 100, 50); + + @assert pixel 1,1 == 0,255,0,255; + @assert pixel 98,1 == 0,255,0,255; + @assert pixel 1,48 == 0,255,0,255; + @assert pixel 98,48 == 0,255,0,255; + expected: green + +- name: 2d.pattern.transform.invalid + testing: + - 2d.pattern.transform + code: | + var canvas2 = document.createElement('canvas'); + canvas2.width = 100; + canvas2.height = 50; + var pattern = ctx.createPattern(canvas2, 'no-repeat'); + @assert throws TypeError pattern.setTransform({a: 1, m11: 2}); + - name: 2d.pattern.image.undefined testing: - 2d.pattern.IDL