Back to index

lightning-sunbird  0.9+nobinonly
ictrap.c
Go to the documentation of this file.
00001 /*
00002  * $Id: ictrap.c,v 1.3.4.2 2005/10/04 03:28:22 vladimir%pobox.com Exp $
00003  *
00004  * Copyright © 2002 Keith Packard
00005  *
00006  * Permission to use, copy, modify, distribute, and sell this software and its
00007  * documentation for any purpose is hereby granted without fee, provided that
00008  * the above copyright notice appear in all copies and that both that
00009  * copyright notice and this permission notice appear in supporting
00010  * documentation, and that the name of Keith Packard not be used in
00011  * advertising or publicity pertaining to distribution of the software without
00012  * specific, written prior permission.  Keith Packard makes no
00013  * representations about the suitability of this software for any purpose.  It
00014  * is provided "as is" without express or implied warranty.
00015  *
00016  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00017  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
00018  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00019  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
00020  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
00021  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00022  * PERFORMANCE OF THIS SOFTWARE.
00023  */
00024 
00025 #include "icint.h"
00026 
00027 pixman_image_t *
00028 FbCreateAlphaPicture (pixman_image_t      *dst,
00029                     pixman_format_t       *format,
00030                     uint16_t       width,
00031                     uint16_t       height)
00032 {
00033     pixman_image_t   *image;
00034     int own_format = 0;
00035 
00036     if (width > 32767 || height > 32767)
00037        return NULL;
00038 
00039     if (!format)
00040     {
00041        own_format = 1;
00042        if (dst->polyEdge == PolyEdgeSharp)
00043            format = pixman_format_create (PIXMAN_FORMAT_NAME_A1);
00044        else
00045            format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
00046        if (!format)
00047            return NULL;
00048     }
00049 
00050     image = pixman_image_create (format, width, height); 
00051 
00052     if (own_format)
00053        pixman_format_destroy (format);
00054 
00055     /* XXX: Is this a reasonable way to clear the image? Would
00056        probably be preferable to use pixman_image_fill_rectangle once such a
00057        beast exists. */
00058     memset (image->pixels->data, 0, height * image->pixels->stride);
00059 
00060     return image;
00061 }
00062 
00063 static pixman_fixed16_16_t
00064 pixman_line_fixed_x (const pixman_line_fixed_t *l, pixman_fixed16_16_t y, int ceil)
00065 {
00066     pixman_fixed16_16_t    dx = l->p2.x - l->p1.x;
00067     xFixed_32_32    ex = (xFixed_32_32) (y - l->p1.y) * dx;
00068     pixman_fixed16_16_t    dy = l->p2.y - l->p1.y;
00069     if (ceil)
00070        ex += (dy - 1);
00071     return l->p1.x + (pixman_fixed16_16_t) (ex / dy);
00072 }
00073 
00074 static void
00075 pixman_trapezoid_bounds (int ntrap, const pixman_trapezoid_t *traps, pixman_box16_t *box)
00076 {
00077     box->y1 = MAXSHORT;
00078     box->y2 = MINSHORT;
00079     box->x1 = MAXSHORT;
00080     box->x2 = MINSHORT;
00081     for (; ntrap; ntrap--, traps++)
00082     {
00083        int16_t x1, y1, x2, y2;
00084 
00085        if (!xTrapezoidValid(traps))
00086            continue;
00087        y1 = xFixedToInt (traps->top);
00088        if (y1 < box->y1)
00089            box->y1 = y1;
00090        
00091        y2 = xFixedToInt (xFixedCeil (traps->bottom));
00092        if (y2 > box->y2)
00093            box->y2 = y2;
00094        
00095        x1 = xFixedToInt (MIN (pixman_line_fixed_x (&traps->left, traps->top, 0),
00096                             pixman_line_fixed_x (&traps->left, traps->bottom, 0)));
00097        if (x1 < box->x1)
00098            box->x1 = x1;
00099        
00100        x2 = xFixedToInt (xFixedCeil (MAX (pixman_line_fixed_x (&traps->right, traps->top, 1),
00101                                       pixman_line_fixed_x (&traps->right, traps->bottom, 1))));
00102        if (x2 > box->x2)
00103            box->x2 = x2;
00104     }
00105 }
00106 
00107 /* XXX: There are failure cases in this function. Don't we need to
00108  * propagate the errors out?
00109  */
00110 void
00111 pixman_composite_trapezoids (pixman_operator_t         op,
00112                           pixman_image_t        *src,
00113                           pixman_image_t        *dst,
00114                           int                   xSrc,
00115                           int                   ySrc,
00116                           const pixman_trapezoid_t *traps,
00117                           int                   ntraps)
00118 {
00119     pixman_image_t   *image = NULL;
00120     pixman_box16_t   traps_bounds, dst_bounds, bounds;
00121     pixman_region16_t       *traps_region, *dst_region;
00122     int16_t          xDst, yDst;
00123     int16_t          xRel, yRel;
00124     pixman_format_t  *format;
00125 
00126     if (ntraps == 0)
00127        return;
00128 
00129     /*
00130      * Check for solid alpha add
00131      */
00132     if (op == PIXMAN_OPERATOR_ADD && miIsSolidAlpha (src))
00133     {
00134        for (; ntraps; ntraps--, traps++)
00135            fbRasterizeTrapezoid (dst, traps, 0, 0);
00136        return;
00137     }
00138 
00139     xDst = traps[0].left.p1.x >> 16;
00140     yDst = traps[0].left.p1.y >> 16;
00141     
00142     pixman_trapezoid_bounds (ntraps, traps, &traps_bounds);
00143 
00144     traps_region = pixman_region_create_simple (&traps_bounds);
00145 
00146     /* XXX: If the image has a clip region set, we should really be
00147      * fetching it here instead, but it looks like we don't yet expose
00148      * a pixman_image_get_clip_region function. */
00149     dst_bounds.x1 = 0;
00150     dst_bounds.y1 = 0;
00151     dst_bounds.x2 = pixman_image_get_width (dst);
00152     dst_bounds.y2 = pixman_image_get_height (dst);
00153 
00154     dst_region = pixman_region_create_simple (&dst_bounds);
00155 
00156     pixman_region_intersect (traps_region, traps_region, dst_region);
00157 
00158     bounds = *(pixman_region_extents (traps_region));
00159 
00160     pixman_region_destroy (traps_region);
00161     pixman_region_destroy (dst_region);
00162 
00163     if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
00164        return;
00165 
00166     format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
00167     if (!format)
00168        return;
00169 
00170     image = FbCreateAlphaPicture (dst, format,
00171                               bounds.x2 - bounds.x1,
00172                               bounds.y2 - bounds.y1);
00173     if (!image)
00174     {
00175        pixman_format_destroy (format);
00176        return;
00177     }
00178 
00179     for (; ntraps; ntraps--, traps++)
00180     {
00181        if (!xTrapezoidValid(traps))
00182            continue;
00183        fbRasterizeTrapezoid (image, traps, 
00184                            -bounds.x1, -bounds.y1);
00185     }
00186 
00187     xRel = bounds.x1 + xSrc - xDst;
00188     yRel = bounds.y1 + ySrc - yDst;
00189     pixman_composite (op, src, image, dst,
00190                     xRel, yRel, 0, 0, bounds.x1, bounds.y1,
00191                     bounds.x2 - bounds.x1,
00192                     bounds.y2 - bounds.y1);
00193     pixman_image_destroy (image);
00194 
00195     pixman_format_destroy (format);
00196 }
00197 
00198 void
00199 pixman_add_trapezoids (pixman_image_t            *dst,
00200                      int                  x_off,
00201                      int                  y_off,
00202                      const pixman_trapezoid_t    *traps,
00203                      int                  ntraps)
00204 {
00205     for (; ntraps; ntraps--, traps++)
00206     {
00207        if (!xTrapezoidValid (traps))
00208            continue;
00209 
00210        fbRasterizeTrapezoid (dst, traps, x_off, y_off);
00211     }
00212 }