]> granicus.if.org Git - graphviz/commitdiff
add support for loading gif images into cairo-based renderers (e.g. -Tpng, -Tgif)
authorellson <devnull@localhost>
Thu, 10 Sep 2009 23:18:32 +0000 (23:18 +0000)
committerellson <devnull@localhost>
Thu, 10 Sep 2009 23:18:32 +0000 (23:18 +0000)
plugin/gd/Makefile.am
plugin/gd/gvloadimage_gd.c

index 971976f8e491a65434221ab3e28958d6c7a3eb60..dc8dc11de7c0bb1628d958d39627e2be7ab86a17 100644 (file)
@@ -14,7 +14,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/lib/gvc \
        -I$(top_srcdir)/lib/$(GRAPH) \
        -I$(top_srcdir)/lib/cdt \
-       $(GD_INCLUDES) $(LIBGVC_CFLAGS)
+       $(PANGOCAIRO_CFLAGS) $(GD_INCLUDES) $(LIBGVC_CFLAGS)
 
 noinst_LTLIBRARIES = libgvplugin_gd_C.la
 
@@ -40,13 +40,13 @@ libgvplugin_gd_la_LIBADD = \
        $(top_builddir)/lib/gvc/libgvc.la \
        $(top_builddir)/lib/$(GRAPH)/lib$(GRAPH).la \
        $(top_builddir)/lib/cdt/libcdt.la \
-       @ICONV_LIBS@ @FONTCONFIG_LIBS@ @FREETYPE2_LIBS@ @JPEG_LIBS@ @PNG_LIBS@ @EXPAT_LIBS@ @Z_LIBS@ @MATH_LIBS@
+       @PANGOCAIRO_LIBS@ @ICONV_LIBS@ @FONTCONFIG_LIBS@ @FREETYPE2_LIBS@ @JPEG_LIBS@ @PNG_LIBS@ @EXPAT_LIBS@ @Z_LIBS@ @MATH_LIBS@
 AM_CPPFLAGS += -DNONDLL
 else
 libgvplugin_gd_la_LIBADD = \
        $(top_builddir)/lib/gvc/libgvc.la \
        $(top_builddir)/lib/$(GRAPH)/lib$(GRAPH).la \
-       $(top_builddir)/lib/cdt/libcdt.la @GD_LIBS@ @MATH_LIBS@
+       $(top_builddir)/lib/cdt/libcdt.la @PANGOCAIRO_LIBS@ @GD_LIBS@ @MATH_LIBS@
 endif
 libgvplugin_gd_la_DEPENDENCIES =  $(top_builddir)/lib/gvc/libgvc.la
 
index 702562fef9b91bfaf40f2e41546abcff4a7e5f31..caab0afbea7f67a84bd97f4d87e29cdf79001d0e 100644 (file)
 #include <stddef.h>
 #include <string.h>
 
+#ifdef HAVE_PANGOCAIRO
+#include <cairo.h>
+#endif
+
 #include "gvplugin_loadimage.h"
 #include "gvio.h"
 
@@ -31,6 +35,7 @@
 typedef enum {
     FORMAT_PNG_GD, FORMAT_GIF_GD, FORMAT_JPG_GD, FORMAT_GD_GD, FORMAT_GD2_GD, FORMAT_XPM_GD, FORMAT_WBMP_GD, FORMAT_XBM_GD,
     FORMAT_PNG_PS, FORMAT_GIF_PS, FORMAT_JPG_PS, FORMAT_GD_PS, FORMAT_GD2_PS, FORMAT_XPM_PS, FORMAT_WBMP_PS, FORMAT_XBM_PS,
+    FORMAT_PNG_CAIRO, FORMAT_GIF_CAIRO, FORMAT_JPG_CAIRO, FORMAT_GD_CAIRO, FORMAT_GD2_CAIRO, FORMAT_XPM_CAIRO, FORMAT_WBMP_CAIRO, FORMAT_XBM_CAIRO,
 } format_type;
 
 
@@ -102,26 +107,84 @@ static gdImagePtr gd_loadimage(GVJ_t * job, usershape_t *us)
     return (gdImagePtr)(us->data);
 }
 
+static gdImagePtr gd_rotateimage(gdImagePtr im, int rotation)
+{
+    gdImagePtr im2 = gdImageCreate(im->sy, im->sx);
+
+    gdImageCopyRotated(im2, im, im2->sx / 2., im2->sy / 2.,
+                0, 0, im->sx, im->sy, rotation);
+    gdImageDestroy(im);
+    return im2;
+}
+       
 static void gd_loadimage_gd(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
 {
-    gdImagePtr im3, im2 = NULL, im = (gdImagePtr) job->context;
+    gdImagePtr im2, im = (gdImagePtr) job->context;
 
     if ((im2 = gd_loadimage(job, us))) {
-        if (job->rotation) {
-            im3 = gdImageCreate(im2->sy, im2->sx); /* scratch image for rotation */
-            gdImageCopyRotated(im3, im2, im3->sx / 2., im3->sy / 2.,
-                0, 0, im2->sx, im2->sy, job->rotation);
-            gdImageCopyResized(im, im3, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
-                ROUND(b.UR.y - b.LL.y), ROUND(b.UR.x - b.LL.x), im3->sx, im3->sy);
-            gdImageDestroy(im3);
-        }
-        else {
-            gdImageCopyResized(im, im2, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
+        if (job->rotation)
+           im2 = gd_rotateimage(im2, job->rotation);
+        gdImageCopyResized(im, im2, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
                 ROUND(b.UR.x - b.LL.x), ROUND(b.UR.y - b.LL.y), im2->sx, im2->sy);
-        }
     }
 }
 
+#ifdef HAVE_PANGOCAIRO
+static void gd_loadimage_cairo(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
+{
+    cairo_t *cr = (cairo_t *) job->context; /* target context */
+    unsigned int x, y, stride, width, height, px;
+    unsigned char *data;
+    cairo_surface_t *surface;    /* source surface */
+    gdImagePtr im;
+
+    if ((im = gd_loadimage(job, us))) {
+       width = im->sx;
+       height = im->sy;
+       stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width);
+       data = malloc (stride * height);
+       surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32,
+                                                       width, height, stride);
+
+       if (im->trueColor) {
+           for (y = 0; y < height; y++) {
+               for (x = 0; x < width; x++) {
+                   px = gdImageTrueColorPixel(im, x, y);
+                   *data++ = gdTrueColorGetBlue(px);
+                   *data++ = gdTrueColorGetGreen(px);
+                   *data++ = gdTrueColorGetRed(px);
+                   *data++ = (0x7F-gdTrueColorGetAlpha(px)) << 1;
+               }
+           }
+       }
+       else {
+           for (y = 0; y < height; y++) {
+               for (x = 0; x < width; x++) {
+                   px = gdImagePalettePixel(im, x, y);
+                   *data++ = im->blue[px];
+                   *data++ = im->green[px];
+                   *data++ = im->red[px];
+                   *data++ = (px==im->transparent)?0x00:0xff;
+               }
+           }
+       }
+
+        cairo_save(cr);
+        cairo_translate(cr,
+                (b.LL.x + (b.UR.x - b.LL.x) * (1. - (job->dpi.x) / 96.) / 2.),
+                (-b.UR.y + (b.UR.y - b.LL.y) * (1. - (job->dpi.y) / 96.) / 2.));
+        cairo_scale(cr,
+                ((b.UR.x - b.LL.x) * (job->dpi.x) / (96. * us->w)),
+                ((b.UR.y - b.LL.y) * (job->dpi.y) / (96. * us->h)));
+        cairo_set_source_surface (cr, surface, 0, 0);
+        cairo_paint (cr);
+        cairo_restore(cr);
+
+       cairo_surface_destroy(surface);
+    }
+}
+#endif
+
 static void gd_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
 {
     gdImagePtr im = NULL;
@@ -192,10 +255,15 @@ static gvloadimage_engine_t engine_ps = {
     gd_loadimage_ps
 };
 
+static gvloadimage_engine_t engine_cairo = {
+    gd_loadimage_cairo
+};
+
 #endif
 
 gvplugin_installed_t gvloadimage_gd_types[] = {
 #ifdef HAVE_LIBGD
+
     {FORMAT_GD_GD, "gd:gd", 1, &engine, NULL},
     {FORMAT_GD2_GD, "gd2:gd", 1, &engine, NULL},
 #ifdef HAVE_GD_GIF
@@ -215,6 +283,7 @@ gvplugin_installed_t gvloadimage_gd_types[] = {
 #ifdef HAVE_GD_XPM
     {FORMAT_XBM_GD, "xbm:gd", 1, &engine, NULL},
 #endif
+
     {FORMAT_GD_PS, "gd:ps", 1, &engine_ps, NULL},
     {FORMAT_GD_PS, "gd:lasi", 1, &engine_ps, NULL},
     {FORMAT_GD2_PS, "gd2:ps", 1, &engine_ps, NULL},
@@ -243,6 +312,29 @@ gvplugin_installed_t gvloadimage_gd_types[] = {
     {FORMAT_XBM_PS, "xbm:ps", 1, &engine_ps, NULL},
     {FORMAT_XBM_PS, "xbm:lasi", 1, &engine_ps, NULL},
 #endif
+
+#ifdef HAVE_PANGOCAIRO
+    {FORMAT_GD_CAIRO, "gd:cairo", 1, &engine_cairo, NULL},
+    {FORMAT_GD2_CAIRO, "gd2:cairo", 1, &engine_cairo, NULL},
+#ifdef HAVE_GD_GIF
+    {FORMAT_GIF_CAIRO, "gif:cairo", 1, &engine_cairo, NULL},
 #endif
+#ifdef HAVE_GD_JPEG
+    {FORMAT_JPG_CAIRO, "jpeg:cairo", 1, &engine_cairo, NULL},
+    {FORMAT_JPG_CAIRO, "jpg:cairo", 1, &engine_cairo, NULL},
+    {FORMAT_JPG_CAIRO, "jpe:cairo", 1, &engine_cairo, NULL},
+#endif
+#ifdef HAVE_GD_PNG
+    {FORMAT_PNG_CAIRO, "png:cairo", -1, &engine_cairo, NULL},
+#endif
+#ifdef HAVE_GD_WBMP
+    {FORMAT_WBMP_CAIRO, "wbmp:cairo", 1, &engine_cairo, NULL},
+#endif
+#ifdef HAVE_GD_XPM
+    {FORMAT_XBM_CAIRO, "xbm:cairo", 1, &engine_cairo, NULL},
+#endif
+#endif /* HAVE_PANGOCAIRO */
+
+#endif /* HAVE_LIBGD */
     {0, NULL, 0, NULL, NULL}
 };