Graphics Output Device; Baseline Test Cases

test[0]=>,(use graphics.device)
test[1]=>

We need graphics.geometry in order to pass most arguments to the graphics device.

test[1]=>,(use graphics.geometry)
test[2]=>

The first thing to do is create an graphics output device. In the case of an EPS device, you are obliged to supply the bounding box when opening the device. However, see open-bbox-device for a way to find the bounding box from a set of drawing commands.

test[2]=>(define p (open-eps-device "test001.eps" (make-rect 0 0 100 50)))
value := p
test[3]=>

If you know PostScript, this will seem eerily familiar. Or maybe not so eerie...

test[3]=>(moveto p (make-point 10 10))
test[4]=>(lineto p (make-point 90 40))
test[5]=>(lineto p (make-point 10 30))
test[6]=>(stroke p)
test[7]=>(close-graphics-device p)
test[8]=>

That's it. Here's the resulting EPS file converted to a PNG:

Here is a somewhat more interesting example, but nothing really new.

test[8]=>(define (star dev n r0 r1)
           (for-each 
             (lambda (i)
               (let* ((r (if (even? i) r0 r1))
                      (angle (* i (/ (* 2 $Pi) n)))
                      (pt (make-point (* (cos angle) r) (* (sin angle) r))))
                 (if (= i 0)
                     (moveto dev pt)
                     (lineto dev pt))))
             (range n))
           (closepath dev))
value := star
test[9]=>(define p (open-eps-device "test002.eps" (make-rect 0 0 110 110)))
value := p
test[10]=>(translate p (make-point 55 55))
test[11]=>(star p 10 25 50)
test[12]=>(with-gstate-saved
           p
           (lambda ()
            (setlinewidth p 3)
            (setlinecap p 'round)
            (setdash p '#(0 5) 0)
            (stroke p)))
test[13]=>(setlinewidth p 0.5)
test[14]=>(stroke p)
test[15]=>(star p 10 15 40)
test[16]=>(setlinewidth p 1)
test[17]=>(setcolor p (device-color p '(rgb 0 0 1)))
test[18]=>(stroke p)
test[19]=>(close-graphics-device p)
test[20]=>

Here's the result:

Computing Bounding Boxes

Remember I said that open-bbox-device could be used to figure out the bounding box for a set of drawing commands? The way that works is you create a virtual graphics device whose job is to accumulate drawing commands and pay attention to how much they paint.

( Note : The bbox device does not pay attention to clipping paths yet, so clipped drawing will still count against the bounding box)

First, for convenience, we'll wrap our entire drawing into a single procedure which just takes a graphics device object onto which to render. That's because we're going to invoke it twice, once for the bbox virtual device and again for the real output.

test[20]=>(define (drawme dev)
            ;; this is the same drawing as before, except I've shifted
            ;; the origin because my eps->png converter doesn't like negative 
            ;; bboxes
            (translate dev (make-point 100 100))
            (star dev 10 25 50)
            (with-gstate-saved
             dev
             (lambda ()
               (setlinewidth dev 3)
               (setlinecap dev 'round)
               (setdash dev '#(0 5) 0)
               (stroke dev)))
            (setlinewidth dev 0.5)
            (stroke dev)
            (star dev 10 15 40)
            (setlinewidth dev 1)
            (setcolor dev (device-color dev '(rgb 0 0 1)))
            (stroke dev))
value := drawme
test[21]=>

The call to close-graphics-device for the bbox device returns the accumulated bounding box.

test[21]=>(define r (let ((p (open-bbox-device)))
                      (drawme p)
                      (close-graphics-device p)))
value := r
test[22]=>r
value := #[<rect> 48.5 50.9472 x 93.4508 98.1057]
test[23]=>(let ((p (open-eps-device "test003.eps" r)))
            (drawme p)
            (close-graphics-device p))
test[24]=>

Here's the result:

Let's make a bigger canvas and draw that explicitly.

test[24]=>(let ((p (open-eps-device "test004.eps" (inset-rect r -20 -20))))
            (with-gstate-saved
             p
             (lambda ()
               (setlinewidth p 0.1)
               (setcolor p (device-color p '(rgb 1 0 0)))
               (rectstroke p r)))
            (drawme p)
            (close-graphics-device p))

Now it's easier to see where the bounding box wound up. If you look closely at the EPS file using GhostView, there appears to be a small margin around the shape; that's because the bbox device is taking into account the line width but not the dashing or linecaps.

Executed using RScheme (v0.7.3.3-b24u, 2005-02-24) at 2005-02-24 13:37:58 CST