Back to index

scribus-ng  1.3.4.dfsg+svn20071115
art_rgb_svp.c
Go to the documentation of this file.
00001 /* Libart_LGPL - library of basic graphic primitives
00002  * Copyright (C) 1998 Raph Levien
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 /* Render a sorted vector path into an RGB buffer. */
00021 
00022 #include "scconfig.h"
00023 
00024 #include "art_rgb_svp.h"
00025 
00026 #include <libart_lgpl/art_svp.h>
00027 #include <libart_lgpl/art_svp_render_aa.h>
00028 #include "art_rgb.h"
00029 
00030 typedef struct _ArtRgbSVPData ArtRgbSVPData;
00031 typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
00032 
00033 struct _ArtRgbSVPData {
00034   art_u32 rgbtab[256];
00035   art_u8 *buf;
00036   int rowstride;
00037   int x0, x1;
00038 };
00039 
00040 struct _ArtRgbSVPAlphaData {
00041   int alphatab[256];
00042   art_u8 r, g, b, alpha;
00043   art_u32 rgb;
00044   art_u8 *buf;
00045   int rowstride;
00046   int x0, x1;
00047 };
00048 
00049 static void
00050 art_rgb_svp_callback_ (void *callback_data, int y,
00051                     int start, ArtSVPRenderAAStep *steps, int n_steps)
00052 {
00053   ArtRgbSVPData *data = (ArtRgbSVPData *)callback_data;
00054   art_u8 *linebuf;
00055   int run_x0, run_x1;
00056   art_u32 running_sum = start;
00057   art_u32 rgb;
00058   int x0, x1;
00059   int k;
00060 
00061   linebuf = data->buf;
00062   x0 = data->x0;
00063   x1 = data->x1;
00064 
00065   if (n_steps > 0)
00066     {
00067       run_x1 = steps[0].x;
00068       if (run_x1 > x0)
00069        {
00070          rgb = data->rgbtab[(running_sum >> 16) & 0xff];
00071 /*       art_rgb_fill_run (linebuf,
00072                          rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
00073                          run_x1 - x0);*/
00074        }
00075 
00076       for (k = 0; k < n_steps - 1; k++)
00077        {
00078          running_sum += steps[k].delta;
00079          run_x0 = run_x1;
00080          run_x1 = steps[k + 1].x;
00081          if (run_x1 > run_x0)
00082            {
00083              rgb = data->rgbtab[(running_sum >> 16) & 0xff];
00084 /*           art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
00085                             rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
00086                             run_x1 - run_x0);*/
00087            }
00088        }
00089       running_sum += steps[k].delta;
00090       if (x1 > run_x1)
00091        {
00092          rgb = data->rgbtab[(running_sum >> 16) & 0xff];
00093 /*       art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
00094                          rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
00095                          x1 - run_x1);*/
00096        }
00097     }
00098   else
00099     {
00100       rgb = data->rgbtab[(running_sum >> 16) & 0xff];
00101 /*      art_rgb_fill_run (linebuf,
00102                      rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
00103                      x1 - x0);*/
00104     }
00105 
00106   data->buf += data->rowstride;
00107 }
00108 
00109 /* Render the vector path into the RGB buffer. */
00110 
00140 void
00141 art_rgb_svp_aa_ (const ArtSVP *svp,
00142               int x0, int y0, int x1, int y1,
00143               art_u32 fg_color, art_u32 bg_color,
00144               art_u8 *buf, int rowstride,
00145               ArtAlphaGamma *alphagamma)
00146 {
00147   ArtRgbSVPData data;
00148 
00149   int r_fg, g_fg, b_fg;
00150   int r_bg, g_bg, b_bg;
00151   int r, g, b;
00152   int dr, dg, db;
00153   int i;
00154 
00155   if (alphagamma == NULL)
00156     {
00157       r_fg = fg_color >> 16;
00158       g_fg = (fg_color >> 8) & 0xff;
00159       b_fg = fg_color & 0xff;
00160 
00161       r_bg = bg_color >> 16;
00162       g_bg = (bg_color >> 8) & 0xff;
00163       b_bg = bg_color & 0xff;
00164 
00165       r = (r_bg << 16) + 0x8000;
00166       g = (g_bg << 16) + 0x8000;
00167       b = (b_bg << 16) + 0x8000;
00168       dr = ((r_fg - r_bg) << 16) / 255;
00169       dg = ((g_fg - g_bg) << 16) / 255;
00170       db = ((b_fg - b_bg) << 16) / 255;
00171 
00172       for (i = 0; i < 256; i++)
00173        {
00174          data.rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
00175          r += dr;
00176          g += dg;
00177          b += db;
00178        }
00179     }
00180   else
00181     {
00182       int *table;
00183       art_u8 *invtab;
00184 
00185       table = alphagamma->table;
00186 
00187       r_fg = table[fg_color >> 16];
00188       g_fg = table[(fg_color >> 8) & 0xff];
00189       b_fg = table[fg_color & 0xff];
00190 
00191       r_bg = table[bg_color >> 16];
00192       g_bg = table[(bg_color >> 8) & 0xff];
00193       b_bg = table[bg_color & 0xff];
00194 
00195       r = (r_bg << 16) + 0x8000;
00196       g = (g_bg << 16) + 0x8000;
00197       b = (b_bg << 16) + 0x8000;
00198       dr = ((r_fg - r_bg) << 16) / 255;
00199       dg = ((g_fg - g_bg) << 16) / 255;
00200       db = ((b_fg - b_bg) << 16) / 255;
00201 
00202       invtab = alphagamma->invtable;
00203       for (i = 0; i < 256; i++)
00204        {
00205          data.rgbtab[i] = (invtab[r >> 16] << 16) |
00206            (invtab[g >> 16] << 8) |
00207            invtab[b >> 16];
00208          r += dr;
00209          g += dg;
00210          b += db;
00211        }
00212     }
00213   data.buf = buf;
00214   data.rowstride = rowstride;
00215   data.x0 = x0;
00216   data.x1 = x1;
00217   art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_callback_, &data);
00218 }
00219 
00220 static void
00221 art_rgb_svp_alpha_callback_ (void *callback_data, int y,
00222                          int start, ArtSVPRenderAAStep *steps, int n_steps)
00223 {
00224   ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
00225   art_u8 *linebuf;
00226   int run_x0, run_x1;
00227   art_u32 running_sum = start;
00228   int x0, x1;
00229   int k;
00230   art_u8 r, g, b;
00231   int *alphatab;
00232   int alpha;
00233 
00234   linebuf = data->buf;
00235   x0 = data->x0;
00236   x1 = data->x1;
00237 
00238   r = data->r;
00239   g = data->g;
00240   b = data->b;
00241   alphatab = data->alphatab;
00242 
00243   if (n_steps > 0)
00244     {
00245       run_x1 = steps[0].x;
00246       if (run_x1 > x0)
00247        {
00248          alpha = (running_sum >> 16) & 0xff;
00249          if (alpha)
00250            art_rgb_run_alpha_ (linebuf,
00251                             r, g, b, alphatab[alpha],
00252                             run_x1 - x0);
00253        }
00254 
00255       for (k = 0; k < n_steps - 1; k++)
00256        {
00257          running_sum += steps[k].delta;
00258          run_x0 = run_x1;
00259          run_x1 = steps[k + 1].x;
00260          if (run_x1 > run_x0)
00261            {
00262              alpha = (running_sum >> 16) & 0xff;
00263              if (alpha)
00264               art_rgb_run_alpha_ (linebuf + (run_x0 - x0) * 4,
00265                                r, g, b, alphatab[alpha],
00266                                run_x1 - run_x0);
00267            }
00268        }
00269       running_sum += steps[k].delta;
00270       if (x1 > run_x1)
00271        {
00272          alpha = (running_sum >> 16) & 0xff;
00273          if (alpha)
00274            art_rgb_run_alpha_ (linebuf + (run_x1 - x0) * 4,
00275                             r, g, b, alphatab[alpha],
00276                             x1 - run_x1);
00277        }
00278     }
00279   else
00280     {
00281       alpha = (running_sum >> 16) & 0xff;
00282       if (alpha)
00283        art_rgb_run_alpha_ (linebuf,
00284                         r, g, b, alphatab[alpha],
00285                         x1 - x0);
00286     }
00287 
00288   data->buf += data->rowstride;
00289 }
00290 
00291 static void
00292 art_rgb_svp_alpha_opaque_callback_ (void *callback_data, int y,
00293                                int start,
00294                                ArtSVPRenderAAStep *steps, int n_steps)
00295 {
00296   ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
00297   art_u8 *linebuf;
00298   int run_x0, run_x1;
00299   art_u32 running_sum = start;
00300   int x0, x1;
00301   int k;
00302   art_u8 r, g, b;
00303   art_u32 rgb;
00304   int *alphatab;
00305   int alpha;
00306 
00307   linebuf = data->buf;
00308   x0 = data->x0;
00309   x1 = data->x1;
00310 
00311   r = data->r;
00312   g = data->g;
00313   b = data->b;
00314   rgb = data->rgb;
00315   alphatab = data->alphatab;
00316 
00317   if (n_steps > 0)
00318     {
00319       run_x1 = steps[0].x;
00320       if (run_x1 > x0)
00321        {
00322          alpha = running_sum >> 16;
00323          if (alpha)
00324            {
00325              if (alpha >= 255)
00326               art_rgb_fill_run_ (linebuf,
00327                               rgb,
00328                               run_x1 - x0);
00329              else
00330               art_rgb_run_alpha_ (linebuf,
00331                                r, g, b, alphatab[alpha],
00332                                run_x1 - x0);
00333            }
00334        }
00335 
00336       for (k = 0; k < n_steps - 1; k++)
00337        {
00338          running_sum += steps[k].delta;
00339          run_x0 = run_x1;
00340          run_x1 = steps[k + 1].x;
00341          if (run_x1 > run_x0)
00342            {
00343              alpha = running_sum >> 16;
00344              if (alpha)
00345               {
00346                 if (alpha >= 255)
00347                   art_rgb_fill_run_ (linebuf + (run_x0 - x0) * 4,
00348                                   rgb,
00349                                   run_x1 - run_x0);
00350                 else
00351                   art_rgb_run_alpha_ (linebuf + (run_x0 - x0) * 4,
00352                                    r, g, b, alphatab[alpha],
00353                                    run_x1 - run_x0);
00354               }
00355            }
00356        }
00357       running_sum += steps[k].delta;
00358       if (x1 > run_x1)
00359        {
00360          alpha = running_sum >> 16;
00361          if (alpha)
00362            {
00363              if (alpha >= 255)
00364               art_rgb_fill_run_ (linebuf + (run_x1 - x0) * 4,
00365                               rgb,
00366                               x1 - run_x1);
00367              else
00368               art_rgb_run_alpha_ (linebuf + (run_x1 - x0) * 4,
00369                                r, g, b, alphatab[alpha],
00370                                x1 - run_x1);
00371            }
00372        }
00373     }
00374   else
00375     {
00376       alpha = running_sum >> 16;
00377       if (alpha)
00378        {
00379          if (alpha >= 255)
00380            art_rgb_fill_run_ (linebuf,
00381                            rgb,
00382                            x1 - x0);
00383          else
00384            art_rgb_run_alpha_ (linebuf,
00385                             r, g, b, alphatab[alpha],
00386                             x1 - x0);
00387        }
00388     }
00389   data->buf += data->rowstride;
00390 }
00391 
00419 void
00420 art_rgb_svp_alpha_ (const ArtSVP *svp,
00421                  int x0, int y0, int x1, int y1,
00422                  art_u32 rgb, int alpha,
00423                  art_u8 *buf, int rowstride,
00424                  ArtAlphaGamma *alphagamma)
00425 {
00426   ArtRgbSVPAlphaData data;
00427   int r, g, b;
00428   int i;
00429   int a, da;
00430 
00431 #ifdef WORDS_BIGENDIAN
00432   r = (rgb >> 8)  & 0xff;
00433   g = (rgb >> 16) & 0xff;
00434   b = (rgb >> 24) & 0xff;
00435 #else
00436   r = (rgb >> 16) & 0xff;
00437   g = (rgb >> 8) & 0xff;
00438   b = rgb & 0xff;
00439 #endif
00440 
00441   data.r = r;
00442   data.g = g;
00443   data.b = b;
00444   data.alpha = alpha;
00445   data.rgb = rgb;
00446 
00447   a = 0x8000;
00448   da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
00449 
00450   for (i = 0; i < 256; i++)
00451     {
00452       data.alphatab[i] = a >> 16;
00453       a += da;
00454     }
00455 
00456   data.buf = buf;
00457   data.rowstride = rowstride;
00458   data.x0 = x0;
00459   data.x1 = x1;
00460   if (alpha == 255)
00461     art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback_,
00462                      &data);
00463   else
00464     art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback_, &data);
00465 }