~ubuntu-branches/ubuntu/maverick/scribus-ng/maverick-backports

« back to all changes in this revision

Viewing changes to scribus/libart/art_kmisc.c

  • Committer: Bazaar Package Importer
  • Author(s): Oleksandr Moskalenko
  • Date: 2009-02-09 09:25:18 UTC
  • mfrom: (5.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090209092518-iqsxmh3pjspgrdyd
Tags: 1.3.5.dfsg~svn20090208-2
debian/control: Use "type-handling -n arm,armel,armeb any" to generate the
list of architectures to build on.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <libart_lgpl/art_vpath.h>
2
 
#include <libart_lgpl/art_bpath.h>
3
 
#include <libart_lgpl/art_misc.h>
4
 
#include <libart_lgpl/art_affine.h>
5
 
#include <libart_lgpl/art_svp_render_aa.h>
6
 
 
7
 
#include "scconfig.h"
8
 
#include "art_kmisc.h"
9
 
#include <math.h>
10
 
 
11
 
/**
12
 
 * art_vpath_render_bez: Render a bezier segment into the vpath.
13
 
 * @p_vpath: Where the pointer to the #ArtVpath structure is stored.
14
 
 * @pn_points: Pointer to the number of points in *@p_vpath.
15
 
 * @pn_points_max: Pointer to the number of points allocated.
16
 
 * @x0: X coordinate of starting bezier point.
17
 
 * @y0: Y coordinate of starting bezier point.
18
 
 * @x1: X coordinate of first bezier control point.
19
 
 * @y1: Y coordinate of first bezier control point.
20
 
 * @x2: X coordinate of second bezier control point.
21
 
 * @y2: Y coordinate of second bezier control point.
22
 
 * @x3: X coordinate of ending bezier point.
23
 
 * @y3: Y coordinate of ending bezier point.
24
 
 * @flatness: Flatness control.
25
 
 *
26
 
 * Renders a bezier segment into the vector path, reallocating and
27
 
 * updating *@p_vpath and *@pn_vpath_max as necessary. *@pn_vpath is
28
 
 * incremented by the number of vector points added.
29
 
 *
30
 
 * This step includes (@x0, @y0) but not (@x3, @y3).
31
 
 *
32
 
 * The @flatness argument guides the amount of subdivision. The Adobe
33
 
 * PostScript reference manual defines flatness as the maximum
34
 
 * deviation between the any point on the vpath approximation and the
35
 
 * corresponding point on the "true" curve, and we follow this
36
 
 * definition here. A value of 0.25 should ensure high quality for aa
37
 
 
38
 
 
39
 
 * rendering.
40
 
 **/
41
 
 void
42
 
ksvg_art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
43
 
                double x0, double y0,
44
 
                double x1, double y1,
45
 
                double x2, double y2,
46
 
                double x3, double y3,
47
 
                double flatness)
48
 
{
49
 
        double x3_0, y3_0;
50
 
        double z3_0_dot;
51
 
        double z1_dot, z2_dot;
52
 
        double z1_perp, z2_perp;
53
 
        double max_perp_sq;
54
 
 
55
 
        double x_m, y_m;
56
 
        double xa1, ya1;
57
 
        double xa2, ya2;
58
 
        double xb1, yb1;
59
 
        double xb2, yb2;
60
 
 
61
 
        /* It's possible to optimize this routine a fair amount.
62
 
 
63
 
           First, once the _dot conditions are met, they will also be met in
64
 
           all further subdivisions. So we might recurse to a different
65
 
           routine that only checks the _perp conditions.
66
 
 
67
 
           Second, the distance _should_ decrease according to fairly
68
 
           predictable rules (a factor of 4 with each subdivision). So it might
69
 
           be possible to note that the distance is within a factor of 4 of
70
 
           acceptable, and subdivide once. But proving this might be hard.
71
 
 
72
 
           Third, at the last subdivision, x_m and y_m can be computed more
73
 
           expeditiously (as in the routine above).
74
 
 
75
 
           Finally, if we were able to subdivide by, say 2 or 3, this would
76
 
           allow considerably finer-grain control, i.e. fewer points for the
77
 
           same flatness tolerance. This would speed things up downstream.
78
 
 
79
 
           In any case, this routine is unlikely to be the bottleneck. It's
80
 
           just that I have this undying quest for more speed...
81
 
 
82
 
*/
83
 
 
84
 
        x3_0 = x3 - x0;
85
 
        y3_0 = y3 - y0;
86
 
 
87
 
        /* z3_0_dot is dist z0-z3 squared */
88
 
        z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
89
 
 
90
 
        /* todo: this test is far from satisfactory. */
91
 
        if (z3_0_dot < 0.001)
92
 
                goto nosubdivide;
93
 
 
94
 
        /* we can avoid subdivision if:
95
 
 
96
 
           z1 has distance no more than flatness from the z0-z3 line
97
 
 
98
 
           z1 is no more z0'ward than flatness past z0-z3
99
 
 
100
 
           z1 is more z0'ward than z3'ward on the line traversing z0-z3
101
 
 
102
 
           and correspondingly for z2 */
103
 
 
104
 
        /* perp is distance from line, multiplied by dist z0-z3 */
105
 
        max_perp_sq = flatness * flatness * z3_0_dot;
106
 
        z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
107
 
        if (z1_perp * z1_perp > max_perp_sq)
108
 
                goto subdivide;
109
 
 
110
 
        z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
111
 
        if (z2_perp * z2_perp > max_perp_sq)
112
 
                goto subdivide;
113
 
 
114
 
        z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
115
 
        if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
116
 
                goto subdivide;
117
 
 
118
 
        z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
119
 
        if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
120
 
                goto subdivide;
121
 
 
122
 
        if (z1_dot + z1_dot > z3_0_dot)
123
 
                goto subdivide;
124
 
 
125
 
        if (z2_dot + z2_dot > z3_0_dot)
126
 
                goto subdivide;
127
 
 
128
 
nosubdivide:
129
 
        /* don't subdivide */
130
 
        art_vpath_add_point (p_vpath, pn, pn_max,
131
 
                        ART_LINETO, x3, y3);
132
 
        return;
133
 
 
134
 
subdivide:
135
 
 
136
 
        xa1 = (x0 + x1) * 0.5;
137
 
        ya1 = (y0 + y1) * 0.5;
138
 
        xa2 = (x0 + 2 * x1 + x2) * 0.25;
139
 
        ya2 = (y0 + 2 * y1 + y2) * 0.25;
140
 
        xb1 = (x1 + 2 * x2 + x3) * 0.25;
141
 
        yb1 = (y1 + 2 * y2 + y3) * 0.25;
142
 
        xb2 = (x2 + x3) * 0.5;
143
 
        yb2 = (y2 + y3) * 0.5;
144
 
        x_m = (xa2 + xb1) * 0.5;
145
 
        y_m = (ya2 + yb1) * 0.5;
146
 
#ifdef VERBOSE
147
 
        printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
148
 
                        xb1, yb1, xb2, yb2);
149
 
#endif
150
 
        ksvg_art_vpath_render_bez (p_vpath, pn, pn_max,
151
 
                        x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
152
 
        ksvg_art_vpath_render_bez (p_vpath, pn, pn_max,
153
 
                        x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
154
 
}
155
 
 
156
 
#define RENDER_LEVEL 4
157
 
#define RENDER_SIZE (1 << (RENDER_LEVEL))
158
 
 
159
 
/**
160
 
 * ksvg_art_bez_path_to_vec: Create vpath from bezier path.
161
 
 * @bez: Bezier path.
162
 
 * @flatness: Flatness control.
163
 
 *
164
 
 * Creates a vector path closely approximating the bezier path defined by
165
 
 * @bez. The @flatness argument controls the amount of subdivision. In
166
 
 * general, the resulting vpath deviates by at most @flatness pixels
167
 
 * from the "ideal" path described by @bez.
168
 
 *
169
 
 * Return value: Newly allocated vpath.
170
 
 **/
171
 
 ArtVpath *
172
 
ksvg_art_bez_path_to_vec(const ArtBpath *bez, double flatness)
173
 
{
174
 
        ArtVpath *vec;
175
 
        int vec_n, vec_n_max;
176
 
        int bez_index;
177
 
        double x, y;
178
 
 
179
 
        vec_n = 0;
180
 
        vec_n_max = RENDER_SIZE;
181
 
        vec = art_new (ArtVpath, vec_n_max);
182
 
 
183
 
        /* Initialization is unnecessary because of the precondition that the
184
 
           bezier path does not begin with LINETO or CURVETO, but is here
185
 
           to make the code warning-free. */
186
 
        x = 0;
187
 
        y = 0;
188
 
 
189
 
        bez_index = 0;
190
 
        do
191
 
        {
192
 
#ifdef VERBOSE
193
 
                printf ("%s %g %g\n",
194
 
                                bez[bez_index].code == ART_CURVETO ? "curveto" :
195
 
                                bez[bez_index].code == ART_LINETO ? "lineto" :
196
 
                                bez[bez_index].code == ART_MOVETO ? "moveto" :
197
 
                                bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" :
198
 
                                "end", bez[bez_index].x3, bez[bez_index].y3);
199
 
#endif
200
 
                /* make sure space for at least one more code */
201
 
                if (vec_n >= vec_n_max)
202
 
                        art_expand (vec, ArtVpath, vec_n_max);
203
 
                switch (bez[bez_index].code)
204
 
                {
205
 
                        case ART_MOVETO_OPEN:
206
 
                        case ART_MOVETO:
207
 
                        case ART_LINETO:
208
 
                                x = bez[bez_index].x3;
209
 
                                y = bez[bez_index].y3;
210
 
                                vec[vec_n].code = bez[bez_index].code;
211
 
                                vec[vec_n].x = x;
212
 
                                vec[vec_n].y = y;
213
 
                                vec_n++;
214
 
                                break;
215
 
                        case ART_END:
216
 
                                vec[vec_n].code = ART_END;
217
 
                                vec[vec_n].x = 0;
218
 
                                vec[vec_n].y = 0;
219
 
                                vec_n++;
220
 
                                break;
221
 
                        case ART_END2:
222
 
                                vec[vec_n].code = (ArtPathcode)ART_END2;
223
 
                                vec[vec_n].x = bez[bez_index].x3;
224
 
                                vec[vec_n].y = bez[bez_index].y3;
225
 
                                vec_n++;
226
 
                                break;
227
 
                        case ART_CURVETO:
228
 
#ifdef VERBOSE
229
 
                                printf ("%g,%g %g,%g %g,%g %g,%g\n", x, y,
230
 
                                                bez[bez_index].x1, bez[bez_index].y1,
231
 
                                                bez[bez_index].x2, bez[bez_index].y2,
232
 
                                                bez[bez_index].x3, bez[bez_index].y3);
233
 
#endif
234
 
                                ksvg_art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
235
 
                                                x, y,
236
 
                                                bez[bez_index].x1, bez[bez_index].y1,
237
 
                                                bez[bez_index].x2, bez[bez_index].y2,
238
 
                                                bez[bez_index].x3, bez[bez_index].y3,
239
 
                                                flatness);
240
 
                                x = bez[bez_index].x3;
241
 
                                y = bez[bez_index].y3;
242
 
                                break;
243
 
                }
244
 
        }
245
 
        while (bez[bez_index++].code != ART_END);
246
 
        return vec;
247
 
}
248
 
 
249
 
/* Private functions for the rgb affine image compositors - primarily,
250
 
*    the determination of runs, eliminating the need for source image
251
 
*       bbox calculation in the inner loop. */
252
 
 
253
 
/* Determine a "run", such that the inverse affine of all pixels from
254
 
*    (x0, y) inclusive to (x1, y) exclusive fit within the bounds
255
 
*       of the source image.
256
 
*
257
 
*          Initial values of x0, x1, and result values stored in first two
258
 
*             pointer arguments.
259
 
*             */
260
 
 
261
 
#define EPSILON 1e-6
262
 
 
263
 
 void ksvg_art_rgb_affine_run (int *p_x0, int *p_x1, int y,
264
 
                int src_width, int src_height,
265
 
                const double affine[6])
266
 
{
267
 
        int x0, x1;
268
 
        double z;
269
 
        double x_intercept;
270
 
        int xi;
271
 
 
272
 
        x0 = *p_x0;
273
 
        x1 = *p_x1;
274
 
 
275
 
        /* do left and right edges */
276
 
        if (affine[0] > EPSILON)
277
 
        {
278
 
                z = affine[2] * (y + 0.5) + affine[4];
279
 
                x_intercept = -z / affine[0];
280
 
                xi = ceil (x_intercept + EPSILON - 0.5);
281
 
                if (xi > x0)
282
 
                        x0 = xi;
283
 
                x_intercept = (-z + src_width) / affine[0];
284
 
                xi = ceil (x_intercept - EPSILON - 0.5);
285
 
                if (xi < x1)
286
 
                        x1 = xi;
287
 
        }
288
 
        else if (affine[0] < -EPSILON)
289
 
        {
290
 
                z = affine[2] * (y + 0.5) + affine[4];
291
 
                x_intercept = (-z + src_width) / affine[0];
292
 
                xi = ceil (x_intercept + EPSILON - 0.5);
293
 
                if (xi > x0)
294
 
                        x0 = xi;
295
 
                x_intercept = -z / affine[0];
296
 
                xi = ceil (x_intercept - EPSILON - 0.5);
297
 
                if (xi < x1)
298
 
                        x1 = xi;
299
 
        }
300
 
        else
301
 
        {
302
 
                z = affine[2] * (y + 0.5) + affine[4];
303
 
                if (z < 0 || z >= src_width)
304
 
                {
305
 
                        *p_x1 = *p_x0;
306
 
                        return;
307
 
                }
308
 
        }
309
 
        /* do top and bottom edges */
310
 
        if (affine[1] > EPSILON)
311
 
        {
312
 
                z = affine[3] * (y + 0.5) + affine[5];
313
 
                x_intercept = -z / affine[1];
314
 
                xi = ceil (x_intercept + EPSILON - 0.5);
315
 
                if (xi > x0)
316
 
                        x0 = xi;
317
 
                x_intercept = (-z + src_height) / affine[1];
318
 
                xi = ceil (x_intercept - EPSILON - 0.5);
319
 
                if (xi < x1)
320
 
                        x1 = xi;
321
 
        }
322
 
        else if (affine[1] < -EPSILON)
323
 
        {
324
 
                z = affine[3] * (y + 0.5) + affine[5];
325
 
                x_intercept = (-z + src_height) / affine[1];
326
 
                xi = ceil (x_intercept + EPSILON - 0.5);
327
 
                if (xi > x0)
328
 
                        x0 = xi;
329
 
                x_intercept = -z / affine[1];
330
 
                xi = ceil (x_intercept - EPSILON - 0.5);
331
 
                if (xi < x1)
332
 
                        x1 = xi;
333
 
        }
334
 
        else
335
 
        {
336
 
                z = affine[3] * (y + 0.5) + affine[5];
337
 
                if (z < 0 || z >= src_height)
338
 
                {
339
 
                        *p_x1 = *p_x0;
340
 
 
341
 
                        return;
342
 
                }
343
 
        }
344
 
 
345
 
 
346
 
        *p_x0 = x0;
347
 
        *p_x1 = x1;
348
 
}
349
 
 
350
 
/**
351
 
 * ksvg_art_rgb_affine: Affine transform source RGB image and composite.
352
 
 * @dst: Destination image RGB buffer.
353
 
 * @x0: Left coordinate of destination rectangle.
354
 
 * @y0: Top coordinate of destination rectangle.
355
 
 * @x1: Right coordinate of destination rectangle.
356
 
 * @y1: Bottom coordinate of destination rectangle.
357
 
 * @dst_rowstride: Rowstride of @dst buffer.
358
 
 * @src: Source image RGB buffer.
359
 
 * @src_width: Width of source image.
360
 
 * @src_height: Height of source image.
361
 
 * @src_rowstride: Rowstride of @src buffer.
362
 
 * @affine: Affine transform.
363
 
 * @level: Filter level.
364
 
 * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
365
 
 * @alpha: Alpha, range 0..256.
366
 
 *
367
 
 * Affine transform the source image stored in @src, compositing over
368
 
 * the area of destination image @dst specified by the rectangle
369
 
 * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
370
 
 * of this rectangle are included, and the right and bottom edges are
371
 
 * excluded.
372
 
 *
373
 
 * The @alphagamma parameter specifies that the alpha compositing be done
374
 
 * in a gamma-corrected color space. Since the source image is opaque RGB,
375
 
 * this argument only affects the edges. In the current implementation,
376
 
 * it is ignored.
377
 
 *
378
 
 * The @level parameter specifies the speed/quality tradeoff of the
379
 
 * image interpolation. Currently, only ART_FILTER_NEAREST is
380
 
 * implemented.
381
 
 *
382
 
 * KSVG additions : we have changed this function to support an alpha level as well.
383
 
*                  also we made sure compositing an rgba image over an rgb buffer works.
384
 
**/
385
 
 void ksvg_art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
386
 
                const art_u8 *src,
387
 
                int src_width, int src_height, int src_rowstride,
388
 
                const double affine[6],
389
 
                ArtFilterLevel level,
390
 
                ArtAlphaGamma *alphagamma,
391
 
                int alpha)
392
 
{
393
 
        /* Note: this is a slow implementation, and is missing all filter
394
 
           levels other than NEAREST. It is here for clarity of presentation
395
 
           and to establish the interface. */
396
 
        int x, y;
397
 
        double inv[6];
398
 
        art_u8 *dst_p, *dst_linestart;
399
 
        const art_u8 *src_p;
400
 
        ArtPoint pt, src_pt;
401
 
        int src_x, src_y;
402
 
        int run_x0, run_x1;
403
 
 
404
 
        dst_linestart = dst;
405
 
        art_affine_invert (inv, affine);
406
 
 
407
 
        if(alpha == 255)
408
 
                for (y = y0; y < y1; y++)
409
 
                {
410
 
                        pt.y = y + 0.5;
411
 
                        run_x0 = x0;
412
 
                        run_x1 = x1;
413
 
                        ksvg_art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
414
 
                                        inv);
415
 
                        dst_p = dst_linestart + (run_x0 - x0) * 4;
416
 
                        for (x = run_x0; x < run_x1; x++)
417
 
                        {
418
 
                                pt.x = x + 0.5;
419
 
                                art_affine_point (&src_pt, &pt, inv);
420
 
                                src_x = floor (src_pt.x);
421
 
                                src_y = floor (src_pt.y);
422
 
                                src_p = src + (src_y * src_rowstride) + src_x * 4;
423
 
#ifdef WORDS_BIGENDIAN
424
 
                                dst_p[0] = dst_p[0] + (((src_p[1] - dst_p[0]) * src_p[0] + 0x80) >> 8);
425
 
        dst_p[1] = dst_p[1] + (((src_p[2] - dst_p[1]) * src_p[0] + 0x80) >> 8);
426
 
        dst_p[2] = dst_p[2] + (((src_p[3] - dst_p[2]) * src_p[0] + 0x80) >> 8);
427
 
#else
428
 
                                dst_p[0] = dst_p[0] + (((src_p[2] - dst_p[0]) * src_p[3] + 0x80) >> 8);
429
 
                                dst_p[1] = dst_p[1] + (((src_p[1] - dst_p[1]) * src_p[3] + 0x80) >> 8);
430
 
                                dst_p[2] = dst_p[2] + (((src_p[0] - dst_p[2]) * src_p[3] + 0x80) >> 8);
431
 
#endif
432
 
                                dst_p += 4;
433
 
                        }
434
 
                        dst_linestart += dst_rowstride;
435
 
                }
436
 
        else
437
 
                for (y = y0; y < y1; y++)
438
 
                {
439
 
                        pt.y = y + 0.5;
440
 
                        run_x0 = x0;
441
 
                        run_x1 = x1;
442
 
                        ksvg_art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
443
 
                                        inv);
444
 
                        dst_p = dst_linestart + (run_x0 - x0) * 4;
445
 
                        for (x = run_x0; x < run_x1; x++)
446
 
                        {
447
 
                                pt.x = x + 0.5;
448
 
                                art_affine_point (&src_pt, &pt, inv);
449
 
                                src_x = floor (src_pt.x);
450
 
                                src_y = floor (src_pt.y);
451
 
                                src_p = src + (src_y * src_rowstride) + src_x * 4;
452
 
                                if (src_p[3] != 0)
453
 
                                        {
454
 
                                        dst_p[0] = dst_p[0] + (((src_p[2] - dst_p[0]) * alpha + 0x80) >> 8);
455
 
                                        dst_p[1] = dst_p[1] + (((src_p[1] - dst_p[1]) * alpha + 0x80) >> 8);
456
 
                                        dst_p[2] = dst_p[2] + (((src_p[0] - dst_p[2]) * alpha + 0x80) >> 8);
457
 
                                        }
458
 
                                dst_p += 4;
459
 
                        }
460
 
                        dst_linestart += dst_rowstride;
461
 
                }
462
 
}
463
 
 
464
 
typedef struct _ksvgArtRgbAffineClipAlphaData ksvgArtRgbAffineClipAlphaData;
465
 
 
466
 
struct _ksvgArtRgbAffineClipAlphaData
467
 
{
468
 
        int alphatab[256];
469
 
        art_u8 alpha;
470
 
        art_u8 *dst;
471
 
        int dst_rowstride;
472
 
        int x0, x1;
473
 
        double inv[6];
474
 
        const art_u8 *src;
475
 
        int src_width;
476
 
        int src_height;
477
 
        int src_rowstride;
478
 
        const art_u8 *mask;
479
 
        int y0;
480
 
};
481
 
 
482
 
static
483
 
void ksvg_art_rgb_affine_clip_run(art_u8 *dst_p, int x0, int x1, int y, const double inv[6],
484
 
        int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
485
 
{
486
 
        const art_u8 *src_p;
487
 
        ArtPoint pt, src_pt;
488
 
        int src_x, src_y;
489
 
        int x;
490
 
 
491
 
        if(alpha > 255)
492
 
                alpha = 255;
493
 
 
494
 
        pt.y = y;
495
 
 
496
 
        for(x = x0; x < x1; x++)
497
 
        {
498
 
                pt.x = x;
499
 
 
500
 
                art_affine_point(&src_pt, &pt, inv);
501
 
 
502
 
                src_x = (int)(src_pt.x);
503
 
                src_y = (int)(src_pt.y);
504
 
 
505
 
                if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
506
 
                {
507
 
                        int s;
508
 
                        int d;
509
 
                        int tmp;
510
 
                        int srcAlpha;
511
 
 
512
 
                        src_p = src + (src_y * src_rowstride) + src_x * 4;
513
 
 
514
 
                        srcAlpha = alpha * src_p[3] + 0x80;
515
 
                        srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
516
 
 
517
 
                        d = *dst_p;
518
 
                        s = src_p[2];
519
 
 
520
 
                        tmp = srcAlpha * (s - d) + 0x80;
521
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
522
 
 
523
 
                        *dst_p++ = d + tmp;
524
 
 
525
 
                        d = *dst_p;
526
 
                        s = src_p[1];
527
 
 
528
 
                        tmp = srcAlpha * (s - d) + 0x80;
529
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
530
 
 
531
 
                        *dst_p++ = d + tmp;
532
 
 
533
 
                        d = *dst_p;
534
 
                        s = src_p[0];
535
 
 
536
 
                        tmp = srcAlpha * (s - d) + 0x80;
537
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
538
 
 
539
 
                        *dst_p++ = d + tmp;
540
 
                }
541
 
                else
542
 
                        dst_p += 3;
543
 
        }
544
 
}
545
 
 
546
 
static void
547
 
ksvg_art_rgb_affine_clip_callback (void *callback_data, int y,
548
 
                                                                                                                int start, ArtSVPRenderAAStep *steps, int n_steps)
549
 
{
550
 
        ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
551
 
        art_u8 *linebuf;
552
 
        int run_x0, run_x1;
553
 
        art_u32 running_sum = start;
554
 
        int x0, x1;
555
 
        int k;
556
 
        int *alphatab;
557
 
        int alpha;
558
 
 
559
 
        linebuf = data->dst;
560
 
        x0 = data->x0;
561
 
        x1 = data->x1;
562
 
 
563
 
        alphatab = data->alphatab;
564
 
 
565
 
        if(n_steps > 0)
566
 
        {
567
 
                run_x1 = steps[0].x;
568
 
                if(run_x1 > x0)
569
 
                {
570
 
                        alpha = (running_sum >> 16) & 0xff;
571
 
                        if(alpha)
572
 
                                ksvg_art_rgb_affine_clip_run(linebuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
573
 
                }
574
 
 
575
 
                for(k = 0; k < n_steps - 1; k++)
576
 
                {
577
 
                        running_sum += steps[k].delta;
578
 
                        run_x0 = run_x1;
579
 
                        run_x1 = steps[k + 1].x;
580
 
                        if(run_x1 > run_x0)
581
 
                        {
582
 
                                alpha = (running_sum >> 16) & 0xff;
583
 
                                if(alpha)
584
 
                                        ksvg_art_rgb_affine_clip_run(linebuf + (run_x0 - x0) * 3, run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
585
 
                        }
586
 
                }
587
 
                running_sum += steps[k].delta;
588
 
                if(x1 > run_x1)
589
 
                {
590
 
                        alpha = (running_sum >> 16) & 0xff;
591
 
                        if(alpha)
592
 
                                ksvg_art_rgb_affine_clip_run(linebuf + (run_x1 - x0) * 3, run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
593
 
                }
594
 
        }
595
 
        else
596
 
        {
597
 
                alpha = (running_sum >> 16) & 0xff;
598
 
                if(alpha)
599
 
                        ksvg_art_rgb_affine_clip_run(linebuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
600
 
        }
601
 
 
602
 
        data->dst += data->dst_rowstride;
603
 
}
604
 
 
605
 
static
606
 
void ksvg_art_rgb_affine_clip_mask_run(art_u8 *dst_p, const art_u8 *mask, int x0, int x1, int y, const double inv[6],
607
 
        int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
608
 
{
609
 
        const art_u8 *src_p;
610
 
        ArtPoint pt, src_pt;
611
 
        int src_x, src_y;
612
 
        int x;
613
 
 
614
 
        if(alpha > 255)
615
 
                alpha = 255;
616
 
 
617
 
        pt.y = y;
618
 
 
619
 
        for(x = x0; x < x1; x++)
620
 
        {
621
 
                pt.x = x;
622
 
 
623
 
                art_affine_point(&src_pt, &pt, inv);
624
 
 
625
 
                src_x = (int)(src_pt.x);
626
 
                src_y = (int)(src_pt.y);
627
 
 
628
 
                if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
629
 
                {
630
 
                        int s;
631
 
                        int d;
632
 
                        int tmp;
633
 
                        int srcAlpha;
634
 
 
635
 
                        src_p = src + (src_y * src_rowstride) + src_x * 4;
636
 
 
637
 
                        srcAlpha = alpha * src_p[3] + 0x80;
638
 
                        srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
639
 
 
640
 
                        srcAlpha = (srcAlpha * *mask++) + 0x80;
641
 
                        srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
642
 
 
643
 
                        d = *dst_p;
644
 
                        s = src_p[2];
645
 
 
646
 
                        tmp = srcAlpha * (s - d) + 0x80;
647
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
648
 
 
649
 
                        *dst_p++ = d + tmp;
650
 
 
651
 
                        d = *dst_p;
652
 
                        s = src_p[1];
653
 
 
654
 
                        tmp = srcAlpha * (s - d) + 0x80;
655
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
656
 
 
657
 
                        *dst_p++ = d + tmp;
658
 
 
659
 
                        d = *dst_p;
660
 
                        s = src_p[0];
661
 
 
662
 
                        tmp = srcAlpha * (s - d) + 0x80;
663
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
664
 
 
665
 
                        *dst_p++ = d + tmp;
666
 
                }
667
 
                else
668
 
                {
669
 
                        dst_p += 3;
670
 
                        mask++;
671
 
                }
672
 
        }
673
 
}
674
 
 
675
 
static void
676
 
ksvg_art_rgb_affine_clip_mask_callback (void *callback_data, int y,
677
 
                                                                                                                int start, ArtSVPRenderAAStep *steps, int n_steps)
678
 
{
679
 
        ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
680
 
        art_u8 *linebuf;
681
 
        int run_x0, run_x1;
682
 
        art_u32 running_sum = start;
683
 
        int x0, x1;
684
 
        int k;
685
 
        int *alphatab;
686
 
        int alpha;
687
 
        const art_u8 *maskbuf;
688
 
 
689
 
        linebuf = data->dst;
690
 
        x0 = data->x0;
691
 
        x1 = data->x1;
692
 
 
693
 
        alphatab = data->alphatab;
694
 
        maskbuf = data->mask + (y - data->y0) * (x1 - x0);
695
 
 
696
 
        if(n_steps > 0)
697
 
        {
698
 
                run_x1 = steps[0].x;
699
 
                if(run_x1 > x0)
700
 
                {
701
 
                        alpha = (running_sum >> 16) & 0xff;
702
 
                        if(alpha)
703
 
                                ksvg_art_rgb_affine_clip_mask_run(linebuf, maskbuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
704
 
                }
705
 
 
706
 
                for(k = 0; k < n_steps - 1; k++)
707
 
                {
708
 
                        running_sum += steps[k].delta;
709
 
                        run_x0 = run_x1;
710
 
                        run_x1 = steps[k + 1].x;
711
 
                        if(run_x1 > run_x0)
712
 
                        {
713
 
                                alpha = (running_sum >> 16) & 0xff;
714
 
                                if(alpha)
715
 
                                        ksvg_art_rgb_affine_clip_mask_run(linebuf + (run_x0 - x0) * 3, maskbuf + (run_x0 - x0), run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
716
 
                        }
717
 
                }
718
 
                running_sum += steps[k].delta;
719
 
                if(x1 > run_x1)
720
 
                {
721
 
                        alpha = (running_sum >> 16) & 0xff;
722
 
                        if(alpha)
723
 
                                ksvg_art_rgb_affine_clip_mask_run(linebuf + (run_x1 - x0) * 3, maskbuf + (run_x1 - x0), run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
724
 
                }
725
 
        }
726
 
        else
727
 
        {
728
 
                alpha = (running_sum >> 16) & 0xff;
729
 
                if(alpha)
730
 
                        ksvg_art_rgb_affine_clip_mask_run(linebuf, maskbuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
731
 
        }
732
 
 
733
 
        data->dst += data->dst_rowstride;
734
 
}
735
 
 
736
 
static
737
 
void ksvg_art_rgba_affine_clip_run(art_u8 *dst_p, int x0, int x1, int y, const double inv[6],
738
 
        int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
739
 
{
740
 
        const art_u8 *src_p;
741
 
        ArtPoint pt, src_pt;
742
 
        int src_x, src_y;
743
 
        int x;
744
 
 
745
 
        if(alpha > 255)
746
 
                alpha = 255;
747
 
 
748
 
        pt.y = y;
749
 
 
750
 
        for(x = x0; x < x1; x++)
751
 
        {
752
 
                pt.x = x;
753
 
 
754
 
                art_affine_point(&src_pt, &pt, inv);
755
 
 
756
 
                src_x = (int)(src_pt.x);
757
 
                src_y = (int)(src_pt.y);
758
 
 
759
 
                if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
760
 
                {
761
 
                        int s;
762
 
                        int d;
763
 
                        int tmp;
764
 
                        int srcAlpha;
765
 
 
766
 
                        src_p = src + (src_y * src_rowstride) + src_x * 4;
767
 
 
768
 
#ifdef WORDS_BIGENDIAN
769
 
                        srcAlpha = alpha * src_p[0] + 0x80;
770
 
#else
771
 
                        srcAlpha = alpha * src_p[3] + 0x80;
772
 
#endif
773
 
                        srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
774
 
 
775
 
                        d = *dst_p;
776
 
#ifdef WORDS_BIGENDIAN  
777
 
                        s = src_p[1];
778
 
#else
779
 
                        s = src_p[2];
780
 
#endif
781
 
                        tmp = srcAlpha * (s - d) + 0x80;
782
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
783
 
 
784
 
                        *dst_p++ = d + tmp;
785
 
 
786
 
                        d = *dst_p;
787
 
#ifdef WORDS_BIGENDIAN  
788
 
                        s = src_p[2];
789
 
#else
790
 
                        s = src_p[1];
791
 
#endif
792
 
                        tmp = srcAlpha * (s - d) + 0x80;
793
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
794
 
 
795
 
                        *dst_p++ = d + tmp;
796
 
 
797
 
                        d = *dst_p;
798
 
#ifdef WORDS_BIGENDIAN  
799
 
                        s = src_p[3];
800
 
#else
801
 
                        s = src_p[0];
802
 
#endif
803
 
 
804
 
                        tmp = srcAlpha * (s - d) + 0x80;
805
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
806
 
 
807
 
                        *dst_p++ = d + tmp;
808
 
 
809
 
                        d = *dst_p;
810
 
 
811
 
                        tmp = srcAlpha * (255 - d) + 0x80;
812
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
813
 
 
814
 
                        *dst_p++ = d + tmp;
815
 
                }
816
 
                else
817
 
                        dst_p += 4;
818
 
        }
819
 
}
820
 
 
821
 
static void
822
 
ksvg_art_rgba_affine_clip_callback (void *callback_data, int y,
823
 
                                                                                                                int start, ArtSVPRenderAAStep *steps, int n_steps)
824
 
{
825
 
        ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
826
 
        art_u8 *linebuf;
827
 
        int run_x0, run_x1;
828
 
        art_u32 running_sum = start;
829
 
        int x0, x1;
830
 
        int k;
831
 
        int *alphatab;
832
 
        int alpha;
833
 
 
834
 
        linebuf = data->dst;
835
 
        x0 = data->x0;
836
 
        x1 = data->x1;
837
 
 
838
 
        alphatab = data->alphatab;
839
 
 
840
 
        if(n_steps > 0)
841
 
        {
842
 
                run_x1 = steps[0].x;
843
 
                if(run_x1 > x0)
844
 
                {
845
 
                        alpha = (running_sum >> 16) & 0xff;
846
 
                        if(alpha)
847
 
                                ksvg_art_rgba_affine_clip_run(linebuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
848
 
                }
849
 
 
850
 
                for(k = 0; k < n_steps - 1; k++)
851
 
                {
852
 
                        running_sum += steps[k].delta;
853
 
                        run_x0 = run_x1;
854
 
                        run_x1 = steps[k + 1].x;
855
 
                        if(run_x1 > run_x0)
856
 
                        {
857
 
                                alpha = (running_sum >> 16) & 0xff;
858
 
                                if(alpha)
859
 
                                        ksvg_art_rgba_affine_clip_run(linebuf + (run_x0 - x0) * 4, run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
860
 
                        }
861
 
                }
862
 
                running_sum += steps[k].delta;
863
 
                if(x1 > run_x1)
864
 
                {
865
 
                        alpha = (running_sum >> 16) & 0xff;
866
 
                        if(alpha)
867
 
                                ksvg_art_rgba_affine_clip_run(linebuf + (run_x1 - x0) * 4, run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
868
 
                }
869
 
        }
870
 
        else
871
 
        {
872
 
                alpha = (running_sum >> 16) & 0xff;
873
 
                if(alpha)
874
 
                        ksvg_art_rgba_affine_clip_run(linebuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
875
 
        }
876
 
 
877
 
        data->dst += data->dst_rowstride;
878
 
}
879
 
 
880
 
static
881
 
void ksvg_art_rgba_affine_clip_mask_run(art_u8 *dst_p, const art_u8 *mask, int x0, int x1, int y, const double inv[6],
882
 
        int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
883
 
{
884
 
        const art_u8 *src_p;
885
 
        ArtPoint pt, src_pt;
886
 
        int src_x, src_y;
887
 
        int x;
888
 
 
889
 
        if(alpha > 255)
890
 
                alpha = 255;
891
 
 
892
 
        pt.y = y;
893
 
 
894
 
        for(x = x0; x < x1; x++)
895
 
        {
896
 
                pt.x = x;
897
 
 
898
 
                art_affine_point(&src_pt, &pt, inv);
899
 
 
900
 
                src_x = (int)(src_pt.x);
901
 
                src_y = (int)(src_pt.y);
902
 
 
903
 
                if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
904
 
                {
905
 
                        int s;
906
 
                        int d;
907
 
                        int tmp;
908
 
                        int srcAlpha;
909
 
 
910
 
                        src_p = src + (src_y * src_rowstride) + src_x * 4;
911
 
 
912
 
                        srcAlpha = alpha * src_p[3] + 0x80;
913
 
                        srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
914
 
 
915
 
                        srcAlpha = (srcAlpha * *mask++) + 0x80;
916
 
                        srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
917
 
 
918
 
                        d = *dst_p;
919
 
                        s = src_p[2];
920
 
 
921
 
                        tmp = srcAlpha * (s - d) + 0x80;
922
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
923
 
 
924
 
                        *dst_p++ = d + tmp;
925
 
 
926
 
                        d = *dst_p;
927
 
                        s = src_p[1];
928
 
 
929
 
                        tmp = srcAlpha * (s - d) + 0x80;
930
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
931
 
 
932
 
                        *dst_p++ = d + tmp;
933
 
 
934
 
                        d = *dst_p;
935
 
                        s = src_p[0];
936
 
 
937
 
                        tmp = srcAlpha * (s - d) + 0x80;
938
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
939
 
 
940
 
                        *dst_p++ = d + tmp;
941
 
 
942
 
                        d = *dst_p;
943
 
 
944
 
                        tmp = srcAlpha * (255 - d) + 0x80;
945
 
                        tmp = (tmp + (tmp >> 8)) >> 8;
946
 
 
947
 
                        *dst_p++ = d + tmp;
948
 
                }
949
 
                else
950
 
                {
951
 
                        dst_p += 4;
952
 
                        mask++;
953
 
                }
954
 
        }
955
 
}
956
 
 
957
 
static void
958
 
ksvg_art_rgba_affine_clip_mask_callback (void *callback_data, int y,
959
 
                                                                                                                int start, ArtSVPRenderAAStep *steps, int n_steps)
960
 
{
961
 
        ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
962
 
        art_u8 *linebuf;
963
 
        int run_x0, run_x1;
964
 
        art_u32 running_sum = start;
965
 
        int x0, x1;
966
 
        int k;
967
 
        int *alphatab;
968
 
        int alpha;
969
 
        const art_u8 *maskbuf;
970
 
 
971
 
        linebuf = data->dst;
972
 
        x0 = data->x0;
973
 
        x1 = data->x1;
974
 
 
975
 
        alphatab = data->alphatab;
976
 
        maskbuf = data->mask + (y - data->y0) * (x1 - x0);
977
 
 
978
 
        if(n_steps > 0)
979
 
        {
980
 
                run_x1 = steps[0].x;
981
 
                if(run_x1 > x0)
982
 
                {
983
 
                        alpha = (running_sum >> 16) & 0xff;
984
 
                        if(alpha)
985
 
                                ksvg_art_rgba_affine_clip_mask_run(linebuf, maskbuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
986
 
                }
987
 
 
988
 
                for(k = 0; k < n_steps - 1; k++)
989
 
                {
990
 
                        running_sum += steps[k].delta;
991
 
                        run_x0 = run_x1;
992
 
                        run_x1 = steps[k + 1].x;
993
 
                        if(run_x1 > run_x0)
994
 
                        {
995
 
                                alpha = (running_sum >> 16) & 0xff;
996
 
                                if(alpha)
997
 
                                        ksvg_art_rgba_affine_clip_mask_run(linebuf + (run_x0 - x0) * 4, maskbuf + (run_x0 - x0), run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
998
 
                        }
999
 
                }
1000
 
                running_sum += steps[k].delta;
1001
 
                if(x1 > run_x1)
1002
 
                {
1003
 
                        alpha = (running_sum >> 16) & 0xff;
1004
 
                        if(alpha)
1005
 
                                ksvg_art_rgba_affine_clip_mask_run(linebuf + (run_x1 - x0) * 4, maskbuf + (run_x1 - x0), run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
1006
 
                }
1007
 
        }
1008
 
        else
1009
 
        {
1010
 
                alpha = (running_sum >> 16) & 0xff;
1011
 
                if(alpha)
1012
 
                        ksvg_art_rgba_affine_clip_mask_run(linebuf, maskbuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
1013
 
        }
1014
 
 
1015
 
        data->dst += data->dst_rowstride;
1016
 
}
1017
 
 
1018
 
/**
1019
 
 * ksvg_art_rgb_affine_clip: Affine transform source RGB image and composite, with clipping path.
1020
 
 * @svp: Clipping path.
1021
 
 * @dst: Destination image RGB buffer.
1022
 
 * @x0: Left coordinate of destination rectangle.
1023
 
 * @y0: Top coordinate of destination rectangle.
1024
 
 * @x1: Right coordinate of destination rectangle.
1025
 
 * @y1: Bottom coordinate of destination rectangle.
1026
 
 * @dst_rowstride: Rowstride of @dst buffer.
1027
 
 * @src: Source image RGB buffer.
1028
 
 * @src_width: Width of source image.
1029
 
 * @src_height: Height of source image.
1030
 
 * @src_rowstride: Rowstride of @src buffer.
1031
 
 * @affine: Affine transform.
1032
 
 * @level: Filter level.
1033
 
 * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
1034
 
 * @alpha: Alpha, range 0..256.
1035
 
 *
1036
 
 * Affine transform the source image stored in @src, compositing over
1037
 
 * the area of destination image @dst specified by the rectangle
1038
 
 * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
1039
 
 * of this rectangle are included, and the right and bottom edges are
1040
 
 * excluded.
1041
 
 *
1042
 
 * The @alphagamma parameter specifies that the alpha compositing be done
1043
 
 * in a gamma-corrected color space. Since the source image is opaque RGB,
1044
 
 * this argument only affects the edges. In the current implementation,
1045
 
 * it is ignored.
1046
 
 *
1047
 
 * The @level parameter specifies the speed/quality tradeoff of the
1048
 
 * image interpolation. Currently, only ART_FILTER_NEAREST is
1049
 
 * implemented.
1050
 
 *
1051
 
 * KSVG additions : we have changed this function to support an alpha level as well.
1052
 
*                  also we made sure compositing an rgba image over an rgb buffer works.
1053
 
**/
1054
 
void ksvg_art_rgb_affine_clip(const ArtSVP *svp, art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride, int dst_channels,
1055
 
                const art_u8 *src,
1056
 
                int src_width, int src_height, int src_rowstride,
1057
 
                const double affine[6],
1058
 
                int alpha, const art_u8 *mask)
1059
 
{
1060
 
        ksvgArtRgbAffineClipAlphaData data;
1061
 
        int i;
1062
 
        int a, da;
1063
 
 
1064
 
        data.alpha = alpha;
1065
 
 
1066
 
        a = 0x8000;
1067
 
        da = (alpha * 66051 + 0x80) >> 8;       /* 66051 equals 2 ^ 32 / (255 * 255) */
1068
 
 
1069
 
        for(i = 0; i < 256; i++)
1070
 
        {
1071
 
                data.alphatab[i] = a >> 16;
1072
 
                a += da;
1073
 
        }
1074
 
 
1075
 
        data.dst = dst;
1076
 
        data.dst_rowstride = dst_rowstride;
1077
 
        data.x0 = x0;
1078
 
        data.x1 = x1;
1079
 
        data.y0 = y0;
1080
 
        data.mask = mask;
1081
 
 
1082
 
        art_affine_invert(data.inv, affine);
1083
 
 
1084
 
        data.src = src;
1085
 
        data.src_width = src_width;
1086
 
        data.src_height = src_height;
1087
 
        data.src_rowstride = src_rowstride;
1088
 
 
1089
 
        if(dst_channels == 3)
1090
 
        {
1091
 
                if(mask)
1092
 
                        art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_affine_clip_mask_callback, &data);
1093
 
                else
1094
 
                        art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_affine_clip_callback, &data);
1095
 
        }
1096
 
        else
1097
 
        {
1098
 
                if(mask)
1099
 
                        art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_affine_clip_mask_callback, &data);
1100
 
                else
1101
 
                        art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_affine_clip_callback, &data);
1102
 
        }
1103
 
}
1104