+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):
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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
#include "mdvi.h"
#include "fonts.h"
-#include "pixbuf-device.h"
+#include "cairo-device.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
DviParams *params;
/* To let document scale we should remember width and height */
-
double base_width;
double base_height;
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,
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;
}
}
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);
*/
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,
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;
}
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);
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 ();
{
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,
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;
}
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);
+ }
}
}
}
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;
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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 */
-
-
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,
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);
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,