From d24b16f917ca749e9ffebbec8eca0ee791e1b67a Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Thu, 20 Dec 2007 10:12:52 +0000 Subject: [PATCH] Add ps specials support in dvi backend when libspectre is present. Fixes 2007-12-20 Carlos Garcia Campos * 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 | 14 ++++++ backend/dvi/Makefile.am | 3 +- backend/dvi/cairo-device.c | 78 ++++++++++++++++++++++++++++++++++ backend/dvi/mdvi-lib/common.h | 2 + backend/dvi/mdvi-lib/mdvi.h | 5 +++ backend/dvi/mdvi-lib/sp-epsf.c | 71 +++++++++++++++++++++++++++---- backend/dvi/mdvi-lib/util.c | 54 +++++++++++++++++++++++ 7 files changed, 217 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6fe31d2c..c4a3cceb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2007-12-20 Carlos Garcia Campos + + * 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 * configure.ac: diff --git a/backend/dvi/Makefile.am b/backend/dvi/Makefile.am index be90e26f..10325e06 100644 --- a/backend/dvi/Makefile.am +++ b/backend/dvi/Makefile.am @@ -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 diff --git a/backend/dvi/cairo-device.c b/backend/dvi/cairo-device.c index 19006d2e..95f3e63a 100644 --- a/backend/dvi/cairo-device.c +++ b/backend/dvi/cairo-device.c @@ -16,7 +16,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include + #include +#ifdef HAVE_SPECTRE +#include +#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; } diff --git a/backend/dvi/mdvi-lib/common.h b/backend/dvi/mdvi-lib/common.h index fe4d6f70..2da61c81 100644 --- a/backend/dvi/mdvi-lib/common.h +++ b/backend/dvi/mdvi-lib/common.h @@ -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)) diff --git a/backend/dvi/mdvi-lib/mdvi.h b/backend/dvi/mdvi-lib/mdvi.h index 961689a0..78244a4c 100644 --- a/backend/dvi/mdvi-lib/mdvi.h +++ b/backend/dvi/mdvi-lib/mdvi.h @@ -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; }; diff --git a/backend/dvi/mdvi-lib/sp-epsf.c b/backend/dvi/mdvi-lib/sp-epsf.c index ca13c864..b266d671 100644 --- a/backend/dvi/mdvi-lib/sp-epsf.c +++ b/backend/dvi/mdvi-lib/sp-epsf.c @@ -20,6 +20,8 @@ #include #include +#include +#include #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); } diff --git a/backend/dvi/mdvi-lib/util.c b/backend/dvi/mdvi-lib/util.c index c1cc649e..788b7744 100644 --- a/backend/dvi/mdvi-lib/util.c +++ b/backend/dvi/mdvi-lib/util.c @@ -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; -- 2.43.5