Back to index

lightning-sunbird  0.9+nobinonly
ictri.c
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2002 Keith Packard
00003  *
00004  * Permission to use, copy, modify, distribute, and sell this software and its
00005  * documentation for any purpose is hereby granted without fee, provided that
00006  * the above copyright notice appear in all copies and that both that
00007  * copyright notice and this permission notice appear in supporting
00008  * documentation, and that the name of Keith Packard not be used in
00009  * advertising or publicity pertaining to distribution of the software without
00010  * specific, written prior permission.  Keith Packard makes no
00011  * representations about the suitability of this software for any purpose.  It
00012  * is provided "as is" without express or implied warranty.
00013  *
00014  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00015  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
00016  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00017  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
00018  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
00019  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00020  * PERFORMANCE OF THIS SOFTWARE.
00021  */
00022 
00023 #include "icint.h"
00024 
00025 static void
00026 pixman_point_fixed_bounds (int npoint, const pixman_point_fixed_t *points, pixman_box16_t *bounds)
00027 {
00028     bounds->x1 = xFixedToInt (points->x);
00029     bounds->x2 = xFixedToInt (xFixedCeil (points->x));
00030     bounds->y1 = xFixedToInt (points->y);
00031     bounds->y2 = xFixedToInt (xFixedCeil (points->y));
00032     points++;
00033     npoint--;
00034     while (npoint-- > 0)
00035     {
00036        int    x1 = xFixedToInt (points->x);
00037        int    x2 = xFixedToInt (xFixedCeil (points->x));
00038        int    y1 = xFixedToInt (points->y);
00039        int    y2 = xFixedToInt (xFixedCeil (points->y));
00040 
00041        if (x1 < bounds->x1)
00042            bounds->x1 = x1;
00043        else if (x2 > bounds->x2)
00044            bounds->x2 = x2;
00045        if (y1 < bounds->y1)
00046            bounds->y1 = y1;
00047        else if (y2 > bounds->y2)
00048            bounds->y2 = y2;
00049        points++;
00050     }
00051 }
00052 
00053 static void
00054 pixman_triangle_bounds (int ntri, const pixman_triangle_t *tris, pixman_box16_t *bounds)
00055 {
00056     pixman_point_fixed_bounds (ntri * 3, (pixman_point_fixed_t *) tris, bounds);
00057 }
00058 
00059 static void
00060 FbRasterizeTriangle (pixman_image_t              *image,
00061                    const pixman_triangle_t       *tri,
00062                    int             x_off,
00063                    int             y_off)
00064 {
00065     const pixman_point_fixed_t     *top, *left, *right, *t;
00066     pixman_trapezoid_t             trap[2];
00067 
00068     top = &tri->p1;
00069     left = &tri->p2;
00070     right = &tri->p3;
00071     if (left->y < top->y) {
00072        t = left; left = top; top = t;
00073     }
00074     if (right->y < top->y) {
00075        t = right; right = top; top = t;
00076     }
00077     /* XXX: This code is broken, left and right must be determined by
00078        comparing the angles of the two edges, (eg. we can only compare
00079        X coordinates if we've already intersected each edge with the
00080        same Y coordinate) */
00081     if (right->x < left->x) {
00082        t = right; right = left; left = t;
00083     }
00084 
00085     /*
00086      * Two cases:
00087      *
00088      *        +             +
00089      *        / \             / \
00090      *       /   \           /   \
00091      *      /     +         +     \
00092      *      /    --           --    \
00093      *     /   --               --   \
00094      *    / ---                   --- \
00095      *  +--                         --+
00096      */
00097     
00098     trap[0].top = top->y;
00099     
00100     trap[0].left.p1.x = top->x;
00101     trap[0].left.p1.y = trap[0].top;
00102     trap[0].left.p2.x = left->x;
00103     trap[0].left.p2.y = left->y;
00104     
00105     trap[0].right.p1 = trap[0].left.p1;
00106     trap[0].right.p2.x = right->x;
00107     trap[0].right.p2.y = right->y;
00108     
00109     if (right->y < left->y)
00110     {
00111        trap[0].bottom = trap[0].right.p2.y;
00112 
00113        trap[1].top = trap[0].bottom;
00114        trap[1].bottom = trap[0].left.p2.y;
00115        
00116        trap[1].left = trap[0].left;
00117        trap[1].right.p1 = trap[0].right.p2;
00118        trap[1].right.p2 = trap[0].left.p2;
00119     }
00120     else
00121     {
00122        trap[0].bottom = trap[0].left.p2.y;
00123        
00124        trap[1].top = trap[0].bottom;
00125        trap[1].bottom = trap[0].right.p2.y;
00126        
00127        trap[1].right = trap[0].right;
00128        trap[1].left.p1 = trap[0].left.p2;
00129        trap[1].left.p2 = trap[0].right.p2;
00130     }
00131     if (trap[0].top != trap[0].bottom)
00132        fbRasterizeTrapezoid (image, &trap[0], x_off, y_off);
00133     if (trap[1].top != trap[1].bottom)
00134        fbRasterizeTrapezoid (image, &trap[1], x_off, y_off);
00135 }
00136 
00137 void
00138 pixman_composite_triangles (pixman_operator_t    op,
00139                     pixman_image_t        *src,
00140                     pixman_image_t        *dst,
00141                     int            xSrc,
00142                     int            ySrc,
00143                     const pixman_triangle_t      *tris,
00144                     int            ntris)
00145 {
00146     pixman_box16_t   bounds;
00147     pixman_image_t          *image = NULL;
00148     int              xDst, yDst;
00149     int              xRel, yRel;
00150     pixman_format_t  *format;
00151     
00152     xDst = tris[0].p1.x >> 16;
00153     yDst = tris[0].p1.y >> 16;
00154 
00155     format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
00156     
00157     if (format)
00158     {
00159        pixman_triangle_bounds (ntris, tris, &bounds);
00160        if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
00161            return;
00162        image = FbCreateAlphaPicture (dst,
00163                                   format,
00164                                   bounds.x2 - bounds.x1,
00165                                   bounds.y2 - bounds.y1);
00166        if (!image)
00167            return;
00168     }
00169     for (; ntris; ntris--, tris++)
00170     {
00171        if (!format)
00172        {
00173            pixman_triangle_bounds (1, tris, &bounds);
00174            if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
00175               continue;
00176            image = FbCreateAlphaPicture (dst,
00177                                      format,
00178                                      bounds.x2 - bounds.x1,
00179                                      bounds.y2 - bounds.y1);
00180            if (!image)
00181               break;
00182        }
00183        FbRasterizeTriangle (image, tris, -bounds.x1, -bounds.y1);
00184        if (!format)
00185        {
00186            xRel = bounds.x1 + xSrc - xDst;
00187            yRel = bounds.y1 + ySrc - yDst;
00188            pixman_composite (op, src, image, dst,
00189                       xRel, yRel, 0, 0, bounds.x1, bounds.y1,
00190                       bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
00191            pixman_image_destroy (image);
00192        }
00193        /* XXX adjust xSrc and ySrc */
00194     }
00195     if (format)
00196     {
00197        xRel = bounds.x1 + xSrc - xDst;
00198        yRel = bounds.y1 + ySrc - yDst;
00199        pixman_composite (op, src, image, dst,
00200                    xRel, yRel, 0, 0, bounds.x1, bounds.y1,
00201                    bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
00202        pixman_image_destroy (image);
00203     }
00204 
00205     pixman_format_destroy (format);
00206 }
00207 
00208 void
00209 pixman_composite_tri_strip (pixman_operator_t           op,
00210                    pixman_image_t         *src,
00211                    pixman_image_t         *dst,
00212                    int             xSrc,
00213                    int             ySrc,
00214                    const pixman_point_fixed_t    *points,
00215                    int             npoints)
00216 {
00217     pixman_triangle_t              tri;
00218     pixman_box16_t   bounds;
00219     pixman_image_t          *image = NULL;
00220     int              xDst, yDst;
00221     int              xRel, yRel;
00222     pixman_format_t  *format;
00223     
00224     xDst = points[0].x >> 16;
00225     yDst = points[0].y >> 16;
00226 
00227     format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
00228     
00229     if (npoints < 3)
00230        return;
00231     if (format)
00232     {
00233        pixman_point_fixed_bounds (npoints, points, &bounds);
00234        if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
00235            return;
00236        image = FbCreateAlphaPicture (dst,
00237                                   format,
00238                                   bounds.x2 - bounds.x1,
00239                                   bounds.y2 - bounds.y1);
00240        if (!image)
00241            return;
00242     }
00243     for (; npoints >= 3; npoints--, points++)
00244     {
00245        tri.p1 = points[0];
00246        tri.p2 = points[1];
00247        tri.p3 = points[2];
00248        if (!format)
00249        {
00250            pixman_triangle_bounds (1, &tri, &bounds);
00251            if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
00252               continue;
00253            image = FbCreateAlphaPicture (dst,
00254                                      format, 
00255                                      bounds.x2 - bounds.x1,
00256                                      bounds.y2 - bounds.y1);
00257            if (!image)
00258               continue;
00259        }
00260        FbRasterizeTriangle (image, &tri, -bounds.x1, -bounds.y1);
00261        if (!format)
00262        {
00263            xRel = bounds.x1 + xSrc - xDst;
00264            yRel = bounds.y1 + ySrc - yDst;
00265            pixman_composite (op, src, image, dst,
00266                       xRel, yRel, 0, 0, bounds.x1, bounds.y1,
00267                       bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
00268            pixman_image_destroy (image);
00269        }
00270     }
00271     if (format)
00272     {
00273        xRel = bounds.x1 + xSrc - xDst;
00274        yRel = bounds.y1 + ySrc - yDst;
00275        pixman_composite (op, src, image, dst,
00276                    xRel, yRel, 0, 0, bounds.x1, bounds.y1,
00277                    bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
00278        pixman_image_destroy (image);
00279     }
00280 
00281     pixman_format_destroy (format);
00282 }
00283 
00284 void
00285 pixman_composite_tri_fan (pixman_operator_t             op,
00286                  pixman_image_t           *src,
00287                  pixman_image_t           *dst,
00288                  int               xSrc,
00289                  int               ySrc,
00290                  const pixman_point_fixed_t      *points,
00291                  int               npoints)
00292 {
00293     pixman_triangle_t              tri;
00294     pixman_box16_t   bounds;
00295     pixman_image_t          *image = NULL;
00296     const pixman_point_fixed_t     *first;
00297     int              xDst, yDst;
00298     int              xRel, yRel;
00299     pixman_format_t  *format;
00300     
00301     xDst = points[0].x >> 16;
00302     yDst = points[0].y >> 16;
00303 
00304     format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
00305     
00306     if (npoints < 3)
00307        return;
00308     if (format)
00309     {
00310        pixman_point_fixed_bounds (npoints, points, &bounds);
00311        if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
00312            return;
00313        image = FbCreateAlphaPicture (dst,
00314                                   format,
00315                                   bounds.x2 - bounds.x1,
00316                                   bounds.y2 - bounds.y1);
00317        if (!image)
00318            return;
00319     }
00320     first = points++;
00321     npoints--;
00322     for (; npoints >= 2; npoints--, points++)
00323     {
00324        tri.p1 = *first;
00325        tri.p2 = points[0];
00326        tri.p3 = points[1];
00327        if (!format)
00328        {
00329            pixman_triangle_bounds (1, &tri, &bounds);
00330            if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
00331               continue;
00332            image = FbCreateAlphaPicture (dst,
00333                                      format, 
00334                                      bounds.x2 - bounds.x1,
00335                                      bounds.y2 - bounds.y1);
00336            if (!image)
00337               continue;
00338        }
00339        FbRasterizeTriangle (image, &tri, -bounds.x1, -bounds.y1);
00340        if (!format)
00341        {
00342            xRel = bounds.x1 + xSrc - xDst;
00343            yRel = bounds.y1 + ySrc - yDst;
00344            pixman_composite (op, src, image, dst,
00345                       xRel, yRel, 0, 0, bounds.x1, bounds.y1,
00346                       bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
00347            pixman_image_destroy (image);
00348        }
00349     }
00350     if (format)
00351     {
00352        xRel = bounds.x1 + xSrc - xDst;
00353        yRel = bounds.y1 + ySrc - yDst;
00354        pixman_composite (op, src, image, dst,
00355                    xRel, yRel, 0, 0, bounds.x1, bounds.y1,
00356                    bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
00357        pixman_image_destroy (image);
00358     }
00359 
00360     pixman_format_destroy (format);
00361 }
00362