2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
8 #include <aros/debug.h>
10 #include <proto/graphics.h>
12 #include "graphics_intern.h"
14 #define USE_WRITEPIXEL
28 struct GfxBase
*gfxbase
;
31 static VOID
settmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
, UBYTE state
);
32 static BOOL
gettmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
);
34 static BOOL
filline(struct fillinfo
*fi
, LONG start_x
, LONG start_y
);
35 static BOOL
outline_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
);
36 static BOOL
color_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
);
39 static int fail_count
;
40 static int pix_written
;
43 /*****************************************************************************
46 #include <clib/graphics_protos.h>
51 AROS_LHA(struct RastPort
*, rp
, A1
),
52 AROS_LHA(ULONG
, mode
, D2
),
53 AROS_LHA(LONG
, x
, D0
),
54 AROS_LHA(LONG
, y
, D1
),
57 struct GfxBase
*, GfxBase
, 55, Graphics
)
60 Flood fill a RastPort.
63 rp - destination RastPort
64 mode - 0: fill adjacent pixels which don't have color of OPen.
65 1: fill adjacent pixels which have the same pen as of coordinate x,y.
66 x,y - coordinate to start filling.
71 The RastPort must have a TmpRas raster whose size is as large as of
83 27-11-96 digulla automatically created from
84 graphics_lib.fd and clib/graphics_protos.h
86 *****************************************************************************/
90 struct TmpRas
*tmpras
= rp
->TmpRas
;
91 ULONG bpr
, needed_size
;
97 EnterFunc(bug("Flood(rp=%p, mode=%d, x=%d, y=%d)\n"
105 /* Check for tmpras */
107 ReturnBool("Flood (No tmpras)", FALSE
);
109 if (NULL
!= rp
->Layer
)
111 fi
.rp_width
= rp
->Layer
->Width
;
112 fi
.rp_height
= rp
->Layer
->Height
;
116 fi
.rp_width
= GetBitMapAttr(rp
->BitMap
, BMA_WIDTH
);
117 fi
.rp_height
= GetBitMapAttr(rp
->BitMap
, BMA_HEIGHT
);
121 bpr
= WIDTH_TO_BYTES( fi
.rp_width
);
122 needed_size
= bpr
* fi
.rp_height
;
124 if (tmpras
->Size
< needed_size
)
125 ReturnBool("Flood (To small tmpras)", FALSE
);
128 /* Clear the needed part of tmpras */
132 !!! Maybe we should use BltClear() here, since
133 !!! tmpras allways reside in CHIP RAM
136 D(bug("Clearing tmpras\n"));
137 memset(tmpras
->RasPtr
, 0, needed_size
);
142 D(bug("Getting outline pen\n"));
143 fi
.fillpen
= GetOutlinePen(rp
);
146 fi
.isfillable
= outline_isfillable
;
151 D(bug("Reading pixel\n"));
152 fi
.fillpen
= ReadPixel(rp
, x
, y
);
153 D(bug("pixel read: %d\n", fi
.fillpen
));
154 fi
.isfillable
= color_isfillable
;
157 fi
.rasptr
= tmpras
->RasPtr
;
161 fi
.orig_apen
= GetAPen(rp
);
162 fi
.orig_bpen
= GetBPen(rp
);
164 fi
.gfxbase
= GfxBase
;
166 D(bug("Calling filline\n"));
167 success
= filline(&fi
, x
, y
);
170 D(bug("fails: %d, pix written: %d\n", fail_count
, pix_written
));
173 SetAPen(rp
, fi
.orig_apen
);
175 ReturnBool("Flood", success
);
183 static VOID
settmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
, UBYTE state
)
185 ULONG idx
= COORD_TO_BYTEIDX(x
, y
, bpr
);
186 UBYTE mask
= XCOORD_TO_MASK( x
);
191 rasptr
[idx
] &= ~mask
;
196 static BOOL
gettmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
)
198 ULONG idx
= COORD_TO_BYTEIDX(x
, y
, bpr
);
199 UBYTE mask
= XCOORD_TO_MASK( x
);
202 /* D(bug("gettmpraspixel (%d, %d, %d): idx=%d, mask=%d, rasptr[idx]=%d, state=%d\n"
203 ,x, y, bpr, idx, mask, rasptr[idx], rasptr[idx] & mask));
205 state
= ((rasptr
[idx
] & mask
) != 0);
207 /* D(bug("Returning %d\n", state));
214 #define GfxBase (fi->gfxbase)
216 static BOOL
color_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
)
220 if (x
< 0 || y
< 0 || x
>= fi
->rp_width
|| y
>= fi
->rp_height
)
223 if (gettmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
))
225 /* D(bug("Pixel checked twice at (%d, %d)\n", x, y)); */
233 fill
= (fi
->fillpen
== ReadPixel(fi
->rp
, x
, y
));
239 static BOOL
outline_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
)
242 /* EnterFunc(bug("outline_isfillable(fi=%p, x=%d, y=%d)\n",
245 if (x
< 0 || y
< 0 || x
>= fi
->rp_width
|| y
>= fi
->rp_height
)
248 if (gettmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
))
250 /* D(bug("Pixel checked twice at (%d, %d)\n", x, y)); */
258 fill
= (fi
->fillpen
!= ReadPixel(fi
->rp
, x
, y
));
261 /* D(bug("fillpen: %d, pen: %d\n", fi->fillpen, ReadPixel(fi->rp, x, y)));
264 /* ReturnBool("outline_isfillable", fill);
271 static VOID
putfillpixel(struct fillinfo
*fi
, LONG x
, LONG y
)
274 /* TODO: Implement use of patterns */
276 #ifdef USE_WRITEPIXEL
277 ULONG pixval
, set_pixel
= 0UL;
279 if (fi
->rp
->AreaPtrn
)
281 set_pixel
= pattern_pen(fi
->rp
290 pixval
= GetAPen(fi
->rp
);
296 SetAPen(fi
->rp
, pixval
);
297 WritePixel(fi
->rp
, x
, y
);
302 settmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
, 1);
310 #define STACKSIZE 100
321 static VOID
init_stack(struct stack
*s
)
326 static BOOL
push(struct stack
*s
, LONG x
, LONG y
)
328 if (s
->current
== STACKSIZE
)
331 s
->items
[s
->current
].x
= x
;
332 s
->items
[s
->current
].y
= y
;
340 static BOOL
pop(struct stack
*s
, LONG
*xptr
, LONG
*yptr
)
348 *xptr
= s
->items
[s
->current
].x
;
349 *yptr
= s
->items
[s
->current
].y
;
355 static BOOL
filline(struct fillinfo
*fi
, LONG start_x
, LONG start_y
)
359 LONG rightmost_above
, rightmost_below
;
360 LONG leftmost_above
, leftmost_below
;
363 EnterFunc(bug("filline(fi=%p, start_x=%d, start_y=%d)\n"
364 ,fi
, start_x
, start_y
));
371 rightmost_above
= start_x
;
372 rightmost_below
= start_x
;
374 for (x
= start_x
+ 1; ; x
++)
377 if (fi
->isfillable(fi
, x
, start_y
))
379 putfillpixel(fi
, x
, start_y
);
382 if (x
> rightmost_above
)
384 if (fi
->isfillable(fi
, x
, start_y
- 1))
386 /* Find rightmost pixel */
388 for (rightmost_above
= x
; ; rightmost_above
++)
390 if (!fi
->isfillable(fi
, rightmost_above
+ 1, start_y
- 1))
395 if (!push(&stack
, rightmost_above
, start_y
- 1))
396 ReturnBool("filline (stack full)", FALSE
);
397 /* filline(fi, rightmost_above, start_y - 1);
404 if (x
> rightmost_below
)
406 if (fi
->isfillable(fi
, x
, start_y
+ 1))
408 /* Find rightmost pixel */
410 for (rightmost_below
= x
; ; rightmost_below
++)
412 if (!fi
->isfillable(fi
, rightmost_below
+ 1, start_y
+ 1))
417 if (!push(&stack
, rightmost_below
, start_y
+ 1))
418 ReturnBool("filline (stack full)", FALSE
);
420 /* filline(fi, rightmost_below, start_y + 1);
429 } /* for (scan right) */
435 leftmost_above
= start_x
+ 1;
436 leftmost_below
= start_x
+ 1;
438 for (x
= start_x
; ; x
-- )
442 if (fi
->isfillable(fi
, x
, start_y
))
444 putfillpixel(fi
, x
, start_y
);
447 if (x
<= leftmost_above
)
449 if (fi
->isfillable(fi
, x
, start_y
- 1))
451 /* Find rightmost pixel */
453 for (leftmost_above
= x
; ; leftmost_above
--)
455 if (!fi
->isfillable(fi
, leftmost_above
- 1, start_y
- 1))
460 if (!push(&stack
, leftmost_above
, start_y
- 1))
461 ReturnBool("filline (stack full)", FALSE
);
462 /* filline(fi, leftmost_above, start_y - 1);
469 if (x
< leftmost_below
)
471 if (fi
->isfillable(fi
, x
, start_y
+ 1))
473 /* Find rightmost pixel */
475 for (leftmost_below
= x
; ; leftmost_below
--)
477 if (!fi
->isfillable(fi
, leftmost_below
- 1, start_y
+ 1))
482 if (!push(&stack
, leftmost_below
, start_y
+ 1))
483 ReturnBool("filline (stack full)", FALSE
);
485 /* filline(fi, leftmost_below, start_y + 1);
494 } /* for (scan left) */
497 if (!pop(&stack
, &start_x
, &start_y
))
499 D(bug("\t\t\tpop(%d, %d)\n", start_x
, start_y
));
503 ReturnBool("filline", TRUE
);