test=>,(use graphics.device) test=>
graphics.geometry in order to
pass most arguments to the graphics device.
test=>,(use graphics.geometry) test=>
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=>(define p (open-eps-device "test001.eps" (make-rect 0 0 100 50))) value := p test=>
If you know PostScript, this will seem eerily familiar. Or maybe not so eerie...
test=>(moveto p (make-point 10 10)) test=>(lineto p (make-point 90 40)) test=>(lineto p (make-point 10 30)) test=>(stroke p) test=>(close-graphics-device p) test=>
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=>(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=>(define p (open-eps-device "test002.eps" (make-rect 0 0 110 110))) value := p test=>(translate p (make-point 55 55)) test=>(star p 10 25 50) test=>(with-gstate-saved p (lambda () (setlinewidth p 3) (setlinecap p 'round) (setdash p '#(0 5) 0) (stroke p))) test=>(setlinewidth p 0.5) test=>(stroke p) test=>(star p 10 15 40) test=>(setlinewidth p 1) test=>(setcolor p (device-color p '(rgb 0 0 1))) test=>(stroke p) test=>(close-graphics-device p) test=>
Here's the result:
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
( 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=>(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=>
The call to
the bbox device returns the accumulated bounding box.
test=>(define r (let ((p (open-bbox-device))) (drawme p) (close-graphics-device p))) value := r test=>r value := #[<rect> 48.5 50.9472 x 93.4508 98.1057] test=>(let ((p (open-eps-device "test003.eps" r))) (drawme p) (close-graphics-device p)) test=>
Here's the result:
Let's make a bigger canvas and draw that explicitly.
test=>(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.