diff options
| author | junov <junov@chromium.org> | 2016-03-14 15:10:19 -0700 |
|---|---|---|
| committer | Commit bot <commit-bot@chromium.org> | 2016-03-14 22:11:22 +0000 |
| commit | 3e81032f06d758c0e79fec2158f1b928f3487036 (patch) | |
| tree | efb98bb393157b469a46ad3f97b64b8c9503a89b | |
| parent | cb3cc25f0064533ad7f1480cc4b0b39675521c61 (diff) | |
| download | chromium_src-3e81032f06d758c0e79fec2158f1b928f3487036.zip chromium_src-3e81032f06d758c0e79fec2158f1b928f3487036.tar.gz chromium_src-3e81032f06d758c0e79fec2158f1b928f3487036.tar.bz2 | |
Make OffscreenCanvasRenderingContext2D renderable on a worker
This change makes 2D contexts renderable on workers. It only
implements the bare minimum interfaces required to draw rectangles
on a worker and bring the results to screen via ImageBitmap transfer.
The new Web APIs that are implemented are:
* OffscreenCanvasRendering2D.fillStyle
* OffscreenCanvasRendering2D.strokeStyle
* OffscreenCanvasRendering2D.fillRect
* OffscreenCanvasRendering2D.strokeRect
* OffscreenCanvasRendering2D.clearRect
* OffscreenCanvas.transferToImageBitmap
BUG=563856, 563832
Review URL: https://codereview.chromium.org/1775153002
Cr-Commit-Position: refs/heads/master@{#381085}
23 files changed, 356 insertions, 37 deletions
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index baf5e5e..bd9efe7 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations @@ -115,6 +115,9 @@ crbug.com/539226 http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-c crbug.com/539226 [ Win ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-redirect-response-handling.html [ Timeout Pass ] crbug.com/539226 [ Win ] http/tests/xmlhttprequest/open-in-body-onload-sync-to-invalid-preflight-handling.html [ Timeout Pass ] +# Expected to fail until OffscreenCanvas can render on the gpu +crbug.com/593514 virtual/gpu/fast/canvas/OffscreenCanvas-strokeRect-in-worker.html [ Failure ] + crbug.com/417782 [ Linux Win ] virtual/rootlayerscrolls/fast/scrolling/fractional-scroll-offset-fixed-position-non-composited.html [ Failure ] crbug.com/492664 [ Linux ] imported/csswg-test/css-writing-modes-3/box-offsets-rel-pos-vlr-005.xht [ Failure ] crbug.com/492664 [ Linux ] imported/csswg-test/css-writing-modes-3/box-offsets-rel-pos-vrl-004.xht [ Failure ] diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-clearRect-in-worker-expected.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-clearRect-in-worker-expected.html new file mode 100644 index 0000000..a2fcc69 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-clearRect-in-worker-expected.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<body> +<canvas id='output' width='100' height='100'></canvas> +<script> +var aCanvas = document.getElementById('output'); +var ctx = aCanvas.getContext('2d'); +ctx.fillStyle = 'green'; +ctx.fillRect(20, 20, 60, 60); +ctx.clearRect(25, 25, 50, 50); +</script> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-clearRect-in-worker.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-clearRect-in-worker.html new file mode 100644 index 0000000..392fcdf --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-clearRect-in-worker.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> +<body> +<canvas id='output' width='100' height='100'></canvas> + +<script id='myWorker' type='text/worker'> +self.onmessage = function(e) { + var aCanvas = new OffscreenCanvas(100, 100); + var ctx = aCanvas.getContext('2d'); + ctx.fillStyle = 'green'; + ctx.fillRect(20, 20, 60, 60); + ctx.fillStyle = 'red'; + ctx.fillRect(25, 25, 50, 50); + // No red should be visible after this + ctx.clearRect(25, 25, 50, 50); + var image = aCanvas.transferToImageBitmap(); + self.postMessage(image, [image]); +}; +</script> + +<script> +if (window.testRunner) { + testRunner.waitUntilDone(); +} +var blob = new Blob([document.getElementById('myWorker').textContent]); +var worker = new Worker(URL.createObjectURL(blob)); +worker.addEventListener('message', msg => { + var outputCtx = document.getElementById('output').getContext('imagebitmap'); + outputCtx.transferImageBitmap(msg.data); + if (window.testRunner) { + testRunner.notifyDone(); + } +}); +worker.postMessage(""); +</script> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-currentColor-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-currentColor-expected.txt new file mode 100644 index 0000000..958372d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-currentColor-expected.txt @@ -0,0 +1,11 @@ +Test that the fill and stroke style attribute yield opaque black when set to 'currentcolor' on an OffscreenCanvasRenderingContext2D + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS ctx.fillStyle is '#000000' +PASS ctx.strokeStyle is '#000000' +PASS successfullyParsed is true + +TEST COMPLETE + diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-currentColor.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-currentColor.html new file mode 100644 index 0000000..b530d522 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-currentColor.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<script src="../../resources/js-test.js"></script> +<script> +description("Test that the fill and stroke style attribute yield opaque black when set to 'currentcolor' on an OffscreenCanvasRenderingContext2D"); + +// Tests onstructor of OffscreenCanvas and length/width change +var aCanvas = new OffscreenCanvas(50, 50); +var ctx = aCanvas.getContext('2d'); +ctx.fillStyle = 'red'; +ctx.fillStyle = 'currentcolor' +shouldBe("ctx.fillStyle", "'#000000'"); + +ctx.strokeStyle = 'red'; +ctx.strokeStyle = 'currentcolor' +shouldBe("ctx.strokeStyle", "'#000000'"); + +</script> diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-fillRect-in-worker-expected.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-fillRect-in-worker-expected.html new file mode 100644 index 0000000..b0b5cd2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-fillRect-in-worker-expected.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> +<body> +<canvas id='output' width='100' height='100' style='background:green'></canvas> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-fillRect-in-worker.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-fillRect-in-worker.html new file mode 100644 index 0000000..08a110f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-fillRect-in-worker.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<body> +<canvas id='output' width='100' height='100' style='background:red'></canvas> + +<script id='myWorker' type='text/worker'> +self.onmessage = function(e) { + var aCanvas = new OffscreenCanvas(100, 100); + var ctx = aCanvas.getContext('2d'); + ctx.fillStyle = 'green'; + ctx.fillRect(0, 0, 100, 100); + var image = aCanvas.transferToImageBitmap(); + self.postMessage(image, [image]); +}; +</script> + +<script> +if (window.testRunner) { + testRunner.waitUntilDone(); +} +var blob = new Blob([document.getElementById('myWorker').textContent]); +var worker = new Worker(URL.createObjectURL(blob)); +worker.addEventListener('message', msg => { + var outputCtx = document.getElementById('output').getContext('imagebitmap'); + outputCtx.transferImageBitmap(msg.data); + if (window.testRunner) { + testRunner.notifyDone(); + } +}); +worker.postMessage(""); +</script> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-strokeRect-in-worker-expected.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-strokeRect-in-worker-expected.html new file mode 100644 index 0000000..120af09 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-strokeRect-in-worker-expected.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<body> +<canvas id='output' width='100' height='100'></canvas> +<script> +var aCanvas = document.getElementById('output'); +var ctx = aCanvas.getContext('2d'); +ctx.strokeStyle = 'green'; +ctx.strokeRect(25, 25, 50, 50); +</script> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-strokeRect-in-worker.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-strokeRect-in-worker.html new file mode 100644 index 0000000..aa8324af --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-strokeRect-in-worker.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<body> +<canvas id='output' width='100' height='100'></canvas> + +<script id='myWorker' type='text/worker'> +self.onmessage = function(e) { + var aCanvas = new OffscreenCanvas(100, 100); + var ctx = aCanvas.getContext('2d'); + ctx.strokeStyle = 'green'; + ctx.strokeRect(25, 25, 50, 50); + var image = aCanvas.transferToImageBitmap(); + self.postMessage(image, [image]); +}; +</script> + +<script> +if (window.testRunner) { + testRunner.waitUntilDone(); +} +var blob = new Blob([document.getElementById('myWorker').textContent]); +var worker = new Worker(URL.createObjectURL(blob)); +worker.addEventListener('message', msg => { + var outputCtx = document.getElementById('output').getContext('imagebitmap'); + outputCtx.transferImageBitmap(msg.data); + if (window.testRunner) { + testRunner.notifyDone(); + } +}); +worker.postMessage(""); +</script> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-transferToImageBitmap-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-transferToImageBitmap-expected.txt new file mode 100644 index 0000000..4b61f00 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-transferToImageBitmap-expected.txt @@ -0,0 +1,16 @@ +PASS aCanvas.transferToImageBitmap() threw exception InvalidStateError: Failed to execute 'transferToImageBitmap' on 'OffscreenCanvas': Cannot transfer an ImageBitmap from an OffscreenCanvas with no context. +PASS image.width is 60 +PASS image.height is 40 +PASS ctx.lineWidth is 5 +PASS imgData[0] is 255 +PASS imgData[1] is 0 +PASS imgData[2] is 0 +PASS imgData[3] is 255 +PASS imgData[0] is 0 +PASS imgData[1] is 0 +PASS imgData[2] is 0 +PASS imgData[3] is 0 +PASS successfullyParsed is true + +TEST COMPLETE + diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-transferToImageBitmap.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-transferToImageBitmap.html new file mode 100644 index 0000000..c0bc6ff --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-transferToImageBitmap.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<script src="../../resources/js-test.js"></script> +<script> +var aCanvas = new OffscreenCanvas(60, 40); + +// TransferToImageBitmap on an OffscreenCanvas with no context +shouldThrow("aCanvas.transferToImageBitmap()"); +ctx = aCanvas.getContext('2d'); + +// Verify ImageBitmap is correctly sized +var image = aCanvas.transferToImageBitmap(); +shouldBe("image.width", "60"); +shouldBe("image.height", "40"); + +// Verify state is preserved through transferToImageBitmap() +ctx.lineWidth = 5; +aCanvas.transferToImageBitmap(); +shouldBe("ctx.lineWidth", "5"); + +// Verify backing is reset through transferToImageBitmap() +ctx.fillStyle = '#f00'; +ctx.fillRect(0, 0, aCanvas.width, aCanvas.height); +var firstImage = aCanvas.transferToImageBitmap(); +var secondImage = aCanvas.transferToImageBitmap(); +var testCanvas = document.createElement('canvas'); +var testCtx = testCanvas.getContext('2d'); +testCtx.drawImage(firstImage, 0, 0); +var imgData = testCtx.getImageData(0, 0, 1, 1).data; +shouldBe("imgData[0]", "255"); +shouldBe("imgData[1]", "0"); +shouldBe("imgData[2]", "0"); +shouldBe("imgData[3]", "255"); +testCtx.clearRect(0, 0, testCanvas.width, testCanvas.height); +testCtx.drawImage(secondImage, 0, 0); +imgData = testCtx.getImageData(0, 0, 1, 1).data; +shouldBe("imgData[0]", "0"); +shouldBe("imgData[1]", "0"); +shouldBe("imgData[2]", "0"); +shouldBe("imgData[3]", "0"); + +</script> diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 7890480..f0ed794 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt @@ -477,20 +477,28 @@ interface OffscreenCanvas getter width method constructor method getContext + method transferToImageBitmap setter height setter width interface OffscreenCanvasRenderingContext2D + getter fillStyle getter offscreenCanvas + getter strokeStyle method arc method arcTo method bezierCurveTo + method clearRect method closePath method constructor method ellipse + method fillRect method lineTo method moveTo method quadraticCurveTo method rect + method strokeRect + setter fillStyle + setter strokeStyle interface PerformanceObserverEntryList method constructor method getEntries diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 6206ef4..ecf1b96 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt @@ -495,21 +495,29 @@ Starting worker: resources/global-interface-listing.js [Worker] getter width [Worker] method constructor [Worker] method getContext +[Worker] method transferToImageBitmap [Worker] setter height [Worker] setter width [Worker] interface OffscreenCanvasRenderingContext2D [Worker] attribute @@toStringTag +[Worker] getter fillStyle [Worker] getter offscreenCanvas +[Worker] getter strokeStyle [Worker] method arc [Worker] method arcTo [Worker] method bezierCurveTo +[Worker] method clearRect [Worker] method closePath [Worker] method constructor [Worker] method ellipse +[Worker] method fillRect [Worker] method lineTo [Worker] method moveTo [Worker] method quadraticCurveTo [Worker] method rect +[Worker] method strokeRect +[Worker] setter fillStyle +[Worker] setter strokeStyle [Worker] interface PerformanceObserverEntryList [Worker] attribute @@toStringTag [Worker] method constructor diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 3b93cdb..bf639ce 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt @@ -3996,21 +3996,29 @@ interface OffscreenCanvas getter width method constructor method getContext + method transferToImageBitmap setter height setter width interface OffscreenCanvasRenderingContext2D attribute @@toStringTag + getter fillStyle getter offscreenCanvas + getter strokeStyle method arc method arcTo method bezierCurveTo + method clearRect method closePath method constructor method ellipse + method fillRect method lineTo method moveTo method quadraticCurveTo method rect + method strokeRect + setter fillStyle + setter strokeStyle interface Option method constructor interface OscillatorNode : AudioSourceNode diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt index 6c706db..55ec6ed 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt @@ -482,21 +482,29 @@ Starting worker: resources/global-interface-listing.js [Worker] getter width [Worker] method constructor [Worker] method getContext +[Worker] method transferToImageBitmap [Worker] setter height [Worker] setter width [Worker] interface OffscreenCanvasRenderingContext2D [Worker] attribute @@toStringTag +[Worker] getter fillStyle [Worker] getter offscreenCanvas +[Worker] getter strokeStyle [Worker] method arc [Worker] method arcTo [Worker] method bezierCurveTo +[Worker] method clearRect [Worker] method closePath [Worker] method constructor [Worker] method ellipse +[Worker] method fillRect [Worker] method lineTo [Worker] method moveTo [Worker] method quadraticCurveTo [Worker] method rect +[Worker] method strokeRect +[Worker] setter fillStyle +[Worker] setter strokeStyle [Worker] interface PerformanceObserverEntryList [Worker] attribute @@toStringTag [Worker] method constructor diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp index ac378f1..d7f716a 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasStyle.cpp @@ -69,7 +69,7 @@ bool parseColorOrCurrentColor(Color& parsedColor, const String& colorString, HTM case ParsedSystemColor: return true; case ParsedCurrentColor: - parsedColor = currentColor(canvas); + parsedColor = canvas ? currentColor(canvas) : Color::black; return true; case ParseFailed: return false; diff --git a/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.cpp b/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.cpp index df10393..d63ae11 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.cpp +++ b/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.cpp @@ -4,6 +4,10 @@ #include "modules/offscreencanvas/OffscreenCanvas.h" +#include "core/dom/ExceptionCode.h" +#if !ENABLE(OILPAN) +#include "core/frame/ImageBitmap.h" // So ~RefPtr can call unref() +#endif #include "core/html/canvas/CanvasContextCreationAttributes.h" #include "modules/offscreencanvas/OffscreenCanvasRenderingContext.h" #include "modules/offscreencanvas/OffscreenCanvasRenderingContextFactory.h" @@ -12,6 +16,13 @@ namespace blink { +OffscreenCanvas::OffscreenCanvas(const IntSize& size) + : m_size(size) +{ } + +OffscreenCanvas::~OffscreenCanvas() +{ } + OffscreenCanvas* OffscreenCanvas::create(unsigned width, unsigned height) { return new OffscreenCanvas(IntSize(clampTo<int>(width), clampTo<int>(height))); @@ -27,11 +38,6 @@ void OffscreenCanvas::setHeight(unsigned height) m_size.setHeight(clampTo<int>(height)); } -OffscreenCanvas::OffscreenCanvas(const IntSize& size) - : m_size(size) -{ -} - OffscreenCanvasRenderingContext2D* OffscreenCanvas::getContext(const String& id, const CanvasContextCreationAttributes& attributes) { OffscreenCanvasRenderingContext::ContextType contextType = OffscreenCanvasRenderingContext::contextTypeFromId(id); @@ -59,6 +65,20 @@ OffscreenCanvasRenderingContext2D* OffscreenCanvas::getContext(const String& id, return static_cast<OffscreenCanvasRenderingContext2D*>(m_context.get()); } +PassRefPtrWillBeRawPtr<ImageBitmap> OffscreenCanvas::transferToImageBitmap(ExceptionState& exceptionState) +{ + if (!m_context) { + exceptionState.throwDOMException(InvalidStateError, "Cannot transfer an ImageBitmap from an OffscreenCanvas with no context"); + return nullptr; + } + RefPtrWillBeRawPtr<ImageBitmap> image = m_context->transferToImageBitmap(exceptionState); + if (!image) { + // Undocumented exception (not in spec) + exceptionState.throwDOMException(V8GeneralError, "Out of memory"); + } + return image.release(); +} + OffscreenCanvasRenderingContext2D* OffscreenCanvas::renderingContext() const { // TODO: When there're more than one context type implemented in the future, diff --git a/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.h b/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.h index abfc419..0e2e957 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.h +++ b/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.h @@ -15,6 +15,7 @@ namespace blink { class CanvasContextCreationAttributes; +class ImageBitmap; class OffscreenCanvasRenderingContext; class OffscreenCanvasRenderingContext2D; class OffscreenCanvasRenderingContextFactory; @@ -23,15 +24,19 @@ class MODULES_EXPORT OffscreenCanvas final : public GarbageCollectedFinalized<Of DEFINE_WRAPPERTYPEINFO(); public: static OffscreenCanvas* create(unsigned width, unsigned height); - ~OffscreenCanvas() {} + ~OffscreenCanvas(); - IntSize size() const { return m_size; } + // IDL attributes unsigned width() const { return m_size.width(); } unsigned height() const { return m_size.height(); } void setWidth(unsigned); void setHeight(unsigned); + // API Methods OffscreenCanvasRenderingContext2D* getContext(const String&, const CanvasContextCreationAttributes&); + PassRefPtrWillBeRawPtr<ImageBitmap> transferToImageBitmap(ExceptionState&); + + IntSize size() const { return m_size; } OffscreenCanvasRenderingContext2D* renderingContext() const; static void registerRenderingContextFactory(PassOwnPtr<OffscreenCanvasRenderingContextFactory>); diff --git a/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.idl b/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.idl index b1436b0..91a95a4 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.idl +++ b/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvas.idl @@ -15,5 +15,6 @@ typedef OffscreenCanvasRenderingContext2D OffscreenRenderingContext; [EnforceRange] attribute unsigned long width; [EnforceRange] attribute unsigned long height; - OffscreenRenderingContext? getContext(DOMString contextId, optional CanvasContextCreationAttributes attributes); + OffscreenRenderingContext? getContext(DOMString contextId, optional CanvasContextCreationAttributes attributes); + [RaisesException] ImageBitmap transferToImageBitmap(); }; diff --git a/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvasRenderingContext.h b/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvasRenderingContext.h index 341baa7..ca3f222 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvasRenderingContext.h +++ b/third_party/WebKit/Source/modules/offscreencanvas/OffscreenCanvasRenderingContext.h @@ -10,6 +10,8 @@ namespace blink { +class ImageBitmap; + class MODULES_EXPORT OffscreenCanvasRenderingContext : public GarbageCollectedFinalized<OffscreenCanvasRenderingContext>, public ScriptWrappable { WTF_MAKE_NONCOPYABLE(OffscreenCanvasRenderingContext); public: @@ -24,6 +26,7 @@ public: OffscreenCanvas* getOffscreenCanvas() const { return m_offscreenCanvas; } virtual ContextType getContextType() const = 0; + virtual PassRefPtrWillBeRawPtr<ImageBitmap> transferToImageBitmap(ExceptionState&) = 0; virtual bool is2d() const { return false; } diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp index 769e0a2..9b0b81c 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp @@ -5,7 +5,10 @@ #include "modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h" #include "bindings/modules/v8/UnionTypesModules.h" +#include "core/frame/ImageBitmap.h" #include "platform/NotImplemented.h" +#include "platform/graphics/ImageBuffer.h" +#include "platform/graphics/StaticBitmapImage.h" #include "wtf/Assertions.h" #define UNIMPLEMENTED ASSERT_NOT_REACHED @@ -31,13 +34,12 @@ DEFINE_TRACE(OffscreenCanvasRenderingContext2D) // BaseRenderingContext2D implementation bool OffscreenCanvasRenderingContext2D::originClean() const { - notImplemented(); - return true; + return m_originClean; } void OffscreenCanvasRenderingContext2D::setOriginTainted() { - notImplemented(); + m_originClean = false; } bool OffscreenCanvasRenderingContext2D::wouldTaintOrigin(CanvasImageSource* source) @@ -48,80 +50,101 @@ bool OffscreenCanvasRenderingContext2D::wouldTaintOrigin(CanvasImageSource* sour int OffscreenCanvasRenderingContext2D::width() const { - return getOffscreenCanvas()->height(); + return getOffscreenCanvas()->width(); } int OffscreenCanvasRenderingContext2D::height() const { - return getOffscreenCanvas()->width(); + return getOffscreenCanvas()->height(); } bool OffscreenCanvasRenderingContext2D::hasImageBuffer() const { - notImplemented(); - return false; + return !!m_imageBuffer; } ImageBuffer* OffscreenCanvasRenderingContext2D::imageBuffer() const { - notImplemented(); - return nullptr; + if (!m_imageBuffer) { + // TODO: crbug.com/593514 Add support for GPU rendering + OffscreenCanvasRenderingContext2D* nonConstThis = const_cast<OffscreenCanvasRenderingContext2D*>(this); + nonConstThis->m_imageBuffer = ImageBuffer::create(IntSize(width(), height()), m_hasAlpha ? NonOpaque : Opaque, InitializeImagePixels); + // TODO: crbug.com/593349 Restore matrix and clip state on the new ImageBuffer. + } + + return m_imageBuffer.get(); } -bool OffscreenCanvasRenderingContext2D::parseColorOrCurrentColor(Color&, const String& colorString) const +PassRefPtrWillBeRawPtr<ImageBitmap> OffscreenCanvasRenderingContext2D::transferToImageBitmap(ExceptionState& exceptionState) { - notImplemented(); - return false; + if (!imageBuffer()) + return nullptr; + // TODO: crbug.com/593514 Add support for GPU rendering + RefPtr<SkImage> skImage = m_imageBuffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown); + RefPtr<StaticBitmapImage> image = StaticBitmapImage::create(skImage.release()); + m_imageBuffer.clear(); // "Transfer" means no retained buffer + return ImageBitmap::create(image.release()); +} + +bool OffscreenCanvasRenderingContext2D::parseColorOrCurrentColor(Color& color, const String& colorString) const +{ + return ::blink::parseColorOrCurrentColor(color, colorString, nullptr); } SkCanvas* OffscreenCanvasRenderingContext2D::drawingCanvas() const { - notImplemented(); - return nullptr; + ImageBuffer* buffer = imageBuffer(); + if (!buffer) + return nullptr; + return imageBuffer()->canvas(); } SkCanvas* OffscreenCanvasRenderingContext2D::existingDrawingCanvas() const { - notImplemented(); - return nullptr; + if (!m_imageBuffer) + return nullptr; + return m_imageBuffer->canvas(); } void OffscreenCanvasRenderingContext2D::disableDeferral(DisableDeferralReason) -{ - notImplemented(); -} +{ } AffineTransform OffscreenCanvasRenderingContext2D::baseTransform() const { - notImplemented(); - return 0; + if (!m_imageBuffer) + return AffineTransform(); // identity + return m_imageBuffer->baseTransform(); } void OffscreenCanvasRenderingContext2D::didDraw(const SkIRect& dirtyRect) -{ - notImplemented(); -} +{ } bool OffscreenCanvasRenderingContext2D::stateHasFilter() { - notImplemented(); + // TODO: crbug.com/593838 make hasFilter accept nullptr + // return state().hasFilter(nullptr, nullptr, IntSize(width(), height()), this); return false; } SkImageFilter* OffscreenCanvasRenderingContext2D::stateGetFilter() { - notImplemented(); + // TODO: make getFilter accept nullptr + // return state().getFilter(nullptr, nullptr, IntSize(width(), height()), this); return nullptr; } void OffscreenCanvasRenderingContext2D::validateStateStack() { - notImplemented(); +#if ENABLE(ASSERT) + SkCanvas* skCanvas = existingDrawingCanvas(); + if (skCanvas) { + ASSERT(static_cast<size_t>(skCanvas->getSaveCount()) == m_stateStack.size()); + } +#endif } bool OffscreenCanvasRenderingContext2D::isContextLost() const { - notImplemented(); return false; } diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h index defa199..0eb2cf9 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h @@ -67,12 +67,16 @@ public: bool hasAlpha() const override { return m_hasAlpha; } bool isContextLost() const override; + PassRefPtrWillBeRawPtr<ImageBitmap> transferToImageBitmap(ExceptionState&) final; + protected: OffscreenCanvasRenderingContext2D(OffscreenCanvas*, const CanvasContextCreationAttributes& attrs); DECLARE_VIRTUAL_TRACE(); private: bool m_hasAlpha; + bool m_originClean = true; + OwnPtr<ImageBuffer> m_imageBuffer; }; } // namespace blink diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl index 88cee00..29a3d06 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl @@ -11,6 +11,15 @@ ] interface OffscreenCanvasRenderingContext2D { // back-reference to the canvas [ImplementedAs=getOffscreenCanvas] readonly attribute OffscreenCanvas offscreenCanvas; + + // colors and styles (see also the CanvasDrawingStyles interface) + attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black) + attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black) + + //CanvasRect interface + void clearRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height); + void fillRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height); + void strokeRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height); }; OffscreenCanvasRenderingContext2D implements CanvasPathMethods; |
