Back to index

lightning-sunbird  0.9+nobinonly
icrect.c
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2000 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 typedef void  (*FillFunc) (pixman_image_t *dst,
00026                           int16_t       xDst,
00027                           int16_t       yDst,
00028                           uint16_t      width,
00029                           uint16_t      height,
00030                           pixman_bits_t  *pixel);
00031 
00032 
00033 static void
00034 pixman_fill_rect_1bpp (pixman_image_t *dst,
00035                      int16_t              xDst,
00036                      int16_t              yDst,
00037                      uint16_t             width,
00038                      uint16_t             height,
00039                      pixman_bits_t  *pixel)
00040 {
00041     uint32_t value = *pixel ? 0xffffffff : 0;
00042     char *line;
00043 
00044     line = (char *)dst->pixels->data
00045           + yDst * dst->pixels->stride;
00046 
00047     if ((width + xDst - 1) / 32 == xDst / 32) {
00048         uint32_t mask = 0;
00049         int pos = xDst / 32;
00050         int i;
00051 
00052         for (i = xDst; i < width; i++)
00053 #if BITMAP_BIT_ORDER == MSBFirst
00054             mask |= 1 << (0x1f - i);
00055 #else
00056             mask |= 1 << i;
00057 #endif
00058 
00059         while (height-- > 0) {
00060             uint32_t *cur = (uint32_t *) line;
00061             cur [pos] = (cur [pos] & ~mask) | (value & mask);
00062            line += dst->pixels->stride;
00063         }
00064     } else {
00065         uint32_t smask = 0, emask = 0;
00066         int end = ((xDst + width) / 32);
00067         int i;
00068 
00069         if (xDst % 32)
00070             for (i = (xDst % 32); i < 32; i++)
00071 #if BITMAP_BIT_ORDER == MSBFirst
00072                 smask |= 1 << (0x1f - i);
00073 #else
00074                 smask |= 1 << i;
00075 #endif
00076 
00077         if ((width + xDst) % 32)
00078             for (i = 0; i < (width + xDst) % 32; i++)
00079 #if BITMAP_BIT_ORDER == MSBFirst
00080                 emask |= 1 << (0x1f - i);
00081 #else
00082                 emask |= 1 << i;
00083 #endif
00084 
00085         while (height-- > 0) {
00086             uint32_t *cur = (uint32_t *) line;
00087             int start = (xDst / 32);
00088 
00089             if (smask) {
00090                 cur [start] = (cur [start] & ~smask) | (value & smask);
00091                 start++;
00092             }
00093 
00094             if (emask)
00095                 cur [end] = (cur [end] & ~emask) | (value & emask);
00096 
00097             if (end > start)
00098                 memset (cur + start, value, (end - start) * 4);
00099            line += dst->pixels->stride;
00100         }
00101     }
00102 }
00103 
00104 static void
00105 pixman_fill_rect_8bpp (pixman_image_t *dst,
00106                      int16_t              xDst,
00107                      int16_t              yDst,
00108                      uint16_t             width,
00109                      uint16_t             height,
00110                      pixman_bits_t  *pixel)
00111 {
00112     int value = (int) (*pixel);
00113     char *line;
00114 
00115     line = (char *)dst->pixels->data +
00116        xDst + yDst * dst->pixels->stride;
00117     while (height-- > 0) {
00118        memset (line, value, width);
00119        line += dst->pixels->stride;
00120     }
00121 }
00122 
00123 static void
00124 pixman_fill_rect_32bpp (pixman_image_t *dst,
00125                      int16_t               xDst,
00126                      int16_t               yDst, 
00127                      uint16_t      width,
00128                      uint16_t      height,
00129                      pixman_bits_t  *pixel)
00130 {
00131     uint32_t int_pixel;
00132     char *line;
00133     char *data;
00134     int w;
00135 
00136     line = (char *)dst->pixels->data +
00137        xDst * 4 + yDst * dst->pixels->stride;
00138      
00139     int_pixel = *(uint32_t *)pixel;
00140     while (height-- > 0) {
00141        data = line;
00142        w = width;
00143        while (w-- > 0) {
00144            *(uint32_t *)data = int_pixel;
00145            data += 4;
00146        }
00147        line += dst->pixels->stride;
00148     }
00149 }
00150 
00151 static void
00152 pixman_fill_rect_general (pixman_image_t *dst,
00153                        int16_t       xDst,
00154                        int16_t       yDst,
00155                        uint16_t      width,
00156                        uint16_t      height,
00157                        pixman_bits_t  *pixel)
00158 {
00159     int pixel_size;
00160     char *line;
00161     char *data;
00162     int w;
00163 
00164     pixel_size = dst->pixels->bpp >> 3;
00165 
00166     line = (char *)dst->pixels->data +
00167        xDst * pixel_size + yDst * dst->pixels->stride;
00168      
00169     while (height-- > 0) {
00170        data = line;
00171        w = width;
00172        while (w-- > 0) {
00173            memcpy (data, pixel, pixel_size);
00174            data += pixel_size;
00175        }
00176        line += dst->pixels->stride;
00177     }
00178 }
00179 
00180 
00181 static void
00182 pixman_color_rects (pixman_image_t  *dst,
00183              pixman_image_t  *clipPict,
00184              pixman_color_t  *color,
00185              int      nRect,
00186              pixman_rectangle_t *rects,
00187              int      xoff,
00188              int      yoff)
00189 {
00190     pixman_bits_t    pixel;
00191     pixman_region16_t  *clip;
00192     pixman_region16_t  *rects_as_region;
00193     pixman_box16_t     *clipped_rects;
00194     int                       i, n_clipped_rects;
00195     FillFunc            func;
00196 
00197     pixman_color_to_pixel (&dst->image_format,
00198                         color,
00199                         &pixel);
00200 
00201     /* offset to the right place on the destination image */
00202     xoff -= dst->pixels->x;
00203     yoff -= dst->pixels->y;
00204     
00205     clip = pixman_region_create();
00206     pixman_region_union_rect (clip, clip,
00207                            dst->pixels->x, dst->pixels->y,
00208                            dst->pixels->width, dst->pixels->height);
00209 
00210     pixman_region_intersect (clip, clip, clipPict->pCompositeClip);
00211     if (clipPict->alphaMap)
00212     {
00213        pixman_region_translate (clip, 
00214                              -clipPict->alphaOrigin.x,
00215                              -clipPict->alphaOrigin.y);
00216        pixman_region_intersect (clip, clip, clipPict->alphaMap->pCompositeClip);
00217        pixman_region_translate (clip, 
00218                              clipPict->alphaOrigin.x,
00219                              clipPict->alphaOrigin.y);
00220     }
00221 
00222     if (xoff || yoff)
00223     {
00224        for (i = 0; i < nRect; i++)
00225        {
00226            rects[i].x -= xoff;
00227            rects[i].y -= yoff;
00228        }
00229     }
00230 
00231     rects_as_region = pixman_region_create ();
00232     for (i = 0; i < nRect; i++)
00233     {
00234        pixman_region_union_rect (rects_as_region, rects_as_region,
00235                               rects[i].x, rects[i].y,
00236                               rects[i].width, rects[i].height);
00237     }
00238 
00239     pixman_region_intersect (rects_as_region, rects_as_region, clip);
00240     pixman_region_destroy (clip);
00241 
00242     n_clipped_rects = pixman_region_num_rects (rects_as_region);
00243     clipped_rects = pixman_region_rects (rects_as_region);
00244 
00245     if (dst->pixels->bpp == 8)
00246        func = pixman_fill_rect_8bpp;
00247     else if (dst->pixels->bpp == 32)
00248        func = pixman_fill_rect_32bpp;
00249     else if (dst->pixels->bpp == 1)
00250        func = pixman_fill_rect_1bpp;
00251     else 
00252        func = pixman_fill_rect_general;
00253     
00254     for (i = 0; i < n_clipped_rects; i++) {
00255        (*func) (dst,
00256                clipped_rects[i].x1, 
00257                clipped_rects[i].y1, 
00258                clipped_rects[i].x2 - clipped_rects[i].x1, 
00259                clipped_rects[i].y2 - clipped_rects[i].y1,
00260                &pixel);
00261     }
00262 
00263     pixman_region_destroy (rects_as_region);
00264 
00265     if (xoff || yoff)
00266     {
00267        for (i = 0; i < nRect; i++)
00268        {
00269            rects[i].x += xoff;
00270            rects[i].y += yoff;
00271        }
00272     }
00273 }
00274 
00275 void pixman_fill_rectangle (pixman_operator_t    op,
00276                     pixman_image_t        *dst,
00277                     const pixman_color_t  *color,
00278                     int            x,
00279                     int            y,
00280                     unsigned int   width,
00281                     unsigned int   height)
00282 {
00283     pixman_rectangle_t rect;
00284 
00285     rect.x = x;
00286     rect.y = y;
00287     rect.width = width;
00288     rect.height = height;
00289 
00290     pixman_fill_rectangles (op, dst, color, &rect, 1);
00291 }
00292 
00293 void
00294 pixman_fill_rectangles (pixman_operator_t        op,
00295                 pixman_image_t            *dst,
00296                 const pixman_color_t             *color,
00297                 const pixman_rectangle_t  *rects,
00298                 int                nRects)
00299 {
00300     pixman_color_t color_s = *color;
00301 
00302     if (color_s.alpha == 0xffff)
00303     {
00304        if (op == PIXMAN_OPERATOR_OVER)
00305            op = PIXMAN_OPERATOR_SRC;
00306     }
00307     if (op == PIXMAN_OPERATOR_CLEAR)
00308        color_s.red = color_s.green = color_s.blue = color_s.alpha = 0;
00309 
00310     if (op == PIXMAN_OPERATOR_SRC || op == PIXMAN_OPERATOR_CLEAR)
00311     {
00312       /* We cast away the constness of rects here, because pixman_color_rects
00313         temporarily modifies it */
00314        pixman_color_rects (dst, dst, &color_s, nRects, (pixman_rectangle_t *)rects, 0, 0);
00315        if (dst->alphaMap)
00316            pixman_color_rects (dst->alphaMap, dst,
00317                        &color_s, nRects, (pixman_rectangle_t *)rects,
00318                        dst->alphaOrigin.x,
00319                        dst->alphaOrigin.y);
00320     }
00321     else
00322     {
00323        pixman_format_t      rgbaFormat;
00324        FbPixels      *pixels;
00325        pixman_image_t              *src;
00326        pixman_bits_t        pixel;
00327 
00328        pixman_format_init (&rgbaFormat, PICT_a8r8g8b8);
00329        
00330        pixels = FbPixelsCreate (1, 1, rgbaFormat.depth);
00331        if (!pixels)
00332            goto bail1;
00333        
00334        pixman_color_to_pixel (&rgbaFormat, &color_s, &pixel);
00335 
00336        /* XXX: Originally, fb had the following:
00337 
00338           (*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &one);
00339 
00340           I haven't checked to see what I might be breaking with a
00341           trivial assignment instead.
00342        */
00343        pixels->data[0] = pixel;
00344 
00345        src = pixman_image_createForPixels (pixels, &rgbaFormat);
00346        if (!src)
00347            goto bail2;
00348 
00349        pixman_image_set_repeat (src, 1);
00350 
00351        while (nRects--)
00352        {
00353            pixman_composite (op, src, NULL, dst, 0, 0, 0, 0, 
00354                       rects->x,
00355                       rects->y,
00356                       rects->width,
00357                       rects->height);
00358            rects++;
00359        }
00360 
00361        pixman_image_destroy (src);
00362 bail2:
00363        FbPixelsDestroy (pixels);
00364 bail1:
00365        ;
00366     }
00367 }
00368 slim_hidden_def(pixman_fill_rectangles);