Hi,

I've been working on creating a plplot widget in gtkmm [1], this widget
uses the extcairo driver. In order to get this widget working I've been
making several modifications to the plplot sources.

The first version of the widget did a full redraw for every modification
and redraw. This was required since the only way to modify the size of
the drawing area was the geometry command line parameter. This method
resulted in two problems. The first was that it's too slow and has a lot
of redraw flickering, the second that although the streams should be
destroyed I run out of streams. (The attached example shows this issue.)

So I went to look how to notify plplot about the changes in geometry. In
the extcairo driver source for the PLESC_DEVINIT escape function there
are some questions whether it should fit into the current context.
plplot has access to the context and its clipping rectangle. Upon a full
redraw the clipping rectangle is the entire context, when partially
redrawn it's the dirty area.
So it's only possible to get the size of the context upon a full redraw.
I haven't been able to determine whether a redraw is partial or full
from within the context, but it's possible to have this information on
the caller side. So I added a extra escape function PLESC_DEVINIT_FIT
which sets the size of the physical plot area to the clip rectangle.
This also allows you to only draw a on a part of the context. As noted
before [2] the offset is ignored, so it isn't possible yet to draw at an
offset. (I might take up on Alan's offer to accept patches.)
So in the current code PLESC_DEVINIT behaves as before and
PLESC_DEVINIT_FIT adjusts the size of the physical plot area to the clip
rectangle of the context. (I'm not entirely happy with that name and am
open to better suggestions.)

I use the PLESC_REDRAW escape function to redraw the widget when dirty.
I'm not entirely sure whether this functionality should use PLESC_REDRAW
or PLESC_EXPOSE.

I also added the PLESC_RESIZE escape function, but that doesn't work as
wanted yet.

Attached a lightly tested proof-of-concept patch shows the new
functionality and the attached sample program to show how it works and
demonstrate some problems I still have. The sample program requires
GTKMM and uses the cmake build system. The example also has some #if 0
parts to show some of the problems encountered; what goes wrong if a
partial redraw would use PLESC_DEVINIT_FIT and current problem with
PLESC_RESIZE and PLESC_DEVINIT_FIT.

When using PLESC_DEVINIT_FIT or PLESC_RESIZE to resize the plot area
plplot uses the new area, but the scaling doesn't work as wanted. I
haven't found a solution yet, but I assume I need to call an/some extra
function(s). I would be happy if somebody who has a deeper knowledge of
the plplot core could help me to identify what's missing. The problem
can be seen when the application is first shown, the widget labeled
"Using clip extents, ori 0" doesn't look like the widget above it, after
resizing the window and back to its original size it looks like the one
above it. It also shows when the resizing uses PLESC_RESIZE.

When using the geometry based widget the applications soon runs out of
streams, when you resize the widgets. This seems like a bug, since the
destructor of the object should free the stream. I might look into this
issue later, for demonstration purposes I increased PL_NSTREAMS.

I'm not familiar with the naming style of internal plplot functions I so
just added the function with a fitting name (init_context), please let
me know what would be the proper name for this function.

Once PLESC_REDRAW/PLESC_EXPOSE and PLESC_RESIZE work properly it would
be possible to let PLESC_DEVINIT always use the current clipping
rectangle and remove the PLESC_DEVINIT_FIT escape function. But I'm not
sure whether this is really wanted and/or how much existing code it
would break.

[1] http://gtkmm.org
[2]
http://www.mail-archive.com/[email protected]/msg03634.html

Regards,
Mark de Wever


diff --git a/drivers/cairo.c b/drivers/cairo.c
index 3d24c23..08fc4f0 100644
--- a/drivers/cairo.c
+++ b/drivers/cairo.c
@@ -2339,6 +2339,43 @@ void plD_eop_extcairo(PLStream *pls)
   an external Cairo context to use for rendering.
   ---------------------------------------------------------------------*/
 
+static void init_context(PLStream *pls,  void *ptr, PLCairo *aStream
+               , const int fit_to_clip)
+{
+      aStream->cairoContext = (cairo_t *)ptr;
+
+      /* Set graphics aliasing */
+      cairo_set_antialias(aStream->cairoContext, 
aStream->graphics_anti_aliasing);
+
+         if(fit_to_clip) {
+                 /* Adjust the size to the size of the clip_rect */
+                 double x1, y1, x2, y2;
+                 cairo_clip_extents(aStream->cairoContext, &x1, &y1, &x2, &y2);
+
+                 pls->xlength = x2 - x1;
+                 pls->ylength = y2 - y1;
+                 // Note cairo device currently doesn't support the offset 
parameters
+                 // so setting them has no effect.
+                 pls->xoffset = x1;
+                 pls->yoffset = y1;
+
+                 PLFLT downscale = 0.0;
+                 if (pls->xlength > pls->ylength)
+                         downscale = (double)pls->xlength/(double)(PIXELS_X-1);
+                 else
+                         downscale = (double)pls->ylength/(double)PIXELS_Y;
+                 plP_setphy((PLINT) 0, (PLINT) (pls->xlength / downscale), 
(PLINT) 0, (PLINT) (pls->ylength / downscale));
+                 plP_setpxl(DPI/25.4/downscale, DPI/25.4/downscale);
+                 aStream->downscale = downscale;
+
+                 // Set up the rotation
+                 plsdiori(pls->diorot);
+         }
+
+      /* 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);
+}
+
 void plD_esc_extcairo(PLStream *pls, PLINT op, void *ptr)
 {
   PLCairo *aStream;
@@ -2347,18 +2384,24 @@ void plD_esc_extcairo(PLStream *pls, PLINT op, void 
*ptr)
 
   switch(op)
     {
+    case PLESC_DEVINIT_FIT: /* Set external context */
+               init_context(pls, ptr, aStream, 1);
+               break;
+
     case PLESC_DEVINIT: /* Set external context */
-      aStream->cairoContext = (cairo_t *)ptr;
-      /* Set graphics aliasing */
-      cairo_set_antialias(aStream->cairoContext, 
aStream->graphics_anti_aliasing);
+               init_context(pls, ptr, aStream, 0);
+               break;
 
-      /* 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);
+    case PLESC_RESIZE:
+               init_context(pls, ptr, aStream, 1);
+               plRemakePlot(pls);
+               break;
 
-      /* Should adjust plot size to fit in the given cairo context?
-         Cairo does not provide a way to query the dimensions of a context? */
+    case PLESC_REDRAW:
+               init_context(pls, ptr, aStream, 0);
+               plRemakePlot(pls);
+               break;
 
-      break;
     default: /* Fall back on default Cairo actions */
       plD_esc_cairo(pls, op, ptr);
       break;
diff --git a/include/plplot.h b/include/plplot.h
index dc99a7c..2aa796c 100644
--- a/include/plplot.h
+++ b/include/plplot.h
@@ -236,6 +236,7 @@ typedef void* PLPointer;
 #define PLESC_START_RASTERIZE   32      /* start rasterized rendering */
 #define PLESC_END_RASTERIZE     33      /* end rasterized rendering */
 #define PLESC_ARC               34      /* render an arc */
+#define PLESC_DEVINIT_FIT       35
 
 /* Alternative unicode text handling control characters */
 #define PLTEXT_FONTCHANGE       0       /* font change in the text stream */
diff --git a/include/plplotP.h b/include/plplotP.h
index 6dcf9b2..9631931 100644
--- a/include/plplotP.h
+++ b/include/plplotP.h
@@ -284,7 +284,7 @@ extern PLDLLIMPEXP_DATA(PLStream *)plsc;
 /* Some constants */
 
 #define PL_MAXPOLY     256     /* Max segments in polyline or polygon */
-#define PL_NSTREAMS    100     /* Max number of concurrent streams. */
+#define PL_NSTREAMS    10000   /* Max number of concurrent streams. */
 #define PL_RGB_COLOR   -1      /* A hack */
 
 #define TEXT_MODE      0


Attachment: plplot_test.tar.gz
Description: GNU Zip compressed data

------------------------------------------------------------------------------
Come build with us! The BlackBerry® Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9-12, 2009. Register now!
http://p.sf.net/sfu/devconf
_______________________________________________
Plplot-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/plplot-devel

Reply via email to