[GRASS-SVN] r34933 - in grass/trunk: general general/g.cairocomp lib/cairodriver

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Dec 19 11:51:39 EST 2008


Author: glynn
Date: 2008-12-19 11:51:39 -0500 (Fri, 19 Dec 2008)
New Revision: 34933

Added:
   grass/trunk/general/g.cairocomp/
   grass/trunk/general/g.cairocomp/Makefile
   grass/trunk/general/g.cairocomp/g.cairocomp.html
   grass/trunk/general/g.cairocomp/main.c
Modified:
   grass/trunk/general/Makefile
   grass/trunk/lib/cairodriver/Graph.c
   grass/trunk/lib/cairodriver/cairodriver.h
   grass/trunk/lib/cairodriver/read.c
   grass/trunk/lib/cairodriver/read_xid.c
   grass/trunk/lib/cairodriver/write.c
   grass/trunk/lib/cairodriver/write_xid.c
Log:
Add alpha channel to Pixmaps
Add g.cairocomp


Modified: grass/trunk/general/Makefile
===================================================================
--- grass/trunk/general/Makefile	2008-12-19 13:49:51 UTC (rev 34932)
+++ grass/trunk/general/Makefile	2008-12-19 16:51:39 UTC (rev 34933)
@@ -3,6 +3,7 @@
 
 SUBDIRS = \
 	g.access \
+	g.cairocomp \
 	g.copy \
 	g.dirseps \
 	g.filename \


Property changes on: grass/trunk/general/g.cairocomp
___________________________________________________________________
Name: svn:ignore
   + *OBJ*


Added: grass/trunk/general/g.cairocomp/Makefile
===================================================================
--- grass/trunk/general/g.cairocomp/Makefile	                        (rev 0)
+++ grass/trunk/general/g.cairocomp/Makefile	2008-12-19 16:51:39 UTC (rev 34933)
@@ -0,0 +1,15 @@
+
+MODULE_TOPDIR = ../..
+
+PGM = g.cairocomp
+EXTRA_INC = $(CAIROINC)
+LIBES = $(GISLIB) $(CAIROLIB)
+DEPENDENCIES= $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+ifneq ($(USE_CAIRO),)
+ifneq ($(USE_X11),)
+default: cmd
+endif
+endif

Added: grass/trunk/general/g.cairocomp/g.cairocomp.html
===================================================================
--- grass/trunk/general/g.cairocomp/g.cairocomp.html	                        (rev 0)
+++ grass/trunk/general/g.cairocomp/g.cairocomp.html	2008-12-19 16:51:39 UTC (rev 34933)
@@ -0,0 +1,9 @@
+<H2>DESCRIPTION</H2>
+
+g.cairocomp is similar to g.pnmcomp, except that it works with X
+Pixmaps instead of PNM files.
+
+<H2>AUTHOR</H2>
+Glynn Clements
+
+<p><i>Last changed: $Date: 2008-08-15 07:16:42 +0100 (Fri, 15 Aug 2008) $</i>

Added: grass/trunk/general/g.cairocomp/main.c
===================================================================
--- grass/trunk/general/g.cairocomp/main.c	                        (rev 0)
+++ grass/trunk/general/g.cairocomp/main.c	2008-12-19 16:51:39 UTC (rev 34933)
@@ -0,0 +1,281 @@
+/*
+ * MODULE:       g.cairocomp
+ * AUTHOR(S):    Glynn Clements
+ * PURPOSE:      g.cairocomp isn't meant for end users. It's an internal tool for use by
+ *               a wx GUI.
+ *               g.cairocomp composites a series of X pixmaps.
+ * COPYRIGHT:    (C) 2008 by Glynn Clements and the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <cairo.h>
+#include <cairo-xlib.h>
+#include <cairo-xlib-xrender.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+static int width, height;
+static XID output;
+static XID visid;
+static Display *dpy;
+static cairo_surface_t *surface;
+static cairo_t *cairo;
+static Screen *screen;
+static XRenderPictFormat *format;
+static int depth;
+
+static XID read_xid(const char *filename)
+{
+    FILE *fp;
+    char buf[64];
+    long xid;
+
+    fp = fopen(filename, "r");
+    if (!fp)
+	G_fatal_error(_("Unable to open input file <%s>"), filename);
+
+    if (!fgets(buf, sizeof(buf), fp))
+	G_fatal_error(_("Unable to read input file <%s>"), filename);
+
+    if (sscanf(buf, "%li", &xid) != 1)
+	G_fatal_error(_("Unable to parse input file <%s>"), filename);
+
+    fclose(fp);
+
+    return (XID) xid;
+}
+
+static void write_xid(const char *filename, XID xid)
+{
+    FILE *fp;
+    char buf[64];
+
+    fp = fopen(filename, "w");
+    if (!fp)
+	G_fatal_error(_("Unable to open output file <%s>"), filename);
+
+    sprintf(buf, "0x%08lx\n", (unsigned long) xid);
+
+    if (fputs(buf, fp) < 0)
+	G_fatal_error(_("Unable to write output file <%s>"), filename);
+
+    fclose(fp);
+}
+
+static void init_xlib(const char *scr)
+{
+    XVisualInfo templ;
+    XVisualInfo *vinfo;
+    int count;
+    Visual *visual;
+    Pixmap pix;
+    int scrn;
+    cairo_surface_t *s1, *s2;
+
+    dpy = XOpenDisplay(NULL);
+    if (!dpy)
+	G_fatal_error(_("Unable to open display"));
+
+    scrn = scr
+	? atoi(scr)
+	: DefaultScreen(dpy);
+    screen = ScreenOfDisplay(dpy, scrn);
+
+    templ.visualid = visid;
+    templ.screen = scrn;
+    vinfo = XGetVisualInfo(dpy, VisualIDMask|VisualScreenMask, &templ, &count);
+    if (!vinfo || !count)
+	G_fatal_error(_("Unable to obtain visual"));
+    visual = vinfo[0].visual;
+
+    pix = XCreatePixmap(dpy, RootWindow(dpy, scrn), 1, 1, vinfo[0].depth);
+    s1 = cairo_xlib_surface_create(dpy, pix, visual, 1, 1);
+    s2 = cairo_surface_create_similar(s1, CAIRO_CONTENT_COLOR_ALPHA, 1, 1);
+    format = cairo_xlib_surface_get_xrender_format(s2);
+    depth = cairo_xlib_surface_get_depth(s2);
+    cairo_surface_destroy(s2);
+    cairo_surface_destroy(s1);
+    XFreePixmap(dpy, pix);
+
+    output = XCreatePixmap(dpy, RootWindow(dpy, scrn), width, height, depth);
+
+    surface = cairo_xlib_surface_create_with_xrender_format(dpy, output, screen, format, width, height);
+    if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
+	G_fatal_error(_("Failed to initialize output surface"));
+
+    cairo = cairo_create(surface);
+}
+
+static void fini_xlib(void)
+{
+    cairo_surface_destroy(surface);
+    XFlush(dpy);
+    XSetCloseDownMode(dpy, RetainPermanent);
+    XCloseDisplay(dpy);
+}
+
+static void erase(const char *color)
+{
+    int r, g, b, a;
+    double fr, fg, fb, fa;
+
+    if (sscanf(color, "%d:%d:%d:%d", &r, &g, &b, &a) != 4)
+	G_fatal_error(_("Invalid color: %s"), color);
+
+    fr = r / 255.0;
+    fg = g / 255.0;
+    fb = b / 255.0;
+    fa = a / 255.0;
+
+    cairo_save(cairo);
+    cairo_set_source_rgba(cairo, fr, fg, fb, fa);
+    cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
+    cairo_paint(cairo);
+    cairo_restore(cairo);
+}
+
+static void overlay(XID src, float alpha)
+{
+    cairo_surface_t *src_surf;
+
+    src_surf = cairo_xlib_surface_create_with_xrender_format(
+	dpy, src, screen, format, width, height);
+    if (cairo_surface_status(src_surf) != CAIRO_STATUS_SUCCESS)
+	G_fatal_error(_("Failed to initialize input surface"));
+
+    cairo_save(cairo);
+    cairo_set_operator(cairo, CAIRO_OPERATOR_OVER);
+    cairo_set_source_surface(cairo, src_surf, 0, 0);
+    cairo_pattern_set_filter(cairo_get_source(cairo), CAIRO_FILTER_NEAREST);
+    cairo_paint_with_alpha(cairo, alpha);
+    cairo_restore(cairo);
+
+    cairo_surface_destroy(src_surf);
+}
+
+int main(int argc, char *argv[])
+{
+    struct GModule *module;
+    struct
+    {
+	struct Option *in, *out, *visual, *screen, *alpha, *width, *height, *bg;
+    } opt;
+    struct Flag *flag_d;
+    int i;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->keywords = _("general");
+    module->description = _("Overlays multiple X Pixmaps");
+
+    opt.in = G_define_option();
+    opt.in->key = "input";
+    opt.in->type = TYPE_STRING;
+    opt.in->required = YES;
+    opt.in->multiple = YES;
+    opt.in->description = _("Names of input files");
+    opt.in->gisprompt = "old_file,file,input";
+
+    opt.out = G_define_option();
+    opt.out->key = "output";
+    opt.out->type = TYPE_STRING;
+    opt.out->required = YES;
+    opt.out->description = _("Name of output file");
+    opt.out->gisprompt = "new_file,file,output";
+
+    opt.visual = G_define_option();
+    opt.visual->key = "visual";
+    opt.visual->type = TYPE_INTEGER;
+    opt.visual->required = YES;
+    opt.visual->description = _("Output Visual XID");
+
+    opt.screen = G_define_option();
+    opt.screen->key = "screen";
+    opt.screen->type = TYPE_INTEGER;
+    opt.screen->required = NO;
+    opt.screen->description = _("Output screen");
+
+    opt.alpha = G_define_option();
+    opt.alpha->key = "opacity";
+    opt.alpha->type = TYPE_DOUBLE;
+    opt.alpha->multiple = YES;
+    opt.alpha->description = _("Layer opacities");
+
+    opt.width = G_define_option();
+    opt.width->key = "width";
+    opt.width->type = TYPE_INTEGER;
+    opt.width->required = YES;
+    opt.width->description = _("Image width");
+
+    opt.height = G_define_option();
+    opt.height->key = "height";
+    opt.height->type = TYPE_INTEGER;
+    opt.height->required = YES;
+    opt.height->description = _("Image height");
+
+    opt.bg = G_define_option();
+    opt.bg->key = "background";
+    opt.bg->type = TYPE_STRING;
+    opt.bg->description = _("Background color");
+
+    flag_d = G_define_flag();
+    flag_d->key = 'd';
+    flag_d->description = _("Don't composite; just delete input Pixmaps");
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    visid = strtoul(opt.visual->answer, NULL, 0);
+    width = atoi(opt.width->answer);
+    height = atoi(opt.height->answer);
+
+    if (flag_d->answer) {
+	dpy = XOpenDisplay(NULL);
+	if (!dpy)
+	    G_fatal_error(_("Unable to open display"));
+	for (i = 0; opt.in->answers[i]; i++) {
+	    unsigned long xid = read_xid(opt.in->answers[i]);
+	    XKillClient(dpy, xid);
+	}
+	XFlush(dpy);
+	XCloseDisplay(dpy);
+	return 0;
+    }
+
+    init_xlib(opt.screen->answer);
+
+    if (opt.bg->answer)
+	erase(opt.bg->answer);
+
+    for (i = 0; opt.in->answers[i]; i++) {
+	XID input = read_xid(opt.in->answers[i]);
+	double alpha;
+
+	if (opt.alpha->answer && !opt.alpha->answers[i])
+	    G_fatal_error(
+		_("input= and opacity= must have the same number of values"));
+
+	alpha = opt.alpha->answer ? atof(opt.alpha->answers[i]) : 1.0;
+
+	overlay(input, alpha);
+    }
+
+    write_xid(opt.out->answer, output);
+
+    fini_xlib();
+
+    return 0;
+}
+

Modified: grass/trunk/lib/cairodriver/Graph.c
===================================================================
--- grass/trunk/lib/cairodriver/Graph.c	2008-12-19 13:49:51 UTC (rev 34932)
+++ grass/trunk/lib/cairodriver/Graph.c	2008-12-19 16:51:39 UTC (rev 34933)
@@ -13,11 +13,13 @@
 */
 
 #include "cairodriver.h"
+
 #include <cairo-ps.h>
 #include <cairo-pdf.h>
 #include <cairo-svg.h>
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
 #include <cairo-xlib.h>
+#include <cairo-xlib-xrender.h>
 #endif
 
 #include <unistd.h>
@@ -28,12 +30,6 @@
 #include <sys/mman.h>
 #endif
 
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#endif
-
 #include <grass/glocale.h>
 
 struct cairo_state ca;
@@ -48,13 +44,16 @@
 
 static void init_xlib(void)
 {
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+    char *p;
     unsigned long xid;
     XVisualInfo templ;
     XVisualInfo *vinfo;
+    int count;
+    Visual *visual;
     int scrn;
-    int count;
-    char *p;
+    Pixmap pix;
+    cairo_surface_t *s1, *s2;
 
     ca.dpy = XOpenDisplay(NULL);
     if (!ca.dpy)
@@ -71,22 +70,32 @@
     templ.visualid = xid;
     templ.screen = scrn;
 
-    vinfo = XGetVisualInfo(ca.dpy, VisualIDMask, &templ, &count);
+    vinfo = XGetVisualInfo(ca.dpy, VisualIDMask|VisualScreenMask, &templ, &count);
     if (!vinfo || !count)
 	G_fatal_error(_("Unable to obtain visual"));
-    ca.visual = vinfo[0].visual;
+    visual = vinfo[0].visual;
 
+    ca.screen = ScreenOfDisplay(ca.dpy, scrn);
+    pix = XCreatePixmap(ca.dpy, RootWindow(ca.dpy, scrn), 1, 1, vinfo[0].depth);
+    s1 = cairo_xlib_surface_create(ca.dpy, pix, visual, 1, 1);
+    s2 = cairo_surface_create_similar(s1, CAIRO_CONTENT_COLOR_ALPHA, 1, 1);
+    ca.format = cairo_xlib_surface_get_xrender_format(s2);
+    ca.depth = cairo_xlib_surface_get_depth(s2);
+    cairo_surface_destroy(s2);
+    cairo_surface_destroy(s1);
+    XFreePixmap(ca.dpy, pix);
+
     if (!ca.win)
 	ca.win = XCreatePixmap(
 	    ca.dpy, RootWindow(ca.dpy, scrn),
-	    ca.width, ca.height, vinfo[0].depth);
+	    ca.width, ca.height, ca.depth);
 #endif
 }
 
 static void fini_xlib(void)
 {
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
-    XSetCloseDownMode(ca.dpy, RetainPermanent);
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+    XSetCloseDownMode(ca.dpy, RetainTemporary);
     XCloseDisplay(ca.dpy);
 #endif
 }
@@ -132,7 +141,7 @@
     else if (ends_with(ca.file_name, ".svg"))
 	ca.file_type = FTYPE_SVG;
 #endif
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     else if (ends_with(ca.file_name, ".xid"))
 	ca.file_type = FTYPE_X11;
 #endif
@@ -265,7 +274,7 @@
 {
     G_debug(1, "Cairo_Graph_close");
 
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     if (ca.file_type == FTYPE_X11) {
 	XFlush(cairo_xlib_surface_get_display(surface));
 	ca.mapped = 0;
@@ -283,7 +292,7 @@
 	surface = NULL;
     }
 
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     if (ca.file_type == FTYPE_X11)
 	fini_xlib();
 #endif
@@ -323,11 +332,11 @@
 		ca.file_name, (double) ca.width, (double) ca.height);
 	break;
 #endif
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     case FTYPE_X11:
 	surface =
-	    (cairo_surface_t *) cairo_xlib_surface_create(
-		ca.dpy, ca.win, ca.visual, ca.width, ca.height);
+	    (cairo_surface_t *) cairo_xlib_surface_create_with_xrender_format(
+		ca.dpy, ca.win, ca.screen, ca.format, ca.width, ca.height);
 	break;
 #endif
     default:

Modified: grass/trunk/lib/cairodriver/cairodriver.h
===================================================================
--- grass/trunk/lib/cairodriver/cairodriver.h	2008-12-19 13:49:51 UTC (rev 34932)
+++ grass/trunk/lib/cairodriver/cairodriver.h	2008-12-19 16:51:39 UTC (rev 34933)
@@ -15,20 +15,25 @@
 #ifndef __CAIRODRIVER_H__
 #define __CAIRODRIVER_H__
 
+#include <grass/config.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <cairo.h>
 
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if !defined(USE_X11) || !CAIRO_HAS_XLIB_SURFACE
+#define CAIRO_HAS_XLIB_XRENDER_SURFACE 0
+#endif
+
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
 #include <X11/X.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#include <cairo-xlib.h>
+#include <X11/extensions/Xrender.h>
 #endif
 
-#include <grass/config.h>
 #include <grass/gis.h>
 
 #include "driver.h"
@@ -63,10 +68,12 @@
     double bgcolor_r, bgcolor_g, bgcolor_b, bgcolor_a;
     int modified;
     int mapped;
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     Display *dpy;
     Drawable win;
-    Visual *visual;
+    Screen *screen;
+    XRenderPictFormat *format;
+    int depth;
 #endif
 };
 

Modified: grass/trunk/lib/cairodriver/read.c
===================================================================
--- grass/trunk/lib/cairodriver/read.c	2008-12-19 13:49:51 UTC (rev 34932)
+++ grass/trunk/lib/cairodriver/read.c	2008-12-19 16:51:39 UTC (rev 34933)
@@ -47,8 +47,8 @@
 	cairo_surface_destroy(img_surf);
     }
 #endif
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
-    if (ca.file_type == FTYPE_X11) {
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
+    else if (ca.file_type == FTYPE_X11) {
 	G_debug(1, "Reading XID from %s", ca.file_name);
 	cairo_read_xid();
     }

Modified: grass/trunk/lib/cairodriver/read_xid.c
===================================================================
--- grass/trunk/lib/cairodriver/read_xid.c	2008-12-19 13:49:51 UTC (rev 34932)
+++ grass/trunk/lib/cairodriver/read_xid.c	2008-12-19 16:51:39 UTC (rev 34933)
@@ -4,7 +4,7 @@
 
 void cairo_read_xid(void)
 {
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     FILE *fp;
     char buf[64];
     unsigned long xid;

Modified: grass/trunk/lib/cairodriver/write.c
===================================================================
--- grass/trunk/lib/cairodriver/write.c	2008-12-19 13:49:51 UTC (rev 34932)
+++ grass/trunk/lib/cairodriver/write.c	2008-12-19 16:51:39 UTC (rev 34933)
@@ -14,11 +14,6 @@
 
 #include "cairodriver.h"
 
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
-#include <X11/Xlib.h>
-#include <cairo-xlib.h>
-#endif
-
 void cairo_write_image(void)
 {
     G_debug(1, "write_image");
@@ -46,7 +41,7 @@
 	cairo_surface_write_to_png(surface, ca.file_name);
     }
 #endif
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     else if (ca.file_type == FTYPE_X11) {
 	G_debug(1, "Writing XID to %s", ca.file_name);
 	cairo_write_xid();

Modified: grass/trunk/lib/cairodriver/write_xid.c
===================================================================
--- grass/trunk/lib/cairodriver/write_xid.c	2008-12-19 13:49:51 UTC (rev 34932)
+++ grass/trunk/lib/cairodriver/write_xid.c	2008-12-19 16:51:39 UTC (rev 34933)
@@ -5,7 +5,7 @@
 
 void cairo_write_xid(void)
 {
-#if defined(USE_X11) && CAIRO_HAS_XLIB_SURFACE
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
     FILE *fp;
     char buf[64];
 



More information about the grass-commit mailing list