1 ;;; Copyright (c) 2007 Zachary Beane, All Rights Reserved
3 ;;; Redistribution and use in source and binary forms, with or without
4 ;;; modification, are permitted provided that the following conditions
7 ;;; * Redistributions of source code must retain the above copyright
8 ;;; notice, this list of conditions and the following disclaimer.
10 ;;; * Redistributions in binary form must reproduce the above
11 ;;; copyright notice, this list of conditions and the following
12 ;;; disclaimer in the documentation and/or other materials
13 ;;; provided with the distribution.
15 ;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
16 ;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 ;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 ;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 ;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 ;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 ;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 ;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 ;;; $Id: graphics-state.lisp,v 1.15 2007/10/01 02:24:44 xach Exp $
31 (defconstant +png-channels
+ 4)
32 (defconstant +png-color-type
+ :truecolor-alpha
)
33 (defvar *default-character-spacing
* 1.0d0
)
35 (defclass graphics-state
()
52 :initarg
:stroke-color
53 :accessor stroke-color
)
59 :accessor dash-vector
)
68 :accessor fill-source
)
77 :accessor blend-style
)
79 :initarg
:transform-matrix
80 :accessor transform-matrix
)
82 :initarg
:clipping-path
83 :accessor clipping-path
)
85 :initarg
:after-paint-fun
86 :accessor after-paint-fun
)
88 :initarg
:font-loaders
89 :accessor font-loaders
)
94 :initarg
:character-spacing
95 :accessor character-spacing
))
99 :stroke-color
(make-instance 'rgba-color
)
103 :fill-color
(make-instance 'rgba-color
)
108 :transform-matrix
(scaling-matrix 1.0 -
1.0)
109 :after-paint-fun
(constantly nil
)
110 :font-loaders
(make-hash-table :test
'equal
)
112 :character-spacing
*default-character-spacing
*))
114 (defgeneric image-data
(state)
116 (zpng:image-data
(image state
))))
118 (defgeneric transform-function
(state)
119 (:documentation
"Return a function that takes x, y coordinates
120 and returns them transformed by STATE's current transformation
121 matrix as multiple values.")
123 (make-transform-function (transform-matrix state
))))
126 (defgeneric call-after-painting
(state fun
)
128 "Call FUN after painting, and reset the post-painting fun to a no-op.")
130 (setf (after-paint-fun state
)
133 (setf (after-paint-fun state
) (constantly nil
))))))
135 (defgeneric after-painting
(state)
136 (:documentation
"Invoke the post-painting function.")
138 (funcall (after-paint-fun state
))))
141 (defgeneric apply-matrix
(state matrix
)
142 (:documentation
"Replace the current transform matrix of STATE
143 with the result of premultiplying it with MATRIX.")
144 (:method
(state matrix
)
145 (let ((old (transform-matrix state
)))
146 (setf (transform-matrix state
) (mult matrix old
)))))
148 (defgeneric clear-paths
(state)
149 (:documentation
"Clear out any paths in STATE.")
151 (setf (paths state
) nil
153 (after-paint-fun state
) (constantly nil
))))
155 (defmethod (setf paths
) :after
(new-value (state graphics-state
))
156 (setf (path state
) (first new-value
)))
158 (defun state-image (state width height
&optional image-data-allocator
)
159 "Set the backing image of the graphics state to an image of the
160 specified dimensions."
162 (if image-data-allocator
163 (make-instance 'zpng
:png
166 :color-type
+png-color-type
+
167 :image-data
(let ((samples (zpng:samples-per-pixel
169 (funcall image-data-allocator
170 (* width height samples
))))
171 (make-instance 'zpng
:png
174 :color-type
+png-color-type
+))
176 (height state
) height
177 (clipping-path state
) (make-clipping-path width height
))
178 (apply-matrix state
(translation-matrix 0 (- height
))))
180 (defun find-font-loader (state file
)
181 (let* ((cache (font-loaders state
))
182 (key (namestring (truename file
))))
183 (or (gethash key cache
)
184 (setf (gethash key cache
) (zpb-ttf:open-font-loader file
)))))
186 (defgeneric close-font-loaders
(state)
187 (:documentation
"Close any font loaders that were obtained with GET-FONT.")
189 (maphash (lambda (filename loader
)
190 (declare (ignore filename
))
191 (ignore-errors (zpb-ttf:close-font-loader loader
)))
192 (font-loaders state
))))
194 (defgeneric clear-state
(state)
195 (:documentation
"Clean up any state in STATE.")
196 (:method
((state graphics-state
))
197 (close-font-loaders state
)))
199 (defun clear-fill-source (state)
200 (setf (fill-source state
) nil
))
202 (defmethod copy ((state graphics-state
))
203 (make-instance 'graphics-state
206 :height
(height state
)
209 :stroke-color
(copy (stroke-color state
))
210 :line-width
(line-width state
)
211 :dash-vector
(copy-seq (dash-vector state
))
212 :dash-phase
(dash-phase state
)
213 :fill-color
(copy (fill-color state
))
214 :fill-source
(fill-source state
)
215 :join-style
(join-style state
)
216 :cap-style
(cap-style state
)
217 :transform-matrix
(copy-seq (transform-matrix state
))
218 :clipping-path
(copy (clipping-path state
))
219 :after-paint-fun
(after-paint-fun state
)
220 :font-loaders
(font-loaders state
)
222 :character-spacing
(character-spacing state
)))