racket / htdp

Other
91 stars 69 forks source link

Support for transparent overlays #175

Open mikekben opened 2 years ago

mikekben commented 2 years ago

Is it possible to add support for an overlay-like operation of "erasing" by overlaying a transparent image? For example, this would be useful for overlaying a doughnut shape over a colorful background while maintaining the background behind the center of the doughnut:

(overlay
 (circle 30 'solid 'green)
 (circle 50 'solid 'red)
 (above (rectangle 200 100 'solid 'green)
        (rectangle 200 100 'solid 'blue)))

but with a transparent rather than solid green background for the center of the doughnut shape, allowing the green-blue split to be visible. I can think of two ways to expand the API to support this functionality:

Looking through the existing API, it seems that implementing this functionality could closely follow the existing overlay implementation, but I hope that others can suggest some additional feedback and propose better ways to proceed!

rfindler commented 2 years ago

The library is built on top of dc<%>, which is itself built on top of platform-specific drawing code provided by the underlying operating system. So I think that an operation that would require, eg, actually calculating where circles get drawn is probably not on the table. That said, there may be some more clever way to use regions and clipping or just the existing calls somehow to get this effect, I'm not sure.

sorawee commented 2 years ago

Specifically for donut, you can kinda hack it by using pen.

Screen Shot 2022-09-12 at 11 55 30 AM
(define donut
  (circle 20
          "outline"
          (make-pen "goldenrod" 10 "solid" "round" "round")))

(overlay donut
         (triangle 200 "solid" "red"))
rfindler commented 2 years ago

Thinking a little bit more about this, it may be possible to leverage the fact that the clipping region in the underlying dc is a region (which supports union operations with anything that can be drawn via a path) that might allow something cool to be done here. I'm probably not going to tackle it soon but just thought I'd mention it.