PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/view.sc

https://bitbucket.org/bunny351/ezd
Scala | 805 lines | 731 code | 74 blank | 0 comment | 9 complexity | b64a080e0d453e6b037334fe48bdba73 MD5 | raw file
  1. ;;; ezd - easy drawing for X11 displays.
  2. ;;;
  3. ;;; A VIEW object maps a DRAWING onto a WINDOW object.
  4. ;* Copyright 1990-1993 Digital Equipment Corporation
  5. ;* All Rights Reserved
  6. ;*
  7. ;* Permission to use, copy, and modify this software and its documentation is
  8. ;* hereby granted only under the following terms and conditions. Both the
  9. ;* above copyright notice and this permission notice must appear in all copies
  10. ;* of the software, derivative works or modified versions, and any portions
  11. ;* thereof, and both notices must appear in supporting documentation.
  12. ;*
  13. ;* Users of this software agree to the terms and conditions set forth herein,
  14. ;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
  15. ;* right and license under any changes, enhancements or extensions made to the
  16. ;* core functions of the software, including but not limited to those affording
  17. ;* compatibility with other hardware or software environments, but excluding
  18. ;* applications which incorporate this software. Users further agree to use
  19. ;* their best efforts to return to Digital any such changes, enhancements or
  20. ;* extensions that they make and inform Digital of noteworthy uses of this
  21. ;* software. Correspondence should be provided to Digital at:
  22. ;*
  23. ;* Director of Licensing
  24. ;* Western Research Laboratory
  25. ;* Digital Equipment Corporation
  26. ;* 250 University Avenue
  27. ;* Palo Alto, California 94301
  28. ;*
  29. ;* This software may be distributed (but not offered for sale or transferred
  30. ;* for compensation) to third parties, provided such third parties agree to
  31. ;* abide by the terms and conditions of this notice.
  32. ;*
  33. ;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  34. ;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  35. ;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  36. ;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  37. ;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  38. ;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  39. ;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  40. ;* SOFTWARE.
  41. (module view)
  42. (include "struct.sch")
  43. (include "display.sch")
  44. (include "window.sch")
  45. (include "drawing.sch")
  46. (include "graphic.sch")
  47. (include "commands.sch")
  48. (include "events.sch")
  49. (include "xternal.sch")
  50. ;;; Creates a VIEW composed of the following fields:
  51. ;;;
  52. ;;; DRAWING-NAME drawing name associated with the view.
  53. ;;; WINDOW-NAME window name associated with the view.
  54. ;;; CLIP-MINX X window bounding box for the view or #f.
  55. ;;; CLIP-MINY
  56. ;;; CLIP-MAXX
  57. ;;; CLIP-MAXY
  58. ;;; DRAWING drawing associated with the view.
  59. ;;; WINDOW window associated with the view.
  60. ;;; USER->X convert user x coordinate to X coordinate system.
  61. ;;; USER->Y convert user y coordinate to X coordinate system.
  62. ;;; USER->LW convert user line width coordinate to X pixels.
  63. ;;; X->USER convert X x coordinate to user coordinate system.
  64. ;;; Y->USER convert X y coordinate to user coordinate system.
  65. ;;; USER->WIDTH convert user x units to X pixels.
  66. ;;; USER->HEIGHT convert user y units to X pixels.
  67. ;;; WIDTH->USER convert X pixels to user x units.
  68. ;;; HEIGHT->USER convert X pixels to user y units.
  69. ;;; ORIGINX X coordinates for drawing's origin.
  70. ;;; ORIGINY
  71. ;;; SCALEX Scale factors to convert drawing units to X.
  72. ;;; SCALEY
  73. ;;; SCALELW
  74. ;;; NEW indicates that this is a newly created view.
  75. ;;; BB-HEAD head of list of BBGRAPHICs in the view.
  76. ;;; BB-TAIL tail of list of BBGRAPHICS in the view.
  77. ;;; STIPPLE-X X coordinates of stipple offset
  78. ;;; STIPPLE-Y
  79. ;;; NEW-TRANSFORM argument list for new transformation
  80. (define-structure VIEW
  81. drawing-name
  82. window-name
  83. (clip-minx #f)
  84. (clip-miny #f)
  85. (clip-maxx #f)
  86. (clip-maxy #f)
  87. (drawing (define (view-drawing self)
  88. (name->drawing (view-drawing-name self)))
  89. #f)
  90. (window (define (view-window self)
  91. (name->window (view-window-name self)))
  92. #f)
  93. (user->x (lambda (x) (inexact->exact x)))
  94. (user->y (lambda (x) (inexact->exact x)))
  95. (user->lw (lambda (x) (if x (inexact->exact x) 0)))
  96. (x->user (lambda (x) x))
  97. (y->user (lambda (x) x))
  98. (user->width (lambda (x) (inexact->exact x)))
  99. (user->height (lambda (x) (inexact->exact x)))
  100. (width->user (lambda (x) x))
  101. (height->user (lambda (x) x))
  102. (originx 0)
  103. (originy 0)
  104. (scalex 1)
  105. (scaley 1)
  106. (scalelw 1)
  107. (new #t)
  108. (bb-head '())
  109. (bb-tail '())
  110. (stipple-x 0)
  111. (stipple-y 0)
  112. (new-transform #f))
  113. (define-in-line-structure-access VIEW
  114. drawing-name
  115. window-name
  116. clip-minx
  117. clip-miny
  118. clip-maxx
  119. clip-maxy
  120. #f
  121. #f
  122. user->x
  123. user->y
  124. user->lw
  125. x->user
  126. y->user
  127. user->width
  128. user->height
  129. width->user
  130. height->user
  131. originx
  132. originy
  133. scalex
  134. scaley
  135. scalelw
  136. new
  137. bb-head
  138. bb-tail
  139. stipple-x
  140. stipple-y
  141. new-transform)
  142. ;;; All procedures that draw into objects assume a "current view". The
  143. ;;; information related to the current view is stored in the following
  144. ;;; global variables.
  145. (define *CURRENT-VIEW* #f)
  146. (define *WINDOW* #f) ;;; From the WINDOW object.
  147. (define *WIDTH* #f)
  148. (define *HEIGHT* #f)
  149. (define *NAME* #f)
  150. (define *FOREGROUND-NAME* #f)
  151. (define *BACKGROUND-NAME* #f)
  152. (define *FOREGROUND* #f)
  153. (define *BACKGROUND* #f)
  154. (define *XWINDOW* #f)
  155. (define USER->X #f) ;;; From the VIEW object.
  156. (define USER->Y #f)
  157. (define USER->LW #f)
  158. (define X->USER #f)
  159. (define Y->USER #f)
  160. (define USER->WIDTH #f)
  161. (define USER->HEIGHT #f)
  162. (define WIDTH->USER #f)
  163. (define HEIGHT->USER #f)
  164. (define STIPPLE-X #f)
  165. (define STIPPLE-Y #f)
  166. (define *CLIP-BBL* #f) ;;; From the call to SET-VIEW.
  167. ;;; The current view is swapped by the following function. One can force
  168. ;;; the cached values to be returned to their structure by supplying #f as the
  169. ;;; argument. The previous value of *CURRENT-VIEW* is returned as the
  170. ;;; value of the function.
  171. (define (SET-VIEW cview clip-bbl)
  172. (unless (eq? cview *current-view*)
  173. (when *current-view*
  174. (view-user->x! *current-view* user->x)
  175. (view-user->y! *current-view* user->y)
  176. (view-user->lw! *current-view* user->lw)
  177. (view-x->user! *current-view* x->user)
  178. (view-y->user! *current-view* y->user)
  179. (view-user->width! *current-view* user->width)
  180. (view-user->height! *current-view* user->height)
  181. (view-width->user! *current-view* width->user)
  182. (view-height->user! *current-view* height->user)
  183. (view-stipple-x! *current-view* stipple-x)
  184. (view-stipple-y! *current-view* stipple-y))
  185. (when cview
  186. (set! user->x (view-user->x cview))
  187. (set! user->y (view-user->y cview))
  188. (set! user->lw (view-user->lw cview))
  189. (set! x->user (view-x->user cview))
  190. (set! y->user (view-y->user cview))
  191. (set! user->width (view-user->width cview))
  192. (set! user->height (view-user->height cview))
  193. (set! width->user (view-width->user cview))
  194. (set! height->user (view-height->user cview))
  195. (set! stipple-x (view-stipple-x cview))
  196. (set! stipple-y (view-stipple-y cview))
  197. (set! *current-drawing* (view-drawing cview))
  198. (set! *window* (view-window cview))
  199. (set! *width* (window-width *window*))
  200. (set! *height* (window-height *window*))
  201. (set! *name* (window-name *window*))
  202. (set! *foreground-name* (window-foreground-name *window*))
  203. (set! *background-name* (window-background-name *window*))
  204. (set! *foreground* (window-foreground *window*))
  205. (set! *background* (window-background *window*))
  206. (set! *xwindow* (window-xwindow *window*))))
  207. (let ((return *current-view*))
  208. (set! *current-view* cview)
  209. (if cview (set! *clip-bbl*
  210. (let ((clipped (clip-bbl-to-view cview clip-bbl)))
  211. (if (and (null? clipped) (view-clip-minx cview))
  212. (list (list (view-clip-minx cview)
  213. (view-clip-miny cview)
  214. (view-clip-maxx cview)
  215. (view-clip-maxy cview)))
  216. clipped))))
  217. return))
  218. ;;; A bounding box list is clipped to a view by the following procedure. A
  219. ;;; newly constructed list of bounding boxes is returned.
  220. (define (CLIP-BBL-TO-VIEW view bbl)
  221. (if (view-clip-minx view)
  222. (let ((clip-minx (view-clip-minx view))
  223. (clip-miny (view-clip-miny view))
  224. (clip-maxx (view-clip-maxx view))
  225. (clip-maxy (view-clip-maxy view)))
  226. (let loop ((bbl bbl))
  227. (if (pair? bbl)
  228. (let* ((bb (car bbl))
  229. (minx (car bb))
  230. (miny (cadr bb))
  231. (maxx (caddr bb))
  232. (maxy (cadddr bb)))
  233. (if (or (<= maxx clip-minx)
  234. (<= maxy clip-miny)
  235. (>= minx clip-maxx)
  236. (>= miny clip-maxy))
  237. (loop (cdr bbl))
  238. (cons (list (max minx clip-minx)
  239. (max miny clip-miny)
  240. (min maxx clip-maxx)
  241. (min maxy clip-maxy))
  242. (loop (cdr bbl)))))
  243. '())))
  244. bbl))
  245. ;;; A bounding box is clipped to a view by the following procedure. Either a
  246. ;;; bounding box of #f is returned.
  247. (define (CLIP-BB-TO-VIEW view minx miny maxx maxy)
  248. (if (view-clip-minx view)
  249. (let ((clip-minx (view-clip-minx view))
  250. (clip-miny (view-clip-miny view))
  251. (clip-maxx (view-clip-maxx view))
  252. (clip-maxy (view-clip-maxy view)))
  253. (if (or (<= maxx clip-minx)
  254. (<= maxy clip-miny)
  255. (>= minx clip-maxx)
  256. (>= miny clip-maxy))
  257. #f
  258. (list (max minx clip-minx)
  259. (max miny clip-miny)
  260. (min maxx clip-maxx)
  261. (min maxy clip-maxy))))
  262. (list minx miny maxx maxy)))
  263. ;;; The following function converts a list of views into a list of lists of
  264. ;;; views, where each list is a list of intersecting views. Each sublist is
  265. ;;; ordered as was the original list of views.
  266. (define (PARTITION-VIEWS views)
  267. (define (INTERSECT? view views)
  268. (if (pair? views)
  269. (let ((v2 (car views)))
  270. (if (and (view-clip-minx view)
  271. (view-clip-minx v2)
  272. (or (<= (view-clip-maxx view)
  273. (view-clip-minx v2))
  274. (<= (view-clip-maxy view)
  275. (view-clip-miny v2))
  276. (>= (view-clip-minx view)
  277. (view-clip-maxx v2))
  278. (>= (view-clip-miny view)
  279. (view-clip-maxy v2))))
  280. (intersect? view (cdr views))
  281. #t))
  282. #f))
  283. (if (pair? views)
  284. (let loop ((intersect (list (car views)))
  285. (disjoint '())
  286. (views (cdr views)))
  287. (if (pair? views)
  288. (let ((view (car views)))
  289. (if (intersect? view intersect)
  290. (loop (append intersect (list view)) disjoint
  291. (cdr views))
  292. (loop intersect (append disjoint (list view))
  293. (cdr views))))
  294. (cons intersect (partition-views disjoint))))
  295. '()))
  296. ;;; Graphics contexts are managed by the following procedure. Given the
  297. ;;; appropriate options, it will return a graphics context. If needed a
  298. ;;; new one will be created. Note that the GC's are actually owned and
  299. ;;; managed by the view's display object.
  300. (define (CV-GC width color stipple dash font arc)
  301. (display-gc *display* width (or color *foreground*) *background*
  302. stipple stipple-x stipple-y dash font arc *clip-bbl*))
  303. ;;; Points are converted to pixels by the following function. A line width
  304. ;;; of #f converts to 0.
  305. (define (POINTS->PIXELS x)
  306. (if x (inexact->exact (round (* *pixels/point* x))) 0))
  307. ;;; The following procedure checks to see if a drawing name exists in the
  308. ;;; last checked window name. It is used in conjuction with WINDOW-EXISTS?
  309. ;;; to parse the window and drawing within the window names in a command.
  310. (define (DRAWING-IN-LAST-EXISTING-WINDOW? x)
  311. (and (symbol? x)
  312. (let loop ((vl (window-views
  313. (name->window last-existing-window-name))))
  314. (if (pair? vl)
  315. (let ((view (car vl)))
  316. (if (eq? x (view-drawing-name view))
  317. #t
  318. (loop (cdr vl))))
  319. #f))))
  320. ;;; A drawing is shown in a window by defining a "view" of a drawing in a
  321. ;;; window. This is done by the OVERLAY and UNDERLAY commands that place the
  322. ;;; drawing over or under the drawings already in the window. If the drawing
  323. ;;; is already visible in the window, it will be repositioned.
  324. (define (OVER/UNDER-LAY wname dname over bb)
  325. (let* ((window (name->window wname))
  326. (drawing (name->drawing dname))
  327. (views (window-views window)))
  328. (define (CVT x) (if (list-ref bb 4) (points->pixels x) x))
  329. (define (ADD-VIEW views view)
  330. (window-views! window (if over
  331. (append views (list view))
  332. (cons view views)))
  333. (when bb
  334. (view-clip-minx! view (cvt (car bb)))
  335. (view-clip-miny! view (cvt (cadr bb)))
  336. (view-clip-maxx! view (cvt (+ (car bb) (caddr bb))))
  337. (view-clip-maxy! view (cvt (+ (cadr bb) (cadddr bb)))))
  338. (handle-view-events view 'overlay #f
  339. (if (view-clip-minx view)
  340. `(,(view-clip-minx view) ,(view-clip-miny view)
  341. ,(- (view-clip-maxx view) (view-clip-minx view))
  342. ,(- (view-clip-maxy view)(view-clip-miny view)))
  343. `(0 0 ,(window-width (view-window view))
  344. ,(window-height (view-window view)))))
  345. (handle-visible-events view))
  346. (let loop ((vl views))
  347. (if (pair? vl)
  348. (let ((view (car vl)))
  349. (if (eq? (view-drawing-name view) dname)
  350. (begin (damage-view-area view)
  351. (set-view #f '())
  352. (add-view (remq view views) view))
  353. (loop (cdr vl))))
  354. (let ((view (make-view dname wname)))
  355. (if (null? views)
  356. (xmapraised *dpy* (window-xwindow window))
  357. (if (not over) (damage-view-area view)))
  358. (add-view views view)))))
  359. (set! *update-display* #t))
  360. (define-ezd-command
  361. `(overlay ,window-exists? ,drawing-exists?
  362. (optional ,non-negative? ,non-negative? ,positive-number?
  363. ,positive-number? (optional POINTS)))
  364. "(overlay window-name drawing-name [ x y width height [ POINTS ] ])"
  365. (lambda (w-name d-name bb) (over/under-lay w-name d-name #t bb)))
  366. (define-ezd-command
  367. `(underlay ,window-exists? ,drawing-exists?
  368. (optional ,non-negative? ,non-negative? ,positive-number?
  369. ,positive-number? (optional POINTS)))
  370. "(underlay window-name drawing-name [ x y width height [ POINTS ] ])"
  371. (lambda (w-name d-name bb) (over/under-lay w-name d-name #f bb)))
  372. ;;; The X window area occupied by a view is "damaged" by the following
  373. ;;; procedure to force it to be updated when the window is redrawn.
  374. (define (DAMAGE-VIEW-AREA view)
  375. (let ((drawing (view-drawing view))
  376. (window (view-window view)))
  377. (set-view view '())
  378. (if (not (drawing-is-clear drawing))
  379. (for-each
  380. (lambda (bbl)
  381. (window-damage-bbl! window
  382. (merge-bbl (car bbl) (cadr bbl) (caddr bbl)
  383. (cadddr bbl) (window-damage-bbl window))))
  384. (clip-bbl-to-view view
  385. (map (lambda (g) ((graphic-compute-bb g)))
  386. (drawing-head drawing)))))))
  387. ;;; A window name and drawing name is translated to a view by the following
  388. ;;; procedure.
  389. (define (WINDOW-DRAWING->VIEW window-name drawing-name)
  390. (let loop ((vl (window-views (name->window window-name))))
  391. (if (pair? vl)
  392. (let ((view (car vl)))
  393. (if (eq? drawing-name (view-drawing-name view))
  394. view
  395. (loop (cdr vl))))
  396. (ezd-error 'WINDOW-DRAWING->VIEW
  397. "DRAWING ~a is not visible in WINDOW ~s"
  398. drawing-name window-name))))
  399. ;;; A view is deleted by the ezd command DELETE-VIEW.
  400. (define (DELETE-VIEW window-name drawing-name)
  401. (let* ((view (window-drawing->view window-name drawing-name))
  402. (window (view-window view)))
  403. (window-views! window (remq view (window-views window)))
  404. (if (null? (window-views window))
  405. (begin (window-exposed! window #f)
  406. (xunmapwindow *dpy* (window-xwindow window)))
  407. (damage-view-area view))
  408. (handle-view-events view 'overlay #f (list #f #f #f #f))
  409. (handle-view-events view 'visible #f (list #f #f #f #f))
  410. (set! *update-display* #t)))
  411. (define-ezd-command
  412. `(delete-view ,window-exists? ,drawing-in-last-existing-window?)
  413. "(delete-view window-name drawing-name)"
  414. delete-view)
  415. ;;; When an area of a drawing is made visible by either making it a view, or
  416. ;;; changing it's coordinate system, then this event must be reported to any
  417. ;;; objects in the drawing that expect it. The arguments are a bounding box
  418. ;;; (in the drawing's coordinate system) of the area of the drawing visible
  419. ;;; in the view.
  420. (define (HANDLE-VISIBLE-EVENTS view)
  421. (handle-view-events view 'visible #f
  422. (list ((view-x->user view) (or (view-clip-minx view) 0))
  423. ((view-y->user view) (or (view-clip-miny view) 0))
  424. ((view-width->user view)
  425. (- (or (view-clip-maxx view) (window-width (view-window view)))
  426. (or (view-clip-minx view) 0)))
  427. ((view-height->user view)
  428. (- (or (view-clip-maxy view)(window-height (view-window view)))
  429. (or (view-clip-miny view) 0))))))
  430. ;;; The coordinate system of a view is modified by the ezd commands
  431. ;;; ORIGIN and SCALE. The ORIGIN command provides the X coordinates of the
  432. ;;; origin of the user's coordinate system. The SCALE command provide the
  433. ;;; scale factors for scaling the x and y coordinates. The coordinate
  434. ;;; transformations are:
  435. ;;;
  436. ;;; x11 = user-x * scale-x + origin-x
  437. ;;; y11 = user-y * scale-y + origin-y
  438. (define-ezd-command
  439. `(origin ,window-exists? ,drawing-in-last-existing-window?
  440. ,number? ,number? (optional points))
  441. "(origin window-name drawing-name x y [ points ])"
  442. (lambda (w d x y points)
  443. (if points
  444. (queue-transform w d (points->pixels x)
  445. (points->pixels y) #f #f #f)
  446. (queue-transform w d x y #f #f #f))))
  447. (define-ezd-command
  448. `(scale ,window-exists? ,drawing-in-last-existing-window?
  449. ,non-zero? ,non-zero? ,positive-number? (optional points))
  450. "(scale window-name drawing-name x-scale y-scale line-width-scale [ points ])"
  451. (lambda (w d x y lw points)
  452. (if points
  453. (queue-transform w d #f #f (* *pixels/point* x)
  454. (* *pixels/point* y) (* *pixels/point* lw))
  455. (queue-transform w d #f #f x y lw))))
  456. ;;; The first step when performing a transformation is to save the new
  457. ;;; transform in the view. The actual transformation occurs the next time the
  458. ;;; display is updated.
  459. (define (QUEUE-TRANSFORM window-name drawing-name originx originy scalex
  460. scaley scalelw)
  461. (let ((view (window-drawing->view window-name drawing-name))
  462. (originx (and originx (inexact->exact (round originx))))
  463. (originy (and originy (inexact->exact (round originy)))))
  464. (when (or (and originx
  465. (or (not (equal? originx (view-originx view)))
  466. (not (equal? originy (view-originy view)))))
  467. (and scalex
  468. (or (not (equal? scalex (view-scalex view)))
  469. (not (equal? scaley (view-scaley view)))
  470. (not (equal? scalelw (view-scalelw view))))))
  471. (view-new-transform! view
  472. (let loop ((old (or (view-new-transform view)
  473. '(#f #f #f #f #f)))
  474. (new (list originx originy scalex scaley
  475. scalelw)))
  476. (if (pair? new)
  477. (cons (or (car new) (car old))
  478. (loop (cdr old) (cdr new)))
  479. '())))
  480. (set! *update-display* #t))))
  481. ;;; When the display is updated, the transformations on all views in a window
  482. ;;; are done together. The first step is to compute the new coordinate
  483. ;;; transformation functions. Once this is done, the display is updated by
  484. ;;; moving existing bits, or damaging it and forcing it to be redrawn. A list
  485. ;;; of views needing visible events is returned. The events are sent after
  486. ;;; drawing completes.
  487. (define VISIBLE-EVENT-QUEUE '())
  488. (define (TRANSFORM-VIEWS views)
  489. (set! visible-event-queue '())
  490. (for-each transform-a-partition (partition-views views))
  491. visible-event-queue)
  492. (define (TRANSFORM-A-PARTITION views)
  493. (define (MERGE x l) (if (member x l) l (cons x l)))
  494. (define (ACCUM func l x default)
  495. (let loop ((v #f) (l l))
  496. (if (pair? l)
  497. (let ((next-v (or (list-ref (car l) x) default)))
  498. (loop (if v (func v next-v) next-v) (cdr l)))
  499. v)))
  500. (let ((rescaled #f)
  501. (deltax '())
  502. (deltay '())
  503. (clip '()))
  504. (for-each
  505. (lambda (view)
  506. (let ((transform (view-new-transform view)))
  507. (view-new-transform! view #f)
  508. (cond ((drawing-is-clear (view-drawing view))
  509. (if (pair? transform)
  510. (apply transform-a-view view transform)))
  511. ((pair? transform)
  512. (let* ((result (apply transform-a-view
  513. view transform))
  514. (rs (car result))
  515. (dx (cadr result))
  516. (dy (caddr result)))
  517. (set! rescaled (or rs rescaled))
  518. (set! deltax (merge dx deltax))
  519. (set! deltay (merge dy deltay))
  520. (set! clip
  521. (merge `(,(view-clip-minx view)
  522. ,(view-clip-miny view)
  523. ,(view-clip-maxx view)
  524. ,(view-clip-maxy view))
  525. clip))))
  526. (else (set! rescaled #t)))))
  527. views)
  528. (if (not (null? deltax))
  529. (let* ((window (view-window (car views)))
  530. (minx (accum min clip 0 0))
  531. (miny (accum min clip 1 0))
  532. (maxx (accum max clip 2 (window-width window)))
  533. (maxy (accum max clip 3 (window-height window))))
  534. (transform-redisplay views
  535. (or rescaled (> (length deltax) 1)
  536. (> (length deltay) 1) (> (length clip) 1))
  537. (car deltax) (car deltay) minx miny maxx maxy)))))
  538. ;;; Coordinate transformations are performed on an existing view by the
  539. ;;; following function.
  540. (define (TRANSFORM-A-VIEW view originx originy scalex scaley scalelw)
  541. (set-view view '())
  542. (let ((was-originx (view-originx *current-view*))
  543. (was-originy (view-originy *current-view*)))
  544. (if originx (view-originx! *current-view* originx))
  545. (if originy (view-originy! *current-view* originy))
  546. (if scalex (view-scalex! *current-view* scalex))
  547. (if scaley (view-scaley! *current-view* scaley))
  548. (if scalelw (view-scalelw! *current-view* scalelw))
  549. (let ((originx (view-originx *current-view*))
  550. (originy (view-originy *current-view*))
  551. (rescaled (or scalex scaley scalelw))
  552. (scalex (view-scalex *current-view*))
  553. (scaley (view-scaley *current-view*))
  554. (scalelw (view-scalelw *current-view*)))
  555. (set! user->x
  556. (lambda (x) (inexact->exact (+ (* x scalex) originx))))
  557. (set! user->y
  558. (lambda (y) (inexact->exact (+ (* y scaley) originy))))
  559. (set! user->lw
  560. (lambda (x) (if x (inexact->exact (* scalelw x)) 0)))
  561. (set! x->user (lambda (x) (/ (- x originx) scalex)))
  562. (set! y->user (lambda (y) (/ (- y originy) scaley)))
  563. (set! user->width
  564. (lambda (w) (inexact->exact (abs (* w scalex)))))
  565. (set! user->height
  566. (lambda (h) (inexact->exact (abs (* h scaley)))))
  567. (set! width->user (lambda (w) (abs (/ w scalex))))
  568. (set! height->user (lambda (h) (abs (/ h scaley))))
  569. (set-view #f '())
  570. (set-view view '())
  571. (set! visible-event-queue (cons view visible-event-queue))
  572. (list rescaled (- originx was-originx)
  573. (- originy was-originy)))))
  574. ;;; Once the coordinate transformation is complete, the following procedure
  575. ;;; is called to change the window. When a partition of a window is being
  576. ;;; uniformly transformed and no scaling is being done, then bits will be
  577. ;;; moved using xcopyarea. All other transformations will result in the
  578. ;;; window being damaged and redrawn.
  579. ;;;
  580. ;;; N.B.: VIEW-COMPILED is required as the optimum case that uses XIFEVENT
  581. ;;; can only be used if TRANSFORM-REDISPLAY is compiled.
  582. (eval-when (load) (define VIEW-COMPILED #t))
  583. (eval-when (eval) (define VIEW-COMPILED #f))
  584. (define (TRANSFORM-REDISPLAY views damage-all deltax deltay
  585. minx miny maxx maxy)
  586. (define (GRAPHICS-EVENT? dpy event any)
  587. (let* ((event (cons 'xeventp
  588. ((lap (x) (POINTER_TSCP (UNSIGNED x))) event)))
  589. (type (xevent-type event)))
  590. (if (or (and (eq? type graphicsexpose)
  591. (eq? (xevent-xgraphicsexpose-drawable event)
  592. *xwindow*))
  593. (and (eq? type noexpose)
  594. (eq? (xevent-xnoexpose-drawable event)
  595. *xwindow*)))
  596. 1
  597. 0)))
  598. (define (HANDLE-GRAPHICS-EVENTS)
  599. (let ((event (xifevent *dpy* graphics-event? (cons 'charp 0))))
  600. (when (eq? (xevent-type event) graphicsexpose)
  601. (window-expose-bbl! *window*
  602. (merge-bbl (xevent-xgraphicsexpose-x event)
  603. (xevent-xgraphicsexpose-y event)
  604. (+ (xevent-xgraphicsexpose-x event)
  605. (xevent-xgraphicsexpose-width
  606. event))
  607. (+ (xevent-xgraphicsexpose-y event)
  608. (xevent-xgraphicsexpose-height
  609. event))
  610. (window-expose-bbl *window*)))
  611. (unless (zero? (xevent-xgraphicsexpose-count
  612. event))
  613. (handle-graphics-events)))))
  614. (define (DAMAGEAREA x y width height)
  615. (window-damage-bbl! *window*
  616. (merge-bbl x y (+ x width) (+ y height)
  617. (window-damage-bbl *window*))))
  618. (set-view (car views) '())
  619. (let ((width (- maxx minx))
  620. (height (- maxy miny)))
  621. (if (or damage-all (not view-compiled) (not (window-exposed *window*))
  622. (>= (abs deltax) width) (>= (abs deltay) height))
  623. (begin (for-each
  624. (lambda (view)
  625. (set-view view '())
  626. (view-new! *current-view* #t)
  627. (view-bb-head! *current-view* '())
  628. (view-bb-tail! *current-view* '()))
  629. views)
  630. (if (window-exposed *window*)
  631. (damagearea minx miny width height)))
  632. (begin (xcopyarea *dpy* *xwindow* *xwindow*
  633. (cv-gc #f #f #f #f #f #f) minx miny width height
  634. (+ minx deltax) (+ miny deltay))
  635. (set! stipple-x (+ stipple-x deltax))
  636. (set! stipple-y (+ stipple-y deltay))
  637. (if (negative? deltax)
  638. (damagearea (+ maxx deltax) miny (abs deltax) height))
  639. (if (positive? deltax)
  640. (damagearea minx miny deltax height))
  641. (if (negative? deltay)
  642. (damagearea minx (+ maxy deltay) width (abs deltay)))
  643. (if (positive? deltay)
  644. (damagearea minx miny width deltay))
  645. (if (eq? *clean-mouse-window* *window*)
  646. (set! *clean-mouse-window* #f))
  647. (for-each
  648. (lambda (view)
  649. (set-view view '())
  650. (for-each
  651. bbgraphic-bounding-box
  652. (view-bb-head *current-view*)))
  653. views)
  654. (handle-graphics-events)))
  655. (set! *update-display* #t)))
  656. ;;; Redraw those portions of the drawing inside the update bounding boxes as
  657. ;;; well as those additions to the drawing outside the bounding boxes. The
  658. ;;; bounding boxes are specified in X's coordinate system. If no bounding
  659. ;;; box list is specified, then simply write the additions.
  660. (define (REDRAW-A-VIEW view bbl)
  661. (define (RECOMPUTE-BBGL gl stop)
  662. (let loop ((gl gl) (head '()) (tail '()))
  663. (if (and (pair? gl) (not (eq? gl stop)))
  664. (let* ((g (car gl))
  665. (bbgl (list (make-bbgraphic g))))
  666. (if (null? head)
  667. (loop (cdr gl) bbgl bbgl)
  668. (loop (cdr gl) head (begin (set-cdr! tail bbgl)
  669. bbgl))))
  670. (begin (view-bb-head! view head)
  671. (view-bb-tail! view tail)))))
  672. (define (ADD-AND-DRAW gl)
  673. (let loop ((gl gl) (head (view-bb-head view))
  674. (tail (view-bb-tail view)))
  675. (if (pair? gl)
  676. (let* ((g (car gl))
  677. (bbg (make-bbgraphic g))
  678. (bbgl (list bbg)))
  679. ((graphic-xdraw g))
  680. (if (null? head)
  681. (loop (cdr gl) bbgl bbgl)
  682. (loop (cdr gl) head (begin (set-cdr! tail bbgl)
  683. bbgl))))
  684. (begin (view-bb-head! view head)
  685. (view-bb-tail! view tail)))))
  686. (define (XDRAW-INTERSECTING-BBGRAPHICS)
  687. (let loop ((minx #f) (miny #f) (maxx #f) (maxy #f) (l bbl))
  688. (if (pair? l)
  689. (let ((h (car l)))
  690. (loop (bbmin minx (car h)) (bbmin miny (cadr h))
  691. (bbmax maxx (caddr h)) (bbmax maxy (cadddr h))
  692. (cdr l)))
  693. (bbgraphics-intersect (view-bb-head view)
  694. minx miny maxx maxy
  695. (if (= (length bbl) 1)
  696. xdraw-bbgraphic
  697. if-in-any-xdraw-bbgraphic)))))
  698. (define (IF-IN-ANY-XDRAW-BBGRAPHIC bbg)
  699. (let ((minx (bbgraphic-minx bbg))
  700. (miny (bbgraphic-miny bbg))
  701. (maxx (bbgraphic-maxx bbg))
  702. (maxy (bbgraphic-maxy bbg)))
  703. (let loop ((bbl bbl))
  704. (if (pair? bbl)
  705. (let ((bb (car bbl)))
  706. (if (or (>= (car bb) maxx) (>= (cadr bb) maxy)
  707. (<= (caddr bb) minx)
  708. (<= (cadddr bb) miny))
  709. (loop (cdr bbl))
  710. (xdraw-bbgraphic bbg)))))))
  711. (let ((drawing (view-drawing view)))
  712. (set-view view '())
  713. (cond ((view-new view)
  714. (view-new! view #f)
  715. (add-and-draw (drawing-head drawing)))
  716. ((drawing-cleared drawing)
  717. (view-bb-head! view '())
  718. (view-bb-tail! view '())
  719. (add-and-draw (drawing-head drawing)))
  720. ((not (null? bbl))
  721. (if (drawing-zmotion drawing)
  722. (recompute-bbgl (drawing-head drawing)
  723. (drawing-added-head drawing)))
  724. (set-view view bbl)
  725. (xdraw-intersecting-bbgraphics)
  726. (set-view view '())
  727. (add-and-draw (drawing-added-head drawing)))
  728. (else (add-and-draw (drawing-added-head drawing))))))
  729. ;;; Module reset/initialization procedure.
  730. (define (VIEW-MODULE-INIT)
  731. (set! *current-view* #f))