[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