home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / dv_x / dvix.zip / BITMAP.C next >
C/C++ Source or Header  |  1992-10-02  |  10KB  |  429 lines

  1. /* bitmap.c: bitmap manipulation code */
  2.  
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "dvi.h"
  8. #include "pxl.h"
  9. #include "general.h"
  10. #include "local.h"
  11. #include "bitorder.h"
  12.  
  13.  
  14. #ifdef MSBITFIRST
  15. #define maskBits(n) (((1<<(n))-1)<<(BYTESIZE-(n)))
  16. #define maskBits2(n) (((1<<(n))-1)<<(BYTESIZE*2-(n)))
  17. #define shiftMask(m,n) ((m)>>(n))
  18. #define shiftBack(m,n) ((m)<<(n))
  19. #define catBits(b0,b1) (((b0)<<BYTESIZE)+(b1))
  20. #define oneBit(n) ((1<<(BYTESIZE-1))>>(n))
  21. #else
  22. #define maskBits(n) ((1<<(n))-1)
  23. #define maskBits2(n) ((1<<(n))-1)
  24. #define shiftMask(m,n) ((m)<<(n))
  25. #define shiftBack(m,n) ((m)>>(n))
  26. #define catBits(b0,b1) (((b1)<<BYTESIZE)+(b0))
  27. #define oneBit(n) (1<<(n))
  28. #endif
  29.  
  30. extern unsigned char reverse_byte[];
  31. char *malloc();
  32.  
  33. /*
  34. ** the following declarations are imported from gf.c
  35. */
  36.  
  37. #define int32   long     /* used when at least 32 bits are required */
  38.  
  39. typedef struct bitmap *BitMap;
  40.  
  41. /* OR the src onto the dst (MSBit/MSByte first) */
  42. bitOr(dstbm,x,y,w,h,srcbm,srcx,srcy)
  43.     BitMap dstbm,srcbm;
  44.     int x, y, w, h, srcx, srcy;
  45. {
  46.     register BYTE *src, *dst;
  47.     register BYTE *sbp, *dbp;
  48.     register long sx, dx, width;
  49.     int dll, sll;
  50.  
  51.     sx = srcx;
  52.     dx = x;
  53.     width = w;
  54.  
  55.     /* do clipping first */
  56.     if (dx < 0) { width += dx; sx -= dx; dx = 0; }
  57.     if (sx < 0) { width += sx; dx -= sx; sx = 0; }
  58.     if (dx+width > dstbm->w) { width = dstbm->w - dx; }
  59.     if (sx+width > srcbm->w) { width = srcbm->w - sx; }
  60.     if (width <= 0) return;
  61.  
  62.     if (y < 0) { h += y; srcy -= y; y = 0; }
  63.     if (srcy < 0) { h += srcy; y -= srcy; srcy = 0; }
  64.     if (y+h > dstbm->h) { h = dstbm->h - y; }
  65.     if (srcy+h > srcbm->h) { h = srcbm->h - srcy; }
  66.     if (h <= 0) return;
  67.  
  68.     /* adjust dx and sx mod BYTESIZE */
  69.     dll = dstbm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
  70.     dst = (BYTE*)dstbm->bits + y*dll;
  71.     if (dx) { dst += dx>>BYTESHIFT; dx &= BYTEMASK; }
  72.     sll = srcbm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
  73.     src = (BYTE*)srcbm->bits + srcy*sll;
  74.     if (srcx) { src += sx>>BYTESHIFT; sx &= BYTEMASK; }
  75.  
  76.     /* save some values for later use (in the loop) */
  77.     w = width;
  78.     dbp = dst;
  79.     sbp = src;
  80.  
  81.     /* now, do the bit-or operations */
  82.     if (sx==0)
  83.     {
  84.     /* easier to do when the source is BYTE aligned */
  85.     if (dx+width<=BYTESIZE)
  86.     {
  87.         register unsigned long mask;
  88.             mask = maskBits(width);
  89.             while (--h>=0)
  90.             {
  91.                 *dst |= shiftMask(mask & *src, dx);
  92.                 dst += dll;
  93.                 src += sll;
  94.             }
  95.     }
  96.     else if (width<=BYTESIZE)
  97.     {
  98.         register unsigned long mask;
  99.             mask = maskBits(width);
  100.             while (--h>=0)
  101.             {
  102.                 dst[0] |= shiftMask(mask & *src, dx);
  103.                 dst[1] |= shiftBack(mask & *src, BYTESIZE-dx);
  104.                 dst += dll;
  105.                 src += sll;
  106.             }
  107.     }
  108.     else
  109.     {
  110.             while (--h>=0)
  111.             {
  112.             register unsigned long bits;
  113.                 while (width >= BYTESIZE)
  114.                 {
  115.             bits = *src++;
  116.                     *dst++ |= shiftMask(bits, dx);
  117.             if (dx) *dst |= shiftBack(bits, BYTESIZE-dx);
  118.                     width -= BYTESIZE;
  119.                 }
  120.                 if (width)
  121.                 {
  122.             bits = *src++ & maskBits(width);
  123.                     *dst++ |= shiftMask(bits, dx);
  124.             if (width+dx>BYTESIZE)
  125.                         *dst |= shiftBack(bits, BYTESIZE-dx);
  126.                 }
  127.                 dst = dbp += dll;
  128.                 src = sbp += sll;
  129.                 width = w;
  130.             }
  131.     }
  132.     }
  133.     else
  134.     {
  135.         while (--h>=0)
  136.         {
  137.         register unsigned long bits;
  138.         bits = 0L;
  139.             while (width >= BYTESIZE)
  140.             {
  141.         bits |= shiftBack(*src, sx);
  142.                 *dst++ |= shiftMask(bits, dx);
  143.                 if (dx) *dst |= shiftBack(bits, BYTESIZE-dx);
  144.         bits = shiftMask(*src++, BYTESIZE-sx);
  145.                 width -= BYTESIZE;
  146.             }
  147.             if (width)
  148.             {
  149.         bits |= shiftMask(*src, sx);
  150.         bits &= maskBits(width);
  151.                 *dst++ |= shiftMask( bits, dx);
  152.         if (width+dx>BYTESIZE)
  153.                     *dst |= shiftBack( bits, BYTESIZE-dx);
  154.             }
  155.             dst = dbp += dll;
  156.             src = sbp += sll;
  157.             width = w;
  158.         }
  159.     }
  160. }
  161.  
  162. #define bitClip(bm,x,y) (x>=0 && y>=0 && x<bm->w && y<bm->h)
  163. #define bitSetOne(bp,x) (bp[(x)>>BYTESHIFT] |= oneBit((x)&BYTEMASK))
  164.  
  165. /* draw a line onto the bitmap as an OR operation */
  166. bitLine(dstbm,x,y,x2,y2)
  167.     BitMap dstbm;
  168.     register int x, y;
  169.     int x2, y2;
  170. {
  171.     register int w, h;
  172.     register BYTE *dst;
  173.     register BYTE *dbp;
  174.     int dll;
  175.  
  176.     /* normalize the (x) direction first */
  177.     w = x2 - x;
  178.     h = y2 - y;
  179.     if (w<0) { x += w; w = -w; y += h; h = -h; }
  180.     if (x+w<0 || x>dstbm->w) return;
  181.  
  182.     dll = dstbm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
  183.     dst = (BYTE*)dstbm->bits + y*dll;
  184.  
  185.     if (h==0) {
  186.     /* horizontal */
  187.     bitFillBox(dstbm,x,y,w+1,1);
  188.     }
  189.     else if (w==0) {
  190.     /* vertical */
  191.     if (h<0) bitFillBox(dstbm,x,y+h,1,1-h);
  192.     else bitFillBox(dstbm,x,y,1,h+1);
  193.     }
  194.     else if (h>0) {
  195.     /* positive slope */
  196.     if (y+h<0 || y>dstbm->h) return;
  197.     if (w>=h) {
  198.         /* wider than high */
  199.         /* slope less than or equal to one */
  200.         register int err, i;
  201.         err = (h<<1) - w;
  202.         for (i=0; i<=w; i++) {
  203.         if (bitClip(dstbm,x,y)) bitSetOne(dst,x);
  204.         if (err>0) {
  205.             y++;
  206.             dst += dll;
  207.             err += (h-w)<<1;
  208.         }
  209.         else
  210.             err += h<<1;
  211.         x++;
  212.         }
  213.     }
  214.     else {
  215.     /* higher than wide */
  216.         /* slope greater than one */
  217.         register int err, i;
  218.         err = (w<<1) - h;
  219.         for (i=0; i<=h; i++) {
  220.         if (bitClip(dstbm,x,y)) bitSetOne(dst,x);
  221.         if (err>0) {
  222.             x++;
  223.             err += (w-h)<<1;
  224.         }
  225.         else
  226.             err += w<<1;
  227.         y++;
  228.         dst += dll;
  229.         }
  230.     }
  231.     }
  232.     else {
  233.     /* negative slope */
  234.     h = -h;
  235.     if (y+h<0 || y>dstbm->h) return;
  236.     if (w>=h) {
  237.         /* wider than high */
  238.         /* abs(slope) less than or equal to one */
  239.         register int err, i;
  240.         err = (h<<1) - w;
  241.         for (i=0; i<=w; i++) {
  242.         if (bitClip(dstbm,x,y)) bitSetOne(dst,x);
  243.         if (err>0) {
  244.             y--;
  245.             dst -= dll;
  246.             err += (h-w)<<1;
  247.         }
  248.         else
  249.             err += h<<1;
  250.         x++;
  251.         }
  252.     }
  253.     else {
  254.     /* higher than wide */
  255.         /* abs(slope) greater than one */
  256.         register int err, i;
  257.         err = (w<<1) - h;
  258.         for (i=0; i<=h; i++) {
  259.         if (bitClip(dstbm,x,y)) bitSetOne(dst,x);
  260.         if (err>0) {
  261.             x++;
  262.             err += (w-h)<<1;
  263.         }
  264.         else
  265.             err += w<<1;
  266.         y--;
  267.         dst -= dll;
  268.         }
  269.     }
  270.     }
  271. }
  272.  
  273. /* draw a filled box of the given size */
  274. bitFillBox(bm,x,y,width,height)
  275.     BitMap bm;
  276. {
  277.     register int dx, dy, w, h;
  278.     register BYTE *dst;
  279.  
  280.     dx = x;
  281.     dy = y;
  282.     w = width;
  283.     h = height;
  284.  
  285.     /* do clipping first */
  286.     if (w<0) { dx += w; w = -w; }
  287.     if (dx < 0) { w += dx; dx = 0; }
  288.     if (dx+w > bm->w) { w = bm->w - dx; }
  289.     if (w <= 0) return;
  290.  
  291.     if (h<0) { dy += h; h = -h; }
  292.     if (dy < 0) { h += dy; dy = 0; }
  293.     if (dy+h > bm->h) { h = bm->h - dy; }
  294.     if (h <= 0) return;
  295.  
  296.     /* adjust dx and sx mod BYTESIZE */
  297.     dst = (BYTE*)bm->bits + dy*bm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
  298.     if (dx) { dst += dx>>BYTESHIFT; dx &= BYTEMASK; }
  299.  
  300.     x = dx;
  301.     width = w;
  302.     dy = bm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
  303.  
  304.     if (dx+width<=BYTESIZE)
  305.     {
  306.     register unsigned long mask;
  307.     mask = maskBits(width);
  308.     if (dx) mask = shiftMask(mask,dx);
  309.     while (--h>=0)
  310.         {
  311.         *dst |= mask;
  312.         dst += dy;
  313.     }
  314.     }
  315.     else
  316.     {
  317.         register BYTE *dbp = dst;
  318.     while (--h>=0)
  319.     {
  320.         if (dx)
  321.         {
  322.         *dst++ |= shiftMask(maskBits(BYTESIZE-dx),dx);
  323.         width -= BYTESIZE-dx;
  324.         }
  325.         while (width >= BYTESIZE)
  326.         {
  327.         *dst++ = ~0;
  328.         width -= BYTESIZE;
  329.         }
  330.         if (width)
  331.         *dst++ |= maskBits(width);
  332.         dst = dbp += dy;
  333.         width = w;
  334.     }
  335.     }
  336. }
  337.  
  338.  
  339. /* draw a dotted box of the given size */
  340. bitGrayBox(bm,x,y,width,height,odd)
  341.     BitMap bm;
  342. {
  343.     register int dx, dy, w, h;
  344.     register long gray = 0x55555555;
  345.     register BYTE *dst;
  346.  
  347.     dx = x;
  348.     dy = y;
  349.     w = width;
  350.     h = height;
  351.  
  352.     /* do clipping first */
  353.     if (dx < 0) { w += dx; dx = 0; }
  354.     if (dx+w > bm->w) { w = bm->w - dx; }
  355.     if (w <= 0) return;
  356.  
  357.     if (dy < 0) { h += dy; dy = 0; }
  358.     if (dy+h > bm->h) { h = bm->h - dy; }
  359.     if (h <= 0) return;
  360.  
  361.     /* keep the pattern aligned with the background */
  362.     if ((odd^dy)&1) gray = ~gray;
  363.  
  364.     /* adjust dx and sx mod BYTESIZE */
  365.     dst = (BYTE*)bm->bits + dy*bm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
  366.     if (dx) { dst += dx>>BYTESHIFT; dx &= BYTEMASK; }
  367.  
  368.     x = dx;
  369.     width = w;
  370.     dy = bm->bytes_wide/(BYTESIZE/BITS_PER_BYTE);
  371.  
  372.     if (dx+width<=BYTESIZE)
  373.     {
  374.     register unsigned long mask;
  375.     mask = maskBits(width);
  376.     if (dx) mask = shiftMask(mask,dx);
  377.     while (--h>=0)
  378.         {
  379.         *dst |= mask & gray;
  380.         dst += dy;
  381.         gray = ~gray;
  382.     }
  383.     }
  384.     else
  385.     {
  386.         register BYTE *dbp = dst;
  387.     while (--h>=0)
  388.     {
  389.         if (dx)
  390.         {
  391.         *dst++ |= shiftMask(maskBits(BYTESIZE-dx),dx) & gray;
  392.         width -= BYTESIZE-dx;
  393.         }
  394.         while (width >= BYTESIZE)
  395.         {
  396.         *dst++ = gray;
  397.         width -= BYTESIZE;
  398.         }
  399.         if (width)
  400.         *dst++ |= maskBits(width) & gray;
  401.         dst = dbp += dy;
  402.         width = w;
  403.         gray = ~gray;
  404.     }
  405.     }
  406. }
  407.  
  408.  
  409. /* clear the contents of a BitMap */
  410. bitClear(dst)
  411.     BitMap dst;
  412. {
  413.     if (dst->bits)
  414.     bzero(dst->bits, dst->bytes_wide * dst->h);
  415. }
  416.  
  417. struct bitmap *
  418. bitCreate(width,height)
  419. {
  420.     unsigned int rowbytes = (width+BYTEMASK)/BYTESIZE*(BYTESIZE/BITS_PER_BYTE);
  421.     struct bitmap *bm;
  422.     bm = (struct bitmap *) malloc(sizeof(struct bitmap));
  423.     bm->w = width;
  424.     bm->h = height;
  425.     bm->bytes_wide = rowbytes;
  426.     bm->bits = malloc(rowbytes*height);
  427.     return bm;
  428. }
  429.