PageRenderTime 58ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/quilt.sc

https://bitbucket.org/bunny351/ezd
Scala | 551 lines | 515 code | 36 blank | 0 comment | 3 complexity | 17fd8766f50e8895bc2e03ccd632fd6d MD5 | raw file
  1. ;;; ezd - easy drawing for X11 displays.
  2. ;;;
  3. ;;; The procedures in this module generate the GRAPHIC objects representing
  4. ;;; rectangles and polygons.
  5. ;* Copyright 1993 Digital Equipment Corporation
  6. ;* All Rights Reserved
  7. ;*
  8. ;* Permission to use, copy, and modify this software and its documentation is
  9. ;* hereby granted only under the following terms and conditions. Both the
  10. ;* above copyright notice and this permission notice must appear in all copies
  11. ;* of the software, derivative works or modified versions, and any portions
  12. ;* thereof, and both notices must appear in supporting documentation.
  13. ;*
  14. ;* Users of this software agree to the terms and conditions set forth herein,
  15. ;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
  16. ;* right and license under any changes, enhancements or extensions made to the
  17. ;* core functions of the software, including but not limited to those affording
  18. ;* compatibility with other hardware or software environments, but excluding
  19. ;* applications which incorporate this software. Users further agree to use
  20. ;* their best efforts to return to Digital any such changes, enhancements or
  21. ;* extensions that they make and inform Digital of noteworthy uses of this
  22. ;* software. Correspondence should be provided to Digital at:
  23. ;*
  24. ;* Director of Licensing
  25. ;* Western Research Laboratory
  26. ;* Digital Equipment Corporation
  27. ;* 250 University Avenue
  28. ;* Palo Alto, California 94301
  29. ;*
  30. ;* This software may be distributed (but not offered for sale or transferred
  31. ;* for compensation) to third parties, provided such third parties agree to
  32. ;* abide by the terms and conditions of this notice.
  33. ;*
  34. ;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  35. ;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  36. ;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  37. ;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  38. ;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  39. ;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  40. ;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  41. ;* SOFTWARE.
  42. (module quilt)
  43. (include "struct.sch")
  44. (include "commands.sch")
  45. (include "ginfo.sch")
  46. (include "display.sch")
  47. (include "view.sch")
  48. (include "psdraw.sch")
  49. (include "drawing.sch")
  50. (include "graphic.sch")
  51. (include "xternal.sch")
  52. ;;; A quilt is generated by the following procedure.
  53. (define (MAKE-QUILT x y width height columns rows color-names color-name-counts
  54. squares)
  55. (define NUMBER-OF-COLORS (vector-length color-names))
  56. (define NUMBER-OF-SQUARES (vector-length squares))
  57. (define CURRENT-TRANSFORM #f)
  58. (define SHAPES (make-vector (vector-length color-names) '()))
  59. (define DRAWING-RECTANGLES #f)
  60. (define (TRANSFORM-SQUARES)
  61. (let ((transform (list user->x user->y)))
  62. (if (not (equal? current-transform transform))
  63. (let* ((ux1 (user->x x))
  64. (ux2 (user->x (+ x width)))
  65. (uy1 (user->y y))
  66. (uy2 (user->y (+ y height)))
  67. (xinc (* (/ (user->width width) columns)
  68. (if (<= ux1 ux2) 1 -1)))
  69. (yinc (* (/ (user->height height) rows)
  70. (if (<= uy1 uy2) 1 -1)))
  71. (basex (if (>= xinc 0)
  72. ux1
  73. (+ ux1 xinc)))
  74. (basey (if (>= yinc 0)
  75. uy1
  76. (+ uy1 yinc)))
  77. (square-width (inexact->exact
  78. (ceiling (abs xinc))))
  79. (square-height (inexact->exact
  80. (ceiling (abs yinc)))))
  81. (set! current-transform transform)
  82. (set! drawing-rectangles
  83. (not (= square-width square-height 1)))
  84. (if drawing-rectangles
  85. (compute-rectangles basex basey xinc yinc
  86. square-width square-height)
  87. (compute-points basex basey xinc yinc))))))
  88. (define (COMPUTE-POINTS basex basey xinc yinc)
  89. (do ((i 0 (+ i 1)))
  90. ((= i number-of-colors))
  91. (vector-set! shapes i
  92. (make-string (* (* 2 c-sizeof-short)
  93. (vector-ref color-name-counts i)))))
  94. (do ((y 0 (+ y 1))
  95. (cx (make-vector number-of-colors 0)))
  96. ((= y rows))
  97. (do ((x 0 (+ x 1)))
  98. ((= x columns))
  99. (let ((color (vector-ref squares (+ (* y columns) x))))
  100. (if color
  101. (let ((points (vector-ref shapes color))
  102. (ptx (vector-ref cx color)))
  103. (c-shortint-set! points ptx
  104. (+ basex (* x xinc)))
  105. (c-shortint-set! points
  106. (+ ptx c-sizeof-short)
  107. (+ basey (* y yinc)))
  108. (vector-set! cx color
  109. (+ ptx (* 2 c-sizeof-short)))))))))
  110. (define (COMPUTE-RECTANGLES basex basey xinc yinc
  111. square-width square-height)
  112. (do ((i 0 (+ i 1)))
  113. ((= i number-of-colors))
  114. (vector-set! shapes i
  115. (make-string (* (* 4 c-sizeof-short)
  116. (vector-ref color-name-counts i)))))
  117. (do ((y 0 (+ y 1))
  118. (cx (make-vector number-of-colors 0)))
  119. ((= y rows))
  120. (do ((x 0 (+ x 1)))
  121. ((= x columns))
  122. (let ((color (vector-ref squares (+ (* y columns) x))))
  123. (if color
  124. (let ((points (vector-ref shapes color))
  125. (ptx (vector-ref cx color)))
  126. (c-shortint-set! points ptx
  127. (+ basex (* x xinc)))
  128. (c-shortint-set! points
  129. (+ ptx c-sizeof-short)
  130. (+ basey (* y yinc)))
  131. (c-shortint-set! points
  132. (+ ptx (* 2 c-sizeof-short))
  133. square-width)
  134. (c-shortint-set! points
  135. (+ ptx (* 3 c-sizeof-short))
  136. square-height)
  137. (vector-set! cx color
  138. (+ ptx (* 4 c-sizeof-short)))))))))
  139. (define (DRAW-COLOR color-x)
  140. (let ((basex x)
  141. (basey y)
  142. (xinc (/ width columns))
  143. (yinc (/ height rows)))
  144. (pscolor (vector-ref color-names color-x))
  145. (do ((y 0 (+ y 1)))
  146. ((= y rows))
  147. (do ((x 0 (+ x 1)))
  148. ((= x columns))
  149. (if (eq? color-x (vector-ref squares
  150. (+ (* y columns) x)))
  151. (pscommand (+ basex (* x xinc))
  152. (+ basey (* y yinc)) "Q"))))))
  153. (define (INSIDE? mouse-x mouse-y)
  154. (let ((col (inexact->exact (/ (- mouse-x x) (/ width columns))))
  155. (row (inexact->exact (/ (- mouse-y y) (/ height rows)))))
  156. (and (< -1 row rows) (< -1 col columns)
  157. (vector-ref squares (+ (* row columns) col)))))
  158. (do ((i 0 (+ i 1)))
  159. ((= i number-of-colors))
  160. (if (eq? (vector-ref color-names i) 'clear)
  161. (vector-set! color-name-counts i 0)))
  162. (make-graphic
  163. #f
  164. (lambda ()
  165. (let ((ux1 (user->x x))
  166. (ux2 (user->x (+ x width)))
  167. (uy1 (user->y y))
  168. (uy2 (user->y (+ y height))))
  169. (list (min ux1 ux2)
  170. (min uy1 uy2)
  171. (+ (max ux1 ux2) 1)
  172. (+ (max uy1 uy2) 1))))
  173. (lambda ()
  174. (transform-squares)
  175. (if drawing-rectangles
  176. (do ((i 0 (+ i 1)))
  177. ((= i number-of-colors))
  178. (if (not (zero? (vector-ref color-name-counts i)))
  179. (xfillrectangles *dpy* *xwindow*
  180. (cv-gc #f (vector-ref color-names i)
  181. #f #f #f #f)
  182. (type/value->pointer 'xrectangleap
  183. (vector-ref shapes i))
  184. (vector-ref color-name-counts i))))
  185. (do ((i 0 (+ i 1)))
  186. ((= i number-of-colors))
  187. (if (not (zero? (vector-ref color-name-counts i)))
  188. (xdrawpoints *dpy* *xwindow*
  189. (cv-gc #f (vector-ref color-names i)
  190. #f #f #f #f)
  191. (type/value->pointer 'xpointap
  192. (vector-ref shapes i))
  193. (vector-ref color-name-counts i)
  194. CoordModeOrigin)))))
  195. (lambda ()
  196. (transform-squares)
  197. (pscommand 1 "dict" "begin")
  198. (let ((xinc (/ width columns))
  199. (yinc (/ height rows)))
  200. (pscommand "/Q" "{newpath" "moveto" xinc 0 "rlineto"
  201. 0 yinc "rlineto" (- xinc) 0 "rlineto" "closepath"
  202. "fill}" "def"))
  203. (do ((i 0 (+ i 1)))
  204. ((= i number-of-colors))
  205. (if (not (zero? (vector-ref color-name-counts i)))
  206. (draw-color i)))
  207. (pscommand "end"))
  208. (lambda (minx miny maxx maxy)
  209. (or (inside? minx miny)
  210. (inside? minx maxy)
  211. (inside? maxx miny)
  212. (inside? maxx maxy)
  213. (inside? (+ minx (/ (- maxx minx) 2))
  214. (+ miny (/ (- maxy miny) 2)))))))
  215. ;;; The QUILT command is used to make a "quilt" from a list colors and
  216. ;;; squares.
  217. (define (QUILT x y width height columns rows color-name-list square-colors)
  218. (let* ((color-names (list->vector color-name-list))
  219. (number-of-colors (length color-name-list))
  220. (color-name-counts (make-vector number-of-colors 0))
  221. (upper-case-a (char->integer #\A))
  222. (lower-case-a (char->integer #\a))
  223. (squares (if (vector? square-colors)
  224. square-colors
  225. (make-vector (* columns rows) #f)))
  226. (number-of-squares (if (vector? square-colors)
  227. (vector-length square-colors)
  228. (string-length square-colors))))
  229. (if (not (equal? number-of-squares (* columns rows)))
  230. (ezd-error 'quilt "Columns*Rows (~s) != # of Square Colors (~s)"
  231. (* columns rows) number-of-squares))
  232. (if (vector? square-colors)
  233. (do ((i 0 (+ i 1)))
  234. ((= i number-of-squares))
  235. (let ((x (vector-ref square-colors i)))
  236. (unless (eq? x #f)
  237. (if (not (and (fixed? x)
  238. (< -1 x number-of-colors)))
  239. (ezd-error 'quilt
  240. "Illegal square-color index: ~a" x))
  241. (vector-set! color-name-counts x
  242. (+ (vector-ref color-name-counts x) 1)))))
  243. (do ((i 0 (+ i 1)))
  244. ((= i number-of-squares))
  245. (let* ((c (string-ref square-colors i))
  246. (x (if (char>=? c #\a)
  247. (- (char->integer c) lower-case-a)
  248. (- (char->integer c) upper-case-a))))
  249. (unless (char=? c #\space)
  250. (if (not (< -1 x number-of-colors))
  251. (ezd-error 'quilt
  252. "Illegal square-color character: ~a"
  253. c))
  254. (vector-set! squares i x)
  255. (vector-set! color-name-counts x
  256. (+ (vector-ref color-name-counts x) 1))))))
  257. (make-quilt x y width height columns rows color-names
  258. color-name-counts squares)))
  259. (define (POSITIVE-INTEGER? x) (and (integer? x) (positive? x)))
  260. (define (SQUARE-COLORS? x) (or (vector? x) (string? x)))
  261. (define-ezd-command
  262. `(quilt ,number? ,number? ,non-negative? ,non-negative?
  263. ,positive-integer? ,positive-integer? (repeat ,color?)
  264. ,square-colors?)
  265. "(quilt x y width height columns rows color... \"square-colors\")"
  266. quilt)
  267. ;;; The BITMAP command is used to make a "quilt" from an X11 bitmap, a PBM
  268. ;;; bitmap (monochrome), a PGM bitmap (grayscale), or a PPM bit map.
  269. (define (BITMAP x y width-height file colors)
  270. (let* ((port (let ((x (catch-error (lambda () (open-input-file file)))))
  271. (if (not (pair? x))
  272. (ezd-error 'x11bitmap
  273. "Unable to open bit map file: ~s" file))
  274. (car x)))
  275. (pbitmap (char=? (peek-char port) #\P))
  276. (pbitmaptype (and pbitmap (read-char port) (read-char port))))
  277. (define (READ-NEXT-CHAR)
  278. (let ((c (read-char port)))
  279. (if (and pbitmap (char=? c #\#))
  280. (let loop ((c (read-char port)))
  281. (unless (or (eof-object? c)
  282. (char=? c #\newline))
  283. (loop (read-char port)))))
  284. (if (eof-object? port)
  285. (ezd-error 'x11bitmap "Unexpected end-of-file!")
  286. c)))
  287. (define (GET-NUMBER)
  288. (if (char-numeric? (peek-char port))
  289. (let ((base (if (and (eq? (peek-char port) #\0)
  290. (read-next-char)
  291. (memq (peek-char port) '(#\x #\X)))
  292. (begin (read-next-char)
  293. 16)
  294. 10)))
  295. (let loop ((c (peek-char port)) (value 0))
  296. (let ((c (assq c '((#\0 0) (#\1 1) (#\2 2)
  297. (#\3 3) (#\4 4) (#\5 5)
  298. (#\6 6) (#\7 7) (#\8 8)
  299. (#\9 9) (#\a 10) (#\b 11)
  300. (#\c 12) (#\d 13) (#\e 14)
  301. (#\f 15) (#\A 10) (#\B 11)
  302. (#\C 12) (#\D 13) (#\E 14)
  303. (#\F 15)))))
  304. (if c
  305. (loop (begin (read-next-char)
  306. (peek-char port))
  307. (+ (* base value) (cadr c)))
  308. value))))
  309. (begin (read-next-char)
  310. (get-number))))
  311. (define (PICK-CHAR char)
  312. (if (char=? (read-next-char) char)
  313. #t
  314. (pick-char char)))
  315. (define (PBM)
  316. (if (and (pair? colors) (> (length colors) 2))
  317. (ezd-error 'bitmap
  318. "Only two colors allowed for PBM bitmaps"))
  319. (let* ((bitmap-width (get-number))
  320. (bitmap-height (get-number))
  321. (count 0)
  322. (foreground-color (if (pair? colors)
  323. (car colors)
  324. 'black))
  325. (background-color (if (> (length colors) 1)
  326. (cadr colors)
  327. #f))
  328. (squares (make-vector (* bitmap-width bitmap-height)
  329. (if background-color 1 #f))))
  330. (do ((i 0 (+ i 1))
  331. (end (* bitmap-width bitmap-height)))
  332. ((= i end))
  333. (let ((bit (get-number)))
  334. (when (= bit 1)
  335. (vector-set! squares i 0)
  336. (set! count (+ count 1)))))
  337. (make-quilt x y
  338. (if (pair? width-height)
  339. (car width-height)
  340. bitmap-width)
  341. (if (pair? width-height)
  342. (cadr width-height)
  343. bitmap-height)
  344. bitmap-width bitmap-height
  345. (if (and foreground-color background-color)
  346. (vector foreground-color background-color)
  347. (vector foreground-color))
  348. (if background-color
  349. (vector count
  350. (- (vector-length squares) count))
  351. (vector count))
  352. squares)))
  353. (define (PGM)
  354. (let* ((bitmap-width (get-number))
  355. (bitmap-height (get-number))
  356. (grays (+ 1 (get-number)))
  357. (counts (make-vector grays 0))
  358. (squares (make-vector (* bitmap-width bitmap-height)
  359. #f))
  360. (color-map (if colors colors (gray-color-map grays)))
  361. (scale (/ (length color-map) grays)))
  362. (do ((i 0 (+ i 1))
  363. (end (* bitmap-width bitmap-height)))
  364. ((= i end))
  365. (let ((pixel (inexact->exact
  366. (* scale (get-number)))))
  367. (vector-set! squares i pixel)
  368. (vector-set! counts pixel
  369. (+ 1 (vector-ref counts pixel)))))
  370. (make-quilt x y
  371. (if (pair? width-height)
  372. (car width-height)
  373. bitmap-width)
  374. (if (pair? width-height)
  375. (cadr width-height)
  376. bitmap-height)
  377. bitmap-width bitmap-height
  378. (list->vector color-map)
  379. counts
  380. squares)))
  381. (define (GRAY-COLOR-MAP grays)
  382. (let ((inc (/ 100 (- (min grays 101) 1))))
  383. (let loop ((count (- (min grays 101) 1))
  384. (color 100) (cl '()))
  385. (if (zero? count)
  386. (let ((cl (cons 'black cl)))
  387. (for-each color? cl)
  388. cl)
  389. (loop (- count 1) (- color inc)
  390. (cons (string->symbol
  391. (format "GRAY~S"
  392. (inexact->exact
  393. color)))
  394. cl))))))
  395. (define (PPM)
  396. (if colors
  397. (format stderr-port
  398. "BITMAP - PPM bitmaps ignore command colors~%"))
  399. (let* ((bitmap-width (get-number))
  400. (bitmap-height (get-number))
  401. (colorvalues (+ 1 (get-number)))
  402. (scale (/ 256 colorvalues))
  403. (counts (make-vector colorvalues 0))
  404. (color-names '())
  405. (cvalue-color-x '())
  406. (color-x 0)
  407. (squares (make-vector (* bitmap-width bitmap-height)
  408. #f)))
  409. (define (ALLOCATE-COLOR cvalue)
  410. (let ((cname (string->symbol
  411. (format "PPM-COLOR-~s"
  412. cvalue))))
  413. (display-define-color *display* cname
  414. cvalue)
  415. (set! color-names
  416. (cons cname color-names))
  417. (set! cvalue-color-x
  418. (cons (cons cvalue color-x)
  419. cvalue-color-x))
  420. (set! color-x (+ color-x 1))
  421. (- color-x 1)))
  422. (do ((i 0 (+ i 1))
  423. (end (* bitmap-width bitmap-height)))
  424. ((= i end))
  425. (let* ((r (inexact->exact (* scale (get-number))))
  426. (g (inexact->exact (* scale (get-number))))
  427. (b (inexact->exact (* scale (get-number))))
  428. (cvalue (+ (* (+ (* r 256) g) 256) b))
  429. (ca (assq cvalue cvalue-color-x))
  430. (pixel (or (and ca (cdr ca))
  431. (allocate-color cvalue))))
  432. (vector-set! squares i pixel)
  433. (vector-set! counts pixel
  434. (+ 1 (vector-ref counts pixel)))))
  435. (make-quilt x y
  436. (if (pair? width-height)
  437. (car width-height)
  438. bitmap-width)
  439. (if (pair? width-height)
  440. (cadr width-height)
  441. bitmap-height)
  442. bitmap-width bitmap-height
  443. (list->vector (reverse color-names))
  444. counts
  445. squares)))
  446. (define (X11BITMAP)
  447. (if (and (pair? colors) (> (length colors) 2))
  448. (ezd-error 'bitmap
  449. "Only two colors allowed for X11 bitmaps"))
  450. (let* ((bitmap-width (begin (pick-char #\space)
  451. (pick-char #\_)
  452. (pick-char #\space)
  453. (get-number)))
  454. (bitmap-height (begin (pick-char #\space)
  455. (pick-char #\_)
  456. (pick-char #\space)
  457. (get-number)))
  458. (count 0)
  459. (foreground-color (if (pair? colors)
  460. (car colors)
  461. 'black))
  462. (background-color (if (> (length colors) 1)
  463. (cadr colors)
  464. #f))
  465. (squares (make-vector (* bitmap-width bitmap-height)
  466. (if background-color 1 #f))))
  467. (pick-char #\{)
  468. (let loop ((bits (get-number))
  469. (bits-left 8)
  470. (rows-left bitmap-height)
  471. (columns-left bitmap-width)
  472. (x 0))
  473. (cond ((zero? columns-left)
  474. (unless (= rows-left 1)
  475. (loop (get-number) 8
  476. (- rows-left 1)
  477. bitmap-width x)))
  478. ((zero? bits-left)
  479. (loop (get-number) 8 rows-left
  480. columns-left x))
  481. (else (when (odd? bits)
  482. (set! count (+ count 1))
  483. (vector-set! squares x 0))
  484. (loop (quotient bits 2)
  485. (- bits-left 1)
  486. rows-left (- columns-left 1)
  487. (+ x 1)))))
  488. (make-quilt x y
  489. (if (pair? width-height)
  490. (car width-height)
  491. bitmap-width)
  492. (if (pair? width-height)
  493. (cadr width-height)
  494. bitmap-height)
  495. bitmap-width bitmap-height
  496. (if (and foreground-color background-color)
  497. (vector foreground-color background-color)
  498. (vector foreground-color))
  499. (if background-color
  500. (vector count
  501. (- (vector-length squares) count))
  502. (vector count))
  503. squares)))
  504. (let ((result (case (and pbitmap pbitmaptype)
  505. ((#\1) (pbm))
  506. ((#\2) (pgm))
  507. ((#\3) (ppm))
  508. (else (x11bitmap)))))
  509. (close-input-port port)
  510. result)))
  511. (define-ezd-command
  512. `(bitmap ,number? ,number? (optional ,non-negative? ,non-negative?)
  513. ,string? (repeat ,color?))
  514. "(bitmap x y [width height] \"file name\" [<color>...])"
  515. bitmap)