1#lang racket/unit 2 3; Simple graphics routines for GRacket 4; Originally written by Johnathan Franklin 5; 6; modified by Gregory Cooper to support FrTime 7 8(require (for-syntax syntax/parse racket/base) 9 racket/class 10 (prefix-in gui: racket/gui/base) 11 frtime/core/frp 12 "graphics-sig.rkt") 13 14(import graphics:posn^) 15(export graphics:posn-less^) 16 17(define-syntax (rec stx) 18 (syntax-parse stx 19 [((~literal rec) var:identifier rhs:expr) 20 #'(letrec ([var rhs]) 21 var)])) 22 23(define send/proc 24 (lambda (class method . args) 25 (send-generic class (make-generic gui:dc<%> method) . args))) 26 27(define send/proc2 28 (lambda (class method . args) 29 (send-generic class (make-generic sixlib-canvas% method) . args))) 30 31(define-struct viewport (label canvas)) 32(define-struct sixmouse (x y left? middle? right?)) 33(define-struct sixkey (value shift control meta alt)) 34(define graphics-flag #f) 35(define global-viewport-list '()) 36(define global-color-vector (make-vector 300 #f)) 37(define global-pen-vector (make-vector 300 #f)) 38(define global-brush-vector (make-vector 300 #f)) 39(define default-font (make-object gui:font% 12 'roman 'normal 'normal)) 40(define black-color (make-object gui:color% "BLACK")) 41 42(define sixlib-canvas% 43 (class gui:canvas% 44 ;; were public 45 (define viewport (void)) 46 (define height 0) 47 (define width 0) 48 (define label 0) 49 (define current-pen 'uninitialized-pen) 50 (define current-brush 'uninitialized-brush) 51 (define bitmap 'uninitalized-bitmap) 52 (define dc 'uninitialized-dc) 53 (define buffer-dc 'uninitialized-buffer-dc) 54 (super-new) 55 (inherit get-parent 56 min-client-width min-client-height 57 stretchable-width stretchable-height) 58 (define current-mouse-pos (make-posn 0 0)) 59 (define mouse-listener #f) 60 (define key-listener #f) 61 (private* 62 [reset-size 63 (lambda () 64 (min-client-width width) 65 (min-client-height height) 66 (stretchable-width #f) 67 (stretchable-height #f) 68 (set! bitmap (make-object gui:bitmap% width height)) 69 (unless (send bitmap ok?) 70 (error "cannot allocate viewport")) 71 (send buffer-dc set-bitmap bitmap) 72 (send buffer-dc set-brush (send dc get-brush)) 73 (send buffer-dc set-pen (send dc get-pen)) 74 (send buffer-dc set-smoothing 'aligned) 75 (let ([f (send dc get-font)]) 76 (when f 77 (send buffer-dc set-font f))) 78 (send buffer-dc clear) 79 (send dc clear))]) 80 81 82 83 (public* 84 [get-mouse-listener (lambda () mouse-listener)] 85 [get-key-listener (lambda () key-listener)] 86 [set-mouse-listener (lambda (ml) (set! mouse-listener ml))] 87 [set-key-listener (lambda (kl) (set! key-listener kl))] 88 [get-posn (lambda () current-mouse-pos)] 89 [get-viewport (lambda () viewport)] 90 [set-viewport (lambda (x) (set! viewport x))] 91 [get-sixlib-height (lambda () height)] 92 [get-sixlib-width (lambda () width)] 93 [get-current-pen (lambda () current-pen)] 94 [get-current-brush (lambda () current-brush)] 95 [get-bitmap (lambda () bitmap)] 96 [get-sixlib-dc (lambda () dc)] 97 [get-buffer-dc (lambda () buffer-dc)] 98 [remember-pen (lambda (pen) (set! current-pen pen))] 99 [remember-brush (lambda (brush) (set! current-brush brush))]) 100 101 (override* 102 [on-paint 103 (lambda () 104 (when (object? buffer-dc) 105 (define bm (send buffer-dc get-bitmap)) 106 (when bm 107 (send dc draw-bitmap bm 0 0))))] 108 109 [on-event 110 (lambda (mouse-event) 111 (set! current-mouse-pos (make-posn (send mouse-event get-x) 112 (send mouse-event get-y))) 113 (send-event mouse-listener mouse-event))] 114 #| 115 (let* ([x (send mouse-event get-x)] 116 [y (send mouse-event get-y)] 117 [left? (send mouse-event button-down? 'left)] 118 [middle? (send mouse-event button-down? 'middle)] 119 [right? (send mouse-event button-down? 'right)] 120 [sixm (make-sixmouse x y left? middle? right?)]) 121 (set! current-mouse-pos (make-posn x y)) 122 (if mouse-listener 123 (send-event mouse-listener sixm))))] 124|# 125 [on-char 126 (lambda (key-event) 127 (when key-listener 128 (send-event 129 key-listener 130 (make-sixkey 131 (send key-event get-key-code) 132 (send key-event get-shift-down) 133 (send key-event get-control-down) 134 (send key-event get-meta-down) 135 (send key-event get-alt-down)))))]) 136 137 (public* 138 [set-dc (lambda (new-dc) (set! dc new-dc))] 139 [set-buffer-dc (lambda (new-buffer-dc) (set! buffer-dc 140 new-buffer-dc))] 141 142 [set-geometry 143 (lambda (new-width new-height) 144 (set! height new-height) 145 (set! width new-width) 146 (reset-size))] 147 [set-height (lambda (new-height) 148 (set! height new-height) 149 (reset-size))] 150 [set-width (lambda (new-width) 151 (set! width new-width) 152 (reset-size))]))) 153 154(define open-frames-timer (make-object gui:timer%)) 155 156(define sixlib-frame% 157 (class gui:frame% 158 (field [canvas #f]) 159 (define/public (set-canvas x) (set! canvas x)) 160 (define/augment (on-close) 161 (close-viewport (send canvas get-viewport)) 162 (inner (void) on-close)) 163 (super-instantiate ()))) 164 165(define (query-mouse-posn viewport) 166 (send (viewport-canvas viewport) get-posn)) 167 168(define repaint 169 (lambda (viewport) 170 (send (viewport-canvas viewport) on-paint))) 171 172(define viewport-mouse-events 173 (lambda (viewport) 174 (send (viewport-canvas viewport) get-mouse-listener))) 175 176(define viewport-key-events 177 (lambda (viewport) 178 (send (viewport-canvas viewport) get-key-listener))) 179 180(define viewport-dc 181 (lambda (viewport) 182 (send (viewport-canvas viewport) get-sixlib-dc))) 183 184(define viewport-buffer-dc 185 (lambda (viewport) 186 (send (viewport-canvas viewport) get-buffer-dc))) 187 188(define viewport-bitmap 189 (lambda (viewport) 190 (send (viewport-canvas viewport) get-bitmap))) 191 192(define viewport-frame 193 (lambda (viewport) 194 (send (send (viewport-canvas viewport) get-parent) get-parent))) 195 196(define viewport-height 197 (lambda (viewport) 198 (send (viewport-canvas viewport) get-sixlib-height))) 199 200(define viewport-width 201 (lambda (viewport) 202 (send (viewport-canvas viewport) get-sixlib-width))) 203 204(define clear-viewport 205 (lambda (viewport) 206 (let* ([vdc (viewport-dc viewport)] 207 [vbdc (viewport-buffer-dc viewport)]) 208 (lambda () 209 (send vdc clear) 210 (send vbdc clear))))) 211 212 213 214(define draw-viewport 215 (lambda (viewport) 216 (let* ([dc (viewport-dc viewport)] 217 [buffer-dc (viewport-buffer-dc viewport)] 218 [w (viewport-width viewport)] 219 [h (viewport-height viewport)]) 220 (rec draw-viewport/color 221 (case-lambda 222 [(color) 223 (let ([new-pen (send gui:the-pen-list find-or-create-pen color 1 'solid)] 224 [new-brush (send gui:the-brush-list find-or-create-brush color 'solid)] 225 [old-pen (send dc get-pen)] 226 [old-brush (send dc get-brush)]) 227 (send dc set-pen new-pen) 228 (send dc set-brush new-brush) 229 (send buffer-dc set-pen new-pen) 230 (send buffer-dc set-brush new-brush) 231 (send dc draw-rectangle 0 0 w h) 232 (send buffer-dc draw-rectangle 0 0 w h) 233 (send dc set-pen old-pen) 234 (send buffer-dc set-pen old-pen) 235 (send dc set-brush old-brush) 236 (send buffer-dc set-brush old-brush))] 237 [() (draw-viewport/color (make-rgb 0 0 0))]))))) 238 239(define flip-viewport 240 (lambda (viewport) 241 (let* ([dc (viewport-dc viewport)] 242 [dc2 (viewport-buffer-dc viewport)] 243 [w (viewport-width viewport)] 244 [h (viewport-height viewport)]) 245 (lambda () 246 (let ([pen (send dc get-pen)] 247 [pen2 (send dc2 get-pen)] 248 [brush (send dc get-brush)] 249 [brush2 (send dc2 get-brush)]) 250 (send dc set-pen xor-pen) 251 (send dc2 set-pen xor-pen) 252 (send dc set-brush xor-brush) 253 (send dc2 set-brush xor-brush) 254 (send dc draw-rectangle 0 0 w h) 255 (send dc2 draw-rectangle 0 0 w h) 256 (send dc set-pen pen) 257 (send dc2 set-pen pen2) 258 (send dc set-brush brush) 259 (send dc2 set-brush brush2)))))) 260 261(define close-viewport 262 (lambda (viewport) 263 (set! global-viewport-list 264 (let loop ([l global-viewport-list]) 265 (cond 266 [(null? l) '()] 267 [(eq? (car l) viewport) (cdr l)] 268 [else (cons (car l) (loop (cdr l)))]))) 269 (send (viewport-frame viewport) show #f) 270 (send (viewport-canvas viewport) show #f) 271 (when (null? global-viewport-list) 272 (send open-frames-timer stop)))) 273 274(define open-graphics 275 (lambda () 276 (set! graphics-flag #t))) 277 278(define close-graphics 279 (lambda () 280 (map close-viewport global-viewport-list) 281 (set! graphics-flag #f) 282 (set! global-viewport-list '()) 283 (send open-frames-timer stop))) 284 285(define graphics-open? (lambda () graphics-flag)) 286 287(define make-rgb 288 (lambda (red green blue) 289 (when (or (< red 0.) (< blue 0.) (< green 0.) 290 (> red 1.) (> blue 1.) (> green 1.)) 291 (error 'make-rgb 292 "all color indices should be in [0.0, 1.0]; provided ~s" 293 (list red green blue))) 294 (let* ([convert (lambda (num) (inexact->exact (round (* 255 num))))] 295 [nred (convert red)] 296 [ngreen (convert green)] 297 [nblue (convert blue)]) 298 (make-object gui:color% nred ngreen nblue)))) 299 300(define make-color make-rgb) 301 302(define (rgb-red rgb) (/ (send rgb red) 255)) 303(define (rgb-blue rgb) (/ (send rgb blue) 255)) 304(define (rgb-green rgb) (/ (send rgb green) 255)) 305 306(define rgb? (lambda (object) (is-a? object gui:color%))) 307(define (color? x) 308 (or (rgb? x) 309 (not (not (send gui:the-color-database find-color x))))) 310 311(define change-color 312 (lambda (index color) 313 (vector-set! global-color-vector index color) 314 (vector-set! global-pen-vector index (get-pen color)) 315 (vector-set! global-brush-vector index (get-brush color)))) 316 317(define (get-color index) 318 (cond 319 [(is-a? index gui:color%) index] 320 [(string? index) (make-object gui:color% index)] 321 [else (vector-ref global-color-vector index)])) 322 323(define get-pen 324 (lambda (index) 325 (cond 326 [(is-a? index gui:pen%) index] 327 [(or (string? index) (is-a? index gui:color%)) 328 (send gui:the-pen-list find-or-create-pen index 1 'solid)] 329 [else (vector-ref global-pen-vector index)]))) 330 331(define get-brush 332 (lambda (index) 333 (cond 334 [(is-a? index gui:brush%) index] 335 [(or (string? index) (is-a? index gui:color%)) 336 (send gui:the-brush-list find-or-create-brush index 'solid)] 337 [else (vector-ref global-brush-vector index)]))) 338 339(define pen? (lambda (object) (is-a? object gui:pen%))) 340(define brush? (lambda (object) (is-a? object gui:brush%))) 341 342(define display-color-vector 343 (lambda () 344 (do 345 ([index 0 (+ index 1)]) 346 ((eq? index 100)) 347 (display (list (/ (rgb-red (get-color index)) 255) 348 (/ (rgb-green (get-color index)) 255) 349 (/ (rgb-blue (get-color index)) 255)))))) 350 351(define make-font 352 (lambda (name) 353 (cond 354 [(eq? name 'large-deco) 355 (make-object gui:font% 40 'decorative 'normal 'normal)] 356 [(eq? name 'small-roman) 357 (make-object gui:font% 12 'roman 'normal 'normal)] 358 [(eq? name 'medium-roman) 359 (make-object gui:font% 24 'roman 'normal 'normal)] 360 [(eq? name 'large-roman) 361 (make-object gui:font% 32 'roman 'normal 'normal)] 362 [else "no such font ~a; only 'large-deco, 'small-roman, 'medium-roman, and 'large-roman" 363 name]))) 364 365(define custom-roman 366 (lambda (size) 367 (make-object gui:font% 368 size 'roman 'normal 'normal))) 369 370(define custom-deco 371 (lambda (size) 372 (make-object gui:font% size 'decorative 'normal 'normal))) 373 374(define set-viewport-pen 375 (lambda (viewport pen) 376 (send (viewport-canvas viewport) remember-pen pen) 377 (let ([pen (get-pen pen)]) 378 (send (viewport-dc viewport) set-pen pen) 379 (send (viewport-buffer-dc viewport) set-pen pen)))) 380 381(define set-viewport-brush 382 (lambda (viewport brush) 383 (send (viewport-canvas viewport) remember-brush brush) 384 (let ([brush (get-brush brush)]) 385 (send (viewport-dc viewport) set-brush brush) 386 (send (viewport-buffer-dc viewport) set-brush brush)))) 387 388(define set-text-foreground 389 (lambda (viewport color) 390 (let ([color (get-color color)]) 391 (send (viewport-dc viewport) set-text-foreground color) 392 (send (viewport-buffer-dc viewport) set-text-foreground color)))) 393 394(define set-text-background 395 (lambda (viewport color) 396 (let ([color (get-color color)]) 397 (send (viewport-dc viewport) set-text-background color) 398 (send (viewport-buffer-dc viewport) set-text-background color)))) 399 400(define set-viewport-font 401 (lambda (viewport font) 402 (send (viewport-dc viewport) set-font font) 403 (send (viewport-buffer-dc viewport) set-font font))) 404 405(define set-viewport-background 406 (lambda (viewport color) 407 (send (viewport-dc viewport) set-background color) 408 (send (viewport-buffer-dc viewport) set-background color))) 409 410(define set-viewport-logical-function 411 (lambda (viewport logical-function) 412 (send (viewport-dc viewport) set-logical-function logical-function) 413 (send (viewport-buffer-dc viewport) set-logical-function 414 logical-function))) 415 416(define white (make-rgb 1 1 1)) 417(define black (make-rgb 0 0 0)) 418(define red (make-rgb 1 0 0)) 419(define green (make-rgb 0 1 0)) 420(define blue (make-rgb 0 0 1)) 421(define white-pen (get-pen white)) 422(define black-pen (get-pen black)) 423(define red-pen (get-pen red)) 424(define blue-pen (get-pen blue)) 425(define green-pen (get-pen green)) 426(define white-brush (get-brush white)) 427(define black-brush (get-brush black)) 428(define red-brush (get-brush red)) 429(define green-brush (get-brush green)) 430(define blue-brush (get-brush blue)) 431 432(define invisi-pen (send gui:the-pen-list find-or-create-pen "WHITE" 0 'transparent)) 433(define invisi-brush (send gui:the-brush-list find-or-create-brush "WHITE" 'transparent)) 434 435(define xor-pen (send gui:the-pen-list find-or-create-pen "BLACK" 1 'xor)) 436(define xor-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'xor)) 437 438(define draw-it (lambda (draw flip clear) (draw))) 439(define flip-it (lambda (draw flip clear) (flip))) 440(define clear-it (lambda (draw flip clear) (clear))) 441 442(define make-draw-proc 443 (lambda (get-pen-name set-pen-name 444 get-current-pen-name set-viewport-pen white-pen) 445 (lambda (viewport) 446 (let* ([vdc (viewport-dc viewport)] 447 [vbdc (viewport-buffer-dc viewport)]) 448 (lambda (color go) 449 (let ([orig (and color 450 (begin0 451 (send/proc2 (viewport-canvas viewport) 452 get-current-pen-name) 453 (set-viewport-pen viewport (get-color color))))]) 454 (go (lambda (draw) 455 (let ([pen (send vdc get-pen)] 456 [brush (send vdc get-brush)]) 457 (send vdc set-brush xor-brush) 458 (send vbdc set-brush xor-brush) 459 (send vdc set-pen xor-pen) 460 (send vbdc set-pen xor-pen) 461 (draw) 462 (send vdc set-brush brush) 463 (send vbdc set-brush brush) 464 (send vdc set-pen pen) 465 (send vbdc set-pen pen))) 466 (lambda (draw) 467 (let ([pen (send/proc vdc get-pen-name)]) 468 (send/proc vdc set-pen-name white-pen) 469 (send/proc vbdc set-pen-name white-pen) 470 (draw) 471 (send/proc vdc set-pen-name pen) 472 (send/proc vbdc set-pen-name pen)))) 473 (when orig 474 (set-viewport-pen viewport orig)))))))) 475 476(define make-do-line 477 (lambda (go) 478 (let ([f (make-draw-proc 'get-pen 'set-pen 479 'get-current-pen set-viewport-pen white-pen)]) 480 (lambda (viewport) 481 (let ([f (f viewport)]) 482 (letrec ([the-function 483 (case-lambda 484 [(posn1 posn2) (the-function posn1 posn2 #f)] 485 [(posn1 posn2 color) 486 (f color 487 (lambda (flip clear) 488 (let* ([x1 (posn-x posn1)] 489 [y1 (posn-y posn1)] 490 [x2 (posn-x posn2)] 491 [y2 (posn-y posn2)] 492 [draw (lambda () 493 (send (viewport-dc viewport) 494 draw-line 495 x1 y1 x2 y2) 496 (send (viewport-buffer-dc viewport) 497 draw-line 498 x1 y1 x2 y2))]) 499 (go draw 500 (lambda () (flip draw)) 501 (lambda () (clear draw))))))])]) 502 the-function)))))) 503 504(define draw-line (make-do-line draw-it)) 505(define (clear-line viewport) 506 (let ([f ((make-do-line clear-it) viewport)]) 507 (rec clear-line-viewport 508 (lambda (p1 p2) 509 (f p1 p2))))) 510(define (flip-line viewport) 511 (let ([f ((make-do-line flip-it) viewport)]) 512 (rec flip-line-viewport 513 (lambda (p1 p2) 514 (f p1 p2))))) 515 516(define (draw/clear/flip ivar) 517 (lambda (init-dc viewport p width height) 518 (let ([dc (viewport-dc viewport)] 519 [buffer-dc (viewport-buffer-dc viewport)]) 520 (init-dc dc) 521 (init-dc buffer-dc) 522 (send/proc dc ivar (posn-x p) (posn-y p) width height) 523 (send/proc buffer-dc ivar (posn-x p) (posn-y p) width height)))) 524 525(define draw/clear/flip-rectangle (draw/clear/flip 'draw-rectangle)) 526(define draw/clear/flip-ellipse (draw/clear/flip 'draw-ellipse)) 527 528(define (draw-arc viewport) 529 (check-viewport 'draw-arc viewport) 530 (rec draw-arc-viewport 531 (case-lambda 532 [(p width height start-radians end-radians) 533 (draw-arc-viewport p width height start-radians end-radians (make-rgb 0 0 0))] 534 [(p width height start-radians end-radians color) 535 (check 'draw-arc 536 posn? p "posn" 537 number? width "number" 538 number? height "number" 539 number? start-radians "number" 540 number? end-radians "number" 541 (orp color? number?) color "color or index") 542 (let ([dc (viewport-dc viewport)] 543 [buffer-dc (viewport-buffer-dc viewport)]) 544 (send dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'solid)) 545 (send dc set-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'transparent)) 546 (send buffer-dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'solid)) 547 (send buffer-dc set-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'transparent)) 548 (send dc draw-arc (posn-x p) (posn-y p) width height start-radians end-radians) 549 (send buffer-dc draw-arc (posn-x p) (posn-y p) width height start-radians end-radians))]))) 550 551(define (draw-solid-arc viewport) 552 (check-viewport 'draw-solid-arc viewport) 553 (rec draw-arc-viewport 554 (case-lambda 555 [(p width height start-radians end-radians) 556 (draw-arc-viewport p width height (make-rgb 0 0 0))] 557 [(p width height start-radians end-radians color) 558 (check 'draw-solid-arc 559 posn? p "posn" 560 number? width "number" 561 number? height "number" 562 number? start-radians "number" 563 number? end-radians "number" 564 (orp color? number?) color "color or index") 565 (let ([dc (viewport-dc viewport)] 566 [buffer-dc (viewport-buffer-dc viewport)]) 567 (send dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'solid)) 568 (send dc set-brush (send gui:the-brush-list find-or-create-brush (get-color color) 'solid)) 569 (send buffer-dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'solid)) 570 (send buffer-dc set-brush (send gui:the-brush-list find-or-create-brush (get-color color) 'solid)) 571 (send dc draw-arc (posn-x p) (posn-y p) width height start-radians end-radians) 572 (send buffer-dc draw-arc (posn-x p) (posn-y p) width height start-radians end-radians))]))) 573 574(define (draw-rectangle viewport) 575 (check-viewport 'draw-rectangle viewport) 576 (rec draw-rectangle-viewport 577 (case-lambda 578 [(p width height) (draw-rectangle-viewport p width height (make-rgb 0 0 0))] 579 [(p width height color) 580 (check 'draw-rectangle 581 posn? p "posn" 582 number? width "number" 583 number? height "number" 584 (orp color? number?) color "color or index") 585 (draw/clear/flip-rectangle 586 (lambda (dc) 587 (send dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'solid)) 588 (send dc set-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'transparent))) 589 viewport p width height)]))) 590 591(define (draw-solid-rectangle viewport) 592 (check-viewport 'draw-solid-rectangle viewport) 593 (rec draw-solid-rectangle-viewport 594 (case-lambda 595 [(p width height) (draw-solid-rectangle-viewport p width height (make-rgb 0 0 0))] 596 [(p width height color) 597 (check 'draw-solid-rectangle 598 posn? p "posn" 599 number? width "number" 600 number? height "number" 601 (orp color? number?) color "color or index") 602 (draw/clear/flip-rectangle 603 (lambda (dc) 604 (send dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'solid)) 605 (send dc set-brush (send gui:the-brush-list find-or-create-brush (get-color color) 'solid))) 606 viewport p width height)]))) 607 608(define (flip-rectangle viewport) 609 (check-viewport 'flip-rectangle viewport) 610 (rec flip-rectangle-viewport 611 (case-lambda 612 [(p width height) (flip-rectangle-viewport p width height (make-rgb 0 0 0))] 613 [(p width height color) 614 (check 'flip-rectangle 615 posn? p "posn" 616 number? width "number" 617 number? height "number" 618 (orp color? number?) color "color or index") 619 (draw/clear/flip-rectangle 620 (lambda (dc) 621 (send dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'xor)) 622 (send dc set-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'transparent))) 623 viewport p width height)]))) 624 625(define (flip-solid-rectangle viewport) 626 (check-viewport 'flip-solid-rectangle viewport) 627 (rec flip-solid-rectangle-viewport 628 (case-lambda 629 [(p width height) (flip-solid-rectangle-viewport p width height (make-rgb 0 0 0))] 630 [(p width height color) 631 (check 'flip-solid-rectangle 632 posn? p "posn" 633 number? width "number" 634 number? height "number" 635 (orp color? number?) color "color or index") 636 (draw/clear/flip-rectangle 637 (lambda (dc) 638 (send dc set-pen (send gui:the-pen-list find-or-create-pen "BLACK" 1 'transparent)) 639 (send dc set-brush (send gui:the-brush-list find-or-create-brush (get-color color) 'xor))) 640 viewport p width height)]))) 641 642(define (draw-ellipse viewport) 643 (check-viewport 'draw-ellipse viewport) 644 (rec draw-ellipse-viewport 645 (case-lambda 646 [(p width height) (draw-ellipse-viewport p width height (make-rgb 0 0 0))] 647 [(p width height color) 648 (check 'draw-ellipse 649 posn? p "posn" 650 number? width "number" 651 number? height "number" 652 (orp color? number?) color "color or index") 653 (draw/clear/flip-ellipse 654 (lambda (dc) 655 (send dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'solid)) 656 (send dc set-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'transparent))) 657 viewport p width height)]))) 658 659(define (draw-solid-ellipse viewport) 660 (check-viewport 'draw-solid-ellipse viewport) 661 (rec draw-solid-ellipse-viewport 662 (case-lambda 663 [(p width height) (draw-solid-ellipse-viewport p width height (make-rgb 0 0 0))] 664 [(p width height color) 665 (check 'draw-solid-ellipse 666 posn? p "posn" 667 number? width "number" 668 number? height "number" 669 (orp color? number?) color "color or index") 670 (draw/clear/flip-ellipse 671 (lambda (dc) 672 (send dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'solid)) 673 (send dc set-brush (send gui:the-brush-list find-or-create-brush (get-color color) 'solid))) 674 viewport p width height)]))) 675 676(define (flip-ellipse viewport) 677 (check-viewport 'flip-ellipse viewport) 678 (rec flip-ellipse-viewport 679 (case-lambda 680 [(p width height) (flip-ellipse-viewport p width height (make-rgb 0 0 0))] 681 [(p width height color) 682 (check 'flip-ellipse 683 posn? p "posn" 684 number? width "number" 685 number? height "number" 686 (orp color? number?) color "color or index") 687 (draw/clear/flip-ellipse 688 (lambda (dc) 689 (send dc set-pen (send gui:the-pen-list find-or-create-pen (get-color color) 1 'xor)) 690 (send dc set-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'transparent))) 691 viewport p width height)]))) 692 693(define (flip-solid-ellipse viewport) 694 (check-viewport 'flip-solid-rectangle viewport) 695 (rec flip-solid-ellipse-viewport 696 (case-lambda 697 [(p width height) (flip-solid-ellipse-viewport p width height (make-rgb 0 0 0))] 698 [(p width height color) 699 (check 'flip-solid-ellipse 700 posn? p "posn" 701 number? width "number" 702 number? height "number" 703 (orp color? number?) color "color or index") 704 (draw/clear/flip-ellipse 705 (lambda (dc) 706 (send dc set-pen (send gui:the-pen-list find-or-create-pen "BLACK" 1 'transparent)) 707 (send dc set-brush (send gui:the-brush-list find-or-create-brush (get-color color) 'xor))) 708 viewport p width height)]))) 709 710(define (clear-rectangle viewport) 711 (check-viewport 'clear-rectangle viewport) 712 (rec clear-rectangle-viewport 713 (lambda (p width height) 714 (check 'clear-rectangle 715 posn? p "posn" 716 number? width "number" 717 number? height "number") 718 (draw/clear/flip-rectangle 719 (lambda (dc) 720 (send dc set-pen (send gui:the-pen-list find-or-create-pen "WHITE" 1 'solid)) 721 (send dc set-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'transparent))) 722 viewport p width height)))) 723 724(define (clear-solid-rectangle viewport) 725 (check-viewport 'clear-solid-rectangle viewport) 726 (rec clear-solid-rectangle-viewport 727 (lambda (p width height) 728 (check 'clear-solid-rectangle 729 posn? p "posn" 730 number? width "number" 731 number? height "number") 732 (draw/clear/flip-rectangle 733 (lambda (dc) 734 (send dc set-pen (send gui:the-pen-list find-or-create-pen "WHITE" 1 'solid)) 735 (send dc set-brush (send gui:the-brush-list find-or-create-brush "WHITE" 'solid))) 736 viewport p width height)))) 737 738(define (clear-ellipse viewport) 739 (check-viewport 'clear-ellipse viewport) 740 (rec clear-ellipse-viewport 741 (lambda (p width height) 742 (check 'clear-ellipse 743 posn? p "posn" 744 number? width "number" 745 number? height "number") 746 (draw/clear/flip-ellipse 747 (lambda (dc) 748 (send dc set-pen (send gui:the-pen-list find-or-create-pen "WHITE" 1 'solid)) 749 (send dc set-brush (send gui:the-brush-list find-or-create-brush "BLACK" 'transparent))) 750 viewport p width height)))) 751 752(define (clear-solid-ellipse viewport) 753 (check-viewport 'clear-solid-ellipse viewport) 754 (rec clear-solid-ellipse-viewport 755 (lambda (p width height) 756 (check 'clear-solid-ellipse 757 posn? p "posn" 758 number? width "number" 759 number? height "number") 760 (draw/clear/flip-ellipse 761 (lambda (dc) 762 (send dc set-pen (send gui:the-pen-list find-or-create-pen "WHITE" 1 'solid)) 763 (send dc set-brush (send gui:the-brush-list find-or-create-brush "WHITE" 'solid))) 764 viewport p width height)))) 765 766(define make-do-pointlist 767 (lambda (go name get-pen-name set-pen-name 768 get-current-pen-name set-viewport-pen white-pen 769 get-brush-name set-brush-name invisi-brush) 770 (let ([f (make-draw-proc get-pen-name set-pen-name 771 get-current-pen-name set-viewport-pen white-pen)]) 772 (lambda (viewport) 773 (let ([f (f viewport)] 774 [vdc (viewport-dc viewport)] 775 [vbdc (viewport-buffer-dc viewport)]) 776 (letrec ([the-function 777 (case-lambda 778 [(posns offset) (the-function posns offset #f)] 779 [(posns offset color) 780 (f color 781 (lambda (flip clear) 782 (let* ([points (map (lambda (p) 783 (make-object gui:point% (posn-x p) (posn-y p))) 784 posns)] 785 [x (posn-x offset)] 786 [y (posn-y offset)] 787 [orig (send/proc vdc get-brush-name)] 788 [draw (lambda () 789 (send/proc vdc set-brush-name 790 invisi-brush) 791 (send/proc vbdc set-brush-name 792 invisi-brush) 793 (send/proc 794 (viewport-dc viewport) name 795 points x y) 796 (send/proc 797 (viewport-buffer-dc viewport) name 798 points x y) 799 (send/proc vdc set-brush-name orig) 800 (send/proc vbdc set-brush-name 801 orig))]) 802 (go draw 803 (lambda () (flip draw)) 804 (lambda () (clear draw))))))])]) 805 the-function)))))) 806 807(define make-do-polygon 808 (lambda (go) 809 (make-do-pointlist go 'draw-polygon 'get-pen 'set-pen 810 'get-current-pen set-viewport-pen white-pen 811 'get-brush 'set-brush invisi-brush))) 812 813(define make-do-solid-polygon 814 (lambda (go) 815 (make-do-pointlist go 'draw-polygon 'get-brush 'set-brush 816 'get-current-brush set-viewport-brush white-brush 817 'get-pen 'set-pen invisi-pen))) 818 819(define draw-polygon (make-do-polygon draw-it)) 820(define (clear-polygon viewport) 821 (let ([f ((make-do-polygon clear-it) viewport)]) 822 (rec clear-polygon-viewport 823 (lambda (posns offset) 824 (f posns offset))))) 825(define (flip-polygon viewport) 826 (let ([f ((make-do-polygon flip-it) viewport)]) 827 (rec flip-polygon-viewport 828 (lambda (posns offset) 829 (f posns offset))))) 830 831(define draw-solid-polygon (make-do-solid-polygon draw-it)) 832(define (clear-solid-polygon viewport) 833 (let ([f ((make-do-solid-polygon clear-it) viewport)]) 834 (rec clear-solid-polygon-viewport 835 (lambda (posns offset) 836 (f posns offset))))) 837(define (flip-solid-polygon viewport) 838 (let ([f ((make-do-solid-polygon flip-it) viewport)]) 839 (rec flip-solid-polygon-viewport 840 (lambda (posns offset) 841 (f posns offset))))) 842 843(define make-do-pixel 844 (lambda (go) 845 (let ([f (make-draw-proc 'get-pen 'set-pen 846 'get-current-pen set-viewport-pen white-pen)]) 847 (lambda (viewport) 848 (let ([f (f viewport)]) 849 (letrec ([the-function 850 (case-lambda 851 [(posn) (the-function posn #f)] 852 [(posn color) 853 (f color 854 (lambda (flip clear) 855 (let* ([x (posn-x posn)] 856 [y (posn-y posn)] 857 [draw (lambda () 858 (send 859 (viewport-dc viewport) draw-point 860 x y) 861 (send 862 (viewport-buffer-dc viewport) 863 draw-point 864 x y))]) 865 (go draw 866 (lambda () (flip draw)) 867 (lambda () (clear draw))))))])]) 868 the-function)))))) 869 870(define draw-pixel (make-do-pixel draw-it)) 871(define (clear-pixel viewport) 872 (let ([f ((make-do-pixel clear-it) viewport)]) 873 (rec clear-pixel-viewport 874 (lambda (posns offset) 875 (f posns offset))))) 876(define (flip-pixel viewport) 877 (let ([f ((make-do-pixel flip-it) viewport)]) 878 (rec flip-pixel-viewport 879 (lambda (posns offset) 880 (f posns offset))))) 881 882(define string-functions 883 (lambda (string-op) 884 (letrec ([outer-function 885 (case-lambda 886 [(viewport) (outer-function viewport default-font)] 887 [(viewport font) 888 (letrec ([the-function 889 (case-lambda 890 [(posn text) (the-function posn text #f)] 891 [(posn text color) 892 (let*-values ([(dc) (viewport-dc viewport)] 893 [(x) (posn-x posn)] 894 [(w h d a) (send dc get-text-extent "X" font)] 895 [(y) (- (posn-y posn) (- h d))] 896 [(buffer) (viewport-buffer-dc viewport)] 897 [(string-create) 898 (lambda () 899 (send dc draw-text text x y) 900 (send buffer draw-text text x y))]) 901 (cond 902 [(eq? string-op 'draw) 903 (when color 904 (set-text-foreground viewport color)) 905 (set-viewport-font viewport font) 906 (send dc draw-text text x y) 907 (send buffer draw-text text x y)] 908 [(eq? string-op 'flip) 909 (when color 910 (set-text-foreground viewport color)) 911 (set-viewport-font viewport font) 912 (string-create)] 913 [(eq? string-op 'clear) 914 (set-text-foreground viewport white) 915 (set-viewport-font viewport font) 916 (string-create) 917 (set-text-foreground viewport black)]))])]) 918 the-function)])]) 919 outer-function))) 920 921(define draw-string (string-functions 'draw)) 922(define (clear-string viewport) 923 (let ([f ((string-functions 'clear) viewport)]) 924 (rec clear-string-viewport 925 (lambda (posns offset) 926 (f posns offset))))) 927(define (flip-string viewport) 928 (let ([f ((string-functions 'flip) viewport)]) 929 (rec flip-string-viewport 930 (lambda (posns offset) 931 (f posns offset))))) 932 933(define get-string-size 934 (case-lambda 935 [(viewport) (get-string-size viewport default-font)] 936 [(viewport font) 937 (lambda (text) 938 (let-values ([(w h d a) (send (viewport-dc viewport) get-text-extent text font)]) 939 (list w h)))])) 940 941(define get-color-pixel 942 (lambda (viewport) 943 (lambda (posn) 944 (let ([c (make-object gui:color%)] 945 [x (posn-x posn)] 946 [y (posn-y posn)]) 947 (unless (send (viewport-buffer-dc viewport) get-pixel x y c) 948 (error 'get-color-pixel "specified point is out-of-range")) 949 c)))) 950 951(define get-pixel 952 (lambda (viewport) 953 (lambda (posn) 954 (let ([c (make-object gui:color%)] 955 [x (posn-x posn)] 956 [y (posn-y posn)]) 957 (unless (send (viewport-buffer-dc viewport) get-pixel x y c) 958 (error 'get-pixel "specified point is out-of-range")) 959 (if (or (< (send c blue) 255) 960 (< (send c red) 255) 961 (< (send c green) 255)) 962 1 963 0))))) 964 965(define (test-pixel viewport) 966 (lambda (color) 967 (let ([c (make-object gui:color%)]) 968 (send (viewport-buffer-dc viewport) try-color color c) 969 c))) 970 971(define draw-pixmap-posn 972 (lambda (filename [type 'unknown/mask]) 973 (check 'draw-pixmap-posn 974 string? filename "filename" 975 (lambda (x) (memq x '(gif xbm xpm bmp pict unknown unknown/mask gif/mask))) type "file type symbol") 976 (let* ([bitmap (make-object gui:bitmap% filename type)]) 977 (lambda (viewport) 978 (check 'draw-pixmap-posn 979 viewport? viewport "viewport") 980 (lambda (posn [color #f]) 981 (check 'draw-pixmap-posn 982 posn? posn "posn" 983 (orp not color?) color (format "color or ~e" #f)) 984 (when color 985 (set-viewport-pen viewport (get-color color))) 986 (let ([x (posn-x posn)] 987 [y (posn-y posn)]) 988 (send (viewport-dc viewport) draw-bitmap bitmap x y 'solid black-color (send bitmap get-loaded-mask)) 989 (send (viewport-buffer-dc viewport) draw-bitmap bitmap x y 'solid black-color (send bitmap get-loaded-mask)))))))) 990 991(define draw-pixmap 992 (lambda (viewport) 993 (check 'draw-pixmap 994 viewport? viewport "viewport") 995 (lambda (filename p [color #f]) 996 (check 'draw-pixmap 997 (andp string? file-exists?) filename "filename" 998 posn? p "posn" 999 (orp not color?) color (format "color or ~e" #f)) 1000 (((draw-pixmap-posn filename 'unknown) viewport) p color)))) 1001 1002(define copy-viewport 1003 (lambda (source target) 1004 (check 'copy-viewport 1005 viewport? source "viewport" 1006 viewport? target "viewport") 1007 (let* ([source-bitmap (viewport-bitmap source)] 1008 [target-dc (viewport-dc target)] 1009 [target-buffer-dc (viewport-buffer-dc target)]) 1010 (send target-dc draw-bitmap source-bitmap 0 0) 1011 (send target-buffer-dc draw-bitmap source-bitmap 0 0)))) 1012 1013(define save-pixmap 1014 (lambda (viewport) 1015 (check 'save-pixmap 1016 viewport? viewport "viewport") 1017 (lambda (filename [kind 'xpm]) 1018 (check 'save-pixmap 1019 (andp string? (orp relative-path? absolute-path?)) filename "filename" 1020 (lambda (x) (memq x '(xpm xbm bmp pict))) kind "file type symbol") 1021 (let ([bm (viewport-bitmap viewport)]) 1022 (send bm save-file filename kind))))) 1023 1024(define sixlib-eventspace #f) 1025 1026(define make-open-viewport 1027 (lambda (name show?) 1028 (unless sixlib-eventspace 1029 (set! sixlib-eventspace 1030 (parameterize ([uncaught-exception-handler 1031 (lambda (x) 1032 ((error-display-handler) 1033 (format "internal error in graphics library: ~a" 1034 (if (exn? x) 1035 (exn-message x) 1036 (format "~e" x))) 1037 x) 1038 ((error-escape-handler)))]) 1039 (gui:make-eventspace)))) 1040 (letrec ([open-viewport 1041 (case-lambda 1042 [(label point) 1043 (cond 1044 [(posn? point) (open-viewport label (posn-x point) (posn-y point))] 1045 [(and (list? point) (= (length point) 2)) 1046 (open-viewport label (car point) (cadr point))] 1047 [else (error name "bad argument ~s" point)])] 1048 [(label width height) 1049 (cond 1050 [graphics-flag 1051 (let* 1052 ([frame 1053 (parameterize ([gui:current-eventspace sixlib-eventspace]) 1054 (make-object sixlib-frame% 1055 label #f width height))] 1056 [panel (make-object gui:vertical-panel% frame)] 1057 [canvas (make-object sixlib-canvas% panel)] 1058 [_ (begin 1059 (send canvas min-height height) 1060 (send canvas min-width width))] 1061 [dc (send canvas get-dc)] 1062 [buffer-dc (make-object gui:bitmap-dc%)] 1063 [viewport (make-viewport label canvas)] 1064 [ml (event-receiver)] 1065 [kl (event-receiver)]) 1066 (send panel set-alignment 'center 'center) 1067 (send frame set-canvas canvas) 1068 (send canvas set-viewport viewport) 1069 (send canvas set-dc dc) 1070 (send canvas set-buffer-dc buffer-dc) 1071 (send canvas set-geometry width height) 1072 (send canvas set-mouse-listener ml) 1073 (send canvas set-key-listener kl) 1074 (when show? 1075 (send frame show #t) 1076 (send canvas focus)) 1077 (set-text-foreground viewport black) 1078 (set-text-background viewport white) 1079 (set-viewport-background viewport white) 1080 (set-viewport-pen viewport black-pen) 1081 (set-viewport-brush viewport black-brush) 1082 ((clear-viewport viewport)) 1083 (when (null? global-viewport-list) 1084 (send open-frames-timer start 100000000)) 1085 (set! global-viewport-list (cons viewport global-viewport-list)) 1086 viewport)] 1087 [else (error "graphics not open")])])]) 1088 open-viewport))) 1089 1090(define open-viewport (make-open-viewport 'open-viewport #t)) 1091(define open-pixmap (make-open-viewport 'open-pixmap #f)) 1092 1093(define (default-display-is-color?) (gui:is-color-display?)) 1094 1095(define position-display 1096 (lambda (viewport counter) 1097 (cond 1098 [(equal? counter 0) '()] 1099 [else (begin 1100 (display (query-mouse-posn viewport)) 1101 (position-display viewport (- counter 1)))]))) 1102 1103 1104(define create-cmap 1105 (lambda () 1106 (do ([index 0 (+ 1 index)]) 1107 ((> index 20)) 1108 (let* ([r (* 0.05 index)] 1109 [b (- 1 r)] 1110 [g (- 1 r)]) 1111 (change-color index (make-rgb r g b)))))) 1112 1113(define viewport->snip 1114 (lambda (viewport) 1115 (let ([orig-bitmap (send (viewport-canvas viewport) get-bitmap)] 1116 [orig-dc (viewport-buffer-dc viewport)]) 1117 (let* ([h (send orig-bitmap get-height)] 1118 [w (send orig-bitmap get-width)] 1119 [new-bitmap (make-object gui:bitmap% w h)] 1120 [tmp-mem-dc (make-object gui:bitmap-dc%)]) 1121 (send tmp-mem-dc set-bitmap new-bitmap) 1122 (send tmp-mem-dc draw-bitmap (send orig-dc get-bitmap) 0 0) 1123 (send tmp-mem-dc set-bitmap #f) 1124 (let ([snip (make-object gui:image-snip%)]) 1125 (send snip set-bitmap new-bitmap) 1126 snip))))) 1127 1128(create-cmap) 1129 1130 1131;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1132;;; ;;; 1133;;; ERROR CHECKING ;;; 1134;;; ;;; 1135;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1136 1137 1138;; check-viewport : symbol TST -> void 1139(define (check-viewport f-name obj) 1140 (unless (viewport? obj) 1141 (error f-name "expected viewport as first argument, got ~e" obj))) 1142 1143;; (define-type arg/pred/name-list (list* (TST -> bool) TST string arg/pred/name-list)) 1144;; check : (symbol arg/pred/name-list *-> void) 1145(define (check f-name . in-args) 1146 (let loop ([args in-args] 1147 [n 0]) 1148 (cond 1149 [(null? args) (void)] 1150 [else (let ([pred? (car args)] 1151 [val (cadr args)] 1152 [name (caddr args)]) 1153 (unless (pred? val) 1154 (error f-name "expected ~a as arg ~a, got: ~e, all args: ~a" 1155 name n val 1156 (let loop ([args in-args]) 1157 (cond 1158 [(null? args) ""] 1159 [else (string-append (format "~e" (cadr args)) 1160 " " 1161 (loop (cdddr args)))])))) 1162 (loop (cdddr args) 1163 (+ n 1)))]))) 1164 1165(define (orp . preds) 1166 (lambda (TST) 1167 (ormap (lambda (p) (p TST)) preds))) 1168 1169(define (andp . preds) 1170 (lambda (TST) 1171 (andmap (lambda (p) (p TST)) preds))) 1172