1 ;;; xlib-xpm.el --- XPM library for Xlib.
3 ;; Copyright (C) 2003-2005 by XWEM Org.
5 ;; Author: Zajcev Evgeny <zevlg@yandex.ru>
6 ;; Created: Fri Nov 28 01:28:18 MSK 2003
7 ;; Keywords: xlib, xwem
8 ;; X-CVS: $Id: xlib-xpm.el,v 1.7 2005-04-04 19:55:30 lg Exp $
10 ;; This file is part of XWEM.
12 ;; XWEM is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; XWEM is distributed in the hope that it will be useful, but WITHOUT
18 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 ;; License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 ;;; Synched up with: Not in FSF
31 ;; Almost everything is hack here.
41 (defvar X:xpm-color-symbols nil
42 "Same as `xpm-color-symbols', but for xlib.")
45 (defun X:xpm-num-colors ()
46 "Return number of colors in xpm."
48 (goto-char (point-min))
49 (if (re-search-forward
50 "\"\\s-*\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-*"
52 (string-to-int (match-string 3))
53 (error "Unable to parse xpm information"))))
55 (defun X:xpm-goto-color-def (def)
56 "Move to color DEF in the xpm header."
57 (goto-char (point-min))
58 (re-search-forward "[ \t]*\"")
60 (re-search-forward "[ \t]*\"")
63 (defun X:xpm-goto-body-line (line &optional num-colors)
64 "Move to LINE lines down from the start of the body of an xpm."
65 (X:xpm-goto-color-def (or num-colors (X:xpm-num-colors)))
68 (defun X:xpm-chars-per-pixel ()
69 "Return number of chars per pixel."
71 (goto-char (point-min))
72 (if (re-search-forward
73 "\"\\s-*\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-*"
75 (string-to-int (match-string 4))
76 (error "Unable to parse xpm."))))
78 (defun X:xpm-get-symcolor (symc-name &optional tag-set)
79 "Get SYMC-NAME color from `X:xpm-color-symbols' list.
80 TAGS-SET is a list of tags, directly passed to `specifier-spec-list'."
81 (let ((xcs X:xpm-color-symbols))
82 (while (and xcs (not (string= (caar xcs) symc-name)))
86 (cond ((stringp xcs) xcs)
88 (let ((sspec (specifier-spec-list xcs nil tag-set t)))
89 (cdr (car (cdr (car sspec))))))
90 (t (error "Invalid element in `X:xpm-color-symbols'"))))))
92 (defun X:xpm-parse-color (chars-per-pixel &optional tag-set)
93 "Parse xpm color string from current line and set the color.
94 CHARS-PER-PIXEL specifies color depth.
95 TAG-SET specifies tag-set to use in order to resolve symbolic color name."
98 (if (re-search-forward
99 ;; Generate a regexp on the fly
100 (concat "\"\\(" (make-string chars-per-pixel ?.) "\\)" ; chars
101 "\\(\\s-+[sm]\\s-+\\(\\S-*\\)\\)*" ; s and m classes
102 "\\s-+\\([c]\\)" ; c class
103 "\\s-+\\([^ \t\"]+\\)")
105 (list (match-string 1)
106 (or (and (match-string 3) (X:xpm-get-symcolor (match-string 3) tag-set))
108 (error "Unable to parse color"))))
111 (defun X:xpm-extract-shape-colors (xdpy &optional tag-set)
112 "Extract colors which marked as None."
113 (let ((xpm-chars-per-pixel (X:xpm-chars-per-pixel))
114 (xpm-num-colors (X:xpm-num-colors))
118 ;; extract colors which need to mask
119 (X:xpm-goto-color-def 0)
120 (while (< co xpm-num-colors)
121 (setq pco (X:xpm-parse-color xpm-chars-per-pixel tag-set))
122 (when (string= "none" (downcase (cadr pco)))
123 (setq nonecols (cons (car pco) nonecols)))
129 (defun X:xpm-bit-vector-to-string (bitv)
130 "Convert bit-vector BITV to string."
134 (str (make-string (+ (/ (length bitv) 8)
135 (if (not (zerop (% (length bitv) 8))) 1 0)) 0)))
138 (while (< idx (length bitv))
142 (logior (aref str off) (lsh (* (aref bitv idx) #x80) (- coff))))
147 (defun X:xpm-parse-shape-body-line (nonec width left-pad xpad)
148 "Parse current line to extract bits using None colors list NONEC."
149 (let ((bitv (make-vector (+ width (- xpad (% width xpad))) 0))
155 (flet ((xpm-calc-off (idx) ; XXX offset in BITV calculator
156 (1- (if (< idx (- 8 left-pad))
157 (- (- 8 left-pad) idx)
159 (setq idx (+ idx left-pad))
160 (+ (* 8 (/ idx 8)) (- 8 (% idx 8)))))))
162 (while (< bidx width)
163 (setq pix (buffer-substring (point) (+ (point) 1))
164 col (member pix nonec))
165 (aset bitv (xpm-calc-off bidx) (if col 0 1))
167 (setq bidx (1+ bidx))))
169 (X:xpm-bit-vector-to-string bitv)))
171 (defun X:xpm-make-shape (xdpy &optional tag-set)
173 Return data for `X-XYPixmap' format."
175 ximg shape shape-index nonec height width
177 (goto-char (point-min))
179 (when (re-search-forward "\"\\s-*\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-*"
181 (setq width (string-to-int (match-string 1)))
182 (setq height (string-to-int (match-string 2)))))
184 (setq left-pad (% width 8))
187 (setq nonec (X:xpm-extract-shape-colors xdpy)))
189 (X:xpm-goto-body-line 0)
190 ;; XXX Check for addition comment line
191 (when (looking-at "^/\\*")
194 (setq shape (make-vector height nil))
197 (while (< shape-index height)
198 (X:xpm-goto-body-line (+ shape-index togo))
199 (aset shape shape-index
200 (X:xpm-parse-shape-body-line nonec width left-pad (X-Dpy-bitmap-scanline-pad xdpy)))
202 (setq shape-index (1+ shape-index)))
205 (setq ximg (XCreateImage xdpy nil 1 X-XYBitmap left-pad shape
206 width height (X-Dpy-bitmap-scanline-pad xdpy) 1))
211 (defun X:xpm-extract-colors (xdpy &optional tag-set)
213 (let ((cmap (XDefaultColormap xdpy))
214 (xpm-num-colors (X:xpm-num-colors))
215 (xpm-chars-per-pixel (X:xpm-chars-per-pixel))
220 (X:xpm-goto-color-def 0)
221 (while (< co xpm-num-colors)
222 (setq pco (X:xpm-parse-color xpm-chars-per-pixel tag-set))
223 (setq prgb (color-instance-rgb-components
224 (make-color-instance (if (string= "none" (downcase (cadr pco)))
229 (XAllocColor xdpy cmap
230 (make-X-Color :dpy xdpy :id (X-Dpy-get-id xdpy)
233 :blue (nth 2 prgb))))
239 (defun X:xpm-parse-body-line (cols)
242 (setq pix (buffer-substring (point) (+ (point) 1))
243 col (assoc pix cols))
244 (when (X-Color-p (cdr col))
245 (setq rlst (cons (X-Color-id (cdr col)) rlst)))
247 (vconcat (nreverse rlst))))
249 (defun X:xpm-make-img (xdpy &optional tag-set)
250 "Create X-Image using current buffer."
251 (let ((depth (XDefaultDepth xdpy))
252 (xpm-num-colors (X:xpm-num-colors))
254 xpm xpm-index height width cols
256 (goto-char (point-min))
258 (when (re-search-forward "\"\\s-*\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-*"
260 (setq width (string-to-int (match-string 1)))
261 (setq height (string-to-int (match-string 2)))))
264 (setq cols (X:xpm-extract-colors xdpy tag-set)))
266 (X:xpm-goto-body-line 0 xpm-num-colors)
267 ;; Check for additional comment
268 (when (looking-at "^/\\*")
271 (setq xpm (make-vector height nil))
274 (while (< xpm-index height)
275 (X:xpm-goto-body-line (+ xpm-index togo) xpm-num-colors)
277 (X:xpm-parse-body-line cols))
279 (setq xpm-index (1+ xpm-index)))
281 (setq data (mapvector #'(lambda (row)
282 (X-formatpad xdpy depth
284 (mapcar #'(lambda (col)
285 (X-formatint xdpy depth col))
289 (setq ximg (XCreateImage xdpy nil depth X-ZPixmap 0 data
290 width height (X-Dpy-bitmap-scanline-pad xdpy) 1))
293 (defun X:xpm-img-from-data (xdpy data &optional shape tag-set)
297 (X:xpm-make-shape xdpy tag-set)
298 (X:xpm-make-img xdpy tag-set))))
300 (defun X:xpm-img-from-file (xdpy file &optional shape tag-set)
302 (insert-file-contents-literally file)
304 (X:xpm-make-shape xdpy tag-set)
305 (X:xpm-make-img xdpy tag-set))))
307 ;; Pixmap manipulations
308 (defun X:xpm-make-pixmap-from-ximg (xdpy d ximg)
309 "On display XDPY and drawable D, create X-Pixmap using X-Image XIMG."
311 (setq pixmap (XCreatePixmap xdpy (make-X-Pixmap :dpy xdpy :id (X-Dpy-get-id xdpy))
312 d (X-Image-depth ximg) (X-Image-width ximg) (X-Image-height ximg)))
314 (setq gc (XCreateGC xdpy pixmap
315 (make-X-Gc :dpy xdpy :id (X-Dpy-get-id xdpy)
319 (XImagePut xdpy gc pixmap 0 0 ximg)
322 ;; Store initial X-Image XIMG in pixmap's properties list
323 (X-Pixmap-put-prop pixmap 'ximg ximg)
326 (defun X:xpm-pixmap-from-data (xdpy d data &optional shape tag-set)
327 "On display XDPY and drawable D create X-Pixmap from DATA."
328 (X:xpm-make-pixmap-from-ximg xdpy d (X:xpm-img-from-data xdpy data shape tag-set)))
330 (defun X:xpm-pixmap-from-file (xdpy d file &optional shape tag-set)
331 "On display XDPY and drawable D create X-Pixmap from FILE."
332 (X:xpm-make-pixmap-from-ximg xdpy d (X:xpm-img-from-file xdpy file shape tag-set)))
337 ;; * bicubic interpolation
338 (defsubst X:xpm-func-P (x)
339 (if (> x 0) (float x) 0.0))
341 (defsubst X:xpm-func-R (x)
342 (/ (+ (X:xpm-func-P (expt (+ x 2) 3)) (- (* 4 (X:xpm-func-P (expt (+ x 1) 3))))
343 (* 6.0 (X:xpm-func-P (expt x 3))) (- (* 4 (X:xpm-func-P (expt (- x 1) 3)))))
346 (defun X:xpm-get-color-component-at (xdpy img x y component)
351 (when (>= y (length img))
352 (setq y (1- (length img))))
353 (when (>= x (length (nth 0 img)))
354 (setq x (1- (length (nth 0 img)))))
356 (let ((col (aref (nth y img) x)))
357 (nth (cond ((eq component 'red) 0)
358 ((eq component 'green) 1)
359 ((eq component 'blue) 2)
361 (caar (last (XQueryColors xdpy (XDefaultColormap xdpy) (list col)))))))
363 (defun X:xpm-func-F (xdpy img factors i j)
364 ;; TODO: calculate dx, dy
365 (let* ((x (* i (car factors)))
366 (y (* j (cdr factors)))
370 (vconcat (mapcar (lambda (comp)
375 (* (X:xpm-get-color-component-at xdpy img (+ i m) (+ j n) comp)
376 (X:xpm-func-R (- dx m))
377 (X:xpm-func-R (- dy n))))
386 ;;; xlib-xpm.el ends here