Back to index

scribus-ng  1.3.4.dfsg+svn20071115
art_kmisc.c
Go to the documentation of this file.
00001 #include <libart_lgpl/art_vpath.h>
00002 #include <libart_lgpl/art_bpath.h>
00003 #include <libart_lgpl/art_misc.h>
00004 #include <libart_lgpl/art_affine.h>
00005 #include <libart_lgpl/art_svp_render_aa.h>
00006 
00007 #include "scconfig.h"
00008 #include "art_kmisc.h"
00009 #include <math.h>
00010 
00041  void
00042 ksvg_art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
00043               double x0, double y0,
00044               double x1, double y1,
00045               double x2, double y2,
00046               double x3, double y3,
00047               double flatness)
00048 {
00049        double x3_0, y3_0;
00050        double z3_0_dot;
00051        double z1_dot, z2_dot;
00052        double z1_perp, z2_perp;
00053        double max_perp_sq;
00054 
00055        double x_m, y_m;
00056        double xa1, ya1;
00057        double xa2, ya2;
00058        double xb1, yb1;
00059        double xb2, yb2;
00060 
00061        /* It's possible to optimize this routine a fair amount.
00062 
00063           First, once the _dot conditions are met, they will also be met in
00064           all further subdivisions. So we might recurse to a different
00065           routine that only checks the _perp conditions.
00066 
00067           Second, the distance _should_ decrease according to fairly
00068           predictable rules (a factor of 4 with each subdivision). So it might
00069           be possible to note that the distance is within a factor of 4 of
00070           acceptable, and subdivide once. But proving this might be hard.
00071 
00072           Third, at the last subdivision, x_m and y_m can be computed more
00073           expeditiously (as in the routine above).
00074 
00075           Finally, if we were able to subdivide by, say 2 or 3, this would
00076           allow considerably finer-grain control, i.e. fewer points for the
00077           same flatness tolerance. This would speed things up downstream.
00078 
00079           In any case, this routine is unlikely to be the bottleneck. It's
00080           just that I have this undying quest for more speed...
00081 
00082 */
00083 
00084        x3_0 = x3 - x0;
00085        y3_0 = y3 - y0;
00086 
00087        /* z3_0_dot is dist z0-z3 squared */
00088        z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
00089 
00090        /* todo: this test is far from satisfactory. */
00091        if (z3_0_dot < 0.001)
00092               goto nosubdivide;
00093 
00094        /* we can avoid subdivision if:
00095 
00096           z1 has distance no more than flatness from the z0-z3 line
00097 
00098           z1 is no more z0'ward than flatness past z0-z3
00099 
00100           z1 is more z0'ward than z3'ward on the line traversing z0-z3
00101 
00102           and correspondingly for z2 */
00103 
00104        /* perp is distance from line, multiplied by dist z0-z3 */
00105        max_perp_sq = flatness * flatness * z3_0_dot;
00106        z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
00107        if (z1_perp * z1_perp > max_perp_sq)
00108               goto subdivide;
00109 
00110        z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
00111        if (z2_perp * z2_perp > max_perp_sq)
00112               goto subdivide;
00113 
00114        z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
00115        if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
00116               goto subdivide;
00117 
00118        z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
00119        if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
00120               goto subdivide;
00121 
00122        if (z1_dot + z1_dot > z3_0_dot)
00123               goto subdivide;
00124 
00125        if (z2_dot + z2_dot > z3_0_dot)
00126               goto subdivide;
00127 
00128 nosubdivide:
00129        /* don't subdivide */
00130        art_vpath_add_point (p_vpath, pn, pn_max,
00131                      ART_LINETO, x3, y3);
00132        return;
00133 
00134 subdivide:
00135 
00136        xa1 = (x0 + x1) * 0.5;
00137        ya1 = (y0 + y1) * 0.5;
00138        xa2 = (x0 + 2 * x1 + x2) * 0.25;
00139        ya2 = (y0 + 2 * y1 + y2) * 0.25;
00140        xb1 = (x1 + 2 * x2 + x3) * 0.25;
00141        yb1 = (y1 + 2 * y2 + y3) * 0.25;
00142        xb2 = (x2 + x3) * 0.5;
00143        yb2 = (y2 + y3) * 0.5;
00144        x_m = (xa2 + xb1) * 0.5;
00145        y_m = (ya2 + yb1) * 0.5;
00146 #ifdef VERBOSE
00147        printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
00148                      xb1, yb1, xb2, yb2);
00149 #endif
00150        ksvg_art_vpath_render_bez (p_vpath, pn, pn_max,
00151                      x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
00152        ksvg_art_vpath_render_bez (p_vpath, pn, pn_max,
00153                      x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
00154 }
00155 
00156 #define RENDER_LEVEL 4
00157 #define RENDER_SIZE (1 << (RENDER_LEVEL))
00158 
00171  ArtVpath *
00172 ksvg_art_bez_path_to_vec(const ArtBpath *bez, double flatness)
00173 {
00174        ArtVpath *vec;
00175        int vec_n, vec_n_max;
00176        int bez_index;
00177        double x, y;
00178 
00179        vec_n = 0;
00180        vec_n_max = RENDER_SIZE;
00181        vec = art_new (ArtVpath, vec_n_max);
00182 
00183        /* Initialization is unnecessary because of the precondition that the
00184           bezier path does not begin with LINETO or CURVETO, but is here
00185           to make the code warning-free. */
00186        x = 0;
00187        y = 0;
00188 
00189        bez_index = 0;
00190        do
00191        {
00192 #ifdef VERBOSE
00193               printf ("%s %g %g\n",
00194                             bez[bez_index].code == ART_CURVETO ? "curveto" :
00195                             bez[bez_index].code == ART_LINETO ? "lineto" :
00196                             bez[bez_index].code == ART_MOVETO ? "moveto" :
00197                             bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" :
00198                             "end", bez[bez_index].x3, bez[bez_index].y3);
00199 #endif
00200               /* make sure space for at least one more code */
00201               if (vec_n >= vec_n_max)
00202                      art_expand (vec, ArtVpath, vec_n_max);
00203               switch (bez[bez_index].code)
00204               {
00205                      case ART_MOVETO_OPEN:
00206                      case ART_MOVETO:
00207                      case ART_LINETO:
00208                             x = bez[bez_index].x3;
00209                             y = bez[bez_index].y3;
00210                             vec[vec_n].code = bez[bez_index].code;
00211                             vec[vec_n].x = x;
00212                             vec[vec_n].y = y;
00213                             vec_n++;
00214                             break;
00215                      case ART_END:
00216                             vec[vec_n].code = ART_END;
00217                             vec[vec_n].x = 0;
00218                             vec[vec_n].y = 0;
00219                             vec_n++;
00220                             break;
00221                      case ART_END2:
00222                             vec[vec_n].code = (ArtPathcode)ART_END2;
00223                             vec[vec_n].x = bez[bez_index].x3;
00224                             vec[vec_n].y = bez[bez_index].y3;
00225                             vec_n++;
00226                             break;
00227                      case ART_CURVETO:
00228 #ifdef VERBOSE
00229                             printf ("%g,%g %g,%g %g,%g %g,%g\n", x, y,
00230                                           bez[bez_index].x1, bez[bez_index].y1,
00231                                           bez[bez_index].x2, bez[bez_index].y2,
00232                                           bez[bez_index].x3, bez[bez_index].y3);
00233 #endif
00234                             ksvg_art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
00235                                           x, y,
00236                                           bez[bez_index].x1, bez[bez_index].y1,
00237                                           bez[bez_index].x2, bez[bez_index].y2,
00238                                           bez[bez_index].x3, bez[bez_index].y3,
00239                                           flatness);
00240                             x = bez[bez_index].x3;
00241                             y = bez[bez_index].y3;
00242                             break;
00243               }
00244        }
00245        while (bez[bez_index++].code != ART_END);
00246        return vec;
00247 }
00248 
00249 /* Private functions for the rgb affine image compositors - primarily,
00250 *    the determination of runs, eliminating the need for source image
00251 *       bbox calculation in the inner loop. */
00252 
00253 /* Determine a "run", such that the inverse affine of all pixels from
00254 *    (x0, y) inclusive to (x1, y) exclusive fit within the bounds
00255 *       of the source image.
00256 *
00257 *          Initial values of x0, x1, and result values stored in first two
00258 *             pointer arguments.
00259 *             */
00260 
00261 #define EPSILON 1e-6
00262 
00263  void ksvg_art_rgb_affine_run (int *p_x0, int *p_x1, int y,
00264               int src_width, int src_height,
00265               const double affine[6])
00266 {
00267        int x0, x1;
00268        double z;
00269        double x_intercept;
00270        int xi;
00271 
00272        x0 = *p_x0;
00273        x1 = *p_x1;
00274 
00275        /* do left and right edges */
00276        if (affine[0] > EPSILON)
00277        {
00278               z = affine[2] * (y + 0.5) + affine[4];
00279               x_intercept = -z / affine[0];
00280               xi = ceil (x_intercept + EPSILON - 0.5);
00281               if (xi > x0)
00282                      x0 = xi;
00283               x_intercept = (-z + src_width) / affine[0];
00284               xi = ceil (x_intercept - EPSILON - 0.5);
00285               if (xi < x1)
00286                      x1 = xi;
00287        }
00288        else if (affine[0] < -EPSILON)
00289        {
00290               z = affine[2] * (y + 0.5) + affine[4];
00291               x_intercept = (-z + src_width) / affine[0];
00292               xi = ceil (x_intercept + EPSILON - 0.5);
00293               if (xi > x0)
00294                      x0 = xi;
00295               x_intercept = -z / affine[0];
00296               xi = ceil (x_intercept - EPSILON - 0.5);
00297               if (xi < x1)
00298                      x1 = xi;
00299        }
00300        else
00301        {
00302               z = affine[2] * (y + 0.5) + affine[4];
00303               if (z < 0 || z >= src_width)
00304               {
00305                      *p_x1 = *p_x0;
00306                      return;
00307               }
00308        }
00309        /* do top and bottom edges */
00310        if (affine[1] > EPSILON)
00311        {
00312               z = affine[3] * (y + 0.5) + affine[5];
00313               x_intercept = -z / affine[1];
00314               xi = ceil (x_intercept + EPSILON - 0.5);
00315               if (xi > x0)
00316                      x0 = xi;
00317               x_intercept = (-z + src_height) / affine[1];
00318               xi = ceil (x_intercept - EPSILON - 0.5);
00319               if (xi < x1)
00320                      x1 = xi;
00321        }
00322        else if (affine[1] < -EPSILON)
00323        {
00324               z = affine[3] * (y + 0.5) + affine[5];
00325               x_intercept = (-z + src_height) / affine[1];
00326               xi = ceil (x_intercept + EPSILON - 0.5);
00327               if (xi > x0)
00328                      x0 = xi;
00329               x_intercept = -z / affine[1];
00330               xi = ceil (x_intercept - EPSILON - 0.5);
00331               if (xi < x1)
00332                      x1 = xi;
00333        }
00334        else
00335        {
00336               z = affine[3] * (y + 0.5) + affine[5];
00337               if (z < 0 || z >= src_height)
00338               {
00339                      *p_x1 = *p_x0;
00340 
00341                      return;
00342               }
00343        }
00344 
00345 
00346        *p_x0 = x0;
00347        *p_x1 = x1;
00348 }
00349 
00385  void ksvg_art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
00386               const art_u8 *src,
00387               int src_width, int src_height, int src_rowstride,
00388               const double affine[6],
00389               ArtFilterLevel level,
00390               ArtAlphaGamma *alphagamma,
00391               int alpha)
00392 {
00393        /* Note: this is a slow implementation, and is missing all filter
00394           levels other than NEAREST. It is here for clarity of presentation
00395           and to establish the interface. */
00396        int x, y;
00397        double inv[6];
00398        art_u8 *dst_p, *dst_linestart;
00399        const art_u8 *src_p;
00400        ArtPoint pt, src_pt;
00401        int src_x, src_y;
00402        int run_x0, run_x1;
00403 
00404        dst_linestart = dst;
00405        art_affine_invert (inv, affine);
00406 
00407        if(alpha == 255)
00408               for (y = y0; y < y1; y++)
00409               {
00410                      pt.y = y + 0.5;
00411                      run_x0 = x0;
00412                      run_x1 = x1;
00413                      ksvg_art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
00414                                    inv);
00415                      dst_p = dst_linestart + (run_x0 - x0) * 4;
00416                      for (x = run_x0; x < run_x1; x++)
00417                      {
00418                             pt.x = x + 0.5;
00419                             art_affine_point (&src_pt, &pt, inv);
00420                             src_x = floor (src_pt.x);
00421                             src_y = floor (src_pt.y);
00422                             src_p = src + (src_y * src_rowstride) + src_x * 4;
00423 #ifdef WORDS_BIGENDIAN
00424                             dst_p[0] = dst_p[0] + (((src_p[1] - dst_p[0]) * src_p[0] + 0x80) >> 8);
00425         dst_p[1] = dst_p[1] + (((src_p[2] - dst_p[1]) * src_p[0] + 0x80) >> 8);
00426         dst_p[2] = dst_p[2] + (((src_p[3] - dst_p[2]) * src_p[0] + 0x80) >> 8);
00427 #else
00428                             dst_p[0] = dst_p[0] + (((src_p[2] - dst_p[0]) * src_p[3] + 0x80) >> 8);
00429                             dst_p[1] = dst_p[1] + (((src_p[1] - dst_p[1]) * src_p[3] + 0x80) >> 8);
00430                             dst_p[2] = dst_p[2] + (((src_p[0] - dst_p[2]) * src_p[3] + 0x80) >> 8);
00431 #endif
00432                             dst_p += 4;
00433                      }
00434                      dst_linestart += dst_rowstride;
00435               }
00436        else
00437               for (y = y0; y < y1; y++)
00438               {
00439                      pt.y = y + 0.5;
00440                      run_x0 = x0;
00441                      run_x1 = x1;
00442                      ksvg_art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
00443                                    inv);
00444                      dst_p = dst_linestart + (run_x0 - x0) * 4;
00445                      for (x = run_x0; x < run_x1; x++)
00446                      {
00447                             pt.x = x + 0.5;
00448                             art_affine_point (&src_pt, &pt, inv);
00449                             src_x = floor (src_pt.x);
00450                             src_y = floor (src_pt.y);
00451                             src_p = src + (src_y * src_rowstride) + src_x * 4;
00452                             if (src_p[3] != 0)
00453                                    {
00454                                    dst_p[0] = dst_p[0] + (((src_p[2] - dst_p[0]) * alpha + 0x80) >> 8);
00455                                    dst_p[1] = dst_p[1] + (((src_p[1] - dst_p[1]) * alpha + 0x80) >> 8);
00456                                    dst_p[2] = dst_p[2] + (((src_p[0] - dst_p[2]) * alpha + 0x80) >> 8);
00457                                    }
00458                             dst_p += 4;
00459                      }
00460                      dst_linestart += dst_rowstride;
00461               }
00462 }
00463 
00464 typedef struct _ksvgArtRgbAffineClipAlphaData ksvgArtRgbAffineClipAlphaData;
00465 
00466 struct _ksvgArtRgbAffineClipAlphaData
00467 {
00468        int alphatab[256];
00469        art_u8 alpha;
00470        art_u8 *dst;
00471        int dst_rowstride;
00472        int x0, x1;
00473        double inv[6];
00474        const art_u8 *src;
00475        int src_width;
00476        int src_height;
00477        int src_rowstride;
00478        const art_u8 *mask;
00479        int y0;
00480 };
00481 
00482 static
00483 void ksvg_art_rgb_affine_clip_run(art_u8 *dst_p, int x0, int x1, int y, const double inv[6],
00484        int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
00485 {
00486        const art_u8 *src_p;
00487        ArtPoint pt, src_pt;
00488        int src_x, src_y;
00489        int x;
00490 
00491        if(alpha > 255)
00492               alpha = 255;
00493 
00494        pt.y = y;
00495 
00496        for(x = x0; x < x1; x++)
00497        {
00498               pt.x = x;
00499 
00500               art_affine_point(&src_pt, &pt, inv);
00501 
00502               src_x = (int)(src_pt.x);
00503               src_y = (int)(src_pt.y);
00504 
00505               if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
00506               {
00507                      int s;
00508                      int d;
00509                      int tmp;
00510                      int srcAlpha;
00511 
00512                      src_p = src + (src_y * src_rowstride) + src_x * 4;
00513 
00514                      srcAlpha = alpha * src_p[3] + 0x80;
00515                      srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
00516 
00517                      d = *dst_p;
00518                      s = src_p[2];
00519 
00520                      tmp = srcAlpha * (s - d) + 0x80;
00521                      tmp = (tmp + (tmp >> 8)) >> 8;
00522 
00523                      *dst_p++ = d + tmp;
00524 
00525                      d = *dst_p;
00526                      s = src_p[1];
00527 
00528                      tmp = srcAlpha * (s - d) + 0x80;
00529                      tmp = (tmp + (tmp >> 8)) >> 8;
00530 
00531                      *dst_p++ = d + tmp;
00532 
00533                      d = *dst_p;
00534                      s = src_p[0];
00535 
00536                      tmp = srcAlpha * (s - d) + 0x80;
00537                      tmp = (tmp + (tmp >> 8)) >> 8;
00538 
00539                      *dst_p++ = d + tmp;
00540               }
00541               else
00542                      dst_p += 3;
00543        }
00544 }
00545 
00546 static void
00547 ksvg_art_rgb_affine_clip_callback (void *callback_data, int y,
00548                                                                                                   int start, ArtSVPRenderAAStep *steps, int n_steps)
00549 {
00550        ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
00551        art_u8 *linebuf;
00552        int run_x0, run_x1;
00553        art_u32 running_sum = start;
00554        int x0, x1;
00555        int k;
00556        int *alphatab;
00557        int alpha;
00558 
00559        linebuf = data->dst;
00560        x0 = data->x0;
00561        x1 = data->x1;
00562 
00563        alphatab = data->alphatab;
00564 
00565        if(n_steps > 0)
00566        {
00567               run_x1 = steps[0].x;
00568               if(run_x1 > x0)
00569               {
00570                      alpha = (running_sum >> 16) & 0xff;
00571                      if(alpha)
00572                             ksvg_art_rgb_affine_clip_run(linebuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00573               }
00574 
00575               for(k = 0; k < n_steps - 1; k++)
00576               {
00577                      running_sum += steps[k].delta;
00578                      run_x0 = run_x1;
00579                      run_x1 = steps[k + 1].x;
00580                      if(run_x1 > run_x0)
00581                      {
00582                             alpha = (running_sum >> 16) & 0xff;
00583                             if(alpha)
00584                                    ksvg_art_rgb_affine_clip_run(linebuf + (run_x0 - x0) * 3, run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00585                      }
00586               }
00587               running_sum += steps[k].delta;
00588               if(x1 > run_x1)
00589               {
00590                      alpha = (running_sum >> 16) & 0xff;
00591                      if(alpha)
00592                             ksvg_art_rgb_affine_clip_run(linebuf + (run_x1 - x0) * 3, run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00593               }
00594        }
00595        else
00596        {
00597               alpha = (running_sum >> 16) & 0xff;
00598               if(alpha)
00599                      ksvg_art_rgb_affine_clip_run(linebuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00600        }
00601 
00602        data->dst += data->dst_rowstride;
00603 }
00604 
00605 static
00606 void ksvg_art_rgb_affine_clip_mask_run(art_u8 *dst_p, const art_u8 *mask, int x0, int x1, int y, const double inv[6],
00607        int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
00608 {
00609        const art_u8 *src_p;
00610        ArtPoint pt, src_pt;
00611        int src_x, src_y;
00612        int x;
00613 
00614        if(alpha > 255)
00615               alpha = 255;
00616 
00617        pt.y = y;
00618 
00619        for(x = x0; x < x1; x++)
00620        {
00621               pt.x = x;
00622 
00623               art_affine_point(&src_pt, &pt, inv);
00624 
00625               src_x = (int)(src_pt.x);
00626               src_y = (int)(src_pt.y);
00627 
00628               if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
00629               {
00630                      int s;
00631                      int d;
00632                      int tmp;
00633                      int srcAlpha;
00634 
00635                      src_p = src + (src_y * src_rowstride) + src_x * 4;
00636 
00637                      srcAlpha = alpha * src_p[3] + 0x80;
00638                      srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
00639 
00640                      srcAlpha = (srcAlpha * *mask++) + 0x80;
00641                      srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
00642 
00643                      d = *dst_p;
00644                      s = src_p[2];
00645 
00646                      tmp = srcAlpha * (s - d) + 0x80;
00647                      tmp = (tmp + (tmp >> 8)) >> 8;
00648 
00649                      *dst_p++ = d + tmp;
00650 
00651                      d = *dst_p;
00652                      s = src_p[1];
00653 
00654                      tmp = srcAlpha * (s - d) + 0x80;
00655                      tmp = (tmp + (tmp >> 8)) >> 8;
00656 
00657                      *dst_p++ = d + tmp;
00658 
00659                      d = *dst_p;
00660                      s = src_p[0];
00661 
00662                      tmp = srcAlpha * (s - d) + 0x80;
00663                      tmp = (tmp + (tmp >> 8)) >> 8;
00664 
00665                      *dst_p++ = d + tmp;
00666               }
00667               else
00668               {
00669                      dst_p += 3;
00670                      mask++;
00671               }
00672        }
00673 }
00674 
00675 static void
00676 ksvg_art_rgb_affine_clip_mask_callback (void *callback_data, int y,
00677                                                                                                   int start, ArtSVPRenderAAStep *steps, int n_steps)
00678 {
00679        ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
00680        art_u8 *linebuf;
00681        int run_x0, run_x1;
00682        art_u32 running_sum = start;
00683        int x0, x1;
00684        int k;
00685        int *alphatab;
00686        int alpha;
00687        const art_u8 *maskbuf;
00688 
00689        linebuf = data->dst;
00690        x0 = data->x0;
00691        x1 = data->x1;
00692 
00693        alphatab = data->alphatab;
00694        maskbuf = data->mask + (y - data->y0) * (x1 - x0);
00695 
00696        if(n_steps > 0)
00697        {
00698               run_x1 = steps[0].x;
00699               if(run_x1 > x0)
00700               {
00701                      alpha = (running_sum >> 16) & 0xff;
00702                      if(alpha)
00703                             ksvg_art_rgb_affine_clip_mask_run(linebuf, maskbuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00704               }
00705 
00706               for(k = 0; k < n_steps - 1; k++)
00707               {
00708                      running_sum += steps[k].delta;
00709                      run_x0 = run_x1;
00710                      run_x1 = steps[k + 1].x;
00711                      if(run_x1 > run_x0)
00712                      {
00713                             alpha = (running_sum >> 16) & 0xff;
00714                             if(alpha)
00715                                    ksvg_art_rgb_affine_clip_mask_run(linebuf + (run_x0 - x0) * 3, maskbuf + (run_x0 - x0), run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00716                      }
00717               }
00718               running_sum += steps[k].delta;
00719               if(x1 > run_x1)
00720               {
00721                      alpha = (running_sum >> 16) & 0xff;
00722                      if(alpha)
00723                             ksvg_art_rgb_affine_clip_mask_run(linebuf + (run_x1 - x0) * 3, maskbuf + (run_x1 - x0), run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00724               }
00725        }
00726        else
00727        {
00728               alpha = (running_sum >> 16) & 0xff;
00729               if(alpha)
00730                      ksvg_art_rgb_affine_clip_mask_run(linebuf, maskbuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00731        }
00732 
00733        data->dst += data->dst_rowstride;
00734 }
00735 
00736 static
00737 void ksvg_art_rgba_affine_clip_run(art_u8 *dst_p, int x0, int x1, int y, const double inv[6],
00738        int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
00739 {
00740        const art_u8 *src_p;
00741        ArtPoint pt, src_pt;
00742        int src_x, src_y;
00743        int x;
00744 
00745        if(alpha > 255)
00746               alpha = 255;
00747 
00748        pt.y = y;
00749 
00750        for(x = x0; x < x1; x++)
00751        {
00752               pt.x = x;
00753 
00754               art_affine_point(&src_pt, &pt, inv);
00755 
00756               src_x = (int)(src_pt.x);
00757               src_y = (int)(src_pt.y);
00758 
00759               if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
00760               {
00761                      int s;
00762                      int d;
00763                      int tmp;
00764                      int srcAlpha;
00765 
00766                      src_p = src + (src_y * src_rowstride) + src_x * 4;
00767 
00768 #ifdef WORDS_BIGENDIAN
00769                      srcAlpha = alpha * src_p[0] + 0x80;
00770 #else
00771                      srcAlpha = alpha * src_p[3] + 0x80;
00772 #endif
00773                      srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
00774 
00775                      d = *dst_p;
00776 #ifdef WORDS_BIGENDIAN  
00777                      s = src_p[1];
00778 #else
00779                      s = src_p[2];
00780 #endif
00781                      tmp = srcAlpha * (s - d) + 0x80;
00782                      tmp = (tmp + (tmp >> 8)) >> 8;
00783 
00784                      *dst_p++ = d + tmp;
00785 
00786                      d = *dst_p;
00787 #ifdef WORDS_BIGENDIAN  
00788                      s = src_p[2];
00789 #else
00790                      s = src_p[1];
00791 #endif
00792                      tmp = srcAlpha * (s - d) + 0x80;
00793                      tmp = (tmp + (tmp >> 8)) >> 8;
00794 
00795                      *dst_p++ = d + tmp;
00796 
00797                      d = *dst_p;
00798 #ifdef WORDS_BIGENDIAN  
00799                      s = src_p[3];
00800 #else
00801                      s = src_p[0];
00802 #endif
00803 
00804                      tmp = srcAlpha * (s - d) + 0x80;
00805                      tmp = (tmp + (tmp >> 8)) >> 8;
00806 
00807                      *dst_p++ = d + tmp;
00808 
00809                      d = *dst_p;
00810 
00811                      tmp = srcAlpha * (255 - d) + 0x80;
00812                      tmp = (tmp + (tmp >> 8)) >> 8;
00813 
00814                      *dst_p++ = d + tmp;
00815               }
00816               else
00817                      dst_p += 4;
00818        }
00819 }
00820 
00821 static void
00822 ksvg_art_rgba_affine_clip_callback (void *callback_data, int y,
00823                                                                                                   int start, ArtSVPRenderAAStep *steps, int n_steps)
00824 {
00825        ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
00826        art_u8 *linebuf;
00827        int run_x0, run_x1;
00828        art_u32 running_sum = start;
00829        int x0, x1;
00830        int k;
00831        int *alphatab;
00832        int alpha;
00833 
00834        linebuf = data->dst;
00835        x0 = data->x0;
00836        x1 = data->x1;
00837 
00838        alphatab = data->alphatab;
00839 
00840        if(n_steps > 0)
00841        {
00842               run_x1 = steps[0].x;
00843               if(run_x1 > x0)
00844               {
00845                      alpha = (running_sum >> 16) & 0xff;
00846                      if(alpha)
00847                             ksvg_art_rgba_affine_clip_run(linebuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00848               }
00849 
00850               for(k = 0; k < n_steps - 1; k++)
00851               {
00852                      running_sum += steps[k].delta;
00853                      run_x0 = run_x1;
00854                      run_x1 = steps[k + 1].x;
00855                      if(run_x1 > run_x0)
00856                      {
00857                             alpha = (running_sum >> 16) & 0xff;
00858                             if(alpha)
00859                                    ksvg_art_rgba_affine_clip_run(linebuf + (run_x0 - x0) * 4, run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00860                      }
00861               }
00862               running_sum += steps[k].delta;
00863               if(x1 > run_x1)
00864               {
00865                      alpha = (running_sum >> 16) & 0xff;
00866                      if(alpha)
00867                             ksvg_art_rgba_affine_clip_run(linebuf + (run_x1 - x0) * 4, run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00868               }
00869        }
00870        else
00871        {
00872               alpha = (running_sum >> 16) & 0xff;
00873               if(alpha)
00874                      ksvg_art_rgba_affine_clip_run(linebuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00875        }
00876 
00877        data->dst += data->dst_rowstride;
00878 }
00879 
00880 static
00881 void ksvg_art_rgba_affine_clip_mask_run(art_u8 *dst_p, const art_u8 *mask, int x0, int x1, int y, const double inv[6],
00882        int alpha, const art_u8 *src, int src_rowstride, int src_width, int src_height)
00883 {
00884        const art_u8 *src_p;
00885        ArtPoint pt, src_pt;
00886        int src_x, src_y;
00887        int x;
00888 
00889        if(alpha > 255)
00890               alpha = 255;
00891 
00892        pt.y = y;
00893 
00894        for(x = x0; x < x1; x++)
00895        {
00896               pt.x = x;
00897 
00898               art_affine_point(&src_pt, &pt, inv);
00899 
00900               src_x = (int)(src_pt.x);
00901               src_y = (int)(src_pt.y);
00902 
00903               if(src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
00904               {
00905                      int s;
00906                      int d;
00907                      int tmp;
00908                      int srcAlpha;
00909 
00910                      src_p = src + (src_y * src_rowstride) + src_x * 4;
00911 
00912                      srcAlpha = alpha * src_p[3] + 0x80;
00913                      srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
00914 
00915                      srcAlpha = (srcAlpha * *mask++) + 0x80;
00916                      srcAlpha = (srcAlpha + (srcAlpha >> 8)) >> 8;
00917 
00918                      d = *dst_p;
00919                      s = src_p[2];
00920 
00921                      tmp = srcAlpha * (s - d) + 0x80;
00922                      tmp = (tmp + (tmp >> 8)) >> 8;
00923 
00924                      *dst_p++ = d + tmp;
00925 
00926                      d = *dst_p;
00927                      s = src_p[1];
00928 
00929                      tmp = srcAlpha * (s - d) + 0x80;
00930                      tmp = (tmp + (tmp >> 8)) >> 8;
00931 
00932                      *dst_p++ = d + tmp;
00933 
00934                      d = *dst_p;
00935                      s = src_p[0];
00936 
00937                      tmp = srcAlpha * (s - d) + 0x80;
00938                      tmp = (tmp + (tmp >> 8)) >> 8;
00939 
00940                      *dst_p++ = d + tmp;
00941 
00942                      d = *dst_p;
00943 
00944                      tmp = srcAlpha * (255 - d) + 0x80;
00945                      tmp = (tmp + (tmp >> 8)) >> 8;
00946 
00947                      *dst_p++ = d + tmp;
00948               }
00949               else
00950               {
00951                      dst_p += 4;
00952                      mask++;
00953               }
00954        }
00955 }
00956 
00957 static void
00958 ksvg_art_rgba_affine_clip_mask_callback (void *callback_data, int y,
00959                                                                                                   int start, ArtSVPRenderAAStep *steps, int n_steps)
00960 {
00961        ksvgArtRgbAffineClipAlphaData *data = (ksvgArtRgbAffineClipAlphaData *)callback_data;
00962        art_u8 *linebuf;
00963        int run_x0, run_x1;
00964        art_u32 running_sum = start;
00965        int x0, x1;
00966        int k;
00967        int *alphatab;
00968        int alpha;
00969        const art_u8 *maskbuf;
00970 
00971        linebuf = data->dst;
00972        x0 = data->x0;
00973        x1 = data->x1;
00974 
00975        alphatab = data->alphatab;
00976        maskbuf = data->mask + (y - data->y0) * (x1 - x0);
00977 
00978        if(n_steps > 0)
00979        {
00980               run_x1 = steps[0].x;
00981               if(run_x1 > x0)
00982               {
00983                      alpha = (running_sum >> 16) & 0xff;
00984                      if(alpha)
00985                             ksvg_art_rgba_affine_clip_mask_run(linebuf, maskbuf, x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00986               }
00987 
00988               for(k = 0; k < n_steps - 1; k++)
00989               {
00990                      running_sum += steps[k].delta;
00991                      run_x0 = run_x1;
00992                      run_x1 = steps[k + 1].x;
00993                      if(run_x1 > run_x0)
00994                      {
00995                             alpha = (running_sum >> 16) & 0xff;
00996                             if(alpha)
00997                                    ksvg_art_rgba_affine_clip_mask_run(linebuf + (run_x0 - x0) * 4, maskbuf + (run_x0 - x0), run_x0, run_x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
00998                      }
00999               }
01000               running_sum += steps[k].delta;
01001               if(x1 > run_x1)
01002               {
01003                      alpha = (running_sum >> 16) & 0xff;
01004                      if(alpha)
01005                             ksvg_art_rgba_affine_clip_mask_run(linebuf + (run_x1 - x0) * 4, maskbuf + (run_x1 - x0), run_x1, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
01006               }
01007        }
01008        else
01009        {
01010               alpha = (running_sum >> 16) & 0xff;
01011               if(alpha)
01012                      ksvg_art_rgba_affine_clip_mask_run(linebuf, maskbuf, x0, x1, y, data->inv, alphatab[alpha], data->src, data->src_rowstride, data->src_width, data->src_height);
01013        }
01014 
01015        data->dst += data->dst_rowstride;
01016 }
01017 
01054 void ksvg_art_rgb_affine_clip(const ArtSVP *svp, art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride, int dst_channels,
01055               const art_u8 *src,
01056               int src_width, int src_height, int src_rowstride,
01057               const double affine[6],
01058               int alpha, const art_u8 *mask)
01059 {
01060        ksvgArtRgbAffineClipAlphaData data;
01061        int i;
01062        int a, da;
01063 
01064        data.alpha = alpha;
01065 
01066        a = 0x8000;
01067        da = (alpha * 66051 + 0x80) >> 8;  /* 66051 equals 2 ^ 32 / (255 * 255) */
01068 
01069        for(i = 0; i < 256; i++)
01070        {
01071               data.alphatab[i] = a >> 16;
01072               a += da;
01073        }
01074 
01075        data.dst = dst;
01076        data.dst_rowstride = dst_rowstride;
01077        data.x0 = x0;
01078        data.x1 = x1;
01079        data.y0 = y0;
01080        data.mask = mask;
01081 
01082        art_affine_invert(data.inv, affine);
01083 
01084        data.src = src;
01085        data.src_width = src_width;
01086        data.src_height = src_height;
01087        data.src_rowstride = src_rowstride;
01088 
01089        if(dst_channels == 3)
01090        {
01091               if(mask)
01092                      art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_affine_clip_mask_callback, &data);
01093               else
01094                      art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgb_affine_clip_callback, &data);
01095        }
01096        else
01097        {
01098               if(mask)
01099                      art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_affine_clip_mask_callback, &data);
01100               else
01101                      art_svp_render_aa(svp, x0, y0, x1, y1, ksvg_art_rgba_affine_clip_callback, &data);
01102        }
01103 }
01104