]> www.fi.muni.cz Git - evince.git/commitdiff
Add ps specials support in dvi backend when libspectre is present. Fixes
authorCarlos Garcia Campos <carlosgc@gnome.org>
Thu, 20 Dec 2007 10:12:52 +0000 (10:12 +0000)
committerCarlos Garcia Campos <carlosgc@src.gnome.org>
Thu, 20 Dec 2007 10:12:52 +0000 (10:12 +0000)
2007-12-20  Carlos Garcia Campos  <carlosgc@gnome.org>
* backend/dvi/Makefile.am:
* backend/dvi/cairo-device.c: (dvi_cairo_draw_ps),
(mdvi_cairo_device_init):
* backend/dvi/mdvi-lib/common.h:
* backend/dvi/mdvi-lib/mdvi.h:
* backend/dvi/mdvi-lib/sp-epsf.c: (epsf_special):
* backend/dvi/mdvi-lib/util.c: (mdvi_strrstr),
(mdvi_build_path_from_cwd):
Add ps specials support in dvi backend when libspectre is
present. Fixes bug #386005.

svn path=/trunk/; revision=2775

ChangeLog
backend/dvi/Makefile.am
backend/dvi/cairo-device.c
backend/dvi/mdvi-lib/common.h
backend/dvi/mdvi-lib/mdvi.h
backend/dvi/mdvi-lib/sp-epsf.c
backend/dvi/mdvi-lib/util.c

index 6fe31d2cdcd1b75509921993c68968c4fe2b3dfd..c4a3ccebd3603ab927c239d82205bd595aeede65 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-12-20  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+       * backend/dvi/Makefile.am:
+       * backend/dvi/cairo-device.c: (dvi_cairo_draw_ps),
+       (mdvi_cairo_device_init):
+       * backend/dvi/mdvi-lib/common.h:
+       * backend/dvi/mdvi-lib/mdvi.h:
+       * backend/dvi/mdvi-lib/sp-epsf.c: (epsf_special):
+       * backend/dvi/mdvi-lib/util.c: (mdvi_strrstr),
+       (mdvi_build_path_from_cwd):
+
+       Add ps specials support in dvi backend when libspectre is
+       present. Fixes bug #386005.
+       
 2007-12-20  Carlos Garcia Campos  <carlosgc@gnome.org>
 
        * configure.ac:
index be90e26fde257bd434e33d7c2f4d39777ce7bad8..10325e069a653e5770c5ea51d63a37cb6799d54c 100644 (file)
@@ -4,7 +4,8 @@ INCLUDES = \
        -I$(top_srcdir)                                 \
        -I$(top_srcdir)/libdocument                     \
        -I$(srcdir)/mdvi-lib                            \
-       $(LIB_CFLAGS)
+       $(LIB_CFLAGS)                                   \
+       $(SPECTRE_CFLAGS)
 
 noinst_LTLIBRARIES = libgtkdvi.la
     
index 19006d2e36818660d412fecd657d2218ce6d3532..95f3e63ae8abaa55cbb4fa3bb34166fd02e51614 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <config.h>
+
 #include <gdk/gdkcolor.h>
+#ifdef HAVE_SPECTRE
+#include <libspectre/spectre.h>
+#endif
+
 #include "cairo-device.h"
 
 typedef struct {
@@ -116,6 +122,73 @@ dvi_cairo_draw_rule (DviContext *dvi,
        cairo_restore (cairo_device->cr);
 }
 
+#ifdef HAVE_SPECTRE
+static void
+dvi_cairo_draw_ps (DviContext *dvi,
+                  const char *filename,
+                  int         x,
+                  int         y,
+                  Uint        width,
+                  Uint        height)
+{
+       DviCairoDevice       *cairo_device;
+       unsigned char        *data = NULL;
+       int                   row_length;
+       SpectreDocument      *psdoc;
+       SpectrePage          *page;
+       SpectreRenderContext *rc;
+       SpectreStatus         status;
+       cairo_surface_t      *image;
+
+       cairo_device = (DviCairoDevice *) dvi->device.device_data;
+
+       psdoc = spectre_document_new ();
+       spectre_document_load (psdoc, filename);
+       if (spectre_document_status (psdoc)) {
+               spectre_document_free (psdoc);
+               return;
+       }
+       
+       page = spectre_document_get_page (psdoc, 0);
+       if (!page) {
+               spectre_document_free (psdoc);
+               return;
+       }
+
+       rc = spectre_render_context_new ();
+       spectre_render_context_set_page_size (rc, width, height);
+       spectre_page_render (page, rc, &data, &row_length);
+       status = spectre_page_status (page);
+       spectre_render_context_free (rc);
+
+       spectre_page_free (page);
+       spectre_document_free (psdoc);
+
+       if (status) {
+               free (data);
+               return;
+       }
+
+       image = cairo_image_surface_create_for_data ((unsigned char *)data,
+                                                    CAIRO_FORMAT_RGB24,
+                                                    width, height,
+                                                    row_length);
+
+       cairo_save (cairo_device->cr);
+
+       cairo_translate (cairo_device->cr,
+                        x + cairo_device->xmargin,
+                        y + cairo_device->ymargin);
+       cairo_set_source_surface (cairo_device->cr, image, 0, 0); 
+       cairo_paint (cairo_device->cr);
+
+       cairo_restore (cairo_device->cr);
+
+       cairo_surface_destroy (image);
+       free (data);
+}
+#endif /* HAVE_SPECTRE */
+
 static int
 dvi_cairo_alloc_colors (void  *device_data,
                        Ulong *pixels,
@@ -208,6 +281,11 @@ mdvi_cairo_device_init (DviDevice *device)
        device->free_image = dvi_cairo_free_image;
        device->put_pixel = dvi_cairo_put_pixel;
        device->set_color = dvi_cairo_set_color;
+#ifdef HAVE_SPECTRE
+       device->draw_ps = dvi_cairo_draw_ps;
+#else
+       device->draw_ps = NULL;
+#endif
        device->refresh = NULL;
 }
 
index fe4d6f7084f88db0095633d12f9c9afa9cc09efb..2da61c815a98cce194789678d7484829f4b7cebc 100644 (file)
@@ -210,6 +210,8 @@ extern char *mdvi_strncpy __PROTO((char *, const char *, size_t));
 extern char *mdvi_strdup __PROTO((const char *));
 extern char *mdvi_strndup __PROTO((const char *, size_t));
 extern void *mdvi_memdup __PROTO((const void *, size_t));
+extern char *mdvi_build_path_from_cwd __PROTO((const char *));
+extern char *mdvi_strrstr __PROTO((const char *, const char *));
 
 /* macros to make memory allocation nicer */
 #define xalloc(t)      (t *)mdvi_malloc(sizeof(t))
index 961689a05a8405b82c67d98d301c134b63bb6721..78244a4cddf2ab81123ad30c40775bc408803ab5 100644 (file)
@@ -102,6 +102,10 @@ typedef void (*DviPutPixel)        __PROTO((void *image, int x, int y, Ulong color));
 typedef void (*DviDevDestroy)   __PROTO((void *data));
 typedef void (*DviRefresh)      __PROTO((DviContext *dvi, void *device_data));
 typedef void (*DviSetColor)    __PROTO((void *device_data, Ulong, Ulong));
+typedef void (*DviPSDraw)       __PROTO((DviContext *context,
+                                        const char *filename, 
+                                        int x, int y,
+                                        Uint width, Uint height));
 
 struct _DviDevice {
        DviGlyphDraw    draw_glyph;
@@ -113,6 +117,7 @@ struct _DviDevice {
        DviDevDestroy   dev_destroy;
        DviRefresh      refresh;
        DviSetColor     set_color;
+       DviPSDraw       draw_ps;
        void *          device_data;
 };
 
index ca13c8645d80e077f89cd63b42df2d5c68d8bded..b266d671f18eff49c36af2afbc607571a7f48a54 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "mdvi.h"
 #include "private.h"
@@ -235,23 +237,74 @@ void      epsf_special(DviContext *dvi, char *prefix, char *arg)
 {
        char    *file;
        char    *special;
+       char    *psfile;
+       char    *tmp;
        EpsfBox box = {0, 0, 0, 0};
        int     x, y;
        int     w, h;
        double  xf, vf;
+       struct stat buf;
        
        file = parse_epsf_special(&box, &special, prefix, arg);
-       if(file != NULL)
-               mdvi_free(special);
-       /* 
-        * draw the bounding box. Notice that it is in PostScript units,
-        * so we have to convert it into pixels
-        */
+       if (file != NULL)
+               mdvi_free (special);
+
        xf = dvi->params.dpi * dvi->params.mag / (72.0 * dvi->params.hshrink);
        vf = dvi->params.vdpi * dvi->params.mag / (72.0 * dvi->params.vshrink);
-       x = FROUND(box.ox * xf);
-       y = FROUND(box.oy * vf);
        w = FROUND(box.bw * xf);
        h = FROUND(box.bh * vf);
-       dvi->device.draw_rule(dvi, dvi->pos.hh + x, dvi->pos.vv + y - h + 1, w, h, 0);
+       x = FROUND(box.ox * xf) + dvi->pos.hh;
+       y = FROUND(box.oy * vf) + dvi->pos.vv - h + 1;
+
+       if (!file || !dvi->device.draw_ps) {
+               dvi->device.draw_rule (dvi, x, y, w, h, 0);
+               return;
+       }
+
+       if (file[0] == '/') { /* Absolute path */
+               if (stat (file, &buf) == 0)
+                       dvi->device.draw_ps (dvi, file, x, y, w, h);
+               else
+                       dvi->device.draw_rule (dvi, x, y, w, h, 0);
+               return;
+       }
+
+       tmp = mdvi_strrstr (dvi->filename, "/");
+       if (tmp) { /* Document directory */
+               int path_len = strlen (dvi->filename) - strlen (tmp + 1);
+               int file_len = strlen (file);
+               
+               psfile = mdvi_malloc (path_len + file_len + 1);
+               psfile[0] = '\0';
+               strncat (psfile, dvi->filename, path_len);
+               strncat (psfile, file, file_len);
+
+               if (stat (psfile, &buf) == 0) {
+                       dvi->device.draw_ps (dvi, psfile, x, y, w, h);
+                       mdvi_free (psfile);
+
+                       return;
+               }
+
+               mdvi_free (psfile);
+       }
+                       
+       psfile = mdvi_build_path_from_cwd (file);
+       if (stat (psfile, &buf) == 0) { /* Current working dir */
+               dvi->device.draw_ps (dvi, psfile, x, y, w, h);
+               mdvi_free (psfile);
+
+               return;
+       }
+
+       mdvi_free (psfile);
+       
+       psfile = kpse_find_pict (file);
+       if (psfile) { /* kpse */
+               dvi->device.draw_ps (dvi, psfile, x, y, w, h);
+       } else {
+               dvi->device.draw_rule(dvi, x, y, w, h, 0);
+       }
+
+       free (psfile);
 }
index c1cc649e2b427f0421757bf9832df7e160dbf7fc..788b7744cf7d09f4ecfac4e6233cd566ba396b62 100644 (file)
@@ -288,6 +288,60 @@ void       *mdvi_memdup(const void *data, size_t length)
        return ptr;
 }
 
+char   *mdvi_strrstr (const char *haystack, const char *needle)
+{
+       size_t i;
+       size_t needle_len;
+       size_t haystack_len;
+       const char *p;
+
+       needle_len = strlen (needle);
+       haystack_len = strlen (haystack);
+
+       if (needle_len == 0)
+               return NULL;
+
+       if (haystack_len < needle_len)
+               return (char *)haystack;
+
+       p = haystack + haystack_len - needle_len;
+       while (p >= haystack) {
+               for (i = 0; i < needle_len; i++)
+                       if (p[i] != needle[i])
+                               goto next;
+
+               return (char *)p;
+
+       next:
+               p--;
+       }
+
+       return NULL;
+}
+
+char   *mdvi_build_path_from_cwd (const char *path)
+{
+       char  *ptr;
+       char  *buf = NULL;
+       size_t buf_size = 512;
+
+       while (1) {
+               buf = mdvi_realloc (buf, buf_size);
+               if ((ptr = getcwd (buf, buf_size)) == NULL && errno == ERANGE) {
+                       buf_size *= 2;
+               } else {
+                       buf = ptr;
+                       break;
+               }
+       }
+
+       buf = mdvi_realloc (buf, strlen (buf) + strlen (path) + 2);
+       strcat (buf, "/");
+       strncat (buf, path, strlen (path));
+       
+       return buf;
+}
+
 double unit2pix_factor(const char *spec)
 {
        double  val;