From 4ce480dd80453275c10c3b99f988667c2f1bdfff Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Sun, 17 Jun 2007 15:05:11 +0000 Subject: Removed Added 2007-06-17 Carlos Garcia Campos * backend/dvi/Makefile.am: * backend/dvi/pixbuf-device.[ch]: Removed * backend/dvi/cairo-device.[ch]: Added * backend/dvi/mdvi-lib/dviread.c: (draw_shrink_rule): * backend/dvi/dvi-document.c: (dvi_document_load), (dvi_document_render), (dvi_document_finalize), (dvi_document_thumbnails_get_thumbnail), (parse_color), (dvi_document_do_color_special): * libdocument/ev-document-misc.[ch]: (ev_document_misc_pixbuf_from_surface): Port dvi backend to cairo and fix a problem with colors. svn path=/trunk/; revision=2506 --- diff --git a/ChangeLog b/ChangeLog index 72b055b..4454805 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2007-06-17 Carlos Garcia Campos + + * backend/dvi/Makefile.am: + * backend/dvi/pixbuf-device.[ch]: Removed + * backend/dvi/cairo-device.[ch]: Added + * backend/dvi/mdvi-lib/dviread.c: (draw_shrink_rule): + * backend/dvi/dvi-document.c: (dvi_document_load), + (dvi_document_render), (dvi_document_finalize), + (dvi_document_thumbnails_get_thumbnail), (parse_color), + (dvi_document_do_color_special): + * libdocument/ev-document-misc.[ch]: + (ev_document_misc_pixbuf_from_surface): + + Port dvi backend to cairo and fix a problem with colors. + 2007-06-14 Carlos Garcia Campos * shell/ev-view.c: (draw_one_page): diff --git a/backend/dvi/Makefile.am b/backend/dvi/Makefile.am index f23a34b..be90e26 100644 --- a/backend/dvi/Makefile.am +++ b/backend/dvi/Makefile.am @@ -11,8 +11,8 @@ noinst_LTLIBRARIES = libgtkdvi.la libgtkdvi_la_SOURCES = \ dvi-document.c \ dvi-document.h \ - pixbuf-device.c \ - pixbuf-device.h \ + cairo-device.c \ + cairo-device.h \ fonts.c \ fonts.h diff --git a/backend/dvi/cairo-device.c b/backend/dvi/cairo-device.c new file mode 100644 index 0000000..19006d2 --- /dev/null +++ b/backend/dvi/cairo-device.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2007 Carlos Garcia Campos + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "cairo-device.h" + +typedef struct { + cairo_t *cr; + + gint xmargin; + gint ymargin; + + gdouble scale; + + Ulong fg; + Ulong bg; + +} DviCairoDevice; + +static void +dvi_cairo_draw_glyph (DviContext *dvi, + DviFontChar *ch, + int x0, + int y0) +{ + DviCairoDevice *cairo_device; + int x, y, w, h; + gboolean isbox; + DviGlyph *glyph; + cairo_surface_t *surface; + + cairo_device = (DviCairoDevice *) dvi->device.device_data; + + glyph = &ch->grey; + + isbox = (glyph->data == NULL || (dvi->params.flags & MDVI_PARAM_CHARBOXES)); + + x = - glyph->x + x0 + cairo_device->xmargin; + y = - glyph->y + y0 + cairo_device->ymargin; + w = glyph->w; + h = glyph->h; + + surface = cairo_get_target (cairo_device->cr); + if (x < 0 || y < 0 + || x + w > cairo_image_surface_get_width (surface) + || y + h > cairo_image_surface_get_height (surface)) + return; + + cairo_save (cairo_device->cr); + if (isbox) { + cairo_rectangle (cairo_device->cr, + x - cairo_device->xmargin, + y - cairo_device->ymargin, + w, h); + cairo_stroke (cairo_device->cr); + } else { + cairo_translate (cairo_device->cr, x, y); + cairo_set_source_surface (cairo_device->cr, + (cairo_surface_t *) glyph->data, + 0, 0); + cairo_paint (cairo_device->cr); + } + + cairo_restore (cairo_device->cr); +} + +static void +dvi_cairo_draw_rule (DviContext *dvi, + int x, + int y, + Uint width, + Uint height, + int fill) +{ + DviCairoDevice *cairo_device; + Ulong color; + + cairo_device = (DviCairoDevice *) dvi->device.device_data; + + color = cairo_device->fg; + + cairo_save (cairo_device->cr); + + cairo_set_line_width (cairo_device->cr, + cairo_get_line_width (cairo_device->cr) * cairo_device->scale); + cairo_set_source_rgb (cairo_device->cr, + ((color >> 16) & 0xff) / 255., + ((color >> 8) & 0xff) / 255., + ((color >> 0) & 0xff) / 255.); + + cairo_rectangle (cairo_device->cr, + x + cairo_device->xmargin, + y + cairo_device->ymargin, + width, height); + if (fill == 0) { + cairo_stroke (cairo_device->cr); + } else { + cairo_fill (cairo_device->cr); + } + + cairo_restore (cairo_device->cr); +} + +static int +dvi_cairo_alloc_colors (void *device_data, + Ulong *pixels, + int npixels, + Ulong fg, + Ulong bg, + double gamma, + int density) +{ + double frac; + GdkColor color, color_fg, color_bg; + int i, n; + + color_bg.red = (bg >> 16) & 0xff; + color_bg.green = (bg >> 8) & 0xff; + color_bg.blue = (bg >> 0) & 0xff; + + color_fg.red = (fg >> 16) & 0xff; + color_fg.green = (fg >> 8) & 0xff; + color_fg.blue = (fg >> 0) & 0xff; + + n = npixels - 1; + for (i = 0; i < npixels; i++) { + frac = (gamma > 0) ? + pow ((double)i / n, 1 / gamma) : + 1 - pow ((double)(n - i) / n, -gamma); + + color.red = frac * ((double)color_fg.red - color_bg.red) + color_bg.red; + color.green = frac * ((double)color_fg.green - color_bg.green) + color_bg.green; + color.blue = frac * ((double)color_fg.blue - color_bg.blue) + color_bg.blue; + + pixels[i] = (color.red << 16) + (color.green << 8) + color.blue + 0xff000000; + } + + return npixels; +} + +static void * +dvi_cairo_create_image (void *device_data, + Uint width, + Uint height, + Uint bpp) +{ + return cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); +} + +static void +dvi_cairo_free_image (void *ptr) +{ + cairo_surface_destroy ((cairo_surface_t *)ptr); +} + +static void +dvi_cairo_put_pixel (void *image, int x, int y, Ulong color) +{ + cairo_t *cr; + cairo_surface_t *surface; + gint rowstride; + guchar *p; + + surface = (cairo_surface_t *) image; + + rowstride = cairo_image_surface_get_stride (surface); + p = cairo_image_surface_get_data (surface) + y * rowstride + x * 4; + + p[2] = (color >> 16) & 0xff; + p[1] = (color >> 8) & 0xff; + p[0] = (color >> 0) & 0xff; +} + +static void +dvi_cairo_set_color (void *device_data, Ulong fg, Ulong bg) +{ + DviCairoDevice *cairo_device = (DviCairoDevice *) device_data; + + cairo_device->fg = fg; + cairo_device->bg = bg; +} + +/* Public methods */ +void +mdvi_cairo_device_init (DviDevice *device) +{ + device->device_data = g_new0 (DviCairoDevice, 1); + + device->draw_glyph = dvi_cairo_draw_glyph; + device->draw_rule = dvi_cairo_draw_rule; + device->alloc_colors = dvi_cairo_alloc_colors; + device->create_image = dvi_cairo_create_image; + device->free_image = dvi_cairo_free_image; + device->put_pixel = dvi_cairo_put_pixel; + device->set_color = dvi_cairo_set_color; + device->refresh = NULL; +} + +void +mdvi_cairo_device_free (DviDevice *device) +{ + DviCairoDevice *cairo_device; + + cairo_device = (DviCairoDevice *) device->device_data; + + if (cairo_device->cr) + cairo_destroy (cairo_device->cr); + + g_free (cairo_device); +} + +cairo_surface_t * +mdvi_cairo_device_get_surface (DviDevice *device) +{ + DviCairoDevice *cairo_device; + + cairo_device = (DviCairoDevice *) device->device_data; + + return cairo_surface_reference (cairo_get_target (cairo_device->cr)); +} + +void +mdvi_cairo_device_render (DviContext* dvi) +{ + DviCairoDevice *cairo_device; + gint page_width; + gint page_height; + cairo_surface_t *surface; + gchar *pixels; + gint rowstride; + static const cairo_user_data_key_t key; + + cairo_device = (DviCairoDevice *) dvi->device.device_data; + + if (cairo_device->cr) + cairo_destroy (cairo_device->cr); + + page_width = dvi->dvi_page_w * dvi->params.conv + 2 * cairo_device->xmargin; + page_height = dvi->dvi_page_h * dvi->params.vconv + 2 * cairo_device->ymargin; + + rowstride = page_width * 4; + pixels = (gchar *) g_malloc (page_height * rowstride); + memset (pixels, 0xff, page_height * rowstride); + + surface = cairo_image_surface_create_for_data (pixels, + CAIRO_FORMAT_RGB24, + page_width, page_height, + rowstride); + cairo_surface_set_user_data (surface, &key, + pixels, (cairo_destroy_func_t)g_free); + + cairo_device->cr = cairo_create (surface); + cairo_surface_destroy (surface); + + mdvi_dopage (dvi, dvi->currpage); +} + +void +mdvi_cairo_device_set_margins (DviDevice *device, + gint xmargin, + gint ymargin) +{ + DviCairoDevice *cairo_device; + + cairo_device = (DviCairoDevice *) device->device_data; + + cairo_device->xmargin = xmargin; + cairo_device->ymargin = ymargin; +} + +void +mdvi_cairo_device_set_scale (DviDevice *device, + gdouble scale) +{ + DviCairoDevice *cairo_device; + + cairo_device = (DviCairoDevice *) device->device_data; + + cairo_device->scale = scale; +} diff --git a/backend/dvi/cairo-device.h b/backend/dvi/cairo-device.h new file mode 100644 index 0000000..d5451be --- /dev/null +++ b/backend/dvi/cairo-device.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007 Carlos Garcia Campos + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef MDVI_CAIRO_DEVICE +#define MDVI_CAIRO_DEVICE + +#include +#include + +#include "mdvi.h" + +G_BEGIN_DECLS + +void mdvi_cairo_device_init (DviDevice *device); +void mdvi_cairo_device_free (DviDevice *device); +cairo_surface_t *mdvi_cairo_device_get_surface (DviDevice *device); +void mdvi_cairo_device_render (DviContext* dvi); +void mdvi_cairo_device_set_margins (DviDevice *device, + gint xmargin, + gint ymargin); +void mdvi_cairo_device_set_scale (DviDevice *device, + gdouble scale); + +G_END_DECLS + +#endif /* MDVI_CAIRO_DEVICE */ diff --git a/backend/dvi/dvi-document.c b/backend/dvi/dvi-document.c index 445c1e0..56d8bbb 100644 --- a/backend/dvi/dvi-document.c +++ b/backend/dvi/dvi-document.c @@ -23,7 +23,7 @@ #include "mdvi.h" #include "fonts.h" -#include "pixbuf-device.h" +#include "cairo-device.h" #include #include @@ -49,7 +49,6 @@ struct _DviDocument DviParams *params; /* To let document scale we should remember width and height */ - double base_width; double base_height; @@ -58,13 +57,15 @@ struct _DviDocument 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); +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); G_DEFINE_TYPE_WITH_CODE (DviDocument, dvi_document, G_TYPE_OBJECT, @@ -75,49 +76,50 @@ G_DEFINE_TYPE_WITH_CODE 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,31 +134,29 @@ 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 cairo_surface_t * dvi_document_render (EvDocument *document, EvRenderContext *rc) { - GdkPixbuf *pixbuf; cairo_surface_t *surface; cairo_surface_t *rotated_surface; DviDocument *dvi_document = DVI_DOCUMENT(document); @@ -170,7 +170,7 @@ dvi_document_render (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, @@ -186,24 +186,19 @@ dvi_document_render (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); - /* FIXME: we should write a mdvi device based on cairo */ - surface = ev_document_misc_surface_from_pixbuf (pixbuf); - g_object_unref (pixbuf); - rotated_surface = ev_document_misc_surface_rotate_and_scale (surface, required_width, - required_height, + required_height, rc->rotation); cairo_surface_destroy (surface); - + return rotated_surface; } @@ -214,7 +209,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); @@ -235,7 +230,7 @@ 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 (); @@ -296,16 +291,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, @@ -316,29 +311,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; @@ -406,54 +403,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); + } } } } diff --git a/backend/dvi/mdvi-lib/dviread.c b/backend/dvi/mdvi-lib/dviread.c index 8398c27..3042951 100644 --- a/backend/dvi/mdvi-lib/dviread.c +++ b/backend/dvi/mdvi-lib/dviread.c @@ -1178,8 +1178,8 @@ static void draw_shrink_rule (DviContext *dvi, int x, int y, Uint w, Uint h, int hs = dvi->params.hshrink; vs = dvi->params.vshrink; - fg = dvi->params.fg; - bg = dvi->params.bg; + fg = dvi->curr_fg; + bg = dvi->curr_bg; if (MDVI_ENABLED(dvi, MDVI_PARAM_ANTIALIASED)) { npixels = vs * hs + 1; diff --git a/backend/dvi/pixbuf-device.c b/backend/dvi/pixbuf-device.c deleted file mode 100644 index 1ef4365..0000000 --- a/backend/dvi/pixbuf-device.c +++ /dev/null @@ -1,220 +0,0 @@ -#include "pixbuf-device.h" -#include - -typedef struct _DviPixbufDevice -{ - GdkPixbuf *pixbuf; - - gboolean valid; - - gint xmargin; - gint ymargin; - - Ulong fg; - Ulong bg; - -} DviPixbufDevice; - -static void dvi_pixbuf_draw_rule(DviContext *dvi, int x, int y, Uint w, Uint h, int fill); - -static void dvi_pixbuf_draw_glyph(DviContext *dvi, DviFontChar *ch, int x0, int y0) -{ - DviPixbufDevice *c_device = (DviPixbufDevice *) dvi->device.device_data; - - int x, y, w, h; - int isbox; - DviGlyph *glyph; - - glyph = &ch->grey; - - isbox = (glyph->data == NULL || (dvi->params.flags & MDVI_PARAM_CHARBOXES)); - - x = - glyph->x + x0 + c_device->xmargin; - y = - glyph->y + y0 + c_device->ymargin; - w = glyph->w; - h = glyph->h; - - if (x < 0 || y < 0 - || x + w > gdk_pixbuf_get_width (c_device->pixbuf) - || y + h > gdk_pixbuf_get_height (c_device->pixbuf)) - return; - - if (isbox) { - dvi_pixbuf_draw_rule(dvi, x - c_device->xmargin, y - c_device->ymargin, w, h, FALSE); - } - else { - gdk_pixbuf_copy_area (GDK_PIXBUF (glyph->data), - 0, 0, - w, h, - c_device->pixbuf, x, y); - } -} - -static void dvi_pixbuf_draw_rule(DviContext *dvi, int x, int y, Uint w, Uint h, int fill) -{ - DviPixbufDevice *c_device = (DviPixbufDevice *) dvi->device.device_data; - gint rowstride; - guchar *p; - gint i, j; - gint red, green, blue; - - red = (c_device->fg >> 16) & 0xff; - green = (c_device->fg >> 8) & 0xff; - blue = c_device->fg & 0xff; - - x += c_device->xmargin; y += c_device->ymargin; - - if (x < 0 || y < 0 - || x + w > gdk_pixbuf_get_width (c_device->pixbuf) - || y + h > gdk_pixbuf_get_height (c_device->pixbuf)) - return; - - rowstride = gdk_pixbuf_get_rowstride (c_device->pixbuf); - p = gdk_pixbuf_get_pixels (c_device->pixbuf) + rowstride * y + 3 * x; - - for (i = 0; i < h; i++) { - if (i == 0 || i == h - 1 || fill) { - for (j = 0; j < w; j++) { - p[j * 3] = red; - p[j * 3 + 1] = green; - p[j * 3 + 2] = blue; - } - } else { - p[0] = red; - p[1] = green; - p[2] = blue; - p[(w - 1) * 3] = red; - p[(w - 1) * 3 + 1] = green; - p[(w - 1) * 3 + 2] = blue; - } - p += rowstride; - } -} - -static int dvi_pixbuf_interpolate_colors(void *device_data, - Ulong *pixels, int nlevels, Ulong fg, Ulong bg, double g, int density) -{ - double frac; - GdkColor color, color_fg, color_bg; - int i, n; - - color_bg.red = (bg >> 16) & 0xff; - color_bg.green = (bg >> 8) & 0xff; - color_bg.blue = bg & 0xff; - - color_fg.red = fg >> 16 & 0xff; - color_fg.green = fg >> 8 & 0xff; - color_fg.blue = fg & 0xff; - - n = nlevels - 1; - for(i = 0; i < nlevels; i++) { - if(g > 0) - frac = pow((double)i / n, 1 / g); - else - frac = 1 - pow((double)(n - i) / n, -g); - color.red = frac * ((double)color_fg.red - color_bg.red) + color_bg.red; - color.green = frac * ((double)color_fg.green - color_bg.green) + color_bg.green; - color.blue = frac * ((double)color_fg.blue - color_bg.blue) + color_bg.blue; - - pixels[i] = (color.red << 16) + (color.green << 8) + color.blue + 0xff000000; - } - - return nlevels; -} - -static void *dvi_pixbuf_create_image(void *device_data, Uint w, Uint h, Uint bpp) -{ - - return gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, w, h); - - return NULL; -} - -static void dvi_pixbuf_free_image(void *ptr) -{ - g_object_unref (GDK_PIXBUF(ptr)); -} - -static void dvi_pixbuf_put_pixel(void *image, int x, int y, Ulong color) -{ - guchar *p; - - p = gdk_pixbuf_get_pixels (GDK_PIXBUF(image)) + y * gdk_pixbuf_get_rowstride(GDK_PIXBUF(image)) + x * 3; - - p[0] = (color >> 16) & 0xff; - p[1] = (color >> 8) & 0xff; - p[2] = color & 0xff; -} - -static void dvi_pixbuf_set_color(void *device_data, Ulong fg, Ulong bg) -{ - DviPixbufDevice *c_device = (DviPixbufDevice *) device_data; - - c_device->fg = fg; - - return; -} - -void mdvi_pixbuf_device_init (DviDevice *device) -{ - device->device_data = - g_new0 (DviPixbufDevice, 1); - - device->draw_glyph = dvi_pixbuf_draw_glyph; - device->draw_rule = dvi_pixbuf_draw_rule; - device->alloc_colors = dvi_pixbuf_interpolate_colors; - device->create_image = dvi_pixbuf_create_image; - device->free_image = dvi_pixbuf_free_image; - device->put_pixel = dvi_pixbuf_put_pixel; - device->set_color = dvi_pixbuf_set_color; - device->refresh = NULL; - - return; -} - -void mdvi_pixbuf_device_free (DviDevice *device) -{ - DviPixbufDevice *c_device = (DviPixbufDevice *) device->device_data; - - if (c_device->pixbuf) - g_object_unref (c_device->pixbuf); - - g_free (c_device); -} - -GdkPixbuf * -mdvi_pixbuf_device_get_pixbuf (DviDevice *device) -{ - DviPixbufDevice *c_device = (DviPixbufDevice *) device->device_data; - - return g_object_ref (c_device->pixbuf); -} - -void -mdvi_pixbuf_device_render (DviContext * dvi) -{ - DviPixbufDevice *c_device = (DviPixbufDevice *) dvi->device.device_data; - gint page_width; - gint page_height; - - if (c_device->pixbuf) - g_object_unref (c_device->pixbuf); - - page_width = dvi->dvi_page_w * dvi->params.conv + 2 * c_device->xmargin; - page_height = dvi->dvi_page_h * dvi->params.vconv + 2 * c_device->ymargin; - - c_device->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, page_width, page_height); - gdk_pixbuf_fill (c_device->pixbuf, 0xffffffff); - - mdvi_dopage (dvi, dvi->currpage); -} - - -void -mdvi_pixbuf_device_set_margins (DviDevice *device, gint xmargin, gint ymargin) -{ - DviPixbufDevice *c_device = (DviPixbufDevice *) device->device_data; - - c_device->xmargin = xmargin; - c_device->ymargin = ymargin; -} diff --git a/backend/dvi/pixbuf-device.h b/backend/dvi/pixbuf-device.h deleted file mode 100644 index bacae4b..0000000 --- a/backend/dvi/pixbuf-device.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MDVI_PIXBUF_DEVICE -#define MDVI_PIXBUF_DEVICE - -#include "mdvi.h" -#include - -void -mdvi_pixbuf_device_init (DviDevice *device); - -void -mdvi_pixbuf_device_free (DviDevice *device); - -GdkPixbuf * -mdvi_pixbuf_device_get_pixbuf (DviDevice *device); - -void -mdvi_pixbuf_device_render (DviContext *dvi); - -void -mdvi_pixbuf_device_set_margins (DviDevice *device, gint xmargin, gint ymargin); - -#endif /* MDVI_PIXBUF_DEVICE */ - - diff --git a/libdocument/ev-document-misc.c b/libdocument/ev-document-misc.c index e8739a1..3dc4bab 100644 --- a/libdocument/ev-document-misc.c +++ b/libdocument/ev-document-misc.c @@ -163,6 +163,73 @@ ev_document_misc_surface_from_pixbuf (GdkPixbuf *pixbuf) return surface; } +GdkPixbuf * +ev_document_misc_pixbuf_from_surface (cairo_surface_t *surface) +{ + GdkPixbuf *pixbuf; + cairo_surface_t *image; + cairo_t *cr; + gboolean has_alpha; + gint width, height; + cairo_format_t surface_format; + gint pixbuf_n_channels; + gint pixbuf_rowstride; + guchar *pixbuf_pixels; + gint x, y; + + width = cairo_image_surface_get_width (surface); + height = cairo_image_surface_get_height (surface); + + surface_format = cairo_image_surface_get_format (surface); + has_alpha = (surface_format == CAIRO_FORMAT_ARGB32); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, 8, + width, height); + pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf); + pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf); + + image = cairo_image_surface_create_for_data (pixbuf_pixels, + surface_format, + width, height, + pixbuf_rowstride); + cr = cairo_create (image); + cairo_set_source_surface (cr, surface, 0, 0); + + if (has_alpha) + cairo_mask_surface (cr, surface, 0, 0); + else + cairo_paint (cr); + + cairo_destroy (cr); + cairo_surface_destroy (image); + + for (y = 0; y < height; y++) { + guchar *p = pixbuf_pixels + y * pixbuf_rowstride; + + for (x = 0; x < width; x++) { + guchar tmp; + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + tmp = p[0]; + p[0] = p[2]; + p[2] = tmp; + p[3] = (has_alpha) ? p[3] : 0xff; +#else + tmp = p[0]; + p[0] = (has_alpha) ? p[3] : 0xff; + p[3] = p[2]; + p[2] = p[1]; + p[1] = tmp; +#endif + p += pixbuf_n_channels; + } + } + + return pixbuf; +} + cairo_surface_t * ev_document_misc_surface_rotate_and_scale (cairo_surface_t *surface, gint dest_width, @@ -207,10 +274,14 @@ ev_document_misc_surface_rotate_and_scale (cairo_surface_t *surface, default: cairo_translate (cr, 0, 0); } - cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_BILINEAR); - cairo_scale (cr, - (gdouble)dest_width / width, - (gdouble)dest_height / height); + + if (dest_width != width || dest_height != height) { + cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_BILINEAR); + cairo_scale (cr, + (gdouble)dest_width / width, + (gdouble)dest_height / height); + } + cairo_rotate (cr, dest_rotation * G_PI / 180.0); cairo_set_source_surface (cr, surface, 0, 0); cairo_paint (cr); diff --git a/libdocument/ev-document-misc.h b/libdocument/ev-document-misc.h index 0860774..b58af18 100644 --- a/libdocument/ev-document-misc.h +++ b/libdocument/ev-document-misc.h @@ -41,7 +41,9 @@ void ev_document_misc_paint_one_page (GdkDrawable *drawable, GdkRectangle *area, GtkBorder *border, gboolean highlight); + cairo_surface_t *ev_document_misc_surface_from_pixbuf (GdkPixbuf *pixbuf); +GdkPixbuf *ev_document_misc_pixbuf_from_surface (cairo_surface_t *surface); cairo_surface_t *ev_document_misc_surface_rotate_and_scale (cairo_surface_t *surface, gint dest_width, gint dest_height, -- cgit v0.9.1