-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support CanvasRenderingContext2D.filter #3793
Support CanvasRenderingContext2D.filter #3793
Conversation
EWS run on previous version of this PR (hash a8c57ff) |
a8c57ff
to
a4e5558
Compare
EWS run on previous version of this PR (hash a4e5558) |
a4e5558
to
ee56e3d
Compare
EWS run on previous version of this PR (hash ee56e3d) |
ee56e3d
to
e874780
Compare
EWS run on previous version of this PR (hash e874780) |
e874780
to
7a2a1cc
Compare
EWS run on previous version of this PR (hash 7a2a1cc) |
7a2a1cc
to
9b0fc35
Compare
EWS run on previous version of this PR (hash 9b0fc35) |
c668981
to
22e09d3
Compare
EWS run on previous version of this PR (hash 22e09d3) |
22e09d3
to
0944eb5
Compare
EWS run on current version of this PR (hash 0944eb5) |
https://bugs.webkit.org/show_bug.cgi?id=198416 rdar://51303686 Reviewed by Simon Fraser. This implements the canvas filter API. According to the specs, the filter will be defined as a string very similar to the CSS filter definition. An SVG filter can be accessed via a URL like this `filter : url(#id);`. To implement this feature without many changes in the CanvasRenderingContext2D code, the new class CanvasFilterTargetSwitcher will be added. In its constructor we are going to switch the rendering context to a source ImageBuffer. The next draw commands will be drawn to this ImageBuffer. In its destructor, the filter will be applied to the source ImageBuffer and the result will be composited back to the original context. Specs link: https://html.spec.whatwg.org/multipage/canvas.html#canvasfilters * LayoutTests/fast/canvas/canvas-filter-basics-expected.txt: Added. * LayoutTests/fast/canvas/canvas-filter-basics.html: Added. * LayoutTests/fast/canvas/canvas-filter-bounding-rect-expected.html: Added. * LayoutTests/fast/canvas/canvas-filter-bounding-rect.html: Added. * LayoutTests/fast/canvas/canvas-filter-drawing-expected.html: Added. * LayoutTests/fast/canvas/canvas-filter-drawing.html: Added. * LayoutTests/fast/canvas/canvas-filter-repaint-rect-expected.html: Added. * LayoutTests/fast/canvas/canvas-filter-repaint-rect.html: Added. * LayoutTests/fast/canvas/canvas-filter-save-restore-expected.html: Added. * LayoutTests/fast/canvas/canvas-filter-save-restore.html: Added. * LayoutTests/fast/canvas/resources/100x100-green-rect-filter-blur.svg: Added. * LayoutTests/fast/canvas/resources/100x100-green-rect-filter-drop-shadow.svg: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.colorMatrix-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.discrete-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.gamma-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.identity-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.linear-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.componentTransfer.table-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.convolveMatrix.exceptions-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.canvasFilterObject.tentative-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/filters/2d.filter.value-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/reset/2d.reset.state.filter-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.tentative-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/filters/2d.filter.canvasFilterObject.tentative.worker-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/filters/2d.filter.value-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/filters/2d.filter.value.worker-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/reset/2d.reset.state.filter-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/reset/2d.reset.state.filter.worker-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/dom/idlharness.https_exclude=(Document_Window_HTML._)-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/dom/idlharness.worker-expected.txt: * LayoutTests/platform/glib/imported/w3c/web-platform-tests/html/dom/idlharness.https_exclude=(Document_Window_HTML._)-expected.txt: * LayoutTests/platform/glib/imported/w3c/web-platform-tests/html/dom/idlharness.worker-expected.txt: * LayoutTests/platform/gtk/imported/w3c/web-platform-tests/html/dom/idlharness.https-expected.txt: * Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: * Source/WebCore/Sources.txt: * Source/WebCore/WebCore.xcodeproj/project.pbxproj: * Source/WebCore/css/parser/CSSPropertyParserWorkerSafe.cpp: (WebCore::CSSPropertyParserWorkerSafe::parseFilterString): * Source/WebCore/css/parser/CSSPropertyParserWorkerSafe.h: * Source/WebCore/html/canvas/CanvasFilterTargetSwitcher.cpp: Added. (WebCore::CanvasFilterTargetSwitcher::create): (WebCore::CanvasFilterTargetSwitcher::CanvasFilterTargetSwitcher): (WebCore::CanvasFilterTargetSwitcher::~CanvasFilterTargetSwitcher): (WebCore::CanvasFilterTargetSwitcher::outsets const): * Source/WebCore/html/canvas/CanvasFilterTargetSwitcher.h: Added. (WebCore::CanvasFilterTargetSwitcher::expandedBounds const): * Source/WebCore/html/canvas/CanvasFilters.idl: * Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp: (WebCore::CanvasRenderingContext2D::setFilterStringWithoutUpdatingStyle): (WebCore::CanvasRenderingContext2D::createFilter const): (WebCore::CanvasRenderingContext2D::calculateFilterOutsets const): * Source/WebCore/html/canvas/CanvasRenderingContext2D.h: * Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp: (WebCore::CanvasRenderingContext2DBase::State::State): (WebCore::CanvasRenderingContext2DBase::setFilterString): (WebCore::CanvasRenderingContext2DBase::fillInternal): (WebCore::CanvasRenderingContext2DBase::strokeInternal): (WebCore::CanvasRenderingContext2DBase::fillRect): (WebCore::CanvasRenderingContext2DBase::strokeRect): (WebCore::CanvasRenderingContext2DBase::drawImage): (WebCore::CanvasRenderingContext2DBase::drawingContext const): (WebCore::CanvasRenderingContext2DBase::inflatedStrokeRect const): (WebCore::CanvasRenderingContext2DBase::drawTextUnchecked): (WebCore::CanvasRenderingContext2DBase::inflateStrokeRect const): Deleted. * Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h: (WebCore::CanvasRenderingContext2DBase::filterString const): (WebCore::CanvasRenderingContext2DBase::setFilterStringWithoutUpdatingStyle): (WebCore::CanvasRenderingContext2DBase::createFilter const): (WebCore::CanvasRenderingContext2DBase::calculateFilterOutsets const): (WebCore::CanvasRenderingContext2DBase::setFilterTargetSwitcher): * Source/WebCore/platform/RectEdges.h: (WebCore::RectEdges::RectEdges): * Source/WebCore/platform/graphics/FloatRect.h: (WebCore::operator+): Canonical link: https://commits.webkit.org/278000@main
0944eb5
to
222707e
Compare
Committed 278000@main (222707e): https://commits.webkit.org/278000@main Reviewed commits have been landed. Closing PR #3793 and removing active labels. |
Awesome to finally see this merged. Thanks everyone who helped getting it across the finish line! ❤️ |
@pencil So will this be implemented in Safari soon? EDIT: I see it's available for testing in Safari Tech Preview currently |
@saghul Yeah I'm also experiencing that blur doesn't work. ctx.filter = "blur(6px)" But after changing it, it still says its set to "none" and does nothing to the canvas. |
@quinton-ashley This should work with any image source. Does this bug happen when applying the filter to a video in the canvas? can you please file this bug in https://bugs.webkit.org? |
I'm trying to use it with an offscreen canvas with an image drawn on it, which is then drawn to a visible canvas. |
@shallawa I submitted the bug report |
Conducting some tests using Safari Technology Preview, apparently when you create a canvas using However, unlike OffscreenCanvas, theoretically a canvas created through Will this functionality be supported? |
This code, for example, presents different results in Safari and Chrome. <html>
<body>
<svg width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<filter id="filter" filterRes="1">
<feColorMatrix type="matrix" values="1 0 0 0 1 0 0.5 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0" />
</filter>
</svg>
</body>
<script>
const canvas = document.createElement("canvas");
const filter = document.querySelector('#filter feColorMatrix');
canvas.width = 800;
canvas.height = 600;
const ctx = canvas.getContext('2d');
const _color = {
redMultiplier: 0,
redOffset: 0,
greenMultiplier: 1,
greenOffset: 0,
blueMultiplier: 1,
blueOffset: 0,
alphaMultiplier: 0.1,
alphaOffset: 0
}
let matrix_str = `${_color.redMultiplier} 0 0 0 ${_color.redOffset / 255} 0 ${_color.greenMultiplier} 0 0 ${_color.greenOffset / 255} 0 0 ${_color.blueMultiplier} 0 ${_color.blueOffset / 255} 0 0 0 ${_color.alphaMultiplier} ${_color.alphaOffset / 255}`;
filter.setAttribute('values', matrix_str);
ctx.filter = 'url(#filter)';
const img = new Image();
img.src = "https://t4.ftcdn.net/jpg/04/38/82/85/360_F_438828559_QccWdc3zAULf7uLTzekIt5XlOEnGj6X0.jpg";
img.onload = () => {
ctx.drawImage(img, 0, 0)
document.body.appendChild(canvas);
}
</script>
</html> In Safari, setting a ...
document.body.appendChild(canvas);
//It works in Safari because the canvas is in the document
ctx.filter = 'url(#filter)';
const img = new Image();
img.src = "https://t4.ftcdn.net/jpg/04/38/82/85/360_F_438828559_QccWdc3zAULf7uLTzekIt5XlOEnGj6X0.jpg";
img.onload = () => {
ctx.drawImage(img, 0, 0)
} Just wanting to know if it will remain this way or if it has been fixed in #30074, as my application depends on this functionality to perform color transformations not supported by OffscreenCanvas. Thank you. |
222707e
0944eb5