Commit 8988947a authored by Dom Lachowicz's avatar Dom Lachowicz

more compartmentalization of libart, accomodation for cairo

parent 7cd6345d
2005-08-03 Dom Lachowicz <cinamod@hotmail.com>
* rsvg-file-util.c: Create 2 generic functions for loading handles from data
* rsvg-art-file-util.c: Move the old rsvg-file-util.c to here
* rsvg.c: Export rsvg_handle_get_dimensions()
* rsvg-cairo.c: Make this compile
2005-08-03 Carl Worth <cworth@cworth.org>
* rsvg-cairo-draw.c: (_set_rsvg_affine), (rsvg_cairo_render_path):
......
......@@ -73,6 +73,7 @@ librsvg_2_base_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined -export-d
librsvg_2_base_la_LIBADD = $(LIBGNOME_VFS_LIBS) $(LIBGSF_LIBS) $(LIBCROCO_LIBS) $(LIBRSVG_LIBS) $(FREETYPE_LIBS)
librsvg_2_libart_la_SOURCES = \
rsvg-art-file-util.c \
rsvg-art-composite.c \
rsvg-art-composite.h \
rsvg-art-draw.c \
......
/* vim: set sw=4: -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
rsvg-file-util.c: SAX-based renderer for SVG files into a GdkPixbuf.
Copyright (C) 2000 Eazel, Inc.
Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com>
This program 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 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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.
Author: Raph Levien <raph@artofcode.com>
*/
#include "config.h"
#include "rsvg.h"
#include "rsvg-private.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define SVG_BUFFER_SIZE (1024 * 8)
static void
rsvg_size_callback (int *width,
int *height,
gpointer data)
{
struct RsvgSizeCallbackData *real_data = (struct RsvgSizeCallbackData *) data;
double zoomx, zoomy, zoom;
int in_width, in_height;
in_width = *width;
in_height = *height;
switch (real_data->type) {
case RSVG_SIZE_ZOOM:
if (*width < 0 || *height < 0)
return;
*width = floor (real_data->x_zoom * *width + 0.5);
*height = floor (real_data->y_zoom * *height + 0.5);
break;
case RSVG_SIZE_ZOOM_MAX:
if (*width < 0 || *height < 0)
return;
*width = floor (real_data->x_zoom * *width + 0.5);
*height = floor (real_data->y_zoom * *height + 0.5);
if (*width > real_data->width || *height > real_data->height)
{
zoomx = (double) real_data->width / *width;
zoomy = (double) real_data->height / *height;
zoom = MIN (zoomx, zoomy);
*width = floor (zoom * *width + 0.5);
*height = floor (zoom * *height + 0.5);
}
break;
case RSVG_SIZE_WH_MAX:
if (*width < 0 || *height < 0)
return;
zoomx = (double) real_data->width / *width;
zoomy = (double) real_data->height / *height;
if (zoomx < 0)
zoom = zoomy;
else if (zoomy < 0)
zoom = zoomx;
else
zoom = MIN (zoomx, zoomy);
*width = floor (zoom * *width + 0.5);
*height = floor (zoom * *height + 0.5);
break;
case RSVG_SIZE_WH:
if (real_data->width != -1)
*width = real_data->width;
if (real_data->height != -1)
*height = real_data->height;
break;
default:
g_assert_not_reached ();
}
if (real_data->keep_aspect_ratio)
{
int out_min = MIN(*width, *height);
if (out_min == *width)
{
*height = in_height * ((double)*width / (double)in_width);
}
else
{
*width = in_width * ((double)*height / (double)in_height);
}
}
}
/* private */
GdkPixbuf *
rsvg_pixbuf_from_data_with_size_data (const guchar * buff,
size_t len,
struct RsvgSizeCallbackData * data,
const char * base_uri,
GError ** error)
{
RsvgHandle * handle;
GdkPixbuf * retval;
handle = rsvg_handle_new ();
if (!handle) {
g_set_error (error, rsvg_error_quark (), 0,
_("Error creating SVG reader"));
return NULL;
}
rsvg_handle_set_size_callback (handle, rsvg_size_callback, data, NULL);
rsvg_handle_set_base_uri (handle, base_uri);
rsvg_handle_write (handle, buff, len, error);
rsvg_handle_close (handle, error);
retval = rsvg_handle_get_pixbuf (handle);
rsvg_handle_free (handle);
return retval;
}
static GdkPixbuf *
rsvg_pixbuf_from_stdio_file_with_size_data(GByteArray *f,
struct RsvgSizeCallbackData * data,
gchar *base_uri,
GError ** error)
{
RsvgHandle * handle;
GdkPixbuf * retval;
handle = rsvg_handle_new ();
if (!handle) {
g_set_error (error, rsvg_error_quark (), 0,
_("Error creating SVG reader"));
return NULL;
}
rsvg_handle_set_size_callback (handle, rsvg_size_callback, data, NULL);
rsvg_handle_set_base_uri(handle, base_uri);
rsvg_handle_write (handle, f->data, f->len, error);
rsvg_handle_close (handle, error);
retval = rsvg_handle_get_pixbuf (handle);
rsvg_handle_free (handle);
return retval;
}
static GdkPixbuf *
rsvg_pixbuf_from_file_with_size_data (const gchar * file_name,
struct RsvgSizeCallbackData * data,
GError ** error)
{
GdkPixbuf * pixbuf;
gchar * base_uri;
GByteArray *f;
base_uri = rsvg_get_base_uri_from_filename(file_name);
f = _rsvg_acquire_xlink_href_resource (file_name, base_uri, error);
if (f)
{
pixbuf = rsvg_pixbuf_from_stdio_file_with_size_data(f, data,
base_uri, error);
g_byte_array_free (f, TRUE);
}
else
{
pixbuf = NULL;
}
g_free(base_uri);
return pixbuf;
}
/**
* rsvg_pixbuf_from_file:
* @file_name: A file name
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. The caller must
* assume the reference to the reurned pixbuf. If an error occurred, @error is
* set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file (const gchar *file_name,
GError **error)
{
return rsvg_pixbuf_from_file_at_size (file_name, -1, -1, error);
}
/**
* rsvg_pixbuf_from_file_at_zoom:
* @file_name: A file name
* @x_zoom: The horizontal zoom factor
* @y_zoom: The vertical zoom factor
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. This pixbuf is scaled
* from the size indicated by the file by a factor of @x_zoom and @y_zoom. The
* caller must assume the reference to the returned pixbuf. If an error
* occurred, @error is set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file_at_zoom (const gchar *file_name,
double x_zoom,
double y_zoom,
GError **error)
{
struct RsvgSizeCallbackData data;
g_return_val_if_fail (file_name != NULL, NULL);
g_return_val_if_fail (x_zoom > 0.0 && y_zoom > 0.0, NULL);
data.type = RSVG_SIZE_ZOOM;
data.x_zoom = x_zoom;
data.y_zoom = y_zoom;
data.keep_aspect_ratio = FALSE;
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}
/**
* rsvg_pixbuf_from_file_at_zoom_with_max:
* @file_name: A file name
* @x_zoom: The horizontal zoom factor
* @y_zoom: The vertical zoom factor
* @max_width: The requested max width
* @max_height: The requested max heigh
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. This pixbuf is scaled
* from the size indicated by the file by a factor of @x_zoom and @y_zoom. If the
* resulting pixbuf would be larger than max_width/max_heigh it is uniformly scaled
* down to fit in that rectangle. The caller must assume the reference to the
* returned pixbuf. If an error occurred, @error is set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file_at_zoom_with_max (const gchar *file_name,
double x_zoom,
double y_zoom,
gint max_width,
gint max_height,
GError **error)
{
struct RsvgSizeCallbackData data;
g_return_val_if_fail (file_name != NULL, NULL);
g_return_val_if_fail (x_zoom > 0.0 && y_zoom > 0.0, NULL);
data.type = RSVG_SIZE_ZOOM_MAX;
data.x_zoom = x_zoom;
data.y_zoom = y_zoom;
data.width = max_width;
data.height = max_height;
data.keep_aspect_ratio = FALSE;
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}
/**
* rsvg_pixbuf_from_file_at_size:
* @file_name: A file name
* @width: The new width, or -1
* @height: The new height, or -1
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. This pixbuf is scaled
* from the size indicated to the new size indicated by @width and @height. If
* either of these are -1, then the default size of the image being loaded is
* used. The caller must assume the reference to the returned pixbuf. If an
* error occurred, @error is set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file_at_size (const gchar *file_name,
gint width,
gint height,
GError **error)
{
struct RsvgSizeCallbackData data;
data.type = RSVG_SIZE_WH;
data.width = width;
data.height = height;
data.keep_aspect_ratio = FALSE;
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}
/**
* rsvg_pixbuf_from_file_at_max_size:
* @file_name: A file name
* @max_width: The requested max width
* @max_height: The requested max heigh
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. This pixbuf is uniformly
* scaled so that the it fits into a rectangle of size max_width * max_height. The
* caller must assume the reference to the returned pixbuf. If an error occurred,
* @error is set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file_at_max_size (const gchar *file_name,
gint max_width,
gint max_height,
GError **error)
{
struct RsvgSizeCallbackData data;
data.type = RSVG_SIZE_WH_MAX;
data.width = max_width;
data.height = max_height;
data.keep_aspect_ratio = FALSE;
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}
......@@ -1011,7 +1011,7 @@ rsvg_handle_new (void)
}
RsvgDimensionData
rsvg_get_dimensions(RsvgHandle * handle)
rsvg_handle_get_dimensions(RsvgHandle * handle)
{
RsvgDimensionData output;
RsvgNodeSvg * sself;
......
......@@ -42,7 +42,7 @@ _pattern_add_rsvg_color_stops (cairo_pattern_t *pattern,
guint32 current_color_rgb,
guint8 opacity)
{
int i;
gsize i;
RsvgGradientStop *stop;
RsvgNode *node;
guint32 rgba;
......@@ -135,7 +135,7 @@ _set_source_rsvg_pattern (cairo_t *cr,
}
static void
_set_source_rvsg_paint_server (cairo_t *cr,
_set_source_rsvg_paint_server (cairo_t *cr,
guint32 current_color_rgb,
RsvgPaintServer *ps,
guint8 opacity)
......@@ -224,10 +224,10 @@ rsvg_cairo_render_path (RsvgDrawingCtx *ctx, const RsvgBpathDef *bpath_def)
}
if (state->stroke != NULL) {
_set_source_paint_server (cr,
state->current_color,
state->stroke,
state->stroke_opacity);
_set_source_rsvg_paint_server (cr,
state->current_color,
state->stroke,
state->stroke_opacity);
cairo_stroke (cr);
}
......
......@@ -27,335 +27,47 @@
#include "rsvg.h"
#include "rsvg-private.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define SVG_BUFFER_SIZE (1024 * 8)
static void
rsvg_size_callback (int *width,
int *height,
gpointer data)
{
struct RsvgSizeCallbackData *real_data = (struct RsvgSizeCallbackData *) data;
double zoomx, zoomy, zoom;
int in_width, in_height;
in_width = *width;
in_height = *height;
switch (real_data->type) {
case RSVG_SIZE_ZOOM:
if (*width < 0 || *height < 0)
return;
*width = floor (real_data->x_zoom * *width + 0.5);
*height = floor (real_data->y_zoom * *height + 0.5);
break;
case RSVG_SIZE_ZOOM_MAX:
if (*width < 0 || *height < 0)
return;
*width = floor (real_data->x_zoom * *width + 0.5);
*height = floor (real_data->y_zoom * *height + 0.5);
if (*width > real_data->width || *height > real_data->height)
{
zoomx = (double) real_data->width / *width;
zoomy = (double) real_data->height / *height;
zoom = MIN (zoomx, zoomy);
*width = floor (zoom * *width + 0.5);
*height = floor (zoom * *height + 0.5);
}
break;
case RSVG_SIZE_WH_MAX:
if (*width < 0 || *height < 0)
return;
zoomx = (double) real_data->width / *width;
zoomy = (double) real_data->height / *height;
if (zoomx < 0)
zoom = zoomy;
else if (zoomy < 0)
zoom = zoomx;
else
zoom = MIN (zoomx, zoomy);
*width = floor (zoom * *width + 0.5);
*height = floor (zoom * *height + 0.5);
break;
case RSVG_SIZE_WH:
if (real_data->width != -1)
*width = real_data->width;
if (real_data->height != -1)
*height = real_data->height;
break;
default:
g_assert_not_reached ();
}
if (real_data->keep_aspect_ratio)
{
int out_min = MIN(*width, *height);
if (out_min == *width)
{
*height = in_height * ((double)*width / (double)in_width);
}
else
{
*width = in_width * ((double)*height / (double)in_height);
}
}
}
/* private */
GdkPixbuf *
rsvg_pixbuf_from_data_with_size_data (const guchar * buff,
size_t len,
struct RsvgSizeCallbackData * data,
const char * base_uri,
GError ** error)
{
RsvgHandle * handle;
GdkPixbuf * retval;
handle = rsvg_handle_new ();
if (!handle) {
g_set_error (error, rsvg_error_quark (), 0,
_("Error creating SVG reader"));
return NULL;
}
rsvg_handle_set_size_callback (handle, rsvg_size_callback, data, NULL);
rsvg_handle_set_base_uri (handle, base_uri);
rsvg_handle_write (handle, buff, len, error);
rsvg_handle_close (handle, error);
retval = rsvg_handle_get_pixbuf (handle);
rsvg_handle_free (handle);
return retval;
}
static GdkPixbuf *
rsvg_pixbuf_from_stdio_file_with_size_data(GByteArray *f,
struct RsvgSizeCallbackData * data,
gchar *base_uri,
GError ** error)
RsvgHandle * rsvg_handle_new_from_data (const guint8 *data,
gsize data_len,
GError **error)
{
RsvgHandle * handle;
GdkPixbuf * retval;
handle = rsvg_handle_new ();
if (!handle) {
g_set_error (error, rsvg_error_quark (), 0,
_("Error creating SVG reader"));
return NULL;
RsvgHandle * handle = rsvg_handle_new ();
if(!handle) {
}
else if(!rsvg_handle_write (handle, data, data_len, error)) {
rsvg_handle_free(handle);
handle = NULL;
} else {
rsvg_handle_close(handle, error);
}
rsvg_handle_set_size_callback (handle, rsvg_size_callback, data, NULL);
rsvg_handle_set_base_uri(handle, base_uri);
rsvg_handle_write (handle, f->data, f->len, error);
rsvg_handle_close (handle, error);
retval = rsvg_handle_get_pixbuf (handle);
rsvg_handle_free (handle);
return retval;
return handle;
}
static GdkPixbuf *
rsvg_pixbuf_from_file_with_size_data (const gchar * file_name,
struct RsvgSizeCallbackData * data,
GError ** error)
RsvgHandle * rsvg_handle_new_from_file (const gchar *file_name,
GError **error)
{
GdkPixbuf * pixbuf;
gchar * base_uri;
GByteArray *f;
RsvgHandle * handle;
base_uri = rsvg_get_base_uri_from_filename(file_name);
f = _rsvg_acquire_xlink_href_resource (file_name, base_uri, error);
if (f)
{
pixbuf = rsvg_pixbuf_from_stdio_file_with_size_data(f, data,
base_uri, error);
handle = rsvg_handle_new_from_data (f->data, f->len, error);
if (handle)
rsvg_handle_set_base_uri (handle, base_uri);
g_byte_array_free (f, TRUE);
}
else
{
pixbuf = NULL;
handle = NULL;
}
g_free(base_uri);
return pixbuf;
}
/**
* rsvg_pixbuf_from_file:
* @file_name: A file name
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. The caller must
* assume the reference to the reurned pixbuf. If an error occurred, @error is
* set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file (const gchar *file_name,
GError **error)
{
return rsvg_pixbuf_from_file_at_size (file_name, -1, -1, error);
}
/**
* rsvg_pixbuf_from_file_at_zoom:
* @file_name: A file name
* @x_zoom: The horizontal zoom factor
* @y_zoom: The vertical zoom factor
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. This pixbuf is scaled
* from the size indicated by the file by a factor of @x_zoom and @y_zoom. The
* caller must assume the reference to the returned pixbuf. If an error
* occurred, @error is set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file_at_zoom (const gchar *file_name,
double x_zoom,
double y_zoom,
GError **error)
{
struct RsvgSizeCallbackData data;
g_return_val_if_fail (file_name != NULL, NULL);
g_return_val_if_fail (x_zoom > 0.0 && y_zoom > 0.0, NULL);
data.type = RSVG_SIZE_ZOOM;
data.x_zoom = x_zoom;
data.y_zoom = y_zoom;
data.keep_aspect_ratio = FALSE;
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}
/**
* rsvg_pixbuf_from_file_at_zoom_with_max:
* @file_name: A file name
* @x_zoom: The horizontal zoom factor
* @y_zoom: The vertical zoom factor
* @max_width: The requested max width
* @max_height: The requested max heigh
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. This pixbuf is scaled
* from the size indicated by the file by a factor of @x_zoom and @y_zoom. If the
* resulting pixbuf would be larger than max_width/max_heigh it is uniformly scaled
* down to fit in that rectangle. The caller must assume the reference to the
* returned pixbuf. If an error occurred, @error is set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file_at_zoom_with_max (const gchar *file_name,
double x_zoom,
double y_zoom,
gint max_width,
gint max_height,
GError **error)
{
struct RsvgSizeCallbackData data;
g_return_val_if_fail (file_name != NULL, NULL);
g_return_val_if_fail (x_zoom > 0.0 && y_zoom > 0.0, NULL);
data.type = RSVG_SIZE_ZOOM_MAX;
data.x_zoom = x_zoom;
data.y_zoom = y_zoom;
data.width = max_width;
data.height = max_height;
data.keep_aspect_ratio = FALSE;
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}
/**
* rsvg_pixbuf_from_file_at_size:
* @file_name: A file name
* @width: The new width, or -1
* @height: The new height, or -1
* @error: return location for errors
*
* Loads a new #GdkPixbuf from @file_name and returns it. This pixbuf is scaled
* from the size indicated to the new size indicated by @width and @height. If
* either of these are -1, then the default size of the image being loaded is
* used. The caller must assume the reference to the returned pixbuf. If an
* error occurred, @error is set and %NULL is returned.
*
* Return value: A newly allocated #GdkPixbuf, or %NULL
**/
GdkPixbuf *
rsvg_pixbuf_from_file_at_size (const gchar *file_name,
gint width,
gint height,
GError **error)
{
struct RsvgSizeCallbackData data;
data.type = RSVG_SIZE_WH;
data.width = width;
data.height = height;
data.keep_aspect_ratio = FALSE;
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}