]> www.fi.muni.cz Git - evince.git/commitdiff
Removed Added
authorCarlos Garcia Campos <carlosgc@gnome.org>
Sun, 17 Jun 2007 15:05:11 +0000 (15:05 +0000)
committerCarlos Garcia Campos <carlosgc@src.gnome.org>
Sun, 17 Jun 2007 15:05:11 +0000 (15:05 +0000)
2007-06-17  Carlos Garcia Campos  <carlosgc@gnome.org>
* 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

ChangeLog
backend/dvi/Makefile.am
backend/dvi/cairo-device.c [new file with mode: 0644]
backend/dvi/cairo-device.h [new file with mode: 0644]
backend/dvi/dvi-document.c
backend/dvi/mdvi-lib/dviread.c
backend/dvi/pixbuf-device.c [deleted file]
backend/dvi/pixbuf-device.h [deleted file]
libdocument/ev-document-misc.c
libdocument/ev-document-misc.h

index 72b055b4e8a9d87644497246dd35e7dc38295706..445480597db76413de54430316508fb183ae5e01 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2007-06-17  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+       * 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  <carlosgc@gnome.org>
 
        * shell/ev-view.c: (draw_one_page):
index f23a34bae544d3ae8b958fd21a7ccc083cae099a..be90e26fde257bd434e33d7c2f4d39777ce7bad8 100644 (file)
@@ -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 (file)
index 0000000..19006d2
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * 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 <gdk/gdkcolor.h>
+#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 (file)
index 0000000..d5451be
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * 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 <glib.h>
+#include <cairo.h>
+
+#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 */
index 445c1e0cab2df14b6dd943c1a0441ff4bfa0493b..56d8bbb84aa7facd1553671528934244e4626676 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "mdvi.h"
 #include "fonts.h"
-#include "pixbuf-device.h"
+#include "cairo-device.h"
 
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
@@ -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);
+                       }
                 }
         }
 }
index 8398c2702085521fa98195e239a19b83dac23485..3042951df5f9c7bb7be27b800cde1c974b474b6e 100644 (file)
@@ -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 (file)
index 1ef4365..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-#include "pixbuf-device.h"
-#include <gtk/gtk.h>
-
-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 (file)
index bacae4b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef MDVI_PIXBUF_DEVICE
-#define MDVI_PIXBUF_DEVICE
-
-#include "mdvi.h"
-#include <gtk/gtk.h>
-
-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 */
-
-
index e8739a1ae8d073683117667c5a6823b0d1ea2ca3..3dc4babef53a14198acedf20422c1586f5f4a4ba 100644 (file)
@@ -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);
index 08607745ef06fe7b67eb7a9c84edb7119a8f1d43..b58af18060057ddd77d595ff9619b9feaacd594e 100644 (file)
@@ -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,