Update of /project/mcclim/cvsroot/mcclim/Backends/gtkairo
In directory clnet:/tmp/cvs-serv28245/Backends/gtkairo
Modified Files:
gtk-ffi.lisp medium.lisp pango.lisp
Added Files:
cairo.lisp
Log Message:
Split up gtkairo/medium.lisp, moving the cairo medium into its own file.
--- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/gtk-ffi.lisp 2006/12/25 19:55:11 1.24
+++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/gtk-ffi.lisp 2006/12/26 12:11:04 1.25
@@ -118,6 +118,9 @@
(defmacro with-cairo-floats ((&optional) &body body)
`(progn ,@body))
+(defmacro slot (o c s)
+ `(cffi:foreign-slot-value ,o ,c ,s))
+
;; Note: There's no need for locking in single threaded mode for most
;; functions, except that the main loop functions try to release the
;; lock temporarily, so those need to be called with locking. Let's do
--- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/medium.lisp 2006/12/25 19:55:11 1.15
+++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/medium.lisp 2006/12/26 12:11:04 1.16
@@ -32,21 +32,16 @@
(defclass gtkairo-medium (climi::basic-medium clim:medium)
((port :initarg :port :accessor port)))
-(defclass cairo-medium (gtkairo-medium)
- ((cr :initform nil :initarg :cr :accessor cr)
- (flipping-original-cr :initform nil :accessor flipping-original-cr)
- (flipping-pixmap :initform nil :accessor flipping-pixmap)
- (flipping-region :accessor flipping-region)
- (surface :initarg :surface :accessor surface)
- (last-seen-sheet :accessor last-seen-sheet)
- (last-seen-region :accessor last-seen-region)))
-
-(defmethod initialize-instance :after
- ((instance cairo-medium) &key cr)
- (unless cr
- (setf (last-seen-sheet instance) nil)))
+(defclass metrik-medium-mixin () ())
+(defclass cairo-metrik-medium (metrik-medium-mixin cairo-medium) ())
+(defclass gdk-metrik-medium (metrik-medium-mixin gdk-medium) ())
-(defparameter *antialiasingp* t)
+(defgeneric invoke-with-medium (fn medium))
+
+(defmacro with-medium ((medium) &body body)
+ `(invoke-with-medium (lambda () ,@body) ,medium))
+
+(defgeneric metrik-medium-for (medium))
(defun gtkwidget-gdkwindow (widget)
(cffi:foreign-slot-value widget 'gtkwidget 'gdkwindow))
@@ -55,55 +50,6 @@
(or (climi::port-lookup-mirror (port medium) (medium-sheet medium))
(error "oops, drawing operation on unmirrored sheet ~A" medium)))
-(defmethod invoke-with-medium (fn (medium cairo-medium))
- (when (or (cr medium)
- (climi::port-lookup-mirror (port medium) (medium-sheet medium)))
- (with-gtk ()
- (multiple-value-prog1
- (funcall fn)
- (when (flipping-original-cr medium)
- (apply-flipping-ink medium))))))
-
-(defun sheet-changed-behind-our-back-p (medium)
- (and (slot-boundp medium 'last-seen-sheet)
- (or (not (eq (last-seen-sheet medium) (medium-sheet medium)))
- (not (region-equal (last-seen-region medium)
- (sheet-region (medium-sheet medium)))))))
-
-(defmethod metrik-medium-for ((medium cairo-medium))
- (cairo-metrik-medium (port medium)))
-
-(defun set-antialias (cr)
- (cairo_set_antialias cr
- (if *antialiasingp*
- :CAIRO_ANTIALIAS_DEFAULT
- :CAIRO_ANTIALIAS_NONE)))
-
-(defun sync-sheet (medium)
- (when (medium-sheet medium) ;ignore the metrik-medium
- (setf (gethash medium (dirty-mediums (port medium))) t))
- (when (or (null (cr medium))
- (sheet-changed-behind-our-back-p medium))
- (with-medium (medium)
- (let* ((mirror (medium-mirror medium))
- (drawable (mirror-drawable mirror)))
- (setf (cr medium) (gdk_cairo_create drawable))
- (dispose-flipping-pixmap medium)
- (pushnew medium (mirror-mediums mirror))
- (set-antialias (cr medium)))
- (setf (last-seen-sheet medium) (medium-sheet medium))
- (setf (last-seen-region medium) (sheet-region (medium-sheet medium))))))
-
-(defun dispose-flipping-pixmap (medium)
- (when (flipping-pixmap medium)
- (gdk_drawable_unref (flipping-pixmap medium))
- (setf (flipping-pixmap medium) nil)))
-
-
-;;;; ------------------------------------------------------------------------
-;;;; 8.3 Output Protocol
-;;;;
-
(defmethod engraft-medium :after ((medium gtkairo-medium) port sheet)
)
@@ -125,169 +71,6 @@
:port port
:sheet sheet))
-;;;; ------------------------------------------------------------------------
-;;;; Drawing Options
-;;;;
-
-(defun sync-transformation (medium &optional extra-transformation)
- (with-slots (cr) medium
- (cffi:with-foreign-object (matrix 'cairo_matrix_t)
- (let ((tr
- (if (medium-sheet medium)
- (sheet-native-transformation (medium-sheet medium))
- clim:+identity-transformation+)))
- (when extra-transformation
- (setf tr (compose-transformations extra-transformation tr)))
- (multiple-value-bind (mxx mxy myx myy tx ty)
- (climi::get-transformation tr)
- ;; Make sure not to hand transformations to cairo that it won't
- ;; like, since debugging gets ugly once a cairo context goes
- ;; into an error state:
- (invert-transformation tr)
- (cairo_matrix_init matrix
- (df mxx) (df mxy) (df myx) (df myy)
- (df tx) (df ty))
- (cairo_set_matrix cr matrix))))))
-
-(defmacro with-cairo-matrix ((matrix transformation) &body body)
- `(cffi:with-foreign-object (,matrix 'cairo_matrix_t)
- (multiple-value-bind (mxx mxy myx myy tx ty)
- (climi::get-transformation ,transformation)
- (cairo_matrix_init ,matrix
- (df mxx) (df mxy) (df myx) (df myy)
- (df tx) (df ty))
- (locally ,@body))))
-
-;;; ink
-
-(defmethod sync-ink :before (medium new-value)
- (with-slots (cr) medium
- (cairo_set_operator cr :over)))
-
-(defmethod sync-ink (medium (new-value (eql clim:+foreground-ink+)))
- (sync-ink medium (clim:medium-foreground medium))) ;### circles?
-
-(defmethod sync-ink (medium (new-value (eql clim:+background-ink+)))
- (sync-ink medium (clim:medium-background medium))) ;### circles?
-
-(defmethod sync-ink (medium (new-value clim:opacity))
- (with-slots (cr) medium
- (cond ((= 0 (opacity-value new-value))
- (cairo_set_source_rgba cr 0d0 0d0 0d0 0d0))
- ((= 1 (opacity-value new-value))
- (sync-ink medium (clim:medium-foreground medium)))
- (t
- (sync-ink medium (clim:compose-in (clim:medium-foreground medium)
- new-value))))))
-
-(defmethod sync-ink (medium (new-value climi::uniform-compositum))
- (with-slots (cr) medium
- (with-slots ((ink climi::ink) (mask climi::mask)) new-value
- (multiple-value-bind (red green blue) (clim:color-rgb ink)
- (cairo_set_source_rgba cr
- (df red)
- (df green)
- (df blue)
- (df (clim:opacity-value mask)))))))
-
-(defmethod sync-ink (medium (new-value clim:color))
- (with-slots (cr) medium
- (multiple-value-bind (red green blue) (clim:color-rgb new-value)
- (cairo_set_source_rgba cr (df red) (df green) (df blue) (df 1.0d0)))))
-
-(defvar *pattern-hash*
- (make-hash-table))
-
-(defun pattern-cairo-pattern (medium pattern)
- (or (gethash pattern *pattern-hash*)
- (setf (gethash pattern *pattern-hash*)
- (let ((s (make-cairo-surface medium
- (pattern-width pattern)
- (pattern-height pattern))))
- (draw-design s pattern)
- (cairo_pattern_create_for_surface (slot-value s 'surface))))))
-
-(defmethod sync-ink (medium (pattern climi::indexed-pattern))
- (with-slots (cr) medium
- (let ((s (make-cairo-surface medium
- (pattern-width pattern)
- (pattern-height pattern))))
- (draw-design s pattern)
- (let ((p (cairo_pattern_create_for_surface (slot-value s 'surface))))
- (cairo_set_source cr p)
- p))))
-
-(defmethod sync-ink (medium (pattern climi::indexed-pattern))
- (with-slots (cr) medium
- (let ((p (pattern-cairo-pattern medium pattern)))
- (cairo_set_source cr p)
- p)))
-
-(defmethod sync-ink (medium (design clim-internals::transformed-design))
- (with-slots ((design climi::design) (transformation climi::transformation))
- design
- ;; ### hmm
- (let ((p (sync-ink medium design)))
- (with-cairo-matrix (matrix (invert-transformation transformation))
- (cairo_pattern_set_matrix p matrix))
- p)))
-
-(defun apply-flipping-ink (medium)
- (let ((from-surface (cairo_get_target (cr medium)))
- (from-drawable (flipping-pixmap medium))
- (to-surface (cairo_get_target (flipping-original-cr medium)))
- (to-drawable (medium-gdkdrawable medium)))
- (cairo_surface_flush from-surface)
- (cairo_surface_flush to-surface)
- (let ((gc (gdk_gc_new to-drawable))
- (region (flipping-region medium)))
- (gdk_gc_set_function gc :GDK_XOR)
- (gdk_draw_drawable to-drawable gc from-drawable
- (floor (bounding-rectangle-min-x region))
- (floor (bounding-rectangle-min-y region))
- (floor (bounding-rectangle-min-x region))
- (floor (bounding-rectangle-min-y region))
- (ceiling (bounding-rectangle-max-x region))
- (ceiling (bounding-rectangle-max-y region)))
- (gdk_gc_unref gc))
- (cairo_surface_mark_dirty to-surface))
- (cairo_destroy (cr medium))
- (setf (cr medium) (flipping-original-cr medium))
- (setf (flipping-original-cr medium) nil))
-
-(defmethod sync-ink (medium (design climi::standard-flipping-ink))
- (setf (flipping-original-cr medium) (cr medium))
- (let* ((mirror (medium-mirror medium))
- (drawable (mirror-drawable mirror)))
- (let* ((region (climi::sheet-mirror-region (medium-sheet medium)))
- (width (floor (bounding-rectangle-max-x region)))
- (height (floor (bounding-rectangle-max-y region)))
- (pixmap
- (or (flipping-pixmap medium)
- (setf (flipping-pixmap medium)
- (gdk_pixmap_new drawable width height -1)))))
- (setf (cr medium) (gdk_cairo_create pixmap))
- (set-antialias (cr medium))
- (setf (flipping-region medium) region)
- (cairo_paint (cr medium))
- (sync-transformation medium)
- (sync-ink medium +white+))))
-
-(defmethod sync-ink (medium new-value)
- (warn "SYNC-INK lost ~S." new-value))
-
-;;; clipping region
-
-(defun sync-clipping-region (medium region)
- (with-slots (cr) medium
- (cairo_reset_clip cr)
- (unless (eq region +everywhere+)
- (unless (eq region +nowhere+)
- (loop for (x y w h) in (clipping-region->rect-seq region) do
- (cairo_rectangle cr (df x) (df y) (df w) (df h))))
- (cairo_clip cr))
- (cairo_new_path cr)))
-
;; copy&paste from medium.lisp|CLX:
;; this seems to work, but find out why all of these +nowhere+s are coming from
;; and kill them at the source...
@@ -305,67 +88,6 @@
(- (round-coordinate (rectangle-max-x rectangle)) clip-x)
(- (round-coordinate (rectangle-max-y rectangle)) clip-y))))
-;;; line-style
-
-(defun sync-line-style (medium line-style)
- (with-slots (cr) medium
- (cairo_set_line_cap cr
- (case (line-style-cap-shape line-style)
- (:butt :butt)
- (:square :square)
- (:round :round)
- (:no-end-point :round))) ;###
- (cond ((null (line-style-dashes line-style))
- (cairo_set_dash cr (cffi:null-pointer) 0 0d0)) ;hmm
- ((eq t (line-style-dashes line-style))
- (let ((d 10))
- (cairo-set-dash* cr
- (case (line-style-unit line-style)
- ((:point :normal)
- (map 'vector (lambda (x)
- (untransform-size
- (medium-transformation
- medium) x))
- (list d)))
- (:coordinate
- (list d))))))
- (t
- ;; line-style-unit!
- (cairo-set-dash* cr
- (case (line-style-unit line-style)
- ((:point :normal)
- (map 'vector (lambda (x)
- (untransform-size
- (medium-transformation medium)
- x))
- (line-style-dashes line-style)))
- (:coordinate
- (line-style-dashes line-style))))))
- (cairo_set_line_join cr
- (case (line-style-joint-shape line-style)
- (:miter :miter)
- (:bevel :bevel)
- (:round :round)
- (:none :round))) ;###
- (cairo_set_line_width cr
- (max 1.0d0
- (df
- (case (line-style-unit line-style)
- ((:point :normal)
- (untransform-size
- (medium-transformation medium)
- (line-style-thickness line-style)))
- (:coordinate
- (line-style-thickness line-style)))))) ))
-
-(defun cairo-set-dash* (cr dashes)
- (let ((ndash (length dashes)))
- (cffi:with-foreign-object (adashes :double ndash)
- (loop
- for i below ndash do
- (setf (cffi:mem-aref adashes :double i) (df (elt dashes i))))
- (cairo_set_dash cr adashes ndash 0d0))))
-
(defun untransform-size (transformation size)
(multiple-value-bind (dx dy) (untransform-distance transformation size 0)
(sqrt (+ (expt dx 2) (expt dy 2)))))
@@ -374,242 +96,6 @@
(multiple-value-bind (dx dy) (transform-distance transformation size 0)
(sqrt (+ (expt dx 2) (expt dy 2)))))
-(defun sync-drawing-options (medium)
- (sync-transformation medium)
- (sync-ink medium (medium-ink medium))
- (sync-clipping-region medium (medium-clipping-region medium))
- (sync-line-style medium (medium-line-style medium)))
-
-;;;; ------------------------------------------------------------------------
-;;;; Drawing Operations
-;;;;
-
-(defmethod medium-draw-point* ((medium cairo-medium) x y)
- (with-medium (medium)
- (sync-sheet medium)
- (sync-transformation medium)
- (sync-ink medium (medium-ink medium))
- (sync-clipping-region medium (medium-clipping-region medium))
- (sync-line-style medium (medium-line-style medium))
- (with-slots (cr) medium
- (cairo_set_line_cap cr :round)
- (setf x (df x))
- (setf y (df y))
- (cairo_move_to cr x y)
- (cairo_line_to cr (+ x 0.5) (+ y 0.5))
- (cairo_stroke cr))))
-
-(defmethod medium-draw-points* ((medium cairo-medium) coord-seq)
- (with-medium (medium)
- (sync-sheet medium)
- (sync-transformation medium)
- (sync-ink medium (medium-ink medium))
- (sync-clipping-region medium (medium-clipping-region medium))
- (sync-line-style medium (medium-line-style medium))
- (with-slots (cr) medium
- (cairo_set_line_cap cr :round)
- (loop for i below (length coord-seq) by 2 do
- (let ((x (df (elt coord-seq (+ i 0))))
- (y (df (elt coord-seq (+ i 1)))))
- (cairo_move_to cr x y)
- (cairo_line_to cr (+ x 0.5) (+ y 0.5))
- (cairo_stroke cr))))))
-
-(defmethod medium-draw-line* ((medium cairo-medium) x1 y1 x2 y2)
- (with-medium (medium)
- (sync-sheet medium)
- (sync-transformation medium)
- (sync-ink medium (medium-ink medium))
- (sync-clipping-region medium (medium-clipping-region medium))
- (sync-line-style medium (medium-line-style medium))
- (with-slots (cr) medium
- (cairo_move_to cr (df x1) (df y1))
- (cairo_line_to cr (df x2) (df y2))
- (cairo_stroke cr))))
-
-(defmethod medium-draw-lines* ((medium cairo-medium) position-seq)
- (with-medium (medium)
- (sync-sheet medium)
- (sync-transformation medium)
- (sync-ink medium (medium-ink medium))
- (sync-clipping-region medium (medium-clipping-region medium))
- (sync-line-style medium (medium-line-style medium))
- (with-slots (cr) medium
- (loop for i below (length position-seq) by 4 do
- (cairo_move_to cr
- (df (elt position-seq (+ i 0)))
- (df (elt position-seq (+ i 1))))
- (cairo_line_to cr
- (df (elt position-seq (+ i 2)))
- (df (elt position-seq (+ i 3)))))
- (cairo_stroke cr))))
[353 lines skipped]
--- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/pango.lisp 2006/12/25 19:55:11 1.4
+++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/pango.lisp 2006/12/26 12:11:04 1.5
@@ -24,20 +24,6 @@
(in-package :clim-gtkairo)
-;;; these shouldn't be here:
-
-(defclass metrik-medium-mixin () ())
-(defclass cairo-metrik-medium (metrik-medium-mixin cairo-medium) ())
-(defclass gdk-metrik-medium (metrik-medium-mixin gdk-medium) ())
-
-(defgeneric invoke-with-medium (fn medium))
-
-(defmacro with-medium ((medium) &body body)
- `(invoke-with-medium (lambda () ,@body) ,medium))
-
-(defgeneric metrik-medium-for (medium))
-
-
;;;; Helper macros.
(defmacro with-pango-layout
--- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/cairo.lisp 2006/12/26 12:11:04 NONE
+++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/cairo.lisp 2006/12/26 12:11:04 1.1
;;; -*- Mode: Lisp; -*-
;;; (c) copyright 2005 by Gilbert Baumann <gilbert(a)base-engineering.com>
;;; (c) copyright 2006 David Lichteblau (david(a)lichteblau.com)
;;; Permission is hereby granted, free of charge, to any person obtaining
;;; a copy of this software and associated documentation files (the
;;; "Software"), to deal in the Software without restriction, including
;;; without limitation the rights to use, copy, modify, merge, publish,
;;; distribute, sublicense, and/or sell copies of the Software, and to
;;; permit persons to whom the Software is furnished to do so, subject to
;;; the following conditions:
;;;
;;; The above copyright notice and this permission notice shall be
;;; included in all copies or substantial portions of the Software.
;;;
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
;;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
;;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
;;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(in-package :clim-gtkairo)
;;; Locking rule for this file: Dokumented entry points in the CLIM
;;; package use WITH-GTK, internal functions can rely on that.
(defclass cairo-medium (gtkairo-medium)
((cr :initform nil :initarg :cr :accessor cr)
(flipping-original-cr :initform nil :accessor flipping-original-cr)
(flipping-pixmap :initform nil :accessor flipping-pixmap)
(flipping-region :accessor flipping-region)
(surface :initarg :surface :accessor surface)
(last-seen-sheet :accessor last-seen-sheet)
(last-seen-region :accessor last-seen-region)))
(defmethod initialize-instance :after
((instance cairo-medium) &key cr)
(unless cr
(setf (last-seen-sheet instance) nil)))
(defparameter *antialiasingp* t)
(defmethod invoke-with-medium (fn (medium cairo-medium))
(when (or (cr medium)
(climi::port-lookup-mirror (port medium) (medium-sheet medium)))
(with-gtk ()
(multiple-value-prog1
(funcall fn)
(when (flipping-original-cr medium)
(apply-flipping-ink medium))))))
(defun sheet-changed-behind-our-back-p (medium)
(and (slot-boundp medium 'last-seen-sheet)
(or (not (eq (last-seen-sheet medium) (medium-sheet medium)))
(not (region-equal (last-seen-region medium)
(sheet-region (medium-sheet medium)))))))
(defmethod metrik-medium-for ((medium cairo-medium))
(cairo-metrik-medium (port medium)))
(defun set-antialias (cr)
(cairo_set_antialias cr
(if *antialiasingp*
:CAIRO_ANTIALIAS_DEFAULT
:CAIRO_ANTIALIAS_NONE)))
(defun sync-sheet (medium)
(when (medium-sheet medium) ;ignore the metrik-medium
(setf (gethash medium (dirty-mediums (port medium))) t))
(when (or (null (cr medium))
(sheet-changed-behind-our-back-p medium))
(with-medium (medium)
(let* ((mirror (medium-mirror medium))
(drawable (mirror-drawable mirror)))
(setf (cr medium) (gdk_cairo_create drawable))
(dispose-flipping-pixmap medium)
(pushnew medium (mirror-mediums mirror))
(set-antialias (cr medium)))
(setf (last-seen-sheet medium) (medium-sheet medium))
(setf (last-seen-region medium) (sheet-region (medium-sheet medium))))))
(defun dispose-flipping-pixmap (medium)
(when (flipping-pixmap medium)
(gdk_drawable_unref (flipping-pixmap medium))
(setf (flipping-pixmap medium) nil)))
;;;; ------------------------------------------------------------------------
;;;; Drawing Options
;;;;
(defun sync-transformation (medium &optional extra-transformation)
(with-slots (cr) medium
(cffi:with-foreign-object (matrix 'cairo_matrix_t)
(let ((tr
(if (medium-sheet medium)
(sheet-native-transformation (medium-sheet medium))
clim:+identity-transformation+)))
(when extra-transformation
(setf tr (compose-transformations extra-transformation tr)))
(multiple-value-bind (mxx mxy myx myy tx ty)
(climi::get-transformation tr)
;; Make sure not to hand transformations to cairo that it won't
;; like, since debugging gets ugly once a cairo context goes
;; into an error state:
(invert-transformation tr)
(cairo_matrix_init matrix
(df mxx) (df mxy) (df myx) (df myy)
(df tx) (df ty))
(cairo_set_matrix cr matrix))))))
(defmacro with-cairo-matrix ((matrix transformation) &body body)
`(cffi:with-foreign-object (,matrix 'cairo_matrix_t)
(multiple-value-bind (mxx mxy myx myy tx ty)
(climi::get-transformation ,transformation)
(cairo_matrix_init ,matrix
(df mxx) (df mxy) (df myx) (df myy)
(df tx) (df ty))
(locally ,@body))))
;;; ink
(defmethod sync-ink :before (medium new-value)
(with-slots (cr) medium
(cairo_set_operator cr :over)))
(defmethod sync-ink (medium (new-value (eql clim:+foreground-ink+)))
(sync-ink medium (clim:medium-foreground medium))) ;### circles?
(defmethod sync-ink (medium (new-value (eql clim:+background-ink+)))
(sync-ink medium (clim:medium-background medium))) ;### circles?
(defmethod sync-ink (medium (new-value clim:opacity))
(with-slots (cr) medium
(cond ((= 0 (opacity-value new-value))
(cairo_set_source_rgba cr 0d0 0d0 0d0 0d0))
((= 1 (opacity-value new-value))
(sync-ink medium (clim:medium-foreground medium)))
(t
(sync-ink medium (clim:compose-in (clim:medium-foreground medium)
new-value))))))
(defmethod sync-ink (medium (new-value climi::uniform-compositum))
(with-slots (cr) medium
(with-slots ((ink climi::ink) (mask climi::mask)) new-value
(multiple-value-bind (red green blue) (clim:color-rgb ink)
(cairo_set_source_rgba cr
(df red)
(df green)
(df blue)
(df (clim:opacity-value mask)))))))
(defmethod sync-ink (medium (new-value clim:color))
(with-slots (cr) medium
(multiple-value-bind (red green blue) (clim:color-rgb new-value)
(cairo_set_source_rgba cr (df red) (df green) (df blue) (df 1.0d0)))))
(defvar *pattern-hash*
(make-hash-table))
(defun pattern-cairo-pattern (medium pattern)
(or (gethash pattern *pattern-hash*)
(setf (gethash pattern *pattern-hash*)
(let ((s (make-cairo-surface medium
(pattern-width pattern)
(pattern-height pattern))))
(draw-design s pattern)
(cairo_pattern_create_for_surface (slot-value s 'surface))))))
(defmethod sync-ink (medium (pattern climi::indexed-pattern))
(with-slots (cr) medium
(let ((s (make-cairo-surface medium
(pattern-width pattern)
(pattern-height pattern))))
(draw-design s pattern)
(let ((p (cairo_pattern_create_for_surface (slot-value s 'surface))))
(cairo_set_source cr p)
p))))
(defmethod sync-ink (medium (pattern climi::indexed-pattern))
(with-slots (cr) medium
(let ((p (pattern-cairo-pattern medium pattern)))
(cairo_set_source cr p)
p)))
(defmethod sync-ink (medium (design clim-internals::transformed-design))
(with-slots ((design climi::design) (transformation climi::transformation))
design
;; ### hmm
(let ((p (sync-ink medium design)))
(with-cairo-matrix (matrix (invert-transformation transformation))
(cairo_pattern_set_matrix p matrix))
p)))
(defun apply-flipping-ink (medium)
(let ((from-surface (cairo_get_target (cr medium)))
(from-drawable (flipping-pixmap medium))
(to-surface (cairo_get_target (flipping-original-cr medium)))
(to-drawable (medium-gdkdrawable medium)))
(cairo_surface_flush from-surface)
(cairo_surface_flush to-surface)
(let ((gc (gdk_gc_new to-drawable))
(region (flipping-region medium)))
(gdk_gc_set_function gc :GDK_XOR)
(gdk_draw_drawable to-drawable gc from-drawable
(floor (bounding-rectangle-min-x region))
(floor (bounding-rectangle-min-y region))
(floor (bounding-rectangle-min-x region))
(floor (bounding-rectangle-min-y region))
(ceiling (bounding-rectangle-max-x region))
(ceiling (bounding-rectangle-max-y region)))
(gdk_gc_unref gc))
(cairo_surface_mark_dirty to-surface))
(cairo_destroy (cr medium))
(setf (cr medium) (flipping-original-cr medium))
(setf (flipping-original-cr medium) nil))
(defmethod sync-ink (medium (design climi::standard-flipping-ink))
(setf (flipping-original-cr medium) (cr medium))
(let* ((mirror (medium-mirror medium))
(drawable (mirror-drawable mirror)))
(let* ((region (climi::sheet-mirror-region (medium-sheet medium)))
(width (floor (bounding-rectangle-max-x region)))
(height (floor (bounding-rectangle-max-y region)))
(pixmap
(or (flipping-pixmap medium)
(setf (flipping-pixmap medium)
(gdk_pixmap_new drawable width height -1)))))
(setf (cr medium) (gdk_cairo_create pixmap))
(set-antialias (cr medium))
(setf (flipping-region medium) region)
(cairo_paint (cr medium))
(sync-transformation medium)
(sync-ink medium +white+))))
(defmethod sync-ink (medium new-value)
(warn "SYNC-INK lost ~S." new-value))
;;; clipping region
(defun sync-clipping-region (medium region)
(with-slots (cr) medium
(cairo_reset_clip cr)
(unless (eq region +everywhere+)
(unless (eq region +nowhere+)
(loop for (x y w h) in (clipping-region->rect-seq region) do
(cairo_rectangle cr (df x) (df y) (df w) (df h))))
(cairo_clip cr))
(cairo_new_path cr)))
;;; line-style
(defun sync-line-style (medium line-style)
(with-slots (cr) medium
(cairo_set_line_cap cr
(case (line-style-cap-shape line-style)
(:butt :butt)
(:square :square)
(:round :round)
(:no-end-point :round))) ;###
(cond ((null (line-style-dashes line-style))
(cairo_set_dash cr (cffi:null-pointer) 0 0d0)) ;hmm
((eq t (line-style-dashes line-style))
(let ((d 10))
(cairo-set-dash* cr
(case (line-style-unit line-style)
((:point :normal)
(map 'vector (lambda (x)
(untransform-size
(medium-transformation
medium) x))
(list d)))
(:coordinate
(list d))))))
(t
;; line-style-unit!
(cairo-set-dash* cr
(case (line-style-unit line-style)
((:point :normal)
(map 'vector (lambda (x)
(untransform-size
(medium-transformation medium)
x))
(line-style-dashes line-style)))
(:coordinate
(line-style-dashes line-style))))))
(cairo_set_line_join cr
(case (line-style-joint-shape line-style)
(:miter :miter)
(:bevel :bevel)
(:round :round)
(:none :round))) ;###
(cairo_set_line_width cr
(max 1.0d0
(df
(case (line-style-unit line-style)
((:point :normal)
(untransform-size
(medium-transformation medium)
(line-style-thickness line-style)))
(:coordinate
(line-style-thickness line-style)))))) ))
(defun cairo-set-dash* (cr dashes)
(let ((ndash (length dashes)))
(cffi:with-foreign-object (adashes :double ndash)
(loop
for i below ndash do
(setf (cffi:mem-aref adashes :double i) (df (elt dashes i))))
(cairo_set_dash cr adashes ndash 0d0))))
(defun sync-drawing-options (medium)
(sync-transformation medium)
(sync-ink medium (medium-ink medium))
(sync-clipping-region medium (medium-clipping-region medium))
(sync-line-style medium (medium-line-style medium)))
;;;; ------------------------------------------------------------------------
;;;; Drawing Operations
;;;;
(defmethod medium-draw-point* ((medium cairo-medium) x y)
(with-medium (medium)
(sync-sheet medium)
(sync-transformation medium)
(sync-ink medium (medium-ink medium))
(sync-clipping-region medium (medium-clipping-region medium))
(sync-line-style medium (medium-line-style medium))
(with-slots (cr) medium
(cairo_set_line_cap cr :round)
(setf x (df x))
(setf y (df y))
(cairo_move_to cr x y)
(cairo_line_to cr (+ x 0.5) (+ y 0.5))
(cairo_stroke cr))))
(defmethod medium-draw-points* ((medium cairo-medium) coord-seq)
(with-medium (medium)
(sync-sheet medium)
(sync-transformation medium)
(sync-ink medium (medium-ink medium))
(sync-clipping-region medium (medium-clipping-region medium))
(sync-line-style medium (medium-line-style medium))
(with-slots (cr) medium
(cairo_set_line_cap cr :round)
(loop for i below (length coord-seq) by 2 do
(let ((x (df (elt coord-seq (+ i 0))))
(y (df (elt coord-seq (+ i 1)))))
(cairo_move_to cr x y)
(cairo_line_to cr (+ x 0.5) (+ y 0.5))
(cairo_stroke cr))))))
(defmethod medium-draw-line* ((medium cairo-medium) x1 y1 x2 y2)
(with-medium (medium)
(sync-sheet medium)
(sync-transformation medium)
(sync-ink medium (medium-ink medium))
(sync-clipping-region medium (medium-clipping-region medium))
(sync-line-style medium (medium-line-style medium))
(with-slots (cr) medium
(cairo_move_to cr (df x1) (df y1))
(cairo_line_to cr (df x2) (df y2))
(cairo_stroke cr))))
(defmethod medium-draw-lines* ((medium cairo-medium) position-seq)
(with-medium (medium)
(sync-sheet medium)
(sync-transformation medium)
(sync-ink medium (medium-ink medium))
(sync-clipping-region medium (medium-clipping-region medium))
(sync-line-style medium (medium-line-style medium))
(with-slots (cr) medium
(loop for i below (length position-seq) by 4 do
(cairo_move_to cr
(df (elt position-seq (+ i 0)))
[328 lines skipped]