home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / mgl11 / examples / ffill.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-10  |  8.8 KB  |  296 lines

  1. /****************************************************************************
  2. *
  3. *                        MegaGraph Graphics Library
  4. *
  5. *                   Copyright (C) 1994 SciTech Software.
  6. *                            All rights reserved.
  7. *
  8. * Filename:     $RCSfile: ffill.c $
  9. * Version:      $Revision: 1.2 $
  10. *
  11. * Language:        ANSI C
  12. * Environment:    IBM PC (MS DOS)
  13. *
  14. * Description:    Flood fill region fill routines. This code shows how to
  15. *                build upon the low level MegaGraph library routines to
  16. *                build fast line adjacency flood fill routines. Two distinct
  17. *                routines are implemented here - a boundary flood fill,
  18. *                and an interior flood fill. Note that since the low
  19. *                level scanline routines do not do any clipping or view
  20. *                port mapping, we must do that within the routines.
  21. *
  22. *                To mimise the amount of stack space that is used, only the
  23. *                variable that absolutely MUST be local are stored as local
  24. *                or passed as parameters, while the rest are stored globally
  25. *                to the recursive routines.
  26. *
  27. *                NOTE:    These routines use a lot of stack space since they
  28. *                        are recursive. If you wish to use these in real
  29. *                        programs, you should use a large stack of about
  30. *                        20k.
  31. *
  32. * $Id: ffill.c 1.2 1994/03/10 09:25:52 kjb release $
  33. *
  34. ****************************************************************************/
  35.  
  36. #include "mgraph.h"
  37. #include <dos.h>
  38.  
  39. /*------------------------- Implementation --------------------------------*/
  40.  
  41. #define    UP        -1
  42. #define    DOWN    1
  43.  
  44. PRIVATE    color_t        border;            /* Color of border pixels            */
  45. PRIVATE    color_t        fill;            /* Color of current fill color        */
  46. PRIVATE    color_t        interior;        /* Color of interior pixels            */
  47. PRIVATE    color_t        back;            /* Background color                    */
  48. PRIVATE    rect        viewPort;        /* The current viewport                */
  49. PRIVATE    rect        clipRect;        /* The current clipping rectangle    */
  50. PRIVATE color_t        v;                /* Global variable                    */
  51.  
  52. PRIVATE int near BorderAdjFill(int x,int y,int D,int prevXL,
  53.     int prevXR)
  54. /****************************************************************************
  55. *
  56. * Function:        BorderAdjFill
  57. * Parameters:    x        - Seed x coordinate
  58. *                y        - Seed y coordinate
  59. *                D        - Direction to fill in (UP,DOWN)
  60. *                prevXL    - Previous x left coordinate
  61. *                prevXR    - Previous x right coordinate
  62. * Returns:        Right coordinate filled up to.
  63. *
  64. * Description:    Recursively border fills an area starting at the seed
  65. *                point (seedX,seedY) and travelling in the direction D.
  66. *
  67. *                A border fill is terminated when it comes across a border
  68. *                pixel of the specified border color.
  69. *
  70. ****************************************************************************/
  71. {
  72.     int        xl,xr;
  73.  
  74.     xl = xr = x;        /* Initialise to seed coordinates            */
  75.  
  76.     /* Scan left in video buffer from the current seed coordinate looking
  77.      * for border pixels.
  78.      */
  79.  
  80.     if (--xl >= clipRect.left) {
  81.         xl = MGL_scanLeftForColor(xl+viewPort.left,y+viewPort.top,border);
  82.         if ((xl -= viewPort.left) < clipRect.left)
  83.             xl = clipRect.left-1;
  84.         xl++;
  85.         }
  86.     else
  87.         xl = clipRect.left;
  88.  
  89.     /* Scan right in video buffer from the current seed coordinate looking
  90.      * for border pixels.
  91.      */
  92.  
  93.     if (++xr < clipRect.right) {
  94.         xr = MGL_scanRightForColor(xr+viewPort.left,y+viewPort.top,border);
  95.         if ((xr -= viewPort.left) >= clipRect.right)
  96.             xr = clipRect.right;
  97.         xr--;
  98.         }
  99.     else
  100.         xr = clipRect.right-1;
  101.  
  102.     /* Fill in the current scan line */
  103.  
  104.     MGL_beginDrawing();
  105.     MGL_scanLine(y+viewPort.top,xl+viewPort.left,xr+viewPort.left+1);
  106.     MGL_endDrawing();
  107.  
  108.     /* Find and fill adjacent line segments in same direction */
  109.  
  110.     if (y+D >= clipRect.top && y+D < clipRect.bottom)
  111.         for (x = xl; x <= xr; x++) {
  112.             v = MGL_getPixelCoord(x,y+D);
  113.             if (v != border && v != fill && v != back)
  114.                 x = BorderAdjFill(x,y+D,D,xl,xr);
  115.             }
  116.  
  117.     /* Find and fill adjacent line segments in opposite direction */
  118.  
  119.     if (y-D >= clipRect.top && y-D < clipRect.bottom) {
  120.         prevXL -= 2;
  121.         for (x = xl; x < prevXL; x++) {
  122.             v = MGL_getPixelCoord(x,y-D);
  123.             if (v != border && v != fill && v != back)
  124.                 x = BorderAdjFill(x,y-D,-D,xl,xr);
  125.             }
  126.  
  127.         for (x = prevXR+2; x < xr; x++) {
  128.             v = MGL_getPixelCoord(x,y-D);
  129.             if (v != border && v != fill && v != back)
  130.                 x = BorderAdjFill(x,y-D,-D,xl,xr);
  131.             }
  132.         }
  133.  
  134.     return xr;
  135. }
  136.  
  137. PUBLIC void MGL_boundaryFill(int x,int y,color_t bdr)
  138. /****************************************************************************
  139. *
  140. * Function:        MGL_boundaryFill
  141. * Parameters:    x    - Seed x coordinate
  142. *                y    - Seed y coordinate
  143. *                bdr    - Border color used for fill
  144. *
  145. * Description:    Does a boundary fill starting at the point (x,y) and
  146. *                filling all the area bounded by pixels of the color bdr.
  147. *
  148. *                The area is filled in with the current drawing color and
  149. *                the current pattern. Note however that you can only use
  150. *                BITMAP_PATTERN_OPAQUE pattern's, or solid fills.
  151. *
  152. ****************************************************************************/
  153. {
  154.     int    penstyle = MGL_getPenStyle();
  155.     int    writemode = MGL_getWriteMode();
  156.  
  157.     if (penstyle == BITMAP_PATTERN_TRANSPARENT || writemode != REPLACE_MODE)
  158.         return;
  159.     back = -1;
  160.     if (penstyle == BITMAP_PATTERN_OPAQUE)
  161.         back = MGL_getBackColor();
  162.     border = bdr;
  163.     fill = MGL_getColor();
  164.  
  165.     /* Set up viewport and clipping rectangles */
  166.  
  167.     MGL_getViewport(&viewPort);
  168.     MGL_getClipRect(&clipRect);
  169.  
  170.     if (MGL_ptInRectCoord(x,y,clipRect))
  171.         BorderAdjFill(x,y,DOWN,x,x);
  172. }
  173.  
  174. PRIVATE int near InteriorAdjFill(int x,int y,int D,int prevXL,
  175.     int prevXR)
  176. /****************************************************************************
  177. *
  178. * Function:        InteriorAdjFill
  179. * Parameters:    x        - Seed x coordinate
  180. *                y        - Seed y coordinate
  181. *                D        - Direction to fill in (UP,DOWN)
  182. *                prevXL    - Previous x left coordinate
  183. *                prevXR    - Previous x right coordinate
  184. * Returns:        Right coordinate filled up to.
  185. *
  186. * Description:    Recursively fills an area starting at the seed point
  187. *                (seedX,seedY) and travelling in the direction D.
  188. *
  189. *                An interior fill is terminated when it comes across a
  190. *                pixel of different to that of the original seed pixel.
  191. *
  192. ****************************************************************************/
  193. {
  194.     int        xl,xr;
  195.  
  196.     xl = xr = x;        /* Initialise to seed coordinates            */
  197.  
  198.     /* Scan left in video buffer from the current seed coordinate looking
  199.      * for border pixels.
  200.      */
  201.  
  202.     if (--xl >= clipRect.left) {
  203.         xl = MGL_scanLeftWhileColor(xl+viewPort.left,y+viewPort.top,interior);
  204.         if ((xl -= viewPort.left) < clipRect.left)
  205.             xl = clipRect.left-1;
  206.         xl++;
  207.         }
  208.     else
  209.         xl = clipRect.left;
  210.  
  211.     /* Scan right in video buffer from the current seed coordinate looking
  212.      * for border pixels.
  213.      */
  214.  
  215.     if (++xr < clipRect.right) {
  216.         xr = MGL_scanRightWhileColor(xr+viewPort.left,y+viewPort.top,interior);
  217.         if ((xr -= viewPort.left) >= clipRect.right)
  218.             xr = clipRect.right;
  219.         xr--;
  220.         }
  221.     else
  222.         xr = clipRect.right-1;
  223.  
  224.     /* Fill in the current scan line */
  225.  
  226.     MGL_beginDrawing();
  227.     MGL_scanLine(y+viewPort.top,xl+viewPort.left,xr+viewPort.left+1);
  228.     MGL_endDrawing();
  229.  
  230.     /* Find and fill adjacent line segments in same direction */
  231.  
  232.     if (y+D >= clipRect.top && y+D < clipRect.bottom)
  233.         for (x = xl; x <= xr; x++) {
  234.             v = MGL_getPixelCoord(x,y+D);
  235.             if (v == interior && v != fill && v != back)
  236.                 x = InteriorAdjFill(x,y+D,D,xl,xr);
  237.             }
  238.  
  239.     /* Find and fill adjacent line segments in opposite direction */
  240.  
  241.     if (y-D >= clipRect.top && y-D < clipRect.bottom) {
  242.         prevXL -= 2;
  243.         for (x = xl; x < prevXL; x++) {
  244.             v = MGL_getPixelCoord(x,y-D);
  245.             if (v == interior && v != fill && v != back)
  246.                 x = InteriorAdjFill(x,y-D,-D,xl,xr);
  247.             }
  248.  
  249.         for (x = prevXR+2; x < xr; x++) {
  250.             v = MGL_getPixelCoord(x,y-D);
  251.             if (v == interior && v != fill && v != back)
  252.                 x = InteriorAdjFill(x,y-D,-D,xl,xr);
  253.             }
  254.         }
  255.  
  256.     return xr;
  257. }
  258.  
  259. PUBLIC void MGL_interiorFill(int x,int y)
  260. /****************************************************************************
  261. *
  262. * Function:        MGL_interiorFill
  263. * Parameters:    x    - Seed x coordinate
  264. *                y    - Seed y coordinate
  265. *
  266. * Description:    Does a flood fill starting at the point (x,y) and
  267. *                filling in all accessible areas of the same color as the
  268. *                seed point.
  269. *
  270. *                The area is filled in with the current drawing color and
  271. *                the current pattern. Note however that you can only use
  272. *                BITMAP_PATTERN_OPAQUE pattern's, or solid fills in replace
  273. *                mode.
  274. *
  275. ****************************************************************************/
  276. {
  277.     int    penstyle = MGL_getPenStyle();
  278.     int    writemode = MGL_getWriteMode();
  279.  
  280.     if (penstyle == BITMAP_PATTERN_TRANSPARENT || writemode != REPLACE_MODE)
  281.         return;
  282.     back = -1;
  283.     if (penstyle == BITMAP_PATTERN_OPAQUE)
  284.         back = MGL_getBackColor();
  285.     if ((interior = MGL_getPixelCoord(x,y)) == -1)
  286.         return;
  287.     fill = MGL_getColor();
  288.  
  289.     /* Set up viewport and clipping rectangles */
  290.  
  291.     MGL_getViewport(&viewPort);
  292.     MGL_getClipRect(&clipRect);
  293.  
  294.     InteriorAdjFill(x,y,DOWN,x,x);
  295. }
  296.