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>
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.
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.
30
* This step includes (@x0, @y0) but not (@x3, @y3).
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
42
ksvg_art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
51
double z1_dot, z2_dot;
52
double z1_perp, z2_perp;
61
/* It's possible to optimize this routine a fair amount.
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.
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.
72
Third, at the last subdivision, x_m and y_m can be computed more
73
expeditiously (as in the routine above).
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.
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...
87
/* z3_0_dot is dist z0-z3 squared */
88
z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
90
/* todo: this test is far from satisfactory. */
94
/* we can avoid subdivision if:
96
z1 has distance no more than flatness from the z0-z3 line
98
z1 is no more z0'ward than flatness past z0-z3
100
z1 is more z0'ward than z3'ward on the line traversing z0-z3
102
and correspondingly for z2 */
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)
110
z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
111
if (z2_perp * z2_perp > max_perp_sq)
114
z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
115
if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
118
z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
119
if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
122
if (z1_dot + z1_dot > z3_0_dot)
125
if (z2_dot + z2_dot > z3_0_dot)
129
/* don't subdivide */
130
art_vpath_add_point (p_vpath, pn, pn_max,
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;
147
printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
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);
156
#define RENDER_LEVEL 4
157
#define RENDER_SIZE (1 << (RENDER_LEVEL))
160
* ksvg_art_bez_path_to_vec: Create vpath from bezier path.
162
* @flatness: Flatness control.
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.
169
* Return value: Newly allocated vpath.
172
ksvg_art_bez_path_to_vec(const ArtBpath *bez, double flatness)
175
int vec_n, vec_n_max;
180
vec_n_max = RENDER_SIZE;
181
vec = art_new (ArtVpath, vec_n_max);
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. */
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);
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)
205
case ART_MOVETO_OPEN:
208
x = bez[bez_index].x3;
209
y = bez[bez_index].y3;
210
vec[vec_n].code = bez[bez_index].code;
216
vec[vec_n].code = ART_END;
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;
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);
234
ksvg_art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
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,
240
x = bez[bez_index].x3;
241
y = bez[bez_index].y3;
245
while (bez[bez_index++].code != ART_END);
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. */
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.
257
* Initial values of x0, x1, and result values stored in first two
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])
275
/* do left and right edges */
276
if (affine[0] > EPSILON)
278
z = affine[2] * (y + 0.5) + affine[4];
279
x_intercept = -z / affine[0];
280
xi = ceil (x_intercept + EPSILON - 0.5);
283
x_intercept = (-z + src_width) / affine[0];
284
xi = ceil (x_intercept - EPSILON - 0.5);
288
else if (affine[0] < -EPSILON)
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);
295
x_intercept = -z / affine[0];
296
xi = ceil (x_intercept - EPSILON - 0.5);
302
z = affine[2] * (y + 0.5) + affine[4];
303
if (z < 0 || z >= src_width)
309
/* do top and bottom edges */
310
if (affine[1] > EPSILON)
312
z = affine[3] * (y + 0.5) + affine[5];
313
x_intercept = -z / affine[1];
314
xi = ceil (x_intercept + EPSILON - 0.5);
317
x_intercept = (-z + src_height) / affine[1];
318
xi = ceil (x_intercept - EPSILON - 0.5);
322
else if (affine[1] < -EPSILON)
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);
329
x_intercept = -z / affine[1];
330
xi = ceil (x_intercept - EPSILON - 0.5);
336
z = affine[3] * (y + 0.5) + affine[5];
337
if (z < 0 || z >= src_height)
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.
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
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,
378
* The @level parameter specifies the speed/quality tradeoff of the
379
* image interpolation. Currently, only ART_FILTER_NEAREST is
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.
385
void ksvg_art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
387
int src_width, int src_height, int src_rowstride,
388
const double affine[6],
389
ArtFilterLevel level,
390
ArtAlphaGamma *alphagamma,
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. */
398
art_u8 *dst_p, *dst_linestart;
405
art_affine_invert (inv, affine);
408
for (y = y0; y < y1; y++)
413
ksvg_art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
415
dst_p = dst_linestart + (run_x0 - x0) * 4;
416
for (x = run_x0; x < run_x1; x++)
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);
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);
434
dst_linestart += dst_rowstride;
437
for (y = y0; y < y1; y++)
442
ksvg_art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
444
dst_p = dst_linestart + (run_x0 - x0) * 4;
445
for (x = run_x0; x < run_x1; x++)
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;
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);
460
dst_linestart += dst_rowstride;
464
typedef struct _ksvgArtRgbAffineClipAlphaData ksvgArtRgbAffineClipAlphaData;
466
struct _ksvgArtRgbAffineClipAlphaData
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)
496
for(x = x0; x < x1; x++)
500
art_affine_point(&src_pt, &pt, inv);
502
src_x = (int)(src_pt.x);
503
src_y = (int)(src_pt.y);
505
if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
512
src_p = src + (src_y * src_rowstride) + src_x * 4;
514
srcAlpha = alpha * src_p[3] + 0x80;
515
srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
520
tmp = srcAlpha * (s - d) + 0x80;
521
tmp = (tmp + (tmp >> 8)) >> 8;
528
tmp = srcAlpha * (s - d) + 0x80;
529
tmp = (tmp + (tmp >> 8)) >> 8;
536
tmp = srcAlpha * (s - d) + 0x80;
537
tmp = (tmp + (tmp >> 8)) >> 8;
547
ksvg_art_rgb_affine_clip_callback (void *callback_data, int y,
548
int start, ArtSVPRenderAAStep *steps, int n_steps)
550
ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
553
art_u32 running_sum = start;
563
alphatab = data->alphatab;
570
alpha = (running_sum >> 16) & 0xff;
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);
575
for(k = 0; k < n_steps - 1; k++)
577
running_sum += steps[k].delta;
579
run_x1 = steps[k + 1].x;
582
alpha = (running_sum >> 16) & 0xff;
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);
587
running_sum += steps[k].delta;
590
alpha = (running_sum >> 16) & 0xff;
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);
597
alpha = (running_sum >> 16) & 0xff;
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);
602
data->dst += data->dst_rowstride;
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)
619
for(x = x0; x < x1; x++)
623
art_affine_point(&src_pt, &pt, inv);
625
src_x = (int)(src_pt.x);
626
src_y = (int)(src_pt.y);
628
if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
635
src_p = src + (src_y * src_rowstride) + src_x * 4;
637
srcAlpha = alpha * src_p[3] + 0x80;
638
srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
640
srcAlpha = (srcAlpha * *mask++) + 0x80;
641
srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
646
tmp = srcAlpha * (s - d) + 0x80;
647
tmp = (tmp + (tmp >> 8)) >> 8;
654
tmp = srcAlpha * (s - d) + 0x80;
655
tmp = (tmp + (tmp >> 8)) >> 8;
662
tmp = srcAlpha * (s - d) + 0x80;
663
tmp = (tmp + (tmp >> 8)) >> 8;
676
ksvg_art_rgb_affine_clip_mask_callback (void *callback_data, int y,
677
int start, ArtSVPRenderAAStep *steps, int n_steps)
679
ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
682
art_u32 running_sum = start;
687
const art_u8 *maskbuf;
693
alphatab = data->alphatab;
694
maskbuf = data->mask + (y - data->y0) * (x1 - x0);
701
alpha = (running_sum >> 16) & 0xff;
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);
706
for(k = 0; k < n_steps - 1; k++)
708
running_sum += steps[k].delta;
710
run_x1 = steps[k + 1].x;
713
alpha = (running_sum >> 16) & 0xff;
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);
718
running_sum += steps[k].delta;
721
alpha = (running_sum >> 16) & 0xff;
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);
728
alpha = (running_sum >> 16) & 0xff;
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);
733
data->dst += data->dst_rowstride;
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)
750
for(x = x0; x < x1; x++)
754
art_affine_point(&src_pt, &pt, inv);
756
src_x = (int)(src_pt.x);
757
src_y = (int)(src_pt.y);
759
if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
766
src_p = src + (src_y * src_rowstride) + src_x * 4;
768
#ifdef WORDS_BIGENDIAN
769
srcAlpha = alpha * src_p[0] + 0x80;
771
srcAlpha = alpha * src_p[3] + 0x80;
773
srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
776
#ifdef WORDS_BIGENDIAN
781
tmp = srcAlpha * (s - d) + 0x80;
782
tmp = (tmp + (tmp >> 8)) >> 8;
787
#ifdef WORDS_BIGENDIAN
792
tmp = srcAlpha * (s - d) + 0x80;
793
tmp = (tmp + (tmp >> 8)) >> 8;
798
#ifdef WORDS_BIGENDIAN
804
tmp = srcAlpha * (s - d) + 0x80;
805
tmp = (tmp + (tmp >> 8)) >> 8;
811
tmp = srcAlpha * (255 - d) + 0x80;
812
tmp = (tmp + (tmp >> 8)) >> 8;
822
ksvg_art_rgba_affine_clip_callback (void *callback_data, int y,
823
int start, ArtSVPRenderAAStep *steps, int n_steps)
825
ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
828
art_u32 running_sum = start;
838
alphatab = data->alphatab;
845
alpha = (running_sum >> 16) & 0xff;
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);
850
for(k = 0; k < n_steps - 1; k++)
852
running_sum += steps[k].delta;
854
run_x1 = steps[k + 1].x;
857
alpha = (running_sum >> 16) & 0xff;
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);
862
running_sum += steps[k].delta;
865
alpha = (running_sum >> 16) & 0xff;
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);
872
alpha = (running_sum >> 16) & 0xff;
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);
877
data->dst += data->dst_rowstride;
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)
894
for(x = x0; x < x1; x++)
898
art_affine_point(&src_pt, &pt, inv);
900
src_x = (int)(src_pt.x);
901
src_y = (int)(src_pt.y);
903
if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
910
src_p = src + (src_y * src_rowstride) + src_x * 4;
912
srcAlpha = alpha * src_p[3] + 0x80;
913
srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
915
srcAlpha = (srcAlpha * *mask++) + 0x80;
916
srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
921
tmp = srcAlpha * (s - d) + 0x80;
922
tmp = (tmp + (tmp >> 8)) >> 8;
929
tmp = srcAlpha * (s - d) + 0x80;
930
tmp = (tmp + (tmp >> 8)) >> 8;
937
tmp = srcAlpha * (s - d) + 0x80;
938
tmp = (tmp + (tmp >> 8)) >> 8;
944
tmp = srcAlpha * (255 - d) + 0x80;
945
tmp = (tmp + (tmp >> 8)) >> 8;
958
ksvg_art_rgba_affine_clip_mask_callback (void *callback_data, int y,
959
int start, ArtSVPRenderAAStep *steps, int n_steps)
961
ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
964
art_u32 running_sum = start;
969
const art_u8 *maskbuf;
975
alphatab = data->alphatab;
976
maskbuf = data->mask + (y - data->y0) * (x1 - x0);
983
alpha = (running_sum >> 16) & 0xff;
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);
988
for(k = 0; k < n_steps - 1; k++)
990
running_sum += steps[k].delta;
992
run_x1 = steps[k + 1].x;
995
alpha = (running_sum >> 16) & 0xff;
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);
1000
running_sum += steps[k].delta;
1003
alpha = (running_sum >> 16) & 0xff;
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);
1010
alpha = (running_sum >> 16) & 0xff;
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);
1015
data->dst += data->dst_rowstride;
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.
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
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,
1047
* The @level parameter specifies the speed/quality tradeoff of the
1048
* image interpolation. Currently, only ART_FILTER_NEAREST is
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.
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,
1056
int src_width, int src_height, int src_rowstride,
1057
const double affine[6],
1058
int alpha, const art_u8 *mask)
1060
ksvgArtRgbAffineClipAlphaData data;
1067
da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
1069
for(i = 0; i < 256; i++)
1071
data.alphatab[i] = a >> 16;
1076
data.dst_rowstride = dst_rowstride;
1082
art_affine_invert(data.inv, affine);
1085
data.src_width = src_width;
1086
data.src_height = src_height;
1087
data.src_rowstride = src_rowstride;
1089
if(dst_channels == 3)
1092
art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_affine_clip_mask_callback, &data);
1094
art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_affine_clip_callback, &data);
1099
art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_affine_clip_mask_callback, &data);
1101
art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_affine_clip_callback, &data);