% Toby Thurston -- 16 Apr 2021 
% Draw a kitsch picture frame round a rectangular path

color gold, dark, grey;
gold = 1/256(243, 197, 127);
dark = 1/256(144, 87, 50);
grey = 1/256(156, 147, 138);

picture ball; ball = image(for i=0 upto 16:
  fill interpath(i/16, 
      fullcircle scaled 10, 
      fullcircle scaled 3 shifted (-2, 2)
  ) withcolor (i/16)[gold, 15/16 white];
endfor) scaled 1/4;

newinternal pf_width; pf_width := 21;

vardef frame expr P = 
    save base, side, f, t, u, xx; 
    picture base, side; path f; numeric t, u, xx;

    t = arclength subpath (0,1) of bbox P;
    u = arclength subpath (1,2) of bbox P;
    xx = max(t, u) + 2 pf_width;
    f = unitsquare xscaled xx yscaled pf_width;

    % convenience / nonce function
    vardef paint_strip(expr y, wd, shade) =
        draw subpath (0, 1) of f 
            shifted (0, if y < 0: pf_width + fi y)
            withpen pencircle scaled wd
            withcolor shade
    enddef;

    base = image(
      % background colour
      fill f withcolor gold;
      % grey strips
      paint_strip(2,    3,   5/4 grey);
      paint_strip(3.5,  1/4, grey);
      paint_strip(5,    1/4, 1/2[gold, dark]);
      paint_strip(-6.5, 1/4, 1/2[gold, dark]);
      paint_strip(-6,   1/4, 1/2[gold, dark]);
      paint_strip(-2,   2,   5/4 grey);
      % spatter with random spots
      for i=0 upto 4 * arclength(subpath (0,1) of f):
        fill fullcircle scaled uniformdeviate 3/4
          shifted (uniformdeviate xx, uniformdeviate pf_width)
          withcolor dark;
      endfor
      % decorative balls
      for x = 2 step 3 until xx:
        draw ball shifted (x, 2);
      endfor
    );

    % make two trapezium shapes
    side = base;
    clip side to (pf_width, 0) -- (pf_width + u, 0) 
              -- (2 pf_width + u, pf_width) -- (0, pf_width) -- cycle;
    clip base to (pf_width, 0) -- (pf_width + t, 0) 
              -- (2 pf_width + t, pf_width) -- (0, pf_width) -- cycle;

    % arrange the pieces into a square
    image(
      draw base rotated 180 shifted point 1 of bbox P shifted (+pf_width, 0);
      draw base rotated   0 shifted point 3 of bbox P shifted (-pf_width, 0);
      draw side rotated  90 shifted point 0 of bbox P shifted (0, -pf_width);
      draw side rotated 270 shifted point 2 of bbox P shifted (0, +pf_width);
    )
enddef;
