Back to index

lightning-sunbird  0.9+nobinonly
icbltone.c
Go to the documentation of this file.
00001 /*
00002  * Id: $
00003  *
00004  * Copyright © 1998 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 "pixman-xserver-compat.h"
00026 
00027 /*
00028  *  Example: srcX = 13 dstX = 8    (FB unit 32 dstBpp 8)
00029  *
00030  *     **** **** **** **** **** **** **** ****
00031  *                   ^
00032  *     ********  ********  ********  ********
00033  *              ^
00034  *  leftShift = 12
00035  *  rightShift = 20
00036  *
00037  *  Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8)
00038  *
00039  *     **** **** **** **** **** **** **** ****
00040  *     ^             
00041  *     ********  ********  ********  ********
00042  *              ^
00043  *
00044  *  leftShift = 24
00045  *  rightShift = 8
00046  */
00047 
00048 #define LoadBits {\
00049     if (leftShift) { \
00050        bitsRight = *src++; \
00051        bits = (FbStipLeft (bitsLeft, leftShift) | \
00052               FbStipRight(bitsRight, rightShift)); \
00053        bitsLeft = bitsRight; \
00054     } else \
00055        bits = *src++; \
00056 }
00057     
00058 #ifndef FBNOPIXADDR
00059     
00060 #define LaneCases1(n,a)         case n: (void)FbLaneCase(n,a); break
00061 #define LaneCases2(n,a)         LaneCases1(n,a); LaneCases1(n+1,a)
00062 #define LaneCases4(n,a)         LaneCases2(n,a); LaneCases2(n+2,a)
00063 #define LaneCases8(n,a)         LaneCases4(n,a); LaneCases4(n+4,a)
00064 #define LaneCases16(n,a)    LaneCases8(n,a); LaneCases8(n+8,a)
00065 #define LaneCases32(n,a)    LaneCases16(n,a); LaneCases16(n+16,a)
00066 #define LaneCases64(n,a)    LaneCases32(n,a); LaneCases32(n+32,a)
00067 #define LaneCases128(n,a)   LaneCases64(n,a); LaneCases64(n+64,a)
00068 #define LaneCases256(n,a)   LaneCases128(n,a); LaneCases128(n+128,a)
00069     
00070 #if FB_SHIFT == 6
00071 #define LaneCases(a)     LaneCases256(0,a)
00072 #endif
00073     
00074 #if FB_SHIFT == 5
00075 #define LaneCases(a)     LaneCases16(0,a)
00076 #endif
00077                                                     
00078 #if FB_SHIFT == 6
00079 static uint8_t const fb8Lane[256] = {
00080 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
00081 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
00082 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
00083 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
00084 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
00085 98, 99, 100, 101, 102,103,104,105,106,107,108,109,110,111,112,113,114,115,
00086 116, 117, 118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,
00087 134, 135, 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,
00088 152, 153, 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,
00089 170, 171, 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,
00090 188, 189, 190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,
00091 206, 207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
00092 224, 225, 226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,
00093 242, 243, 244,245,246,247,248,249,250,251,252,253,254,255,
00094 };
00095 
00096 static uint8_t const fb16Lane[256] = {
00097     0x00, 0x03, 0x0c, 0x0f,
00098     0x30, 0x33, 0x3c, 0x3f,
00099     0xc0, 0xc3, 0xcc, 0xcf,
00100     0xf0, 0xf3, 0xfc, 0xff,
00101 };
00102 
00103 static uint8_t const fb32Lane[16] = {
00104     0x00, 0x0f, 0xf0, 0xff,
00105 };
00106 #endif
00107 
00108 #if FB_SHIFT == 5
00109 static uint8_t const fb8Lane[16] = {
00110     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
00111 };
00112 
00113 static uint8_t const fb16Lane[16] = {
00114     0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
00115 };
00116 
00117 static uint8_t const fb32Lane[16] = {
00118     0, 15,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00119 };
00120 #endif
00121 
00122 static const uint8_t *
00123 fbLaneTable(int bpp)
00124 {
00125     switch (bpp) {
00126     case 8:
00127        return fb8Lane;
00128     case 16:
00129        return fb16Lane;
00130     case 32:
00131        return fb32Lane;
00132     }
00133     return NULL;
00134 }
00135 #endif
00136 
00137 void
00138 fbBltOne (FbStip    *src,
00139          FbStride  srcStride,          /* FbStip units per scanline */
00140          int      srcX,         /* bit position of source */
00141          FbBits    *dst,
00142          FbStride  dstStride,          /* FbBits units per scanline */
00143          int      dstX,         /* bit position of dest */
00144          int      dstBpp,       /* bits per destination unit */
00145 
00146          int      width,        /* width in bits of destination */
00147          int      height,       /* height in scanlines */
00148 
00149          FbBits    fgand,       /* rrop values */
00150          FbBits    fgxor,
00151          FbBits    bgand,
00152          FbBits    bgxor)
00153 {
00154     const FbBits    *fbBits;
00155     int                  pixelsPerDst;           /* dst pixels per FbBits */
00156     int                  unitsPerSrc;            /* src patterns per FbStip */
00157     int                  leftShift, rightShift;  /* align source with dest */
00158     FbBits        startmask, endmask;            /* dest scanline masks */
00159     FbStip        bits=0, bitsLeft, bitsRight;/* source bits */
00160     FbStip        left;
00161     FbBits        mask;
00162     int                  nDst;                   /* dest longwords (w.o. end) */
00163     int                  w;
00164     int                  n, nmiddle;
00165     int                  dstS;                   /* stipple-relative dst X coordinate */
00166     Bool          copy;                   /* accelerate dest-invariant */
00167     Bool          transparent;            /* accelerate 0 nop */
00168     int                  srcinc;                 /* source units consumed */
00169     Bool          endNeedsLoad = FALSE;   /* need load for endmask */
00170 #ifndef FBNOPIXADDR
00171     const CARD8          *fbLane;
00172 #endif
00173     int                  startbyte, endbyte;
00174 
00175 #ifdef FB_24BIT
00176     if (dstBpp == 24)
00177     {
00178        fbBltOne24 (src, srcStride, srcX,
00179                   dst, dstStride, dstX, dstBpp,
00180                   width, height,
00181                   fgand, fgxor, bgand, bgxor);
00182        return;
00183     }
00184 #endif
00185     
00186     /*
00187      * Number of destination units in FbBits == number of stipple pixels
00188      * used each time
00189      */
00190     pixelsPerDst = FB_UNIT / dstBpp;
00191 
00192     /*
00193      * Number of source stipple patterns in FbStip 
00194      */
00195     unitsPerSrc = FB_STIP_UNIT / pixelsPerDst;
00196     
00197     copy = FALSE;
00198     transparent = FALSE;
00199     if (bgand == 0 && fgand == 0)
00200        copy = TRUE;
00201     else if (bgand == FB_ALLONES && bgxor == 0)
00202        transparent = TRUE;
00203 
00204     /*
00205      * Adjust source and dest to nearest FbBits boundary
00206      */
00207     src += srcX >> FB_STIP_SHIFT;
00208     dst += dstX >> FB_SHIFT;
00209     srcX &= FB_STIP_MASK;
00210     dstX &= FB_MASK;
00211 
00212     FbMaskBitsBytes(dstX, width, copy, 
00213                   startmask, startbyte, nmiddle, endmask, endbyte);
00214 
00215     /*
00216      * Compute effective dest alignment requirement for
00217      * source -- must align source to dest unit boundary
00218      */
00219     dstS = dstX / dstBpp;
00220     /*
00221      * Compute shift constants for effective alignement
00222      */
00223     if (srcX >= dstS)
00224     {
00225        leftShift = srcX - dstS;
00226        rightShift = FB_STIP_UNIT - leftShift;
00227     }
00228     else
00229     {
00230        rightShift = dstS - srcX;
00231        leftShift = FB_STIP_UNIT - rightShift;
00232     }
00233     /*
00234      * Get pointer to stipple mask array for this depth
00235      */
00236     fbBits = NULL;   /* unused */
00237     if (pixelsPerDst <= 8)
00238        fbBits = fbStippleTable(pixelsPerDst);
00239 #ifndef FBNOPIXADDR
00240     fbLane = NULL;
00241     if (transparent && fgand == 0 && dstBpp >= 8)
00242        fbLane = fbLaneTable(dstBpp);
00243 #endif
00244     
00245     /*
00246      * Compute total number of destination words written, but 
00247      * don't count endmask 
00248      */
00249     nDst = nmiddle;
00250     if (startmask)
00251        nDst++;
00252     
00253     dstStride -= nDst;
00254 
00255     /*
00256      * Compute total number of source words consumed
00257      */
00258     
00259     srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc;
00260     
00261     if (srcX > dstS)
00262        srcinc++;
00263     if (endmask)
00264     {
00265        endNeedsLoad = nDst % unitsPerSrc == 0;
00266        if (endNeedsLoad)
00267            srcinc++;
00268     }
00269 
00270     srcStride -= srcinc;
00271     
00272     /*
00273      * Copy rectangle
00274      */
00275     while (height--)
00276     {
00277        w = nDst;         /* total units across scanline */
00278        n = unitsPerSrc;    /* units avail in single stipple */
00279        if (n > w)
00280            n = w;
00281        
00282        bitsLeft = 0;
00283        if (srcX > dstS)
00284            bitsLeft = *src++;
00285        if (n)
00286        {
00287            /*
00288             * Load first set of stipple bits
00289             */
00290            LoadBits;
00291 
00292            /*
00293             * Consume stipple bits for startmask
00294             */
00295            if (startmask)
00296            {
00297 #if FB_UNIT > 32
00298               if (pixelsPerDst == 16)
00299                   mask = FbStipple16Bits(FbLeftStipBits(bits,16));
00300               else
00301 #endif
00302                   mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
00303 #ifndef FBNOPIXADDR         
00304               if (fbLane)
00305               {
00306                   fbTransparentSpan (dst, mask & startmask, fgxor, 1);
00307               }
00308               else
00309 #endif
00310               {
00311                   if (mask || !transparent)
00312                      FbDoLeftMaskByteStippleRRop (dst, mask,
00313                                                fgand, fgxor, bgand, bgxor,
00314                                                startbyte, startmask);
00315               }
00316               bits = FbStipLeft (bits, pixelsPerDst);
00317               dst++;
00318               n--;
00319               w--;
00320            }
00321            /*
00322             * Consume stipple bits across scanline
00323             */
00324            for (;;)
00325            {
00326               w -= n;
00327               if (copy)
00328               {
00329                   while (n--)
00330                   {
00331 #if FB_UNIT > 32
00332                      if (pixelsPerDst == 16)
00333                          mask = FbStipple16Bits(FbLeftStipBits(bits,16));
00334                      else
00335 #endif
00336                          mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
00337                      *dst = FbOpaqueStipple (mask, fgxor, bgxor);
00338                      dst++;
00339                      bits = FbStipLeft(bits, pixelsPerDst);
00340                   }
00341               }
00342               else
00343               {
00344 #ifndef FBNOPIXADDR
00345                   if (fbLane)
00346                   {
00347                      while (bits && n)
00348                      {
00349                          switch (fbLane[FbLeftStipBits(bits,pixelsPerDst)]) {
00350                             LaneCases((CARD8 *) dst);
00351                          }
00352                          bits = FbStipLeft(bits,pixelsPerDst);
00353                          dst++;
00354                          n--;
00355                      }
00356                      dst += n;
00357                   }
00358                   else
00359 #endif
00360                   {
00361                      while (n--)
00362                      {
00363                          left = FbLeftStipBits(bits,pixelsPerDst);
00364                          if (left || !transparent)
00365                          {
00366                             mask = fbBits[left];
00367                             *dst = FbStippleRRop (*dst, mask,
00368                                                 fgand, fgxor, bgand, bgxor);
00369                          }
00370                          dst++;
00371                          bits = FbStipLeft(bits, pixelsPerDst);
00372                      }
00373                   }
00374               }
00375               if (!w)
00376                   break;
00377               /*
00378                * Load another set and reset number of available units
00379                */
00380               LoadBits;
00381               n = unitsPerSrc;
00382               if (n > w)
00383                   n = w;
00384            }
00385        }
00386        /*
00387         * Consume stipple bits for endmask
00388         */
00389        if (endmask)
00390        {
00391            if (endNeedsLoad)
00392            {
00393               LoadBits;
00394            }
00395 #if FB_UNIT > 32
00396            if (pixelsPerDst == 16)
00397               mask = FbStipple16Bits(FbLeftStipBits(bits,16));
00398            else
00399 #endif
00400               mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
00401 #ifndef FBNOPIXADDR
00402            if (fbLane)
00403            {
00404               fbTransparentSpan (dst, mask & endmask, fgxor, 1);
00405            }
00406            else
00407 #endif
00408            {
00409               if (mask || !transparent)
00410                   FbDoRightMaskByteStippleRRop (dst, mask, 
00411                                             fgand, fgxor, bgand, bgxor,
00412                                             endbyte, endmask);
00413            }
00414        }
00415        dst += dstStride;
00416        src += srcStride;
00417     }
00418 }
00419 
00420 #ifdef FB_24BIT
00421 
00422 /*
00423  * Crufty macros to initialize the mask array, most of this
00424  * is to avoid compile-time warnings about shift overflow
00425  */
00426 
00427 #if BITMAP_BIT_ORDER == MSBFirst
00428 #define Mask24Pos(x,r) ((x)*24-(r))
00429 #else
00430 #define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0))
00431 #endif
00432 
00433 #define Mask24Neg(x,r)      (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0)
00434 #define Mask24Check(x,r)    (Mask24Pos(x,r) < 0 ? 0 : \
00435                           Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r))
00436 
00437 #define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \
00438                    (Mask24Pos(x,r) < 0 ? \
00439                     0xffffff >> Mask24Neg (x,r) : \
00440                     0xffffff << Mask24Check(x,r)) : 0)
00441 
00442 #define SelMask24(b,n,r)    ((((b) >> n) & 1) * Mask24(n,r))
00443 
00444 /*
00445  * Untested for MSBFirst or FB_UNIT == 32
00446  */
00447 
00448 #if FB_UNIT == 64
00449 #define C4_24(b,r) \
00450     (SelMask24(b,0,r) | \
00451      SelMask24(b,1,r) | \
00452      SelMask24(b,2,r) | \
00453      SelMask24(b,3,r))
00454 
00455 #define FbStip24New(rot)    (2 + (rot != 0))
00456 #define FbStip24Len      4
00457 
00458 static const FbBits fbStipple24Bits[3][1 << FbStip24Len] = {
00459     /* rotate 0 */
00460     {
00461        C4_24( 0, 0), C4_24( 1, 0), C4_24( 2, 0), C4_24( 3, 0),
00462        C4_24( 4, 0), C4_24( 5, 0), C4_24( 6, 0), C4_24( 7, 0),
00463        C4_24( 8, 0), C4_24( 9, 0), C4_24(10, 0), C4_24(11, 0),
00464        C4_24(12, 0), C4_24(13, 0), C4_24(14, 0), C4_24(15, 0),
00465     },
00466     /* rotate 8 */
00467     {
00468        C4_24( 0, 8), C4_24( 1, 8), C4_24( 2, 8), C4_24( 3, 8),
00469        C4_24( 4, 8), C4_24( 5, 8), C4_24( 6, 8), C4_24( 7, 8),
00470        C4_24( 8, 8), C4_24( 9, 8), C4_24(10, 8), C4_24(11, 8),
00471        C4_24(12, 8), C4_24(13, 8), C4_24(14, 8), C4_24(15, 8),
00472     },
00473     /* rotate 16 */
00474     {
00475        C4_24( 0,16), C4_24( 1,16), C4_24( 2,16), C4_24( 3,16),
00476        C4_24( 4,16), C4_24( 5,16), C4_24( 6,16), C4_24( 7,16),
00477        C4_24( 8,16), C4_24( 9,16), C4_24(10,16), C4_24(11,16),
00478        C4_24(12,16), C4_24(13,16), C4_24(14,16), C4_24(15,16),
00479     }
00480 };
00481 
00482 #endif
00483 
00484 #if FB_UNIT == 32
00485 #define C2_24(b,r)  \
00486     (SelMask24(b,0,r) | \
00487      SelMask24(b,1,r))
00488 
00489 #define FbStip24Len      2
00490 #if BITMAP_BIT_ORDER == MSBFirst
00491 #define FbStip24New(rot)    (1 + (rot == 0))
00492 #else
00493 #define FbStip24New(rot)    (1 + (rot == 8))
00494 #endif
00495 
00496 static const FbBits fbStipple24Bits[3][1 << FbStip24Len] = {
00497     /* rotate 0 */
00498     {
00499        C2_24( 0, 0), C2_24 ( 1, 0), C2_24 ( 2, 0), C2_24 ( 3, 0),
00500     },
00501     /* rotate 8 */
00502     {
00503        C2_24( 0, 8), C2_24 ( 1, 8), C2_24 ( 2, 8), C2_24 ( 3, 8),
00504     },
00505     /* rotate 16 */
00506     {
00507        C2_24( 0,16), C2_24 ( 1,16), C2_24 ( 2,16), C2_24 ( 3,16),
00508     }
00509 };
00510 #endif
00511 
00512 #if BITMAP_BIT_ORDER == LSBFirst
00513 
00514 #define FbMergeStip24Bits(left, right, new) \
00515        (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new))))
00516 
00517 #define FbMergePartStip24Bits(left, right, llen, rlen) \
00518        (left | FbStipRight(right, llen))
00519 
00520 #else
00521 
00522 #define FbMergeStip24Bits(left, right, new) \
00523        ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right)
00524 
00525 #define FbMergePartStip24Bits(left, right, llen, rlen) \
00526        (FbStipLeft(left, rlen) | right)
00527 
00528 #endif
00529 
00530 #define fbFirstStipBits(len,stip) {\
00531     int       __len = (len); \
00532     if (len <= remain) { \
00533        stip = FbLeftStipBits(bits, len); \
00534     } else { \
00535        stip = FbLeftStipBits(bits, remain); \
00536        bits = *src++; \
00537        __len = (len) - remain; \
00538        stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \
00539                                  remain, __len); \
00540        remain = FB_STIP_UNIT; \
00541     } \
00542     bits = FbStipLeft (bits, __len); \
00543     remain -= __len; \
00544 }
00545 
00546 #define fbInitStipBits(offset,len,stip) {\
00547     bits = FbStipLeft (*src++,offset); \
00548     remain = FB_STIP_UNIT - offset; \
00549     fbFirstStipBits(len,stip); \
00550     stip = FbMergeStip24Bits (0, stip, len); \
00551 }
00552     
00553 #define fbNextStipBits(rot,stip) {\
00554     int           __new = FbStip24New(rot); \
00555     FbStip  __right; \
00556     fbFirstStipBits(__new, __right); \
00557     stip = FbMergeStip24Bits (stip, __right, __new); \
00558     rot = FbNext24Rot (rot); \
00559 }
00560 
00561 /*
00562  * Use deep mask tables that incorporate rotation, pull
00563  * a variable number of bits out of the stipple and
00564  * reuse the right bits as needed for the next write
00565  *
00566  * Yes, this is probably too much code, but most 24-bpp screens
00567  * have no acceleration so this code is used for stipples, copyplane
00568  * and text
00569  */
00570 void
00571 fbBltOne24 (FbStip   *srcLine,
00572            FbStride  srcStride,  /* FbStip units per scanline */
00573            int              srcX,      /* bit position of source */
00574            FbBits    *dst,
00575            FbStride  dstStride,  /* FbBits units per scanline */
00576            int              dstX,      /* bit position of dest */
00577            int              dstBpp,           /* bits per destination unit */
00578 
00579            int              width,     /* width in bits of destination */
00580            int              height,           /* height in scanlines */
00581 
00582            FbBits    fgand,     /* rrop values */
00583            FbBits    fgxor,
00584            FbBits    bgand,
00585            FbBits    bgxor)
00586 {
00587     FbStip    *src;
00588     FbBits    leftMask, rightMask, mask;
00589     int              nlMiddle, nl;
00590     FbStip    stip, bits;
00591     int              remain;
00592     int              dstS;
00593     int              firstlen;
00594     int              rot0, rot;
00595     int              nDst;
00596     
00597     srcLine += srcX >> FB_STIP_SHIFT;
00598     dst += dstX >> FB_SHIFT;
00599     srcX &= FB_STIP_MASK;
00600     dstX &= FB_MASK;
00601     rot0 = FbFirst24Rot (dstX);
00602     
00603     FbMaskBits (dstX, width, leftMask, nlMiddle, rightMask);
00604     
00605     dstS = (dstX + 23) / 24;
00606     firstlen = FbStip24Len - dstS;
00607     
00608     nDst = nlMiddle;
00609     if (leftMask)
00610        nDst++;
00611     dstStride -= nDst;
00612     
00613     /* opaque copy */
00614     if (bgand == 0 && fgand == 0)
00615     {
00616        while (height--)
00617        {
00618            rot = rot0;
00619            src = srcLine;
00620            srcLine += srcStride;
00621            fbInitStipBits (srcX,firstlen, stip);
00622            if (leftMask)
00623            {
00624               mask = fbStipple24Bits[rot >> 3][stip];
00625               *dst = (*dst & ~leftMask) | (FbOpaqueStipple (mask,
00626                                                        FbRot24(fgxor, rot),
00627                                                        FbRot24(bgxor, rot))
00628                                         & leftMask);
00629               dst++;
00630               fbNextStipBits(rot,stip);
00631            }
00632            nl = nlMiddle;
00633            while (nl--)
00634            {
00635               mask = fbStipple24Bits[rot>>3][stip];
00636               *dst = FbOpaqueStipple (mask, 
00637                                    FbRot24(fgxor, rot),
00638                                    FbRot24(bgxor, rot));
00639               dst++;
00640               fbNextStipBits(rot,stip);
00641            }
00642            if (rightMask)
00643            {
00644               mask = fbStipple24Bits[rot >> 3][stip];
00645               *dst = (*dst & ~rightMask) | (FbOpaqueStipple (mask,
00646                                                         FbRot24(fgxor, rot),
00647                                                         FbRot24(bgxor, rot))
00648                                          & rightMask);
00649            }
00650            dst += dstStride;
00651            src += srcStride;
00652        }
00653     }
00654     /* transparent copy */
00655     else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0)
00656     {
00657        while (height--)
00658        {
00659            rot = rot0;
00660            src = srcLine;
00661            srcLine += srcStride;
00662            fbInitStipBits (srcX, firstlen, stip);
00663            if (leftMask)
00664            {
00665               if (stip)
00666               {
00667                   mask = fbStipple24Bits[rot >> 3][stip] & leftMask;
00668                   *dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask);
00669               }
00670               dst++;
00671               fbNextStipBits (rot, stip);
00672            }
00673            nl = nlMiddle;
00674            while (nl--)
00675            {
00676               if (stip)
00677               {
00678                   mask = fbStipple24Bits[rot>>3][stip];
00679                   *dst = (*dst & ~mask) | (FbRot24(fgxor,rot) & mask);
00680               }
00681               dst++;
00682               fbNextStipBits (rot, stip);
00683            }
00684            if (rightMask)
00685            {
00686               if (stip)
00687               {
00688                   mask = fbStipple24Bits[rot >> 3][stip] & rightMask;
00689                   *dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask);
00690               }
00691            }
00692            dst += dstStride;
00693        }
00694     }
00695     else
00696     {
00697        while (height--)
00698        {
00699            rot = rot0;
00700            src = srcLine;
00701            srcLine += srcStride;
00702            fbInitStipBits (srcX, firstlen, stip);
00703            if (leftMask)
00704            {
00705               mask = fbStipple24Bits[rot >> 3][stip];
00706               *dst = FbStippleRRopMask (*dst, mask,
00707                                      FbRot24(fgand, rot),
00708                                      FbRot24(fgxor, rot),
00709                                      FbRot24(bgand, rot),
00710                                      FbRot24(bgxor, rot),
00711                                      leftMask);
00712               dst++;
00713               fbNextStipBits(rot,stip);
00714            }
00715            nl = nlMiddle;
00716            while (nl--)
00717            {
00718               mask = fbStipple24Bits[rot >> 3][stip];
00719               *dst = FbStippleRRop (*dst, mask,
00720                                   FbRot24(fgand, rot),
00721                                   FbRot24(fgxor, rot),
00722                                   FbRot24(bgand, rot),
00723                                   FbRot24(bgxor, rot));
00724               dst++;
00725               fbNextStipBits(rot,stip);
00726            }
00727            if (rightMask)
00728            {
00729               mask = fbStipple24Bits[rot >> 3][stip];
00730               *dst = FbStippleRRopMask (*dst, mask,
00731                                      FbRot24(fgand, rot),
00732                                      FbRot24(fgxor, rot),
00733                                      FbRot24(bgand, rot),
00734                                      FbRot24(bgxor, rot),
00735                                      rightMask);
00736            }
00737            dst += dstStride;
00738        }
00739     }
00740 }
00741 #endif
00742