368 lines
8.0 KiB
C
368 lines
8.0 KiB
C
/* viewer-cairo.c: Common code for Cairo-based viewers
|
|
*
|
|
* Copyright (C) 1999,2004,2005 Red Hat, Inc.
|
|
* Copyright (C) 2001 Sun Microsystems
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
#include "config.h"
|
|
|
|
#include "viewer-cairo.h"
|
|
#include "viewer-render.h"
|
|
|
|
#include <cairo.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_CAIRO_XLIB
|
|
#ifdef HAVE_XFT
|
|
#include "viewer-x.h"
|
|
#include <cairo-xlib.h>
|
|
|
|
static cairo_surface_t *
|
|
cairo_x_view_iface_create_surface (gpointer instance,
|
|
gpointer surface,
|
|
int width,
|
|
int height)
|
|
{
|
|
XViewer *x = (XViewer *)instance;
|
|
Drawable drawable = (Drawable) surface;
|
|
|
|
return cairo_xlib_surface_create (x->display, drawable,
|
|
DefaultVisual (x->display, x->screen),
|
|
width, height);
|
|
}
|
|
|
|
static void
|
|
cairo_x_view_iface_paint_background (gpointer instance G_GNUC_UNUSED,
|
|
cairo_t *cr)
|
|
{
|
|
cairo_set_source_rgb (cr, 1, 1, 1);
|
|
cairo_paint (cr);
|
|
|
|
if (opt_bg_set)
|
|
{
|
|
cairo_set_source_rgba (cr,
|
|
opt_bg_color.red / 65535.,
|
|
opt_bg_color.green / 65535.,
|
|
opt_bg_color.blue / 65535.,
|
|
opt_bg_alpha / 65535.);
|
|
cairo_paint (cr);
|
|
}
|
|
}
|
|
|
|
static CairoViewerIface cairo_x_viewer_iface = {
|
|
&x_viewer,
|
|
cairo_x_view_iface_create_surface,
|
|
cairo_x_view_iface_paint_background
|
|
};
|
|
#endif /* HAVE_XFT */
|
|
#endif /* HAVE_CAIRO_XLIB */
|
|
|
|
|
|
|
|
|
|
static cairo_surface_t *
|
|
cairo_view_iface_create_surface (gpointer instance,
|
|
gpointer surface,
|
|
int width,
|
|
int height)
|
|
{
|
|
return cairo_surface_reference (surface);
|
|
}
|
|
|
|
|
|
|
|
static gpointer
|
|
cairo_image_view_create (const PangoViewer *klass G_GNUC_UNUSED)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
cairo_image_view_destroy (gpointer instance G_GNUC_UNUSED)
|
|
{
|
|
}
|
|
|
|
static gpointer
|
|
cairo_image_view_create_surface (gpointer instance,
|
|
int width,
|
|
int height)
|
|
{
|
|
cairo_t *cr;
|
|
cairo_surface_t *surface;
|
|
|
|
/* TODO: Be smarter about format? */
|
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
|
|
|
cr = cairo_create (surface);
|
|
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
|
|
cairo_paint (cr);
|
|
cairo_destroy (cr);
|
|
|
|
return surface;
|
|
}
|
|
|
|
static void
|
|
cairo_image_view_destroy_surface (gpointer instance,
|
|
gpointer surface)
|
|
{
|
|
cairo_surface_destroy (surface);
|
|
}
|
|
|
|
const PangoViewer cairo_image_viewer = {
|
|
"CairoImage",
|
|
NULL,
|
|
NULL,
|
|
cairo_image_view_create,
|
|
cairo_image_view_destroy,
|
|
NULL,
|
|
cairo_image_view_create_surface,
|
|
cairo_image_view_destroy_surface,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
static void
|
|
cairo_image_view_iface_paint_background (gpointer instance G_GNUC_UNUSED,
|
|
cairo_t *cr)
|
|
{
|
|
cairo_set_source_rgb (cr, 1, 1, 1);
|
|
cairo_paint (cr);
|
|
|
|
if (opt_bg_set)
|
|
{
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
|
cairo_set_source_rgba (cr,
|
|
opt_bg_color.red / 65535.,
|
|
opt_bg_color.green / 65535.,
|
|
opt_bg_color.blue / 65535.,
|
|
opt_bg_alpha / 65535.);
|
|
cairo_paint (cr);
|
|
}
|
|
}
|
|
|
|
static CairoViewerIface cairo_image_viewer_iface = {
|
|
&cairo_image_viewer,
|
|
cairo_view_iface_create_surface,
|
|
cairo_image_view_iface_paint_background
|
|
};
|
|
|
|
|
|
|
|
|
|
#ifdef CAIRO_HAS_SVG_SURFACE
|
|
# include <cairo-svg.h>
|
|
#endif
|
|
#ifdef CAIRO_HAS_PDF_SURFACE
|
|
# include <cairo-pdf.h>
|
|
#endif
|
|
#ifdef CAIRO_HAS_PS_SURFACE
|
|
# include <cairo-ps.h>
|
|
# if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0)
|
|
# define HAS_EPS 1
|
|
|
|
static cairo_surface_t *
|
|
_cairo_eps_surface_create (const char *filename,
|
|
double width,
|
|
double height)
|
|
{
|
|
cairo_surface_t *surface;
|
|
|
|
surface = cairo_ps_surface_create (filename, width, height);
|
|
cairo_ps_surface_set_eps (surface, TRUE);
|
|
|
|
return surface;
|
|
}
|
|
|
|
# else
|
|
# undef HAS_EPS
|
|
# endif
|
|
#endif
|
|
|
|
typedef cairo_surface_t *(*CairoVectorFileCreateFunc) (const char *filename,
|
|
double width,
|
|
double height);
|
|
|
|
typedef struct
|
|
{
|
|
const char *filename;
|
|
CairoVectorFileCreateFunc constructor;
|
|
} CairoVectorViewer;
|
|
|
|
static gpointer
|
|
cairo_vector_view_create (const PangoViewer *klass G_GNUC_UNUSED)
|
|
{
|
|
const char *extension = NULL;
|
|
CairoVectorFileCreateFunc constructor = NULL;
|
|
|
|
if (opt_output)
|
|
{
|
|
extension = strrchr (opt_output, '.');
|
|
if (extension)
|
|
extension++; /* skip the dot */
|
|
}
|
|
|
|
if (!extension)
|
|
return NULL;
|
|
|
|
if (0)
|
|
{}
|
|
#ifdef CAIRO_HAS_SVG_SURFACE
|
|
else if (0 == g_ascii_strcasecmp (extension, "svg"))
|
|
constructor = cairo_svg_surface_create;
|
|
#endif
|
|
#ifdef CAIRO_HAS_PDF_SURFACE
|
|
else if (0 == g_ascii_strcasecmp (extension, "pdf"))
|
|
constructor = cairo_pdf_surface_create;
|
|
#endif
|
|
#ifdef CAIRO_HAS_PS_SURFACE
|
|
else if (0 == g_ascii_strcasecmp (extension, "ps"))
|
|
constructor = cairo_ps_surface_create;
|
|
#ifdef HAS_EPS
|
|
else if (0 == g_ascii_strcasecmp (extension, "eps"))
|
|
constructor = _cairo_eps_surface_create;
|
|
#endif
|
|
#endif
|
|
|
|
if (constructor)
|
|
{
|
|
CairoVectorViewer *instance;
|
|
|
|
instance = g_slice_new (CairoVectorViewer);
|
|
|
|
/* save output filename and unset it such that the viewer layer
|
|
* doesn't try to save to file.
|
|
*/
|
|
instance->filename = opt_output;
|
|
opt_output = NULL;
|
|
|
|
instance->constructor = constructor;
|
|
|
|
/* Fix dpi on 72. That's what cairo vector surfaces are. */
|
|
opt_dpi = 72;
|
|
|
|
return instance;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
cairo_vector_view_destroy (gpointer instance G_GNUC_UNUSED)
|
|
{
|
|
CairoVectorViewer *c = (CairoVectorViewer *) instance;
|
|
|
|
g_slice_free (CairoVectorViewer, c);
|
|
}
|
|
|
|
static gpointer
|
|
cairo_vector_view_create_surface (gpointer instance,
|
|
int width,
|
|
int height)
|
|
{
|
|
CairoVectorViewer *c = (CairoVectorViewer *) instance;
|
|
cairo_surface_t *surface;
|
|
|
|
surface = c->constructor (c->filename, width, height);
|
|
|
|
/*cairo_surface_set_fallback_resolution (surface, fallback_resolution_x, fallback_resolution_y);*/
|
|
|
|
return surface;
|
|
}
|
|
|
|
static void
|
|
cairo_vector_view_destroy_surface (gpointer instance,
|
|
gpointer surface)
|
|
{
|
|
/* TODO: check for errors */
|
|
cairo_surface_destroy (surface);
|
|
}
|
|
|
|
const PangoViewer cairo_vector_viewer = {
|
|
"CairoFile",
|
|
NULL,
|
|
NULL,
|
|
cairo_vector_view_create,
|
|
cairo_vector_view_destroy,
|
|
NULL,
|
|
cairo_vector_view_create_surface,
|
|
cairo_vector_view_destroy_surface,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
static void
|
|
cairo_vector_view_iface_paint_background (gpointer instance G_GNUC_UNUSED,
|
|
cairo_t *cr)
|
|
{
|
|
if (opt_bg_set)
|
|
{
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
|
cairo_set_source_rgba (cr,
|
|
opt_bg_color.red / 65535.,
|
|
opt_bg_color.green / 65535.,
|
|
opt_bg_color.blue / 65535.,
|
|
opt_bg_alpha / 65535.);
|
|
cairo_paint (cr);
|
|
}
|
|
}
|
|
|
|
static CairoViewerIface cairo_vector_viewer_iface = {
|
|
&cairo_vector_viewer,
|
|
cairo_view_iface_create_surface,
|
|
cairo_vector_view_iface_paint_background
|
|
};
|
|
|
|
|
|
|
|
gpointer
|
|
cairo_viewer_iface_create (const CairoViewerIface **iface)
|
|
{
|
|
gpointer ret;
|
|
|
|
*iface = &cairo_vector_viewer_iface;
|
|
ret = (*iface)->backend_class->create ((*iface)->backend_class);
|
|
if (ret)
|
|
return ret;
|
|
|
|
#ifdef HAVE_CAIRO_XLIB
|
|
#ifdef HAVE_XFT
|
|
if (opt_display)
|
|
{
|
|
*iface = &cairo_x_viewer_iface;
|
|
return (*iface)->backend_class->create ((*iface)->backend_class);
|
|
}
|
|
#endif /* HAVE_XFT */
|
|
#endif /* HAVE_CAIRO_XLIB */
|
|
|
|
*iface = &cairo_image_viewer_iface;
|
|
return (*iface)->backend_class->create ((*iface)->backend_class);
|
|
}
|
|
|
|
void
|
|
cairo_viewer_add_options (GOptionGroup *group G_GNUC_UNUSED)
|
|
{
|
|
}
|