[comp.windows.x] using stipple/tile with CLX?

hall@polya.Stanford.EDU (Keith A. Hall) (08/30/89)

Does anyone have a short example program of stippling and/or tiling
using CLX?  My goal is to simulate grayscale on a monochrome server.
Thank you for any tips.

Keith Hall
hall@eclipse.stanford.edu

rao@PARC.xerox.com (Ramana Rao) (08/31/89)

Here's a short example of how you might simulate grayscale on a monochrome
server.  Of course, I yanked this code from a larger system that I'm working
on, so it may look odd, and of course, it could be better, but at least, ...

(in-package 'xlib)

(defun shade-test (&key (host-name "localhost"))
  (let* ((display   (open-display host-name))
	 (screen    (first (display-roots display)))
	 (root (screen-root screen))
	 (black  (screen-black-pixel screen))
	 (white  (screen-white-pixel screen))
	 (window (create-window :parent root
				:background white
				:x 10 :y 10 :width 300 :height 300))
	 (gc (create-gcontext :drawable window
			      :foreground black
			      :fill-style :solid)))

    (map-window window)
    (display-finish-output display)
    (sleep 1)
    (dolist (shade '(0 7.25 12.5 25 37.5 50 62.5 75 87.5 92.75 100))
      (setf-shade root gc 100 white black)
      (draw-rectangle window gc 10 10 280 280 t)
      (setf-shade root gc shade white black)
      (draw-rectangle window gc 20 20 260 260 t)
      (display-finish-output display)
      (sleep 1))
    (close-display display)))

(defun setf-shade (root gcontext shade white black)
  (case shade
    (0
     (setf (xlib:gcontext-fill-style gcontext) :solid
	   (xlib:gcontext-foreground gcontext) white))
    (100
     (setf (xlib:gcontext-fill-style gcontext) :solid
	   (xlib:gcontext-foreground gcontext) black))
    (otherwise
     (setf (xlib:gcontext-fill-style gcontext) :opaque-stippled  
	   (xlib:gcontext-foreground gcontext) black
	   (xlib:gcontext-background gcontext) white
	   (xlib:gcontext-stipple gcontext) 
	   (convert-shade root gcontext shade)))))

(defun convert-shade (root gc shade)
	;; Much of this code originally comes from Stan Lanning. 
  (multiple-value-bind (width height) (xlib:query-best-stipple 8 8 root)
    (let* ((width (cond ((< width 4) 4)
			((evenp width) width)
			(t (+ 1 width))))
	   (height (cond ((< height 4) 4)
			 ((evenp height) height)
			 (t (+ 1 height))))
	   (stipple (xlib:create-pixmap :width width :height height :depth 1
					:drawable root))
	   ;; To draw on the stipple, we get an "image" the size of the
	   ;; stipple, draw on it, and then paint that image back on the
	   ;; stipple. 
	   (image (xlib:get-image stipple :x 0 :y 0
				  :width width :height height))
	   (image-data (xlib::image-x-data image)))
      ;; The image-data is a vector that can be treated as a two-d array of
      ;; bytes, where each row of the pixmap is contained in a row of the array.
      ;; For whatever reasons, X might pad the rows with extra bytes, so the
      ;; number of columns that contain "real" data is likely smaller than the
      ;; number of columns in the array.  So... we make a two-d array displaced
      ;; to this image-data, and then treat it as if it contained just the
      ;; number of bytes that contain "real" info.
      (let ((nrows (xlib:image-height image))
	    (ncolumns (/ (xlib:image-width image) 8))
	    (array (make-array (list (/ (array-total-size image-data)
					(xlib::image-x-bytes-per-line image))
				     (xlib::image-x-bytes-per-line image))
			       :element-type (array-element-type image-data)
			       :displaced-to image-data)))
	;; Some special cases that we handle, to ensure a pleasing appearence.
	;; We only deal with shades <= 50%; darker shades are computed as the
	;; complement shade.
	(case (if (> shade 50)
		  (- 100 shade)
		  shade)
	  (50 (dotimes (row nrows)
		(let ((byte (ecase (rem row 2)
			      (0 #b10101010)
			      (1 #b01010101))))
		  (dotimes (column ncolumns)
		    (setf (aref array row column) byte)))))
	  (37.5 (dotimes (row nrows)
		  (let ((byte (ecase (rem row 8)
				(0 #b10101011)
				(1 #b01011101)
				(2 #b11101010)
				(3 #b01010111)
				(4 #b10111010)
				(5 #b11010101)
				(6 #b10101110)
				(7 #b01110101))))
		    (dotimes (column ncolumns)
		      (setf (aref array row column) byte)))))
	  (25 (dotimes (row nrows)
		(let ((byte (ecase (rem row 4)
			      (0 #b01000100)
			      (1 #b00100010)
			      (2 #b10001000)
			      (3 #b00010001))))
		  (dotimes (column ncolumns)
		    (setf (aref array row column) byte)))))
	  (12.5 (dotimes (row nrows)
		  (let ((byte (ecase (rem row 8)
				(0 #b00000001)
				(1 #b00001000)
				(2 #b01000000)
				(3 #b00000010)
				(4 #b00010000)
				(5 #b10000000)
				(6 #b00000100)
				(7 #b00100000))))
		    (dotimes (column ncolumns)
		      (setf (aref array row column) byte)))))
	  (7.25 (dotimes (row nrows)
		  (let ((byte (ecase (rem row 8)
				(0 #b00000001)
				(1 #b00000000)
				(2 #b00010000)
				(3 #b00000000)
				(4 #b01000000)
				(5 #b00000000)
				(6 #b00000100)
				(7 #b00000000))))
		    (dotimes (column ncolumns)
		      (setf (aref array row column) byte)))))
	  (0 (dotimes (row nrows)
	       (dotimes (column ncolumns)
		 (setf (aref array row column) #b00000000))))
	  (t (error "~%Can't yet handle arbitrary shades")))
	;; If the shade is > 50%, it is the inverse of the complement shade,
	;; so... 
	(when (> shade 50)
	  (dotimes (row nrows)
	    (dotimes (column ncolumns)
	      (setf (aref array row column)
		    (mask-field (byte 8 0)
				(lognot (aref array row column)))))))
	(xlib:put-image stipple gc image :x 0 :y 0)
	stipple))))



  










--
Ramana Rao (Internet: Rao@arisia.xerox.com)
Xerox Palo Alto Research Center (PARC)
3333 Coyote Hill Road; Palo Alto, CA, USA  94304
TEL: 415-494-4716; FAX: 415-494-4334