+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:
-I$(top_srcdir) \
-I$(top_srcdir)/libdocument \
-I$(srcdir)/mdvi-lib \
- $(LIB_CFLAGS)
+ $(LIB_CFLAGS) \
+ $(SPECTRE_CFLAGS)
noinst_LTLIBRARIES = libgtkdvi.la
* 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 {
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,
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;
}
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))
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;
DviDevDestroy dev_destroy;
DviRefresh refresh;
DviSetColor set_color;
+ DviPSDraw draw_ps;
void * device_data;
};
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include "mdvi.h"
#include "private.h"
{
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);
}
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;