W3C home > Mailing lists > Public > www-svg@w3.org > April 2011

Re: Comments on SVG Compositing

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Fri, 8 Apr 2011 13:12:20 -0700
Message-ID: <BANLkTimUbjifQU6avQSRHnoLg+OWVXoizg@mail.gmail.com>
To: Rik Cabanier <cabanier@gmail.com>
Cc: www-svg <www-svg@w3.org>
Rik, thanks for the response!  I understand some of the design choices
a little more.

I still have a problem with 'clip-to-self'.  There are some operations
in which it can be useful, but others in which it's useless and kinda
confusing - one should instead use the appropriate normal compositing
operation.

For example, applying "clip-to-self:object" to A in "A clear B" is
exactly equivalent to applying "clip-to-self:canvas" to A in "A
dst-out B".  Lessee, I'll make a quick table...

"object"     => "canvas"
A clear B    => A dst-out B
A src B      => A src-over (A dst-out B)
A src-in B   => (A src-in B) src-over (A dst-out B)
A dst-in B   => (A dst-in B) src-over (A dst-out B)
A src-out B  => (A src-out B) src-over (A dst-out B) (A xor B *almost*
works, but it's not quite the same)
A dst-atop B => A dst-over B

If I were designing this myself, I'd remove the ability of c-t-s to
affect clear and dst-atop, since you can just use a better comp-op
instead.

The other 4 seem useful, but they also seem incomplete - if it's
useful to use this with "A src B" (keeping the part of B outside of
A), then wouldn't it be just as useful to use it with "A dst B"
(keeping the part of A outside of B)?  Is there a good reason why we
don't have this reversed capability, which we could apply to 'dst' and
'dst-out' (and apply to src-in and dst-in to get a different
behavior)?  Something like "comp-clip-to: canvas | src | dst |
intersection", with the default being 'canvas'.  The currently-defined
value of "object" would be 'src', affecting the src, src-in, dst-in,
and src-out operators.  'dst' would affect the dst, src-in, dst-in,
and dst-out operators.  'intersection' would only affect src-in and
dst-in.

This is general and easy to understand - the compositing is limited to
certain bounds, with stuff outside those bounds unaffected by the
composition.  The name also makes clear that it's the *compositing*
that is being clipped; the current name seems to be backwards to
someone relatively unfamiliar with the terms of art, as it seems like
you are "clipping to the object" when you remove the destination, and
"clipping to the canvas" when you keep it - the opposite of what the
values actually do!

----------------


The 'enable-background' property still seems confusing because it
appears to reverse the ordering of the operations, but I think that's
just because of the way the example is laid out - we naturally assume
that you should start by resolving operations from the inside out,
when the actual drawing order is the opposite.  That is, the
'accumulate' example appears to use the following markup:

<svg ...>
  <rect ... />
  <g enable-background='accumulate'>
    <circle ... />
    <polygon ... comp-op='multiply' />
  </g>
</svg>

Is this right?  Presenting it in such a way would, I think, make it
easier to understand what's happening, and why the triangle is the
only thing affected by the property in that example (the circle is
composited over the background with 'src-over' and is fully opaque, so
e-b doesn't make a difference here).  The presentation that the
example uses, where the compositing operations are binary operation
between elements, feels misleading.

-------------------


>> I don't have strong graphics experience, so there may be something I'm
>> missing here, but 'enable-background' and 'knock-out' appear to be
>> *exactly* identical in operation, just applying to different things:
>> 'knock-out' transforms "A op B" to "A op (A dst_out B)", while
>> enable-background transforms "[group image] over [background]" to
>> "[group image] over ([group image] dst_out [background]".  Can these
>> two properties be unified in some way?
>>
> knock-out = how objects within the container blend with each other
> enable-background = how objects within the container blend with the
> background
> The programming logic between the 2 modes is very different so I think that
> this is enough for a separate attribute.

Your description makes them seem even more similar.  ^_^  From the POV
of an author with relatively little graphics experience, there's no
important difference between these two for me.  The fact that
implementations might implement the two in different fashions is
irrelevant to me, because I'm not an implementor.


> If you unify them into 1 property, it would also result in many states:
> knock-out (= 3 states) * enable-background (= 3 states) = 9 different names
> which is more confusing.

I'm not sure I understand.  'knock-out' and 'enable-background' have
only two states each.  Further, the syntax seems like it can be very
simple; something like:

comp-over: none | [ group || [ background | rect(x,y,w,h)] ]

...with 'comp-over: group background;' being the default.

The only thing that would let me justify this being split into two
property would be if it seems like it's useful to have these cascade
separately.  I don't have enough experience with using these to
understand if that's something important or not.


-----------------

So, to sum up, I propose reworking the 'clip-to-self',
'enable-background', and 'knock-out' properties into two more
author-friendly properties:

comp-clip-to: canvas | src | dst | intersection;
comp-over: none | [group || [background | rect(x,y,w,h)]]

'comp-clip-to' limits the area that the compositing occurs within.
I'm ambivalent on whether it affects all properties or just the
handful that can't be easily done just by switching to a different
comp-op.  The default is 'canvas'.

'comp-over' determines what you composite each element over when
building a group.  'group' means to use the results of previous
compositing within the group.  'background' means to use the nearest
ancestor group's buffer; rect() is the same, but cuts out a specific
rectangle of the nearest ancestor group's buffer to be used.    'none'
just means to always run each compositing operation with a transparent
black buffer, ignoring the ancestor buffers or previous elements in
the group.  The default value is "group background".

The 'comp-op' property in the draft seems fine.

~TJ
Received on Friday, 8 April 2011 20:13:09 GMT

This archive was generated by hypermail 2.3.1 : Friday, 8 March 2013 15:54:48 GMT