Re: [whatwg] Support filters in Canvas

2016-02-26 Thread Ian Kilpatrick
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 Novosad  wrote:

> 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

2016-02-26 Thread Justin Novosad
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

2016-02-26 Thread Domenic Denicola
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

2016-02-26 Thread Anne van Kesteren
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.


-- 
https://annevankesteren.nl/


Re: [whatwg] Support filters in Canvas

2016-02-26 Thread Ali Juma
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