X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=backend%2Fdvi%2Fdvi-document.c;h=c8295232a3aaaa5b8481b6d4ba120bce58f2e1d6;hb=f51872613abaaa42c716e2fe6a2e4695c529dc4b;hp=9abdca7105e2240a068be7f964ebb903c037eea5;hpb=b7031c73b6facaa3ab47a1463f88b4c40344e1a3;p=evince.git diff --git a/backend/dvi/dvi-document.c b/backend/dvi/dvi-document.c index 9abdca71..c8295232 100644 --- a/backend/dvi/dvi-document.c +++ b/backend/dvi/dvi-document.c @@ -17,15 +17,18 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "config.h" + +#include #include "dvi-document.h" #include "ev-document-thumbnails.h" #include "ev-document-misc.h" +#include "ev-file-exporter.h" #include "mdvi.h" #include "fonts.h" -#include "pixbuf-device.h" +#include "cairo-device.h" -#include #include GMutex *dvi_context_mutex = NULL; @@ -49,75 +52,81 @@ struct _DviDocument DviParams *params; /* To let document scale we should remember width and height */ - double base_width; double base_height; gchar *uri; + + /* PDF exporter */ + gchar *exporter_filename; + GString *exporter_opts; }; typedef struct _DviDocumentClass DviDocumentClass; -static void dvi_document_do_color_special (DviContext *dvi, const char *prefix, const char *arg); -static void dvi_document_document_iface_init (EvDocumentIface *iface); +static void dvi_document_document_iface_init (EvDocumentIface *iface); static void dvi_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface); -static void dvi_document_get_page_size (EvDocument *document, - int page, - double *width, - double *height); - -G_DEFINE_TYPE_WITH_CODE - (DviDocument, dvi_document, G_TYPE_OBJECT, - { - G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT, dvi_document_document_iface_init); - G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS, dvi_document_document_thumbnails_iface_init) +static void dvi_document_file_exporter_iface_init (EvFileExporterIface *iface); +static void dvi_document_get_page_size (EvDocument *document, + int page, + double *width, + double *height); +static void dvi_document_do_color_special (DviContext *dvi, + const char *prefix, + const char *arg); + +EV_BACKEND_REGISTER_WITH_CODE (DviDocument, dvi_document, + { + G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS, dvi_document_document_thumbnails_iface_init); + G_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER, dvi_document_file_exporter_iface_init); }); static gboolean dvi_document_load (EvDocument *document, - const char *uri, - GError **error) + const char *uri, + GError **error) { - gchar *filename; - DviDocument *dvi_document = DVI_DOCUMENT(document); - - filename = g_filename_from_uri (uri, NULL, error); - - if (!filename) { + gchar *filename; + DviDocument *dvi_document = DVI_DOCUMENT(document); + + filename = g_filename_from_uri (uri, NULL, error); + + if (!filename) { g_set_error (error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_INVALID, _("File not available")); return FALSE; - } + } - g_mutex_lock (dvi_context_mutex); - if (dvi_document->context) - mdvi_destroy_context (dvi_document->context); - - dvi_document->context = mdvi_init_context(dvi_document->params, dvi_document->spec, filename); - g_mutex_unlock (dvi_context_mutex); - - if (!dvi_document->context) { + g_mutex_lock (dvi_context_mutex); + if (dvi_document->context) + mdvi_destroy_context (dvi_document->context); + + dvi_document->context = mdvi_init_context(dvi_document->params, dvi_document->spec, filename); + g_mutex_unlock (dvi_context_mutex); + + if (!dvi_document->context) { g_set_error (error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_INVALID, _("DVI document has incorrect format")); return FALSE; - } - - mdvi_pixbuf_device_init (&dvi_document->context->device); - - dvi_document->base_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv + } + + mdvi_cairo_device_init (&dvi_document->context->device); + + + dvi_document->base_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv + 2 * unit2pix(dvi_document->params->dpi, MDVI_HMARGIN) / dvi_document->params->hshrink; - - dvi_document->base_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv + + dvi_document->base_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv + 2 * unit2pix(dvi_document->params->vdpi, MDVI_VMARGIN) / dvi_document->params->vshrink; - - g_free (dvi_document->uri); - dvi_document->uri = g_strdup (uri); - - return TRUE; + + g_free (dvi_document->uri); + dvi_document->uri = g_strdup (uri); + + return TRUE; } @@ -132,35 +141,32 @@ dvi_document_save (EvDocument *document, } static int -dvi_document_get_n_pages (EvDocument *document) +dvi_document_get_n_pages (EvDocument *document) { - DviDocument *dvi_document = DVI_DOCUMENT (document); - return dvi_document->context->npages; + DviDocument *dvi_document = DVI_DOCUMENT (document); + + return dvi_document->context->npages; } static void -dvi_document_get_page_size (EvDocument *document, - int page, - double *width, - double *height) +dvi_document_get_page_size (EvDocument *document, + int page, + double *width, + double *height) { - DviDocument * dvi_document = DVI_DOCUMENT (document); + DviDocument *dvi_document = DVI_DOCUMENT (document); *width = dvi_document->base_width; *height = dvi_document->base_height;; - - return; } -static GdkPixbuf * -dvi_document_render_pixbuf (EvDocument *document, - EvRenderContext *rc) +static cairo_surface_t * +dvi_document_render (EvDocument *document, + EvRenderContext *rc) { - GdkPixbuf *pixbuf; - GdkPixbuf *rotated_pixbuf; - + cairo_surface_t *surface; + cairo_surface_t *rotated_surface; DviDocument *dvi_document = DVI_DOCUMENT(document); - gint required_width, required_height; gint proposed_width, proposed_height; gint xmargin = 0, ymargin = 0; @@ -171,14 +177,14 @@ dvi_document_render_pixbuf (EvDocument *document, */ g_mutex_lock (dvi_context_mutex); - mdvi_setpage(dvi_document->context, rc->page); + mdvi_setpage (dvi_document->context, rc->page); mdvi_set_shrink (dvi_document->context, (int)((dvi_document->params->hshrink - 1) / rc->scale) + 1, (int)((dvi_document->params->vshrink - 1) / rc->scale) + 1); - required_width = dvi_document->base_width * rc->scale; - required_height = dvi_document->base_height * rc->scale; + required_width = dvi_document->base_width * rc->scale + 0.5; + required_height = dvi_document->base_height * rc->scale + 0.5; proposed_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv; proposed_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv; @@ -187,18 +193,20 @@ dvi_document_render_pixbuf (EvDocument *document, if (required_height >= proposed_height) ymargin = (required_height - proposed_height) / 2; - mdvi_pixbuf_device_set_margins (&dvi_document->context->device, xmargin, ymargin); - - mdvi_pixbuf_device_render (dvi_document->context); - - pixbuf = mdvi_pixbuf_device_get_pixbuf (&dvi_document->context->device); + mdvi_cairo_device_set_margins (&dvi_document->context->device, xmargin, ymargin); + mdvi_cairo_device_set_scale (&dvi_document->context->device, rc->scale); + mdvi_cairo_device_render (dvi_document->context); + surface = mdvi_cairo_device_get_surface (&dvi_document->context->device); g_mutex_unlock (dvi_context_mutex); - rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rc->rotation); - g_object_unref (pixbuf); - - return rotated_pixbuf; + rotated_surface = ev_document_misc_surface_rotate_and_scale (surface, + required_width, + required_height, + rc->rotation); + cairo_surface_destroy (surface); + + return rotated_surface; } static void @@ -208,7 +216,7 @@ dvi_document_finalize (GObject *object) g_mutex_lock (dvi_context_mutex); if (dvi_document->context) { - mdvi_pixbuf_device_free (&dvi_document->context->device); + mdvi_cairo_device_free (&dvi_document->context->device); mdvi_destroy_context (dvi_document->context); } g_mutex_unlock (dvi_context_mutex); @@ -216,6 +224,12 @@ dvi_document_finalize (GObject *object) if (dvi_document->params) g_free (dvi_document->params); + if (dvi_document->exporter_filename) + g_free (dvi_document->exporter_filename); + + if (dvi_document->exporter_opts) + g_string_free (dvi_document->exporter_opts, TRUE); + g_free (dvi_document->uri); G_OBJECT_CLASS (dvi_document_parent_class)->finalize (object); @@ -229,19 +243,13 @@ dvi_document_class_init (DviDocumentClass *klass) gobject_class->finalize = dvi_document_finalize; - mdvi_init_kpathsea("evince", MDVI_MFMODE, MDVI_FALLBACK_FONT, MDVI_DPI); + mdvi_init_kpathsea ("evince", MDVI_MFMODE, MDVI_FALLBACK_FONT, MDVI_DPI); mdvi_register_special ("Color", "color", NULL, dvi_document_do_color_special, 1); mdvi_register_fonts (); dvi_context_mutex = g_mutex_new (); } -static gboolean -dvi_document_can_get_text (EvDocument *document) -{ - return FALSE; -} - static EvDocumentInfo * dvi_document_get_info (EvDocument *document) { @@ -257,10 +265,9 @@ dvi_document_document_iface_init (EvDocumentIface *iface) { iface->load = dvi_document_load; iface->save = dvi_document_save; - iface->can_get_text = dvi_document_can_get_text; iface->get_n_pages = dvi_document_get_n_pages; iface->get_page_size = dvi_document_get_page_size; - iface->render_pixbuf = dvi_document_render_pixbuf; + iface->render = dvi_document_render; iface->get_info = dvi_document_get_info; } @@ -290,16 +297,16 @@ dvi_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document, { DviDocument *dvi_document = DVI_DOCUMENT (document); GdkPixbuf *pixbuf; - GdkPixbuf *border_pixbuf; GdkPixbuf *rotated_pixbuf; + cairo_surface_t *surface; gint thumb_width, thumb_height; gint proposed_width, proposed_height; - + thumb_width = (gint) (dvi_document->base_width * rc->scale); thumb_height = (gint) (dvi_document->base_height * rc->scale); - - g_mutex_lock (dvi_context_mutex); + g_mutex_lock (dvi_context_mutex); + mdvi_setpage (dvi_document->context, rc->page); mdvi_set_shrink (dvi_document->context, @@ -310,29 +317,31 @@ dvi_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document, proposed_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv; if (border) { - mdvi_pixbuf_device_set_margins (&dvi_document->context->device, - MAX (thumb_width - proposed_width, 0) / 2, - MAX (thumb_height - proposed_height, 0) / 2); + mdvi_cairo_device_set_margins (&dvi_document->context->device, + MAX (thumb_width - proposed_width, 0) / 2, + MAX (thumb_height - proposed_height, 0) / 2); } else { - mdvi_pixbuf_device_set_margins (&dvi_document->context->device, - MAX (thumb_width - proposed_width - 2, 0) / 2, - MAX (thumb_height - proposed_height - 2, 0) / 2); + mdvi_cairo_device_set_margins (&dvi_document->context->device, + MAX (thumb_width - proposed_width - 2, 0) / 2, + MAX (thumb_height - proposed_height - 2, 0) / 2); } - - - mdvi_pixbuf_device_render (dvi_document->context); - pixbuf = mdvi_pixbuf_device_get_pixbuf (&dvi_document->context->device); + mdvi_cairo_device_set_scale (&dvi_document->context->device, rc->scale); + mdvi_cairo_device_render (dvi_document->context); + surface = mdvi_cairo_device_get_surface (&dvi_document->context->device); g_mutex_unlock (dvi_context_mutex); - + + pixbuf = ev_document_misc_pixbuf_from_surface (surface); + cairo_surface_destroy (surface); + rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rc->rotation); g_object_unref (pixbuf); - - if (border) { - GdkPixbuf *tmp_pixbuf = rotated_pixbuf; - - rotated_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf); - g_object_unref (tmp_pixbuf); + + if (border) { + GdkPixbuf *tmp_pixbuf = rotated_pixbuf; + + rotated_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf); + g_object_unref (tmp_pixbuf); } return rotated_pixbuf; @@ -345,6 +354,84 @@ dvi_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface) iface->get_dimensions = dvi_document_thumbnails_get_dimensions; } +/* EvFileExporterIface */ +static void +dvi_document_file_exporter_begin (EvFileExporter *exporter, + EvFileExporterContext *fc) +{ + DviDocument *dvi_document = DVI_DOCUMENT(exporter); + + if (dvi_document->exporter_filename) + g_free (dvi_document->exporter_filename); + dvi_document->exporter_filename = g_strdup (fc->filename); + + if (dvi_document->exporter_opts) { + g_string_free (dvi_document->exporter_opts, TRUE); + } + dvi_document->exporter_opts = g_string_new ("-s "); +} + +static void +dvi_document_file_exporter_do_page (EvFileExporter *exporter, + EvRenderContext *rc) +{ + DviDocument *dvi_document = DVI_DOCUMENT(exporter); + + g_string_append_printf (dvi_document->exporter_opts, "%d,", (rc->page) + 1); +} + +static void +dvi_document_file_exporter_end (EvFileExporter *exporter) +{ + gchar *command_line; + gint exit_stat; + GError *err = NULL; + gboolean success; + + DviDocument *dvi_document = DVI_DOCUMENT(exporter); + + command_line = g_strdup_printf ("dvipdfm %s -o %s \"%s\"", /* dvipdfm -s 1,2,.., -o exporter_filename dvi_filename */ + dvi_document->exporter_opts->str, + dvi_document->exporter_filename, + dvi_document->context->filename); + + success = g_spawn_command_line_sync (command_line, + NULL, + NULL, + &exit_stat, + &err); + + g_free (command_line); + + if (success == FALSE) { + g_warning ("Error: %s", err->message); + } else if (exit_stat != 0) { + g_warning ("Error: dvipdfm exited with non-zero status."); + } + + if (err) + g_error_free (err); +} + +static EvFileExporterCapabilities +dvi_document_file_exporter_get_capabilities (EvFileExporter *exporter) +{ + return EV_FILE_EXPORTER_CAN_PAGE_SET | + EV_FILE_EXPORTER_CAN_COPIES | + EV_FILE_EXPORTER_CAN_COLLATE | + EV_FILE_EXPORTER_CAN_REVERSE | + EV_FILE_EXPORTER_CAN_GENERATE_PDF; +} + +static void +dvi_document_file_exporter_iface_init (EvFileExporterIface *iface) +{ + iface->begin = dvi_document_file_exporter_begin; + iface->do_page = dvi_document_file_exporter_do_page; + iface->end = dvi_document_file_exporter_end; + iface->get_capabilities = dvi_document_file_exporter_get_capabilities; +} + #define RGB2ULONG(r,g,b) ((0xFF<<24)|(r<<16)|(g<<8)|(b)) static gboolean @@ -400,54 +487,95 @@ hsb2rgb (float h, float s, float v, char *red, char *green, char *blue) } static void -dvi_document_do_color_special (DviContext *dvi, const char *prefix, const char *arg) +parse_color (const gchar *ptr, + gdouble *color, + gint n_color) { - char *op, *color; + gchar *p = (gchar *)ptr; + gint i; + + for (i = 0; i < n_color; i++) { + while (isspace (*p)) p++; + color[i] = g_ascii_strtod (p, NULL); + while (!isspace (*p) && *p != '\0') p++; + if (*p == '\0') + break; + } +} +static void +dvi_document_do_color_special (DviContext *dvi, const char *prefix, const char *arg) +{ if (strncmp (arg, "pop", 3) == 0) { mdvi_pop_color (dvi); } else if (strncmp (arg, "push", 4) == 0) { - /* Find color source : Named, CMYK or RGB */ - const char *tmp = arg+4; + /* Find color source: Named, CMYK or RGB */ + const char *tmp = arg + 4; + while (isspace (*tmp)) tmp++; if (!strncmp ("rgb", tmp, 3)) { - float r, g, b; - unsigned char red, green, blue; - sscanf (tmp+4, "%f %f %f", &r, &g, &b); - red = 255*r; - green = 255*g; - blue = 255*b; + gdouble rgb[3]; + guchar red, green, blue; + + parse_color (tmp + 4, rgb, 3); + + red = 255 * rgb[0]; + green = 255 * rgb[1]; + blue = 255 * rgb[2]; + mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF); } else if (!strncmp ("hsb", tmp, 4)) { - float h, s, b; - char red, green, blue; - sscanf (tmp+4, "%f %f %f", &h, &s, &b); + gdouble hsb[3]; + guchar red, green, blue; - if (hsb2rgb (h, s, b, &red, &green, &blue)) + parse_color (tmp + 4, hsb, 3); + + if (hsb2rgb (hsb[0], hsb[1], hsb[2], &red, &green, &blue)) mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF); } else if (!strncmp ("cmyk", tmp, 4)) { - double r, g, b, c, m, y, k; - - sscanf (tmp+5, "%f %f %f %f", &c, &m, &y, &k); + gdouble cmyk[4]; + double r, g, b; + guchar red, green, blue; + + parse_color (tmp + 5, cmyk, 4); - r = 1.0 - c - k; + r = 1.0 - cmyk[0] - cmyk[3]; if (r < 0.0) r = 0.0; - g = 1.0 - m - k; + g = 1.0 - cmyk[1] - cmyk[3]; if (g < 0.0) g = 0.0; - b = 1.0 - y - k; + b = 1.0 - cmyk[2] - cmyk[3]; if (b < 0.0) b = 0.0; - mdvi_push_color (dvi, RGB2ULONG ((char)(r*255+0.5), (char)(r*255+0.5), - (char)(b*255+0.5)), 0xFFFFFFFF); + + red = r * 255 + 0.5; + green = g * 255 + 0.5; + blue = b * 255 + 0.5; + + mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF); + } else if (!strncmp ("gray ", tmp, 5)) { + gdouble gray; + guchar rgb; + + parse_color (tmp + 5, &gray, 1); + + rgb = gray * 255 + 0.5; + + mdvi_push_color (dvi, RGB2ULONG (rgb, rgb, rgb), 0xFFFFFFFF); } else { GdkColor color; - if (gdk_color_parse (tmp, &color)) - mdvi_push_color (dvi, RGB2ULONG (color.red*255/65535, - color.green*255/65535, - color.blue*255/65535), 0xFFFFFFFF); + + if (gdk_color_parse (tmp, &color)) { + guchar red, green, blue; + + red = color.red * 255 / 65535.; + green = color.green * 255 / 65535.; + blue = color.blue * 255 / 65535.; + + mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF); + } } } } @@ -480,4 +608,7 @@ dvi_document_init (DviDocument *dvi_document) { dvi_document->context = NULL; dvi_document_init_params (dvi_document); + + dvi_document->exporter_filename = NULL; + dvi_document->exporter_opts = NULL; }