source: trunk/third/libart_lgpl/art_rgb_svp.c @ 18256

Revision 18256, 11.3 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18255, which included commits to RCS files with non-trunk default branches.
Line 
1/* Libart_LGPL - library of basic graphic primitives
2 * Copyright (C) 1998 Raph Levien
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20/* Render a sorted vector path into an RGB buffer. */
21
22#include "config.h"
23#include "art_rgb_svp.h"
24
25#include "art_svp.h"
26#include "art_svp_render_aa.h"
27#include "art_rgb.h"
28
29typedef struct _ArtRgbSVPData ArtRgbSVPData;
30typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
31
32struct _ArtRgbSVPData {
33  art_u32 rgbtab[256];
34  art_u8 *buf;
35  int rowstride;
36  int x0, x1;
37};
38
39struct _ArtRgbSVPAlphaData {
40  int alphatab[256];
41  art_u8 r, g, b, alpha;
42  art_u8 *buf;
43  int rowstride;
44  int x0, x1;
45};
46
47static void
48art_rgb_svp_callback (void *callback_data, int y,
49                      int start, ArtSVPRenderAAStep *steps, int n_steps)
50{
51  ArtRgbSVPData *data = (ArtRgbSVPData *)callback_data;
52  art_u8 *linebuf;
53  int run_x0, run_x1;
54  art_u32 running_sum = start;
55  art_u32 rgb;
56  int x0, x1;
57  int k;
58
59  linebuf = data->buf;
60  x0 = data->x0;
61  x1 = data->x1;
62
63  if (n_steps > 0)
64    {
65      run_x1 = steps[0].x;
66      if (run_x1 > x0)
67        {
68          rgb = data->rgbtab[(running_sum >> 16) & 0xff];
69          art_rgb_fill_run (linebuf,
70                            rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
71                            run_x1 - x0);
72        }
73
74      for (k = 0; k < n_steps - 1; k++)
75        {
76          running_sum += steps[k].delta;
77          run_x0 = run_x1;
78          run_x1 = steps[k + 1].x;
79          if (run_x1 > run_x0)
80            {
81              rgb = data->rgbtab[(running_sum >> 16) & 0xff];
82              art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
83                                rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
84                                run_x1 - run_x0);
85            }
86        }
87      running_sum += steps[k].delta;
88      if (x1 > run_x1)
89        {
90          rgb = data->rgbtab[(running_sum >> 16) & 0xff];
91          art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
92                            rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
93                            x1 - run_x1);
94        }
95    }
96  else
97    {
98      rgb = data->rgbtab[(running_sum >> 16) & 0xff];
99      art_rgb_fill_run (linebuf,
100                        rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
101                        x1 - x0);
102    }
103
104  data->buf += data->rowstride;
105}
106
107/* Render the vector path into the RGB buffer. */
108
109/**
110 * art_rgb_svp_aa: Render sorted vector path into RGB buffer.
111 * @svp: The source sorted vector path.
112 * @x0: Left coordinate of destination rectangle.
113 * @y0: Top coordinate of destination rectangle.
114 * @x1: Right coordinate of destination rectangle.
115 * @y1: Bottom coordinate of destination rectangle.
116 * @fg_color: Foreground color in 0xRRGGBB format.
117 * @bg_color: Background color in 0xRRGGBB format.
118 * @buf: Destination RGB buffer.
119 * @rowstride: Rowstride of @buf buffer.
120 * @alphagamma: #ArtAlphaGamma for gamma-correcting the rendering.
121 *
122 * Renders the shape specified with @svp into the @buf RGB buffer.
123 * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
124 * of the rectangle rendered. The new pixels are stored starting at
125 * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
126 * an offset within @svp, and may be tweaked as a way of doing
127 * integer-pixel translations without fiddling with @svp itself.
128 *
129 * The @fg_color and @bg_color arguments specify the opaque colors to
130 * be used for rendering. For pixels of entirely 0 winding-number,
131 * @bg_color is used. For pixels of entirely 1 winding number,
132 * @fg_color is used. In between, the color is interpolated based on
133 * the fraction of the pixel with a winding number of 1. If
134 * @alphagamma is NULL, then linear interpolation (in pixel counts) is
135 * the default. Otherwise, the interpolation is as specified by
136 * @alphagamma.
137 **/
138void
139art_rgb_svp_aa (const ArtSVP *svp,
140                int x0, int y0, int x1, int y1,
141                art_u32 fg_color, art_u32 bg_color,
142                art_u8 *buf, int rowstride,
143                ArtAlphaGamma *alphagamma)
144{
145  ArtRgbSVPData data;
146
147  int r_fg, g_fg, b_fg;
148  int r_bg, g_bg, b_bg;
149  int r, g, b;
150  int dr, dg, db;
151  int i;
152
153  if (alphagamma == NULL)
154    {
155      r_fg = fg_color >> 16;
156      g_fg = (fg_color >> 8) & 0xff;
157      b_fg = fg_color & 0xff;
158
159      r_bg = bg_color >> 16;
160      g_bg = (bg_color >> 8) & 0xff;
161      b_bg = bg_color & 0xff;
162
163      r = (r_bg << 16) + 0x8000;
164      g = (g_bg << 16) + 0x8000;
165      b = (b_bg << 16) + 0x8000;
166      dr = ((r_fg - r_bg) << 16) / 255;
167      dg = ((g_fg - g_bg) << 16) / 255;
168      db = ((b_fg - b_bg) << 16) / 255;
169
170      for (i = 0; i < 256; i++)
171        {
172          data.rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
173          r += dr;
174          g += dg;
175          b += db;
176        }
177    }
178  else
179    {
180      int *table;
181      art_u8 *invtab;
182
183      table = alphagamma->table;
184
185      r_fg = table[fg_color >> 16];
186      g_fg = table[(fg_color >> 8) & 0xff];
187      b_fg = table[fg_color & 0xff];
188
189      r_bg = table[bg_color >> 16];
190      g_bg = table[(bg_color >> 8) & 0xff];
191      b_bg = table[bg_color & 0xff];
192
193      r = (r_bg << 16) + 0x8000;
194      g = (g_bg << 16) + 0x8000;
195      b = (b_bg << 16) + 0x8000;
196      dr = ((r_fg - r_bg) << 16) / 255;
197      dg = ((g_fg - g_bg) << 16) / 255;
198      db = ((b_fg - b_bg) << 16) / 255;
199
200      invtab = alphagamma->invtable;
201      for (i = 0; i < 256; i++)
202        {
203          data.rgbtab[i] = (invtab[r >> 16] << 16) |
204            (invtab[g >> 16] << 8) |
205            invtab[b >> 16];
206          r += dr;
207          g += dg;
208          b += db;
209        }
210    }
211  data.buf = buf;
212  data.rowstride = rowstride;
213  data.x0 = x0;
214  data.x1 = x1;
215  art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_callback, &data);
216}
217
218static void
219art_rgb_svp_alpha_callback (void *callback_data, int y,
220                            int start, ArtSVPRenderAAStep *steps, int n_steps)
221{
222  ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
223  art_u8 *linebuf;
224  int run_x0, run_x1;
225  art_u32 running_sum = start;
226  int x0, x1;
227  int k;
228  art_u8 r, g, b;
229  int *alphatab;
230  int alpha;
231
232  linebuf = data->buf;
233  x0 = data->x0;
234  x1 = data->x1;
235
236  r = data->r;
237  g = data->g;
238  b = data->b;
239  alphatab = data->alphatab;
240
241  if (n_steps > 0)
242    {
243      run_x1 = steps[0].x;
244      if (run_x1 > x0)
245        {
246          alpha = (running_sum >> 16) & 0xff;
247          if (alpha)
248            art_rgb_run_alpha (linebuf,
249                               r, g, b, alphatab[alpha],
250                               run_x1 - x0);
251        }
252
253      for (k = 0; k < n_steps - 1; k++)
254        {
255          running_sum += steps[k].delta;
256          run_x0 = run_x1;
257          run_x1 = steps[k + 1].x;
258          if (run_x1 > run_x0)
259            {
260              alpha = (running_sum >> 16) & 0xff;
261              if (alpha)
262                art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
263                                   r, g, b, alphatab[alpha],
264                                   run_x1 - run_x0);
265            }
266        }
267      running_sum += steps[k].delta;
268      if (x1 > run_x1)
269        {
270          alpha = (running_sum >> 16) & 0xff;
271          if (alpha)
272            art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
273                               r, g, b, alphatab[alpha],
274                               x1 - run_x1);
275        }
276    }
277  else
278    {
279      alpha = (running_sum >> 16) & 0xff;
280      if (alpha)
281        art_rgb_run_alpha (linebuf,
282                           r, g, b, alphatab[alpha],
283                           x1 - x0);
284    }
285
286  data->buf += data->rowstride;
287}
288
289static void
290art_rgb_svp_alpha_opaque_callback (void *callback_data, int y,
291                                   int start,
292                                   ArtSVPRenderAAStep *steps, int n_steps)
293{
294  ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
295  art_u8 *linebuf;
296  int run_x0, run_x1;
297  art_u32 running_sum = start;
298  int x0, x1;
299  int k;
300  art_u8 r, g, b;
301  int *alphatab;
302  int alpha;
303
304  linebuf = data->buf;
305  x0 = data->x0;
306  x1 = data->x1;
307
308  r = data->r;
309  g = data->g;
310  b = data->b;
311  alphatab = data->alphatab;
312
313  if (n_steps > 0)
314    {
315      run_x1 = steps[0].x;
316      if (run_x1 > x0)
317        {
318          alpha = running_sum >> 16;
319          if (alpha)
320            {
321              if (alpha >= 255)
322                art_rgb_fill_run (linebuf,
323                                  r, g, b,
324                                  run_x1 - x0);
325              else
326                art_rgb_run_alpha (linebuf,
327                                   r, g, b, alphatab[alpha],
328                                   run_x1 - x0);
329            }
330        }
331
332      for (k = 0; k < n_steps - 1; k++)
333        {
334          running_sum += steps[k].delta;
335          run_x0 = run_x1;
336          run_x1 = steps[k + 1].x;
337          if (run_x1 > run_x0)
338            {
339              alpha = running_sum >> 16;
340              if (alpha)
341                {
342                  if (alpha >= 255)
343                    art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
344                                      r, g, b,
345                                      run_x1 - run_x0);
346                  else
347                    art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
348                                       r, g, b, alphatab[alpha],
349                                       run_x1 - run_x0);
350                }
351            }
352        }
353      running_sum += steps[k].delta;
354      if (x1 > run_x1)
355        {
356          alpha = running_sum >> 16;
357          if (alpha)
358            {
359              if (alpha >= 255)
360                art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
361                                  r, g, b,
362                                  x1 - run_x1);
363              else
364                art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
365                                   r, g, b, alphatab[alpha],
366                                   x1 - run_x1);
367            }
368        }
369    }
370  else
371    {
372      alpha = running_sum >> 16;
373      if (alpha)
374        {
375          if (alpha >= 255)
376            art_rgb_fill_run (linebuf,
377                              r, g, b,
378                              x1 - x0);
379          else
380            art_rgb_run_alpha (linebuf,
381                               r, g, b, alphatab[alpha],
382                               x1 - x0);
383        }
384    }
385
386  data->buf += data->rowstride;
387}
388
389/**
390 * art_rgb_svp_alpha: Alpha-composite sorted vector path over RGB buffer.
391 * @svp: The source sorted vector path.
392 * @x0: Left coordinate of destination rectangle.
393 * @y0: Top coordinate of destination rectangle.
394 * @x1: Right coordinate of destination rectangle.
395 * @y1: Bottom coordinate of destination rectangle.
396 * @rgba: Color in 0xRRGGBBAA format.
397 * @buf: Destination RGB buffer.
398 * @rowstride: Rowstride of @buf buffer.
399 * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
400 *
401 * Renders the shape specified with @svp over the @buf RGB buffer.
402 * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
403 * of the rectangle rendered. The new pixels are stored starting at
404 * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
405 * an offset within @svp, and may be tweaked as a way of doing
406 * integer-pixel translations without fiddling with @svp itself.
407 *
408 * The @rgba argument specifies the color for the rendering. Pixels of
409 * entirely 0 winding number are left untouched. Pixels of entirely
410 * 1 winding number have the color @rgba composited over them (ie,
411 * are replaced by the red, green, blue components of @rgba if the alpha
412 * component is 0xff). Pixels of intermediate coverage are interpolated
413 * according to the rule in @alphagamma, or default to linear if
414 * @alphagamma is NULL.
415 **/
416void
417art_rgb_svp_alpha (const ArtSVP *svp,
418                   int x0, int y0, int x1, int y1,
419                   art_u32 rgba,
420                   art_u8 *buf, int rowstride,
421                   ArtAlphaGamma *alphagamma)
422{
423  ArtRgbSVPAlphaData data;
424  int r, g, b, alpha;
425  int i;
426  int a, da;
427
428  r = rgba >> 24;
429  g = (rgba >> 16) & 0xff;
430  b = (rgba >> 8) & 0xff;
431  alpha = rgba & 0xff;
432
433  data.r = r;
434  data.g = g;
435  data.b = b;
436  data.alpha = alpha;
437
438  a = 0x8000;
439  da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
440
441  for (i = 0; i < 256; i++)
442    {
443      data.alphatab[i] = a >> 16;
444      a += da;
445    }
446
447  data.buf = buf;
448  data.rowstride = rowstride;
449  data.x0 = x0;
450  data.x1 = x1;
451  if (alpha == 255)
452    art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback,
453                       &data);
454  else
455    art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback, &data);
456}
457
Note: See TracBrowser for help on using the repository browser.