MetaPost outputs PostScript, and PostScript draws solid areas (I think). So, transparency may not be achieved without drawing anew background picture. That's heavy, memory consuming and certainly not elegant.
Suppose that a
currentpicture is given.
You want to put on this picture some filled cycle path
c with color
What would be nice is extracting exactly what in
currentpicture is enclosed within
c; then draw this with a
color which would be intermediate between
yourcolor and the original color.
If it was possible to remove the previous picture
enclosed within the path
c as it
may happen for pixelized output, it would be very
nice nice since it would mean that the output's size
wouldn't grow to much.
In one of John Hobby's manuals is described the way to extract informations from the currentpicture, especially the control sequence
for <symbolic token> within <picture>.
currentpicture, a cycle path
c, a transparency factor
transparency and a color
yourcolor. What I may do is:
cwith the background color and take care that it will be at the back most level. The reason for that will be clear later.
currentpicture, draw this subpicture into a temporary picture with some intermediate color.
The reason for having added some blank picture at the begining
is that when the path covers the background, it should be visible.
So that this part must exist within the
% % settings % color yourcolor; yourcolor=red; transparency:=0.75; % % usage: transparentfill <cyclic path>; % vardef transparentfill expr c= save p_; picture p_; p_=currentpicture; currentpicture:=nullpicture; fill c withcolor background; addto currentpicture also p_; p_:=nullpicture; for p within currentpicture: addto p_ also p withcolor transparency[yourcolor,(redpart p,greenpart p,bluepart p)]; endfor clip p_ to c; draw p_; enddef;
A sample. Just the one on the right.
Why is it so bad? Try to fill two transparent areas that overlay. Their intersection will be opaque. Let's see why.
Suppose given a usual picture (no clipped area).
First fill cyclic path
sequence. This will add on top of the
currentpicture a plain subpicture
p1 whose nature is quite different
from usual pictures (solid filled areas, strokes,
...): it is a clipped picture.
Now fill cyclic path
c2 with the
control sequence. Processing
first will come the original
which will be treated right as before. At last will
p1 which will be seen a single
object whose contour is
c1 and color
Now you can guess what will
happen: to the temporary picture
is added the contour
c1 filled with
an intermediate color between black and
c2 to obtain, say,
and added to
currentpicture which is now equal
originalpicture + p1 + p2 (order matters),
and which is not what you wanted it to be.
Fortunately, there exists a boolean valued operator
clipped, so that it is possible
in the previous loop to detect whether
is a clipped picture or not. If it is, one has to
examin it deeper (and here comes recursivity).
The following code makes that
stuff. It is quite heavy and non-elegant. In fact,
since there is a very little documentation about
MetaPost processing, I just made some
random-binary-script-writting. The fact is that it
seems to work (it will be improved).
color yourcolor; yourcolor:=blue; picture AlphaPict; AlphaPict=nullpicture; Alpha:=0.25; def AlphaFill expr c= AlphaPict:=nullpicture; AlphaPicture(currentpicture,c); addto currentpicture also AlphaPict; enddef; vardef AlphaPicture(expr p,c)= save p_; picture p_; p_=nullpicture; addto p_ contour c withcolor Alpha[background,yourcolor]; for p__ within p: if (not clipped p__) and (not bounded p__): addto p_ also p__ withcolor Alpha[(redpart p__,greenpart p__,bluepart p__),yourcolor]; else: begingroup save AlphaPict; picture AlphaPict; AlphaPict=nullpicture; AlphaPicture(p__,pathpart p__); addto p_ also AlphaPict; endgroup; fi endfor clip p_ to c; addto AlphaPict also p_; enddef;
Just the one on the right.
That's my usual Dangerous sign. I've filled
four partially overlapping squares.
A simple thing to do in order to improve previous code is to draw subpicture if and only if its bounding box intersects the bounding box of the path. Here is more or less the code implemented in my statsmac package.
picture alphapict_; alphapict_=nullpicture; color fillcolor; fillcolor=red; fgalpha := 0.5; % usual alpha parameter bgalpha:= 1; % alpha parameter with respect to the background vardef alphafill expr c = alphapict_ := nullpicture; alphafill_(currentpicture, c); addto currentpicture also alphapict_; enddef; def alphafill_(expr p, c) = begingroup save p_, xmax_, xmin_, ymax_, ymin_; picture p_; p_ = nullpicture; (xmin_, ymin_) = llcorner c; (xmax_, ymax_) = urcorner c; addto p_ contour c withcolor bgalpha[background, fillcolor]; for p__ within p: numeric xmin__, xmax__, ymin__, ymax__; (xmin__, ymin__) = llcorner p__; (xmax__, ymax__) = urcorner p__; if (xmax__<= xmin_) or (xmin__ >= xmax_): else: if (ymax__<= ymin_) or (ymin__ >= ymax_): else: if (not clipped p__) and (not bounded p__): addto p_ also p__ withcolor fgalpha[(redpart p__, greenpart p__, bluepart p__), fillcolor]; else: begingroup save alphapict_; picture alphapict_; alphapict_ = nullpicture; alphafill_(p__, pathpart p__); addto p_ also alphapict_; endgroup; fi fi fi endfor clip p_ to c; addto alphapict_ also p_; endgroup; enddef;
A sample. Just the one on the right. That's some local building. I replace the sphere by a transparent cube (lighter). One should notice that the text is made of clipped and transformed text pictures (that's postscript fonts, I did not try bitmap fonts yet), so that the macro seems to work quite well.
If you have some better ideas, let me know!