home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / dec / qdss / qdspans.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-19  |  18.9 KB  |  684 lines

  1. /***********************************************************
  2. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. extern int PixmapUseOffscreen;
  26. #include "scrnintstr.h"
  27.  
  28. #include "pixmapstr.h"
  29.  
  30. #include <sys/types.h>
  31.  
  32. #include "X.h"
  33. #include "windowstr.h"
  34. #include "regionstr.h"
  35. #include "gcstruct.h"
  36. #include "dixstruct.h"
  37.  
  38. #include "Xproto.h"
  39. #include "Xprotostr.h"
  40. #include "mi.h"
  41. #include "Xmd.h"
  42. #include "servermd.h"
  43.  
  44. /*
  45.  * driver headers
  46.  */
  47. #include "Ultrix2.0inc.h"
  48. #include <vaxuba/qduser.h>
  49. #include <vaxuba/qdioctl.h>
  50. #include <vaxuba/qdreg.h>
  51.  
  52. #include "qd.h"
  53. #include "qdgc.h"
  54.  
  55. #include "qdprocs.h"
  56.  
  57. /*
  58.  * used as procedure vector when drawable is an undrawable window
  59.  */
  60. void
  61. qdFSUndrawable()
  62. {
  63. }
  64.  
  65. #define    PIXDEPTH(x)    ((x->drawable).depth)
  66. /* ZCOPY - XXX replaced by does-everything function qddopixel! */
  67. #if NPLANES==24
  68. # define ZCOPY(s,d,sw,dw) \
  69.        {*((unsigned char *) d) = *((unsigned char *) s); \
  70.     *(((unsigned char *) d)+dw) = *(((unsigned char *) s)+sw); \
  71.     *(((unsigned char *) d)+2*(dw)) = *(((unsigned char *) s)+2*(sw));}
  72. #else    /* NPLANES == 8 */
  73. # define ZCOPY(s,d,sw,dw) \
  74.        {*((unsigned char *) d) = *((unsigned char *) s);}
  75. #endif
  76.  
  77. #if NPLANES==24
  78. #define DOPIXEL(psrc, dst, pGC, delta) qddopixel(psrc, dst, pGC, delta)
  79. #else
  80. #define DOPIXEL(psrc, dst, pGC, delta) qddopixel(psrc, dst, pGC)
  81. #endif
  82.  
  83.  
  84. #define u_char    unsigned char
  85.  
  86. /*
  87.  * GetSpans -- for each span, gets bits from drawable starting at ppt[i]
  88.  * and continuing for pwidth[i] bits
  89.  * Each scanline returned will be server scanline padded, i.e., it will come
  90.  * out to an integral number of longwords.
  91.  */
  92. /*
  93.  * Currently, the caller does an Xfree of the returned value.
  94.  *
  95.  * If Drawable is the screen
  96.  *    hand the bytes back a pixel at a time.
  97.  * If Drawable is a pixmap
  98.  *    hand the bytes back a pixel at a time.
  99.  */
  100.  
  101. extern    int Nentries;
  102. extern    int Nplanes;
  103. #if NPLANES==24
  104. extern    int Nchannels;
  105. #else
  106. #define Nchannels 1
  107. #endif
  108. extern unsigned int Allplanes;
  109.  
  110. /*
  111.  * In R4, we change the interface slightly for GetSpans when pDrawable
  112.  * is a Pixmap: pDrawable->{x,y} must have been pre-addes to the ppt
  113.  * coordinates. For off-screen Pixmaps, this means they have absolute
  114.  * GPX-relative coordinates, which is what we want anyway.
  115.  * This convention is useful, because the mi routines usually add
  116.  * in pDrawable->{x,y} before calling GetSpans. The exception is
  117.  * miPushPixels (since it "knows" that the mask is a Bitmap); we have
  118.  * to be sure it is only called when mask->drawable->{x,y} are both 0.
  119.  */
  120.  
  121. void
  122. qdGetSpans( pDrawable, wMax, ppt, pwidth, nspans,pdstStart)
  123.     DrawablePtr        pDrawable;    /* drawable from which to get bits */
  124.     int            wMax;        /* largest value of all *pwidths */
  125.     register DDXPointPtr ppt;        /* points to start copying from */
  126.     int            *pwidth;    /* list of number of bits to copy */
  127.     int            nspans;        /* number of scanlines to copy */
  128.     unsigned int    *pdstStart;    /* where to put the bits */
  129. {
  130.     static void        qdGSPixFull();
  131.     unsigned int *    pret;
  132.     int x, y;
  133. #if NPLANES==24
  134.     24-plane support has been removed
  135. #else
  136.     DDXPointPtr          pptInit;
  137.     int                  *pwidthInit;
  138.     int                  i;
  139. #endif
  140.     if ( pDrawable->type == UNDRAWABLE_WINDOW)
  141.         return ;
  142.     if ( pDrawable->depth == 1 && pDrawable->type == DRAWABLE_PIXMAP) {
  143.     QDPixPtr pix = (QDPixPtr)pDrawable;
  144.     if (QD_PIX_DATA(&pix->pixmap) == NULL) {
  145.         extern int DebugDma;
  146.         int size = pix->pixmap.devKind * QDPIX_HEIGHT(&pix->pixmap);
  147.         QD_PIX_DATA(&pix->pixmap) = (pointer)Xalloc(size);
  148. #ifdef DEBUG
  149.         if (DebugDma > 0)
  150.         printf("[Copy pixmap 0x%x from offscreen]\n", pix);
  151. #endif
  152.         CopyPixmapFromOffscreen(pix, QD_PIX_DATA(&pix->pixmap));
  153.     }
  154.         x = QDPIX_X(pix);
  155.     y = QDPIX_Y(pix);
  156.     QDPIX_X(pix) = QDPIX_Y(pix) = 0;
  157.     mfbGetSpans( pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
  158.         QDPIX_X(pix) = x;
  159.     QDPIX_Y(pix) = y;
  160.     return;
  161.     }
  162.  
  163.     pptInit = ppt;
  164.     pwidthInit = pwidth;
  165.  
  166.     /*
  167.      * It's a full depth Pixmap or a window.
  168.      * Use an upper bound for the number of bytes to allocate.
  169.      */
  170.     if ( pDrawable->depth == Nplanes)
  171.         pret = pdstStart;
  172.     else
  173.         return;
  174.  
  175.  
  176.     if ( pDrawable->type == DRAWABLE_WINDOW)
  177.     {
  178.     int    ns;            /* span count */
  179.     u_char *  pr = (u_char *) pret;
  180.  
  181.     for ( ns=0; ns<nspans; ns++, pwidth++, ppt++)
  182.     {
  183.         tlgetimage((WindowPtr) pDrawable,
  184.                ppt->x, ppt->y,
  185.                *pwidth, 1, Allplanes, pr);
  186.         pr += *pwidth;
  187.     }
  188.     }
  189.     else if (QD_PIX_DATA((PixmapPtr)pDrawable) == NULL){ /*offscreen PIXMAP*/
  190.     int    ns;            /* span count */
  191.     u_char *  pr = (u_char *) pret;
  192.  
  193.     for ( ns=0; ns<nspans; ns++, pwidth++, ppt++)
  194.     {
  195.         tlgetimage((WindowPtr)NULL,
  196.               ppt->x, ppt->y,
  197.               *pwidth, 1, Allplanes, pr);
  198.         pr += *pwidth;
  199.     }
  200.     }
  201.     else    /* DRAWABLE_PIXMAP */
  202.     {
  203.     tlCancelPixmap( (QDPixPtr)pDrawable);
  204.     qdGSPixFull( (PixmapPtr)pDrawable, wMax, ppt, pwidth, nspans, pret);
  205.     }
  206. }
  207.  
  208. static void
  209. qdGSPixFull( pPix, wMax, ppt, pwidth, nspans, pret)
  210.     PixmapPtr        pPix;
  211.     int            wMax;        /* largest value of all *pwidths */
  212.     register DDXPointPtr ppt;        /* points to start copying from */
  213.     int            *pwidth;    /* list of number of bits to copy */
  214.     int            nspans;        /* number of scanlines to copy */
  215.     int *        pret;        /* return value */
  216. {
  217.     u_char *    ps = QD_PIX_DATA(pPix);
  218.     register u_char *    pd = (u_char *)pret;
  219.     int        ns;                /* span count */
  220.     register int    i;
  221.     register int    pixwidth = QDPIX_WIDTH(pPix);
  222.  
  223.  
  224.     for ( ns=0; ns<nspans; ns++, pwidth++, ppt++) {
  225. #if NPLANES==24
  226.     int skip = ppt->y*pixwidth + ppt->x;
  227.     register u_char *psr = ps + skip;                 /*red*/
  228.     register u_char *psg = ps+pixwidth*QDPIX_HEIGHT(pPix)+skip; /*green*/
  229.     register u_char *psb = ps+2*pixwidth*QDPIX_HEIGHT(pPix)+skip; /*blue*/
  230.     for ( i = *pwidth; --i >= 0; )
  231.     {
  232.         *pd++ = *psr++; 
  233.         *pd++ = *psg++; 
  234.         *pd++ = *psb++; 
  235.     }
  236. #else
  237.     bcopy(ps + ppt->y * pixwidth + ppt->x, pd, *pwidth);
  238.     pd += *pwidth;
  239. #endif
  240.     }
  241. }
  242. void
  243. qdSetSpansWin(pDraw, pGC, pPixels, pPoint, pWidth, n, fSorted)
  244.     DrawablePtr pDraw;
  245.     GC *pGC;
  246.     pointer pPixels;
  247.     DDXPointPtr pPoint;
  248.     int *pWidth;
  249.     int n;
  250.     int fSorted;
  251. {
  252.     int        ispan;  /* counts spans */
  253.     int        ipix;    /* indexes pPixels; knows about pixel size */
  254.  
  255.     if (pWidth[0] <= 0 || n <= 0)
  256.     return;
  257.  
  258.     for ( ispan = ipix = 0; ispan < n; ipix += pWidth[ispan++]*Nchannels) {
  259. #if NPLANES==24
  260.     /*
  261.      * convert from rgb, rgb, rgb to
  262.      * all red, all green, all blue for tlsetspan's convenience
  263.      */
  264.     unsigned char *    newpix;
  265.     int        j, off;
  266.     register int    isnf;    /* index to server-natural */
  267.  
  268.     if ( pWidth[ispan] <= 0)
  269.         continue;
  270.     newpix = (unsigned char *)
  271.         ALLOCATE_LOCAL(pWidth[ispan] * 3 * sizeof(unsigned char));
  272.     for (j=0, isnf=ipix; j<pWidth[ispan]; j++) {
  273.         for (off = 0; off < 3; off++) {
  274.         newpix[j+pWidth[ispan]*off] =
  275.             pPixels[isnf++];
  276.         }
  277.     }
  278.     tlsetspans(pDraw, pGC, newpix, &pPoint[ispan],
  279.            &pWidth[ispan], 1, 1);
  280.     DEALLOCATE_LOCAL(newpix);
  281. #else    /* NPLANES == 8 */
  282.     if ( pWidth[ispan] <= 0)
  283.         continue;
  284.     tlsetspans(pDraw, pGC, &pPixels[ipix], &pPoint[ispan],
  285.            &pWidth[ispan], 1, 1);
  286. #endif
  287.     }
  288. }
  289.  
  290. void
  291. qdSetSpansPix1(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted)
  292.     QDPixPtr pPix;
  293.     GC *pGC;
  294.     pointer pPixels;
  295.     DDXPointPtr pPoint;
  296.     int *pWidth;
  297.     int n;
  298.     int fSorted;
  299. {
  300.     if (QD_PIX_DATA(&pPix->pixmap) == NULL) {
  301.     /* This code could be better, but it shouldn't be used much. */
  302.     PixmapRec    tempBMap;
  303.     SETUP_PIXMAP_AS_WINDOW((DrawablePtr)pPix, pGC);
  304.     pGC->fgPixel = Allplanes;
  305.     pGC->bgPixel = 0;
  306.     QDPIX_HEIGHT(&tempBMap) = 1;
  307.     for ( ; --n >= 0; pWidth++, pPoint++) {
  308.         int         ic;     /* clip rect index */
  309.         int    numRects = REGION_NUM_RECTS(QDGC_COMPOSITE_CLIP(pGC));
  310.         register BoxPtr rects = REGION_RECTS(QDGC_COMPOSITE_CLIP(pGC));
  311.         BoxPtr newRects;
  312.  
  313.         /* create a temporary bitmap and transplant pImage into it  */
  314.         QDPIX_WIDTH(&tempBMap) = *pWidth;
  315.         tempBMap.devKind = PixmapBytePad(QDPIX_WIDTH(&tempBMap), 1);
  316.         QD_PIX_DATA(&tempBMap) = pPixels;
  317.  
  318.         for ( ic=0; ic < numRects; ic++, rects++)
  319.         tlBitmapBichrome(pGC, &tempBMap, Allplanes, 0,
  320.                  pPoint->x + QDPIX_X(pPix),
  321.                  pPoint->y + QDPIX_Y(pPix),
  322.                  rects);
  323.         pPixels += tempBMap.devKind;
  324.     }
  325.     CLEANUP_PIXMAP_AS_WINDOW(pGC);
  326.     }
  327.     else {
  328.     CHECK_MOVED(pGC, &pPix->pixmap.drawable);
  329.     mfbSetSpans(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted);
  330.     }
  331. }
  332.  
  333. void
  334. qdSetSpansPixN(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted)
  335.     PixmapPtr pPix;
  336.     GC *pGC;
  337.     pointer pPixels;
  338.     DDXPointPtr pPoint;
  339.     int *pWidth;
  340.     int n;
  341.     int fSorted;
  342. {
  343.     int        ispan;  /* counts spans */
  344.     int        ipix;    /* indexes pPixels; knows about pixel size */
  345.     int        j;
  346.     int        ic;    /* clip rect index */
  347.     BoxPtr      pc = REGION_RECTS(QDGC_COMPOSITE_CLIP(pGC));
  348. #if NPLANES<24
  349.     int fast;
  350. #endif
  351.  
  352.     if (pWidth[0] <= 0 || n <= 0)
  353.     return;
  354.  
  355.     if (QD_PIX_DATA(pPix) == NULL) {
  356.     CHECK_MOVED(pGC, &pPix->drawable);
  357.     qdSetSpansWin(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted);
  358.     return;
  359.     }
  360.  
  361.     tlCancelPixmap( pPix);
  362.     CHECK_MOVED(pGC, &pPix->drawable);
  363.  
  364. #if NPLANES<24
  365.     fast = pGC->alu == GXcopy && (pGC->planemask & Allplanes) == Allplanes;
  366. #endif
  367.     /* for each clipping rectangle */
  368.     for ( ic = REGION_NUM_RECTS(QDGC_COMPOSITE_CLIP(pGC)); --ic >= 0; pc++) {
  369.     /* for each scan */
  370.     for (ispan = ipix = 0; ispan < n; ipix += pWidth[ispan++]*Nchannels) {
  371.         unsigned char *psrc, *pdst;
  372.         int x, y;
  373.         y = pPoint[ispan].y;
  374.         if (pc->y2 <= y || pc->y1 > y)
  375.         continue;
  376.         x = pPoint[ispan].x;
  377.         j = x+pWidth[ispan];
  378.         psrc = &pPixels[ipix];
  379.         if (x < pc->x1) {
  380.         psrc += Nchannels * (pc->x1 - x);
  381.         x = pc->x1;
  382.         }
  383.         if (j > pc->x2) j = pc->x2;
  384.         j -= x;
  385.         pdst = QD_PIX_DATA(pPix) + x + y * QDPIX_WIDTH(pPix);
  386. #if NPLANES != 24
  387.         if (fast) {
  388.         if (j > 0)
  389.             bcopy(psrc, pdst, j);
  390.         }
  391.         else
  392. #endif
  393.         while ( --j >= 0) { /* each pt */
  394.         if (x >= pc->x2) break;
  395.         DOPIXEL(psrc, pdst, pGC, QDPIX_WIDTH(pPix)*QDPIX_HEIGHT(pPix));
  396.         x++; psrc += Nchannels; pdst++;
  397.         }    /* for j (inc on scan) */
  398.     }    /* for ispan (scan) */
  399.     }
  400. }
  401.  
  402. void
  403. qdSetSpansPix(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted)
  404.     PixmapPtr pPix;
  405.     GC *pGC;
  406.     pointer pPixels;
  407.     DDXPointPtr pPoint;
  408.     int *pWidth;
  409.     int n;
  410.     int fSorted;
  411. {
  412.     if (pPix->drawable.depth > 1)
  413.     qdSetSpansPixN(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted);
  414.     else
  415.     qdSetSpansPix1(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted);
  416. }
  417.  
  418.  
  419. /*
  420.  * FillSpans cases
  421.  */
  422.  
  423. /*
  424.  * Hack arg list and call qdFillBoxesOddSize.
  425.  * In addition to having to duplicate code, it wins because the
  426.  * region routines called by the primitive rect fill routines
  427.  * can coalesce (thin) spans to larger boxes.
  428.  */
  429. void
  430. qdWinFSOddSize( pDraw, pGC, nInit, pptInit, pwidthInit, fSorted)
  431.     DrawablePtr    pDraw;
  432.     GC        *pGC;
  433.     int        nInit;
  434.     DDXPointPtr    pptInit;
  435.     int        *pwidthInit;
  436.     int        fSorted;
  437. {
  438.     BoxPtr    pdestboxes;
  439.     register BoxPtr    pbox;
  440.     int        nr;
  441.  
  442.     pdestboxes = pbox = (BoxPtr) ALLOCATE_LOCAL( nInit*sizeof(BoxRec));
  443.     for (nr = nInit; --nr >= 0; pbox++, pptInit++, pwidthInit++)
  444.     {
  445.     pbox->x1 = pptInit->x;
  446.     pbox->x2 = pptInit->x + *pwidthInit;
  447.     pbox->y1 = pptInit->y;
  448.     pbox->y2 = pptInit->y + 1;
  449.     }
  450.     qdPolyFillBoxesOddSize( pDraw, pGC, nInit, pdestboxes);
  451.     DEALLOCATE_LOCAL(pdestboxes);
  452. }
  453.  
  454. #define    CLIPSPANS \
  455.     register DDXPointPtr    ppt; \
  456.     register int *        pwidth; \
  457.     DDXPointPtr    ppt0; \
  458.     int *    pwidth0; \
  459.     int        n; \
  460.     n = nInit * miFindMaxBand(QDGC_COMPOSITE_CLIP(pGC));\
  461.     if ( n == 0) \
  462.     return; \
  463.     pwidth0 = pwidth = (int *)ALLOCATE_LOCAL( n * sizeof(int)); \
  464.     ppt0 = ppt = (DDXPointRec *)ALLOCATE_LOCAL( n * sizeof(DDXPointRec)); \
  465.     if ( !ppt || !pwidth) \
  466.     FatalError("alloca failed in qd FillSpans.\n"); \
  467.     n = miClipSpans(QDGC_COMPOSITE_CLIP(pGC), \
  468.     pptInit, pwidthInit, nInit, ppt, pwidth, fSorted)
  469.  
  470. #define CLIPSPANS_FREE \
  471.      DEALLOCATE_LOCAL(ppt0); DEALLOCATE_LOCAL(pwidth0)
  472.  
  473. #define CALL_SPAN_WITH_DUMMY(FUNC) \
  474.     /* make dummy window and use that as the drawable */\
  475.     SETUP_PIXMAP_AS_WINDOW(&pPix->drawable, pGC);    \
  476.     CHECK_MOVED(pGC, &pPix->drawable);            \
  477.     FUNC(pPix, pGC, nInit, pptInit, pwidthInit, fSorted);\
  478.     CLEANUP_PIXMAP_AS_WINDOW(pGC);
  479.  
  480. void
  481. qdFSPixSolid(pPix, pGC, nInit, pptInit, pwidthInit, fSorted)
  482.     PixmapPtr    pPix;
  483.     GC        *pGC;
  484.     int        nInit;
  485.     DDXPointPtr    pptInit;
  486.     int        *pwidthInit;
  487.     int        fSorted;
  488. {
  489.     tlSinglePixmap( pPix);
  490.     if (QD_PIX_DATA(pPix) == NULL) {
  491.     CALL_SPAN_WITH_DUMMY(tlSolidSpans);
  492.     return;
  493.     }
  494.     CHECK_MOVED(pGC, &pPix->drawable);
  495.     if (pPix->drawable.depth == 1) {
  496.     void (*func)();
  497.     extern void mfbBlackSolidFS(), mfbWhiteSolidFS(), 
  498.         mfbInvertSolidFS();
  499.     switch (mfbReduceRop(pGC->alu, pGC->fgPixel)) {
  500.       case GXclear:    func = mfbBlackSolidFS; break;
  501.       case GXset:    func = mfbWhiteSolidFS; break;
  502.       case GXnoop:    func = NoopDDA; break;
  503.       case GXinvert:func = mfbInvertSolidFS; break;
  504.     }
  505.     (*func)(pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  506.     }
  507.     else {
  508.     CLIPSPANS;
  509. #if NPLANES<24
  510.         if (pGC->alu == GXcopy && (pGC->planemask & Allplanes) == Allplanes) {
  511.         register long fg;
  512.         fg = pGC->fgPixel;
  513.         fg = (fg << 8) | fg;
  514.         fg = (fg << 16) | fg;
  515.         for ( ; --n >= 0; ppt++) {
  516.         register unsigned char *pdst =
  517.             QD_PIX_DATA(pPix) + ppt->x + ppt->y * QDPIX_WIDTH(pPix);
  518.         register int w = *pwidth++;
  519.         int alDst = (int)pdst & 3;
  520.         /* simplified algorithm from cfbsp.c */
  521.         if (alDst + w <= 4) /* all bits inside same lonword */
  522.             while ( --w >= 0) *pdst++ = fg;
  523.         else {
  524.             if (alDst) {
  525.             /* word-align destination */
  526.             alDst = 4 - alDst;
  527.             w -= alDst;
  528.             while (--alDst >= 0) *pdst++ = fg;
  529.             }
  530.             /* loop over longwords */
  531.             alDst = w & 3;
  532.             w >>= 2;
  533.             while (--w >= 0)
  534.             *(long*)pdst++ = fg;
  535.             /* Do ragged right bytes. */
  536.             w = alDst;
  537.             while (--w >= 0) *pdst++ = fg;
  538.         }
  539.         }
  540.         }
  541.         else
  542. #endif
  543.         for ( ; n > 0; n--, pwidth++, ppt++) {
  544.         unsigned char *pdst =
  545.             QD_PIX_DATA(pPix) + ppt->x + ppt->y * QDPIX_WIDTH(pPix);
  546.         for ( ; *pwidth; (*pwidth)--, pdst++)
  547.             DOPIXEL(&pGC->fgPixel, pdst, pGC,
  548.             QDPIX_WIDTH(pPix) * QDPIX_HEIGHT(pPix));
  549.         }
  550.     CLIPSPANS_FREE;
  551.     }
  552. }
  553.  
  554. void
  555. qdFSPixTiled(pPix, pGC, nInit, pptInit, pwidthInit, fSorted)
  556.     PixmapPtr    pPix;
  557.     GC        *pGC;
  558.     int        nInit;
  559.     DDXPointPtr    pptInit;
  560.     int        *pwidthInit;
  561.     int        fSorted;
  562. {
  563.     register int    tbase, tinc, tbit;
  564.     unsigned long    scratch;
  565.  
  566.     tlSinglePixmap( pPix);
  567.     if (QD_PIX_DATA(pPix) == NULL) {
  568.     void (*func)();
  569.     extern void tlTiledSpans();
  570.     if (qdNaturalSizePixmap(pGC->tile.pixmap)) func = tlTiledSpans;
  571.     else func = qdWinFSOddSize;
  572.     { CALL_SPAN_WITH_DUMMY((*func)); }
  573.     return;
  574.     }
  575.     
  576.     CHECK_MOVED(pGC, &pPix->drawable);
  577.     if (pPix->drawable.depth == 1) {
  578.     tlCancelPixmap(pGC->stipple);
  579.     if (QDPIX_WIDTH(pGC->tile.pixmap) == 32)
  580.         mfbTileFS(pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  581.     else
  582.         mfbUnnaturalTileFS(pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  583.     } else {
  584.     CLIPSPANS;
  585. #ifdef DEBUG
  586.     if (PIXDEPTH(pGC->tile.pixmap) < Nplanes)
  587.         FatalError("tile is not full-depth pixmap\n");
  588. #endif
  589.     for ( ; n > 0; n--, ppt++, pwidth++) {
  590.         unsigned char *pdst =
  591.         QD_PIX_DATA(pPix) + ppt->x + ppt->y * QDPIX_WIDTH(pPix);
  592.         tbase = ((ppt->y) % QDPIX_HEIGHT(pGC->tile.pixmap))
  593.         * QPPADBYTES(QDPIX_WIDTH(pGC->tile.pixmap));
  594.         for ( ; *pwidth > 0; (ppt->x)++, *(pwidth)--, pdst++) {
  595.         tinc = tbase + (ppt->x) % QDPIX_WIDTH(pGC->tile.pixmap);
  596.         ZCOPY(QD_PIX_DATA(pGC->tile.pixmap) + tinc, &scratch,
  597.           QDPIX_WIDTH(pGC->tile.pixmap) * QDPIX_HEIGHT(pGC->tile), 1);
  598.         DOPIXEL(&scratch, pdst, pGC,
  599.             QDPIX_WIDTH(pPix) * QDPIX_HEIGHT(pPix));
  600.         }
  601.     }
  602.     CLIPSPANS_FREE;
  603.     }
  604. }
  605.  
  606. void
  607. qdFSPixStippleorOpaqueStip( pPix, pGC, nInit, pptInit, pwidthInit, fSorted)
  608.     PixmapPtr    pPix;
  609.     GC        *pGC;
  610.     int        nInit;
  611.     DDXPointPtr    pptInit;
  612.     int        *pwidthInit;
  613.     int        fSorted;
  614. {
  615.     int    tbase;    /* address of first byte in a stipple row */
  616.     int    tinc;    /* byte address within a stipple row */
  617.     int    tbit;    /* bit address within a stipple byte */
  618.  
  619.     tlSinglePixmap( pPix);
  620.     if (QD_PIX_DATA(pPix) == NULL) {
  621.     void (*func)();
  622.     extern void tlStipSpans(), tlOpStipSpans();
  623.     if (!qdNaturalSizePixmap(pGC->stipple))
  624.         func = qdWinFSOddSize;
  625.     else if (pGC->fillStyle == FillStippled)
  626.         func = tlStipSpans;
  627.     else
  628.         func = tlOpStipSpans;
  629.     { CALL_SPAN_WITH_DUMMY((*func)); }
  630.     return;
  631.     }
  632.  
  633.     CHECK_MOVED(pGC, &pPix->drawable);
  634.     if (pPix->drawable.depth == 1) {
  635.     /* simplified simulation of stuff done by mfbValidateGC */
  636.     int rop = mfbReduceRop(pGC->alu,pGC->fgPixel);
  637.     tlCancelPixmap(pGC->stipple);
  638.     if ( pGC->fillStyle == FillStippled) {
  639.         ((mfbPrivGCPtr)pGC->devPrivates[mfbGCPrivateIndex].ptr)->rop = rop;
  640.         mfbUnnaturalStippleFS( pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  641.     }
  642.     else {
  643.         extern int InverseAlu[16];
  644.         if (pGC->fgPixel == pGC->bgPixel) ;
  645.         else if (pGC->fgPixel) rop = pGC->alu;
  646.         else rop = InverseAlu[pGC->alu];
  647.         ((mfbPrivGCPtr)pGC->devPrivates[mfbGCPrivateIndex].ptr)->ropOpStip = rop;
  648.         mfbUnnaturalTileFS( pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  649.     }
  650.     return;
  651.     } else {
  652.     CLIPSPANS;
  653. #ifdef DEBUG
  654.     if (PIXDEPTH(pGC->stipple) != 1)
  655.         FatalError("stipple is not bitmap\n");
  656. #endif
  657.     for ( ; n > 0; n--, ppt++, pwidth++) {
  658.         unsigned char *pdst =
  659.         QD_PIX_DATA(pPix) + ppt->x + ppt->y * QDPIX_WIDTH(pPix);
  660.         tbase = UMOD(ppt->y-pGC->patOrg.y, QDPIX_HEIGHT(pGC->stipple))
  661.         * QPPADBYTES(QDPIX_WIDTH(pGC->stipple));
  662.         for ( ; *pwidth > 0; ppt->x++, (*pwidth)--, pdst++) {
  663.         tbit = ppt->x + pGC->patOrg.x;
  664.         tinc = tbase + UMOD(tbit, QDPIX_WIDTH(pGC->stipple)) / 8;
  665.         tbit &= 7;
  666.         if ( pGC->fillStyle == FillStippled) {
  667.             if ((QD_PIX_DATA(pGC->stipple)[tinc] >> tbit) & 1)
  668.             DOPIXEL(&pGC->fgPixel, pdst, pGC,
  669.                 QDPIX_WIDTH(pPix)*QDPIX_HEIGHT(pPix));
  670.         }
  671.         else {    /* FillOpaqueStippled */
  672.             if ((QD_PIX_DATA(pGC->stipple)[tinc] >> tbit) & 1)
  673.             DOPIXEL(&pGC->fgPixel, pdst, pGC,
  674.                 QDPIX_WIDTH(pPix) * QDPIX_HEIGHT(pPix));
  675.             else
  676.             DOPIXEL(&pGC->bgPixel, pdst, pGC,
  677.                 QDPIX_WIDTH(pPix) * QDPIX_HEIGHT(pPix));
  678.         }
  679.         }
  680.     }
  681.     CLIPSPANS_FREE;
  682.     }
  683. }
  684.