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
);