Graphviz  2.29.20120524.0446
plugin/pango/gvloadimage_pango.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017 
00018 #include <stdlib.h>
00019 
00020 #include "gvplugin_loadimage.h"
00021 #include "gvio.h"
00022 
00023 #ifdef HAVE_PANGOCAIRO
00024 #include <cairo.h>
00025 
00026 #ifdef WIN32 //*dependencies
00027     #pragma comment( lib, "gvc.lib" )
00028     #pragma comment( lib, "glib-2.0.lib" )
00029     #pragma comment( lib, "pango-1.0.lib" )
00030     #pragma comment( lib, "pangocairo-1.0.lib" )
00031     #pragma comment( lib, "cairo.lib" )
00032     #pragma comment( lib, "gobject-2.0.lib" )
00033     #pragma comment( lib, "graph.lib" )
00034 #endif
00035 
00036 
00037 
00038 
00039 typedef enum {
00040     FORMAT_PNG_CAIRO, FORMAT_PNG_PS,
00041 } format_type;
00042 
00043 static cairo_status_t
00044 reader (void *closure, unsigned char *data, unsigned int length)
00045 {
00046     if (length == fread(data, 1, length, (FILE *)closure)
00047      || feof((FILE *)closure))
00048         return CAIRO_STATUS_SUCCESS;
00049     return CAIRO_STATUS_READ_ERROR;
00050 }
00051 
00052 static void cairo_freeimage(usershape_t *us)
00053 {
00054     cairo_surface_destroy((cairo_surface_t*)(us->data));
00055 }
00056 
00057 static cairo_surface_t* cairo_loadimage(GVJ_t * job, usershape_t *us)
00058 {
00059     cairo_surface_t *surface = NULL; /* source surface */
00060 
00061     assert(job);
00062     assert(us);
00063     assert(us->name);
00064 
00065     if (us->data) {
00066         if (us->datafree == cairo_freeimage)
00067              surface = (cairo_surface_t*)(us->data); /* use cached data */
00068         else {
00069              us->datafree(us);        /* free incompatible cache data */
00070              us->datafree = NULL;
00071              us->data = NULL;
00072         }
00073     }
00074     if (!surface) { /* read file into cache */
00075         if (!gvusershape_file_access(us))
00076             return NULL;
00077         switch (us->type) {
00078 #ifdef CAIRO_HAS_PNG_FUNCTIONS
00079             case FT_PNG:
00080                 surface = cairo_image_surface_create_from_png_stream(reader, us->f);
00081                 cairo_surface_reference(surface);
00082                 break;
00083 #endif
00084             default:
00085                 surface = NULL;
00086         }
00087         if (surface) {
00088             us->data = (void*)surface;
00089             us->datafree = cairo_freeimage;
00090         }
00091         gvusershape_file_release(us);
00092     }
00093     return surface;
00094 }
00095 
00096 static void pango_loadimage_cairo(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
00097 {
00098     cairo_t *cr = (cairo_t *) job->context; /* target context */
00099     cairo_surface_t *surface;    /* source surface */
00100 
00101     surface = cairo_loadimage(job, us);
00102     if (surface) {
00103         cairo_save(cr);
00104         cairo_translate(cr,
00105                 (b.LL.x + (b.UR.x - b.LL.x) * (1. - (job->dpi.x) / 96.) / 2.),
00106                 (-b.UR.y + (b.UR.y - b.LL.y) * (1. - (job->dpi.y) / 96.) / 2.));
00107         cairo_scale(cr,
00108                 ((b.UR.x - b.LL.x) * (job->dpi.x) / (96. * us->w)),
00109                 ((b.UR.y - b.LL.y) * (job->dpi.y) / (96. * us->h)));
00110         cairo_set_source_surface (cr, surface, 0, 0);
00111         cairo_paint (cr);
00112         cairo_restore(cr);
00113     }
00114 }
00115 
00116 static void pango_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
00117 {
00118     cairo_surface_t *surface;   /* source surface */
00119     cairo_format_t format;
00120     int X, Y, x, y, stride;
00121     unsigned char *data, *ix, alpha, red, green, blue;
00122 
00123     surface = cairo_loadimage(job, us);
00124     if (surface) {
00125         format = cairo_image_surface_get_format(surface);
00126         if ((format != CAIRO_FORMAT_ARGB32) && (format != CAIRO_FORMAT_RGB24))
00127             return;
00128 
00129         X = cairo_image_surface_get_width(surface);
00130         Y = cairo_image_surface_get_height(surface);
00131         stride = cairo_image_surface_get_stride(surface);
00132         data = cairo_image_surface_get_data(surface);
00133 
00134         gvputs(job, "save\n");
00135 
00136         /* define image data as string array (one per raster line) */
00137         /* see parallel code in gd_loadimage_ps().  FIXME: refactor... */
00138         gvputs(job, "/myctr 0 def\n");
00139         gvputs(job, "/myarray [\n");
00140         for (y = 0; y < Y; y++) {
00141             gvputs(job, "<");
00142             ix = data + y * stride;
00143             for (x = 0; x < X; x++) {
00144                 /* FIXME - this code may have endian problems */
00145                 blue = *ix++;
00146                 green = *ix++;
00147                 red = *ix++;
00148                 alpha = *ix++;
00149                 if (alpha < 0x7f)
00150                     gvputs(job, "ffffff");
00151                 else
00152                     gvprintf(job, "%02x%02x%02x", red, green, blue);
00153             }
00154             gvputs(job, ">\n");
00155         }
00156         gvputs(job, "] def\n");
00157         gvputs(job,"/myproc { myarray myctr get /myctr myctr 1 add def } def\n");
00158 
00159         /* this sets the position of the image */
00160         gvprintf(job, "%g %g translate\n",
00161                 (b.LL.x + (b.UR.x - b.LL.x) * (1. - (job->dpi.x) / 96.) / 2.),
00162                 (b.LL.y + (b.UR.y - b.LL.y) * (1. - (job->dpi.y) / 96.) / 2.));
00163 
00164         /* this sets the rendered size to fit the box */
00165         gvprintf(job,"%g %g scale\n",
00166                 ((b.UR.x - b.LL.x) * 72. / 96.),
00167                 ((b.UR.y - b.LL.y) * 72. / 96.));
00168 
00169         /* xsize ysize bits-per-sample [matrix] */
00170         gvprintf(job, "%d %d 8 [%d 0 0 %d 0 %d]\n", X, Y, X, -Y, Y);
00171 
00172         gvputs(job, "{myproc} false 3 colorimage\n");
00173 
00174         gvputs(job, "restore\n");
00175     }
00176 }
00177 
00178 static gvloadimage_engine_t engine_cairo = {
00179     pango_loadimage_cairo
00180 };
00181 
00182 static gvloadimage_engine_t engine_ps = {
00183     pango_loadimage_ps
00184 };
00185 #endif
00186 
00187 gvplugin_installed_t gvloadimage_pango_types[] = {
00188 #ifdef HAVE_PANGOCAIRO
00189     {FORMAT_PNG_CAIRO, "png:cairo", 1, &engine_cairo, NULL},
00190     {FORMAT_PNG_PS, "png:lasi", 2, &engine_ps, NULL},
00191     {FORMAT_PNG_PS, "png:ps", 2, &engine_ps, NULL},
00192 #endif
00193     {0, NULL, 0, NULL, NULL}
00194 };