Re: Getting a pointer to a cairo context?

Hazen Babcock <[email protected]> Tue, 8 Apr 2008 21:52:14 -0400
Newsgroups gmane.lisp.clg.devel
Message-ID <[email protected]>
On Apr 8, 2008, at 1:44 PM, Espen S Johnsen wrote:

> Hazen Babcock <[email protected]> writes:
>
>> It is possible to get a pointer to a cairo context? I thought that
>> perhaps (gffi::foreign-location cr) would do it, but passing this to
>> the code that expects a pointer to a cairo context seems to crash my
>> (SBCL) Lisp process.
>
>> I hoped that something like this might work:
>>
>> (gdk:with-cairo-context (cr (widget-window drawing-area))
>>      (multiple-value-bind (width height)
>>            (widget-get-size-allocation drawing-area)
>>          (cairo:scale cr width height))
>>      (draw-a-plot (gffi::foreign-location cr)))
>
> This should be correct as far as i can tell, but I couldn't figure out
> how to use cl-plplot with cairo so I wasn't able to do any testing. If
> you could provide some example code I could try to reproduce the  
> crash.

My sample program follows. I only added the necessary functionality  
for this to cl-plplot and to PLplot in the last few days so  
unfortunately you'd need both the latest cl-plplot from cvs and the  
latest PLplot from svn to test this. I tested the part PLplot of this  
with a simple C program (also follows) so I don't think that this is  
the problem. Maybe I'm not passing the pointer correctly in cl- 
plplot? The relevant CFFI code there is:

(DEFCFUN ("pl_cmd" C-PL-CMD) :VOID (OP PLINT) (PTR PLPOINTER))

PLPOINTER is of CFFI type :pointer.

thanks,
-Hazen


;;;
;;; Combining PLplot and GTK.
;;;

(defpackage :plplot-gtk
   (:use :common-lisp
         :cl-plplot-system
         :clg))

(in-package :plplot-gtk)

;; to use first do the following:
;
; 1. (require :gtk)
; 2. (require :cl-plplot)
; 3. (clg-init)
;

;; global variables

; windows
(defvar *main-window*)

;; functions

(defun draw-a-plot (cr)
   "Attempts to use PLplot to draw a plot in context cr."
   (plsdev "extcairo")
   (plinit)
   (pl-cmd 26 cr)
   (plcol0 1)
   (plwid 2)
   (plenv 0 2 0 2 0 0)
   (plcol0 2)
   (pllab "x" "y" "title")
   (plend))

(defun setup-drawing (drawing-area)
   "Creates the drawing function."
   (signal-connect drawing-area 'expose-event
                   #'(lambda (event)
                       (declare (ignore event))
                       (gdk:with-cairo-context (cr (widget-window  
drawing-area))
                         (multiple-value-bind (width height)
                             (widget-get-size-allocation drawing-area)
                           (cairo:scale cr width height))
                         (cairo:set-source-color cr 1.0 01.0 1.0)
                         (cairo:rectangle cr 0.0 0.0 1.0 1.0)
                         (cairo:fill cr)
                         (cairo:set-source-color cr 0.5 0.5 0.5)
                         (cairo:rectangle cr 0.1 0.1 0.8 0.8)
                         (cairo:fill cr)
                         (draw-a-plot (gffi::foreign-location cr))))))

;(cairo:xlib-surface-get-drawable
;(gdk:drawable-display

(defun create-main-window ()
   "Creates the main window."
   (let ((menu-bar)
         (graph-area)
         (main-window (make-instance 'window
                                     :title "Plplot-GTK" :name  
"main_window"
                                     :width-request 400 :height- 
request 300
                                     :visible t)))

     ; menu setup
     (let ((menu (make-instance 'menu-item :label "File"))
           (sub-menu (make-instance 'menu)))
       (setf menu-bar (make-instance 'menu-bar))
       (let ((item (make-instance 'menu-item :label "Quit")))
         (signal-connect item 'activate #'(lambda ()
                                            (widget-destroy *main- 
window*)))
         (menu-shell-append sub-menu item))
       (setf (menu-item-submenu menu) sub-menu)
       (menu-shell-append menu-bar menu))

     ; graphics setup
     (setf graph-area (make-instance 'drawing-area))
     (setup-drawing graph-area)

     ; window setup
     (make-instance 'v-box
                    :parent main-window
                    :child (list menu-bar :expand nil :fill nil)
                    :child graph-area)
     (signal-connect main-window 'destroy #'(lambda ()
                                              (setf *main-window* nil)))
     (setf *main-window* main-window)
     (widget-show-all main-window)))



PLplot C test program:

#include <stdio.h>

#include <cairo.h>
#include <cairo-ps.h>

#include <plplot.h>

int main(int argc, char *argv[])
{
   cairo_surface_t *cairoSurface;
   cairo_t *cairoContext;

   cairoSurface = cairo_ps_surface_create("test.ps", 720, 540);
   cairoContext = cairo_create(cairoSurface);

   plsdev("extcairo");
   plinit();
   pl_cmd(PLESC_DEVINIT, cairoContext);
   plenv(0.0, 1.0, 0.0, 1.0, 1, 0);
   pllab("x", "y", "title");
   plend();

   cairo_destroy(cairoContext);
   cairo_surface_destroy(cairoSurface);
}


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone