Complementary masking

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 12:26:56 UTC