home *** CD-ROM | disk | FTP | other *** search
- (in-package :oou)
- (oou-provide :QuickDraw-u)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; QuickDraw-u.lisp
- ;;
- ;; Copyright ⌐ 1992 Northwestern University Institute for the Learning Sciences
- ;; All Rights Reserved
- ;;
- ;; author: Michael S. Engber
- ;;
- ;; utilities for quickdraw
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (oou-dependencies
- :records-u)
-
- (export '( with-pen-state
- with-text-state with-font-spec
- with-back-pat with-back-pix-pat
- with-hilite-color
- with-current-portBits
- with-clip-rgn
- with-QDProcs
- move-region-to
- frame-rect-3D
- ))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; macros
-
- (eval-when (:compile-toplevel :load-toplevel :execute)
-
- (defmacro with-pen-state ((&key pnLoc pnSize pnMode pnPat pnPixPat) &body body)
- (let ((state (gensym)))
- `(rlet ((,state :PenState))
- (require-trap #_GetPenState ,state)
- (unwind-protect
- (progn
- ,@(when pnLoc `((require-trap #_MoveTo (point-h ,pnLoc) (point-v ,pnLoc))))
- ,@(when pnSize `((require-trap #_PenSize (point-h ,pnSize) (point-v ,pnSize))))
- ,@(when pnMode `((require-trap #_PenMode ,pnMode)))
- ,@(when pnPat `((require-trap #_PenPat ,pnPat)))
- ,@(when pnPixPat `((require-trap #_PenPixPat ,pnPixPat)))
- ,@body)
- (require-trap #_SetPenState ,state)))))
-
- ;;;;;;;;;;
- ;;font macros
-
- (defmacro with-text-state ((&key txFont txFace txMode txSize) &body body)
- (let ((thePort (gensym))
- (old-font (gensym))
- (old-face (gensym))
- (old-mode (gensym))
- (old-size (gensym)))
- `(with-macptrs ((,thePort (%getport)))
- (let(,@(when txFont `((,old-font (pref ,thePort :GrafPort.txFont))))
- ,@(when txFace `((,old-face (pref ,thePort :GrafPort.txFace))))
- ,@(when txMode `((,old-mode (pref ,thePort :GrafPort.txMode))))
- ,@(when txSize `((,old-size (pref ,thePort :GrafPort.txSize)))))
- (unwind-protect
- (progn
- ,@(when txFont `((require-trap #_TextFont ,txFont)))
- ,@(when txFace `((require-trap #_TextFace ,txFace)))
- ,@(when txMode `((require-trap #_TextMode ,txMode)))
- ,@(when txSize `((require-trap #_TextSize ,txSize)))
- ,@body)
- ,@(when txFont `((require-trap #_TextFont ,old-font)))
- ,@(when txFace `((require-trap #_TextFace ,old-face)))
- ,@(when txMode `((require-trap #_TextMode ,old-mode)))
- ,@(when txSize `((require-trap #_TextSize ,old-size))))))))
-
- (defmacro with-font-spec (font-spec &body body)
- (if (and (listp font-spec) (every #'constantp font-spec))
- (multiple-value-bind (ff ms) (font-codes font-spec)
- `(with-font-codes ,ff ,ms ,@body))
- (let ((ff (gensym))
- (ms (gensym)))
- `(multiple-value-bind (,ff ,ms) (font-codes ,font-spec)
- (with-font-codes ,ff ,ms ,@body)))))
-
- ;;;;;;;;;;
- ;; macros for getting an appropriate ptr from the current port to pass to CopyBits
- ;; Note: this works with both GrafPort's AND CGrafPort's
-
- (defmacro with-current-portBits (portBits &body body)
- `(with-macptrs ((,portBits (pref (%getport) :GrafPort.portBits)))
- ,@body))
-
-
- ;;;;;;;;;;
- ;; BackPat macros
- ;; Note: these both work with GrafPort's AND CGrafPort's
-
- (defmacro with-back-pat (pattern &body body)
- (let ((fn (gensym)))
- `(flet ((,fn () (require-trap #_BackPat ,pattern) ,@body))
- (declare (dynamic-extent #',fn))
- (call-with-back-pat-saved #',fn))))
-
- (defmacro with-back-pix-pat (pix-pat &body body)
- (let ((fn (gensym))
- (data_p (gensym)))
- `(flet ((,fn ()
- (if (zerop (href ,pix-pat PixPat.patType))
- (with-dereferenced-handles ((,data_p (href ,pix-pat PixPat.patData)))
- (require-trap #_BackPat ,data_p))
- (require-trap #_BackPixPat ,pix-pat))
- ,@body))
- (declare (dynamic-extent #',fn))
- (call-with-back-pat-saved #',fn))))
-
- ;;;;;;;;;;
- ;; hilite color macro
- (defmacro with-hilite-color (color &body body)
- (let ((fn (gensym))
- (rgb (gensym)))
- `(flet ((,fn () ,@body))
- (declare (dynamic-extent #',fn))
- (with-rgb (,rgb ,color)
- (call-with-hilite-color ,rgb #',fn)))))
-
- ;;;;;;;;;;
- ;;clip macros
-
- (defmacro with-clip-rgn (clip-rgn &body body)
- (let ((old-clip (gensym)))
- `(with-macptrs ((,old-clip (require-trap #_NewRgn)))
- (unwind-protect
- (progn
- (require-trap #_GetClip ,old-clip)
- (require-trap #_SetClip ,clip-rgn)
- ,@body)
- (require-trap #_SetClip ,old-clip)
- (require-trap #_DisposeRgn ,old-clip)))))
-
- ;;;;;;;;;;
- ;;QDProc macro
- ;; Note: these both work with GrafPort's AND CGrafPort's
-
- (defmacro with-QDProcs ((&key textProc lineProc rectProc rRectProc ovalProc arcProc polyProc
- rgnProc bitsProc commentProc txMeasProc getPicProc putPicProc
- opCodeProc newProc1 newProc2 newProc3 newProc4 newProc5 newProc6
- )
- &body body)
- ;;GrafPorts & CGrafPorts are handled identically! This works because:
- ;; - the first 13 fields of a CQDProc are a QDProc
- ;; - both GrafPorts & CGrafPorts use the same stdProcs for these 13 fields.
- (let ((thePort (gensym))
- (old-procs (gensym))
- (new-procs (gensym)))
- `(with-macptrs ((,thePort (%getport))
- (,old-procs (pref ,thePort :GrafPort.grafProcs)))
- (rlet ((,new-procs :CQDProcs))
- (if (%null-ptr-p ,old-procs)
- (require-trap #_SetStdCProcs ,new-procs)
- (require-trap #_BlockMove ,old-procs ,new-procs (rlength :CQDProcs)))
- ,@(when textProc `((pset ,new-procs :CQDProcs.textProc ,textProc )))
- ,@(when lineProc `((pset ,new-procs :CQDProcs.lineProc ,lineProc )))
- ,@(when rectProc `((pset ,new-procs :CQDProcs.rectProc ,rectProc )))
- ,@(when rRectProc `((pset ,new-procs :CQDProcs.rRectProc ,rRectProc )))
- ,@(when ovalProc `((pset ,new-procs :CQDProcs.textProc ,ovalProc )))
- ,@(when arcProc `((pset ,new-procs :CQDProcs.arcProc ,arcProc )))
- ,@(when polyProc `((pset ,new-procs :CQDProcs.polyProc ,polyProc )))
- ,@(when rgnProc `((pset ,new-procs :CQDProcs.rgnProc ,rgnProc )))
- ,@(when bitsProc `((pset ,new-procs :CQDProcs.bitsProc ,bitsProc )))
- ,@(when commentProc `((pset ,new-procs :CQDProcs.commentProc ,commentProc)))
- ,@(when txMeasProc `((pset ,new-procs :CQDProcs.txMeasProc ,txMeasProc )))
- ,@(when getPicProc `((pset ,new-procs :CQDProcs.getPicProc ,getPicProc )))
- ,@(when putPicProc `((pset ,new-procs :CQDProcs.putPicProc ,putPicProc )))
- ,@(when opCodeProc `((pset ,new-procs :CQDProcs.opCodeProc ,opCodeProc )))
- ,@(when newProc1 `((pset ,new-procs :CQDProcs.newProc1 ,newProc1 )))
- ,@(when newProc2 `((pset ,new-procs :CQDProcs.newProc2 ,newProc2 )))
- ,@(when newProc3 `((pset ,new-procs :CQDProcs.newProc3 ,newProc3 )))
- ,@(when newProc4 `((pset ,new-procs :CQDProcs.newProc4 ,newProc4 )))
- ,@(when newProc5 `((pset ,new-procs :CQDProcs.newProc5 ,newProc5 )))
- ,@(when newProc6 `((pset ,new-procs :CQDProcs.newProc6 ,newProc6 )))
- (unwind-protect
- (progn
- (pset ,thePort :CGrafPort.grafProcs ,new-procs)
- ,@body)
- (pset ,thePort :CGrafPort.grafProcs ,old-procs))))))
-
- )
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- (defun call-with-back-pat-saved (fn)
- (with-macptrs ((thePort (%getport)))
- (let ((pat-type 0))
- (declare (dynamic-extent pat-type))
- (rlet ((old-pat :Pattern))
- (if (wptr-color-p thePort)
- (with-macptrs ((ppat (pref thePort :CGrafPort.bkPixPat)))
- (setf pat-type (href ppat PixPat.patType))
- (if (zerop pat-type)
- (with-dereferenced-handles ((data_p (href ppat PixPat.patData)))
- (pset old-pat :Pattern data_p))
- (%setf-macptr old-pat (pref thePort :CGrafPort.bkPixPat))))
- (#_BlockMove (pref thePort :GrafPort.bkPat) old-pat (rlength :Pattern)))
- (unwind-protect
- (funcall fn)
- (if (zerop pat-type)
- (#_BackPat old-pat)
- (#_BackPixPat old-pat)))))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defun call-with-hilite-color (rgb fn)
- (with-macptrs ((thePort (%getport)))
- (if (wptr-color-p thePort)
- (rlet ((old-hiliteRGB :RGBColor))
- (with-dereferenced-handles ((grafVars (pref thePort :CGrafPort.grafVars)))
- (pset old-hiliteRGB :RGBColor (pref grafVars :GrafVars.rgbHiliteColor)))
- (unwind-protect
- (progn
- (#_HiliteColor rgb)
- (funcall fn))
- (#_HiliteColor old-hiliteRGB)))
- (rlet ((old-hiliteRGB :RGBColor))
- (with-macptrs ((global-hilite-rgb (%int-to-ptr #$HiliteRGB)))
- (pset old-hiliteRGB :RGBColor global-hilite-rgb)
- (unwind-protect
- (progn
- (pset global-hilite-rgb :RGBColor rgb)
- (funcall fn))
- (pset global-hilite-rgb :RGBColor rgb)))))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defun move-region-to (rgn-handle h &optional v)
- (let* ((delta (make-point h v))
- (dh (point-h delta))
- (dv (point-v delta)))
- (#_OffsetRgn rgn-handle (- dh (href rgn-handle :Region.rgnBBox.left))
- (- dv (href rgn-handle :Region.rgnBBox.top )))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;;Mac human interface guidlines specify that the light source is in the
- ;;upper-left corner. Hence and botRight shadow gives a "popped out" look
- ;;and a topLeft shadow gives a "pushed in" look.
-
- (defun frame-rect-3D (rect frame-width shadow-position)
- ;;Frame's the specified Rect with a 3D look.
- ;;Note: this effect only looks right over patterned or colored backgrounds
- (let* ((%top (pref rect :Rect.top ))
- (%left (pref rect :Rect.left ))
- (%bot (pref rect :Rect.bottom))
- (%right (pref rect :Rect.right )))
- (with-pen-state (:pnSize (make-point frame-width frame-width)
- :pnMode #$patCopy
- :pnLoc (make-point %left (- %bot frame-width)))
- ;;left & top edges
- (#_PenPat (ecase shadow-position (:topLeft *black-pattern*) (:botRight *white-pattern*)))
- (#_LineTo %left %top)
- (#_LineTo (- %right frame-width) %top)
-
- ;;right & bottom edges
- (#_PenPat (ecase shadow-position (:topLeft *white-pattern*) (:botRight *black-pattern*)))
- (#_LineTo (- %right frame-width) (- %bot frame-width))
- (#_LineTo %left (- %bot frame-width))
-
- ;;topRight & botLeft corners
- (#_PenPat (ecase shadow-position (:topLeft *black-pattern*) (:botRight *white-pattern*)))
- (#_PenSize 1 1)
- (#_MoveTo (- %right frame-width) (+ %top frame-width -2))
- (dotimes (i (1- frame-width)) (#_Line i 0) (#_Move (- i) -1))
- (#_MoveTo %left (1- %bot))
- (dotimes (i frame-width) (#_Line i 0) (#_Move (- i) -1)))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-