-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraphic.scm
344 lines (303 loc) · 11.2 KB
/
graphic.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
;;; ezd - easy drawing for X11 displays.
;;;
;;; A DRAWING is composed of GRAPHIC objects.
;* Copyright 1990-1993 Digital Equipment Corporation
;* All Rights Reserved
;*
;* Permission to use, copy, and modify this software and its documentation is
;* hereby granted only under the following terms and conditions. Both the
;* above copyright notice and this permission notice must appear in all copies
;* of the software, derivative works or modified versions, and any portions
;* thereof, and both notices must appear in supporting documentation.
;*
;* Users of this software agree to the terms and conditions set forth herein,
;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
;* right and license under any changes, enhancements or extensions made to the
;* core functions of the software, including but not limited to those affording
;* compatibility with other hardware or software environments, but excluding
;* applications which incorporate this software. Users further agree to use
;* their best efforts to return to Digital any such changes, enhancements or
;* extensions that they make and inform Digital of noteworthy uses of this
;* software. Correspondence should be provided to Digital at:
;*
;* Director of Licensing
;* Western Research Laboratory
;* Digital Equipment Corporation
;* 250 University Avenue
;* Palo Alto, California 94301
;*
;* This software may be distributed (but not offered for sale or transferred
;* for compensation) to third parties, provided such third parties agree to
;* abide by the terms and conditions of this notice.
;*
;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
;* SOFTWARE.
;;; Drawings are composed of GRAPHIC structures with the following fields:
;;;
;;; NAME object name or #f
;;; COMPUTE-BB procedure to compute the bounding box for the graphical
;;; object in X coordinates in terms of the *current-view*
;;; XDRAW procedure to draw the object into an X window via the
;;; current view.
;;; PSDRAW procedure to draw the object to a Postscript file via
;;; the current view.
;;; INTERSECT? boolean procedure to determine whether a bounding
;;; rectangle expressed in the drawings coordinate system
;;; intersects the object.
;;; EVENTS list of events specific to the graphical object.
;;; REDRAW-SEQ sequence number when object added to drawing.
(define-structure graphic
name
compute-bb
xdraw
psdraw
intersect?
(events '())
(redraw-seq *redraw-seq*))
(define-in-line-structure-access graphic
name
compute-bb
xdraw
psdraw
intersect?
events
redraw-seq)
;;; The slots of one graphical object are copied to another by the following
;;; function.
(define (set-graphic! to from)
(graphic-name! to (graphic-name from))
(graphic-compute-bb! to (graphic-compute-bb from))
(graphic-xdraw! to (graphic-xdraw from))
(graphic-psdraw! to (graphic-psdraw from))
(graphic-intersect?! to (graphic-intersect? from))
(graphic-events! to (graphic-events from))
(graphic-redraw-seq! to *redraw-seq*))
;;; A graphic is recognized as representing a clear object by having
;;; DRAW-CLEAR as it's XDRAW procedure.
(define (draw-clear) #t)
;;; The null graphic is a graphic that never intersects or draws.
(define null-graphic
(make-graphic 'null-graphic (lambda () '(0 0 0 0))
draw-clear draw-clear
(lambda (minx miny maxx maxy) #f)))
;;; A BBGRAPHIC represents the mapping of a GRAPHIC object into the current
;;; VIEW. It contains the following slots.
;;;
;;; GRAPHIC graphic object
;;; MINX bounding box in X coordinates for the graphic object
;;; MINY
;;; MAXX
;;; MAXY
(define-structure bbgraphic
graphic
(minx 0)
(miny 0)
(maxx 0)
(maxy (bbgraphic-bounding-box self)))
(define-in-line-structure-access bbgraphic
graphic
minx
miny
maxx
maxy)
(define (bbgraphic-bounding-box self)
(let* ((bb ((graphic-compute-bb (bbgraphic-graphic self))))
(minx (inexact->exact (floor (car bb))))
(miny (inexact->exact (floor (cadr bb))))
(maxx (inexact->exact (ceiling (caddr bb))))
(maxy (inexact->exact (ceiling (cadddr bb)))))
(bbgraphic-minx! self minx)
(bbgraphic-miny! self miny)
(bbgraphic-maxx! self maxx)
(bbgraphic-maxy! self maxy)
maxy))
;;; A BBGRAPHIC's bounding box is updated as required by the following
;;; procedure.
(define (update-bbgraphic bbg)
(let ((g (bbgraphic-graphic bbg)))
(if (eq? (graphic-redraw-seq g) *redraw-seq*)
(bbgraphic-bounding-box bbg))))
;;; A list of BBGRAPHICs is drawn to an X window via the current view by the
;;; following procedure.
(define (xdraw-bbgraphic-list bbgl)
(for-each (lambda (bbg) ((graphic-xdraw (bbgraphic-graphic bbg)))) bbgl))
;;; A BBGRAPHIC is drawn to an X window via the current view by the following
;;; procedure.
(define (xdraw-bbgraphic bbg) ((graphic-xdraw (bbgraphic-graphic bbg))))
;;; A list of BBGRAPHICs is drawn in Postscript via the current view by the
;;; following procedure.
(define (psdraw-bbgraphic-list bbgl)
(for-each (lambda (bbg) ((graphic-psdraw (bbgraphic-graphic bbg)))) bbgl))
;;; A BBGRAPHIC is drawn in Postscript to the current view by the following
;;; procedure.
(define (psdraw-bbgraphic bbg) ((graphic-psdraw (bbgraphic-graphic bbg))))
;;; The minimum and maximum of pairs of coordinates are computed by the
;;; following functions that allow one or both of the arguments to be #F.
(define (bbmin x y)
(if (and x y) (min x y) (or x y)))
(define (bbmax x y)
(if (and x y) (max x y) (or x y)))
;;; An ACTION is applied to all members of the BBGRAPHICs list intersecting a
;;; rectangle by the following procedure. The bounding box coordinates are
;;; X coordinates.
(define (bbgraphics-intersect bbgl minx miny maxx maxy action)
(if minx
(let loop ((bbgl bbgl))
(if (pair? bbgl)
(let* ((bbg (car bbgl))
(g (bbgraphic-graphic bbg)))
(if (eq? (graphic-redraw-seq g) *redraw-seq*)
(bbgraphic-bounding-box bbg))
(if (not (or (>= (bbgraphic-minx bbg) maxx)
(>= (bbgraphic-miny bbg) maxy)
(<= (bbgraphic-maxx bbg) minx)
(<= (bbgraphic-maxy bbg) miny)))
(action bbg))
(loop (cdr bbgl)))
#f))
#f))
;;; An ACTION is applied to all members of the BBGRAPHICs list not intersecting
;;; a rectangle by the following procedure. The bounding box coordinates are
;;; X coordinates.
(define (bbgraphics-not-intersect bbgl minx miny maxx maxy action)
(if minx
(let loop ((bbgl bbgl))
(if (pair? bbgl)
(let* ((bbg (car bbgl))
(g (bbgraphic-graphic bbg)))
(if (eq? (graphic-redraw-seq g) *redraw-seq*)
(bbgraphic-bounding-box bbg))
(if (or (>= (bbgraphic-minx bbg) maxx)
(>= (bbgraphic-miny bbg) maxy)
(<= (bbgraphic-maxx bbg) minx)
(<= (bbgraphic-maxy bbg) miny))
(action bbg))
(loop (cdr bbgl)))
#f))
#f))
;;; The top most object in a view that intersects a bounding box is returned
;;; by the following function. Objects currently drawn as well as objects to
;;; be drawn are examined.
(define (bbgraphics-really-intersect view minx miny maxx maxy)
(set-view view '())
(let ((uminx (min (x->user minx) (x->user maxx)))
(uminy (min (y->user miny) (y->user maxy)))
(umaxx (max (x->user minx) (x->user maxx)))
(umaxy (max (y->user miny) (y->user maxy))))
(let loop ((bbgl (view-bb-head view)) (match #f))
(if (pair? bbgl)
(let* ((bbg (car bbgl))
(g (bbgraphic-graphic bbg)))
(if (eq? (graphic-redraw-seq g) *redraw-seq*)
(bbgraphic-bounding-box bbg))
(if (or (>= (bbgraphic-minx bbg) maxx)
(>= (bbgraphic-miny bbg) maxy)
(<= (bbgraphic-maxx bbg) minx)
(<= (bbgraphic-maxy bbg) miny)
(not ((graphic-intersect? g) uminx uminy umaxx
umaxy)))
(loop (cdr bbgl) match)
(loop (cdr bbgl) g)))
(let loop ((gl (if (view-new view)
(drawing-head (view-drawing view))
(drawing-added-head (view-drawing view))))
(match match))
(if (pair? gl)
(let* ((g (car gl))
(bbox ((graphic-compute-bb g))))
(if (or (>= (car bbox) maxx)
(>= (cadr bbox) maxy)
(<= (caddr bbox) minx)
(<= (cadddr bbox) miny)
(not ((graphic-intersect? g) uminx
uminy umaxx umaxy)))
(loop (cdr gl) match)
(loop (cdr gl) g)))
match))))))
;;; Named graphical objects are constructed by the following function.
(define (ezd-object name commands)
(let* ((gl (let loop ((cl commands))
(if (pair? cl)
(let ((g (ezd-one (car cl))))
(if (isa-graphic? g)
(cons g (loop (cdr cl)))
(begin (ezd-error 'ezd-object
"OBJECTs may only contain graphics commands: ~s"
(car cl))
(loop (cdr cl)))))
'())))
(clear (let loop ((gl gl))
(if (pair? gl)
(and (eq? (graphic-xdraw (car gl)) draw-clear)
(loop (cdr gl)))
#t))))
(define (bb-really-intersect? uminx uminy umaxx umaxy)
(let* ((x1 (user->x uminx))
(y1 (user->y uminy))
(x2 (user->x umaxx))
(y2 (user->y umaxy))
(xminx (min x1 x2))
(xminy (min y1 y2))
(xmaxx (max x1 x2))
(xmaxy (max y1 y2)))
(let loop ((gl gl))
(if (null? gl)
#f
(or (let ((bb ((graphic-compute-bb
(car gl)))))
(and (not (or (>= (car bb) xmaxx)
(>= (cadr bb) xmaxy)
(<= (caddr bb) xminx)
(<= (cadddr bb)
xminy)))
((graphic-intersect? (car gl))
uminx uminy umaxx umaxy)))
(loop (cdr gl)))))))
(case (length gl)
((0) (make-graphic
name
(lambda () '(0 0 0 0))
draw-clear
draw-clear
(lambda (minx miny maxx maxy) #f)))
((1) (graphic-name! (car gl) name)
(car gl))
(else (make-graphic
name
(lambda ()
(let loop ((gl gl) (minx #f) (miny #f)
(maxx #f) (maxy #f))
(if (pair? gl)
(let ((bb ((graphic-compute-bb
(car gl)))))
(loop (cdr gl)
(bbmin minx (car bb))
(bbmin miny (cadr bb))
(bbmax maxx (caddr bb))
(bbmax maxy
(cadddr bb))))
(list minx miny maxx maxy))))
(if clear
draw-clear
(lambda () (for-each
(lambda (g) ((graphic-xdraw g)))
gl)))
(if clear
draw-clear
(lambda () (for-each
(lambda (g) ((graphic-psdraw g)))
gl)))
bb-really-intersect?)))))
(define-ezd-command
`(object ,(lambda (x) (and (symbol? x) (not (eq? x '*)))) (repeat ,any?))
"(object name commands...)"
ezd-object)
;;; Module reset/initialization procedure.
(define (graphic-module-init)
#t)