[css-filters] feBlend filter

All,

last week Michael Mullany posted a screenshot of a
transformed feBlend filter: http://tinypic.com/r/rc3qs0/5 [1]
The thing that struck me what that the part of the backdrop was pulled into
the filter (so a piece of the red rectangle was copied over).

After thinking this over a bit, I think that there's a flaw in how the
feBlend filter currently works.
Given the following markup:

    <defs>
    <filter id="what" >
      <feBlend mode="screen" in="SourceGraphic" in2="BackgroundImage"/>
    </filter>
  </defs>

  <g enable-background="new">
    <rect width="100" height="100" fill="red"/>
    <g filter="url(#what)">
      <rect x="50" y="50" width="100" height="100" fill="rgb(0,255,0)"
opacity=".5"/>
    </g>
  </g>


This snippet of SVG, implies that the content of <g> will be blended with
the backdrop.
The formula of 'feBlend ' with a 'screen' blend mode [2] is:

cr = cb + ca - ca * cb

This formula is the combination of a screen blend + a source-over composite
[3]. This seems reasonable.
However, the result of this filter is then again composited (because of
normal alpha compositing) so the blended content is composited twice.

You can observe that behavior in the following markup [4]:

  <defs>
    <filter id="what" >
      <feBlend mode="*normal*" in="SourceGraphic" in2="BackgroundImage"/>
    </filter>
  </defs>

  <g enable-background="new">
    <rect width="100" height="100" fill="red"/>
    <g filter="url(#what)">
      <rect x="50" y="50" width="100" height="100" fill="rgb(0,255,0)"
opacity=".5"/>
    </g>
  </g>

  <g enable-background="new" transform="translate(0,200)">
    <rect width="100" height="100" fill="red"/>
    <g>
      <rect x="50" y="50" width="100" height="100" fill="rgb(0,255,0)"
opacity=".5"/>
    </g>
  </g>

See the attached png for a screenshot.
The intersection of the 2 rectangles looks different because the one with
the filter is composited twice.

I believe the problem is with the formulas for 'feBlend'. They shouldn't
also do compositing.
Because of this, you can't correctly implement blending with SVG filters.

I'm unsure how this can be fixed cleanly since it's probably too late to
change the blend formulas. Maybe we can introduce a new filter primitive?

1: http://lists.w3.org/Archives/Public/www-style/2013May/0621.html
2:
https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#feBlendElement
3: https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending

cr = ás x (1 - áb) x Cs + ás x áb x B(Cb, Cs) + (1 - ás) x áb x Cb
= ás x (1 - áb) x Cs + ás x áb x (Cb + Cs -(Cb x Cs)) + (1 - ás) x áb x Cb
= ás x Cs - ás x áb x Cs + ás x áb x Cb + ás x áb x Cs - ás x áb x  Cb x Cs
+ áb x Cb - ás x áb x Cb
= ás x Cs - ás x áb x  Cb x Cs + áb x Cb
= cs - cs x cb + bc

4: http://www.codepen.io/seraphzz/pen/jideo (Only IE 10 +)

Received on Wednesday, 29 May 2013 20:53:04 UTC