Re: [whatwg] Support filters in Canvas
Having an opaque handle (CanvasFilter) would be great for Houdini paint. This would mean that when we plumb in a property of CSS type the TypedOM can have an opaque handle to that filter. I.e. registerPaint('x', class { paint(ctx, styleMap) { const filter = styleMap.get('--my-filter').filter; // ... ctx.filter = filter; // \o/ ctx.filter = 'url(#thing)'; // would fail for Houdini paint. } }); It would make a lot of sense as wouldn't have to deal with paint time resolving of url(), when happens when filter changes, etc. This is similar to what we'd like to do with text (assigning an already resolved FontFace or similar). Ian On Fri, Feb 26, 2016 at 8:20 AM, Justin Novosadwrote: > On Fri, Feb 26, 2016 at 10:40 AM, Anne van Kesteren > wrote: > > > On Fri, Feb 26, 2016 at 4:34 PM, Ali Juma wrote: > > > The current canvas filters proposal [1] allows using SVG reference > > filters > > > defined in external documents (e.g. “url(file.svg#filter)”). Since the > > > external document needs to be loaded before the filter can be applied, > > > there’s a delay between setting the context’s filter attribute to such > a > > > filter and actually having the filter apply to drawing operations. > > > > Perhaps we could support assigning an SVG filter directly (as an > > object)? Developers would be responsible to load them if they're > > external. Adding yet another network API that's a thin layer on top of > > some CSS syntax seems a little hackish. I'd prefer if we exposed > > filters at a lower level somehow. > > > > Just thought of a way to solve this problem without new API. You can load > the svg file as xml using XHR, and therefore guarantee the resource's > continued availability thereafter. In order to make the filter node > reachable for setting it as a canvas filter using the url() syntax, I think > you'd have to pull it in to your HTML with something like: > someLocalElement.innerHTML = new > XMLSerializer().serializeToString(svgObtainedViaXHR.documentElement); > I know this is gross (parse->serialize->re-parse), but I'm just saying > there is a way (I think). > > > > > -- > > https://annevankesteren.nl/ > > >
Re: [whatwg] Support filters in Canvas
On Fri, Feb 26, 2016 at 10:40 AM, Anne van Kesterenwrote: > On Fri, Feb 26, 2016 at 4:34 PM, Ali Juma wrote: > > The current canvas filters proposal [1] allows using SVG reference > filters > > defined in external documents (e.g. “url(file.svg#filter)”). Since the > > external document needs to be loaded before the filter can be applied, > > there’s a delay between setting the context’s filter attribute to such a > > filter and actually having the filter apply to drawing operations. > > Perhaps we could support assigning an SVG filter directly (as an > object)? Developers would be responsible to load them if they're > external. Adding yet another network API that's a thin layer on top of > some CSS syntax seems a little hackish. I'd prefer if we exposed > filters at a lower level somehow. > Just thought of a way to solve this problem without new API. You can load the svg file as xml using XHR, and therefore guarantee the resource's continued availability thereafter. In order to make the filter node reachable for setting it as a canvas filter using the url() syntax, I think you'd have to pull it in to your HTML with something like: someLocalElement.innerHTML = new XMLSerializer().serializeToString(svgObtainedViaXHR.documentElement); I know this is gross (parse->serialize->re-parse), but I'm just saying there is a way (I think). > -- > https://annevankesteren.nl/ >
Re: [whatwg] Support filters in Canvas
From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of Anne van Kesteren > Perhaps we could support assigning an SVG filter directly (as an object)? > Developers would be responsible to load them if they're external. Adding yet > another network API that's a thin layer on top of some CSS syntax seems a > little hackish. I'd prefer if we exposed filters at a lower level somehow. I tend to agree. I don't like that the filter property is now sometimes a string, sometimes a CanvasFilter. Maybe something like `setFilter((DOMString or CanvasFilter) filter)` with the readonly `filter` property returning a CanvasFilter all the time? This would involve fleshing out CanvasFilter a bit. Strawman: const filter1 = new CanvasFilter("contrast(50%) blur(3px)"); // filter1 looks like { value: "contrast(50%) blur(3px)", loadedFrom: null } CanvasFilter.load("file.svg#blur").then(filter2 => { // filter2 looks like { value: null, loadedFrom: "file.svg#blur" } ctx.setFilter(filter1); ctx.strokeText("Canvas", 50, 500); assert(ctx.filter === filter1); ctx.setFilter(filter2); ctx.strokeText("Filters", 50, 100); assert(ctx.filter === filter2); ctx.setFilter(filter3); ctx.strokeText("SVG", 50, 200); }); This doesn't really solve Anne's concerns about a new networking API, but I am not sure how to do that given that fragments are involved (which are not a networking concept, really). Maaaybe you could do something like fetch("file.svg").then(res => res.blob()).then(blob => { const filter2 = CanvasFilter.fromSVG(blob, "#blur"); // ... }); --- Alternately, is it possible to generically represent a loaded SVG filter as a string? Browsing the linked thread it seems unlikely as it may involve further external resource fetches etc. But that would help some design space.
Re: [whatwg] Support filters in Canvas
On Fri, Feb 26, 2016 at 4:34 PM, Ali Jumawrote: > The current canvas filters proposal [1] allows using SVG reference filters > defined in external documents (e.g. “url(file.svg#filter)”). Since the > external document needs to be loaded before the filter can be applied, > there’s a delay between setting the context’s filter attribute to such a > filter and actually having the filter apply to drawing operations. Perhaps we could support assigning an SVG filter directly (as an object)? Developers would be responsible to load them if they're external. Adding yet another network API that's a thin layer on top of some CSS syntax seems a little hackish. I'd prefer if we exposed filters at a lower level somehow. -- https://annevankesteren.nl/
Re: [whatwg] Support filters in Canvas
The current canvas filters proposal [1] allows using SVG reference filters defined in external documents (e.g. “url(file.svg#filter)”). Since the external document needs to be loaded before the filter can be applied, there’s a delay between setting the context’s filter attribute to such a filter and actually having the filter apply to drawing operations. So authors can’t predict when the filter will start getting applied. For example: var canvas = document.getElementById(“canvas”); var ctx = canvas.getContext(“2d”); ctx.filter = “url(file.svg#blur)” ctx.font = “48px serif” ctx.strokeText(“Hello world”, 50, 100); Unless file.svg happens to already be loaded, it won’t be loaded in time for the call to strokeText. After some unpredictable delay, the document will finish loading and the filter will start being applied to future draw operations. Another problem is switching between filters defined in separate documents within the same animation frame. Continuing the previous example: ctx.filter = “url(file2.svg#dropShadow)” ctx.strokeText(“Hello again”, 50, 200); ctx.filter = “url(file.svg#blur)” ctx.strokeText(“Canvas”, 50, 300); As soon as the filter property’s value is changed, documents that the previous value referred to may get unloaded. So after switching back to “url(file.svg#blur)” there might be another delay before the filter is useable again. To address these problems, I’d like to propose adding a createFilter method. This takes a string (a filter value) and returns a promise. If the filter fails to load, the promise is rejected. Otherwise, once the filter finishes loading, the promise resolves to a CanvasFilter instance that acts as an opaque handle to the filter. The filter is guaranteed to remain loaded as long as the handle has references. A CanvasFilter can be directly used as a filter attribute value. That is, the filter attribute is now defined as: attribute (DOMString or CanvasFilter) filter; For example: var filters = []; var promises = []; promises[0] = ctx.createFilter(“url(file.svg#blur)”); promises[1] = ctx.createFilter(“url(file2.svg#dropShadow)”); Promise.all(promises).then(function(values) { filters = values; // Filters can now be used without any delay. ctx.filter = filters[0]; ctx.strokeText(“Canvas”, 50, 400); ctx.filter = filters[1]; ctx.strokeText(“Filters”, 50, 100); ctx.filter = filters[0]; ctx.strokeText(“SVG”, 50, 200); }); … // Once we no longer need these filters, release them. filters = []; Ali [1] https://lists.w3.org/Archives/Public/public-whatwg-archive/2014Sep/0110.html