-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
CanvasFilter objects as input to CanvasRenderingContext2D.filter attribute #6763
Conversation
@whatwg/canvas please review as well. |
This comment has been minimized.
This comment has been minimized.
Pulling out a separate thread from the data model to discuss some input questions: Currently the input is defined as If you want to support arbitrary filters using the same names as the SVG spec, then What happens if I fill in more than one member of the dictionary? All the examples seem to only fill in a single one. I assume you want to allow a pipeline to contain multiple of the same type of filter, right? E.g. new CanvasFilter([
{ blur: ... },
{ colorMatrix: ... },
{ blur: ... }
]); Otherwise we could get rid of the array, i.e. transform const f = new CanvasFilter([
{ blur: ... },
{ colorMatrix: ... }
]); into const f = new CanvasFilter({
blur: ...,
colorMatrix: ...
}); (taking advantage of the fact that JavaScript objects are ordered.) You can probably get more type-safety, and get the bindings layer to do more work for you, by using Of course, you'd get maximal type-safety---and I think it would also benefit ecosystems like TypeScript, which generate IDE autocomplete from the IDL---if you created separate dictionaries for each filter type, which contained exactly the right properties with exactly the right types. But that would require serious maintenance work to keep in sync with the SVG filters spec. (Probably we'd want to define those dictionaries in the SVG filter spec and just reference them from HTML...) |
source
Outdated
<p class="note">Currently, <code>CanvasFilter</code>s can only be linked lists. Full filter | ||
graphs are a planned expansion of this feature.</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is agreed upon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was basing this off of the conclusions of the TAG review (w3ctag/design-reviews#627) I'm okay with leaving this note out for the time being if it makes other implementers uncomfortable and TAG is okay with it.
No, these four were the top requested by our users/partners. The plan is to eventually support all, though some make little sense in canvas world. For example, Also, there was a preference expressed by Apple to keep things modest initially in this thread: "In practice, most content uses only a fairly small set of filter types. If we're going to add filter support, we should start with a small set of popular filters, and only expand the set if compelling needs arise."
To be honest that was an arbitrary decision made by me when writing the initial proof-of-concept. I'd still love to drop the "fe" prefix though.
Spec-wise that sounds good, but given Apple's reluctance to bite this all off at once that feels unwise. Each one of these does require some work on the user-agent side.
Good question. In my head these dictionaries were really designed as individual stages, but having multiple members filled out will simply apply those filter stages in the order they appear. Perhaps this is another point in favor of
Yeah, totally necessary.
I like this, though the idea with using plain-old dictionaries was one put for by @fserb to reduce the amount of changes to IDL files that would be needed. Thoughts @fserb? |
Based on what you've said so far, my recommendation is that you do something like the following. It takes into account the following desires:
typedef record<DOMString, record<DOMString, any>> CanvasFilterInput;
[Exposed=(Window,Worker)]
interface CanvasFilter {
constructor(CanvasFilterInput or sequence<CanvasFilterInput>) filters);
}; Define the supported filter names to be « "gaussianBlur", "colorMatrix", "convolveMatrix", "componentTransfer" ». Define an XML filter as a struct whose items are a name, a string, and attributes, an ordered map of strings to strings. Define the IDL type for the canvas filter attribute attrName using an algorithm that looks at the grammar definition and returns one of Then your code to assemble the normalized form as part of the constructor looks something like:
Some notes:
|
Is there a precedent where the order of the keys is preserved in such a meaningful manner? I feel it would be a lot more simpler to not wrap the attributes inside a filterDict, but instead have its name be one of the members of this attribute. So something like const f = new CanvasFilter([
{ name: "convolveMatrix", kernelMatrix: [ ... ] },
{ name: "gaussianBlur", stdDeviation: 2 }
]); This way no ambiguity about the order (though if graph is coming, I guess Note: |
@Kaiido I like this. Unless @fserb objects I vote we go with that. I also think leveraging the ordering of javascript objects is surprising.
Unless I'm missing something, it looks like SVG itself uses "name": https://drafts.fxtf.org/filter-effects/#elementdef-fecolormatrix |
Yes, they use the word "name" to describe the filters in the specs, my concern was about the fact that there could theoretically have been an attribute named <feFooBar name="meaningful-value"/> In this case that would have conflicted with this model, since we could not set both the CanvasFilter's name and the SVGFilter's attribute. So I checked for such attributes, and the two only I found were on unrelated elements, both deprecated now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a description of how "XML filter" is mapped to a filter to be used for rendering. I guess it pretty straightforwardly maps to a filter primitive (why is that not its name?), but that needs to be spelled out somewhere.
I added some minimal language to 4.12.5.1.21 Drawing model. Thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good with only a couple conceptual issues remaining before we can move on to editorial tweaks:
- Make sure each
CanvasFilter
has a defined XML filter list associated with it. - Do you want to change to the structure @Kaiido mentioned where instead of records we use
{ name: "x", attr1: "y", attr2: "z" }
structure? In that case I thinkCanvasFilterInput
becomes justrecord<DOMString, any>
, and then the constructor code needs to be updated to special-case name (before the generic attributes loop).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, great! The overall model looks good so we're at the point of lots of editorial tweaks :)
I spoke with @fserb about this and he suggested the key "filter" in order to be even less ambiguous. With this kind of use "name" is a little funny:
As opposed to:
Thoughts? |
I personally do like 1. Technically, the global |
As initially specced, CanvasFilter inputs had a single key that was the name of the filter: ctx.filter = new CanvasFilter({gaussianBlur: {stdDeviation: 5}}); As the result of the debate here (whatwg/html#6763) the interface is changed to have a "filter" key that names the filter type: ctx.filter = new CanvasFilter( {filter: "gaussianBlur", stdDeviation: 5}}); Bug: 1169216 Change-Id: If3fdd9185c1f02dd2dece7db0c92aba76f2d97e1
As initially specced, CanvasFilter inputs had a single key that was the name of the filter: ctx.filter = new CanvasFilter({gaussianBlur: {stdDeviation: 5}}); As the result of the debate here (whatwg/html#6763) the interface is changed to have a "filter" key that names the filter type: ctx.filter = new CanvasFilter( {filter: "gaussianBlur", stdDeviation: 5}); Bug: 1169216 Change-Id: If3fdd9185c1f02dd2dece7db0c92aba76f2d97e1
As initially specced, CanvasFilter inputs had a single key that was the name of the filter: ctx.filter = new CanvasFilter({gaussianBlur: {stdDeviation: 5}}); As the result of the debate here (whatwg/html#6763) the interface is changed to have a "filter" key that names the filter type: ctx.filter = new CanvasFilter( {filter: "gaussianBlur", stdDeviation: 5}); Bug: 1169216 Change-Id: If3fdd9185c1f02dd2dece7db0c92aba76f2d97e1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3098009 Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Reviewed-by: Fernando Serboncini <fserb@chromium.org> Cr-Commit-Position: refs/heads/main@{#916494}
Reference tests are fine for successful conversions (although you could use And yeah, merging this PR makes this feature part of the standard and the standard ought to have good test coverage, so we should have those tests. The process is a bit quicker than in other standards organizations, but we still have some prerequisites. |
From the discussion here (whatwg/html#6763) we need to explicitly test all possible types of inputs for filter attributes. Bug: 1201359 Change-Id: I5ef5905298a17310e4eb54c3c01ab8d6b7973737
@annevk Here's the PR with the tests crrev.com/c/3320960 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. @annevk?
From the discussion here (whatwg/html#6763) we need to explicitly test all possible types of inputs for filter attributes. Bug: 1201359 Change-Id: I5ef5905298a17310e4eb54c3c01ab8d6b7973737 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3320960 Reviewed-by: Yi Xu <yiyix@chromium.org> Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Cr-Commit-Position: refs/heads/main@{#951163}
From the discussion here (whatwg/html#6763) we need to explicitly test all possible types of inputs for filter attributes. Bug: 1201359 Change-Id: I5ef5905298a17310e4eb54c3c01ab8d6b7973737 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3320960 Reviewed-by: Yi Xu <yiyix@chromium.org> Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Cr-Commit-Position: refs/heads/main@{#951163}
From the discussion here (whatwg/html#6763) we need to explicitly test all possible types of inputs for filter attributes. Bug: 1201359 Change-Id: I5ef5905298a17310e4eb54c3c01ab8d6b7973737 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3320960 Reviewed-by: Yi Xu <yiyix@chromium.org> Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Cr-Commit-Position: refs/heads/main@{#951163}
Thanks, looks good to me as well. Will you file the remaining implementation bugs @mysteryDate? See instructions at https://github.com/whatwg/meta/blob/main/MAINTAINERS.md. I might push another fixup for some indentation issue I just noticed. |
Yes, I'll file the remaining implementation bugs this week. Glad to be moving on! 🙌 |
Woohoo, thanks for sticking with us through this very long (323 comment!) review. I think the resulting spec is really nice. |
Yay! Happy holidays everyone. So glad to get this in. |
…asFilter, a=testonly Automatic update from web-platform-tests Test outside of IDL conversions for CanvasFilter From the discussion here (whatwg/html#6763) we need to explicitly test all possible types of inputs for filter attributes. Bug: 1201359 Change-Id: I5ef5905298a17310e4eb54c3c01ab8d6b7973737 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3320960 Reviewed-by: Yi Xu <yiyix@chromium.org> Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Cr-Commit-Position: refs/heads/main@{#951163} -- wpt-commits: fee11623a87d803799f1ec469edcbbefa7d72383 wpt-pr: 31973
If the "filter" key to a new CanvasFilter is unsupported or empty it will now warn the user in the console. See discussion here: whatwg/html#6763 I'm out of ideas for how to test this as there appears to be no way to catch the warning in javascript. Bug: 1272819 Change-Id: I2847b5efd126e29bd3228a4de540671c21087539 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3296334 Reviewed-by: Fernando Serboncini <fserb@chromium.org> Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Cr-Commit-Position: refs/heads/main@{#961977}
As initially specced, CanvasFilter inputs had a single key that was the name of the filter: ctx.filter = new CanvasFilter({gaussianBlur: {stdDeviation: 5}}); As the result of the debate here (whatwg/html#6763) the interface is changed to have a "filter" key that names the filter type: ctx.filter = new CanvasFilter( {filter: "gaussianBlur", stdDeviation: 5}); Bug: 1169216 Change-Id: If3fdd9185c1f02dd2dece7db0c92aba76f2d97e1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3098009 Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Reviewed-by: Fernando Serboncini <fserb@chromium.org> Cr-Commit-Position: refs/heads/main@{#916494} NOKEYCHECK=True GitOrigin-RevId: 833d2100d38c8656a28bb72109f07aa5158e9f9c
From the discussion here (whatwg/html#6763) we need to explicitly test all possible types of inputs for filter attributes. Bug: 1201359 Change-Id: I5ef5905298a17310e4eb54c3c01ab8d6b7973737 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3320960 Reviewed-by: Yi Xu <yiyix@chromium.org> Reviewed-by: Domenic Denicola <domenic@chromium.org> Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Cr-Commit-Position: refs/heads/main@{#951163} NOKEYCHECK=True GitOrigin-RevId: ba6cbce4987586600aa98a2b2289c55faa2cdfc3
If the "filter" key to a new CanvasFilter is unsupported or empty it will now warn the user in the console. See discussion here: whatwg/html#6763 I'm out of ideas for how to test this as there appears to be no way to catch the warning in javascript. Bug: 1272819 Change-Id: I2847b5efd126e29bd3228a4de540671c21087539 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3296334 Reviewed-by: Fernando Serboncini <fserb@chromium.org> Commit-Queue: Aaron Krajeski <aaronhk@chromium.org> Cr-Commit-Position: refs/heads/main@{#961977} NOKEYCHECK=True GitOrigin-RevId: 3c24d94ae972621f005e42d6f74e0b6588fb44d5
Only the height was checked (rejecting `[]` kernels) but kernels with zero width like `[[], []]` were incorrectly accepted. The current CanvasFilter specification is defined by reusing the SVG specification for how the filters attributes work (whatwg/html#6763). For the "feConvolveMatrix" filter, the SVG specification says (https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElement): "Attribute definitions: - order = "<number-optional-number>" Indicates the number of cells in each dimension for ‘kernelMatrix’. The values provided must be <integer>s greater than zero. The first number, <orderX>, indicates the number of columns in the matrix. The second number, <orderY>, indicates the number of rows in the matrix. If <orderY> is not provided, it defaults to <orderX>." Change-Id: I23baf05db73e679a52cd9d553d7c6308d91b56f9 Bug: 1428652
Only the height was checked (rejecting `[]` kernels) but kernels with zero width like `[[], []]` were incorrectly accepted. The current CanvasFilter specification is defined by reusing the SVG specification for how the filters attributes work (whatwg/html#6763). For the "feConvolveMatrix" filter, the SVG specification says (https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElement): "Attribute definitions: - order = "<number-optional-number>" Indicates the number of cells in each dimension for ‘kernelMatrix’. The values provided must be <integer>s greater than zero. The first number, <orderX>, indicates the number of columns in the matrix. The second number, <orderY>, indicates the number of rows in the matrix. If <orderY> is not provided, it defaults to <orderX>." Change-Id: I23baf05db73e679a52cd9d553d7c6308d91b56f9 Bug: 1428652 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4377066 Reviewed-by: Aaron Krajeski <aaronhk@chromium.org> Commit-Queue: Jean-Philippe Gravel <jpgravel@chromium.org> Cr-Commit-Position: refs/heads/main@{#1124423}
Only the height was checked (rejecting `[]` kernels) but kernels with zero width like `[[], []]` were incorrectly accepted. The current CanvasFilter specification is defined by reusing the SVG specification for how the filters attributes work (whatwg/html#6763). For the "feConvolveMatrix" filter, the SVG specification says (https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElement): "Attribute definitions: - order = "<number-optional-number>" Indicates the number of cells in each dimension for ‘kernelMatrix’. The values provided must be <integer>s greater than zero. The first number, <orderX>, indicates the number of columns in the matrix. The second number, <orderY>, indicates the number of rows in the matrix. If <orderY> is not provided, it defaults to <orderX>." Change-Id: I23baf05db73e679a52cd9d553d7c6308d91b56f9 Bug: 1428652 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4377066 Reviewed-by: Aaron Krajeski <aaronhk@chromium.org> Commit-Queue: Jean-Philippe Gravel <jpgravel@chromium.org> Cr-Commit-Position: refs/heads/main@{#1124423}
Only the height was checked (rejecting `[]` kernels) but kernels with zero width like `[[], []]` were incorrectly accepted. The current CanvasFilter specification is defined by reusing the SVG specification for how the filters attributes work (whatwg/html#6763). For the "feConvolveMatrix" filter, the SVG specification says (https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElement): "Attribute definitions: - order = "<number-optional-number>" Indicates the number of cells in each dimension for ‘kernelMatrix’. The values provided must be <integer>s greater than zero. The first number, <orderX>, indicates the number of columns in the matrix. The second number, <orderY>, indicates the number of rows in the matrix. If <orderY> is not provided, it defaults to <orderX>." Change-Id: I23baf05db73e679a52cd9d553d7c6308d91b56f9 Bug: 1428652 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4377066 Reviewed-by: Aaron Krajeski <aaronhk@chromium.org> Commit-Queue: Jean-Philippe Gravel <jpgravel@chromium.org> Cr-Commit-Position: refs/heads/main@{#1124423}
Only the height was checked (rejecting `[]` kernels) but kernels with zero width like `[[], []]` were incorrectly accepted. The current CanvasFilter specification is defined by reusing the SVG specification for how the filters attributes work (whatwg/html#6763). For the "feConvolveMatrix" filter, the SVG specification says (https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElement): "Attribute definitions: - order = "<number-optional-number>" Indicates the number of cells in each dimension for ‘kernelMatrix’. The values provided must be <integer>s greater than zero. The first number, <orderX>, indicates the number of columns in the matrix. The second number, <orderY>, indicates the number of rows in the matrix. If <orderY> is not provided, it defaults to <orderX>." Change-Id: I23baf05db73e679a52cd9d553d7c6308d91b56f9 Bug: 1428652 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4377066 Reviewed-by: Aaron Krajeski <aaronhk@chromium.org> Commit-Queue: Jean-Philippe Gravel <jpgravel@chromium.org> Cr-Commit-Position: refs/heads/main@{#1124423}
…olveMatrix CanvasFilters., a=testonly Automatic update from web-platform-tests Reject kernelMatrix with 0 width in convolveMatrix CanvasFilters. Only the height was checked (rejecting `[]` kernels) but kernels with zero width like `[[], []]` were incorrectly accepted. The current CanvasFilter specification is defined by reusing the SVG specification for how the filters attributes work (whatwg/html#6763). For the "feConvolveMatrix" filter, the SVG specification says (https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElement): "Attribute definitions: - order = "<number-optional-number>" Indicates the number of cells in each dimension for ‘kernelMatrix’. The values provided must be <integer>s greater than zero. The first number, <orderX>, indicates the number of columns in the matrix. The second number, <orderY>, indicates the number of rows in the matrix. If <orderY> is not provided, it defaults to <orderX>." Change-Id: I23baf05db73e679a52cd9d553d7c6308d91b56f9 Bug: 1428652 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4377066 Reviewed-by: Aaron Krajeski <aaronhk@chromium.org> Commit-Queue: Jean-Philippe Gravel <jpgravel@chromium.org> Cr-Commit-Position: refs/heads/main@{#1124423} -- wpt-commits: 8b9f4e275162d151dc2a0c847601542d75051cbf wpt-pr: 39255
WhatWG bug: #5621
Original propsal: https://github.com/fserb/canvas2D/blob/master/spec/filters.md
TAG review thread: w3ctag/design-reviews#627
Webkit-dev thread: https://lists.webkit.org/pipermail/webkit-dev/2021-May/031840.html
Mozilla standards thread: mozilla/standards-positions#519
/canvas.html ( diff )
/infrastructure.html ( diff )
/references.html ( diff )