[Tex/LaTex] Draw a transparent box (over a grid)

metaposttransparency

How can I draw a transparent box in Metafont? I would like to have something like the legend in this graph: https://de.wikipedia.org/wiki/Datei:Articlecount_topten_wikipedia.svg. You could say I want to "override" the background (in the example above the grid) of the box with transparency.

Best Answer

[I'm assuming we are talking MetaPost rather than MetaFont].

You can do transparency in MetaPost by iterating over all the components of a picture and re-colouring them appropriately. Here's an example of a grid and simple transparent rectangle.

enter image description here

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);
% parameters
u = 1cm;
ymax = xmax = 2.75;
xmin = ymin = -2.75;

% make a plain grid
path xx, yy;
xx = ((xmin,0) -- (xmax,0)) scaled u;
yy = ((0,ymin) -- (0,ymax)) scaled u;

drawoptions(dashed evenly scaled .5 withcolor .7 white);
for i = ceiling ymin upto floor ymax: draw xx shifted (0,i*u); endfor
for i = ceiling xmin upto floor xmax: draw yy shifted (i*u,0); endfor

drawoptions(withpen pencircle scaled .7);
xx := xx scaled 1.05;
yy := yy scaled 1.05;
drawarrow xx;
drawarrow yy;
drawoptions();

label.rt (btex $x$ etex, point infinity of xx);
label.top(btex $y$ etex, point infinity of yy);

% draw the "transparent" box
path box; box = unitsquare shifted 1/2 down shifted 1/4 left scaled 3cm;

alpha = 5/8;  % alpha: 0=invisible, 1=opaque
color filler; filler = .95[blue,white];
picture bg, fg; 
bg = currentpicture; % save the current pic *before* filling the box
fg = image( 
  for e within bg:
    draw e if 5=colormodel e: withcolor alpha[colorpart e, filler] fi;
  endfor
);
clip fg to box; 

fill box withcolor filler;  
draw fg;
draw box;

endfig;
end.

Notes

Given a picture variable p the syntax for e within p steps through all the components of the picture p. Each e is also a picture variable. colormodel e returns the colour model being used for the element; 5 means the usual RGB colours, 0 means it's not coloured. colorpart e returns the colour of the element.

So what the loop does is redraw everything in the saved copy of the current picture, and for each element that's coloured using an RGB colour it recolours it using a colour that is alpha of the way between the original colour and the colour used as a filler. This creates an approximate illusion of transparency.

It's tempting to write for e within currentpicture but for some unknown reason, this does not work. You have to save currentpicture to a picture variable and then step through that.