[GRASS-dev] g.cairocomp

Glynn Clements glynn at gclements.plus.com
Sat Dec 20 22:40:15 EST 2008


Martin Landa wrote:

> g.cairocomp seems to be promising. I am just not sure how to use it in
> wxGUI ('visual' and 'screen' parameters). Any pointers welcomed.

I was unsure of how to reliably choose a suitable visual, so I made it
a parameter. But it seems that the default visual will typically work,
so I've made it optional (r34961).

If you want to try the existing version, pick any visual from the list
displayed by xdpyinfo. The default visual is probably a good choice,
as that's what the cairo driver uses if you don't set GRASS_CAIRO_VISUAL.

The screen= parameter is already optional, and the default should
work. The default screen is the one after the dot in $DISPLAY (e.g. 
for ":0.1", 0 is the display and 1 is the default screen), or 0 if not
specified (e.g. if $DISPLAY is just ":0"). If you only have one
screen, then it will be 0.

Example usage:

	GRASS_PNGFILE=map1.xid d.rast elevation.dem
	GRASS_PNGFILE=map2.xid d.vect -c fields
	g.cairocomp in=map1.xid,map2.xid out=foo.xid width=640 height=480

foo.xid will contain the XID of the composed Pixmap.

The tricky part is figuring out how to make a wxBitmap out of this,
ideally without pulling it over to the client then sending it back to
the server.

AFAICT, this involves using gdk_pixmap_foreign_new_for_display() to
wrap the XID in a GdkPixmap, then a subclass of wxBitmap which
provides a new constructor using wxBitmap::SetPixmap() to do the
actual work.

In the meantime, I've attached a simple test program which can be used
to examine Pixmaps referenced by XID. Sample usage:

	./xpmdump `cat foo.xid` > foo.ppm	# RGB channels
	./xpmdump -a `cat foo.xid` > foo.pgm	# alpha channel

Once you're done testing, you can use:

	# note: foo.xid added to the list of inputs
	g.cairocomp -d in=map1.xid,map2.xid,foo.xid out=foo.xid width=640 height=480

to delete the pixmaps. Or modify the test program to call:

	XKillClient(dpy, AllTemporary)

to delete all resources owned by clients which have terminated in
RetainTemporary mode (which probably means d.* and g.cairocomp).

> Anyway, would be possible to implement support for wx map displays in
> d.mon. Something like
> 
> d.mon start=wx0
> d.rast elevation
> d.mon stop=wx0

d.mon doesn't exist in 7.0.

If you want d.* commands to interact with the GUI, you need to decide
upon a messaging mechanism

[wxWidgets has classes for DDE, with a TCP-based workalike on Unix;
wxPython doesn't appear to have bindings for it, though.]

You would really want to send the commands rather than just their
output, so that you can re-run the command if you zoom/pan/etc.

Once that's available, there are several options. One is to make
R_open_driver() send the programs arguments (e.g. via
G_recreate_command()) to the driver and quit (that would need
exceptions for e.g. "d.font -l", d.colorlist, etc).

Another is to add a new function which (most) d.* commands would call
to send the command to the GUI, unless they're actually being invoked
by the GUI. This would have the advantage that d.* scripts could send
the original command to the GUI rather than the various d.* commands
which they use.

Another would be to just create shell aliases, e.g.

	alias d.rast='g.gui.send d.rast'

-- 
Glynn Clements <glynn at gclements.plus.com>

-------------- next part --------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>

int main(int argc, char **argv)
{
	Display *dpy;
	Status st;
	Drawable xid;
	Window root;
	int x, y;
	unsigned int w, h, b, d;
	XImage *img;
	int i, j;
	const unsigned char *p;
	int alpha = 0;

	if (strcmp(argv[1], "-a") == 0) {
	    alpha = 1;
	    argv++;
	    argc--;
	}

	dpy = XOpenDisplay(NULL);
	xid = strtoul(argv[1], NULL, 0);

	st = XGetGeometry(dpy, xid, &root, &x, &y, &w, &h, &b, &d);
	if (!st)
	    return 1;

	fprintf(stderr, "root: 0x%08lx\n", (unsigned long) root);
	fprintf(stderr, "x, y: %d, %d\n", x, y);
	fprintf(stderr, "w, h: %u, %u\n", w, h);
	fprintf(stderr, "border: %u\n", b);
	fprintf(stderr, "depth: %u\n", d);

	printf("P%d\n%d %d\n255\n", alpha ? 5 : 6, w, h);

	img = XGetImage(dpy, xid, 0, 0, w, h, ~0, ZPixmap);
	for (j = 0; j < img->height; j++) {
	    p = (const unsigned char *) img->data + j * img->bytes_per_line;
	    for (i = 0; i < img->width; i++) {
		int b = *p++;
		int g = *p++;
		int r = *p++;
		int a = *p++;
		if (alpha)
		    putchar(a);
		else {
		    putchar(r);
		    putchar(g);
		    putchar(b);
		}
	    }
	}

	XCloseDisplay(dpy);

	return 0;
}



More information about the grass-dev mailing list