Back to index

lightning-sunbird  0.9+nobinonly
fbedge.c
Go to the documentation of this file.
00001 /*
00002  * $Id: fbedge.c,v 1.3.4.1 2005/09/27 23:09:03 vladimir%pobox.com Exp $
00003  *
00004  * Copyright © 2004 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 <string.h>
00026 #include "pixman-xserver-compat.h"
00027 
00028 #ifdef RENDER
00029 
00030 /*
00031  * 4 bit alpha
00032  */
00033 
00034 #define N_BITS       4
00035 #define rasterizeEdges      fbRasterizeEdges4
00036 
00037 #if BITMAP_BIT_ORDER == LSBFirst
00038 #define Shift4(o)    ((o) << 2)
00039 #else
00040 #define Shift4(o)    ((1-(o)) << 2)
00041 #endif
00042 
00043 #define Get4(x,o)    (((x) >> Shift4(o)) & 0xf)
00044 #define Put4(x,o,v)  (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o)))
00045 
00046 #define DefineAlpha(line,x) \
00047     CARD8   *__ap = (CARD8 *) line + ((x) >> 1); \
00048     int           __ao = (x) & 1
00049 
00050 #define StepAlpha    ((__ap += __ao), (__ao ^= 1))
00051 
00052 #define AddAlpha(a) {                                          \
00053     CARD8   __o = *__ap;                                \
00054     CARD8   __a = (a) + Get4(__o, __ao);                \
00055     *__ap = Put4 (__o, __ao, __a | (0 - ((__a) >> 4)));        \
00056 }
00057 
00058 #include "fbedgeimp.h"
00059 
00060 #undef AddAlpha
00061 #undef StepAlpha
00062 #undef DefineAlpha
00063 #undef rasterizeEdges
00064 #undef N_BITS
00065 
00066 
00067 /*
00068  * 1 bit alpha
00069  */
00070 
00071 #define N_BITS 1
00072 #define rasterizeEdges      fbRasterizeEdges1
00073 
00074 #include "fbedgeimp.h"
00075 
00076 #undef rasterizeEdges
00077 #undef N_BITS
00078 
00079 /*
00080  * 8 bit alpha
00081  */
00082 
00083 static INLINE CARD8
00084 clip255 (int x)
00085 {
00086     if (x > 255) return 255;
00087     return x;
00088 }
00089 
00090 static INLINE void
00091 add_saturate_8 (CARD8 *buf, int value, int length)
00092 {
00093     while (length--)
00094     {
00095         *buf = clip255 (*buf + value);
00096         buf++;
00097     }
00098 }
00099 
00100 /*
00101  * We want to detect the case where we add the same value to a long
00102  * span of pixels.  The triangles on the end are filled in while we
00103  * count how many sub-pixel scanlines contribute to the middle section.
00104  *
00105  *                 +--------------------------+
00106  *  fill_height =|   \                      /
00107  *                     +------------------+
00108  *                      |================|
00109  *                   fill_start       fill_end
00110  */
00111 static void
00112 fbRasterizeEdges8 (FbBits   *buf,
00113                  int        width,
00114                  int        stride,
00115                  RenderEdge *l,
00116                  RenderEdge *r,
00117                  xFixed     t,
00118                  xFixed     b)
00119 {
00120     xFixed  y = t;
00121     FbBits  *line;
00122     int fill_start = -1, fill_end = -1;
00123     int fill_size = 0;
00124 
00125     line = buf + xFixedToInt (y) * stride;
00126 
00127     for (;;)
00128     {
00129         CARD8 *ap = (CARD8 *) line;
00130        xFixed lx, rx;
00131        int    lxi, rxi;
00132        
00133        /* clip X */
00134        lx = l->x;
00135        if (lx < 0)
00136            lx = 0;
00137        rx = r->x;
00138        if (xFixedToInt (rx) >= width)
00139            rx = IntToxFixed (width);
00140        
00141        /* Skip empty (or backwards) sections */
00142        if (rx > lx)
00143        {
00144             int lxs, rxs;
00145 
00146            /* Find pixel bounds for span. */
00147            lxi = xFixedToInt (lx);
00148            rxi = xFixedToInt (rx);
00149 
00150             /* Sample coverage for edge pixels */
00151             lxs = RenderSamplesX (lx, 8);
00152             rxs = RenderSamplesX (rx, 8);
00153 
00154             /* Add coverage across row */
00155             if (lxi == rxi)
00156             {
00157                 ap[lxi] = clip255 (ap[lxi] + rxs - lxs);
00158             }
00159             else
00160             {
00161                 ap[lxi] = clip255 (ap[lxi] + N_X_FRAC(8) - lxs);
00162 
00163                 /* Move forward so that lxi/rxi is the pixel span */
00164                 lxi++;
00165 
00166                 /* Don't bother trying to optimize the fill unless
00167                  * the span is longer than 4 pixels. */
00168                 if (rxi - lxi > 4)
00169                 {
00170                     if (fill_start < 0)
00171                     {
00172                         fill_start = lxi;
00173                         fill_end = rxi;
00174                         fill_size++;
00175                     }
00176                     else
00177                     {
00178                         if (lxi >= fill_end || rxi < fill_start)
00179                         {
00180                             /* We're beyond what we saved, just fill it */
00181                             add_saturate_8 (ap + fill_start,
00182                                             fill_size * N_X_FRAC(8),
00183                                             fill_end - fill_start);
00184                             fill_start = lxi;
00185                             fill_end = rxi;
00186                             fill_size = 1;
00187                         }
00188                         else
00189                         {
00190                             /* Update fill_start */
00191                             if (lxi > fill_start)
00192                             {
00193                                 add_saturate_8 (ap + fill_start,
00194                                                 fill_size * N_X_FRAC(8),
00195                                                 lxi - fill_start);
00196                                 fill_start = lxi;
00197                             }
00198                             else if (lxi < fill_start)
00199                             {
00200                                 add_saturate_8 (ap + lxi, N_X_FRAC(8),
00201                                                 fill_start - lxi);
00202                             }
00203 
00204                             /* Update fill_end */
00205                             if (rxi < fill_end)
00206                             {
00207                                 add_saturate_8 (ap + rxi,
00208                                                 fill_size * N_X_FRAC(8),
00209                                                 fill_end - rxi);
00210                                 fill_end = rxi;
00211                             }
00212                             else if (fill_end < rxi)
00213                             {
00214                                 add_saturate_8 (ap + fill_end,
00215                                                 N_X_FRAC(8),
00216                                                 rxi - fill_end);
00217                             }
00218                             fill_size++;
00219                         }
00220                     }
00221                 }
00222                 else
00223                 {
00224                     add_saturate_8 (ap + lxi, N_X_FRAC(8), rxi - lxi);
00225                 }
00226 
00227                 /* Do not add in a 0 alpha here. This check is
00228                  * necessary to avoid a buffer overrun, (when rx
00229                  * is exactly on a pixel boundary). */
00230                 if (rxs)
00231                     ap[rxi] = clip255 (ap[rxi] + rxs);
00232             }
00233        }
00234 
00235        if (y == b) {
00236             /* We're done, make sure we clean up any remaining fill. */
00237             if (fill_start != fill_end) {
00238                 if (fill_size == N_Y_FRAC(8))
00239                 {
00240                     memset (ap + fill_start, 0xff, fill_end - fill_start);
00241                 }
00242                 else
00243                 {
00244                     add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8),
00245                                     fill_end - fill_start);
00246                 }
00247             }
00248            break;
00249         }
00250 
00251        if (xFixedFrac (y) != Y_FRAC_LAST(8))
00252        {
00253            RenderEdgeStepSmall (l);
00254            RenderEdgeStepSmall (r);
00255            y += STEP_Y_SMALL(8);
00256        }
00257        else
00258        {
00259            RenderEdgeStepBig (l);
00260            RenderEdgeStepBig (r);
00261            y += STEP_Y_BIG(8);
00262             if (fill_start != fill_end)
00263             {
00264                 if (fill_size == N_Y_FRAC(8))
00265                 {
00266                     memset (ap + fill_start, 0xff, fill_end - fill_start);
00267                 }
00268                 else
00269                 {
00270                     add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8),
00271                                     fill_end - fill_start);
00272                 }
00273                 fill_start = fill_end = -1;
00274                 fill_size = 0;
00275             }
00276            line += stride;
00277        }
00278     }
00279 }
00280 
00281 void
00282 fbRasterizeEdges (FbBits    *buf,
00283                 int         bpp,
00284                 int         width,
00285                 int         stride,
00286                 RenderEdge  *l,
00287                 RenderEdge  *r,
00288                 xFixed      t,
00289                 xFixed      b)
00290 {
00291     switch (bpp) {
00292     case 1:
00293        fbRasterizeEdges1 (buf, width, stride, l, r, t, b);
00294        break;
00295     case 4:
00296        fbRasterizeEdges4 (buf, width, stride, l, r, t, b);
00297        break;
00298     case 8:
00299        fbRasterizeEdges8 (buf, width, stride, l, r, t, b);
00300        break;
00301     }
00302 }
00303 
00304 #endif /* RENDER */