Commit c87ffa34 authored by Dom Lachowicz's avatar Dom Lachowicz

rendering images to cairo now largely works

parent 37189b7c
2005-08-07 Dom Lachowicz <cinamod@hotmail.com>
* rsvg-cairo-draw.c (rsvg_cairo_render_path): Implement line join, cap, width, dash, miter limit
* rsvg-cairo-draw.c (rsvg_cairo_render_image): Drawing images now largely works
2005-08-04 Carl Worth <cworth@cworth.org>
......
......@@ -431,7 +431,7 @@ rsvg_art_add_clipping_rect(RsvgDrawingCtx *ctx, double x, double y, double w, do
data->clippath_loaded = FALSE;
}
void *
GdkPixbuf *
rsvg_art_get_image_of_node(RsvgDrawingCtx *ctx, RsvgNode * drawable,
double w, double h)
{
......
......@@ -41,7 +41,7 @@ gboolean rsvg_art_needs_discrete_layer(RsvgState *state);
void rsvg_art_clip_image (GdkPixbuf *intermediate, ArtSVP *path);
void rsvg_art_add_clipping_rect(RsvgDrawingCtx *ctx, double x, double y, double w, double h);
void * rsvg_art_get_image_of_node(RsvgDrawingCtx *ctx, RsvgNode * drawable, double w, double h);
GdkPixbuf * rsvg_art_get_image_of_node(RsvgDrawingCtx *ctx, RsvgNode * drawable, double w, double h);
G_END_DECLS
......
......@@ -1340,7 +1340,7 @@ rsvg_add_clipping_rect (RsvgDrawingCtx *ctx, double x, double y, double w, doubl
ctx->render->add_clipping_rect(ctx, x, y, w, h);
}
void * rsvg_get_image_of_node(RsvgDrawingCtx *ctx, RsvgNode * drawable,
GdkPixbuf * rsvg_get_image_of_node(RsvgDrawingCtx *ctx, RsvgNode * drawable,
double w, double h)
{
return ctx->render->get_image_of_node(ctx, drawable, w, h);
......
......@@ -242,30 +242,100 @@ rsvg_cairo_render_path (RsvgDrawingCtx *ctx, const RsvgBpathDef *bpath_def)
cairo_restore (cr);
}
void rsvg_cairo_render_image (RsvgDrawingCtx *ctx, const GdkPixbuf * img,
double x, double y, double w, double h)
void rsvg_cairo_render_image (RsvgDrawingCtx *ctx, const GdkPixbuf * pixbuf,
double pixbuf_x, double pixbuf_y, double w, double h)
{
/* XXX: Untested */
RsvgCairoRender *render = (RsvgCairoRender *)ctx->render;
RsvgState *state = rsvg_state_current(ctx);
cairo_surface_t * surface;
unsigned char * data = gdk_pixbuf_get_pixels(img);
cairo_save (render->cr);
gint width = gdk_pixbuf_get_width (pixbuf);
gint height = gdk_pixbuf_get_height (pixbuf);
guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
guchar *cairo_pixels;
cairo_format_t format;
cairo_surface_t *surface;
static const cairo_user_data_key_t key;
int j;
surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24,
w, h, w * 4);
cairo_translate (render->cr, x, y);
/* XXX: This is not quite right... w & h aren't respected, but everything else seems to work ok */
cairo_set_source_surface (render->cr, surface, 0, 0);
if (state->opacity != 1.0)
cairo_paint_with_alpha (render->cr, state->opacity);
else
cairo_paint (render->cr);
cairo_surface_destroy (surface);
cairo_save (render->cr);
_set_rsvg_affine (render->cr, state->affine);
if (n_channels == 3)
format = CAIRO_FORMAT_RGB24;
else
format = CAIRO_FORMAT_ARGB32;
cairo_pixels = g_malloc (4 * width * height);
surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels,
format,
width, height, 4 * width);
cairo_surface_set_user_data (surface, &key,
cairo_pixels, (cairo_destroy_func_t)g_free);
for (j = height; j; j--)
{
guchar *p = gdk_pixels;
guchar *q = cairo_pixels;
if (n_channels == 3)
{
guchar *end = p + 3 * width;
while (p < end)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
q[0] = p[2];
q[1] = p[1];
q[2] = p[0];
#else
q[1] = p[0];
q[2] = p[1];
q[3] = p[2];
#endif
p += 3;
q += 4;
}
}
else
{
guchar *end = p + 4 * width;
guint t1,t2,t3;
#define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
while (p < end)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
MULT(q[0], p[2], p[3], t1);
MULT(q[1], p[1], p[3], t2);
MULT(q[2], p[0], p[3], t3);
q[3] = p[3];
#else
q[0] = p[3];
MULT(q[1], p[0], p[3], t1);
MULT(q[2], p[1], p[3], t2);
MULT(q[3], p[2], p[3], t3);
#endif
p += 4;
q += 4;
}
#undef MULT
}
gdk_pixels += gdk_rowstride;
cairo_pixels += 4 * width;
}
cairo_set_source_surface (render->cr, surface, pixbuf_x, pixbuf_y);
cairo_paint (render->cr);
cairo_surface_destroy (surface);
cairo_restore (render->cr);
}
......@@ -332,7 +402,7 @@ static cairo_status_t png_write_func(void * closure,
return CAIRO_STATUS_SUCCESS;
}
void *
GdkPixbuf *
rsvg_cairo_get_image_of_node (RsvgDrawingCtx *ctx,
RsvgNode *drawable,
double width,
......
......@@ -51,7 +51,7 @@ rsvg_cairo_add_clipping_rect (RsvgDrawingCtx *ctx,
double x, double y,
double width, double height);
void *
GdkPixbuf *
rsvg_cairo_get_image_of_node (RsvgDrawingCtx *ctx,
RsvgNode *drawable,
double width,
......
......@@ -148,8 +148,8 @@ struct RsvgRender {
void (* push_discrete_layer) (RsvgDrawingCtx *ctx);
void (* add_clipping_rect) (RsvgDrawingCtx *ctx,
double x, double y, double w, double h);
void * (* get_image_of_node) (RsvgDrawingCtx *ctx, RsvgNode * drawable,
double w, double h);
GdkPixbuf * (* get_image_of_node) (RsvgDrawingCtx *ctx, RsvgNode * drawable,
double w, double h);
};
struct _RsvgIRect {
......@@ -263,8 +263,8 @@ void rsvg_render_image (RsvgDrawingCtx *ctx, GdkPixbuf * pb,
void rsvg_render_free (RsvgRender * render);
void rsvg_add_clipping_rect (RsvgDrawingCtx *ctx, double x, double y,
double w, double h);
void * rsvg_get_image_of_node(RsvgDrawingCtx *ctx, RsvgNode * drawable,
double w, double h);
GdkPixbuf * rsvg_get_image_of_node(RsvgDrawingCtx *ctx, RsvgNode * drawable,
double w, double h);
void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment