home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / mfb / mfbclip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-30  |  6.1 KB  |  241 lines

  1. /***********************************************************
  2. Copyright 1987 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. /* $XConsortium: mfbclip.c,v 5.2 89/11/30 14:21:50 keith Exp $ */
  25. #include "X.h"
  26. #include "miscstruct.h"
  27. #include "pixmapstr.h"
  28. #include "scrnintstr.h"
  29. #include "regionstr.h"
  30. #include "gc.h"
  31. #include "maskbits.h"
  32. #include "mi.h"
  33.  
  34. #define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2)            \
  35. if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&            \
  36.     (!((reg)->data->numRects &&                    \
  37.        ((r-1)->y1 == (ry1)) &&                    \
  38.        ((r-1)->y2 == (ry2)) &&                    \
  39.        ((r-1)->x1 <= (rx1)) &&                    \
  40.        ((r-1)->x2 >= (rx2)))))                    \
  41. {                                \
  42.     if ((reg)->data->numRects == (reg)->data->size)        \
  43.     {                                \
  44.     miRectAlloc(reg, 1);                    \
  45.     fr = REGION_BOXPTR(reg);                \
  46.     r = fr + (reg)->data->numRects;                \
  47.     }                                \
  48.     r->x1 = (rx1);                        \
  49.     r->y1 = (ry1);                        \
  50.     r->x2 = (rx2);                        \
  51.     r->y2 = (ry2);                        \
  52.     (reg)->data->numRects++;                    \
  53.     if(r->x1 < (reg)->extents.x1)                \
  54.     (reg)->extents.x1 = r->x1;                \
  55.     if(r->x2 > (reg)->extents.x2)                \
  56.     (reg)->extents.x2 = r->x2;                \
  57.     r++;                            \
  58. }
  59.  
  60. /* Convert bitmap clip mask into clipping region. 
  61.  * First, goes through each line and makes boxes by noting the transitions
  62.  * from 0 to 1 and 1 to 0.
  63.  * Then it coalesces the current line with the previous if they have boxes
  64.  * at the same X coordinates.
  65.  */
  66. RegionPtr
  67. mfbPixmapToRegion(pPix)
  68.     PixmapPtr    pPix;
  69. {
  70.     register RegionPtr    pReg;
  71.     register unsigned    *pw, w;
  72.     register int    ib;
  73.     int            width, h, base, rx1, crects;
  74.     unsigned int    *pwLineEnd;
  75.     int            irectPrevStart, irectLineStart;
  76.     register BoxPtr    prectO, prectN;
  77.     BoxPtr        FirstRect, rects, prectLineStart;
  78.     Bool        fInBox, fSame;
  79.     register unsigned    mask0 = mask[0];
  80.  
  81.  
  82.     pReg = (*pPix->drawable.pScreen->RegionCreate)(NULL, 1);
  83.     if(!pReg)
  84.     return NullRegion;
  85.     FirstRect = REGION_BOXPTR(pReg);
  86.     rects = FirstRect;
  87.     width = pPix->drawable.width;
  88.     pReg->extents.x1 = width - 1;
  89.     pReg->extents.x2 = 0;
  90.     pw = (unsigned int  *)pPix->devPrivate.ptr;
  91.     irectPrevStart = -1;
  92.     for(h = 0; h < pPix->drawable.height; h++)
  93.     {
  94.     irectLineStart = rects - FirstRect;
  95.     /* If the Screen left most bit of the word is set, we're starting in
  96.      * a box */
  97.     if(*pw & mask0)
  98.     {
  99.         fInBox = TRUE;
  100.         rx1 = 0;
  101.     }
  102.     else
  103.         fInBox = FALSE;
  104.     /* Process all words which are fully in the pixmap */
  105.     pwLineEnd = pw + (width >> 5);
  106.     for (base = 0; pw < pwLineEnd; base += 32)
  107.     {
  108.         w = *pw++;
  109.         if (fInBox)
  110.         {
  111.         if (!~w)
  112.             continue;
  113.         }
  114.         else
  115.         {
  116.         if (!w)
  117.             continue;
  118.         }
  119.         for(ib = 0; ib < 32; ib++)
  120.         {
  121.             /* If the Screen left most bit of the word is set, we're
  122.          * starting a box */
  123.         if(w & mask0)
  124.         {
  125.             if(!fInBox)
  126.             {
  127.             rx1 = base + ib;
  128.             /* start new box */
  129.             fInBox = TRUE;
  130.             }
  131.         }
  132.         else
  133.         {
  134.             if(fInBox)
  135.             {
  136.             /* end box */
  137.             ADDRECT(pReg, rects, FirstRect,
  138.                 rx1, h, base + ib, h + 1);
  139.             fInBox = FALSE;
  140.             }
  141.         }
  142.         /* Shift the word VISUALLY left one. */
  143.         w = SCRLEFT(w, 1);
  144.         }
  145.     }
  146.     if(width & 0x1F)
  147.     {
  148.         /* Process final partial word on line */
  149.         w = *pw++;
  150.         for(ib = 0; ib < (width & 0x1F); ib++)
  151.         {
  152.             /* If the Screen left most bit of the word is set, we're
  153.          * starting a box */
  154.         if(w & mask0)
  155.         {
  156.             if(!fInBox)
  157.             {
  158.             rx1 = base + ib;
  159.             /* start new box */
  160.             fInBox = TRUE;
  161.             }
  162.         }
  163.         else
  164.         {
  165.             if(fInBox)
  166.             {
  167.             /* end box */
  168.             ADDRECT(pReg, rects, FirstRect,
  169.                 rx1, h, base + ib, h + 1);
  170.             fInBox = FALSE;
  171.             }
  172.         }
  173.         /* Shift the word VISUALLY left one. */
  174.         w = SCRLEFT(w, 1);
  175.         }
  176.     }
  177.     /* If scanline ended with last bit set, end the box */
  178.     if(fInBox)
  179.     {
  180.         ADDRECT(pReg, rects, FirstRect,
  181.             rx1, h, base + (width & 0x1f), h + 1);
  182.     }
  183.     /* if all rectangles on this line have the same x-coords as
  184.      * those on the previous line, then add 1 to all the previous  y2s and 
  185.      * throw away all the rectangles from this line 
  186.      */
  187.     fSame = FALSE;
  188.     if(irectPrevStart != -1)
  189.     {
  190.         crects = irectLineStart - irectPrevStart;
  191.         if(crects == ((rects - FirstRect) - irectLineStart))
  192.         {
  193.             prectO = FirstRect + irectPrevStart;
  194.             prectN = prectLineStart = FirstRect + irectLineStart;
  195.         fSame = TRUE;
  196.             while(prectO < prectLineStart)
  197.         {
  198.             if((prectO->x1 != prectN->x1) || (prectO->x2 != prectN->x2))
  199.             {
  200.               fSame = FALSE;
  201.               break;
  202.             }
  203.             prectO++;
  204.             prectN++;
  205.         }
  206.         if (fSame)
  207.         {
  208.             prectO = FirstRect + irectPrevStart;
  209.             while(prectO < prectLineStart)
  210.             {
  211.             prectO->y2 += 1;
  212.             prectO++;
  213.             }
  214.             rects -= crects;
  215.             pReg->data->numRects -= crects;
  216.         }
  217.         }
  218.     }
  219.     if(!fSame)
  220.         irectPrevStart = irectLineStart;
  221.     }
  222.     if (!pReg->data->numRects)
  223.     pReg->extents.x1 = pReg->extents.x2 = 0;
  224.     else
  225.     {
  226.     pReg->extents.y1 = REGION_BOXPTR(pReg)->y1;
  227.     pReg->extents.y2 = REGION_END(pReg)->y2;
  228.     if (pReg->data->numRects == 1)
  229.     {
  230.         xfree(pReg->data);
  231.         pReg->data = (RegDataPtr)NULL;
  232.     }
  233.     }
  234. #ifdef DEBUG
  235.     if (!miValidRegion(pReg))
  236.     FatalError("Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__);
  237. #endif
  238.     return(pReg);
  239. }
  240.  
  241.