;;; -*- Mode: LISP; Syntax: Common-lisp; Package: XLIB; Base: 10; Lowercase: Yes -*- ;;; CLX drawing requests ;;; ;;; TEXAS INSTRUMENTS INCORPORATED ;;; P.O. BOX 2909 ;;; AUSTIN, TEXAS 78769 ;;; ;;; Copyright (C) 1987 Texas Instruments Incorporated. ;;; ;;; Permission is granted to any individual or institution to use, copy, modify, ;;; and distribute this software, provided that this complete copyright and ;;; permission notice is maintained, intact, in all copies and supporting ;;; documentation. ;;; ;;; Texas Instruments Incorporated provides this software "as is" without ;;; express or implied warranty. ;;; (in-package :xlib) (defvar *inhibit-appending* nil) (defun draw-point (drawable gcontext x y) ;; Should be clever about appending to existing buffered protocol request. (declare (type drawable drawable) (type gcontext gcontext) (type int16 x y)) (let ((display (drawable-display drawable))) (declare (type display display)) (with-display (display) (force-gcontext-changes-internal gcontext) (with-buffer-output (display :length *requestsize*) (let* ((last-request-byte (display-last-request display)) (current-boffset buffer-boffset)) ;; To append or not append, that is the question (if (and (not *inhibit-appending*) last-request-byte ;; Same request? (= (aref-card8 buffer-bbuf last-request-byte) *x-polypoint*) (progn ;; Set buffer pointers to last request (set-buffer-offset last-request-byte) ;; same drawable and gcontext? (or (compare-request (4) (data 0) (drawable drawable) (gcontext gcontext)) (progn ;; If failed, reset buffer pointers (set-buffer-offset current-boffset) nil)))) ;; Append request (progn ;; Set new request length (card16-put 2 (index+ 1 (index-ash (index- current-boffset last-request-byte) -2))) (set-buffer-offset current-boffset) (put-items (0) ; Insert new point (int16 x y)) (setf (display-boffset display) (index+ buffer-boffset 4))) ;; New Request (progn (put-items (4) (code *x-polypoint*) (data 0) ;; Relative-p false (length 4) (drawable drawable) (gcontext gcontext) (int16 x y)) (buffer-new-request-number display) (setf (buffer-last-request display) buffer-boffset) (setf (display-boffset display) (index+ buffer-boffset 16))))))) (display-invoke-after-function display))) (defun draw-points (drawable gcontext points &optional relative-p) (declare (type drawable drawable) (type gcontext gcontext) (type sequence points) ;(repeat-seq (integer x) (integer y)) (type boolean relative-p)) (with-buffer-request ((drawable-display drawable) *x-polypoint* :gc-force gcontext) ((data boolean) relative-p) (drawable drawable) (gcontext gcontext) ((sequence :format int16) points))) (defun draw-line (drawable gcontext x1 y1 x2 y2 &optional relative-p) ;; Should be clever about appending to existing buffered protocol request. (declare (type drawable drawable) (type gcontext gcontext) (type int16 x1 y1 x2 y2) (type boolean relative-p)) (let ((display (drawable-display drawable))) (declare (type display display)) (when relative-p (incf x2 x1) (incf y2 y1)) (with-display (display) (force-gcontext-changes-internal gcontext) (with-buffer-output (display :length *requestsize*) (let* ((last-request-byte (display-last-request display)) (current-boffset buffer-boffset)) ;; To append or not append, that is the question (if (and (not *inhibit-appending*) last-request-byte ;; Same request? (= (aref-card8 buffer-bbuf last-request-byte) *x-polysegment*) (progn ;; Set buffer pointers to last request (set-buffer-offset last-request-byte) ;; same drawable and gcontext? (or (compare-request (4) (drawable drawable) (gcontext gcontext)) (progn ;; If failed, reset buffer pointers (set-buffer-offset current-boffset) nil)))) ;; Append request (progn ;; Set new request length (card16-put 2 (index+ 2 (index-ash (index- current-boffset last-request-byte) -2))) (set-buffer-offset current-boffset) (put-items (0) ; Insert new point (int16 x1 y1 x2 y2)) (setf (display-boffset display) (index+ buffer-boffset 8))) ;; New Request (progn (put-items (4) (code *x-polysegment*) (length 5) (drawable drawable) (gcontext gcontext) (int16 x1 y1 x2 y2)) (buffer-new-request-number display) (setf (buffer-last-request display) buffer-boffset) (setf (display-boffset display) (index+ buffer-boffset 20))))))) (display-invoke-after-function display))) (defun draw-lines (drawable gcontext points &key relative-p fill-p (shape :complex)) (declare (type drawable drawable) (type gcontext gcontext) (type sequence points) ;(repeat-seq (integer x) (integer y)) (type boolean relative-p fill-p) (type (member :complex :non-convex :convex) shape)) (if fill-p (fill-polygon drawable gcontext points relative-p shape) (with-buffer-request ((drawable-display drawable) *x-polyline* :gc-force gcontext) ((data boolean) relative-p) (drawable drawable) (gcontext gcontext) ((sequence :format int16) points)))) ;; Internal function called from DRAW-LINES (defun fill-polygon (drawable gcontext points relative-p shape) ;; This is clever about appending to previous requests. Should it be? (declare (type drawable drawable) (type gcontext gcontext) (type sequence points) ;(repeat-seq (integer x) (integer y)) (type boolean relative-p) (type (member :complex :non-convex :convex) shape)) (with-buffer-request ((drawable-display drawable) *x-fillpoly* :gc-force gcontext) (drawable drawable) (gcontext gcontext) ((member8 :complex :non-convex :convex) shape) (boolean relative-p) ((sequence :format int16) points))) (defun draw-segments (drawable gcontext segments) (declare (type drawable drawable) (type gcontext gcontext) ;; (repeat-seq (integer x1) (integer y1) (integer x2) (integer y2))) (type sequence segments)) (with-buffer-request ((drawable-display drawable) *x-polysegment* :gc-force gcontext) (drawable drawable) (gcontext gcontext) ((sequence :format int16) segments))) (defun draw-rectangle (drawable gcontext x y width height &optional fill-p) ;; Should be clever about appending to existing buffered protocol request. (declare (type drawable drawable) (type gcontext gcontext) (type int16 x y) (type card16 width height) (type boolean fill-p)) (let ((display (drawable-display drawable)) (request (if fill-p *x-polyfillrectangle* *x-polyrectangle*))) (declare (type display display) (type card16 request)) (with-display (display) (force-gcontext-changes-internal gcontext) (with-buffer-output (display :length *requestsize*) (let* ((last-request-byte (display-last-request display)) (current-boffset buffer-boffset)) ;; To append or not append, that is the question (if (and (not *inhibit-appending*) last-request-byte ;; Same request? (= (aref-card8 buffer-bbuf last-request-byte) request) (progn ;; Set buffer pointers to last request (set-buffer-offset last-request-byte) ;; same drawable and gcontext? (or (compare-request (4) (drawable drawable) (gcontext gcontext)) (progn ;; If failed, reset buffer pointers (set-buffer-offset current-boffset) nil)))) ;; Append request (progn ;; Set new request length (card16-put 2 (index+ 2 (index-ash (index- current-boffset last-request-byte) -2))) (set-buffer-offset current-boffset) (put-items (0) ; Insert new point (int16 x y) (card16 width height)) (setf (display-boffset display) (index+ buffer-boffset 8))) ;; New Request (progn (put-items (4) (code request) (length 5) (drawable drawable) (gcontext gcontext) (int16 x y) (card16 width height)) (buffer-new-request-number display) (setf (buffer-last-request display) buffer-boffset) (setf (display-boffset display) (index+ buffer-boffset 20))))))) (display-invoke-after-function display))) (defun draw-rectangles (drawable gcontext rectangles &optional fill-p) (declare (type drawable drawable) (type gcontext gcontext) ;; (repeat-seq (integer x) (integer y) (integer width) (integer height))) (type sequence rectangles) (type boolean fill-p)) (with-buffer-request ((drawable-display drawable) (if fill-p *x-polyfillrectangle* *x-polyrectangle*) :gc-force gcontext) (drawable drawable) (gcontext gcontext) ((sequence :format int16) rectangles))) (defun draw-arc (drawable gcontext x y width height angle1 angle2 &optional fill-p) ;; Should be clever about appending to existing buffered protocol request. (declare (type drawable drawable) (type gcontext gcontext) (type int16 x y) (type card16 width height) (type angle angle1 angle2) (type boolean fill-p)) (let ((display (drawable-display drawable)) (request (if fill-p *x-polyfillarc* *x-polyarc*))) (declare (type display display) (type card16 request)) (with-display (display) (force-gcontext-changes-internal gcontext) (with-buffer-output (display :length *requestsize*) (let* ((last-request-byte (display-last-request display)) (current-boffset buffer-boffset)) ;; To append or not append, that is the question (if (and (not *inhibit-appending*) last-request-byte ;; Same request? (= (aref-card8 buffer-bbuf last-request-byte) request) (progn ;; Set buffer pointers to last request (set-buffer-offset last-request-byte) ;; same drawable and gcontext? (or (compare-request (4) (drawable drawable) (gcontext gcontext)) (progn ;; If failed, reset buffer pointers (set-buffer-offset current-boffset) nil)))) ;; Append request (progn ;; Set new request length (card16-put 2 (index+ 3 (index-ash (index- current-boffset last-request-byte) -2))) (set-buffer-offset current-boffset) (put-items (0) ; Insert new point (int16 x y) (card16 width height) (angle angle1 angle2)) (setf (display-boffset display) (index+ buffer-boffset 12))) ;; New Request (progn (put-items (4) (code request) (length 6) (drawable drawable) (gcontext gcontext) (int16 x y) (card16 width height) (angle angle1 angle2)) (buffer-new-request-number display) (setf (buffer-last-request display) buffer-boffset) (setf (display-boffset display) (index+ buffer-boffset 24))))))) (display-invoke-after-function display))) (defun draw-arcs-list (drawable gcontext arcs &optional fill-p) (declare (type drawable drawable) (type gcontext gcontext) (type list arcs) (type boolean fill-p)) (let* ((display (drawable-display drawable)) (limit (index- (buffer-size display) 12)) (length (length arcs)) (request (if fill-p *x-polyfillarc* *x-polyarc*))) (with-buffer-request ((drawable-display drawable) request :gc-force gcontext) (drawable drawable) (gcontext gcontext) (progn (card16-put 2 (index+ (index-ash length -1) 3)) ; Set request length (in words) (set-buffer-offset (index+ buffer-boffset 12)) ; Position to start of data (do ((arc arcs)) ((endp arc) (setf (buffer-boffset display) buffer-boffset)) ;; Make sure there's room (when (index>= buffer-boffset limit) (setf (buffer-boffset display) buffer-boffset) (buffer-flush display) (set-buffer-offset (buffer-boffset display))) (int16-put 0 (pop arc)) (int16-put 2 (pop arc)) (card16-put 4 (pop arc)) (card16-put 6 (pop arc)) (angle-put 8 (pop arc)) (angle-put 10 (pop arc)) (set-buffer-offset (index+ buffer-boffset 12))))))) (defun draw-arcs-vector (drawable gcontext arcs &optional fill-p) (declare (type drawable drawable) (type gcontext gcontext) (type vector arcs) (type boolean fill-p)) (let* ((display (drawable-display drawable)) (limit (index- (buffer-size display) 12)) (length (length arcs)) (request (if fill-p *x-polyfillarc* *x-polyarc*))) (with-buffer-request ((drawable-display drawable) request :gc-force gcontext) (drawable drawable) (gcontext gcontext) (progn (card16-put 2 (index+ (index-ash length -1) 3)) ; Set request length (in words) (set-buffer-offset (index+ buffer-boffset 12)) ; Position to start of data (do ((n 0 (index+ n 6)) (length (length arcs))) ((index>= n length) (setf (buffer-boffset display) buffer-boffset)) ;; Make sure there's room (when (index>= buffer-boffset limit) (setf (buffer-boffset display) buffer-boffset) (buffer-flush display) (set-buffer-offset (buffer-boffset display))) (int16-put 0 (aref arcs (index+ n 0))) (int16-put 2 (aref arcs (index+ n 1))) (card16-put 4 (aref arcs (index+ n 2))) (card16-put 6 (aref arcs (index+ n 3))) (angle-put 8 (aref arcs (index+ n 4))) (angle-put 10 (aref arcs (index+ n 5))) (set-buffer-offset (index+ buffer-boffset 12))))))) (defun draw-arcs (drawable gcontext arcs &optional fill-p) (declare (type drawable drawable) (type gcontext gcontext) (type sequence arcs) (type boolean fill-p)) (etypecase arcs (list (draw-arcs-list drawable gcontext arcs fill-p)) (vector (draw-arcs-vector drawable gcontext arcs fill-p)))) ;; The following image routines are bare minimum. It may be useful to define ;; some form of "image" object to hide representation details and format ;; conversions. It also may be useful to provide stream-oriented interfaces ;; for reading and writing the data. (defun put-raw-image (drawable gcontext data &key (start 0) (depth (required-arg depth)) (x (required-arg x)) (y (required-arg y)) (width (required-arg width)) (height (required-arg height)) (left-pad 0) (format (required-arg format))) ;; Data must be a sequence of 8-bit quantities, already in the appropriate format ;; for transmission; the caller is responsible for all byte and bit swapping and ;; compaction. Start is the starting index in data; the end is computed from the ;; other arguments. (declare (type drawable drawable) (type gcontext gcontext) (type sequence data) ; Sequence of integers (type array-index start) (type card8 depth left-pad) ;; required (type int16 x y) ;; required (type card16 width height) ;; required (type (member :bitmap :xy-pixmap :z-pixmap) format)) (with-buffer-request ((drawable-display drawable) *x-putimage* :gc-force gcontext) ((data (member :bitmap :xy-pixmap :z-pixmap)) format) (drawable drawable) (gcontext gcontext) (card16 width height) (int16 x y) (card8 left-pad depth) (pad16 nil) ((sequence :format card8 :start start) data))) (defun get-raw-image (drawable &key data (start 0) (x (required-arg x)) (y (required-arg y)) (width (required-arg width)) (height (required-arg height)) (plane-mask #xffffffff) (format (required-arg format)) (result-type '(vector card8))) ;; If data is given, it is modified in place (and returned), otherwise a new sequence ;; is created and returned, with a size computed from the other arguments and the ;; returned depth. The sequence is filled with 8-bit quantities, in transmission ;; format; the caller is responsible for any byte and bit swapping and compaction ;; required for further local use. (declare (type drawable drawable) (type (or null sequence) data) ;; sequence of integers (type int16 x y) ;; required (type card16 width height) ;; required (type array-index start) (type pixel plane-mask) (type (member :xy-pixmap :z-pixmap) format)) (declare (values (sequence integer) depth visual-info)) (let ((display (drawable-display drawable))) (with-buffer-request-and-reply (display *x-getimage* nil :sizes (8 32)) (((data (member error :xy-pixmap :z-pixmap)) format) (drawable drawable) (int16 x y) (card16 width height) (card32 plane-mask)) (let ((depth (card8-get 1)) (length (* 4 (card32-get 4))) (visual (resource-id-get 8))) (values (sequence-get :result-type result-type :format card8 :length length :start start :data data :index *replysize*) depth (visual-info display visual))))))