Dplug icon indicating copy to clipboard operation
Dplug copied to clipboard

dplug:canvas enhancements

Open p0nce opened this issue 5 years ago • 6 comments

  • [x] ways to do multiple lineTo in one call.
  • [ ] Clipping rect, to avoid reinitializing the canvas for each dirtyRect (need to fix gradients coordinates I think)
    • [ ] Note that if we had arbitrary clipping rect, would redraw even less, perhaps doable in canvasity!
  • [ ] Gradients coordinates should be transformed on use based on current matrix and not before, breaking => superseded by canvasity somehow
  • [ ] fillStyle should be saveable, breaking too
  • [x] add even-odd rule (savable state) in order to allows circles with holes
  • [x] bypass transform if just a translation? => not worth it
  • [ ] backport the new circle gradient from upstream dg2d, which is like in a browser Behaviour observed in both Chrome and Firefox.
  • [x] is it possible to blit on separate buffer then composite afterwards? In order to have more operations than source-over?
    • blitting white on black can makes a coverage mask! => yes, but only a few blend modes doable
  • [x] make extra sure no down reallocate are happening
  • [x] it should be possible to pass an ImageRef!L16 as destination. Colors should be converted L16 to RGBA8, using the 1/3 trick, and blitted back. This will allow to remove more oldschool draw.d methods => superseded by canvasity
  • [x] globalAlpha (non-optimal path), state-saveable => superseded by canvasity
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var grd = ctx.createRadialGradient(75, 50, 5, 90, 60, 100);
grd.addColorStop(0, "red");
grd.addColorStop(1, "white");
ctx.fillStyle = grd;
ctx.translate(20,0);
ctx.fillRect(10, 10, 150, 100);
ctx.translate(50,0);
ctx.fillRect(10, 120, 150, 100);
</script>
</body>
</html>
```


On second `fillRect` center of gradient is translated vs the first rectangle.
It is indeed more intuitive on use.
This will also allow to reuse gradients over several dirty rects.

I do'nt know how to do it in case of scale(x, y) with x different from y as then it's not circles anymore.

p0nce avatar Apr 27 '20 17:04 p0nce

But it gets much harder with scale since circles won't stay circles, this is actually supported in browsers. (EDIT: it worked, but wouldn't work if shearing was allowed)

p0nce avatar Apr 27 '20 17:04 p0nce

Point coord

  • [x] Use vec2f as alternative whenever possible.

p0nce avatar May 21 '20 11:05 p0nce

Reference for possible composite operations: https://www.w3schools.com/tags/playcanvas.php?filename=playcanvas_globalcompop

Is globalCompositeOperation implementable?

  • source-over the only one we support.

    • the rasterizer currently does: dest = dest * (1 - alpha) + alpha * src. If we do that on black, we obtain alpha * source color.
    • what happens to source alpha? Typically copied to dest alpha. So what we may have is: RGBA(source-red * source-alpha, source-green * source-alpha, source-blue * source-alpha, source-alpha) not clear all blitters will give that
    • now if source color is white, dst is black, then we can output source-alpha. But that wouldn't account for color and alpha of gradients separately. We would need a special blitter function that outputs RGBA(source-red, source-green, source-blue, source-alpha) instead of premultiplied? (or, we could unpremultiply lol)
  • source-atop: alpha of source should be premultiplied with alpha of dest.

  • source-in: alpha of destination multiplied with alpha of source, and alpha of source should be multiplied with alpha of dest.

  • source-out: alpha of dest taken instead of alpha of source

  • lighter: take max of dest and alpha*src (not sure what happens to alpha)

  • copy: only consider source

  • xor: alpha is down to zero if both alpha are 1

All explained in https://ssp.impulsetrain.com/porterduff.html

p0nce avatar Nov 26 '23 11:11 p0nce

From my understanding: image

  • We have only "Over" right now.
  • We could have "Xor" and "Atop" rather easily.
  • Desirable GIMP blending = Add, Multiply, Lighen Only, Darken Only, Divide, Grain Fusion, Difference, they would combine a blend mode and a porter-duff operator apparently. I think we can implement those instead of PorterDuff... all those for which source-alpha acts effectively like opacity.

p0nce avatar Nov 26 '23 13:11 p0nce

Implemented sourceOver, add, subtract. We don't follow html spec here, in that background alpha is always assumed to be opaque (= 255). (EDIT: added lighten and darken modes too) Eventually we could also add globalAlpha which also breaks the fast path. Well that's 5 interesting modes without unpremultiply or redo the blitters.

p0nce avatar Nov 26 '23 15:11 p0nce

image

p0nce avatar Nov 27 '23 15:11 p0nce