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 {
38 art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
44 art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
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. */
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;
62 int running_sum = start;
66 ArtRenderMaskRun *run = render->run;
71 if (run_x1 > x0 && running_sum > 0x80ff)
74 run[0].alpha = running_sum;
78 for (i = 0; i < n_steps - 1; i++)
80 running_sum += steps[i].delta;
82 run_x1 = steps[i + 1].x;
85 run[n_run].x = run_x0;
86 run[n_run].alpha = running_sum;
92 running_sum += steps[n_steps - 1].delta;
93 run[n_run].x = run_x1;
94 run[n_run].alpha = running_sum;
97 if (running_sum > 0x80ff)
100 run[n_run].alpha = 0x8000;
104 else if ((running_sum >> 16) > 0)
107 run[0].alpha = running_sum;
109 run[1].alpha = running_sum;
113 render->n_run = n_run;
115 art_render_invoke_callbacks (render, z->dest_ptr, y);
117 z->dest_ptr += render->rowstride;
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;
129 int running_sum = start;
133 ArtRenderMaskRun *run = render->run;
134 int *span_x = render->span_x;
139 if (run_x1 > x0 && running_sum > 0x80ff)
142 run[0].alpha = running_sum;
148 for (i = 0; i < n_steps - 1; i++)
150 running_sum += steps[i].delta;
152 run_x1 = steps[i + 1].x;
155 run[n_run].x = run_x0;
156 run[n_run].alpha = running_sum;
158 if ((n_span & 1) != (running_sum > 0x80ff))
159 span_x[n_span++] = run_x0;
164 running_sum += steps[n_steps - 1].delta;
165 run[n_run].x = run_x1;
166 run[n_run].alpha = running_sum;
168 if ((n_span & 1) != (running_sum > 0x80ff))
169 span_x[n_span++] = run_x1;
171 if (running_sum > 0x80ff)
174 run[n_run].alpha = 0x8000;
176 span_x[n_span++] = x1;
179 else if ((running_sum >> 16) > 0)
182 run[0].alpha = running_sum;
184 run[1].alpha = running_sum;
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;
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;
211 ArtRenderMaskRun *run = render->run;
212 art_u32 opacity = render->opacity;
215 running_sum = start - 0x7f80;
220 alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
221 if (run_x1 > x0 && alpha > 0x80ff)
224 run[0].alpha = alpha;
228 for (i = 0; i < n_steps - 1; i++)
230 running_sum += steps[i].delta;
232 run_x1 = steps[i + 1].x;
235 run[n_run].x = run_x0;
236 alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
237 run[n_run].alpha = alpha;
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;
252 run[n_run].alpha = 0x8000;
256 else if ((running_sum >> 16) > 0)
259 run[0].alpha = running_sum;
261 run[1].alpha = running_sum;
265 render->n_run = n_run;
267 art_render_invoke_callbacks (render, z->dest_ptr, y);
269 z->dest_ptr += render->rowstride;
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;
285 ArtRenderMaskRun *run = render->run;
286 int *span_x = render->span_x;
287 art_u32 opacity = render->opacity;
290 running_sum = start - 0x7f80;
295 alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
296 if (run_x1 > x0 && alpha > 0x80ff)
299 run[0].alpha = alpha;
305 for (i = 0; i < n_steps - 1; i++)
307 running_sum += steps[i].delta;
309 run_x1 = steps[i + 1].x;
312 run[n_run].x = run_x0;
313 alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
314 run[n_run].alpha = alpha;
316 if ((n_span & 1) != (alpha > 0x80ff))
317 span_x[n_span++] = run_x0;
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;
327 if ((n_span & 1) != (alpha > 0x80ff))
328 span_x[n_span++] = run_x1;
333 run[n_run].alpha = 0x8000;
335 span_x[n_span++] = x1;
338 else if ((running_sum >> 16) > 0)
341 run[0].alpha = running_sum;
343 run[1].alpha = running_sum;
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;
359 art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
361 ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
362 void (*callback) (void *callback_data,
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;
373 callback = art_render_svp_callback;
377 if (render->need_span)
378 callback = art_render_svp_callback_opacity_span;
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,
387 art_render_svp_done (&self->super, render);
391 art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
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.
403 * Adds @svp to the render object as a mask. Note: @svp must remain
404 * allocated until art_render_invoke() is called on @render.
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);