fix crashes reported by Debian Cylab Mayhem Team
[swftools.git] / lib / art / art_render_svp.c
blob895e3ccf7d3d1039d65ce4e1eaa8cafb15ff3b95
1 /*
2 * art_render_gradient.c: SVP mask source for modular rendering.
4 * Libart_LGPL - library of basic graphic primitives
5 * Copyright (C) 2000 Raph Levien
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
22 * Authors: Raph Levien <raph@acm.org>
25 #include "art_render_svp.h"
26 #include "art_svp_render_aa.h"
28 typedef struct _ArtMaskSourceSVP ArtMaskSourceSVP;
30 struct _ArtMaskSourceSVP {
31 ArtMaskSource super;
32 ArtRender *render;
33 const ArtSVP *svp;
34 art_u8 *dest_ptr;
37 static void
38 art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
40 art_free (self);
43 static int
44 art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
46 return 10;
49 /* The basic art_render_svp_callback function is repeated four times,
50 for all combinations of non-unit opacity and generating spans. In
51 general, I'd consider this bad style, but in this case I plead
52 a measurable performance improvement. */
54 static void
55 art_render_svp_callback (void *callback_data, int y,
56 int start, ArtSVPRenderAAStep *steps, int n_steps)
58 ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
59 ArtRender *render = z->render;
60 int n_run = 0;
61 int i;
62 int running_sum = start;
63 int x0 = render->x0;
64 int x1 = render->x1;
65 int run_x0, run_x1;
66 ArtRenderMaskRun *run = render->run;
68 if (n_steps > 0)
70 run_x1 = steps[0].x;
71 if (run_x1 > x0 && running_sum > 0x80ff)
73 run[0].x = x0;
74 run[0].alpha = running_sum;
75 n_run++;
78 for (i = 0; i < n_steps - 1; i++)
80 running_sum += steps[i].delta;
81 run_x0 = run_x1;
82 run_x1 = steps[i + 1].x;
83 if (run_x1 > run_x0)
85 run[n_run].x = run_x0;
86 run[n_run].alpha = running_sum;
87 n_run++;
90 if (x1 > run_x1)
92 running_sum += steps[n_steps - 1].delta;
93 run[n_run].x = run_x1;
94 run[n_run].alpha = running_sum;
95 n_run++;
97 if (running_sum > 0x80ff)
99 run[n_run].x = x1;
100 run[n_run].alpha = 0x8000;
101 n_run++;
104 else if ((running_sum >> 16) > 0)
106 run[0].x = x0;
107 run[0].alpha = running_sum;
108 run[1].x = x1;
109 run[1].alpha = running_sum;
110 n_run = 2;
113 render->n_run = n_run;
115 art_render_invoke_callbacks (render, z->dest_ptr, y);
117 z->dest_ptr += render->rowstride;
120 static void
121 art_render_svp_callback_span (void *callback_data, int y,
122 int start, ArtSVPRenderAAStep *steps, int n_steps)
124 ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
125 ArtRender *render = z->render;
126 int n_run = 0;
127 int n_span = 0;
128 int i;
129 int running_sum = start;
130 int x0 = render->x0;
131 int x1 = render->x1;
132 int run_x0, run_x1;
133 ArtRenderMaskRun *run = render->run;
134 int *span_x = render->span_x;
136 if (n_steps > 0)
138 run_x1 = steps[0].x;
139 if (run_x1 > x0 && running_sum > 0x80ff)
141 run[0].x = x0;
142 run[0].alpha = running_sum;
143 n_run++;
144 span_x[0] = x0;
145 n_span++;
148 for (i = 0; i < n_steps - 1; i++)
150 running_sum += steps[i].delta;
151 run_x0 = run_x1;
152 run_x1 = steps[i + 1].x;
153 if (run_x1 > run_x0)
155 run[n_run].x = run_x0;
156 run[n_run].alpha = running_sum;
157 n_run++;
158 if ((n_span & 1) != (running_sum > 0x80ff))
159 span_x[n_span++] = run_x0;
162 if (x1 > run_x1)
164 running_sum += steps[n_steps - 1].delta;
165 run[n_run].x = run_x1;
166 run[n_run].alpha = running_sum;
167 n_run++;
168 if ((n_span & 1) != (running_sum > 0x80ff))
169 span_x[n_span++] = run_x1;
171 if (running_sum > 0x80ff)
173 run[n_run].x = x1;
174 run[n_run].alpha = 0x8000;
175 n_run++;
176 span_x[n_span++] = x1;
179 else if ((running_sum >> 16) > 0)
181 run[0].x = x0;
182 run[0].alpha = running_sum;
183 run[1].x = x1;
184 run[1].alpha = running_sum;
185 n_run = 2;
186 span_x[0] = x0;
187 span_x[1] = x1;
188 n_span = 2;
191 render->n_run = n_run;
192 render->n_span = n_span;
194 art_render_invoke_callbacks (render, z->dest_ptr, y);
196 z->dest_ptr += render->rowstride;
199 static void
200 art_render_svp_callback_opacity (void *callback_data, int y,
201 int start, ArtSVPRenderAAStep *steps, int n_steps)
203 ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
204 ArtRender *render = z->render;
205 int n_run = 0;
206 int i;
207 art_u32 running_sum;
208 int x0 = render->x0;
209 int x1 = render->x1;
210 int run_x0, run_x1;
211 ArtRenderMaskRun *run = render->run;
212 art_u32 opacity = render->opacity;
213 art_u32 alpha;
215 running_sum = start - 0x7f80;
217 if (n_steps > 0)
219 run_x1 = steps[0].x;
220 alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
221 if (run_x1 > x0 && alpha > 0x80ff)
223 run[0].x = x0;
224 run[0].alpha = alpha;
225 n_run++;
228 for (i = 0; i < n_steps - 1; i++)
230 running_sum += steps[i].delta;
231 run_x0 = run_x1;
232 run_x1 = steps[i + 1].x;
233 if (run_x1 > run_x0)
235 run[n_run].x = run_x0;
236 alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
237 run[n_run].alpha = alpha;
238 n_run++;
241 if (x1 > run_x1)
243 running_sum += steps[n_steps - 1].delta;
244 run[n_run].x = run_x1;
245 alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
246 run[n_run].alpha = alpha;
247 n_run++;
249 if (alpha > 0x80ff)
251 run[n_run].x = x1;
252 run[n_run].alpha = 0x8000;
253 n_run++;
256 else if ((running_sum >> 16) > 0)
258 run[0].x = x0;
259 run[0].alpha = running_sum;
260 run[1].x = x1;
261 run[1].alpha = running_sum;
262 n_run = 2;
265 render->n_run = n_run;
267 art_render_invoke_callbacks (render, z->dest_ptr, y);
269 z->dest_ptr += render->rowstride;
272 static void
273 art_render_svp_callback_opacity_span (void *callback_data, int y,
274 int start, ArtSVPRenderAAStep *steps, int n_steps)
276 ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
277 ArtRender *render = z->render;
278 int n_run = 0;
279 int n_span = 0;
280 int i;
281 art_u32 running_sum;
282 int x0 = render->x0;
283 int x1 = render->x1;
284 int run_x0, run_x1;
285 ArtRenderMaskRun *run = render->run;
286 int *span_x = render->span_x;
287 art_u32 opacity = render->opacity;
288 art_u32 alpha;
290 running_sum = start - 0x7f80;
292 if (n_steps > 0)
294 run_x1 = steps[0].x;
295 alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
296 if (run_x1 > x0 && alpha > 0x80ff)
298 run[0].x = x0;
299 run[0].alpha = alpha;
300 n_run++;
301 span_x[0] = x0;
302 n_span++;
305 for (i = 0; i < n_steps - 1; i++)
307 running_sum += steps[i].delta;
308 run_x0 = run_x1;
309 run_x1 = steps[i + 1].x;
310 if (run_x1 > run_x0)
312 run[n_run].x = run_x0;
313 alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
314 run[n_run].alpha = alpha;
315 n_run++;
316 if ((n_span & 1) != (alpha > 0x80ff))
317 span_x[n_span++] = run_x0;
320 if (x1 > run_x1)
322 running_sum += steps[n_steps - 1].delta;
323 run[n_run].x = run_x1;
324 alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
325 run[n_run].alpha = alpha;
326 n_run++;
327 if ((n_span & 1) != (alpha > 0x80ff))
328 span_x[n_span++] = run_x1;
330 if (alpha > 0x80ff)
332 run[n_run].x = x1;
333 run[n_run].alpha = 0x8000;
334 n_run++;
335 span_x[n_span++] = x1;
338 else if ((running_sum >> 16) > 0)
340 run[0].x = x0;
341 run[0].alpha = running_sum;
342 run[1].x = x1;
343 run[1].alpha = running_sum;
344 n_run = 2;
345 span_x[0] = x0;
346 span_x[1] = x1;
347 n_span = 2;
350 render->n_run = n_run;
351 render->n_span = n_span;
353 art_render_invoke_callbacks (render, z->dest_ptr, y);
355 z->dest_ptr += render->rowstride;
358 static void
359 art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
361 ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
362 void (*callback) (void *callback_data,
363 int y,
364 int start,
365 ArtSVPRenderAAStep *steps, int n_steps);
367 z->dest_ptr = render->pixels;
368 if (render->opacity == 0x10000)
370 if (render->need_span)
371 callback = art_render_svp_callback_span;
372 else
373 callback = art_render_svp_callback;
375 else
377 if (render->need_span)
378 callback = art_render_svp_callback_opacity_span;
379 else
380 callback = art_render_svp_callback_opacity;
383 art_svp_render_aa (z->svp,
384 render->x0, render->y0,
385 render->x1, render->y1, callback,
386 self);
387 art_render_svp_done (&self->super, render);
390 static void
391 art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
392 art_boolean first)
394 /* todo */
395 art_die ("art_render_svp non-driver mode not yet implemented.\n");
399 * art_render_svp: Use an SVP as a render mask source.
400 * @render: Render object.
401 * @svp: SVP.
403 * Adds @svp to the render object as a mask. Note: @svp must remain
404 * allocated until art_render_invoke() is called on @render.
406 void
407 art_render_svp (ArtRender *render, const ArtSVP *svp)
409 ArtMaskSourceSVP *mask_source;
410 mask_source = art_new (ArtMaskSourceSVP, 1);
412 mask_source->super.super.render = NULL;
413 mask_source->super.super.done = art_render_svp_done;
414 mask_source->super.can_drive = art_render_svp_can_drive;
415 mask_source->super.invoke_driver = art_render_svp_invoke_driver;
416 mask_source->super.prepare = art_render_svp_prepare;
417 mask_source->render = render;
418 mask_source->svp = svp;
420 art_render_add_mask_source (render, &mask_source->super);