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
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
