Re: Complementary masking

Hi J.R.

It is possible to create an SVG that has uses two masks that are
"complments" of one another and share a single path definition.

Here's a simple example:

<svg width="500" height="300">
  <defs>
    <path id="maskshape" d="M0 0 L200 0 C250 100 250 200 200 300 L0 300 Z"/>

    <mask id="mask1">
      <rect width="500" height="300" fill="black"/>
      <use xlink:href="#maskshape" fill="white"/>
    </mask>
    <mask id="mask1-complement">
      <rect width="500" height="300" fill="white"/>
      <use xlink:href="#maskshape" fill="black"/>
    </mask>
  </defs>

  <rect width="500" height="300" fill="darkorange" mask="url(#mask1)" />
  <rect width="500" height="300" fill="darkslateblue"
mask="url(#mask1-complement)" />
</svg>


https://jsfiddle.net/tukk4so2/

Regards

Paul


On 2 June 2016 at 20:52, J. R. Haigh <jrhaigh+ml.w3.svg@fsfe.org> wrote:

> Dear SVG standards editors,
>         Something which I frequently want to do is to clip 2 objects such
> that one fits tightly with the other. I create a clipping path for object A
> and a complementary clipping path for object B. This is cumbersome because
> updating the original clipping path does not update its complement.
>         It also suffers from a common misrendering of antialiased edges
> which leaves a ‘hairline’ of translucency, 1 pixel thick regardless of the
> zoom. This is a misrendering because supersampling diminishes the hairline
> – surely a correct rendering of /scalable/ vector graphics should not be
> affected by the zoom level or resolution, i.e. be ‘resolution-agnostic’.
>         Furthermore, when trying to generalise this to masking, it gets
> even more cumbersome. Creating a complement mask object may be a challenge
> in itself, but to have to update it manually each time the original is
> altered is even more cumbersome.
>         However, I've found a way of using compositing filters to
> demonstrate the concept of complement masking, and this can be used for
> complementary clipping without hairlines even without resolution-agnostic
> rendering:
>
>     <filter
>        style="color-interpolation-filters:sRGB"
>        id="filter-complementary-masking"
>        inkscape:label="Complementary Masking">
>       <feImage
>          id="feImage-objectA"
>          xlink:href="#objectA"
>          result="result1" />
>       <feComposite
>          id="feComposite-mask"
>          in2="SourceAlpha"
>          operator="in"
>          result="result2" />
>       <feImage
>          id="feImage-objectB"
>          xlink:href="#objectB"
>          result="result3" />
>       <feComposite
>          id="feComposite-complementMask"
>          in2="SourceAlpha"
>          operator="out"
>          result="result4" />
>       <feComposite
>          id="feComposite-add"
>          in2="result2"
>          operator="arithmetic"
>          k2="1"
>          k3="1" />
>     </filter>
>
> It's not very practical, though, because it comes with a few problems
> which make it cumbersome:
> • behaves very differently from the SVG mask element (
> https://www.w3.org/TR/SVG/masking#Masking ) for which this is
> conceptually a generalisation of;
>         - the XML looks very different and is applied using the Filter
> Editor in Inkscape rather than the ‘Object’ → ‘Mask’ → ‘Set’ menu item;
>         - the original objects remain;
>         - the masked objects do not appear in their original positions;
>         - the masked objects move when the path is moved or when it is
> altered such that the left or top edges of the bounding box move (the
> objects should stay still regardless of how the path is manipulated);
> • in Inkscape 0.91 (at least), the feImage filter renders clipped paths at
> fixed resolution (anything closer than 1:1 zoom appears pixelated; even
> when the clipped path is part of a group, only the clipped path has fixed
> resolution, other objects within the group are scalable).
>
>         Ideally, the masking and clipping of the SVG standard should be
> updated to provide a native means to do complementary masking. The
> resolution-dependent rendering remains a problem, though, particularly for
> complementary clipping because I also often want object A and object B to
> be clones of the same object, but for there to be 1 or more other objects
> between the normal clip and the complement clip in the Z-order.
>         I suggest that the amendment to the standard wrt. complementary
> clipping be:
> • introduce 2 new insideness rules, ‘zero’ and ‘even’[1], used for the
> fill-rule and clip-rule properties – an svg:clipPath element can be used
> for a complement clipping by setting clip-rule to ‘zero’ in the default
> case where the ‘original clip’ uses the ‘nonzero’ insideness rule, or
> ‘even’ where the original is set to ‘odd’;
> • require resolution-agnostic rendering such that hairlines are fixed on
> the complementary clipping and other situations in which they appear.
> (Note 1: Also please make ‘odd’ a synonym of ‘evenodd’, as the insideness
> is just when it's odd, not even.)
>         For the complementary masking, the svg:mask element can be used as
> it is in the defs, staying consistent with svg:clipPath which is also used
> as-is, but in the drawing, something needs to take exactly 2 input objects,
> so maybe there should be a new container element which takes exactly 2
> children and has a mask property specifying an svg:mask element (from the
> defs) and applies it as a mask to the first element and as a complement
> mask to the second element, much in the manner of the above filter. The
> specifics of how best to specify the 2 input objects needs some more
> thought.
>         The complementary masking would perhaps be most commonly useful
> for merging 2 different objects, but the usecase of weaving objects
> together still applies:
> • an object is cloned (this will be the main one which others are weaved
> into);
> • 1 or more other objects are grouped with either of the clones with the
> clone at the back of the group;
> • the group and the other clone (or the 2 groups if both clones have had
> objects grouped to them) are then complementary masked together again.
>         More than 2 objects can be complementary masked by nesting such
> maskings and using n - 1 svg:mask references where n is the number of
> objects that are desired to be complementary masked. Overall it's a pretty
> comprehensive generalisation I think, at least as far as I can see.
>         I hope that these suggestions are useful for progressing the
> standard.
>
> Yours faithfully,
> J. R. Haigh.
> --
> Sent from Claws Mail on NixOS.
>
>
>

Received on Thursday, 2 June 2016 14:19:45 UTC