From: Jonathan W. <jw...@ph...> - 2008-03-05 02:36:17
|
Hi I am working on an application which requires plots to be displayed within the context of the program's windows. In practice this means that I needed plplot to have the ability to plot to a supplied X Drawable rather than to an X window which plplot creates and manages itself. The attached patch is a first pass at implementing this idea within the xcairo driver (against plplot 5.8.0). I have tested this in the context of a gtk application using both a Window and a Pixmap as the destination drawable and it seems to work fine. In order for this to work the application must have a way to pass both an open Display as well as the Drawable itself to plplot. To achieve this I implemented a PLESC_DEVINIT function for the xcairo device which expects a pointer to the new PLXcairoDrawableInfo structure. The idea is that the parent application populates this structure with the required information before calling PLESC_DEVINIT. Note that for the purposes of this patch PLXcairoDrawableInfo is defined in cairo.c to keep it self-contained, but plplot.h would be its ultimate resting place. I toyed with the idea of having the display/drawable passed in with device options before plinit() but using PLESC_DEVINIT seems like a neater solution to me. Instead I use a single integer option to set xcairo into xdrawable mode. When running in this so-called xdrawable mode plplot makes no attempt at maintaining the plot in terms of handling expose events and the like. My reasoning here is that since the drawable was created by the application the application has a much better change of efficiently handling expose events. Comments and feedback are welcome. For what it's worth I think that this feature would make a worthwhile addition to plplot. In a way it is similar in functionality to plplotcanvas but unlike plplotcanvas the xdrawable solution does not drag in a large number of extraneous dependencies (gnome-print for example). Since almost every application framework/toolkit can provide X drawables it makes plplot accessable to almost every developer regardless of their preferred GUI framework. As a final comment, the following code snippet illustrates how I connect a gtk drawing area (or gdk pixmap) to plplot: struct { Display *display; Drawable drawable; } xinfo; plsdev("xcairo"); plsetopt("drvopt", "external_drawable"); plinit(); xinfo.display = GDK_WINDOW_XDISPLAY( [a GtkDrawingArea widget] ); xinfo.drawable = GDK_WINDOW_XID( [a GtkDrawingArea widget] ); pl_cmd(PLESC_DEVINIT, &xinfo); [ do plotting ] plend(); To use a GdkPixmap, the xinfo initialisation lines simply become xinfo.display = GDK_PIXMAP_XDISPLAY( [a GdkPixmap] ); xinfo.drawable = GDK_PIXMAP_XID( [a GdkPixmap] ); In due course the xinfo structure will be of type PLXcairoDrawableInfo. Regards jonathan --- drivers/cairo.c-orig 2007-11-19 06:34:11.000000000 +1030 +++ drivers/cairo.c 2008-03-05 13:04:15.000000000 +1030 @@ -73,10 +73,12 @@ static int text_clipping; static int text_anti_aliasing; static int graphics_anti_aliasing; +static int external_drawable; static DrvOpt cairo_options[] = {{"text_clipping", DRV_INT, &text_clipping, "Use text clipping (text_clipping=0|1)"}, {"text_anti_aliasing", DRV_INT, &text_anti_aliasing, "Set desired text anti-aliasing (text_anti_aliasing=0|1|2|3). The numbers are in the same order as the cairo_antialias_t enumeration documented at http://cairographics.org/manual/cairo-cairo-t.html#cairo-antialias-t)"}, {"graphics_anti_aliasing", DRV_INT, &graphics_anti_aliasing, "Set desired graphics anti-aliasing (graphics_anti_aliasing=0|1|2|3). The numbers are in the same order as the cairo_antialias_t enumeration documented at http://cairographics.org/manual/cairo-cairo-t.html#cairo-antialias-t"}, + {"external_drawable", DRV_INT, &external_drawable, "Plot to external X drawable"}, {NULL, DRV_INT, NULL, NULL}}; typedef struct { @@ -89,6 +91,7 @@ short exit_event_loop; Display *XDisplay; Window XWindow; + unsigned int xdrawable_mode; #endif #if defined(PLD_memcairo) unsigned char *memory; @@ -116,6 +119,14 @@ #endif ; +/* Structure for passing external drawables to xcairo devices via + * the PLESC_DEVINIT escape function. + */ +typedef struct { + Display *display; + Drawable drawable; +} PLXcairoDrawableInfo; + //--------------------------------------------------------------------- // Font style and weight lookup tables (copied // from the psttf driver). @@ -206,6 +217,12 @@ aStream = (PLCairo *)pls->dev; + /* Some Cairo devices support delayed device setup (eg: xcairo with + * external drawable). + */ + if (aStream->cairoSurface == NULL) + return; + // Fill in the window with the background color. cairo_rectangle(aStream->cairoContext, 0.0, 0.0, pls->xlength, pls->ylength); cairo_set_source_rgb(aStream->cairoContext, @@ -661,6 +678,10 @@ // Allocate a cairo stream structure aStream = malloc(sizeof(PLCairo)); + aStream->XDisplay = NULL; + aStream->XWindow = -1; + aStream->cairoSurface = NULL; + aStream->cairoContext = NULL; // Set text clipping off as this makes the driver pretty slow aStream->text_clipping = 0; @@ -794,6 +815,38 @@ } //--------------------------------------------------------------------- +// xcairo_init_cairo() +// +// Configures Cairo to use whichever X Drawable is set up in the given +// stream. This is called by plD_init_xcairo() in the event we are +// drawing into a plplot-managed window, and plD_esc_xcairo() if +// we are using an external X Drawable. +// +// A return value of 0 indicates success. Currently this function only +// returns 0. +//---------------------------------------------------------------------- + +static signed int xcairo_init_cairo(PLStream *pls) +{ + PLCairo *aStream; + Visual *defaultVisual; + + aStream = (PLCairo *)pls->dev; + + // Create an cairo surface & context that are associated with the X window. + defaultVisual = DefaultVisual(aStream->XDisplay, 0); + aStream->cairoSurface = cairo_xlib_surface_create(aStream->XDisplay, aStream->XWindow, defaultVisual, pls->xlength, pls->ylength); + aStream->cairoContext = cairo_create(aStream->cairoSurface); + + // Invert the surface so that the graphs are drawn right side up. + rotate_cairo_surface(pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength); + + // Set graphics aliasing + cairo_set_antialias(aStream->cairoContext, aStream->graphics_anti_aliasing); + + return 0; +} +//--------------------------------------------------------------------- // plD_init_xcairo() // // Initialize Cairo X Windows device. @@ -802,47 +855,44 @@ void plD_init_xcairo(PLStream *pls) { char plotTitle[40]; - Visual *defaultVisual; XGCValues values; PLCairo *aStream; - // Setup the PLStream and the font lookup table + // Setup the PLStream and the font lookup table. aStream = stream_and_font_setup(pls, 1); - // X Windows setup - aStream->XDisplay = NULL; - aStream->XDisplay = XOpenDisplay(NULL); - if(aStream->XDisplay == NULL){ - printf("Failed to open X Windows display\n"); - // some sort of error here - } - XScreen = DefaultScreen(aStream->XDisplay); - rootWindow = RootWindow(aStream->XDisplay, XScreen); - aStream->exit_event_loop = 0; + // Save the pointer to the structure in the PLplot stream + pls->dev = aStream; - // Initialize plot title - sprintf(plotTitle, "PLplot"); - - // Create a X Window. - aStream->XWindow = XCreateSimpleWindow(aStream->XDisplay, rootWindow, 0, 0, pls->xlength, pls->ylength, - 1, BlackPixel(aStream->XDisplay, XScreen), BlackPixel(aStream->XDisplay, XScreen)); - XStoreName(aStream->XDisplay, aStream->XWindow, plotTitle); - XSelectInput(aStream->XDisplay, aStream->XWindow, NoEventMask); - XMapWindow(aStream->XDisplay, aStream->XWindow); + // Create a X Window if required. + if (external_drawable != 0) { + aStream->xdrawable_mode = 1; + } else { + // Initialize plot title + sprintf(plotTitle, "PLplot"); - // Create an cairo surface & context that are associated with the X window. - defaultVisual = DefaultVisual(aStream->XDisplay, 0); - aStream->cairoSurface = cairo_xlib_surface_create(aStream->XDisplay, aStream->XWindow, defaultVisual, pls->xlength, pls->ylength); - aStream->cairoContext = cairo_create(aStream->cairoSurface); + // X Windows setup + aStream->XDisplay = NULL; + aStream->XDisplay = XOpenDisplay(NULL); + if(aStream->XDisplay == NULL){ + printf("Failed to open X Windows display\n"); + // some sort of error here + } + XScreen = DefaultScreen(aStream->XDisplay); + rootWindow = RootWindow(aStream->XDisplay, XScreen); - // Save the pointer to the structure in the PLplot stream - pls->dev = aStream; + aStream->XWindow = XCreateSimpleWindow(aStream->XDisplay, rootWindow, 0, 0, pls->xlength, pls->ylength, + 1, BlackPixel(aStream->XDisplay, XScreen), BlackPixel(aStream->XDisplay, XScreen)); + XStoreName(aStream->XDisplay, aStream->XWindow, plotTitle); + XSelectInput(aStream->XDisplay, aStream->XWindow, NoEventMask); + XMapWindow(aStream->XDisplay, aStream->XWindow); + aStream->xdrawable_mode = 0; - // Invert the surface so that the graphs are drawn right side up. - rotate_cairo_surface(pls, 1.0, 0.0, 0.0, -1.0, 0.0, pls->ylength); + xcairo_init_cairo(pls); + } + + aStream->exit_event_loop = 0; - // Set graphics aliasing - cairo_set_antialias(aStream->cairoContext, aStream->graphics_anti_aliasing); } //--------------------------------------------------------------------- @@ -863,6 +913,9 @@ aStream = (PLCairo *)pls->dev; + if (aStream->xdrawable_mode) + return; + XFlush(aStream->XDisplay); // Loop, handling selected events, till the user elects to close the plot. @@ -906,8 +959,12 @@ plD_tidy_cairo(pls); + if (aStream->xdrawable_mode) + return; + // Close the window and the display. XFlush(aStream->XDisplay); + XDestroyWindow(aStream->XDisplay, aStream->XWindow); XCloseDisplay(aStream->XDisplay); @@ -941,6 +998,38 @@ XFlush(aStream->XDisplay); xcairo_get_cursor(pls, (PLGraphicsIn*)ptr); break; + case PLESC_DEVINIT: { // Set external drawable + Window rootwin; + PLXcairoDrawableInfo *xinfo = (PLXcairoDrawableInfo *)ptr; + signed int x, y; + unsigned int w, h, b, d; + if (xinfo == NULL) { + printf("xcairo: PLESC_DEVINIT ignored, no drawable info provided\n"); + return; + } + if (aStream->xdrawable_mode == 0) { + printf("xcairo: PLESC_DEVINIT called with drawable but stream not in xdrawable mode\n"); + return; + } + aStream->XDisplay = xinfo->display; + aStream->XWindow = xinfo->drawable; + + /* Ensure plplot knows the real dimensions of the drawable */ + XGetGeometry(aStream->XDisplay, aStream->XWindow, &rootwin, + &x, &y, &w, &h, &b, &d); + pls->xlength = w; + pls->ylength = h; + plP_setphy((PLINT) 0, (PLINT) pls->xlength / DOWNSCALE, (PLINT) 0, + (PLINT) pls->ylength / DOWNSCALE); + + /* Associate cairo with the supplied drawable */ + xcairo_init_cairo(pls); + + /* Recalculate dimensions and the like now that the drawable is known */ + plbop(); + + break; + } } } |
From: Hazen B. <hba...@ma...> - 2008-03-05 04:10:48
|
On Mar 4, 2008, at 9:36 PM, Jonathan Woithe wrote: > Hi > > I am working on an application which requires plots to be displayed > within > the context of the program's windows. In practice this means that > I needed > plplot to have the ability to plot to a supplied X Drawable rather > than to an X window which plplot creates and manages itself. How well do you think it would work to have PLplot/cairo draw into a memory buffer which is then transfered by the library user to a X Drawable? This seems to be more general, but perhaps plotting to X Drawable already covers 90% of the common use cases? The structure for this already exists to some extent in the form of the memcairo driver, but unfortunately this driver is not yet functional. Also, in your patch, you need to consider the situation where the user does not have X Windows and the related libraries installed on their machine. best, -Hazen |
From: Jonathan W. <jw...@ph...> - 2008-03-05 04:25:49
|
> On Mar 4, 2008, at 9:36 PM, Jonathan Woithe wrote: > > > I am working on an application which requires plots to be displayed > > within the context of the program's windows. In practice this means > > that I needed plplot to have the ability to plot to a supplied X > > Drawable rather than to an X window which plplot creates and manages > > itself. > > How well do you think it would work to have PLplot/cairo draw into a > memory buffer which is then transfered by the library user to a X > Drawable? This seems to be more general, but perhaps plotting to X > Drawable already covers 90% of the common use cases? In terms xcairo driver users I would expect the Drawable approach to cover nearly every possibility because an X Drawable can be provided by most (if not all) X11 GUI framework. For users not utilising X the xcairo driver is not really useful anyway. > The structure for this already exists to some extent in the form of the > memcairo driver, but unfortunately this driver is not yet functional. If the memcairo driver becomes functional then perhaps that could be used instead. As you mentioned though, it doesn't work now and so isn't a viable solution at present. Having said that, I suspect there are performance advantages when using a Drawable if the ultimate destination of the image is an X display. > Also, in your patch, you need to consider the situation where the > user does not have X Windows and the related libraries installed on > their machine. Sorry, I'm not sure I understand why this is an issue or what it is you are referring to. If the user "does not have X Windows and the related libraries installed on their machine" then the cairo / xcairo drivers either won't compile or won't link at runtime. Either way they will not be useable. My patch doesn't introduce any new external dependencies that don't already exist within the xcairo driver so I'm uncertain as to what precisely it is that I need to consider. I should explicitly state here that my patch only modifies the xcairo driver. The other cairo drivers are totally unaffected. Regards jonathan |
From: Doug H. <dh...@ma...> - 2008-03-05 16:12:16
|
Hazon, Jonathan: I would second the idea of having a memory buffer be the target at some level. I would be interested in getting memcairo working--this allows for powerful direct manipulation of images via PDL, plplot and image libraries. I have used this to good effect on several occasions, but the current limitation are the ugly fonts used by the plain vanilla 'mem' driver. Regards, Doug Hunt dh...@uc... Software Engineer III UCAR - COSMIC, Tel. (303) 497-2611 On Tue, 4 Mar 2008, Hazen Babcock wrote: > > On Mar 4, 2008, at 9:36 PM, Jonathan Woithe wrote: > >> Hi >> >> I am working on an application which requires plots to be displayed >> within >> the context of the program's windows. In practice this means that >> I needed >> plplot to have the ability to plot to a supplied X Drawable rather >> than to an X window which plplot creates and manages itself. > > How well do you think it would work to have PLplot/cairo draw into a > memory buffer which is then transfered by the library user to a X > Drawable? This seems to be more general, but perhaps plotting to X > Drawable already covers 90% of the common use cases? The structure > for this already exists to some extent in the form of the memcairo > driver, but unfortunately this driver is not yet functional. > > Also, in your patch, you need to consider the situation where the > user does not have X Windows and the related libraries installed on > their machine. > > best, > -Hazen > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Plplot-devel mailing list > Plp...@li... > https://lists.sourceforge.net/lists/listinfo/plplot-devel > |
From: Jonathan W. <jw...@ph...> - 2008-03-05 22:54:57
|
Hi guys > Hazon, Jonathan: I would second the idea of having a memory buffer be the > target at some level. I have no arguments with this. However, a memory buffer is really targetting a slightly different problem. An X Drawable is a server-side resource and therefore there are possibly performance advantages to using a Drawable if an X Window was the ultimate destination of the plot. In my mind the ability to output to an X Drawable complements something like memcairo. One would use memcairo if, for example, direct editing of the image were desired. > I would be interested in getting memcairo working--this allows for > powerful direct manipulation of images via PDL, plplot and image > libraries. I have used this to good effect on several occasions, but the > current limitation are the ugly fonts used by the plain vanilla 'mem' > driver. For sure. As I said, I do not see the X Drawable extension to the xcairo device as a replacement for memcairo. They are both addressing different problem spaces IMHO. Besides this, the X Drawable extension doesn't really add a lot of additional code to the xcairo driver while making plplot directly accessible to almost all Xwindows developers. This is why I am keen to see it merged. Regards jonathan |
From: Hazen B. <hba...@ma...> - 2008-03-07 01:18:27
|
On Mar 5, 2008, at 5:54 PM, Jonathan Woithe wrote: > > For sure. As I said, I do not see the X Drawable extension to the > xcairo > device as a replacement for memcairo. They are both addressing > different > problem spaces IMHO. > > Besides this, the X Drawable extension doesn't really add a lot of > additional code to the xcairo driver while making plplot directly > accessible > to almost all Xwindows developers. This is why I am keen to see it > merged. I agree that having both is a reasonable proposal and I think it should be possible to merge something like this before the next release. Does anyone know if the current xwin driver supports a X Drawable? If it does then it might be a good idea to try and keep the interfaces consistent. If it does not are their any objections to Jonathan's proposed interface? best, -Hazen |
From: Maurice L. <mj...@br...> - 2008-03-07 02:34:49
|
On Thursday, March 6, 2008 at 20:15:18 (-0500) Hazen Babcock writes: > > On Mar 5, 2008, at 5:54 PM, Jonathan Woithe wrote: > > > > For sure. As I said, I do not see the X Drawable extension to the > > xcairo > > device as a replacement for memcairo. They are both addressing > > different > > problem spaces IMHO. > > > > Besides this, the X Drawable extension doesn't really add a lot of > > additional code to the xcairo driver while making plplot directly > > accessible > > to almost all Xwindows developers. This is why I am keen to see it > > merged. > > I agree that having both is a reasonable proposal and I think it > should be possible to merge something like this before the next release. > > Does anyone know if the current xwin driver supports a X Drawable? If > it does then it might be a good idea to try and keep the interfaces > consistent. If it does not are their any objections to Jonathan's > proposed interface? It doesn't currently. The proposed interface seemed ok to me, sounds like a good idea in general. Any plans to make available a test/demo program for showing this off? -- Maurice LeBrun |
From: Jonathan W. <jw...@ph...> - 2008-03-07 02:38:38
|
Hi guys > On Mar 5, 2008, at 5:54 PM, Jonathan Woithe wrote: > > > > For sure. As I said, I do not see the X Drawable extension to the > > xcairo device as a replacement for memcairo. They are both addressing > > different problem spaces IMHO. > > > > Besides this, the X Drawable extension doesn't really add a lot of > > additional code to the xcairo driver while making plplot directly > > accessible > > to almost all Xwindows developers. This is why I am keen to see it > > merged. > > I agree that having both is a reasonable proposal and I think it > should be possible to merge something like this before the next release. > > Does anyone know if the current xwin driver supports a X Drawable? If > it does then it might be a good idea to try and keep the interfaces > consistent. As far as I could tell it does not - otherwise I would have used it (or at least derived my X Drawable interface from it). > Any plans to make available a test/demo program for showing this off? I've got the small test program I used when developing the patch - I'll try to knock it into shape and post it either later today or on Monday. Regards jonathan |
From: Hazen B. <hba...@ma...> - 2008-03-09 21:50:27
|
On Mar 6, 2008, at 9:38 PM, Jonathan Woithe wrote: > Hi guys >> >> I agree that having both is a reasonable proposal and I think it >> should be possible to merge something like this before the next >> release. >> >> Does anyone know if the current xwin driver supports a X Drawable? If >> it does then it might be a good idea to try and keep the interfaces >> consistent. > > As far as I could tell it does not - otherwise I would have used it > (or at > least derived my X Drawable interface from it). I applied your patch and I tested it just to make sure that things still worked the "standard" way. If you have a chance, could you verify that it also works for you and as you intended? You'll need to get version 8258+ from our svn repo. Thanks for the contribution, it enables a nice separation of graphing and window management, which was never a strength of xcairo. best, -Hazen |
From: Jonathan W. <jw...@ph...> - 2008-03-11 06:43:04
|
Hi Hazen > >> I agree that having both is a reasonable proposal and I think it > >> should be possible to merge something like this before the next > >> release. > >> > >> Does anyone know if the current xwin driver supports a X Drawable? If > >> it does then it might be a good idea to try and keep the interfaces > >> consistent. > > > > As far as I could tell it does not - otherwise I would have used it > > (or at > > least derived my X Drawable interface from it). > > I applied your patch and I tested it just to make sure that things > still worked the "standard" way. If you have a chance, could you > verify that it also works for you and as you intended? You'll need to > get version 8258+ from our svn repo. I've tested this functionality in svn 8268 and it appears to work fine. Thanks for merging this. I'll try to test this with multiple streams soon but it *should* be fine. One extremely minor quibble: the spelling of my name in the svn log entry is incorrect. It should be "Woithe", not "Woite". :-) Regards jonathan |
From: Jonathan W. <jw...@ph...> - 2008-03-07 06:12:37
|
Hi > > > For sure. As I said, I do not see the X Drawable extension to the > > > xcairo device as a replacement for memcairo. They are both > > > addressing different problem spaces IMHO. > > > > > > Besides this, the X Drawable extension doesn't really add a lot of > > > additional code to the xcairo driver while making plplot directly > > > accessible to almost all Xwindows developers. This is why I am keen > > > to see it merged. > > > > I agree that having both is a reasonable proposal and I think it > > should be possible to merge something like this before the next release. > > > > Does anyone know if the current xwin driver supports a X Drawable? If > > it does then it might be a good idea to try and keep the interfaces > > consistent. If it does not are their any objections to Jonathan's > > proposed interface? > : > Any plans to make available a test/demo program for showing this off? A small-ish demo is attached. It uses GTK since that's what I was using when developing the code but it trivially generalises to any framework so long as an X Display and an X Drawable are accessible (including, obviously, a "pure" libX11 application). The attached program can be compiled so plot via a pixmap or directly to an X Window. This program compiles and runs against plplot patched as per the patch I posted. The only change to a production version would be that the structure used for xinfo in setup_plot_drawable() would have a type of PLXcairoDrawableInfo once its declaration was moved to plplot.h. Under bash compile with: gcc -Wall $(pkg-config --cflags --libs plplotd gtk+-2.0) \ -o plplot_xdrawable_demo plplot_xdrawable_demo.c Regards jonathan /* * A simple GTK application demonstrating the use of the X Drawable * functionality of plplot's xcairo driver. * * Copyright (C) 2008 Jonathan Woithe <jw...@ph...> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ /* Set to 0 to draw direct to an X Window, 1 to draw via a pixmap */ #define TO_PIXMAP 1 #include <stdio.h> #include <plplot.h> #include <gtk/gtk.h> /* Needed for GDK_WINDOW_XID */ #include <gdk/gdkx.h> /* Main menu structure */ static GtkItemFactoryEntry menu_items[] = { { "/_File", NULL, NULL, 0, "<Branch>" }, { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL }, }; #define APP_INITIAL_WIDTH 320 #define APP_INITIAL_HEIGHT 200 typedef struct App { GtkWidget *rootwindow; GtkWidget *plotwindow; GdkPixmap *plotwindow_pixmap; } App; App app; /* ======================================================================== */ void setup_plot_drawable(App *app) { struct { Display *display; Drawable drawable; } xinfo; PLFLT x[3] = {1,3,4}; PLFLT y[3] = {3,2,5}; plsdev("xcairo"); plsetopt("drvopt", "external_drawable"); plinit(); #if TO_PIXMAP==1 /* Here we set up to draw to a pixmap */ xinfo.display = GDK_PIXMAP_XDISPLAY(app->plotwindow_pixmap); xinfo.drawable = GDK_PIXMAP_XID(app->plotwindow_pixmap); #else /* Alternatively, we can do direct to a visible X Window */ xinfo.display = GDK_WINDOW_XDISPLAY(app->plotwindow->window); xinfo.drawable = GDK_WINDOW_XID(app->plotwindow->window); #endif pl_cmd(PLESC_DEVINIT, &xinfo); plenv(0,5,0,5,0,0); plline(3, x, y); plend(); } /* ======================================================================== */ static gint ev_plotwindow_conf(GtkWidget *widget, GdkEventConfigure *ev, gpointer *data) { #if TO_PIXMAP==1 /* Allocate pixmap */ if (app.plotwindow_pixmap) gdk_pixmap_unref(app.plotwindow_pixmap); app.plotwindow_pixmap = gdk_pixmap_new(widget->window, widget->allocation.width,widget->allocation.height,-1); /* Clear the pixmap to a sensible background colour */ gdk_draw_rectangle(app.plotwindow_pixmap, widget->style->black_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); /* If drawing to a pixmap we can do a plot from the conf handler since * the pixmap is now realised (the window widget isn't). */ setup_plot_drawable(&app); #endif return(TRUE); } static gint ev_plotwindow_expose(GtkWidget *widget, GdkEventExpose *ev, gpointer *data) { #if TO_PIXMAP==1 /* Dump the cached plot (created in the conf handler) to the window from * the pixmap. We don't need to recreate the plot on each expose. */ gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], app.plotwindow_pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); #else /* If drawing direct to an X Window, ensure GTK's double buffering * is turned off for that window or else the plot will be overridden * when the buffer is dumped to the screen. */ setup_plot_drawable(&app); #endif return(TRUE); } /* ======================================================================== */ void init_app(App *app) { GtkWidget *menubar; GtkItemFactory *item_factory; GtkAccelGroup *accel_group = gtk_accel_group_new(); signed int nitems = sizeof(menu_items) / sizeof(menu_items[0]); GtkWidget *vbox, *hbox; /* Create the top-level root window */ app->rootwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(app->rootwindow), "delete_event", gtk_main_quit, NULL); /* A toplevel box to hold things */ vbox = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(app->rootwindow), vbox); /* Construct the main menu structure */ item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR,"<main>",accel_group); gtk_item_factory_create_items(item_factory, nitems, menu_items, NULL); gtk_window_add_accel_group(GTK_WINDOW(app->rootwindow), accel_group); menubar = gtk_item_factory_get_widget(item_factory,"<main>"); gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); gtk_widget_show(menubar); /* Fiddle with boxes to effect an indent from the edges of the root window */ hbox = gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 10); vbox = gtk_vbox_new(FALSE,10); gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 10); /* Add an area to plot into */ app->plotwindow = gtk_drawing_area_new(); app->plotwindow_pixmap = NULL; #if TO_PIXMAP!=1 /* Turn off double buffering if we are plotting direct to the plotwindow * in setup_plot_drawable(). */ GTK_WIDGET_UNSET_FLAGS(app->plotwindow, GTK_DOUBLE_BUFFERED); #endif /* By experiment, 3x3 seems to be the smallest size plplot can cope with. * Here we utilise the side effect that gtk_widget_set_size_request() * effectively sets the minimum size of the widget. */ gtk_widget_set_size_request(app->plotwindow,3,3); gtk_box_pack_start(GTK_BOX(vbox), app->plotwindow, TRUE, TRUE, 0); // Set the initial size of the application gtk_window_set_default_size(GTK_WINDOW(app->rootwindow), APP_INITIAL_WIDTH,APP_INITIAL_HEIGHT); g_signal_connect(G_OBJECT(app->plotwindow), "configure_event", G_CALLBACK(ev_plotwindow_conf), NULL); g_signal_connect(G_OBJECT(app->plotwindow), "expose_event", G_CALLBACK(ev_plotwindow_expose), NULL); gtk_widget_show_all(app->rootwindow); } /* ======================================================================== */ int main(int argc, char *argv[]) { gtk_init(&argc, &argv); init_app(&app); gtk_main(); return 0; } /* ======================================================================== */ |
From: Hazen B. <hba...@ma...> - 2008-03-06 04:20:10
|
On Mar 5, 2008, at 11:12 AM, Doug Hunt wrote: > Hazon, Jonathan: I would second the idea of having a memory buffer > be the > target at some level. I would be interested in getting memcairo > working--this allows for powerful direct manipulation of images via > PDL, > plplot and image libraries. I have used this to good effect on > several > occasions, but the current limitation are the ugly fonts used by > the plain > vanilla 'mem' driver. What is your time frame? I might have time this weekend to try and figure out what is going wrong, but if you are already working on this... -Hazen |
From: Doug H. <dh...@ma...> - 2008-03-06 16:40:12
|
Hazen: (Sorry about the typo on your name!) I hope to be able to look into this today, but it might take me a while to get up to speed. I'll let you know if I find anything that might be of help on your weekend coding expedition... --Doug dh...@uc... Software Engineer III UCAR - COSMIC, Tel. (303) 497-2611 On Wed, 5 Mar 2008, Hazen Babcock wrote: > > On Mar 5, 2008, at 11:12 AM, Doug Hunt wrote: > >> Hazon, Jonathan: I would second the idea of having a memory buffer be the >> target at some level. I would be interested in getting memcairo >> working--this allows for powerful direct manipulation of images via PDL, >> plplot and image libraries. I have used this to good effect on several >> occasions, but the current limitation are the ugly fonts used by the plain >> vanilla 'mem' driver. > > What is your time frame? I might have time this weekend to try and figure out > what is going wrong, but if you are already working on this... > > -Hazen |
From: Doug H. <dh...@ma...> - 2008-03-07 00:03:00
Attachments:
testMemCairo1.png
plplot_5.9.0.memcairo.patch
|
Hi Hazen, all: I think I was able to get the memcairo driver working. Attached is a patch to plplot-5.9.0:drivers/cairo.c. The immediate problem was that the X and Y dimensions of the plot were not correct in plD_eop_memcairo. The PLstream record values pls->phyxma and pls->phyyma were updated during plotting (made larger) so that when the cairo drawing surface memory was copied back out to the user-supplied memory area, a SEGFAULT occurred. I replaced pls->phyxma and pls->phyyma in the loop with pls->xlength and pls->ylength (these were set up for this purpose in plD_init_memcairo) and that seemed to do the trick. The other changes I made were more basic. It seems that the memcairo driver as it stands was designed to overwrite the user-input memory area, initializing it to all black. This behavior is not useful, as the purpose of the 'mem' drivers (as I understand it) is to be able to add decoration to a user-supplied image (see the attachment). In order to get this behavior, I had to initialize the cairo drawing surface with the user-input memory area, using 'cairo_image_surface_create_for_data' instead of 'cairo_image_surface_create'. I also added an empty subroutine plD_bop_memcairo which is used instead of plD_bop_cairo. This is done because plD_bop_cairo zeroes out the image, which is not what is desired. Please take a look at this patch and consider including it in plplot. It has no effect on any driver other than memcairo. Regards, Doug Hunt dh...@uc... Software Engineer III UCAR - COSMIC, Tel. (303) 497-2611 On Wed, 5 Mar 2008, Hazen Babcock wrote: > > On Mar 5, 2008, at 11:12 AM, Doug Hunt wrote: > >> Hazon, Jonathan: I would second the idea of having a memory buffer be the >> target at some level. I would be interested in getting memcairo >> working--this allows for powerful direct manipulation of images via PDL, >> plplot and image libraries. I have used this to good effect on several >> occasions, but the current limitation are the ugly fonts used by the plain >> vanilla 'mem' driver. > > What is your time frame? I might have time this weekend to try and figure out > what is going wrong, but if you are already working on this... > > -Hazen |
From: Hazen B. <hba...@ma...> - 2008-03-09 22:17:23
|
On Mar 6, 2008, at 6:52 PM, Doug Hunt wrote: > Hi Hazen, all: I think I was able to get the memcairo driver > working. Attached is a patch to plplot-5.9.0:drivers/cairo.c. > > The immediate problem was that the X and Y dimensions of the plot > were not correct in plD_eop_memcairo. The PLstream record values > pls->phyxma and pls->phyyma were updated during plotting (made > larger) so that when the cairo drawing surface memory was copied > back out to the user-supplied memory area, a SEGFAULT occurred. > > I replaced pls->phyxma and pls->phyyma in the loop with pls- > >xlength and pls->ylength (these were set up for this purpose in > plD_init_memcairo) and that seemed to do the trick. > > The other changes I made were more basic. It seems that the > memcairo driver as it stands was designed to overwrite the user- > input memory area, initializing it to all black. This behavior is > not useful, as the purpose of the 'mem' drivers (as I understand > it) is to be able to add decoration to a user-supplied image (see > the attachment). > > In order to get this behavior, I had to initialize the cairo > drawing surface with the user-input memory area, using > > 'cairo_image_surface_create_for_data' > > instead of > > 'cairo_image_surface_create'. > > I also added an empty subroutine plD_bop_memcairo which is used > instead of plD_bop_cairo. This is done because plD_bop_cairo > zeroes out the image, which is not what is desired. > > Please take a look at this patch and consider including it in > plplot. It has no effect on any driver other than memcairo. Hi Doug, It looks good. I applied it and now the memcairo driver works as expected (v8261). Thanks for your work to make this driver functional. best, -Hazen |
From: Doug H. <dh...@ma...> - 2008-03-10 15:53:24
|
Hazen: Thanks! --Doug dh...@uc... Software Engineer III UCAR - COSMIC, Tel. (303) 497-2611 On Sun, 9 Mar 2008, Hazen Babcock wrote: > > On Mar 6, 2008, at 6:52 PM, Doug Hunt wrote: > >> Hi Hazen, all: I think I was able to get the memcairo driver working. >> Attached is a patch to plplot-5.9.0:drivers/cairo.c. >> >> The immediate problem was that the X and Y dimensions of the plot were not >> correct in plD_eop_memcairo. The PLstream record values pls->phyxma and >> pls->phyyma were updated during plotting (made larger) so that when the >> cairo drawing surface memory was copied back out to the user-supplied >> memory area, a SEGFAULT occurred. >> >> I replaced pls->phyxma and pls->phyyma in the loop with pls->xlength and >> pls->ylength (these were set up for this purpose in plD_init_memcairo) and >> that seemed to do the trick. >> >> The other changes I made were more basic. It seems that the memcairo >> driver as it stands was designed to overwrite the user-input memory area, >> initializing it to all black. This behavior is not useful, as the purpose >> of the 'mem' drivers (as I understand it) is to be able to add decoration >> to a user-supplied image (see the attachment). >> >> In order to get this behavior, I had to initialize the cairo drawing >> surface with the user-input memory area, using >> >> 'cairo_image_surface_create_for_data' >> >> instead of >> >> 'cairo_image_surface_create'. >> >> I also added an empty subroutine plD_bop_memcairo which is used instead of >> plD_bop_cairo. This is done because plD_bop_cairo zeroes out the image, >> which is not what is desired. >> >> Please take a look at this patch and consider including it in plplot. It >> has no effect on any driver other than memcairo. > > Hi Doug, > > It looks good. I applied it and now the memcairo driver works as expected > (v8261). Thanks for your work to make this driver functional. > > best, > -Hazen |
From: Doug H. <dh...@ma...> - 2008-03-12 15:34:14
|
Hi again, Hazen, all: I just noticed that the patch I sent contains a bug. I used malloc where I ought to have used calloc in one place. Would it be possible for me to get SVN access so I can just fix this myself? I'd also like to look into the possibility of adding optional alpha channel support for the memcairo driver in the future. Thanks much! --Doug Hunt dh...@uc... Software Engineer III UCAR - COSMIC, Tel. (303) 497-2611 On Sun, 9 Mar 2008, Hazen Babcock wrote: > > On Mar 6, 2008, at 6:52 PM, Doug Hunt wrote: > >> Hi Hazen, all: I think I was able to get the memcairo driver working. >> Attached is a patch to plplot-5.9.0:drivers/cairo.c. >> >> The immediate problem was that the X and Y dimensions of the plot were not >> correct in plD_eop_memcairo. The PLstream record values pls->phyxma and >> pls->phyyma were updated during plotting (made larger) so that when the >> cairo drawing surface memory was copied back out to the user-supplied >> memory area, a SEGFAULT occurred. >> >> I replaced pls->phyxma and pls->phyyma in the loop with pls->xlength and >> pls->ylength (these were set up for this purpose in plD_init_memcairo) and >> that seemed to do the trick. >> >> The other changes I made were more basic. It seems that the memcairo >> driver as it stands was designed to overwrite the user-input memory area, >> initializing it to all black. This behavior is not useful, as the purpose >> of the 'mem' drivers (as I understand it) is to be able to add decoration >> to a user-supplied image (see the attachment). >> >> In order to get this behavior, I had to initialize the cairo drawing >> surface with the user-input memory area, using >> >> 'cairo_image_surface_create_for_data' >> >> instead of >> >> 'cairo_image_surface_create'. >> >> I also added an empty subroutine plD_bop_memcairo which is used instead of >> plD_bop_cairo. This is done because plD_bop_cairo zeroes out the image, >> which is not what is desired. >> >> Please take a look at this patch and consider including it in plplot. It >> has no effect on any driver other than memcairo. > > Hi Doug, > > It looks good. I applied it and now the memcairo driver works as expected > (v8261). Thanks for your work to make this driver functional. > > best, > -Hazen |
From: Hazen B. <hba...@ma...> - 2008-03-12 22:56:08
|
On Mar 12, 2008, at 11:34 AM, Doug Hunt wrote: > Hi again, Hazen, all: I just noticed that the patch I sent > contains a bug. I used malloc where I ought to have used calloc in > one place. > > Would it be possible for me to get SVN access so I can just fix > this myself? I'd also like to look into the possibility of adding > optional alpha channel support for the memcairo driver in the future. memcairo doesn't already have alpha channel support? All the other cairo drivers do since they use shared drawing functions. I'll defer your question re SVN access to one of the project administrators, though I suspect that it won't be a problem. -Hazen |
From: Doug H. <dh...@ma...> - 2008-03-12 23:34:45
|
Hi Hazen: The original 'mem' driver plotted into an unsigned char array with size 3 x height x width (thus no alpha channel). The cairo drivers plot into 32 bit RGB arrays (with an alpha channel). For the memcairo driver (as a first cut), I just copied in the 24 bits of RGB info into the 32 bit RGB/alpha words, leaving the alpha channel 0. When cairo is done with its magic, the 32bit RGB/alpha words are copied back into a 24 bit RGB array. I'd like to figure out how to get my graphics package to work with an alpha channel and add an option to pass in 32 bit RGB/alpha words. Regards, Doug dh...@uc... Software Engineer III UCAR - COSMIC, Tel. (303) 497-2611 On Wed, 12 Mar 2008, Hazen Babcock wrote: > > On Mar 12, 2008, at 11:34 AM, Doug Hunt wrote: > >> Hi again, Hazen, all: I just noticed that the patch I sent contains a bug. >> I used malloc where I ought to have used calloc in one place. >> >> Would it be possible for me to get SVN access so I can just fix this >> myself? I'd also like to look into the possibility of adding optional >> alpha channel support for the memcairo driver in the future. > > memcairo doesn't already have alpha channel support? All the other cairo > drivers do since they use shared drawing functions. > > I'll defer your question re SVN access to one of the project administrators, > though I suspect that it won't be a problem. > > -Hazen |
From: Hazen B. <hba...@ma...> - 2008-03-12 23:44:17
|
On Mar 12, 2008, at 7:28 PM, Doug Hunt wrote: > Hi Hazen: > > The original 'mem' driver plotted into an unsigned char array with > size > 3 x height x width (thus no alpha channel). The cairo drivers plot > into > 32 bit RGB arrays (with an alpha channel). For the memcairo driver > (as a > first cut), I just copied in the 24 bits of RGB info into the 32 bit > RGB/alpha words, leaving the alpha channel 0. When cairo is done > with its > magic, the 32bit RGB/alpha words are copied back into a 24 bit RGB > array. > > I'd like to figure out how to get my graphics package to work with an > alpha channel and add an option to pass in 32 bit RGB/alpha words. If I understand correctly, this alpha channel would be for the purposes of overlaying the memcairo array onto another array, possibly generated by some other rendering program? A reasonable alpha equivalent of plsmem() might be plsmema(), which would follow the convention that we used for the other alpha support channels. Then I guess it is just a matter of memcairo knowing whether it is dealing with a 24bit or a 32bit array. -Hazen |
From: Hazen B. <hba...@ma...> - 2008-03-22 03:06:43
|
On Mar 4, 2008, at 9:36 PM, Jonathan Woithe wrote: > Hi > > I am working on an application which requires plots to be displayed > within > the context of the program's windows. In practice this means that > I needed > plplot to have the ability to plot to a supplied X Drawable rather > than to an X window which plplot creates and manages itself. Another thought along this line. How about a driver that would plot to a supplied cairo context? This is easy to get from e.g. Gdk, and it might provide some extra flexibility. Gtk on Windows might for example benefit from this approach. This driver could be called just "cairo" to emphasize its generic nature. -Hazen |
From: Jonathan W. <jw...@ph...> - 2008-03-24 23:09:04
|
> > I am working on an application which requires plots to be displayed > > within the context of the program's windows. In practice this means > > that I needed plplot to have the ability to plot to a supplied X > > Drawable rather than to an X window which plplot creates and manages > > itself. > > Another thought along this line. How about a driver that would plot > to a supplied cairo context? This is easy to get from e.g. Gdk, and > it might provide some extra flexibility. Gtk on Windows might for > example benefit from this approach. This driver could be called just > "cairo" to emphasize its generic nature. It's a fair thought and probably not all that difficult to do. The existing cairo framework could be used, with an extension like I did for X Drawables being used to pass in an externally created cairo context. I could look into this in more detail but I won't have a lot of time over the next few weeks. If no one else beats me to it I'll pick up on this when time allows. Regards jonathan |
From: Hazen B. <hba...@ma...> - 2008-04-07 00:41:20
|
On Mar 24, 2008, at 7:08 PM, Jonathan Woithe wrote: >>> I am working on an application which requires plots to be displayed >>> within the context of the program's windows. In practice this means >>> that I needed plplot to have the ability to plot to a supplied X >>> Drawable rather than to an X window which plplot creates and manages >>> itself. >> >> Another thought along this line. How about a driver that would plot >> to a supplied cairo context? This is easy to get from e.g. Gdk, and >> it might provide some extra flexibility. Gtk on Windows might for >> example benefit from this approach. This driver could be called just >> "cairo" to emphasize its generic nature. > > It's a fair thought and probably not all that difficult to do. The > existing > cairo framework could be used, with an extension like I did for X > Drawables > being used to pass in an externally created cairo context. > > I could look into this in more detail but I won't have a lot of > time over > the next few weeks. If no one else beats me to it I'll pick up on > this when > time allows. I've started on this, and decided to call the device "extcairo" for Cairo external context driver. While working on this, I noticed that for the xcairo driver with external drawable you clear the drawable before plotting. Any thoughts on whether it might be better to leave that to the end user in case they don't want the current contents of the drawable erased? This is the approach that Doug has taken with the memcairo driver. best, -Hazen |
From: Jonathan W. <jw...@ph...> - 2008-04-07 01:17:10
|
Hi Hazen > >>> I am working on an application which requires plots to be displayed > >>> within the context of the program's windows. In practice this means > >>> that I needed plplot to have the ability to plot to a supplied X > >>> Drawable rather than to an X window which plplot creates and manages > >>> itself. > >> > >> Another thought along this line. How about a driver that would plot > >> to a supplied cairo context? This is easy to get from e.g. Gdk, and > >> it might provide some extra flexibility. Gtk on Windows might for > >> example benefit from this approach. This driver could be called just > >> "cairo" to emphasize its generic nature. > > > > It's a fair thought and probably not all that difficult to do. The > > existing cairo framework could be used, with an extension like I did for > > X Drawables being used to pass in an externally created cairo context. > > > > I could look into this in more detail but I won't have a lot of time > > over the next few weeks. If no one else beats me to it I'll pick up on > > this when time allows. > > I've started on this, and decided to call the device "extcairo" for > Cairo external context driver. Sounds fine. > While working on this, I noticed that for the xcairo driver with external > drawable you clear the drawable before plotting. Any thoughts on whether > it might be better to leave that to the end user in case they don't want > the current contents of the drawable erased? This is the approach that > Doug has taken with the memcairo driver. Really? I didn't think the drawable was being cleared although this could be the result of a memory of things I observed partway though the development of the external drawable code. In any case, I think arguments could be made that the "clearing to the background colour" should at least be made an option, as you stated above. Having said that, things are as they are because this is the behaviour of the current cairo-based devices. Admittedly a pre-existing drawable is different from one created by plplot but even so, consistency can sometimes be a good thing. The other thing to bear in mind is that "clearing to the background colour" will be the usual operational mode I would imagine, so an argument could be raised that the "don't clear" behaviour should be an opt-in option - possibly set using a new escape function or perhaps via a new "flags" option to the PLXcairoDrawableInfo structure. If we went with the latter though, PLXcairoDrawableInfo really needs to be made available to applications. Currently there's only 2 members - the display and the drawable - and it's not too hard for users to hack up their own structure to pass in. However, once we go beyond this PLXcairoDrawableInfo really must be publically available so users can't get it wrong. For what it's worth I think the PLXcairoDrawableInfo definition should be public anyway but from what I've been lead to believe there are issues with this - something about compilation of the plplot headers when X isn't on the system. Regards jonathan |
From: Hazen B. <hba...@ma...> - 2008-04-08 02:22:07
|
On Apr 6, 2008, at 9:17 PM, Jonathan Woithe wrote: > > Having said that, things are as they are because this is the > behaviour of > the current cairo-based devices. Admittedly a pre-existing > drawable is > different from one created by plplot but even so, consistency can > sometimes > be a good thing. The other thing to bear in mind is that "clearing > to the > background colour" will be the usual operational mode I would > imagine, so an > argument could be raised that the "don't clear" behaviour should be an > opt-in option - possibly set using a new escape function or perhaps > via a > new "flags" option to the PLXcairoDrawableInfo structure. If we > went with > the latter though, PLXcairoDrawableInfo really needs to be made > available > to applications. Currently there's only 2 members - the display > and the > drawable - and it's not too hard for users to hack up their own > structure > to pass in. However, once we go beyond this PLXcairoDrawableInfo > really > must be publically available so users can't get it wrong. I'd propose making "clearing to the background color" a driver option so that we can use it with xcairo, memcairo and extcairo. I think that we should make our decision about the clearing default consistent across these 3 driver options, but I don't have much preference about whether or not clearing is the default. Doug, any thoughts about having clearing be the default? best, -Hazen |