Commit 8c7f0d73 authored by Caleb Michael Moore's avatar Caleb Michael Moore

made images abstract

parent be57dd13
......@@ -27,6 +27,7 @@
Caleb Moore <c.moore@student.unsw.edu.au>
*/
#include <string.h>
#include <math.h>
#include "rsvg-art-composite.h"
#include "rsvg-art-render.h"
......@@ -36,6 +37,8 @@
#include "rsvg-mask.h"
#include <libart_lgpl/art_rgba.h>
#include <libart_lgpl/art_affine.h>
#include <libart_lgpl/art_rgb_svp.h>
static void
rsvg_pixmap_destroy (gchar *pixels, gpointer data)
......@@ -340,8 +343,8 @@ rsvg_art_needs_discrete_layer(RsvgState *state)
}
void
rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
gint srcheight, GdkPixbuf * dst, gint dstx, gint dsty)
rsvg_art_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
gint srcheight, GdkPixbuf * dst, gint dstx, gint dsty)
{
gint rightx;
gint bottomy;
......@@ -434,3 +437,139 @@ rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
}
}
}
void
rsvg_art_affine_image(GdkPixbuf *img, GdkPixbuf *intermediate,
double * affine, double w, double h)
{
gdouble tmp_affine[6];
gdouble inv_affine[6];
gdouble raw_inv_affine[6];
gint intstride;
gint basestride;
gint basex, basey;
gdouble fbasex, fbasey;
gdouble rawx, rawy;
guchar * intpix;
guchar * basepix;
gint i, j, k, basebpp, ii, jj;
gboolean has_alpha;
gdouble pixsum[4];
gboolean xrunnoff, yrunnoff;
gint iwidth, iheight;
gint width, height;
width = gdk_pixbuf_get_width (img);
height = gdk_pixbuf_get_height (img);
iwidth = gdk_pixbuf_get_width (intermediate);
iheight = gdk_pixbuf_get_height (intermediate);
has_alpha = gdk_pixbuf_get_has_alpha (img);
basestride = gdk_pixbuf_get_rowstride (img);
intstride = gdk_pixbuf_get_rowstride (intermediate);
basepix = gdk_pixbuf_get_pixels (img);
intpix = gdk_pixbuf_get_pixels (intermediate);
basebpp = has_alpha ? 4 : 3;
art_affine_invert(raw_inv_affine, affine);
/*scale to w and h*/
tmp_affine[0] = (double)w;
tmp_affine[3] = (double)h;
tmp_affine[1] = tmp_affine[2] = tmp_affine[4] = tmp_affine[5] = 0;
art_affine_multiply(tmp_affine, tmp_affine, affine);
art_affine_invert(inv_affine, tmp_affine);
/*apply the transformation*/
for (i = 0; i < iwidth; i++)
for (j = 0; j < iheight; j++)
{
fbasex = (inv_affine[0] * (double)i + inv_affine[2] * (double)j +
inv_affine[4]) * (double)width;
fbasey = (inv_affine[1] * (double)i + inv_affine[3] * (double)j +
inv_affine[5]) * (double)height;
basex = floor(fbasex);
basey = floor(fbasey);
rawx = raw_inv_affine[0] * i + raw_inv_affine[2] * j +
raw_inv_affine[4];
rawy = raw_inv_affine[1] * i + raw_inv_affine[3] * j +
raw_inv_affine[5];
if (rawx < 0 || rawy < 0 || rawx >= w ||
rawy >= h || basex < 0 || basey < 0
|| basex >= width || basey >= height)
{
for (k = 0; k < 4; k++)
intpix[i * 4 + j * intstride + k] = 0;
}
else
{
if (basex < 0 || basex + 1 >= width)
xrunnoff = TRUE;
else
xrunnoff = FALSE;
if (basey < 0 || basey + 1 >= height)
yrunnoff = TRUE;
else
yrunnoff = FALSE;
for (k = 0; k < basebpp; k++)
pixsum[k] = 0;
for (ii = 0; ii < 2; ii++)
for (jj = 0; jj < 2; jj++)
{
if (basex + ii < 0 || basey + jj< 0
|| basex + ii >= width || basey + jj >= height)
;
else
{
for (k = 0; k < basebpp; k++)
{
pixsum[k] +=
(double)basepix[basebpp * (basex + ii) + (basey + jj) * basestride + k]
* (xrunnoff ? 1 : fabs(fbasex - (double)(basex + (1 - ii))))
* (yrunnoff ? 1 : fabs(fbasey - (double)(basey + (1 - jj))));
}
}
}
for (k = 0; k < basebpp; k++)
intpix[i * 4 + j * intstride + k] = pixsum[k];
if (!has_alpha)
intpix[i * 4 + j * intstride + 3] = 255;
}
}
}
void
rsvg_art_clip_image(GdkPixbuf *intermediate, ArtSVP *path)
{
gint intstride;
gint basestride;
guchar * intpix;
guchar * basepix;
gint i, j;
gint width, height;
GdkPixbuf * base;
width = gdk_pixbuf_get_width (intermediate);
height = gdk_pixbuf_get_height (intermediate);
intstride = gdk_pixbuf_get_rowstride (intermediate);
intpix = gdk_pixbuf_get_pixels (intermediate);
base = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8,
width, height);
basestride = gdk_pixbuf_get_rowstride (base);
basepix = gdk_pixbuf_get_pixels (base);
art_rgb_svp_aa(path, 0, 0, width, height, 0xFFFFFF, 0x000000, basepix, basestride, NULL);
for (i = 0; i < width; i++)
for (j = 0; j < height; j++)
{
intpix[i * 4 + j * intstride + 3] = intpix[i * 4 + j * intstride + 3] *
basepix[i * 3 + j * basestride] / 255;
}
}
......@@ -38,9 +38,12 @@ void rsvg_art_pop_discrete_layer(RsvgDrawingCtx *ctx);
void rsvg_art_push_discrete_layer (RsvgDrawingCtx *ctx);
gboolean rsvg_art_needs_discrete_layer(RsvgState *state);
void
rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
gint srcheight, GdkPixbuf * dst, gint dstx, gint dsty);
void rsvg_art_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy,
gint srcwidth, gint srcheight,
GdkPixbuf * dst, gint dstx, gint dsty);
void rsvg_art_clip_image (GdkPixbuf *intermediate, ArtSVP *path);
void rsvg_art_affine_image(GdkPixbuf *img, GdkPixbuf *intermediate,
double * affine, double w, double h);
G_END_DECLS
......
......@@ -537,3 +537,66 @@ rsvg_art_svp_render_path (RsvgDrawingCtx *ctx, const char *d)
rsvg_bpath_def_free (bpath_def);
}
void rsvg_art_render_image (RsvgDrawingCtx *ctx, GdkPixbuf * img,
double x, double y, double w, double h)
{
int i, j;
double tmp_affine[6];
double tmp_tmp_affine[6];
RsvgState *state = rsvg_state_current(ctx);
GdkPixbuf *intermediate;
double basex, basey;
ArtIRect temprect;
/*this will have to change*/
GdkPixbuf * pixbuf = ((RsvgArtRender *)ctx->render)->pixbuf;
for (i = 0; i < 6; i++)
tmp_affine[i] = state->affine[i];
/*translate to x and y*/
tmp_tmp_affine[0] = tmp_tmp_affine[3] = 1;
tmp_tmp_affine[1] = tmp_tmp_affine[2] = 0;
tmp_tmp_affine[4] = x;
tmp_tmp_affine[5] = y;
art_affine_multiply(tmp_affine, tmp_tmp_affine, tmp_affine);
intermediate = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
rsvg_art_affine_image(img, intermediate, tmp_affine, w, h);
if (state->clippath)
{
rsvg_art_clip_image(intermediate, state->clippath);
}
/*slap it down*/
rsvg_art_alpha_blt (intermediate, 0, 0,
gdk_pixbuf_get_width (intermediate),
gdk_pixbuf_get_height (intermediate),
pixbuf,
0, 0);
temprect.x0 = gdk_pixbuf_get_width (intermediate);
temprect.y0 = gdk_pixbuf_get_height (intermediate);
temprect.x1 = 0;
temprect.y1 = 0;
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
{
basex = tmp_affine[0] * w * i + tmp_affine[2] * h * j + tmp_affine[4];
basey = tmp_affine[1] * w * i + tmp_affine[3] * h * j + tmp_affine[5];
temprect.x0 = MIN(basex, temprect.x0);
temprect.y0 = MIN(basey, temprect.y0);
temprect.x1 = MAX(basex, temprect.x1);
temprect.y1 = MAX(basey, temprect.y1);
}
art_irect_union(&ctx->bbox, &ctx->bbox, &temprect);
g_object_unref (G_OBJECT (intermediate));
}
......@@ -33,6 +33,8 @@ G_BEGIN_DECLS
void rsvg_art_render_path (RsvgDrawingCtx *ctx, const char *d);
void rsvg_art_svp_render_path (RsvgDrawingCtx *ctx, const char *d);
void rsvg_art_render_image (RsvgDrawingCtx *ctx, GdkPixbuf * img,
double x, double y, double w, double h);
G_END_DECLS
......
......@@ -32,6 +32,7 @@ RsvgArtRender * rsvg_art_render_new(GdkPixbuf * pb)
output = g_new(RsvgArtRender, 1);
output->super.render_path = rsvg_art_render_path;
output->super.render_image = rsvg_art_render_image;
output->super.pop_discrete_layer = rsvg_art_pop_discrete_layer;
output->super.push_discrete_layer = rsvg_art_push_discrete_layer;
......@@ -44,6 +45,12 @@ static void
bogus(RsvgDrawingCtx *ctx)
{
}
static void
image_bogus(RsvgDrawingCtx *ctx, GdkPixbuf *pb,
double x, double y, double w, double h)
{
}
RsvgArtSVPRender * rsvg_art_svp_render_new()
{
......@@ -51,6 +58,7 @@ RsvgArtSVPRender * rsvg_art_svp_render_new()
output = g_new(RsvgArtSVPRender, 1);
output->super.render_path = rsvg_art_svp_render_path;
output->super.render_image = image_bogus;
output->super.pop_discrete_layer = bogus;
output->super.push_discrete_layer = bogus;
......
......@@ -33,14 +33,12 @@
#include <math.h>
#include <rsvg-art-render.h>
#include <rsvg-art-composite.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */
/* probably poor form, but it saves us from whacking it in the header file */
void rsvg_clip_image(GdkPixbuf *intermediate, ArtSVP *path);
#define PERFECTBLUR 0
/*************************************************************/
......@@ -341,9 +339,9 @@ rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source, GdkPixbuf * output,
bounds = rsvg_filter_primitive_get_bounds (NULL, ctx);
if (rsvg_state_current (context)->clippath)
rsvg_clip_image(ctx->lastresult.result, rsvg_state_current (context)->clippath);
rsvg_art_clip_image(ctx->lastresult.result, rsvg_state_current (context)->clippath);
rsvg_alpha_blt (ctx->lastresult.result, bounds.x1, bounds.y1, bounds.x2 - bounds.x1,
rsvg_art_alpha_blt (ctx->lastresult.result, bounds.x1, bounds.y1, bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1, output, bounds.x1, bounds.y1);
context->bbox.x0 = bounds.x1;
context->bbox.y0 = bounds.y1;
......@@ -1969,9 +1967,9 @@ rsvg_filter_primitive_merge_render (RsvgFilterPrimitive * self,
for (i = 0; i < mself->nodes->len; i++)
{
in = rsvg_filter_get_in (g_ptr_array_index (mself->nodes, i), ctx);
rsvg_alpha_blt (in, boundarys.x1, boundarys.y1, boundarys.x2 - boundarys.x1,
boundarys.y2 - boundarys.y1, output, boundarys.x1,
boundarys.y1);
rsvg_art_alpha_blt (in, boundarys.x1, boundarys.y1, boundarys.x2 - boundarys.x1,
boundarys.y2 - boundarys.y1, output, boundarys.x1,
boundarys.y1);
g_object_unref (G_OBJECT (in));
}
......@@ -3992,11 +3990,11 @@ rsvg_filter_primitive_image_render_ext (RsvgFilterPrimitive * self,
intermediate = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8, boundarys.x2 - boundarys.x1,
boundarys.y2 - boundarys.y1);
rsvg_affine_image(img, intermediate,
ctx->paffine,
(boundarys.x2 - boundarys.x1) / ctx->paffine[0],
(boundarys.y2 - boundarys.y1) / ctx->paffine[3]);
rsvg_art_affine_image(img, intermediate,
ctx->paffine,
(boundarys.x2 - boundarys.x1) / ctx->paffine[0],
(boundarys.y2 - boundarys.y1) / ctx->paffine[3]);
if (!intermediate)
{
g_object_unref (G_OBJECT (img));
......
......@@ -120,10 +120,6 @@ void
rsvg_filter_adobe_blend(gint modenum, GdkPixbuf *in, GdkPixbuf *bg, GdkPixbuf *output,
RsvgDrawingCtx * ctx);
void
rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
gint srcheight, GdkPixbuf * dst, gint dstx, gint dsty);
G_END_DECLS
#endif
......@@ -443,144 +443,6 @@ rsvg_pixbuf_new_from_href (const char *href,
return NULL;
}
void
rsvg_affine_image(GdkPixbuf *img, GdkPixbuf *intermediate,
double * affine, double w, double h)
{
gdouble tmp_affine[6];
gdouble inv_affine[6];
gdouble raw_inv_affine[6];
gint intstride;
gint basestride;
gint basex, basey;
gdouble fbasex, fbasey;
gdouble rawx, rawy;
guchar * intpix;
guchar * basepix;
gint i, j, k, basebpp, ii, jj;
gboolean has_alpha;
gdouble pixsum[4];
gboolean xrunnoff, yrunnoff;
gint iwidth, iheight;
gint width, height;
width = gdk_pixbuf_get_width (img);
height = gdk_pixbuf_get_height (img);
iwidth = gdk_pixbuf_get_width (intermediate);
iheight = gdk_pixbuf_get_height (intermediate);
has_alpha = gdk_pixbuf_get_has_alpha (img);
basestride = gdk_pixbuf_get_rowstride (img);
intstride = gdk_pixbuf_get_rowstride (intermediate);
basepix = gdk_pixbuf_get_pixels (img);
intpix = gdk_pixbuf_get_pixels (intermediate);
basebpp = has_alpha ? 4 : 3;
art_affine_invert(raw_inv_affine, affine);
/*scale to w and h*/
tmp_affine[0] = (double)w;
tmp_affine[3] = (double)h;
tmp_affine[1] = tmp_affine[2] = tmp_affine[4] = tmp_affine[5] = 0;
art_affine_multiply(tmp_affine, tmp_affine, affine);
art_affine_invert(inv_affine, tmp_affine);
/*apply the transformation*/
for (i = 0; i < iwidth; i++)
for (j = 0; j < iheight; j++)
{
fbasex = (inv_affine[0] * (double)i + inv_affine[2] * (double)j +
inv_affine[4]) * (double)width;
fbasey = (inv_affine[1] * (double)i + inv_affine[3] * (double)j +
inv_affine[5]) * (double)height;
basex = floor(fbasex);
basey = floor(fbasey);
rawx = raw_inv_affine[0] * i + raw_inv_affine[2] * j +
raw_inv_affine[4];
rawy = raw_inv_affine[1] * i + raw_inv_affine[3] * j +
raw_inv_affine[5];
if (rawx < 0 || rawy < 0 || rawx >= w ||
rawy >= h || basex < 0 || basey < 0
|| basex >= width || basey >= height)
{
for (k = 0; k < 4; k++)
intpix[i * 4 + j * intstride + k] = 0;
}
else
{
if (basex < 0 || basex + 1 >= width)
xrunnoff = TRUE;
else
xrunnoff = FALSE;
if (basey < 0 || basey + 1 >= height)
yrunnoff = TRUE;
else
yrunnoff = FALSE;
for (k = 0; k < basebpp; k++)
pixsum[k] = 0;
for (ii = 0; ii < 2; ii++)
for (jj = 0; jj < 2; jj++)
{
if (basex + ii < 0 || basey + jj< 0
|| basex + ii >= width || basey + jj >= height)
;
else
{
for (k = 0; k < basebpp; k++)
{
pixsum[k] +=
(double)basepix[basebpp * (basex + ii) + (basey + jj) * basestride + k]
* (xrunnoff ? 1 : fabs(fbasex - (double)(basex + (1 - ii))))
* (yrunnoff ? 1 : fabs(fbasey - (double)(basey + (1 - jj))));
}
}
}
for (k = 0; k < basebpp; k++)
intpix[i * 4 + j * intstride + k] = pixsum[k];
if (!has_alpha)
intpix[i * 4 + j * intstride + 3] = 255;
}
}
}
void rsvg_clip_image(GdkPixbuf *intermediate, ArtSVP *path);
void
rsvg_clip_image(GdkPixbuf *intermediate, ArtSVP *path)
{
gint intstride;
gint basestride;
guchar * intpix;
guchar * basepix;
gint i, j;
gint width, height;
GdkPixbuf * base;
width = gdk_pixbuf_get_width (intermediate);
height = gdk_pixbuf_get_height (intermediate);
intstride = gdk_pixbuf_get_rowstride (intermediate);
intpix = gdk_pixbuf_get_pixels (intermediate);
base = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8,
width, height);
basestride = gdk_pixbuf_get_rowstride (base);
basepix = gdk_pixbuf_get_pixels (base);
art_rgb_svp_aa(path, 0, 0, width, height, 0xFFFFFF, 0x000000, basepix, basestride, NULL);
for (i = 0; i < width; i++)
for (j = 0; j < height; j++)
{
intpix[i * 4 + j * intstride + 3] = intpix[i * 4 + j * intstride + 3] *
basepix[i * 3 + j * basestride] / 255;
}
}
void
rsvg_preserve_aspect_ratio(unsigned int aspect_ratio, double width,
double height, double * w, double * h,
......@@ -646,23 +508,13 @@ rsvg_defs_drawable_image_draw (RsvgDefsDrawable * self, RsvgDrawingCtx *ctx,
RsvgDefsDrawableImage *z = (RsvgDefsDrawableImage *)self;
double x = z->x, y = z->y, w = z->w, h = z->h;
unsigned int aspect_ratio = z->preserve_aspect_ratio;
ArtIRect temprect;
GdkPixbuf *img = z->img;
int i, j;
double tmp_affine[6];
double tmp_tmp_affine[6];
RsvgState *state = rsvg_state_current(ctx);
GdkPixbuf *intermediate;
double basex, basey;
ArtSVP * temppath;
/*this will have to change*/
GdkPixbuf * pixbuf = ((RsvgArtRender *)ctx->render)->pixbuf;
rsvg_state_reinherit_top(ctx, &self->state, dominate);
for (i = 0; i < 6; i++)
tmp_affine[i] = state->affine[i];
if (!z->overflow && (aspect_ratio & RSVG_ASPECT_RATIO_SLICE)){
temppath = rsvg_rect_clip_path(x, y, w, h, ctx);
state->clip_path_loaded = TRUE;
......@@ -674,60 +526,11 @@ rsvg_defs_drawable_image_draw (RsvgDefsDrawable * self, RsvgDrawingCtx *ctx,
(double)gdk_pixbuf_get_height(img), &w, &h,
&x, &y);
/*translate to x and y*/
tmp_tmp_affine[0] = tmp_tmp_affine[3] = 1;
tmp_tmp_affine[1] = tmp_tmp_affine[2] = 0;
tmp_tmp_affine[4] = x;
tmp_tmp_affine[5] = y;
art_affine_multiply(tmp_affine, tmp_tmp_affine, tmp_affine);
intermediate = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
if (!intermediate)
{
g_object_unref (G_OBJECT (img));
return;
}
rsvg_affine_image(img, intermediate, tmp_affine, w, h);
rsvg_push_discrete_layer(ctx);
if (state->clippath)
{
rsvg_clip_image(intermediate, state->clippath);
}
rsvg_render_image(ctx, img, x, y, w, h);
/*slap it down*/
rsvg_alpha_blt (intermediate, 0, 0,
gdk_pixbuf_get_width (intermediate),
gdk_pixbuf_get_height (intermediate),
pixbuf,
0, 0);
temprect.x0 = gdk_pixbuf_get_width (intermediate);
temprect.y0 = gdk_pixbuf_get_height (intermediate);
temprect.x1 = 0;
temprect.y1 = 0;
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
{
basex = tmp_affine[0] * w * i + tmp_affine[2] * h * j + tmp_affine[4];
basey = tmp_affine[1] * w * i + tmp_affine[3] * h * j + tmp_affine[5];
temprect.x0 = MIN(basex, temprect.x0);
temprect.y0 = MIN(basey, temprect.y0);
temprect.x1 = MAX(basex, temprect.x1);
temprect.y1 = MAX(basey, temprect.y1);
}
art_irect_union(&ctx->bbox, &ctx->bbox, &temprect);
rsvg_pop_discrete_layer(ctx);
g_object_unref (G_OBJECT (intermediate));
}
void
......
......@@ -48,9 +48,6 @@ void rsvg_preserve_aspect_ratio(unsigned int aspect_ratio, double width,
double height, double * w, double * h,
double * x, double * y);
void
rsvg_affine_image(GdkPixbuf *img, GdkPixbuf *intermediate,
double * affine, double w, double h);
gchar *
rsvg_get_file_path (const gchar * filename, const gchar *basedir);
......
......@@ -145,6 +145,8 @@ struct RsvgDrawingCtx {
struct RsvgRender {
void (* render_path) (RsvgDrawingCtx *ctx, const char *d);
void (* render_image) (RsvgDrawingCtx *ctx, GdkPixbuf * pixbuf,
double x, double y, double w, double h);
void (* pop_discrete_layer) (RsvgDrawingCtx *ctx);
void (* push_discrete_layer) (RsvgDrawingCtx *ctx);
};
......@@ -240,6 +242,8 @@ _rsvg_acquire_xlink_href_resource (const char *href,
void rsvg_pop_discrete_layer(RsvgDrawingCtx *ctx);
void rsvg_push_discrete_layer (RsvgDrawingCtx *ctx);
void rsvg_render_path (RsvgDrawingCtx *ctx, const char *d);
void rsvg_render_image (RsvgDrawingCtx *ctx, GdkPixbuf * pb,
double x, double y, double w, double h);
G_END_DECLS
......
......@@ -1979,3 +1979,8 @@ void rsvg_render_path (RsvgDrawingCtx *ctx, const char *d)
{
ctx->render->render_path(ctx, d);
}
void rsvg_render_image (RsvgDrawingCtx *ctx, GdkPixbuf * pb,
double x, double y, double w, double h)
{
ctx->render->render_image(ctx, pb, x, y, w, h);
}
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