~ubuntu-branches/ubuntu/trusty/librsvg/trusty-proposed

« back to all changes in this revision

Viewing changes to rsvg-filter.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl
  • Date: 2012-03-27 01:47:52 UTC
  • mfrom: (1.1.32) (34.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20120327014752-c9vmipiww40cnip7
Tags: 2.36.0-1
* New upstream release.
* Update debian/copyright using the machine-readable copyright format 1.0.
* Bump Standards-Version to 3.9.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include "rsvg-image.h"
32
32
#include "rsvg-css.h"
33
33
#include "rsvg-cairo-render.h"
 
34
 
34
35
#include <string.h>
35
36
 
36
37
#include <math.h>
42
43
typedef struct _RsvgFilterPrimitiveOutput RsvgFilterPrimitiveOutput;
43
44
 
44
45
struct _RsvgFilterPrimitiveOutput {
45
 
    GdkPixbuf *result;
 
46
    cairo_surface_t *surface;
46
47
    RsvgIRect bounds;
47
48
    gboolean Rused;
48
49
    gboolean Gused;
56
57
    gint width, height;
57
58
    RsvgFilter *filter;
58
59
    GHashTable *results;
59
 
    GdkPixbuf *source;
60
 
    GdkPixbuf *bg;
 
60
    cairo_surface_t *source_surface;
 
61
    cairo_surface_t *bg_surface;
61
62
    RsvgFilterPrimitiveOutput lastresult;
62
 
    double affine[6];
63
 
    double paffine[6];
 
63
    cairo_matrix_t affine;
 
64
    cairo_matrix_t paffine;
64
65
    int channelmap[4];
65
66
    RsvgDrawingCtx *ctx;
66
67
};
89
90
rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
90
91
{
91
92
    RsvgBbox box, otherbox;
92
 
    double affine[6];
 
93
    cairo_matrix_t affine;
93
94
 
94
 
    _rsvg_affine_identity (affine);
95
 
    rsvg_bbox_init (&box, affine);
96
 
    rsvg_bbox_init (&otherbox, ctx->affine);
 
95
    cairo_matrix_init_identity (&affine);
 
96
    rsvg_bbox_init (&box, &affine);
 
97
    rsvg_bbox_init (&otherbox, &ctx->affine);
97
98
    otherbox.virgin = 0;
98
99
    if (ctx->filter->filterunits == objectBoundingBox)
99
100
        _rsvg_push_view_box (ctx->ctx, 1., 1.);
100
 
    otherbox.x = _rsvg_css_normalize_length (&ctx->filter->x, ctx->ctx, 'h');
101
 
    otherbox.y = _rsvg_css_normalize_length (&ctx->filter->y, ctx->ctx, 'v');
102
 
    otherbox.w = _rsvg_css_normalize_length (&ctx->filter->width, ctx->ctx, 'h');
103
 
    otherbox.h = _rsvg_css_normalize_length (&ctx->filter->height, ctx->ctx, 'v');
 
101
    otherbox.rect.x = _rsvg_css_normalize_length (&ctx->filter->x, ctx->ctx, 'h');
 
102
    otherbox.rect.y = _rsvg_css_normalize_length (&ctx->filter->y, ctx->ctx, 'v');
 
103
    otherbox.rect.width = _rsvg_css_normalize_length (&ctx->filter->width, ctx->ctx, 'h');
 
104
    otherbox.rect.height = _rsvg_css_normalize_length (&ctx->filter->height, ctx->ctx, 'v');
104
105
    if (ctx->filter->filterunits == objectBoundingBox)
105
106
        _rsvg_pop_view_box (ctx->ctx);
106
107
 
110
111
        if (self->x.factor != 'n' || self->y.factor != 'n' ||
111
112
            self->width.factor != 'n' || self->height.factor != 'n') {
112
113
 
113
 
            rsvg_bbox_init (&otherbox, ctx->paffine);
 
114
            rsvg_bbox_init (&otherbox, &ctx->paffine);
114
115
            otherbox.virgin = 0;
115
116
            if (ctx->filter->primitiveunits == objectBoundingBox)
116
117
                _rsvg_push_view_box (ctx->ctx, 1., 1.);
117
118
            if (self->x.factor != 'n')
118
 
                otherbox.x = _rsvg_css_normalize_length (&self->x, ctx->ctx, 'h');
 
119
                otherbox.rect.x = _rsvg_css_normalize_length (&self->x, ctx->ctx, 'h');
119
120
            else
120
 
                otherbox.x = 0;
 
121
                otherbox.rect.x = 0;
121
122
            if (self->y.factor != 'n')
122
 
                otherbox.y = _rsvg_css_normalize_length (&self->y, ctx->ctx, 'v');
 
123
                otherbox.rect.y = _rsvg_css_normalize_length (&self->y, ctx->ctx, 'v');
123
124
            else
124
 
                otherbox.y = 0;
 
125
                otherbox.rect.y = 0;
125
126
            if (self->width.factor != 'n')
126
 
                otherbox.w = _rsvg_css_normalize_length (&self->width, ctx->ctx, 'h');
 
127
                otherbox.rect.width = _rsvg_css_normalize_length (&self->width, ctx->ctx, 'h');
127
128
            else
128
 
                otherbox.w = ctx->ctx->vb.w;
 
129
                otherbox.rect.width = ctx->ctx->vb.rect.width;
129
130
            if (self->height.factor != 'n')
130
 
                otherbox.h = _rsvg_css_normalize_length (&self->height, ctx->ctx, 'v');
 
131
                otherbox.rect.height = _rsvg_css_normalize_length (&self->height, ctx->ctx, 'v');
131
132
            else
132
 
                otherbox.h = ctx->ctx->vb.h;
 
133
                otherbox.rect.height = ctx->ctx->vb.rect.height;
133
134
            if (ctx->filter->primitiveunits == objectBoundingBox)
134
135
                _rsvg_pop_view_box (ctx->ctx);
135
136
            rsvg_bbox_clip (&box, &otherbox);
136
137
        }
137
138
 
138
 
    rsvg_bbox_init (&otherbox, affine);
 
139
    rsvg_bbox_init (&otherbox, &affine);
139
140
    otherbox.virgin = 0;
140
 
    otherbox.x = 0;
141
 
    otherbox.y = 0;
142
 
    otherbox.w = ctx->width;
143
 
    otherbox.h = ctx->height;
 
141
    otherbox.rect.x = 0;
 
142
    otherbox.rect.y = 0;
 
143
    otherbox.rect.width = ctx->width;
 
144
    otherbox.rect.height = ctx->height;
144
145
    rsvg_bbox_clip (&box, &otherbox);
145
146
    {
146
 
        RsvgIRect output = { box.x, box.y,
147
 
            box.x + box.w,
148
 
            box.y + box.h
 
147
        RsvgIRect output = { box.rect.x, box.rect.y,
 
148
            box.rect.x + box.rect.width,
 
149
            box.rect.y + box.rect.height
149
150
        };
150
151
        return output;
151
152
    }
152
153
}
153
154
 
154
 
GdkPixbuf *
155
 
_rsvg_pixbuf_new_cleared (GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample,
156
 
                          int width, int height)
 
155
static cairo_surface_t *
 
156
_rsvg_image_surface_new (int width, int height)
157
157
{
158
 
    GdkPixbuf *pb;
159
 
    guchar *data;
160
 
 
161
 
    pb = gdk_pixbuf_new (colorspace, has_alpha, bits_per_sample, width, height);
162
 
    data = gdk_pixbuf_get_pixels (pb);
163
 
    memset (data, 0, width * height * 4);
164
 
 
165
 
    return pb;
 
158
    cairo_surface_t *surface;
 
159
 
 
160
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
 
161
    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
 
162
      cairo_surface_destroy (surface);
 
163
      return NULL;
 
164
    }
 
165
 
 
166
    return surface;
166
167
}
167
168
 
168
169
static guchar
169
 
gdk_pixbuf_get_interp_pixel (guchar * src, gdouble ox, gdouble oy, guchar ch, RsvgIRect boundarys,
 
170
get_interp_pixel (guchar * src, gdouble ox, gdouble oy, guchar ch, RsvgIRect boundarys,
170
171
                             guint rowstride)
171
172
{
172
173
    double xmod, ymod;
173
174
    double dist1, dist2, dist3, dist4;
174
175
    double c, c1, c2, c3, c4;
 
176
    double fox, foy, cox, coy;
175
177
 
176
178
    xmod = fmod (ox, 1.0);
177
179
    ymod = fmod (oy, 1.0);
181
183
    dist3 = (xmod) * (ymod);
182
184
    dist4 = (1 - xmod) * (ymod);
183
185
 
184
 
    if (floor (ox) <= boundarys.x0 || floor (ox) >= boundarys.x1 ||
185
 
        floor (oy) <= boundarys.y0 || floor (oy) >= boundarys.y1)
 
186
    fox = floor (ox);
 
187
    foy = floor (oy);
 
188
    cox = ceil (ox);
 
189
    coy = ceil (oy);
 
190
 
 
191
    if (fox <= boundarys.x0 || fox >= boundarys.x1 ||
 
192
        foy <= boundarys.y0 || foy >= boundarys.y1)
186
193
        c1 = 0;
187
194
    else
188
 
        c1 = src[(guint) floor (oy) * rowstride + (guint) floor (ox) * 4 + ch];
 
195
        c1 = src[(guint) foy * rowstride + (guint) fox * 4 + ch];
189
196
 
190
 
    if (ceil (ox) <= boundarys.x0 || ceil (ox) >= boundarys.x1 ||
191
 
        floor (oy) <= boundarys.y0 || floor (oy) >= boundarys.y1)
 
197
    if (cox <= boundarys.x0 || cox >= boundarys.x1 ||
 
198
        foy <= boundarys.y0 || foy >= boundarys.y1)
192
199
        c2 = 0;
193
200
    else
194
 
        c2 = src[(guint) floor (oy) * rowstride + (guint) ceil (ox) * 4 + ch];
 
201
        c2 = src[(guint) foy * rowstride + (guint) cox * 4 + ch];
195
202
 
196
 
    if (ceil (ox) <= boundarys.x0 || ceil (ox) >= boundarys.x1 ||
197
 
        ceil (oy) <= boundarys.y0 || ceil (oy) >= boundarys.y1)
 
203
    if (cox <= boundarys.x0 || cox >= boundarys.x1 ||
 
204
        coy <= boundarys.y0 || coy >= boundarys.y1)
198
205
        c3 = 0;
199
206
    else
200
 
        c3 = src[(guint) ceil (oy) * rowstride + (guint) ceil (ox) * 4 + ch];
 
207
        c3 = src[(guint) coy * rowstride + (guint) cox * 4 + ch];
201
208
 
202
 
    if (floor (ox) <= boundarys.x0 || floor (ox) >= boundarys.x1 ||
203
 
        ceil (oy) <= boundarys.y0 || ceil (oy) >= boundarys.y1)
 
209
    if (fox <= boundarys.x0 || fox >= boundarys.x1 ||
 
210
        coy <= boundarys.y0 || coy >= boundarys.y1)
204
211
        c4 = 0;
205
212
    else
206
 
        c4 = src[(guint) ceil (oy) * rowstride + (guint) floor (ox) * 4 + ch];
 
213
        c4 = src[(guint) coy * rowstride + (guint) fox * 4 + ch];
207
214
 
208
215
    c = (c1 * dist1 + c2 * dist2 + c3 * dist3 + c4 * dist4) / (dist1 + dist2 + dist3 + dist4);
209
216
 
211
218
}
212
219
 
213
220
static void
214
 
rsvg_filter_fix_coordinate_system (RsvgFilterContext * ctx, RsvgState * state, RsvgBbox bbox)
 
221
rsvg_filter_fix_coordinate_system (RsvgFilterContext * ctx, RsvgState * state, RsvgBbox *bbox)
215
222
{
216
223
    int x, y, height, width;
217
 
    int i;
218
 
 
219
 
    x = bbox.x;
220
 
    y = bbox.y;
221
 
    width = bbox.w;
222
 
    height = bbox.h;
223
 
 
224
 
    ctx->width = gdk_pixbuf_get_width (ctx->source);
225
 
    ctx->height = gdk_pixbuf_get_height (ctx->source);
226
 
 
227
 
    for (i = 0; i < 6; i++)
228
 
        ctx->affine[i] = state->affine[i];
 
224
 
 
225
    x = bbox->rect.x;
 
226
    y = bbox->rect.y;
 
227
    width = bbox->rect.width;
 
228
    height = bbox->rect.height;
 
229
 
 
230
    ctx->width = cairo_image_surface_get_width (ctx->source_surface);
 
231
    ctx->height = cairo_image_surface_get_height (ctx->source_surface);
 
232
 
 
233
    ctx->affine = state->affine;
229
234
    if (ctx->filter->filterunits == objectBoundingBox) {
230
 
        double affine[6] = { width, 0, 0, height, x, y };
231
 
        _rsvg_affine_multiply (ctx->affine, affine, ctx->affine);
 
235
        cairo_matrix_t affine;
 
236
        cairo_matrix_init (&affine, width, 0, 0, height, x, y);
 
237
        cairo_matrix_multiply (&ctx->affine, &affine, &ctx->affine);
232
238
    }
233
 
    for (i = 0; i < 6; i++)
234
 
        ctx->paffine[i] = state->affine[i];
 
239
    ctx->paffine = state->affine;
235
240
    if (ctx->filter->primitiveunits == objectBoundingBox) {
236
 
        double affine[6] = { width, 0, 0, height, x, y };
237
 
        _rsvg_affine_multiply (ctx->paffine, affine, ctx->paffine);
 
241
        cairo_matrix_t affine;
 
242
        cairo_matrix_init (&affine, width, 0, 0, height, x, y);
 
243
        cairo_matrix_multiply (&ctx->paffine, &affine, &ctx->paffine);
238
244
    }
239
245
}
240
246
 
241
 
void
242
 
rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
243
 
                gint srcheight, GdkPixbuf * dst, gint dstx, gint dsty)
 
247
static void
 
248
rsvg_alpha_blt (cairo_surface_t *src,
 
249
                gint srcx,
 
250
                gint srcy,
 
251
                gint srcwidth,
 
252
                gint srcheight,
 
253
                cairo_surface_t *dst,
 
254
                gint dstx,
 
255
                gint dsty)
244
256
{
245
257
    gint rightx;
246
258
    gint bottomy;
255
267
    gint x, y, srcrowstride, dstrowstride, sx, sy, dx, dy;
256
268
    guchar *src_pixels, *dst_pixels;
257
269
 
 
270
    cairo_surface_flush (src);
 
271
 
258
272
    dstheight = srcheight;
259
273
    dstwidth = srcwidth;
260
274
 
261
275
    rightx = srcx + srcwidth;
262
276
    bottomy = srcy + srcheight;
263
277
 
264
 
    if (rightx > gdk_pixbuf_get_width (src))
265
 
        rightx = gdk_pixbuf_get_width (src);
266
 
    if (bottomy > gdk_pixbuf_get_height (src))
267
 
        bottomy = gdk_pixbuf_get_height (src);
 
278
    if (rightx > cairo_image_surface_get_width (src))
 
279
        rightx = cairo_image_surface_get_width (src);
 
280
    if (bottomy > cairo_image_surface_get_height (src))
 
281
        bottomy = cairo_image_surface_get_height (src);
268
282
    srcwidth = rightx - srcx;
269
283
    srcheight = bottomy - srcy;
270
284
 
271
285
    rightx = dstx + dstwidth;
272
286
    bottomy = dsty + dstheight;
273
 
    if (rightx > gdk_pixbuf_get_width (dst))
274
 
        rightx = gdk_pixbuf_get_width (dst);
275
 
    if (bottomy > gdk_pixbuf_get_height (dst))
276
 
        bottomy = gdk_pixbuf_get_height (dst);
 
287
    if (rightx > cairo_image_surface_get_width (dst))
 
288
        rightx = cairo_image_surface_get_width (dst);
 
289
    if (bottomy > cairo_image_surface_get_height (dst))
 
290
        bottomy = cairo_image_surface_get_height (dst);
277
291
    dstwidth = rightx - dstx;
278
292
    dstheight = bottomy - dsty;
279
293
 
307
321
    if (dstoffsety > srcoffsety)
308
322
        srcoffsety = dstoffsety;
309
323
 
310
 
    srcrowstride = gdk_pixbuf_get_rowstride (src);
311
 
    dstrowstride = gdk_pixbuf_get_rowstride (dst);
 
324
    srcrowstride = cairo_image_surface_get_stride (src);
 
325
    dstrowstride = cairo_image_surface_get_stride (dst);
312
326
 
313
 
    src_pixels = gdk_pixbuf_get_pixels (src);
314
 
    dst_pixels = gdk_pixbuf_get_pixels (dst);
 
327
    src_pixels = cairo_image_surface_get_data (src);
 
328
    dst_pixels = cairo_image_surface_get_data (dst);
315
329
 
316
330
    for (y = srcoffsety; y < srcheight; y++)
317
331
        for (x = srcoffsetx; x < srcwidth; x++) {
335
349
                }
336
350
            }
337
351
        }
 
352
 
 
353
    cairo_surface_mark_dirty (dst);
338
354
}
339
355
 
340
 
void
341
 
rsvg_art_affine_image (const GdkPixbuf * img, GdkPixbuf * intermediate,
342
 
                       double *affine, double w, double h)
 
356
static gboolean
 
357
rsvg_art_affine_image (cairo_surface_t *img, 
 
358
                       cairo_surface_t *intermediate,
 
359
                       cairo_matrix_t *affine, 
 
360
                       double w, 
 
361
                       double h)
343
362
{
344
 
    gdouble tmp_affine[6];
345
 
    gdouble inv_affine[6];
346
 
    gdouble raw_inv_affine[6];
 
363
    cairo_matrix_t inv_affine, raw_inv_affine;
347
364
    gint intstride;
348
365
    gint basestride;
349
366
    gint basex, basey;
358
375
    gint iwidth, iheight;
359
376
    gint width, height;
360
377
 
361
 
    width = gdk_pixbuf_get_width (img);
362
 
    height = gdk_pixbuf_get_height (img);
363
 
    iwidth = gdk_pixbuf_get_width (intermediate);
364
 
    iheight = gdk_pixbuf_get_height (intermediate);
365
 
 
366
 
    has_alpha = gdk_pixbuf_get_has_alpha (img);
367
 
 
368
 
    basestride = gdk_pixbuf_get_rowstride (img);
369
 
    intstride = gdk_pixbuf_get_rowstride (intermediate);
370
 
    basepix = gdk_pixbuf_get_pixels (img);
371
 
    intpix = gdk_pixbuf_get_pixels (intermediate);
 
378
    g_assert (cairo_image_surface_get_format (intermediate) == CAIRO_FORMAT_ARGB32);
 
379
 
 
380
    cairo_surface_flush (img);
 
381
 
 
382
    width = cairo_image_surface_get_width (img);
 
383
    height = cairo_image_surface_get_height (img);
 
384
    iwidth = cairo_image_surface_get_width (intermediate);
 
385
    iheight = cairo_image_surface_get_height (intermediate);
 
386
 
 
387
    has_alpha = cairo_image_surface_get_format (img) == CAIRO_FORMAT_ARGB32;
 
388
 
 
389
    basestride = cairo_image_surface_get_stride (img);
 
390
    intstride = cairo_image_surface_get_stride (intermediate);
 
391
    basepix = cairo_image_surface_get_data (img);
 
392
    intpix = cairo_image_surface_get_data (intermediate);
372
393
    basebpp = has_alpha ? 4 : 3;
373
394
 
374
 
    _rsvg_affine_invert (raw_inv_affine, affine);
375
 
 
376
 
    /*scale to w and h */
377
 
    tmp_affine[0] = (double) w;
378
 
    tmp_affine[3] = (double) h;
379
 
    tmp_affine[1] = tmp_affine[2] = tmp_affine[4] = tmp_affine[5] = 0;
380
 
    _rsvg_affine_multiply (tmp_affine, tmp_affine, affine);
381
 
 
382
 
    _rsvg_affine_invert (inv_affine, tmp_affine);
383
 
 
 
395
    raw_inv_affine = *affine;
 
396
    if (cairo_matrix_invert (&raw_inv_affine) != CAIRO_STATUS_SUCCESS)
 
397
      return FALSE;
 
398
 
 
399
    cairo_matrix_init_scale (&inv_affine, w, h);
 
400
    cairo_matrix_multiply (&inv_affine, &inv_affine, affine);
 
401
    if (cairo_matrix_invert (&inv_affine) != CAIRO_STATUS_SUCCESS)
 
402
      return FALSE;
384
403
 
385
404
    /*apply the transformation */
386
405
    for (i = 0; i < iwidth; i++)
387
406
        for (j = 0; j < iheight; j++) {
388
 
            fbasex = (inv_affine[0] * (double) i + inv_affine[2] * (double) j +
389
 
                      inv_affine[4]) * (double) width;
390
 
            fbasey = (inv_affine[1] * (double) i + inv_affine[3] * (double) j +
391
 
                      inv_affine[5]) * (double) height;
 
407
            fbasex = (inv_affine.xx * (double) i + inv_affine.xy * (double) j +
 
408
                      inv_affine.x0) * (double) width;
 
409
            fbasey = (inv_affine.yx * (double) i + inv_affine.yy * (double) j +
 
410
                      inv_affine.y0) * (double) height;
392
411
            basex = floor (fbasex);
393
412
            basey = floor (fbasey);
394
 
            rawx = raw_inv_affine[0] * i + raw_inv_affine[2] * j + raw_inv_affine[4];
395
 
            rawy = raw_inv_affine[1] * i + raw_inv_affine[3] * j + raw_inv_affine[5];
 
413
            rawx = raw_inv_affine.xx * i + raw_inv_affine.xy * j + raw_inv_affine.x0;
 
414
            rawy = raw_inv_affine.yx * i + raw_inv_affine.yy * j + raw_inv_affine.y0;
396
415
            if (rawx < 0 || rawy < 0 || rawx >= w ||
397
416
                rawy >= h || basex < 0 || basey < 0 || basex >= width || basey >= height) {
398
417
                for (k = 0; k < 4; k++)
429
448
            }
430
449
 
431
450
        }
 
451
 
 
452
    /* Don't need cairo_surface_mark_dirty(intermediate) here since
 
453
     * the only caller does further work and then calls that himself.
 
454
     */
 
455
 
 
456
    return TRUE;
432
457
}
433
458
 
434
459
static void
437
462
    RsvgFilterPrimitiveOutput *output;
438
463
 
439
464
    output = (RsvgFilterPrimitiveOutput *) value;
440
 
    g_object_unref (output->result);
 
465
    cairo_surface_destroy (output->surface);
441
466
    g_free (output);
442
467
}
443
468
 
447
472
    if (!ctx)
448
473
        return;
449
474
 
450
 
    if (ctx->bg)
451
 
        g_object_unref (ctx->bg);
 
475
    if (ctx->bg_surface)
 
476
        cairo_surface_destroy (ctx->bg_surface);
452
477
 
453
478
    g_free (ctx);
454
479
}
455
480
 
456
481
/**
457
 
 * rsvg_filter_render: Create a new pixbuf applied the filter.
 
482
 * rsvg_filter_render: Create a new surface applied the filter.
458
483
 * @self: a pointer to the filter to use
459
 
 * @source: a pointer to the source pixbuf
 
484
 * @source: the a #cairo_surface_t of type %CAIRO_SURFACE_TYPE_IMAGE
460
485
 * @context: the context
461
486
 *
462
487
 * This function will create a context for itself, set up the coordinate systems
463
488
 * execute all its little primatives and then clean up its own mess
 
489
 * 
 
490
 * Returns: (transfer full): a new #cairo_surface_t
464
491
 **/
465
 
GdkPixbuf *
466
 
rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source,
467
 
                    RsvgDrawingCtx * context, RsvgBbox * bounds, char *channelmap)
 
492
cairo_surface_t *
 
493
rsvg_filter_render (RsvgFilter *self,
 
494
                    cairo_surface_t *source,
 
495
                    RsvgDrawingCtx *context, 
 
496
                    RsvgBbox *bounds, 
 
497
                    char *channelmap)
468
498
{
469
499
    RsvgFilterContext *ctx;
470
500
    RsvgFilterPrimitive *current;
471
501
    guint i;
472
 
    GdkPixbuf *out;
 
502
    cairo_surface_t *output;
473
503
 
 
504
    g_return_val_if_fail (source != NULL, NULL);
 
505
    g_return_val_if_fail (cairo_surface_get_type (source) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
474
506
 
475
507
    ctx = g_new (RsvgFilterContext, 1);
476
508
    ctx->filter = self;
477
 
    ctx->source = source;
478
 
    ctx->bg = NULL;
 
509
    ctx->source_surface = source;
 
510
    ctx->bg_surface = NULL;
479
511
    ctx->results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, rsvg_filter_free_pair);
480
512
    ctx->ctx = context;
481
513
 
482
 
    g_object_ref (source);
483
 
 
484
 
    rsvg_filter_fix_coordinate_system (ctx, rsvg_current_state (context), *bounds);
485
 
 
486
 
    ctx->lastresult.result = source;
 
514
    rsvg_filter_fix_coordinate_system (ctx, rsvg_current_state (context), bounds);
 
515
 
 
516
    ctx->lastresult.surface = cairo_surface_reference (source);
487
517
    ctx->lastresult.Rused = 1;
488
518
    ctx->lastresult.Gused = 1;
489
519
    ctx->lastresult.Bused = 1;
499
529
            rsvg_filter_primitive_render (current, ctx);
500
530
    }
501
531
 
502
 
    out = ctx->lastresult.result;
 
532
    output = ctx->lastresult.surface;
503
533
 
504
534
    g_hash_table_destroy (ctx->results);
505
535
 
506
536
    rsvg_filter_context_free (ctx);
507
537
 
508
 
    return out;
 
538
    return output;
509
539
}
510
540
 
511
541
/**
522
552
{
523
553
    RsvgFilterPrimitiveOutput *store;
524
554
 
525
 
    g_object_unref (ctx->lastresult.result);
 
555
    cairo_surface_destroy (ctx->lastresult.surface);
526
556
 
527
557
    store = g_new (RsvgFilterPrimitiveOutput, 1);
528
558
    *store = result;
529
559
 
530
 
    if (strcmp (name->str, "")) {
531
 
        g_object_ref (result.result);        /* increments the references for the table */
 
560
    if (name->str[0] != '\0') {
 
561
        cairo_surface_reference (result.surface);        /* increments the references for the table */
532
562
        g_hash_table_insert (ctx->results, g_strdup (name->str), store);
533
563
    }
534
564
 
535
 
    g_object_ref (result.result);    /* increments the references for the last result */
 
565
    cairo_surface_reference (result.surface);    /* increments the references for the last result */
536
566
    ctx->lastresult = result;
537
567
}
538
568
 
539
569
static void
540
 
rsvg_filter_store_result (GString * name, GdkPixbuf * result, RsvgFilterContext * ctx)
 
570
rsvg_filter_store_result (GString * name,
 
571
                          cairo_surface_t *surface,
 
572
                          RsvgFilterContext * ctx)
541
573
{
542
574
    RsvgFilterPrimitiveOutput output;
543
575
    output.Rused = 1;
548
580
    output.bounds.y0 = 0;
549
581
    output.bounds.x1 = ctx->width;
550
582
    output.bounds.y1 = ctx->height;
551
 
    output.result = result;
 
583
    output.surface = surface;
552
584
 
553
585
    rsvg_filter_store_output (name, output, ctx);
554
586
}
555
587
 
556
 
static GdkPixbuf *
557
 
pixbuf_get_alpha (GdkPixbuf * pb, RsvgFilterContext * ctx)
 
588
static cairo_surface_t *
 
589
surface_get_alpha (cairo_surface_t *source,
 
590
                   RsvgFilterContext * ctx)
558
591
{
559
592
    guchar *data;
560
593
    guchar *pbdata;
561
 
    GdkPixbuf *output;
562
 
 
563
594
    gsize i, pbsize;
564
 
 
565
 
    pbsize = gdk_pixbuf_get_width (pb) * gdk_pixbuf_get_height (pb);
566
 
 
567
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8,
568
 
                                       gdk_pixbuf_get_width (pb), gdk_pixbuf_get_height (pb));
569
 
 
570
 
    data = gdk_pixbuf_get_pixels (output);
571
 
    pbdata = gdk_pixbuf_get_pixels (pb);
572
 
 
 
595
    cairo_surface_t *surface;
 
596
 
 
597
    if (source == NULL)
 
598
        return NULL;
 
599
 
 
600
    cairo_surface_flush (source);
 
601
 
 
602
    pbsize = cairo_image_surface_get_width (source) * 
 
603
             cairo_image_surface_get_height (source);
 
604
 
 
605
    surface = _rsvg_image_surface_new (cairo_image_surface_get_width (source),
 
606
                                       cairo_image_surface_get_height (source));
 
607
    if (surface == NULL)
 
608
        return NULL;
 
609
 
 
610
    data = cairo_image_surface_get_data (surface);
 
611
    pbdata = cairo_image_surface_get_data (source);
 
612
 
 
613
    /* FIXMEchpe: rewrite this into nested width, height loops */
573
614
    for (i = 0; i < pbsize; i++)
574
615
        data[i * 4 + ctx->channelmap[3]] = pbdata[i * 4 + ctx->channelmap[3]];
575
616
 
576
 
    return output;
 
617
    cairo_surface_mark_dirty (surface);
 
618
    return surface;
577
619
}
578
620
 
579
 
static GdkPixbuf *
 
621
static cairo_surface_t *
580
622
rsvg_compile_bg (RsvgDrawingCtx * ctx)
581
623
{
582
 
    RsvgCairoRender *render = (RsvgCairoRender *) ctx->render;
 
624
    RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
 
625
    cairo_surface_t *surface;
583
626
    cairo_t *cr;
584
 
    cairo_surface_t *surface;
585
627
    GList *i;
586
 
    unsigned char *pixels = g_new0 (guint8, render->width * render->height * 4);
587
 
    int rowstride = render->width * 4;
588
 
 
589
 
    GdkPixbuf *output = gdk_pixbuf_new_from_data (pixels,
590
 
                                                  GDK_COLORSPACE_RGB, TRUE, 8,
591
 
                                                  render->width, render->height,
592
 
                                                  rowstride,
593
 
                                                  (GdkPixbufDestroyNotify) g_free,
594
 
                                                  NULL);
595
 
 
596
 
    surface = cairo_image_surface_create_for_data (pixels,
597
 
                                                   CAIRO_FORMAT_ARGB32,
598
 
                                                   render->width, render->height, rowstride);
 
628
 
 
629
    surface = _rsvg_image_surface_new (render->width, render->height);
 
630
    if (surface == NULL)
 
631
        return NULL;
599
632
 
600
633
    cr = cairo_create (surface);
601
 
    cairo_surface_destroy (surface);
602
634
 
603
635
    for (i = g_list_last (render->cr_stack); i != NULL; i = g_list_previous (i)) {
604
636
        cairo_t *draw = i->data;
610
642
    }
611
643
 
612
644
    cairo_destroy (cr);
613
 
    return output;
 
645
 
 
646
    return surface;
614
647
}
615
648
 
616
 
static GdkPixbuf *
 
649
/**
 
650
 * rsvg_filter_get_bg:
 
651
 * 
 
652
 * Returns: (transfer none): a #cairo_surface_t, or %NULL
 
653
 */
 
654
static cairo_surface_t *
617
655
rsvg_filter_get_bg (RsvgFilterContext * ctx)
618
656
{
619
 
    if (!ctx->bg)
620
 
        ctx->bg = rsvg_compile_bg (ctx->ctx);
 
657
    if (!ctx->bg_surface)
 
658
        ctx->bg_surface = rsvg_compile_bg (ctx->ctx);
621
659
 
622
 
    return ctx->bg;
 
660
    return ctx->bg_surface;
623
661
}
624
662
 
 
663
/* FIXMEchpe: proper return value and out param! */
625
664
/**
626
 
 * rsvg_filter_get_in: Gets a pixbuf for a primative.
627
 
 * @name: The name of the pixbuf
 
665
 * rsvg_filter_get_in: Gets a surface for a primitive
 
666
 * @name: The name of the surface
628
667
 * @ctx: the context that this was called in
629
 
 *
 
668
 * @
630
669
 * Returns: a pointer to the result that the name refers to, a special
631
 
 * Pixbuf if the name is a special keyword or NULL if nothing was found
 
670
 * surface if the name is a special keyword or NULL if nothing was found
632
671
 **/
633
672
static RsvgFilterPrimitiveOutput
634
673
rsvg_filter_get_result (GString * name, RsvgFilterContext * ctx)
638
677
    output.bounds.x0 = output.bounds.x1 = output.bounds.y0 = output.bounds.y1 = 0;
639
678
 
640
679
    if (!strcmp (name->str, "SourceGraphic")) {
641
 
        g_object_ref (ctx->source);
642
 
        output.result = ctx->source;
 
680
        output.surface = cairo_surface_reference (ctx->source_surface);
643
681
        output.Rused = output.Gused = output.Bused = output.Aused = 1;
644
682
        return output;
645
683
    } else if (!strcmp (name->str, "BackgroundImage")) {
646
 
        output.result = g_object_ref (rsvg_filter_get_bg (ctx));
 
684
        output.surface = rsvg_filter_get_bg (ctx);
 
685
        if (output.surface)
 
686
            cairo_surface_reference (output.surface);
647
687
        output.Rused = output.Gused = output.Bused = output.Aused = 1;
648
688
        return output;
649
 
    } else if (!strcmp (name->str, "") || !strcmp (name->str, "none") || !name) {
650
 
        g_object_ref (ctx->lastresult.result);
 
689
    } else if (!name || !strcmp (name->str, "") || !strcmp (name->str, "none")) {
651
690
        output = ctx->lastresult;
 
691
        cairo_surface_reference (output.surface);
652
692
        return output;
653
693
    } else if (!strcmp (name->str, "SourceAlpha")) {
654
694
        output.Rused = output.Gused = output.Bused = 0;
655
695
        output.Aused = 1;
656
 
        output.result = pixbuf_get_alpha (ctx->source, ctx);
 
696
        output.surface = surface_get_alpha (ctx->source_surface, ctx);
657
697
        return output;
658
698
    } else if (!strcmp (name->str, "BackgroundAlpha")) {
659
699
        output.Rused = output.Gused = output.Bused = 0;
660
700
        output.Aused = 1;
661
 
        output.result = pixbuf_get_alpha (rsvg_filter_get_bg (ctx), ctx);
 
701
        output.surface = surface_get_alpha (rsvg_filter_get_bg (ctx), ctx);
662
702
        return output;
663
703
    }
664
704
 
666
706
 
667
707
    if (outputpointer != NULL) {
668
708
        output = *outputpointer;
669
 
        g_object_ref (output.result);
 
709
        cairo_surface_reference (output.surface);
670
710
        return output;
671
711
    }
672
712
 
673
 
    g_warning (_("%s not found\n"), name->str);
 
713
    /* g_warning (_("%s not found\n"), name->str); */
674
714
 
675
715
    output = ctx->lastresult;
676
 
    g_object_ref (ctx->lastresult.result);
 
716
    cairo_surface_reference (output.surface);
677
717
    return output;
678
718
}
679
719
 
680
 
 
681
 
static GdkPixbuf *
 
720
/**
 
721
 * rsvg_filter_get_in:
 
722
 * @name:
 
723
 * @ctx:
 
724
 * 
 
725
 * Returns: (transfer full): a new #cairo_surface_t, or %NULL
 
726
 */
 
727
static cairo_surface_t *
682
728
rsvg_filter_get_in (GString * name, RsvgFilterContext * ctx)
683
729
{
684
 
    return rsvg_filter_get_result (name, ctx).result;
 
730
    return rsvg_filter_get_result (name, ctx).surface;
685
731
}
686
732
 
687
733
/**
782
828
};
783
829
 
784
830
static void
785
 
rsvg_filter_blend (RsvgFilterPrimitiveBlendMode mode, GdkPixbuf * in, GdkPixbuf * in2,
786
 
                   GdkPixbuf * output, RsvgIRect boundarys, int *channelmap)
 
831
rsvg_filter_blend (RsvgFilterPrimitiveBlendMode mode, 
 
832
                   cairo_surface_t *in, 
 
833
                   cairo_surface_t *in2,
 
834
                   cairo_surface_t* output, 
 
835
                   RsvgIRect boundarys, 
 
836
                   int *channelmap)
787
837
{
788
838
    guchar i;
789
839
    gint x, y;
791
841
    guchar *in_pixels;
792
842
    guchar *in2_pixels;
793
843
    guchar *output_pixels;
794
 
    height = gdk_pixbuf_get_height (in);
795
 
    width = gdk_pixbuf_get_width (in);
796
 
    rowstride = gdk_pixbuf_get_rowstride (in);
797
 
    rowstride2 = gdk_pixbuf_get_rowstride (in2);
798
 
    rowstrideo = gdk_pixbuf_get_rowstride (output);
799
 
 
800
 
    output_pixels = gdk_pixbuf_get_pixels (output);
801
 
    in_pixels = gdk_pixbuf_get_pixels (in);
802
 
    in2_pixels = gdk_pixbuf_get_pixels (in2);
 
844
 
 
845
    cairo_surface_flush (in);
 
846
    cairo_surface_flush (in2);
 
847
 
 
848
    height = cairo_image_surface_get_height (in);
 
849
    width = cairo_image_surface_get_width (in);
 
850
    rowstride = cairo_image_surface_get_stride (in);
 
851
    rowstride2 = cairo_image_surface_get_stride (in2);
 
852
    rowstrideo = cairo_image_surface_get_stride (output);
 
853
 
 
854
    output_pixels = cairo_image_surface_get_data (output);
 
855
    in_pixels = cairo_image_surface_get_data (in);
 
856
    in2_pixels = cairo_image_surface_get_data (in2);
803
857
 
804
858
    if (boundarys.x0 < 0)
805
859
        boundarys.x0 = 0;
889
943
            }
890
944
            output_pixels[4 * x + y * rowstrideo + channelmap[3]] = qr * 255.0;
891
945
        }
 
946
 
 
947
    cairo_surface_mark_dirty (output);
892
948
}
893
949
 
894
 
 
895
950
static void
896
951
rsvg_filter_primitive_blend_render (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
897
952
{
899
954
 
900
955
    RsvgFilterPrimitiveBlend *upself;
901
956
 
902
 
    GdkPixbuf *output;
903
 
    GdkPixbuf *in;
904
 
    GdkPixbuf *in2;
 
957
    cairo_surface_t *output, *in, *in2;
905
958
 
906
959
    upself = (RsvgFilterPrimitiveBlend *) self;
907
960
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
908
961
 
909
962
    in = rsvg_filter_get_in (self->in, ctx);
 
963
    if (in == NULL)
 
964
      return;
 
965
 
910
966
    in2 = rsvg_filter_get_in (upself->in2, ctx);
 
967
    if (in2 == NULL) {
 
968
        cairo_surface_destroy (in);
 
969
        return;
 
970
    }
911
971
 
912
 
    output =
913
 
        _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, gdk_pixbuf_get_width (in),
914
 
                                  gdk_pixbuf_get_height (in));
 
972
    output = _rsvg_image_surface_new (cairo_image_surface_get_width (in),
 
973
                                      cairo_image_surface_get_height (in));
 
974
    if (output == NULL) {
 
975
        cairo_surface_destroy (in);
 
976
        cairo_surface_destroy (in2);
 
977
        return;
 
978
    }
915
979
 
916
980
    rsvg_filter_blend (upself->mode, in, in2, output, boundarys, ctx->channelmap);
917
981
 
918
982
    rsvg_filter_store_result (self->result, output, ctx);
919
983
 
920
 
    g_object_unref (in);
921
 
    g_object_unref (in2);
922
 
    g_object_unref (output);
 
984
    cairo_surface_destroy (in);
 
985
    cairo_surface_destroy (in2);
 
986
    cairo_surface_destroy (output);
923
987
}
924
988
 
925
989
static void
1022
1086
 
1023
1087
    RsvgFilterPrimitiveConvolveMatrix *upself;
1024
1088
 
1025
 
    GdkPixbuf *output;
1026
 
    GdkPixbuf *in;
 
1089
    cairo_surface_t *output, *in;
1027
1090
 
1028
1091
    gint sx, sy, kx, ky;
1029
1092
    guchar sval;
1036
1099
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
1037
1100
 
1038
1101
    in = rsvg_filter_get_in (self->in, ctx);
1039
 
    in_pixels = gdk_pixbuf_get_pixels (in);
1040
 
 
1041
 
    height = gdk_pixbuf_get_height (in);
1042
 
    width = gdk_pixbuf_get_width (in);
1043
 
 
1044
 
    targetx = upself->targetx * ctx->paffine[0];
1045
 
    targety = upself->targety * ctx->paffine[3];
 
1102
    if (in == NULL)
 
1103
        return;
 
1104
 
 
1105
    cairo_surface_flush (in);
 
1106
 
 
1107
    in_pixels = cairo_image_surface_get_data (in);
 
1108
 
 
1109
    height = cairo_image_surface_get_height (in);
 
1110
    width = cairo_image_surface_get_width (in);
 
1111
 
 
1112
    targetx = upself->targetx * ctx->paffine.xx;
 
1113
    targety = upself->targety * ctx->paffine.yy;
1046
1114
 
1047
1115
    if (upself->dx != 0 || upself->dy != 0) {
1048
 
        dx = upself->dx * ctx->paffine[0];
1049
 
        dy = upself->dy * ctx->paffine[3];
 
1116
        dx = upself->dx * ctx->paffine.xx;
 
1117
        dy = upself->dy * ctx->paffine.yy;
1050
1118
    } else
1051
1119
        dx = dy = 1;
1052
1120
 
1053
 
    rowstride = gdk_pixbuf_get_rowstride (in);
1054
 
 
1055
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
1056
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
1121
    rowstride = cairo_image_surface_get_stride (in);
 
1122
 
 
1123
    output = _rsvg_image_surface_new (width, height);
 
1124
    if (output == NULL) {
 
1125
        cairo_surface_destroy (in);
 
1126
        return;
 
1127
    }
 
1128
 
 
1129
    output_pixels = cairo_image_surface_get_data (output);
1057
1130
 
1058
1131
    for (y = boundarys.y0; y < boundarys.y1; y++)
1059
1132
        for (x = boundarys.x0; x < boundarys.x1; x++) {
1117
1190
                    output_pixels[4 * x + y * rowstride + ctx->channelmap[3]] / 255;
1118
1191
            }
1119
1192
        }
 
1193
 
 
1194
    cairo_surface_mark_dirty (output);
 
1195
 
1120
1196
    rsvg_filter_store_result (self->result, output, ctx);
1121
1197
 
1122
 
    g_object_unref (in);
1123
 
    g_object_unref (output);
 
1198
    cairo_surface_destroy (in);
 
1199
    cairo_surface_destroy (output);
1124
1200
}
1125
1201
 
1126
1202
static void
1260
1336
};
1261
1337
 
1262
1338
static void
1263
 
box_blur (GdkPixbuf * in, GdkPixbuf * output, guchar * intermediate, gint kw,
1264
 
          gint kh, RsvgIRect boundarys, RsvgFilterPrimitiveOutput op)
 
1339
box_blur (cairo_surface_t *in, 
 
1340
          cairo_surface_t *output, 
 
1341
          guchar *intermediate, 
 
1342
          gint kw,
 
1343
          gint kh, 
 
1344
          RsvgIRect boundarys, 
 
1345
          RsvgFilterPrimitiveOutput op)
1265
1346
{
1266
1347
    gint ch;
1267
1348
    gint x, y;
1268
 
    gint rowstride, height, width;
1269
 
 
 
1349
    gint rowstride;
1270
1350
    guchar *in_pixels;
1271
1351
    guchar *output_pixels;
1272
 
 
1273
1352
    gint sum;
1274
1353
 
1275
 
 
1276
 
    height = gdk_pixbuf_get_height (in);
1277
 
    width = gdk_pixbuf_get_width (in);
1278
 
 
1279
 
    in_pixels = gdk_pixbuf_get_pixels (in);
1280
 
    output_pixels = gdk_pixbuf_get_pixels (output);
1281
 
 
1282
 
    rowstride = gdk_pixbuf_get_rowstride (in);
 
1354
    in_pixels = cairo_image_surface_get_data (in);
 
1355
    output_pixels = cairo_image_surface_get_data (output);
 
1356
 
 
1357
    rowstride = cairo_image_surface_get_stride (in);
1283
1358
 
1284
1359
    if (kw > boundarys.x1 - boundarys.x0)
1285
1360
        kw = boundarys.x1 - boundarys.x0;
1372
1447
}
1373
1448
 
1374
1449
static void
1375
 
fast_blur (GdkPixbuf * in, GdkPixbuf * output, gfloat sx,
1376
 
           gfloat sy, RsvgIRect boundarys, RsvgFilterPrimitiveOutput op)
 
1450
fast_blur (cairo_surface_t *in, 
 
1451
           cairo_surface_t *output, 
 
1452
           gfloat sx,
 
1453
           gfloat sy, 
 
1454
           RsvgIRect boundarys, 
 
1455
           RsvgFilterPrimitiveOutput op)
1377
1456
{
1378
1457
    gint kx, ky;
1379
1458
    guchar *intermediate;
1380
1459
 
 
1460
    cairo_surface_flush (in);
 
1461
 
1381
1462
    kx = floor (sx * 3 * sqrt (2 * M_PI) / 4 + 0.5);
1382
1463
    ky = floor (sy * 3 * sqrt (2 * M_PI) / 4 + 0.5);
1383
1464
 
1391
1472
    box_blur (output, output, intermediate, kx, ky, boundarys, op);
1392
1473
 
1393
1474
    g_free (intermediate);
 
1475
 
 
1476
    cairo_surface_mark_dirty (output);
1394
1477
}
1395
1478
 
1396
1479
static void
1397
1480
rsvg_filter_primitive_gaussian_blur_render (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
1398
1481
{
1399
1482
    RsvgFilterPrimitiveGaussianBlur *upself;
1400
 
 
1401
 
    GdkPixbuf *output;
1402
 
    GdkPixbuf *in;
 
1483
    cairo_surface_t *output, *in;
1403
1484
    RsvgIRect boundarys;
1404
1485
    gfloat sdx, sdy;
1405
1486
    RsvgFilterPrimitiveOutput op;
1408
1489
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
1409
1490
 
1410
1491
    op = rsvg_filter_get_result (self->in, ctx);
1411
 
    in = op.result;
 
1492
    in = op.surface;
1412
1493
 
1413
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8,
1414
 
                                       gdk_pixbuf_get_width (in), gdk_pixbuf_get_height (in));
 
1494
    output = _rsvg_image_surface_new (cairo_image_surface_get_width (in), 
 
1495
                                      cairo_image_surface_get_height (in));
 
1496
    if (output == NULL) {
 
1497
        cairo_surface_destroy (in);
 
1498
        return;
 
1499
    }
1415
1500
 
1416
1501
    /* scale the SD values */
1417
 
    sdx = upself->sdx * ctx->paffine[0];
1418
 
    sdy = upself->sdy * ctx->paffine[3];
 
1502
    sdx = upself->sdx * ctx->paffine.xx;
 
1503
    sdy = upself->sdy * ctx->paffine.yy;
1419
1504
 
1420
1505
    fast_blur (in, output, sdx, sdy, boundarys, op);
1421
1506
 
1422
 
    op.result = output;
 
1507
    op.surface = output;
1423
1508
    op.bounds = boundarys;
1424
1509
    rsvg_filter_store_output (self->result, op, ctx);
1425
1510
 
1426
 
    g_object_unref (in);
1427
 
    g_object_unref (output);
 
1511
    cairo_surface_destroy (in);
 
1512
    cairo_surface_destroy (output);
1428
1513
}
1429
1514
 
1430
1515
static void
1509
1594
    RsvgFilterPrimitiveOutput out;
1510
1595
    RsvgFilterPrimitiveOffset *upself;
1511
1596
 
1512
 
    GdkPixbuf *output;
1513
 
    GdkPixbuf *in;
 
1597
    cairo_surface_t *output, *in;
1514
1598
 
1515
1599
    double dx, dy;
1516
1600
    int ox, oy;
1519
1603
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
1520
1604
 
1521
1605
    in = rsvg_filter_get_in (self->in, ctx);
1522
 
    in_pixels = gdk_pixbuf_get_pixels (in);
1523
 
 
1524
 
    height = gdk_pixbuf_get_height (in);
1525
 
    width = gdk_pixbuf_get_width (in);
1526
 
 
1527
 
    rowstride = gdk_pixbuf_get_rowstride (in);
1528
 
 
1529
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
1530
 
 
1531
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
1606
    if (in == NULL)
 
1607
        return;
 
1608
 
 
1609
    cairo_surface_flush (in);
 
1610
 
 
1611
    in_pixels = cairo_image_surface_get_data (in);
 
1612
 
 
1613
    height = cairo_image_surface_get_height (in);
 
1614
    width = cairo_image_surface_get_width (in);
 
1615
 
 
1616
    rowstride = cairo_image_surface_get_stride (in);
 
1617
 
 
1618
    output = _rsvg_image_surface_new (width, height);
 
1619
    if (output == NULL) {
 
1620
        cairo_surface_destroy (in);
 
1621
        return;
 
1622
    }
 
1623
 
 
1624
    output_pixels = cairo_image_surface_get_data (output);
1532
1625
 
1533
1626
    dx = _rsvg_css_normalize_length (&upself->dx, ctx->ctx, 'w');
1534
1627
    dy = _rsvg_css_normalize_length (&upself->dy, ctx->ctx, 'v');
1535
1628
 
1536
 
    ox = ctx->paffine[0] * dx + ctx->paffine[2] * dy;
1537
 
    oy = ctx->paffine[1] * dx + ctx->paffine[3] * dy;
 
1629
    ox = ctx->paffine.xx * dx + ctx->paffine.xy * dy;
 
1630
    oy = ctx->paffine.yx * dx + ctx->paffine.yy * dy;
1538
1631
 
1539
1632
    for (y = boundarys.y0; y < boundarys.y1; y++)
1540
1633
        for (x = boundarys.x0; x < boundarys.x1; x++) {
1549
1642
            }
1550
1643
        }
1551
1644
 
1552
 
    out.result = output;
 
1645
    cairo_surface_mark_dirty (output);
 
1646
 
 
1647
    out.surface = output;
1553
1648
    out.Rused = 1;
1554
1649
    out.Gused = 1;
1555
1650
    out.Bused = 1;
1558
1653
 
1559
1654
    rsvg_filter_store_output (self->result, out, ctx);
1560
1655
 
1561
 
    g_object_unref (in);
1562
 
    g_object_unref (output);
 
1656
    cairo_surface_destroy  (in);
 
1657
    cairo_surface_destroy (output);
1563
1658
}
1564
1659
 
1565
1660
static void
1638
1733
 
1639
1734
    RsvgFilterPrimitiveMerge *upself;
1640
1735
 
1641
 
    GdkPixbuf *output;
1642
 
    GdkPixbuf *in;
 
1736
    cairo_surface_t *output, *in;
1643
1737
 
1644
1738
    upself = (RsvgFilterPrimitiveMerge *) self;
1645
1739
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
1646
1740
 
1647
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height);
 
1741
    output = _rsvg_image_surface_new (ctx->width, ctx->height);
 
1742
    if (output == NULL) {
 
1743
        return;
 
1744
    }
1648
1745
 
1649
1746
    for (i = 0; i < upself->super.super.children->len; i++) {
1650
1747
        RsvgFilterPrimitive *mn;
1652
1749
        if (RSVG_NODE_TYPE (&mn->super) != RSVG_NODE_TYPE_FILTER_PRIMITIVE_MERGE_NODE)
1653
1750
            continue;
1654
1751
        in = rsvg_filter_get_in (mn->in, ctx);
 
1752
        if (in == NULL)
 
1753
            continue;
 
1754
 
1655
1755
        rsvg_alpha_blt (in, boundarys.x0, boundarys.y0, boundarys.x1 - boundarys.x0,
1656
1756
                        boundarys.y1 - boundarys.y0, output, boundarys.x0, boundarys.y0);
1657
 
        g_object_unref (in);
 
1757
        cairo_surface_destroy (in);
1658
1758
    }
1659
1759
 
1660
1760
    rsvg_filter_store_result (self->result, output, ctx);
1661
1761
 
1662
 
    g_object_unref (output);
 
1762
    cairo_surface_destroy (output);
1663
1763
}
1664
1764
 
1665
1765
static void
1778
1878
 
1779
1879
    RsvgFilterPrimitiveColourMatrix *upself;
1780
1880
 
1781
 
    GdkPixbuf *output;
1782
 
    GdkPixbuf *in;
 
1881
    cairo_surface_t *output, *in;
1783
1882
 
1784
1883
    int sum;
1785
1884
 
1787
1886
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
1788
1887
 
1789
1888
    in = rsvg_filter_get_in (self->in, ctx);
1790
 
    in_pixels = gdk_pixbuf_get_pixels (in);
1791
 
 
1792
 
    height = gdk_pixbuf_get_height (in);
1793
 
    width = gdk_pixbuf_get_width (in);
1794
 
 
1795
 
    rowstride = gdk_pixbuf_get_rowstride (in);
1796
 
 
1797
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
1798
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
1889
    if (in == NULL)
 
1890
        return;
 
1891
 
 
1892
    cairo_surface_flush (in);
 
1893
 
 
1894
    in_pixels = cairo_image_surface_get_data (in);
 
1895
 
 
1896
    height = cairo_image_surface_get_height (in);
 
1897
    width = cairo_image_surface_get_width (in);
 
1898
 
 
1899
    rowstride = cairo_image_surface_get_stride (in);
 
1900
 
 
1901
    output = _rsvg_image_surface_new (width, height);
 
1902
    if (output == NULL) {
 
1903
        cairo_surface_destroy (in);
 
1904
        return;
 
1905
    }
 
1906
 
 
1907
    output_pixels = cairo_image_surface_get_data (output);
1799
1908
 
1800
1909
    for (y = boundarys.y0; y < boundarys.y1; y++)
1801
1910
        for (x = boundarys.x0; x < boundarys.x1; x++) {
1842
1951
            }
1843
1952
        }
1844
1953
 
 
1954
    cairo_surface_mark_dirty (output);
 
1955
 
1845
1956
    rsvg_filter_store_result (self->result, output, ctx);
1846
1957
 
1847
 
    g_object_unref (in);
1848
 
    g_object_unref (output);
 
1958
    cairo_surface_destroy (in);
 
1959
    cairo_surface_destroy(output);
1849
1960
}
1850
1961
 
1851
1962
static void
2098
2209
    gint achan = ctx->channelmap[3];
2099
2210
    guchar *in_pixels;
2100
2211
    guchar *output_pixels;
2101
 
 
2102
 
    RsvgFilterPrimitiveComponentTransfer *upself;
2103
 
 
2104
 
    GdkPixbuf *output;
2105
 
    GdkPixbuf *in;
2106
 
    upself = (RsvgFilterPrimitiveComponentTransfer *) self;
 
2212
    cairo_surface_t *output, *in;
 
2213
 
2107
2214
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
2108
2215
 
2109
2216
    for (c = 0; c < 4; c++) {
2128
2235
    }
2129
2236
 
2130
2237
    in = rsvg_filter_get_in (self->in, ctx);
2131
 
    in_pixels = gdk_pixbuf_get_pixels (in);
2132
 
 
2133
 
    height = gdk_pixbuf_get_height (in);
2134
 
    width = gdk_pixbuf_get_width (in);
2135
 
 
2136
 
    rowstride = gdk_pixbuf_get_rowstride (in);
2137
 
 
2138
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
2139
 
 
2140
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
2238
    if (in == NULL)
 
2239
        return;
 
2240
 
 
2241
    cairo_surface_flush (in);
 
2242
 
 
2243
    in_pixels = cairo_image_surface_get_data (in);
 
2244
 
 
2245
    height = cairo_image_surface_get_height (in);
 
2246
    width = cairo_image_surface_get_width (in);
 
2247
 
 
2248
    rowstride = cairo_image_surface_get_stride (in);
 
2249
 
 
2250
    output = _rsvg_image_surface_new (width, height);
 
2251
    if (output == NULL) {
 
2252
        cairo_surface_destroy (in);
 
2253
        return;
 
2254
    }
 
2255
 
 
2256
    output_pixels = cairo_image_surface_get_data (output);
2141
2257
 
2142
2258
    for (y = boundarys.y0; y < boundarys.y1; y++)
2143
2259
        for (x = boundarys.x0; x < boundarys.x1; x++) {
2164
2280
                    outpix[ctx->channelmap[c]] * outpix[achan] / 255;
2165
2281
            output_pixels[y * rowstride + x * 4 + achan] = outpix[achan];
2166
2282
        }
 
2283
 
 
2284
    cairo_surface_mark_dirty (output);
 
2285
 
2167
2286
    rsvg_filter_store_result (self->result, output, ctx);
2168
2287
 
2169
 
    g_object_unref (in);
2170
 
    g_object_unref (output);
 
2288
    cairo_surface_destroy (in);
 
2289
    cairo_surface_destroy (output);
2171
2290
}
2172
2291
 
2173
2292
static void
2311
2430
 
2312
2431
    RsvgFilterPrimitiveErode *upself;
2313
2432
 
2314
 
    GdkPixbuf *output;
2315
 
    GdkPixbuf *in;
 
2433
    cairo_surface_t *output, *in;
2316
2434
 
2317
2435
    gint kx, ky;
2318
2436
    guchar val;
2321
2439
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
2322
2440
 
2323
2441
    in = rsvg_filter_get_in (self->in, ctx);
2324
 
    in_pixels = gdk_pixbuf_get_pixels (in);
2325
 
 
2326
 
    height = gdk_pixbuf_get_height (in);
2327
 
    width = gdk_pixbuf_get_width (in);
2328
 
 
2329
 
    rowstride = gdk_pixbuf_get_rowstride (in);
 
2442
    if (in == NULL)
 
2443
        return;
 
2444
 
 
2445
    cairo_surface_flush (in);
 
2446
 
 
2447
    in_pixels = cairo_image_surface_get_data (in);
 
2448
 
 
2449
    height = cairo_image_surface_get_height (in);
 
2450
    width = cairo_image_surface_get_width (in);
 
2451
 
 
2452
    rowstride = cairo_image_surface_get_stride (in);
2330
2453
 
2331
2454
    /* scale the radius values */
2332
 
    kx = upself->rx * ctx->paffine[0];
2333
 
    ky = upself->ry * ctx->paffine[3];
2334
 
 
2335
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
2336
 
 
2337
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
2455
    kx = upself->rx * ctx->paffine.xx;
 
2456
    ky = upself->ry * ctx->paffine.yy;
 
2457
 
 
2458
    output = _rsvg_image_surface_new (width, height);
 
2459
    if (output == NULL) {
 
2460
        cairo_surface_destroy (in);
 
2461
        return;
 
2462
    }
 
2463
 
 
2464
    output_pixels = cairo_image_surface_get_data (output);
2338
2465
 
2339
2466
    for (y = boundarys.y0; y < boundarys.y1; y++)
2340
2467
        for (x = boundarys.x0; x < boundarys.x1; x++)
2362
2489
                    }
2363
2490
                output_pixels[y * rowstride + x * 4 + ch] = extreme;
2364
2491
            }
 
2492
 
 
2493
    cairo_surface_mark_dirty (output);
 
2494
 
2365
2495
    rsvg_filter_store_result (self->result, output, ctx);
2366
2496
 
2367
 
    g_object_unref (in);
2368
 
    g_object_unref (output);
 
2497
    cairo_surface_destroy (in);
 
2498
    cairo_surface_destroy (output);
2369
2499
}
2370
2500
 
2371
2501
static void
2464
2594
 
2465
2595
    RsvgFilterPrimitiveComposite *upself;
2466
2596
 
2467
 
    GdkPixbuf *output;
2468
 
    GdkPixbuf *in;
2469
 
    GdkPixbuf *in2;
 
2597
    cairo_surface_t *output, *in, *in2;
2470
2598
 
2471
2599
    upself = (RsvgFilterPrimitiveComposite *) self;
2472
2600
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
2473
2601
 
2474
2602
    in = rsvg_filter_get_in (self->in, ctx);
2475
 
    in_pixels = gdk_pixbuf_get_pixels (in);
 
2603
    if (in == NULL)
 
2604
        return;
 
2605
 
 
2606
    cairo_surface_flush (in);
 
2607
 
2476
2608
    in2 = rsvg_filter_get_in (upself->in2, ctx);
2477
 
    in2_pixels = gdk_pixbuf_get_pixels (in2);
2478
 
 
2479
 
    height = gdk_pixbuf_get_height (in);
2480
 
    width = gdk_pixbuf_get_width (in);
2481
 
 
2482
 
    rowstride = gdk_pixbuf_get_rowstride (in);
2483
 
 
2484
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
2485
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
2609
    if (in2 == NULL) {
 
2610
        cairo_surface_destroy (in);
 
2611
        return;
 
2612
    }
 
2613
 
 
2614
    cairo_surface_flush (in2);
 
2615
 
 
2616
    in_pixels = cairo_image_surface_get_data (in);
 
2617
    in2_pixels = cairo_image_surface_get_data (in2);
 
2618
 
 
2619
    height = cairo_image_surface_get_height (in);
 
2620
    width = cairo_image_surface_get_width (in);
 
2621
 
 
2622
    rowstride = cairo_image_surface_get_stride (in);
 
2623
 
 
2624
    output = _rsvg_image_surface_new (width, height);
 
2625
    if (output == NULL) {
 
2626
        cairo_surface_destroy (in);
 
2627
        cairo_surface_destroy (in2);
 
2628
        return;
 
2629
    }
 
2630
 
 
2631
    output_pixels = cairo_image_surface_get_data (output);
2486
2632
 
2487
2633
    if (upself->mode == COMPOSITE_MODE_ARITHMETIC)
2488
2634
        for (y = boundarys.y0; y < boundarys.y1; y++)
2570
2716
                output_pixels[4 * x + y * rowstride + 3] = qr;
2571
2717
            }
2572
2718
 
 
2719
    cairo_surface_mark_dirty (output);
 
2720
 
2573
2721
    rsvg_filter_store_result (self->result, output, ctx);
2574
2722
 
2575
 
    g_object_unref (in);
2576
 
    g_object_unref (in2);
2577
 
    g_object_unref (output);
 
2723
    cairo_surface_destroy (in);
 
2724
    cairo_surface_destroy (in2);
 
2725
    cairo_surface_destroy (output);
2578
2726
}
2579
2727
 
2580
2728
static void
2672
2820
    gint rowstride, height, width;
2673
2821
    RsvgIRect boundarys;
2674
2822
    guchar *output_pixels;
2675
 
    GdkPixbuf *output;
 
2823
    cairo_surface_t *output;
2676
2824
    char pixcolour[4];
2677
2825
    RsvgFilterPrimitiveOutput out;
2678
2826
 
2683
2831
 
2684
2832
    height = ctx->height;
2685
2833
    width = ctx->width;
2686
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
2687
 
    rowstride = gdk_pixbuf_get_rowstride (output);
2688
 
 
2689
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
2834
    output = _rsvg_image_surface_new (width, height);
 
2835
    if (output == NULL)
 
2836
        return;
 
2837
 
 
2838
    rowstride = cairo_image_surface_get_stride (output);
 
2839
 
 
2840
    output_pixels = cairo_image_surface_get_data (output);
2690
2841
 
2691
2842
    for (i = 0; i < 3; i++)
2692
2843
        pixcolour[i] = (int) (((unsigned char *)
2698
2849
            for (i = 0; i < 4; i++)
2699
2850
                output_pixels[4 * x + y * rowstride + ctx->channelmap[i]] = pixcolour[i];
2700
2851
 
2701
 
    out.result = output;
 
2852
    cairo_surface_mark_dirty (output);
 
2853
 
 
2854
    out.surface = output;
2702
2855
    out.Rused = 1;
2703
2856
    out.Gused = 1;
2704
2857
    out.Bused = 1;
2707
2860
 
2708
2861
    rsvg_filter_store_output (self->result, out, ctx);
2709
2862
 
2710
 
    g_object_unref (output);
 
2863
    cairo_surface_destroy (output);
2711
2864
}
2712
2865
 
2713
2866
static void
2786
2939
 
2787
2940
    RsvgFilterPrimitiveDisplacementMap *upself;
2788
2941
 
2789
 
    GdkPixbuf *output;
2790
 
    GdkPixbuf *in;
2791
 
    GdkPixbuf *in2;
 
2942
    cairo_surface_t *output, *in, *in2;
2792
2943
 
2793
2944
    double ox, oy;
2794
2945
 
2796
2947
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
2797
2948
 
2798
2949
    in = rsvg_filter_get_in (self->in, ctx);
2799
 
    in_pixels = gdk_pixbuf_get_pixels (in);
 
2950
    if (in == NULL)
 
2951
        return;
 
2952
 
 
2953
    cairo_surface_flush (in);
2800
2954
 
2801
2955
    in2 = rsvg_filter_get_in (upself->in2, ctx);
2802
 
    in2_pixels = gdk_pixbuf_get_pixels (in2);
2803
 
 
2804
 
    height = gdk_pixbuf_get_height (in);
2805
 
    width = gdk_pixbuf_get_width (in);
2806
 
 
2807
 
    rowstride = gdk_pixbuf_get_rowstride (in);
2808
 
 
2809
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
2810
 
 
2811
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
2956
    if (in == NULL) {
 
2957
        cairo_surface_destroy (in);
 
2958
        return;
 
2959
    }
 
2960
 
 
2961
    cairo_surface_flush (in2);
 
2962
 
 
2963
    in_pixels = cairo_image_surface_get_data (in);
 
2964
    in2_pixels = cairo_image_surface_get_data (in2);
 
2965
 
 
2966
    height = cairo_image_surface_get_height (in);
 
2967
    width = cairo_image_surface_get_width (in);
 
2968
 
 
2969
    rowstride = cairo_image_surface_get_stride (in);
 
2970
 
 
2971
    output = _rsvg_image_surface_new (width, height);
 
2972
    if (output == NULL) {
 
2973
        cairo_surface_destroy (in);
 
2974
        cairo_surface_destroy (in2);
 
2975
        return;
 
2976
    }
 
2977
 
 
2978
    output_pixels = cairo_image_surface_get_data (output);
2812
2979
 
2813
2980
    switch (upself->xChannelSelector) {
2814
2981
    case 'R':
2849
3016
    for (y = boundarys.y0; y < boundarys.y1; y++)
2850
3017
        for (x = boundarys.x0; x < boundarys.x1; x++) {
2851
3018
            if (xch != 4)
2852
 
                ox = x + upself->scale * ctx->paffine[0] *
 
3019
                ox = x + upself->scale * ctx->paffine.xx *
2853
3020
                    ((double) in2_pixels[y * rowstride + x * 4 + xch] / 255.0 - 0.5);
2854
3021
            else
2855
3022
                ox = x;
2856
3023
 
2857
3024
            if (ych != 4)
2858
 
                oy = y + upself->scale * ctx->paffine[3] *
 
3025
                oy = y + upself->scale * ctx->paffine.yy *
2859
3026
                    ((double) in2_pixels[y * rowstride + x * 4 + ych] / 255.0 - 0.5);
2860
3027
            else
2861
3028
                oy = y;
2862
3029
 
2863
3030
            for (ch = 0; ch < 4; ch++) {
2864
3031
                output_pixels[y * rowstride + x * 4 + ch] =
2865
 
                    gdk_pixbuf_get_interp_pixel (in_pixels, ox, oy, ch, boundarys, rowstride);
 
3032
                    get_interp_pixel (in_pixels, ox, oy, ch, boundarys, rowstride);
2866
3033
            }
2867
3034
        }
2868
3035
 
 
3036
    cairo_surface_mark_dirty (output);
 
3037
 
2869
3038
    rsvg_filter_store_result (self->result, output, ctx);
2870
3039
 
2871
 
    g_object_unref (in);
2872
 
    g_object_unref (in2);
2873
 
    g_object_unref (output);
 
3040
    cairo_surface_destroy (in);
 
3041
    cairo_surface_destroy (in2);
 
3042
    cairo_surface_destroy (output);
2874
3043
}
2875
3044
 
2876
3045
static void
3185
3354
    gint x, y, tileWidth, tileHeight, rowstride, width, height;
3186
3355
    RsvgIRect boundarys;
3187
3356
    guchar *output_pixels;
3188
 
    GdkPixbuf *output;
3189
 
    gdouble affine[6];
3190
 
    GdkPixbuf *in;
 
3357
    cairo_surface_t *output, *in;
 
3358
    cairo_matrix_t affine;
 
3359
 
 
3360
    affine = ctx->paffine;
 
3361
    if (cairo_matrix_invert (&affine) != CAIRO_STATUS_SUCCESS)
 
3362
      return;
3191
3363
 
3192
3364
    in = rsvg_filter_get_in (self->in, ctx);
3193
 
    height = gdk_pixbuf_get_height (in);
3194
 
    width = gdk_pixbuf_get_width (in);
3195
 
    rowstride = gdk_pixbuf_get_rowstride (in);
 
3365
    if (in == NULL)
 
3366
        return;
 
3367
 
 
3368
    cairo_surface_flush (in);
 
3369
 
 
3370
    height = cairo_image_surface_get_height (in);
 
3371
    width = cairo_image_surface_get_width (in);
 
3372
    rowstride = cairo_image_surface_get_stride (in);
3196
3373
 
3197
3374
    upself = (RsvgFilterPrimitiveTurbulence *) self;
3198
3375
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
3200
3377
    tileWidth = (boundarys.x1 - boundarys.x0);
3201
3378
    tileHeight = (boundarys.y1 - boundarys.y0);
3202
3379
 
3203
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
3204
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
3380
    output = _rsvg_image_surface_new (width, height);
 
3381
    if (output == NULL) {
 
3382
        cairo_surface_destroy (in);
 
3383
        return;
 
3384
    }
3205
3385
 
3206
 
    _rsvg_affine_invert (affine, ctx->paffine);
 
3386
    output_pixels = cairo_image_surface_get_data (output);
3207
3387
 
3208
3388
    for (y = 0; y < tileHeight; y++) {
3209
3389
        for (x = 0; x < tileWidth; x++) {
3210
3390
            gint i;
3211
3391
            double point[2];
3212
3392
            guchar *pixel;
3213
 
            point[0] = affine[0] * (x + boundarys.x0) + affine[2] * (y + boundarys.y0) + affine[4];
3214
 
            point[1] = affine[1] * (x + boundarys.x0) + affine[3] * (y + boundarys.y0) + affine[5];
 
3393
            point[0] = affine.xx * (x + boundarys.x0) + affine.xy * (y + boundarys.y0) + affine.x0;
 
3394
            point[1] = affine.yx * (x + boundarys.x0) + affine.yy * (y + boundarys.y0) + affine.y0;
3215
3395
 
3216
3396
            pixel = output_pixels + 4 * (x + boundarys.x0) + (y + boundarys.y0) * rowstride;
3217
3397
 
3237
3417
        }
3238
3418
    }
3239
3419
 
 
3420
    cairo_surface_mark_dirty (output);
 
3421
 
3240
3422
    rsvg_filter_store_result (self->result, output, ctx);
3241
3423
 
3242
 
    g_object_unref (in);
3243
 
    g_object_unref (output);
 
3424
    cairo_surface_destroy (in);
 
3425
    cairo_surface_destroy (output);
3244
3426
}
3245
3427
 
3246
3428
static void
3326
3508
    GString *href;
3327
3509
};
3328
3510
 
3329
 
static GdkPixbuf *
 
3511
static cairo_surface_t *
3330
3512
rsvg_filter_primitive_image_render_in (RsvgFilterPrimitive * self, RsvgFilterContext * context)
3331
3513
{
3332
3514
    RsvgDrawingCtx *ctx;
3333
3515
    RsvgFilterPrimitiveImage *upself;
3334
 
    int i;
3335
3516
    RsvgNode *drawable;
3336
3517
 
3337
3518
    ctx = context->ctx;
3345
3526
    if (!drawable)
3346
3527
        return NULL;
3347
3528
 
3348
 
    for (i = 0; i < 6; i++)
3349
 
        rsvg_current_state (ctx)->affine[i] = context->paffine[i];
 
3529
    rsvg_current_state (ctx)->affine = context->paffine;
3350
3530
 
3351
 
    return rsvg_get_image_of_node (ctx, drawable, context->width, context->height);
 
3531
    return rsvg_get_surface_of_node (ctx, drawable, context->width, context->height);
3352
3532
}
3353
3533
 
3354
 
static GdkPixbuf *
 
3534
static cairo_surface_t *
3355
3535
rsvg_filter_primitive_image_render_ext (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
3356
3536
{
3357
3537
    RsvgIRect boundarys;
3358
3538
    RsvgFilterPrimitiveImage *upself;
3359
 
    GdkPixbuf *img;
 
3539
    cairo_surface_t *img, *intermediate;
3360
3540
    int i;
3361
 
    GdkPixbuf *intermediate;
3362
3541
    unsigned char *pixels;
3363
3542
    int channelmap[4];
3364
3543
    int length;
3376
3555
    if (width == 0 || height == 0)
3377
3556
        return NULL;
3378
3557
 
3379
 
    img = rsvg_pixbuf_new_from_href (upself->href->str,
3380
 
                                     rsvg_handle_get_base_uri (upself->ctx), NULL);
3381
 
 
 
3558
    img = rsvg_cairo_surface_new_from_href (upself->ctx,
 
3559
                                            upself->href->str,
 
3560
                                            NULL);
3382
3561
    if (!img)
3383
3562
        return NULL;
3384
3563
 
3385
 
    intermediate = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8, width, height);
3386
 
 
3387
 
 
3388
 
    rsvg_art_affine_image (img, intermediate,
3389
 
                           ctx->paffine,
3390
 
                           (boundarys.x1 - boundarys.x0) / ctx->paffine[0],
3391
 
                           (boundarys.y1 - boundarys.y0) / ctx->paffine[3]);
3392
 
 
3393
 
    if (!intermediate) {
3394
 
        g_object_unref (img);
 
3564
    intermediate = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
 
3565
    if (cairo_surface_status (intermediate) != CAIRO_STATUS_SUCCESS ||
 
3566
        !rsvg_art_affine_image (img, intermediate,
 
3567
                                &ctx->paffine,
 
3568
                                (gdouble) width / ctx->paffine.xx,
 
3569
                                (gdouble) height / ctx->paffine.yy)) {
 
3570
        cairo_surface_destroy (intermediate);
 
3571
        cairo_surface_destroy (img);
3395
3572
        return NULL;
3396
3573
    }
3397
3574
 
3398
 
    g_object_unref (img);
 
3575
    cairo_surface_destroy (img);
3399
3576
 
3400
 
    length = gdk_pixbuf_get_height (intermediate) * gdk_pixbuf_get_rowstride (intermediate);
 
3577
    length = cairo_image_surface_get_height (intermediate) * 
 
3578
             cairo_image_surface_get_stride (intermediate);
3401
3579
    for (i = 0; i < 4; i++)
3402
3580
        channelmap[i] = ctx->channelmap[i];
3403
 
    pixels = gdk_pixbuf_get_pixels (intermediate);
 
3581
    pixels = cairo_image_surface_get_data (intermediate);
3404
3582
    for (i = 0; i < length; i += 4) {
3405
3583
        unsigned char alpha;
3406
3584
        unsigned char pixel[4];
3418
3596
            pixels[i + ch] = pixel[ch];
3419
3597
    }
3420
3598
 
 
3599
    cairo_surface_mark_dirty (intermediate);
3421
3600
    return intermediate;
3422
 
 
3423
3601
}
3424
3602
 
3425
3603
static void
3428
3606
    RsvgIRect boundarys;
3429
3607
    RsvgFilterPrimitiveImage *upself;
3430
3608
    RsvgFilterPrimitiveOutput op;
 
3609
    int x, y;
3431
3610
 
3432
 
    GdkPixbuf *output, *img;
 
3611
    cairo_surface_t *output, *img;
3433
3612
 
3434
3613
    upself = (RsvgFilterPrimitiveImage *) self;
3435
3614
 
3438
3617
 
3439
3618
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
3440
3619
 
3441
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height);
 
3620
    output = _rsvg_image_surface_new (ctx->width, ctx->height);
 
3621
    if (output == NULL)
 
3622
        return;
3442
3623
 
3443
3624
    img = rsvg_filter_primitive_image_render_in (self, ctx);
3444
3625
    if (img == NULL) {
3445
3626
        img = rsvg_filter_primitive_image_render_ext (self, ctx);
3446
 
        if (img) {
3447
 
            gdk_pixbuf_copy_area (img, 0, 0,
3448
 
                                  boundarys.x1 - boundarys.x0,
3449
 
                                  boundarys.y1 - boundarys.y0, output, boundarys.x0, boundarys.y0);
3450
 
            g_object_unref (img);
3451
 
        }
 
3627
        x = y = 0;
3452
3628
    } else {
3453
 
        gdk_pixbuf_copy_area (img, boundarys.x0, boundarys.y0, boundarys.x1 - boundarys.x0,
3454
 
                              boundarys.y1 - boundarys.y0, output, boundarys.x0, boundarys.y0);
3455
 
        g_object_unref (img);
3456
 
    }
3457
 
 
3458
 
    op.result = output;
 
3629
        x = boundarys.x0;
 
3630
        y = boundarys.y0;
 
3631
    }
 
3632
    if (img) {
 
3633
        cairo_t *cr;
 
3634
 
 
3635
        cr = cairo_create (output);
 
3636
        cairo_set_source_surface (cr, img, x, y);
 
3637
        cairo_rectangle (cr, 0, 0,
 
3638
                         boundarys.x1 - boundarys.x0,
 
3639
                         boundarys.y1 - boundarys.y0);
 
3640
        cairo_clip (cr);
 
3641
        cairo_translate (cr, -boundarys.x0, -boundarys.y0);
 
3642
        cairo_paint (cr);
 
3643
        cairo_destroy (cr);
 
3644
 
 
3645
        cairo_surface_destroy (img);
 
3646
    }
 
3647
 
 
3648
    op.surface = output;
3459
3649
    op.bounds = boundarys;
3460
3650
    op.Rused = 1;
3461
3651
    op.Gused = 1;
3464
3654
 
3465
3655
    rsvg_filter_store_output (self->result, op, ctx);
3466
3656
 
3467
 
    g_object_unref (output);
 
3657
    cairo_surface_destroy (output);
3468
3658
}
3469
3659
 
3470
3660
static void
3526
3716
    filter->super.render = &rsvg_filter_primitive_image_render;
3527
3717
    filter->super.super.free = &rsvg_filter_primitive_image_free;
3528
3718
    filter->super.super.set_atts = rsvg_filter_primitive_image_set_atts;
 
3719
    filter->href = NULL;
3529
3720
    return (RsvgNode *) filter;
3530
3721
}
3531
3722
 
3719
3910
 
3720
3911
    Nx = -surfaceScale * factorx * ((gdouble)
3721
3912
                                    (Kx[0] *
3722
 
                                     gdk_pixbuf_get_interp_pixel (I, x - dx, y - dy, chan,
 
3913
                                     get_interp_pixel (I, x - dx, y - dy, chan,
3723
3914
                                                                  boundarys,
3724
3915
                                                                  rowstride) +
3725
 
                                     Kx[1] * gdk_pixbuf_get_interp_pixel (I, x, y - dy, chan,
3726
 
                                                                          boundarys,
3727
 
                                                                          rowstride) +
3728
 
                                     Kx[2] * gdk_pixbuf_get_interp_pixel (I, x + dx, y - dy, chan,
3729
 
                                                                          boundarys,
3730
 
                                                                          rowstride) +
3731
 
                                     Kx[3] * gdk_pixbuf_get_interp_pixel (I, x - dx, y, chan,
3732
 
                                                                          boundarys,
3733
 
                                                                          rowstride) +
3734
 
                                     Kx[4] * gdk_pixbuf_get_interp_pixel (I, x, y, chan, boundarys,
3735
 
                                                                          rowstride) +
3736
 
                                     Kx[5] * gdk_pixbuf_get_interp_pixel (I, x + dx, y, chan,
3737
 
                                                                          boundarys,
3738
 
                                                                          rowstride) +
3739
 
                                     Kx[6] * gdk_pixbuf_get_interp_pixel (I, x - dx, y + dy, chan,
3740
 
                                                                          boundarys,
3741
 
                                                                          rowstride) +
3742
 
                                     Kx[7] * gdk_pixbuf_get_interp_pixel (I, x, y + dy, chan,
3743
 
                                                                          boundarys,
3744
 
                                                                          rowstride) +
3745
 
                                     Kx[8] * gdk_pixbuf_get_interp_pixel (I, x + dx, y + dy, chan,
 
3916
                                     Kx[1] * get_interp_pixel (I, x, y - dy, chan,
 
3917
                                                                          boundarys,
 
3918
                                                                          rowstride) +
 
3919
                                     Kx[2] * get_interp_pixel (I, x + dx, y - dy, chan,
 
3920
                                                                          boundarys,
 
3921
                                                                          rowstride) +
 
3922
                                     Kx[3] * get_interp_pixel (I, x - dx, y, chan,
 
3923
                                                                          boundarys,
 
3924
                                                                          rowstride) +
 
3925
                                     Kx[4] * get_interp_pixel (I, x, y, chan, boundarys,
 
3926
                                                                          rowstride) +
 
3927
                                     Kx[5] * get_interp_pixel (I, x + dx, y, chan,
 
3928
                                                                          boundarys,
 
3929
                                                                          rowstride) +
 
3930
                                     Kx[6] * get_interp_pixel (I, x - dx, y + dy, chan,
 
3931
                                                                          boundarys,
 
3932
                                                                          rowstride) +
 
3933
                                     Kx[7] * get_interp_pixel (I, x, y + dy, chan,
 
3934
                                                                          boundarys,
 
3935
                                                                          rowstride) +
 
3936
                                     Kx[8] * get_interp_pixel (I, x + dx, y + dy, chan,
3746
3937
                                                                          boundarys,
3747
3938
                                                                          rowstride))) / 255.0;
3748
3939
 
3749
3940
    Ny = -surfaceScale * factory * ((gdouble)
3750
3941
                                    (Ky[0] *
3751
 
                                     gdk_pixbuf_get_interp_pixel (I, x - dx, y - dy, chan,
 
3942
                                     get_interp_pixel (I, x - dx, y - dy, chan,
3752
3943
                                                                  boundarys,
3753
3944
                                                                  rowstride) +
3754
 
                                     Ky[1] * gdk_pixbuf_get_interp_pixel (I, x, y - dy, chan,
3755
 
                                                                          boundarys,
3756
 
                                                                          rowstride) +
3757
 
                                     Ky[2] * gdk_pixbuf_get_interp_pixel (I, x + dx, y - dy, chan,
3758
 
                                                                          boundarys,
3759
 
                                                                          rowstride) +
3760
 
                                     Ky[3] * gdk_pixbuf_get_interp_pixel (I, x - dx, y, chan,
3761
 
                                                                          boundarys,
3762
 
                                                                          rowstride) +
3763
 
                                     Ky[4] * gdk_pixbuf_get_interp_pixel (I, x, y, chan, boundarys,
3764
 
                                                                          rowstride) +
3765
 
                                     Ky[5] * gdk_pixbuf_get_interp_pixel (I, x + dx, y, chan,
3766
 
                                                                          boundarys,
3767
 
                                                                          rowstride) +
3768
 
                                     Ky[6] * gdk_pixbuf_get_interp_pixel (I, x - dx, y + dy, chan,
3769
 
                                                                          boundarys,
3770
 
                                                                          rowstride) +
3771
 
                                     Ky[7] * gdk_pixbuf_get_interp_pixel (I, x, y + dy, chan,
3772
 
                                                                          boundarys,
3773
 
                                                                          rowstride) +
3774
 
                                     Ky[8] * gdk_pixbuf_get_interp_pixel (I, x + dx, y + dy, chan,
 
3945
                                     Ky[1] * get_interp_pixel (I, x, y - dy, chan,
 
3946
                                                                          boundarys,
 
3947
                                                                          rowstride) +
 
3948
                                     Ky[2] * get_interp_pixel (I, x + dx, y - dy, chan,
 
3949
                                                                          boundarys,
 
3950
                                                                          rowstride) +
 
3951
                                     Ky[3] * get_interp_pixel (I, x - dx, y, chan,
 
3952
                                                                          boundarys,
 
3953
                                                                          rowstride) +
 
3954
                                     Ky[4] * get_interp_pixel (I, x, y, chan, boundarys,
 
3955
                                                                          rowstride) +
 
3956
                                     Ky[5] * get_interp_pixel (I, x + dx, y, chan,
 
3957
                                                                          boundarys,
 
3958
                                                                          rowstride) +
 
3959
                                     Ky[6] * get_interp_pixel (I, x - dx, y + dy, chan,
 
3960
                                                                          boundarys,
 
3961
                                                                          rowstride) +
 
3962
                                     Ky[7] * get_interp_pixel (I, x, y + dy, chan,
 
3963
                                                                          boundarys,
 
3964
                                                                          rowstride) +
 
3965
                                     Ky[8] * get_interp_pixel (I, x + dx, y + dy, chan,
3775
3966
                                                                          boundarys,
3776
3967
                                                                          rowstride))) / 255.0;
3777
3968
 
3801
3992
 
3802
3993
static vector3
3803
3994
get_light_direction (RsvgNodeLightSource * source, gdouble x1, gdouble y1, gdouble z,
3804
 
                     gdouble * affine, RsvgDrawingCtx * ctx)
 
3995
                     cairo_matrix_t *affine, RsvgDrawingCtx * ctx)
3805
3996
{
3806
3997
    vector3 output;
3807
3998
 
3814
4005
    default:
3815
4006
        {
3816
4007
            double x, y;
3817
 
            x = affine[0] * x1 + affine[2] * y1 + affine[4];
3818
 
            y = affine[1] * x1 + affine[3] * y1 + affine[5];
 
4008
            x = affine->xx * x1 + affine->xy * y1 + affine->x0;
 
4009
            y = affine->yx * x1 + affine->yy * y1 + affine->y0;
3819
4010
            output.x = _rsvg_css_normalize_length (&source->x, ctx, 'h') - x;
3820
4011
            output.y = _rsvg_css_normalize_length (&source->y, ctx, 'v') - y;
3821
4012
            output.z = _rsvg_css_normalize_length (&source->z, ctx, 'o') - z;
3828
4019
 
3829
4020
static vector3
3830
4021
get_light_colour (RsvgNodeLightSource * source, vector3 colour,
3831
 
                  gdouble x1, gdouble y1, gdouble z, gdouble * affine, RsvgDrawingCtx * ctx)
 
4022
                  gdouble x1, gdouble y1, gdouble z, cairo_matrix_t *affine, RsvgDrawingCtx * ctx)
3832
4023
{
3833
4024
    double base, angle, x, y;
3834
4025
    vector3 s;
3846
4037
    spy = _rsvg_css_normalize_length (&source->pointsAtY, ctx, 'v');
3847
4038
    spz = _rsvg_css_normalize_length (&source->pointsAtZ, ctx, 'o');
3848
4039
 
3849
 
    x = affine[0] * x1 + affine[2] * y1 + affine[4];
3850
 
    y = affine[1] * x1 + affine[3] * y1 + affine[5];
 
4040
    x = affine->xx * x1 + affine->xy * y1 + affine->x0;
 
4041
    y = affine->yx * x1 + affine->yy * y1 + affine->y0;
3851
4042
 
3852
4043
    L.x = sx - x;
3853
4044
    L.y = sy - y;
3861
4052
 
3862
4053
    base = -dotproduct (L, s);
3863
4054
 
3864
 
    angle = acos (base) * 180.0 / M_PI;
 
4055
    angle = acos (base);
3865
4056
 
3866
4057
    if (base < 0 || angle > source->limitingconeAngle) {
3867
4058
        output.x = 0;
3893
4084
        if ((value = rsvg_property_bag_lookup (atts, "elevation")))
3894
4085
            data->elevation = rsvg_css_parse_angle (value) / 180.0 * M_PI;
3895
4086
        if ((value = rsvg_property_bag_lookup (atts, "limitingConeAngle")))
3896
 
            data->limitingconeAngle = rsvg_css_parse_angle (value);
 
4087
            data->limitingconeAngle = rsvg_css_parse_angle (value) / 180.0 * M_PI;
3897
4088
        if ((value = rsvg_property_bag_lookup (atts, "x")))
3898
4089
            data->x = data->pointsAtX = _rsvg_css_parse_length (value);
3899
4090
        if ((value = rsvg_property_bag_lookup (atts, "y")))
3953
4144
    gdouble factor, surfaceScale;
3954
4145
    vector3 lightcolour, L, N;
3955
4146
    vector3 colour;
3956
 
    gdouble iaffine[6];
 
4147
    cairo_matrix_t iaffine;
3957
4148
    RsvgNodeLightSource *source = NULL;
3958
4149
    RsvgIRect boundarys;
3959
4150
 
3962
4153
 
3963
4154
    RsvgFilterPrimitiveDiffuseLighting *upself;
3964
4155
 
3965
 
    GdkPixbuf *output;
3966
 
    GdkPixbuf *in;
 
4156
    cairo_surface_t *output, *in;
 
4157
 
3967
4158
    unsigned int i;
3968
4159
 
3969
4160
    for (i = 0; i < self->super.children->len; i++) {
3977
4168
    if (source == NULL)
3978
4169
        return;
3979
4170
 
 
4171
    iaffine = ctx->paffine;
 
4172
    if (cairo_matrix_invert (&iaffine) != CAIRO_STATUS_SUCCESS)
 
4173
      return;
 
4174
 
3980
4175
    upself = (RsvgFilterPrimitiveDiffuseLighting *) self;
3981
4176
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
3982
4177
 
3983
4178
    in = rsvg_filter_get_in (self->in, ctx);
3984
 
    in_pixels = gdk_pixbuf_get_pixels (in);
3985
 
 
3986
 
    height = gdk_pixbuf_get_height (in);
3987
 
    width = gdk_pixbuf_get_width (in);
3988
 
 
3989
 
    rowstride = gdk_pixbuf_get_rowstride (in);
3990
 
 
3991
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
3992
 
 
3993
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
4179
    if (in == NULL)
 
4180
        return;
 
4181
 
 
4182
    cairo_surface_flush (in);
 
4183
 
 
4184
    in_pixels = cairo_image_surface_get_data (in);
 
4185
 
 
4186
    height = cairo_image_surface_get_height (in);
 
4187
    width = cairo_image_surface_get_width (in);
 
4188
 
 
4189
    rowstride = cairo_image_surface_get_stride (in);
 
4190
 
 
4191
    output = _rsvg_image_surface_new (width, height);
 
4192
    if (output == NULL) {
 
4193
        cairo_surface_destroy (in);
 
4194
        return;
 
4195
    }
 
4196
 
 
4197
    output_pixels = cairo_image_surface_get_data (output);
3994
4198
 
3995
4199
    colour.x = ((guchar *) (&upself->lightingcolour))[2] / 255.0;
3996
4200
    colour.y = ((guchar *) (&upself->lightingcolour))[1] / 255.0;
4004
4208
        rawdx = 1;
4005
4209
        rawdy = 1;
4006
4210
    } else {
4007
 
        dx = upself->dx * ctx->paffine[0];
4008
 
        dy = upself->dy * ctx->paffine[3];
 
4211
        dx = upself->dx * ctx->paffine.xx;
 
4212
        dy = upself->dy * ctx->paffine.yy;
4009
4213
        rawdx = upself->dx;
4010
4214
        rawdy = upself->dy;
4011
4215
    }
4012
4216
 
4013
 
    _rsvg_affine_invert (iaffine, ctx->paffine);
4014
 
 
4015
4217
    for (y = boundarys.y0; y < boundarys.y1; y++)
4016
4218
        for (x = boundarys.x0; x < boundarys.x1; x++) {
4017
4219
            z = surfaceScale * (double) in_pixels[y * rowstride + x * 4 + ctx->channelmap[3]];
4018
 
            L = get_light_direction (source, x, y, z, iaffine, ctx->ctx);
 
4220
            L = get_light_direction (source, x, y, z, &iaffine, ctx->ctx);
4019
4221
            N = get_surface_normal (in_pixels, boundarys, x, y,
4020
4222
                                    dx, dy, rawdx, rawdy, upself->surfaceScale,
4021
4223
                                    rowstride, ctx->channelmap[3]);
4022
 
            lightcolour = get_light_colour (source, colour, x, y, z, iaffine, ctx->ctx);
 
4224
            lightcolour = get_light_colour (source, colour, x, y, z, &iaffine, ctx->ctx);
4023
4225
            factor = dotproduct (N, L);
4024
4226
 
4025
4227
            output_pixels[y * rowstride + x * 4 + ctx->channelmap[0]] =
4031
4233
            output_pixels[y * rowstride + x * 4 + ctx->channelmap[3]] = 255;
4032
4234
        }
4033
4235
 
 
4236
    cairo_surface_mark_dirty (output);
 
4237
 
4034
4238
    rsvg_filter_store_result (self->result, output, ctx);
4035
4239
 
4036
 
    g_object_unref (in);
4037
 
    g_object_unref (output);
 
4240
    cairo_surface_destroy (in);
 
4241
    cairo_surface_destroy (output);
4038
4242
}
4039
4243
 
4040
4244
static void
4127
4331
    gdouble factor, max, base;
4128
4332
    vector3 lightcolour, colour;
4129
4333
    vector3 L;
4130
 
    gdouble iaffine[6];
 
4334
    cairo_matrix_t iaffine;
4131
4335
    RsvgIRect boundarys;
4132
4336
    RsvgNodeLightSource *source = NULL;
4133
4337
 
4136
4340
 
4137
4341
    RsvgFilterPrimitiveSpecularLighting *upself;
4138
4342
 
4139
 
    GdkPixbuf *output;
4140
 
    GdkPixbuf *in;
 
4343
    cairo_surface_t *output, *in;
4141
4344
 
4142
4345
    unsigned int i;
4143
4346
 
4151
4354
    if (source == NULL)
4152
4355
        return;
4153
4356
 
 
4357
    iaffine = ctx->paffine;
 
4358
    if (cairo_matrix_invert (&iaffine) != CAIRO_STATUS_SUCCESS)
 
4359
      return;
 
4360
 
4154
4361
    upself = (RsvgFilterPrimitiveSpecularLighting *) self;
4155
4362
    boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
4156
4363
 
4157
4364
    in = rsvg_filter_get_in (self->in, ctx);
4158
 
    in_pixels = gdk_pixbuf_get_pixels (in);
4159
 
 
4160
 
    height = gdk_pixbuf_get_height (in);
4161
 
    width = gdk_pixbuf_get_width (in);
4162
 
 
4163
 
    rowstride = gdk_pixbuf_get_rowstride (in);
4164
 
 
4165
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
4166
 
 
4167
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
4365
    if (in == NULL)
 
4366
        return;
 
4367
 
 
4368
    cairo_surface_flush (in);
 
4369
 
 
4370
    in_pixels = cairo_image_surface_get_data (in);
 
4371
 
 
4372
    height = cairo_image_surface_get_height (in);
 
4373
    width = cairo_image_surface_get_width (in);
 
4374
 
 
4375
    rowstride = cairo_image_surface_get_stride (in);
 
4376
 
 
4377
    output = _rsvg_image_surface_new (width, height);
 
4378
    if (output == NULL) {
 
4379
        cairo_surface_destroy (in);
 
4380
        return;
 
4381
    }
 
4382
 
 
4383
    output_pixels = cairo_image_surface_get_data (output);
4168
4384
 
4169
4385
    colour.x = ((guchar *) (&upself->lightingcolour))[2] / 255.0;
4170
4386
    colour.y = ((guchar *) (&upself->lightingcolour))[1] / 255.0;
4172
4388
 
4173
4389
    surfaceScale = upself->surfaceScale / 255.0;
4174
4390
 
4175
 
    _rsvg_affine_invert (iaffine, ctx->paffine);
4176
 
 
4177
4391
    for (y = boundarys.y0; y < boundarys.y1; y++)
4178
4392
        for (x = boundarys.x0; x < boundarys.x1; x++) {
4179
4393
            z = in_pixels[y * rowstride + x * 4 + 3] * surfaceScale;
4180
 
            L = get_light_direction (source, x, y, z, iaffine, ctx->ctx);
 
4394
            L = get_light_direction (source, x, y, z, &iaffine, ctx->ctx);
4181
4395
            L.z += 1;
4182
4396
            L = normalise (L);
4183
4397
 
4184
 
            lightcolour = get_light_colour (source, colour, x, y, z, iaffine, ctx->ctx);
 
4398
            lightcolour = get_light_colour (source, colour, x, y, z, &iaffine, ctx->ctx);
4185
4399
            base = dotproduct (get_surface_normal (in_pixels, boundarys, x, y,
4186
 
                                                   1, 1, 1.0 / ctx->paffine[0],
4187
 
                                                   1.0 / ctx->paffine[3], upself->surfaceScale,
 
4400
                                                   1, 1, 1.0 / ctx->paffine.xx,
 
4401
                                                   1.0 / ctx->paffine.yy, upself->surfaceScale,
4188
4402
                                                   rowstride, ctx->channelmap[3]), L);
4189
4403
 
4190
4404
            factor = upself->specularConstant * pow (base, upself->specularExponent) * 255;
4210
4424
 
4211
4425
        }
4212
4426
 
 
4427
    cairo_surface_mark_dirty (output);
 
4428
 
4213
4429
    rsvg_filter_store_result (self->result, output, ctx);
4214
4430
 
4215
 
    g_object_unref (in);
4216
 
    g_object_unref (output);
 
4431
    cairo_surface_destroy (in);
 
4432
    cairo_surface_destroy (output);
4217
4433
}
4218
4434
 
4219
4435
static void
4313
4529
    guchar *in_pixels;
4314
4530
    guchar *output_pixels;
4315
4531
 
4316
 
    GdkPixbuf *output;
4317
 
    GdkPixbuf *in;
4318
 
 
4319
 
    RsvgFilterPrimitiveTile *upself;
4320
 
 
4321
 
    upself = (RsvgFilterPrimitiveTile *) self;
 
4532
    cairo_surface_t *output, *in;
 
4533
 
4322
4534
    oboundarys = rsvg_filter_primitive_get_bounds (self, ctx);
4323
4535
 
4324
4536
    input = rsvg_filter_get_result (self->in, ctx);
4325
 
    in = input.result;
 
4537
    in = input.surface;
4326
4538
    boundarys = input.bounds;
4327
4539
 
4328
 
 
4329
 
    in_pixels = gdk_pixbuf_get_pixels (in);
4330
 
 
4331
 
    output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height);
4332
 
    rowstride = gdk_pixbuf_get_rowstride (output);
4333
 
 
4334
 
    output_pixels = gdk_pixbuf_get_pixels (output);
 
4540
    cairo_surface_flush (in);
 
4541
 
 
4542
    in_pixels = cairo_image_surface_get_data (in);
 
4543
 
 
4544
    output = _rsvg_image_surface_new (ctx->width, ctx->height);
 
4545
    if (output == NULL) {
 
4546
        cairo_surface_destroy (in);
 
4547
        return;
 
4548
    }
 
4549
 
 
4550
    rowstride = cairo_image_surface_get_stride (output);
 
4551
 
 
4552
    output_pixels = cairo_image_surface_get_data (output);
4335
4553
 
4336
4554
    for (y = oboundarys.y0; y < oboundarys.y1; y++)
4337
4555
        for (x = oboundarys.x0; x < oboundarys.x1; x++)
4343
4561
                               boundarys.y0) * rowstride + i];
4344
4562
            }
4345
4563
 
 
4564
    cairo_surface_mark_dirty (output);
 
4565
 
4346
4566
    rsvg_filter_store_result (self->result, output, ctx);
4347
4567
 
4348
 
    g_object_unref (output);
 
4568
    cairo_surface_destroy (in);
 
4569
    cairo_surface_destroy (output);
4349
4570
}
4350
4571
 
4351
4572
static void