[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Off-screen drawing problem

I have been trying to draw off-screen to a bitmap, and copying the off-screen
image into a visible window.  (The goal is to eliminate flicker as windows
are redrawn.)  I seem to be able to copy the image OK, but I can't draw to the
off-screen bitmap.

I wrote a small example that creates a window and an off-screen buffer, and
tries to make them interact.  As it appears below, the buffer's .portBits
are left to be the default, which is the bitmap for the entire screen.  So
when you copy from the buffer into the main window, you get an image of the
upper-left corner of the screen.

When I try to allocate my own portBits, using ccl:make-bitmap, I still can't
seem to draw to the buffer (this instruction is commented out in
MAC-create-buffer below).  Then, when I copy from the buffer into the window,
I just get a bunch of garbage because it was never initialized to anything

Does anyone have an example of off-screen drawing that works, or could you
make a small modification to this code to get it to work properly?  I have the
feeling that all it needs is the proper setting of a pointer, or something.

Thanks very much,

--Andrew Mickish

(in-package :COMMON-LISP-USER)

;; Load required MCL files
   (progn (require 'traps)
          (require 'interfaces)
          (require 'quickdraw)
          (ccl::require-interface 'quickdraw)
          (ccl::require-interface 'events)

(defvar *region-to-clear* (ccl:new-region))

;;; The class for the MAIN window
(defparameter *MAC-DRAWABLE*
  (defclass MAC-DRAWABLE
    ((plist :initarg :plist
            :initform :plist-init))))

(let ((counter -1))
  (defun next-color ()
    (incf counter)
    (case counter
      (0 ccl:*red-color*)
      (1 ccl:*green-color*)
      (2 ccl:*yellow-color*)
      (3 (setf counter -1)

(defun MAC-draw-rectangle (drawable left top width height pen-mode fill-color)
  (let* ((right (+ left width))
         (bottom (+ top height)))
    (ccl:set-pen-mode drawable pen-mode)
    (ccl::with-rectangle-arg (r left top right bottom)
      (ccl:with-fore-color fill-color
        (#_PaintRect r)))))

(defun MAC-create-window (parent-window x y width height title)
  (let ((drawable
             (make-instance 'MAC-DRAWABLE
               :view-position (ccl:make-point x y)
               :view-size (ccl:make-point width height)
               :close-box-p T
               :window-type :document-with-zoom
               :window-show NIL
               :window-title title
               :color-p T
               :plist NIL)))

(defun draw-colored-rect (x y)
  (MAC-draw-rectangle main x y 100 100 :patCopy (next-color)))

;;; Set up a window to show the operations

;;;  Create a window
(setf main (mac-create-window NIL 515 45 200 150 "Main"))
(ccl:window-show main)

;;; Clear the window and draw a rectangle in it.  (This works repeatedly.)
(ccl:with-focused-view main
  (ccl:set-rect-region *region-to-clear* 0 0 200 150)
  (#_EraseRgn *region-to-clear*)
  (draw-colored-rect 20 20))

;;;  Now show the undesirable behavior

(defun MAC-create-buffer (width height &optional bitmap-p)
  (declare (ignore bitmap-p))
  (let ((old-device (#_GetGDevice))
        ;; The old-device might not be the deepest screen
        (deepest-screen (ccl::with-rectangle-arg (r 0 0 ccl:*screen-width*
                          (#_GetMaxDevice r)))
        (image (ccl:make-bitmap 0 0 width height))

    ;(#_SetGDevice deepest-screen)

    ;; The buffer is a top-level window, just like the main window, except that
    ;; I never call ccl:window-show on it.
    (setf buffer (MAC-create-window NIL 0 0 width height "BUFFER"))

    ;; If I try to set the portBits myself, then only garbage will get copied
    ;; into the main window later.  Maybe this is because I never succeed in
    ;; drawing to the buffer?
    ;(ccl:rset (ccl:wptr buffer) :GrafPort.portBits image)

    ;(#_SetGDevice old-device)

;;; Try to draw another rectangle "off-screen", and copy the image back
;;; into the main window.  Currently, this just copies an image of the
;;; upper-left corner of the screen into the main window.  Uncommenting the
;;; appropriate line in MAC-create-buffer will give the buffer its own bitmap.
(let ((buffer (MAC-create-buffer 200 150)))
  (ccl:with-focused-view buffer
    (draw-colored-rect 30 30))
  (ccl::with-rectangle-arg (r 0 0 200 150)
    (ccl:copy-bits (ccl:rref (ccl:wptr buffer) :Grafport.portBits)
                   (ccl:rref (ccl:wptr main) :Grafport.portBits)
                   r r)))