Make CanvasRenderingContext2D use WebIDL unions / Variants for createPattern and...
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Nov 2016 01:03:48 +0000 (01:03 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Nov 2016 01:03:48 +0000 (01:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=165086

Reviewed by Darin Adler.

* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::size):
Add overloads of size for each type of CanvasSource.
(WebCore::CanvasRenderingContext2D::drawImage):
(WebCore::CanvasRenderingContext2D::createPattern):
* html/canvas/CanvasRenderingContext2D.h:
* html/canvas/CanvasRenderingContext2D.idl:
Use variants to reduce code duplication and match spec language in drawImage and createPattern.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209048 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/html/canvas/CanvasRenderingContext2D.h
Source/WebCore/html/canvas/CanvasRenderingContext2D.idl

index 8c1a56c..01f4f8d 100644 (file)
@@ -1,3 +1,19 @@
+2016-11-27  Sam Weinig  <sam@webkit.org>
+
+        Make CanvasRenderingContext2D use WebIDL unions / Variants for createPattern and drawImage
+        https://bugs.webkit.org/show_bug.cgi?id=165086
+
+        Reviewed by Darin Adler.
+
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::size):
+        Add overloads of size for each type of CanvasSource.
+        (WebCore::CanvasRenderingContext2D::drawImage):
+        (WebCore::CanvasRenderingContext2D::createPattern):
+        * html/canvas/CanvasRenderingContext2D.h:
+        * html/canvas/CanvasRenderingContext2D.idl:
+        Use variants to reduce code duplication and match spec language in drawImage and createPattern.
+
 2016-11-28  Beth Dakin  <bdakin@apple.com>
 
         Blacklist Netflix for TouchBar support
index 7113527..2040742 100644 (file)
@@ -1318,7 +1318,7 @@ enum ImageSizeType {
     ImageSizeBeforeDevicePixelRatio
 };
 
-static LayoutSize size(HTMLImageElement& imageElement, ImageSizeType sizeType)
+static LayoutSize size(HTMLImageElement& imageElement, ImageSizeType sizeType = ImageSizeBeforeDevicePixelRatio)
 {
     LayoutSize size;
     if (CachedImage* cachedImage = imageElement.cachedImage()) {
@@ -1330,6 +1330,11 @@ static LayoutSize size(HTMLImageElement& imageElement, ImageSizeType sizeType)
     return size;
 }
 
+static FloatSize size(HTMLCanvasElement& canvasElement)
+{
+    return FloatSize(canvasElement.size());
+}
+
 #if ENABLE(VIDEO)
 static FloatSize size(HTMLVideoElement& video)
 {
@@ -1347,21 +1352,38 @@ static inline FloatRect normalizeRect(const FloatRect& rect)
         std::max(rect.height(), -rect.height()));
 }
 
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLImageElement& imageElement, float x, float y)
+ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float dx, float dy)
 {
-    LayoutSize destRectSize = size(imageElement, ImageSizeAfterDevicePixelRatio);
-    return drawImage(imageElement, x, y, destRectSize.width(), destRectSize.height());
+    return WTF::switchOn(image,
+        [&] (RefPtr<HTMLImageElement>& imageElement) -> ExceptionOr<void> {
+            LayoutSize destRectSize = size(*imageElement, ImageSizeAfterDevicePixelRatio);
+            LayoutSize sourceRectSize = size(*imageElement, ImageSizeBeforeDevicePixelRatio);
+            return this->drawImage(*imageElement, FloatRect { 0, 0, sourceRectSize.width(), sourceRectSize.height() }, FloatRect { dx, dy, destRectSize.width(), destRectSize.height() });
+        },
+        [&] (auto& element) -> ExceptionOr<void> {
+            FloatSize elementSize = size(*element);
+            return this->drawImage(*element, FloatRect { 0, 0, elementSize.width(), elementSize.height() }, FloatRect { dx, dy, elementSize.width(), elementSize.height() });
+        }
+    );
 }
 
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLImageElement& imageElement, float x, float y, float width, float height)
+ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float dx, float dy, float dw, float dh)
 {
-    LayoutSize sourceRectSize = size(imageElement, ImageSizeBeforeDevicePixelRatio);
-    return drawImage(imageElement, FloatRect { 0, 0, sourceRectSize.width(), sourceRectSize.height() }, FloatRect { x, y, width, height });
+    return WTF::switchOn(image,
+        [&] (auto& element) -> ExceptionOr<void> {
+            FloatSize elementSize = size(*element);
+            return this->drawImage(*element, FloatRect { 0, 0, elementSize.width(), elementSize.height() }, FloatRect { dx, dy, dw, dh });
+        }
+    );
 }
 
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLImageElement& imageElement, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
+ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
 {
-    return drawImage(imageElement, FloatRect { sx, sy, sw, sh }, FloatRect { dx, dy, dw, dh });
+    return WTF::switchOn(image,
+        [&] (auto& element) -> ExceptionOr<void> {
+            return this->drawImage(*element, FloatRect { sx, sy, sw, sh }, FloatRect { dx, dy, dw, dh });
+        }
+    );
 }
 
 ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLImageElement& imageElement, const FloatRect& srcRect, const FloatRect& dstRect)
@@ -1446,21 +1468,6 @@ ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLImageElement& imageEle
     return { };
 }
 
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLCanvasElement& sourceCanvas, float x, float y)
-{
-    return drawImage(sourceCanvas, 0, 0, sourceCanvas.width(), sourceCanvas.height(), x, y, sourceCanvas.width(), sourceCanvas.height());
-}
-
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLCanvasElement& sourceCanvas, float x, float y, float width, float height)
-{
-    return drawImage(sourceCanvas, FloatRect(0, 0, sourceCanvas.width(), sourceCanvas.height()), FloatRect { x, y, width, height });
-}
-
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLCanvasElement& sourceCanvas, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
-{
-    return drawImage(sourceCanvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh));
-}
-
 ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLCanvasElement& sourceCanvas, const FloatRect& srcRect, const FloatRect& dstRect)
 {
     FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas.size());
@@ -1518,23 +1525,6 @@ ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLCanvasElement& sourceC
 
 #if ENABLE(VIDEO)
 
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLVideoElement& video, float x, float y)
-{
-    FloatSize videoSize = size(video);
-    return drawImage(video, x, y, videoSize.width(), videoSize.height());
-}
-
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLVideoElement& video, float x, float y, float width, float height)
-{
-    FloatSize videoSize = size(video);
-    return drawImage(video, FloatRect { 0, 0, videoSize.width(), videoSize.height() }, FloatRect { x, y, width, height });
-}
-
-ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLVideoElement& video, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
-{
-    return drawImage(video, FloatRect { sx, sy, sw, sh }, FloatRect { dx, dy, dw, dh });
-}
-
 ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLVideoElement& video, const FloatRect& srcRect, const FloatRect& dstRect)
 {
     if (video.readyState() == HTMLMediaElement::HAVE_NOTHING || video.readyState() == HTMLMediaElement::HAVE_METADATA)
@@ -1748,12 +1738,19 @@ ExceptionOr<Ref<CanvasGradient>> CanvasRenderingContext2D::createRadialGradient(
     return WTFMove(gradient);
 }
 
-ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLImageElement& imageElement, const String& repetitionType)
+ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(CanvasImageSource&& image, const String& repetition)
 {
     bool repeatX, repeatY;
-    if (!CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY))
+    if (!CanvasPattern::parseRepetitionType(repetition, repeatX, repeatY))
         return Exception { SYNTAX_ERR };
 
+    return WTF::switchOn(image,
+        [&](auto& element) -> ExceptionOr<RefPtr<CanvasPattern>> { return this->createPattern(*element, repeatX, repeatY); }
+    );
+}
+
+ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLImageElement& imageElement, bool repeatX, bool repeatY)
+{
     auto* cachedImage = imageElement.cachedImage();
 
     // If the image loading hasn't started or the image is not complete, it is not fully decodable.
@@ -1777,29 +1774,21 @@ ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLI
     return RefPtr<CanvasPattern> { CanvasPattern::create(*cachedImage->imageForRenderer(imageElement.renderer()), repeatX, repeatY, originClean) };
 }
 
-ExceptionOr<Ref<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLCanvasElement& canvas, const String& repetitionType)
+ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLCanvasElement& canvas, bool repeatX, bool repeatY)
 {
     if (!canvas.width() || !canvas.height() || !canvas.buffer())
         return Exception { INVALID_STATE_ERR };
 
-    bool repeatX, repeatY;
-    if (!CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY))
-        return Exception { SYNTAX_ERR };
-
-    return CanvasPattern::create(*canvas.copiedImage(), repeatX, repeatY, canvas.originClean());
+    return RefPtr<CanvasPattern> { CanvasPattern::create(*canvas.copiedImage(), repeatX, repeatY, canvas.originClean()) };
 }
     
 #if ENABLE(VIDEO)
 
-ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLVideoElement& videoElement, const String& repetitionType)
+ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLVideoElement& videoElement, bool repeatX, bool repeatY)
 {
     if (videoElement.readyState() < HTMLMediaElement::HAVE_CURRENT_DATA)
         return nullptr;
     
-    bool repeatX, repeatY;
-    if (!CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY))
-        return Exception { SYNTAX_ERR };
-
     checkOrigin(&videoElement);
     bool originClean = canvas().originClean();
 
index 2a87f26..54be9d0 100644 (file)
@@ -55,6 +55,12 @@ class HTMLVideoElement;
 class ImageData;
 class TextMetrics;
 
+#if ENABLE(VIDEO)
+using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLVideoElement>, RefPtr<HTMLCanvasElement>>;
+#else
+using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>;
+#endif
+
 class CanvasRenderingContext2D final : public CanvasRenderingContext, public CanvasPath {
 public:
     CanvasRenderingContext2D(HTMLCanvasElement&, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode);
@@ -156,21 +162,9 @@ public:
 
     void clearShadow();
 
-    ExceptionOr<void> drawImage(HTMLImageElement&, float x, float y);
-    ExceptionOr<void> drawImage(HTMLImageElement&, float x, float y, float width, float height);
-    ExceptionOr<void> drawImage(HTMLImageElement&, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh);
-    ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect);
-    ExceptionOr<void> drawImage(HTMLCanvasElement&, float x, float y);
-    ExceptionOr<void> drawImage(HTMLCanvasElement&, float x, float y, float width, float height);
-    ExceptionOr<void> drawImage(HTMLCanvasElement&, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh);
-    ExceptionOr<void> drawImage(HTMLCanvasElement&, const FloatRect& srcRect, const FloatRect& dstRect);
-    ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&);
-#if ENABLE(VIDEO)
-    ExceptionOr<void> drawImage(HTMLVideoElement&, float x, float y);
-    ExceptionOr<void> drawImage(HTMLVideoElement&, float x, float y, float width, float height);
-    ExceptionOr<void> drawImage(HTMLVideoElement&, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh);
-    ExceptionOr<void> drawImage(HTMLVideoElement&, const FloatRect& srcRect, const FloatRect& dstRect);
-#endif
+    ExceptionOr<void> drawImage(CanvasImageSource&&, float dx, float dy);
+    ExceptionOr<void> drawImage(CanvasImageSource&&, float dx, float dy, float dw, float dh);
+    ExceptionOr<void> drawImage(CanvasImageSource&&, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh);
 
     void drawImageFromRect(HTMLImageElement&, float sx = 0, float sy = 0, float sw = 0, float sh = 0, float dx = 0, float dy = 0, float dw = 0, float dh = 0, const String& compositeOperation = emptyString());
 
@@ -180,11 +174,7 @@ public:
 
     ExceptionOr<Ref<CanvasGradient>> createLinearGradient(float x0, float y0, float x1, float y1);
     ExceptionOr<Ref<CanvasGradient>> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
-    ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLImageElement&, const String& repetitionType);
-    ExceptionOr<Ref<CanvasPattern>> createPattern(HTMLCanvasElement&, const String& repetitionType);
-#if ENABLE(VIDEO)
-    ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLVideoElement&, const String& repetitionType);
-#endif
+    ExceptionOr<RefPtr<CanvasPattern>> createPattern(CanvasImageSource&&, const String& repetition);
 
     ExceptionOr<RefPtr<ImageData>> createImageData(ImageData*) const;
     ExceptionOr<RefPtr<ImageData>> createImageData(float width, float height) const;
@@ -331,6 +321,19 @@ private:
     void applyStrokePattern();
     void applyFillPattern();
 
+    ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLImageElement&, bool repeatX, bool repeatY);
+    ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLCanvasElement&, bool repeatX, bool repeatY);
+#if ENABLE(VIDEO)
+    ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLVideoElement&, bool repeatX, bool repeatY);
+#endif
+
+    ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect);
+    ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&);
+    ExceptionOr<void> drawImage(HTMLCanvasElement&, const FloatRect& srcRect, const FloatRect& dstRect);
+#if ENABLE(VIDEO)
+    ExceptionOr<void> drawImage(HTMLVideoElement&, const FloatRect& srcRect, const FloatRect& dstRect);
+#endif
+
     void drawTextInternal(const String& text, float x, float y, bool fill, std::optional<float> maxWidth = std::nullopt);
 
     // The relationship between FontCascade and CanvasRenderingContext2D::FontProxy must hold certain invariants.
index c75100b..498828d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Apple Inc.  All rights reserved.
+ * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 enum ImageSmoothingQuality { "low", "medium", "high" };
 enum CanvasWindingRule { "nonzero", "evenodd" };
 
+// FIXME: This should include SVGImageElement and ImageBitmap.
+#if defined(ENABLE_VIDEO) && ENABLE_VIDEO
+typedef (HTMLImageElement or HTMLVideoElement or HTMLCanvasElement) CanvasImageSource;
+#else
+typedef (HTMLImageElement or HTMLCanvasElement) CanvasImageSource;
+#endif
+
 [
     CustomIsReachable,
     JSGenerateToJSObject,
@@ -53,9 +60,6 @@ enum CanvasWindingRule { "nonzero", "evenodd" };
 
     attribute DOMString globalCompositeOperation;
 
-    [MayThrowException] CanvasGradient createLinearGradient(float x0, float y0, float x1, float y1);
-    [MayThrowException] CanvasGradient createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
-
     attribute unrestricted float lineWidth;
     attribute DOMString lineCap;
     attribute DOMString lineJoin;
@@ -132,15 +136,12 @@ enum CanvasWindingRule { "nonzero", "evenodd" };
 
     void strokeRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height);
 
-    [MayThrowException] void drawImage(HTMLImageElement image, unrestricted float x, unrestricted float y);
-    [MayThrowException] void drawImage(HTMLImageElement image, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height);
-    [MayThrowException] void drawImage(HTMLImageElement image, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh);
-    [MayThrowException] void drawImage(HTMLCanvasElement canvas, unrestricted float x, unrestricted float y);
-    [MayThrowException] void drawImage(HTMLCanvasElement canvas, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height);
-    [MayThrowException] void drawImage(HTMLCanvasElement canvas, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh);
-    [Conditional=VIDEO, MayThrowException] void drawImage(HTMLVideoElement video, unrestricted float x, unrestricted float y);
-    [Conditional=VIDEO, MayThrowException] void drawImage(HTMLVideoElement video, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height);
-    [Conditional=VIDEO, MayThrowException] void drawImage(HTMLVideoElement video, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh);
+    // FIXME: This should move to the CanvasDrawImage interface.
+    // FIXME: All the unrestricted float arguments below should be unrestricted doubles.
+    [MayThrowException] void drawImage(CanvasImageSource image, unrestricted float x, unrestricted float y);
+    [MayThrowException] void drawImage(CanvasImageSource image, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height);
+    [MayThrowException] void drawImage(CanvasImageSource image, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh);
+
 
     void drawImageFromRect(HTMLImageElement image,
         optional unrestricted float sx = 0, optional unrestricted float sy = 0, optional unrestricted float sw = 0, optional unrestricted float sh = 0,
@@ -162,14 +163,14 @@ enum CanvasWindingRule { "nonzero", "evenodd" };
     void webkitPutImageDataHD(ImageData imagedata, float dx, float dy);
     void webkitPutImageDataHD(ImageData imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight);
 
-    [MayThrowException] CanvasPattern createPattern(HTMLCanvasElement canvas, [TreatNullAs=EmptyString] DOMString repetitionType);
-    [MayThrowException] CanvasPattern createPattern(HTMLImageElement image, [TreatNullAs=EmptyString] DOMString repetitionType);
-    [Conditional=VIDEO, MayThrowException] CanvasPattern? createPattern(HTMLVideoElement video, [TreatNullAs=EmptyString] DOMString repetitionType);
     [MayThrowException] ImageData createImageData(ImageData? imagedata);
     [MayThrowException] ImageData createImageData(float sw, float sh);
 
     [Custom] attribute custom strokeStyle;
     [Custom] attribute custom fillStyle;
+    [MayThrowException] CanvasGradient createLinearGradient(float x0, float y0, float x1, float y1);
+    [MayThrowException] CanvasGradient createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
+    [MayThrowException] CanvasPattern? createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition);
 
     // pixel manipulation
     [MayThrowException] ImageData getImageData(float sx, float sy, float sw, float sh);