Commit 4ce480dd authored by Carlos Garcia Campos's avatar Carlos Garcia Campos Committed by Carlos Garcia Campos

Removed Added

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
parent 489459b1
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):
......
......@@ -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
......
/*
* 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;
}
/*
* 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 */
......@@ -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];