(define image.read-object! (lambda (image port) (let* ((type (read port)) (stroked? (list.contains? (list "empty ellipse" "empty circle" "empty rectangle" "empty square" "line") type)) (color (read port)) (brush (if stroked? (read port) (envt.get-brush)))) (cond ; If we are at eof, return eof. ((eof-object? type) type) ; Otherwise, there is more to draw. (else ; Set the color and brush. (envt.set-fgcolor! (cname->rgb color)) (envt.set-brush! brush) ; Select the shape type, read the remaining data, and draw it. (cond ((list.contains? (list "empty ellipse" "filled ellipse") type) (let* ((left (read port)) (top (read port)) (width (read port)) (height (read port))) (image.select-ellipse! image selection.replace left top width height) (if stroked? (image.stroke! image) (image.fill! image)) (image.select-nothing! image))) ((list.contains? (list "empty circle" "filled circle") type) (let* ((left (read port)) (top (read port)) (diameter (read port))) (image.select-ellipse! image selection.replace left top diameter diameter) (if stroked? (image.stroke! image) (image.fill! image)) (image.select-nothing! image))) ((list.contains? (list "empty rectangle" "filled rectangle") type) (let* ((left (read port)) (top (read port)) (width (read port)) (height (read port))) (image.select-rectangle! image selection.replace left top width height) (if stroked? (image.stroke! image) (image.fill! image)) (image.select-nothing! image))) ((list.contains? (list "empty square" "filled square") type) (let* ((left (read port)) (top (read port)) (side (read port))) (image.select-rectangle! image selection.replace left top side side) (if stroked? (image.stroke! image) (image.fill! image)) (image.select-nothing! image))) ((equal? type "line") (let* ((start-col (read port)) (start-row (read port)) (end-col (read port)) (end-row (read port))) (image.draw-line! image start-col start-row end-col end-row))))))))) (define image.read-objects! (lambda (image filename) (let kernel ((in-port (open-input-file filename))) (cond ; If we are at the end of the file, close the port and return the image. ((eof-object? (peek-char in-port)) (close-input-port in-port) image) ; Otherwise, read the next object and recursively call the kernel. (else (image.read-object! image in-port) (kernel in-port)))))) (define list.contains? (lambda (lst val) (and (not (null? lst)) (or (equal? (car lst) val) (list.contains? (cdr lst) val))))) (define empty-ellipse.write (lambda (port color brush left top width height) (write "empty ellipse" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write brush port) (display " " port) (write left port) (display " " port) (write top port) (display " " port) (write width port) (display " " port) (write height port) (newline port))) (define filled-ellipse.write (lambda (port color left top width height) (write "filled ellipse" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write left port) (display " " port) (write top port) (display " " port) (write width port) (display " " port) (write height port) (newline port))) (define empty-circle.write (lambda (port color brush left top diameter) (write "empty circle" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write brush port) (display " " port) (write left port) (display " " port) (write top port) (display " " port) (write diameter port) (newline port))) (define filled-circle.write (lambda (port color left top diameter) (write "filled circle" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write left port) (display " " port) (write top port) (display " " port) (write diameter port) (newline port))) (define empty-rectangle.write (lambda (port color brush left top width height) (write "empty rectangle" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write brush port) (display " " port) (write left port) (display " " port) (write top port) (display " " port) (write width port) (display " " port) (write height port) (newline port))) (define filled-rectangle.write (lambda (port color left top width height) (write "filled rectangle" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write left port) (display " " port) (write top port) (display " " port) (write width port) (display " " port) (write height port) (newline port))) (define empty-square.write (lambda (port color brush left top side) (write "empty square" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write brush port) (display " " port) (write left port) (display " " port) (write top port) (display " " port) (write side port) (newline port))) (define filled-square.write (lambda (port color left top side) (write "filled square" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write left port) (display " " port) (write top port) (display " " port) (write side port) (newline port))) (define line.write (lambda (port color brush start-col start-row end-col end-row) (write "line" port) (display " " port) (write (if (rgb? color) (rgb->cname color) color) port) (display " " port) (write brush port) (display " " port) (write start-col port) (display " " port) (write start-row port) (display " " port) (write end-col port) (display " " port) (write end-row port) (newline port)))