W3C home > Mailing lists > Public > whatwg@whatwg.org > September 2013

Re: [whatwg] remove resetClip from the Canvas 2D spec

From: Ian Hickson <ian@hixie.ch>
Date: Thu, 12 Sep 2013 01:08:10 +0000 (UTC)
To: WHATWG List <whatwg@whatwg.org>
Message-ID: <alpine.DEB.2.00.1309120056550.12199@ps20323.dreamhostps.com>
On Fri, 9 Aug 2013, Simon Sarris wrote:
>
> As an alternative [to resetClip()] I would propose something like 
> setClip() or setClip(path) (with the former working on the current path, 
> just like clip()/fill()/stroke() does).

Seems like this would have the same problems as resetClip(), since it's 
essentially the same as a call to resetClip() followed by a call to clip().


On Fri, 9 Aug 2013, Justin Novosad wrote:
>
> What if resetClip restored the clip to what it was at the save call that 
> created the current state stack level? In other words, restore the clip, 
> but without popping it off the save/restore stack.
> 
> Also, resetMatrix could be defined to do the same.

Wouldn't that be the same as just save()/clip()/restore() ?


On Mon, 12 Aug 2013, Rik Cabanier wrote:
> 
> It would be good to hear specific use cases for 'resetClip' so we can make
> that call.

The main use case would be something like:

   c.save();
   c.resetTransform();
   c.resetClip();
   // draw something at the top right...
   c.restore();

...deep inside some draw code.


> > Also, resetMatrix could be defined to do the same.
> 
> Is that API defined somewhere?

I think Justin meant resetTransform().


On Mon, 12 Aug 2013, Simon Sarris wrote:
>
> I think most performance-minded use cases will be fine with junov's idea
> since they will not want to touch the stack in the first place.
> 
> Here's a simple use case: Suppose there are nested objects to be drawn,
> Panels, TextBlocks, and other visual elements. Panels are containers that
> draw a background and all of their children - and they contain any number
> of Panels or TextBlocks or other elements, and TextBlocks set the context
> font (to their font) and draw some text.
> 
> The drawing structure is hierarchical, and drawn elements may be offset
> from their immediate parent. So a drawing hierarchy might look like this:
> 
> Panel(A)
>     Panel(B)
>         TextBlock
>     TextBlock
> 
> That is, Panel(A) contains Panel(B) and a TextBlock. And Panel(B) contains
> another TextBlock. In practice, nesting could be much deeper and more
> complicated.
> 
> Now suppose also that Panels have some settings, such as a maximum width,
> that might cause their visual elements to be clipped. So a panel might need
> to save(), clip(), draw all of its children, and then restore(). Nesting
> means multiple levels of clipping, for instance with the above hierarchy it
> might look like:
> 
> Panel(A)
>     clip (save)
>     drawChildren:
>         Panel(B)
>             clip (save)
>             drawChildren:
>                 TextBlock
>                     sets font X
>                     fillText
>             restore
>         TextBlock
>             sets font X
>             fillText
>     restore
> 
> This is problematic, because it means:
> 
> 1. I must use save() and restore(), which are slow in their own right

I'm pretty sure save() and restore() are the right solution here. If those 
don't work, we should fix those, not add more features that might have 
their own issues.


> 2. The usage of save() and restore() means that, even if all (or most) of
> my fonts are set to the same value, I have to keep setting them over and
> over. Setting the font is slow in practice, even if it is set to the same
> value as before, and so it should be cached if at all possible.

Again, if settings fonts is slow, that should be fixed independently of 
resetClip().


On Mon, 12 Aug 2013, Justin Novosad wrote:
> 
> Good point, I think part of the problem has to do with the fact that save
> is non-selective (saves all of the state).
> Might be worthwhile to have a selective save that pushes only a
> user-specified subset of the current state onto the stack.

There's no reason save() and restore() need be slow just because they save 
a lot. It's relatively easy to have a stack that only saves the things 
that have changed (e.g. by setting a bit when you change things, so you 
know what has changed, and then only pushing onto the stack the 
instructions to change the stuff that has changed).


On Mon, 12 Aug 2013, Simon Sarris wrote:
> 
> Yes, since save() and restore() save and restore everything, it creates 
> the side effect of needing to set ctx.font/fillStyle/strokeStyle more 
> often than otherwise, which are slow to set, probably because of some 
> CSS parser activity, but I'm not wise enough to know.

save() and restore() should have no reason to go through the CSS parser.


On Mon, 12 Aug 2013, Justin Novosad wrote:
>
> Ok, so here is a simple proposal:
> 
> IDL:
> enum CanvasSaveMode { "all", "transform", "clip", "transform-and-clip" };
> save(optional CanvasSaveMode mode);
> 
> Modes:
> all: save the entire rendering context state
> transform: save only the current transform
> clip: save only the current clip
> 
> if mode is not specified, the entire context state is saved (for backward
> compatibility)
> 
> The restore method's interface does not change. It restores whatever state
> was saved by the matching save call.

I don't understand what problem this is solving.


On Tue, 13 Aug 2013, Simon Sarris wrote:
> 
> I'd argue its not strictly a performance issue. More generally its 
> awkward that you can reset any piece of the canvas context state except 
> the clipping region. The clipping region alone requires you to clobber 
> all state in order to reset it.
> 
> You can set the fillStyle back to black, you can set the transformation 
> matrix back to identity, etc. But you can't set the clipping region back 
> to the entire canvas area without save()/restore() or 
> can.width=can.width. It's the only thing like that.
> 
> That ought to be considered bad on principle I think. It makes clipping 
> a really odd operation compared to anything else, and at the least it 
> makes the one part of the API unintuitive.

This is the argument for resetClip(), though the only use case seems to be 
the one I mentioned (drawing something at the top right, or whatever, deep 
inside some code that has clipped and transformed).

I've marked the resetClip() feature in the spec as being considered form 
removal. If no browser implement it in due course, I'll remove it. Despite 
being relatively commonly requested, it must be admitted that the use 
cases for this feature aren't that compelling.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
Received on Thursday, 12 September 2013 01:08:43 UTC

This archive was generated by hypermail 2.4.0 : Wednesday, 22 January 2020 17:00:09 UTC