source: trunk/third/librsvg/art_render_svp.c @ 17277

Revision 17277, 9.4 KB checked in by amb, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17276, which included commits to RCS files with non-trunk default branches.
Line 
1/* This file is adapted from art_render_gradient.c in Libart version 2.3.0 */
2
3#include <libart_lgpl/libart-features.h>
4
5#if LIBART_MAJOR_VERSION == 2 && LIBART_MINOR_VERSION < 3
6
7/*
8 * art_render_gradient.c: SVP mask source for modular rendering.
9 *
10 * Libart_LGPL - library of basic graphic primitives
11 * Copyright (C) 2000 Raph Levien
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 * Library General Public License for more details.
22 *
23 * You should have received a copy of the GNU Library General Public
24 * License along with this library; if not, write to the
25 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 * Boston, MA 02111-1307, USA.
27 *
28 * Authors: Raph Levien <raph@acm.org>
29 */
30
31/* Use an SVP as a render mask source. */
32
33#include <libart_lgpl/art_misc.h>
34#include <libart_lgpl/art_alphagamma.h>
35#include <libart_lgpl/art_svp.h>
36#include <libart_lgpl/art_svp_render_aa.h>
37
38#include "art_render.h"
39#include "art_render_svp.h"
40
41typedef struct _ArtMaskSourceSVP ArtMaskSourceSVP;
42
43struct _ArtMaskSourceSVP {
44  ArtMaskSource super;
45  ArtRender *render;
46  const ArtSVP *svp;
47  art_u8 *dest_ptr;
48};
49
50static void
51art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
52{
53  art_free (self);
54}
55
56static int
57art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
58{
59  return 10;
60}
61
62/* The basic art_render_svp_callback function is repeated four times,
63   for all combinations of non-unit opacity and generating spans. In
64   general, I'd consider this bad style, but in this case I plead
65   a measurable performance improvement. */
66
67static void
68art_render_svp_callback (void *callback_data, int y,
69                         int start, ArtSVPRenderAAStep *steps, int n_steps)
70{
71  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
72  ArtRender *render = z->render;
73  int n_run = 0;
74  int i;
75  int running_sum = start;
76  int x0 = render->x0;
77  int x1 = render->x1;
78  int run_x0, run_x1;
79  ArtRenderMaskRun *run = render->run;
80
81  if (n_steps > 0)
82    {
83      run_x1 = steps[0].x;
84      if (run_x1 > x0 && running_sum > 0x80ff)
85        {
86          run[0].x = x0;
87          run[0].alpha = running_sum;
88          n_run++;
89        }
90
91      for (i = 0; i < n_steps - 1; i++)
92        {
93          running_sum += steps[i].delta;
94          run_x0 = run_x1;
95          run_x1 = steps[i + 1].x;
96          if (run_x1 > run_x0)
97            {
98              run[n_run].x = run_x0;
99              run[n_run].alpha = running_sum;
100              n_run++;
101            }
102        }
103      if (x1 > run_x1)
104        {
105          running_sum += steps[n_steps - 1].delta;
106          run[n_run].x = run_x1;
107          run[n_run].alpha = running_sum;
108          n_run++;
109        }
110      if (running_sum > 0x80ff)
111        {
112          run[n_run].x = x1;
113          run[n_run].alpha = 0x8000;
114          n_run++;
115        }
116    }
117
118  render->n_run = n_run;
119
120  art_render_invoke_callbacks (render, z->dest_ptr, y);
121
122  z->dest_ptr += render->rowstride;
123}
124
125static void
126art_render_svp_callback_span (void *callback_data, int y,
127                              int start, ArtSVPRenderAAStep *steps, int n_steps)
128{
129  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
130  ArtRender *render = z->render;
131  int n_run = 0;
132  int n_span = 0;
133  int i;
134  int running_sum = start;
135  int x0 = render->x0;
136  int x1 = render->x1;
137  int run_x0, run_x1;
138  ArtRenderMaskRun *run = render->run;
139  int *span_x = render->span_x;
140
141  if (n_steps > 0)
142    {
143      run_x1 = steps[0].x;
144      if (run_x1 > x0 && running_sum > 0x80ff)
145        {
146          run[0].x = x0;
147          run[0].alpha = running_sum;
148          n_run++;
149          span_x[0] = x0;
150          n_span++;
151        }
152
153      for (i = 0; i < n_steps - 1; i++)
154        {
155          running_sum += steps[i].delta;
156          run_x0 = run_x1;
157          run_x1 = steps[i + 1].x;
158          if (run_x1 > run_x0)
159            {
160              run[n_run].x = run_x0;
161              run[n_run].alpha = running_sum;
162              n_run++;
163              if ((n_span & 1) != (running_sum > 0x80ff))
164                span_x[n_span++] = run_x0;
165            }
166        }
167      if (x1 > run_x1)
168        {
169          running_sum += steps[n_steps - 1].delta;
170          run[n_run].x = run_x1;
171          run[n_run].alpha = running_sum;
172          n_run++;
173          if ((n_span & 1) != (running_sum > 0x80ff))
174            span_x[n_span++] = run_x1;
175        }
176      if (running_sum > 0x80ff)
177        {
178          run[n_run].x = x1;
179          run[n_run].alpha = 0x8000;
180          n_run++;
181          span_x[n_span++] = x1;
182        }
183    }
184
185  render->n_run = n_run;
186  render->n_span = n_span;
187
188  art_render_invoke_callbacks (render, z->dest_ptr, y);
189
190  z->dest_ptr += render->rowstride;
191}
192
193static void
194art_render_svp_callback_opacity (void *callback_data, int y,
195                                 int start, ArtSVPRenderAAStep *steps, int n_steps)
196{
197  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
198  ArtRender *render = z->render;
199  int n_run = 0;
200  int i;
201  art_u32 running_sum;
202  int x0 = render->x0;
203  int x1 = render->x1;
204  int run_x0, run_x1;
205  ArtRenderMaskRun *run = render->run;
206  art_u32 opacity = render->opacity;
207  art_u32 alpha;
208
209  running_sum = start - 0x7f80;
210
211  if (n_steps > 0)
212    {
213      run_x1 = steps[0].x;
214      alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
215      if (run_x1 > x0 && alpha > 0x80ff)
216        {
217          run[0].x = x0;
218          run[0].alpha = alpha;
219          n_run++;
220        }
221
222      for (i = 0; i < n_steps - 1; i++)
223        {
224          running_sum += steps[i].delta;
225          run_x0 = run_x1;
226          run_x1 = steps[i + 1].x;
227          if (run_x1 > run_x0)
228            {
229              run[n_run].x = run_x0;
230              alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
231              run[n_run].alpha = alpha;
232              n_run++;
233            }
234        }
235      if (x1 > run_x1)
236        {
237          running_sum += steps[n_steps - 1].delta;
238          run[n_run].x = run_x1;
239          alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
240          run[n_run].alpha = alpha;
241          n_run++;
242        }
243      if (alpha > 0x80ff)
244        {
245          run[n_run].x = x1;
246          run[n_run].alpha = 0x8000;
247          n_run++;
248        }
249    }
250
251  render->n_run = n_run;
252
253  art_render_invoke_callbacks (render, z->dest_ptr, y);
254
255  z->dest_ptr += render->rowstride;
256}
257
258static void
259art_render_svp_callback_opacity_span (void *callback_data, int y,
260                                      int start, ArtSVPRenderAAStep *steps, int n_steps)
261{
262  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
263  ArtRender *render = z->render;
264  int n_run = 0;
265  int n_span = 0;
266  int i;
267  art_u32 running_sum;
268  int x0 = render->x0;
269  int x1 = render->x1;
270  int run_x0, run_x1;
271  ArtRenderMaskRun *run = render->run;
272  int *span_x = render->span_x;
273  art_u32 opacity = render->opacity;
274  art_u32 alpha;
275
276  running_sum = start - 0x7f80;
277
278  if (n_steps > 0)
279    {
280      run_x1 = steps[0].x;
281      alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
282      if (run_x1 > x0 && alpha > 0x80ff)
283        {
284          run[0].x = x0;
285          run[0].alpha = alpha;
286          n_run++;
287          span_x[0] = x0;
288          n_span++;
289        }
290
291      for (i = 0; i < n_steps - 1; i++)
292        {
293          running_sum += steps[i].delta;
294          run_x0 = run_x1;
295          run_x1 = steps[i + 1].x;
296          if (run_x1 > run_x0)
297            {
298              run[n_run].x = run_x0;
299              alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
300              run[n_run].alpha = alpha;
301              n_run++;
302              if ((n_span & 1) != (alpha > 0x80ff))
303                span_x[n_span++] = run_x0;
304            }
305        }
306      if (x1 > run_x1)
307        {
308          running_sum += steps[n_steps - 1].delta;
309          run[n_run].x = run_x1;
310          alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
311          run[n_run].alpha = alpha;
312          n_run++;
313          if ((n_span & 1) != (alpha > 0x80ff))
314            span_x[n_span++] = run_x1;
315        }
316      if (alpha > 0x80ff)
317        {
318          run[n_run].x = x1;
319          run[n_run].alpha = 0x8000;
320          n_run++;
321          span_x[n_span++] = x1;
322        }
323    }
324
325  render->n_run = n_run;
326  render->n_span = n_span;
327
328  art_render_invoke_callbacks (render, z->dest_ptr, y);
329
330  z->dest_ptr += render->rowstride;
331}
332
333static void
334art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
335{
336  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
337  void (*callback) (void *callback_data,
338                    int y,
339                    int start,
340                    ArtSVPRenderAAStep *steps, int n_steps);
341
342  z->dest_ptr = render->pixels;
343  if (render->opacity == 0x10000)
344    {
345      if (render->need_span)
346        callback = art_render_svp_callback_span;
347      else
348        callback = art_render_svp_callback;
349    }
350  else
351    {
352      if (render->need_span)
353        callback = art_render_svp_callback_opacity_span;
354      else
355        callback = art_render_svp_callback_opacity;
356    }
357
358  art_svp_render_aa (z->svp,
359                     render->x0, render->y0,
360                     render->x1, render->y1, callback,
361                     self);
362  art_render_svp_done (&self->super, render);
363}
364
365static void
366art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
367                        art_boolean first)
368{
369  /* todo */
370  art_die ("art_render_svp non-driver mode not yet implemented.\n");
371}
372
373/**
374 * art_render_svp: Use an SVP as a render mask source.
375 * @render: Render object.
376 * @svp: SVP.
377 *
378 * Adds @svp to the render object as a mask. Note: @svp must remain
379 * allocated until art_render_invoke() is called on @render.
380 **/
381void
382art_render_svp (ArtRender *render, const ArtSVP *svp)
383{
384  ArtMaskSourceSVP *mask_source;
385  mask_source = art_new (ArtMaskSourceSVP, 1);
386
387  mask_source->super.super.render = NULL;
388  mask_source->super.super.done = art_render_svp_done;
389  mask_source->super.can_drive = art_render_svp_can_drive;
390  mask_source->super.invoke_driver = art_render_svp_invoke_driver;
391  mask_source->super.prepare = art_render_svp_prepare;
392  mask_source->render = render;
393  mask_source->svp = svp;
394
395  art_render_add_mask_source (render, &mask_source->super);
396}
397
398#endif
Note: See TracBrowser for help on using the repository browser.