chiark / gitweb /
Fix compilation for Gtk with the new, stricter inheritance
[clg] / gdk / pixbuf.lisp
index c622ccaceca3e04f21b5b43602e66165d6056b93..910e1cd99ccb0a480d37fad6d835347a3cbb23ef 100644 (file)
-;; Common Lisp bindings for GTK+ v2.0
-;; Copyright (C) 2004 Espen S. Johnsen <espen@users.sf.net>
+;; Common Lisp bindings for GTK+ v2.x
+;; Copyright 2004-2005 Espen S. Johnsen <espen@users.sf.net>
 ;;
-;; This library is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU Lesser General Public
-;; License as published by the Free Software Foundation; either
-;; version 2 of the License, or (at your option) any later version.
+;; 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:
 ;;
-;; This library is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;; Lesser General Public License for more details.
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
 ;;
-;; You should have received a copy of the GNU Lesser General Public
-;; License along with this library; if not, write to the Free Software
-;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+;; 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.
 
-;; $Id: pixbuf.lisp,v 1.2 2005-02-14 00:46:31 espen Exp $
+;; $Id: pixbuf.lisp,v 1.9 2008-12-10 03:01:34 espen Exp $
 
 
 (in-package "GDK")
 
-(defbinding pixbuf-get-option () (copy-of string)
-  (pixbuf pixbuf)
-  (key string))
+(defbinding %pixbuf-new () pointer
+  colorspace 
+  (has-alpha boolean)
+  (bits-per-sample int)
+  (width int)
+  (height int))
+
+(defbinding %pixbuf-new-from-data () pointer
+  (data pointer)
+  colorspace       
+  (has-alpha boolean)
+  (bits-per-sample int)
+  (width int)
+  (height int)
+  (rowstride int)
+  (nil null)
+  (nil null))
 
-(defbinding %pixbuf-new-from-file () (referenced pixbuf)
+(defbinding %pixbuf-new-from-xpm-data () pointer
+  (data (vector string)))
+
+(defbinding %pixbuf-new-from-file () pointer
   (filename pathname)
-  (nil gerror :out))
+  (nil (or null gerror) :out))
 
-(defbinding %pixbuf-new-from-file-at-size () (referenced pixbuf)
+(defbinding %pixbuf-new-from-file-at-size () pointer
   (filename pathname)
   (width int)
   (height int)
-  (nil gerror :out))
+  (nil (or null gerror) :out))
 
-#+gtk2.6
-(defbinding %pixbuf-new-from-file-at-scale () (referenced pixbuf)
+#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0")
+(defbinding %pixbuf-new-from-file-at-scale () pointer
   (filename pathname)
   (width int)
   (height int)
   (preserve-aspect-ratio boolean)
-  (nil gerror :out))
-
-(defun pixbuf-load (filename &key width height size (preserve-aspect-ratio t))
-  #-gtk2.6
-  (unless preserve-aspect-ratio 
-    (warn ":preserve-aspect-ratio not supported with this version of Gtk"))
+  (nil (or null gerror) :out))
 
-  (multiple-value-bind (pixbuf gerror)
+(defun %pixbuf-load (filename width height preserve-aspect-p)
+  (multiple-value-bind (location gerror)
       (cond
-       (size 
-       #-gtk2.6(%pixbuf-new-from-file-at-size filename size size)
-       #+gtk2.6(%pixbuf-new-from-file-at-scale filename size size preserve-aspect-ratio))
-       ((and width height)
-       #-gtk2.6(%pixbuf-new-from-file-at-size filename width height)
-       #+gtk2.6(%pixbuf-new-from-file-at-scale filename width height preserve-aspect-ratio))
-       ((or width height)
-       (error "Both :width and :height must be specified"))
-       (t (%pixbuf-new-from-file filename)))
+       ((and width height)
+        (%pixbuf-new-from-file-at-size filename width height))
+       ((or width height)
+        #?-(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0")
+        (error "Both :width and :height must be specified")
+        #?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0")
+        (%pixbuf-new-from-file-at-scale filename 
+         (or width -1) (or height -1) preserve-aspect-p))
+       (t (%pixbuf-new-from-file filename)))
     (if gerror
        (signal-gerror gerror)
-      pixbuf)))
+      location)))
+
+#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.14.0")
+(progn
+  (defbinding %pixbuf-new-from-stream () pointer
+    gio:input-stream-designator
+    (nil (or null gio:cancellable))
+    (nil (or null gerror) :out))
+
+  (defbinding %pixbuf-new-from-stream-at-scale () pointer
+    gio:input-stream-designator
+    (width int)
+    (height int)
+    (preserve-aspect-ratio boolean)
+    (nil (or null gio:cancellable))
+    (nil (or null gerror) :out))
+
+  (defun %load-from-stream (stream width height preserve-aspect-p)
+    (multiple-value-bind (location gerror)
+       (cond
+         ((or width height)
+          (%pixbuf-new-from-stream-at-scale stream
+           (or width -1) (or height -1) preserve-aspect-p))
+         (t (%pixbuf-new-from-stream stream)))
+      (if gerror
+         (signal-gerror gerror)
+       location))))
+
+(defmethod allocate-foreign ((pixbuf pixbuf) &key source (bits-per-sample 8)
+                            (colorspace :rgb) (has-alpha t) width height 
+                            (preserve-aspect-ratio t) destroy stride)
+  (cond
+   ((not source) 
+    (%pixbuf-new colorspace has-alpha bits-per-sample width height))
+   ((typep source 'pointer)
+    ;; TODO: destory
+    (%pixbuf-new-from-data source colorspace has-alpha bits-per-sample width height (or stride (* width (if has-alpha 4 3)))))
+   ((and (vectorp source) (stringp (aref source 0)))
+    (%pixbuf-new-from-xpm-data source))
+   ((typep source 'vector)
+
+    )
+   ((or (pathnamep source) (stringp source))
+    #?-(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0")
+    (unless preserve-aspect-ratio 
+      (warn ":preserve-aspect-ratio not supported with this version of Gtk"))
+    (%pixbuf-load source width height preserve-aspect-ratio))
+   #?(pkg-exists-p "gtk+-2.0" :atleast-version "2.14.0")
+   ((typep source 'gio:input-stream-designator)
+    (%load-from-stream source width height preserve-aspect-ratio))
+   ((call-next-method))))
+
+
+(defbinding (pixbuf-subpixbuf "gdk_pixbuf_new_subpixbuf") () 
+    (or null (referenced pixbuf))
+  pixbuf (src-x int) (src-y int) (width int) (height int))
+
+(defbinding pixbuf-copy () (or null (referenced pixbuf))
+  pixbuf)
+
+
+(defbinding pixbuf-get-option () (copy-of string)
+  (pixbuf pixbuf)
+  (key string))
+
+(defun pixbuf-load (filename &key width height size (preserve-aspect-ratio t))
+  (make-instance 'pixbuf :source filename 
+   :width (or size width) :height (or size height)
+   :preserve-aspect-ratio preserve-aspect-ratio))
 
 
 ;; (defbinding pixbuf-get-file-info () (copy-of pixbuf-format)
@@ -73,14 +159,14 @@ (defbinding %pixbuf-savev () boolean
   (filename pathname)
   (type string)
   (keys strings)
-  (values string)
-  (nil gerror :out))
+  (values strings)
+  (nil (or null gerror) :out))
 
-(defun pixbuf-save (pixbuf filename type &rest options)
+(defun %pixbuf-save-options (options)
   (let ((keys (make-array 0 :adjustable t :fill-pointer t))
        (values (make-array 0 :adjustable t :fill-pointer t)))
     (loop 
-     as (key value . rest) = options then rest
+     for (key value) on options by #'cddr
      do (vector-push-extend (string-downcase key) keys)
         (vector-push-extend 
         (etypecase value 
@@ -88,13 +174,59 @@ (defun pixbuf-save (pixbuf filename type &rest options)
           (symbol (string-downcase value))
           (number (format nil "~A" value)))
         values))
-    (multiple-value-bind (ok-p gerror)
-       (%pixbuf-savev pixbuf filename type keys values)
-      (unless ok-p
-       (signal-gerror gerror)))))
+    (values keys values)))
 
-(defbinding pixbuf-new-from-xpm-data () (referenced pixbuf)
-  (data (vector string)))
+(defgeneric pixbuf-save (pixbuf dest type &rest options))
+
+(defmethod pixbuf-save (pixbuf (filename string) type &rest options)
+  (multiple-value-bind (ok-p gerror)
+      (multiple-value-call #'%pixbuf-savev 
+       pixbuf filename (string-downcase type) 
+       (%pixbuf-save-options options))
+    (unless ok-p
+      (signal-gerror gerror))))
+
+(defmethod pixbuf-save (pixbuf (pathname pathname) type &rest options)
+  (apply #'pixbuf-save pixbuf (namestring (translate-logical-pathname pathname))
+   type options))
+
+(define-callback stream-write-func boolean 
+    ((data pointer) (length gsize) (gerror pointer) (stream-id pointer-data))
+  (block stream-write
+    (handler-case
+       (let ((stream (find-user-data stream-id)))
+         (write-sequence
+          (map-c-vector 'vector 'identity data '(unsigned-byte 8) length)
+          stream))
+      (serious-condition (condition)
+       (gerror-set-in-callback gerror (file-error-domain) 
+        (enum-int :failed 'file-error-enum) (princ-to-string condition))
+       (return-from stream-write nil)))
+    t))
+
+(defbinding %pixbuf-save-to-callbackv (pixbuf stream type keys values) boolean
+  (pixbuf pixbuf)
+  (stream-write-func callback)
+  (stream pointer-data)
+  (type string)
+  (keys strings)
+  (values strings)
+  (nil (or null gerror) :out))
+
+(defmethod pixbuf-save (pixbuf (stream stream) type &rest options)
+  (let ((stream-id (register-user-data stream)))
+    (unwind-protect
+        (multiple-value-bind (ok-p gerror)
+            (multiple-value-call #'%pixbuf-save-to-callbackv
+              pixbuf stream-id (string-downcase type) 
+              (%pixbuf-save-options options))
+          (unless ok-p
+            (signal-gerror gerror)))
+      (destroy-user-data stream-id))))
+
+
+;; (defbinding pixbuf-new-from-xpm-data () (referenced pixbuf)
+;;   (data (vector string)))
 
 (defbinding %pixbuf-new-subpixbuf () pixbuf ;; or (referenced pixbuf)?
   (pixbuf pixbuf)
@@ -108,6 +240,69 @@ (defun copy-pixbuf (pixbuf &optional x y width height)
       (%pixbuf-copy pixbuf)
     (%pixbuf-new-subpixbuf pixbuf x y width height)))
 
+(defbinding %pixbuf-get-from-drawable () (or null (referenced pixbuf))
+  (dest (or null pixbuf))
+  (drawable drawable)
+  (colormap (or null colormap))
+  (src-x int)
+  (src-y int)
+  (dest-x int)
+  (dest-y int)
+  (width int)
+  (height int))
+
+(defun pixbuf-get-from-drawable (drawable &key (src-x 0) (src-y 0) (dest-x 0) (dest-y 0) width height colormap dest)
+  (unless (or (and width height) (not (typep drawable 'window)))
+    (error "Width and height must be specified for windows"))
+  (or
+   (%pixbuf-get-from-drawable dest drawable
+    (cond
+     (colormap)
+     ((slot-boundp drawable 'colormap) nil)
+     ((colormap-get-system)))
+    src-x src-y dest-x dest-y (or width -1) (or height -1))
+   (error "Couldn't get pixbuf from drawable")))
+
+
+;;; Pixbuf Loader
+
+(defbinding %pixbuf-loader-new-with-type () pointer
+  (type string)
+  (nil gerror-signal :out))
+
+(defbinding %pixbuf-loader-new-with-mime-type () pointer
+  (mime-type string)
+  (nil gerror-signal :out))
+
+(defmethod allocate-foreign ((loader pixbuf-loader) &key type mime-type)
+  (cond
+   ((and type mime-type) 
+    (error "Only one of the keyword arguments :TYPE and :MIME-TYPE can be specified"))
+   (type (%pixbuf-loader-new-with-type type))
+   (mime-type (%pixbuf-loader-new-with-mime-type mime-type))
+   ((call-next-method))))
+
+(defbinding pixbuf-loader-write (loader buffer &optional (length (length buffer))) boolean
+  (loader pixbuf-loader)
+  (buffer (unboxed-vector (unsigned-byte 8)))
+  (length integer)  
+  (nil gerror-signal :out))
+
+(defbinding pixbuf-loader-close () boolean
+  (loader pixbuf-loader)
+  (nil gerror-signal :out))
+
+(defbinding pixbuf-loader-get-pixbuf () (or null pixbuf)
+  (loader pixbuf-loader))
+
+(defbinding pixbuf-loader-get-animation () (or null pixbuf-animation)
+  (loader pixbuf-loader))
+
+(defbinding pixbuf-loader-set-size () nil
+  (loader pixbuf-loader)
+  (width integer)
+  (height integer))
+
 
 ;;; Utilities
 
@@ -119,3 +314,25 @@ (defbinding pixbuf-add-alpha
   (red (unsigned 8))
   (green (unsigned 8))
   (blue (unsigned 8)))
+
+;; The purpose of this function is to be able to share pixel data
+;; between GdkPixbufs and Cairo image surfaces.
+#+nil
+(defun pixbuf-swap-rgb (pixbuf)
+  (assert (= (pixbuf-bits-per-sample pixbuf) 8))
+  (assert (= (pixbuf-n-channels pixbuf) 4))
+  (assert (pixbuf-has-alpha-p pixbuf))
+  (let ((pixels (pixbuf-pixels pixbuf))
+       (stride (pixbuf-rowstride pixbuf))
+       (n-channels (pixbuf-n-channels pixbuf)))
+    (loop for y from 0 below (pixbuf-height pixbuf) do
+     (let ((row-offset (* y stride)))
+       (loop for x from 0 below (pixbuf-width pixbuf) do
+        (let* ((offset (+ row-offset (* n-channels x)))
+              (p0 (ref-uint-8 pixels offset))
+              (p2 (ref-uint-8 pixels (+ offset 2))))
+         (setf (ref-uint-8 pixels offset) p2)
+         (setf (ref-uint-8 pixels (+ offset 2)) p0)))))))
+
+(defbinding (pixbuf-swap-rgb "clg_gdk_pixbuf_swap_rgb") () nil
+  pixbuf)