2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
8 #include <proto/graphics.h>
10 #include "graphics_intern.h"
17 #include <aros/debug.h>
20 #define USE_WRITEPIXEL
32 struct GfxBase
*gfxbase
;
35 static VOID
settmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
, UBYTE state
);
36 static BOOL
gettmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
);
38 static BOOL
filline(struct fillinfo
*fi
, LONG start_x
, LONG start_y
);
39 static BOOL
outline_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
);
40 static BOOL
color_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
);
43 static int fail_count
;
44 static int pix_written
;
47 /*****************************************************************************
50 #include <clib/graphics_protos.h>
55 AROS_LHA(struct RastPort
*, rp
, A1
),
56 AROS_LHA(ULONG
, mode
, D2
),
57 AROS_LHA(LONG
, x
, D0
),
58 AROS_LHA(LONG
, y
, D1
),
61 struct GfxBase
*, GfxBase
, 55, Graphics
)
64 Flood fill a RastPort.
67 rp - destination RastPort
68 mode - 0: fill adjacent pixels which don't have color of OPen.
69 1: fill adjacent pixels which have the same pen as of coordinate x,y.
70 x,y - coordinate to start filling.
75 The RastPort must have a TmpRas raster whose size is as large as of
87 27-11-96 digulla automatically created from
88 graphics_lib.fd and clib/graphics_protos.h
90 *****************************************************************************/
94 struct TmpRas
*tmpras
= rp
->TmpRas
;
95 ULONG bpr
, needed_size
;
96 ULONG rp_width
, rp_height
;
104 EnterFunc(bug("Flood(rp=%p, mode=%d, x=%d, y=%d)\n"
112 /* Check for tmpras */
114 ReturnBool("Flood (No tmpras)", FALSE
);
116 if (NULL
!= rp
->Layer
)
118 rp_width
= rp
->Layer
->Width
;
119 rp_height
= rp
->Layer
->Height
;
123 rp_width
= GetBitMapAttr(rp
->BitMap
, BMA_WIDTH
);
124 rp_height
= GetBitMapAttr(rp
->BitMap
, BMA_HEIGHT
);
128 bpr
= WIDTH_TO_BYTES( rp_width
);
129 needed_size
= bpr
* rp_height
;
131 if (tmpras
->Size
< needed_size
)
132 ReturnBool("Flood (To small tmpras)", FALSE
);
135 /* Clear the needed part of tmpras */
139 !!! Maybe we should use BltClear() here, since
140 !!! tmpras allways reside in CHIP RAM
143 D(bug("Clearing tmpras\n"));
144 memset(tmpras
->RasPtr
, 0, needed_size
);
147 D(bug("Drawing outline\n"));
148 /* Draw an outline to stop "leaks" */
152 for (idx
= 0; idx
< bpr
; idx
++ ) /* top */
153 tmpras
->RasPtr
[idx
] = 0xFF;
156 for (idx
= bpr
; idx
< needed_size
; idx
+= bpr
) /* left */
157 tmpras
->RasPtr
[idx
] |= 0x80;
160 right_mask
= XCOORD_TO_MASK(rp_width
- 1);
161 D(bug("Width=%d, mask=%d\n", rp_width
, right_mask
));
162 for (idx
= (bpr
* 2) - 1; idx
< needed_size
; idx
+= bpr
) /* right */
163 tmpras
->RasPtr
[idx
] |= right_mask
;
166 D(bug("height=%d, idx=%d\n", rp_height
, bpr
* (rp_height
- 1) ));
167 for (idx
= bpr
* (rp_height
- 1); idx
< needed_size
; idx
++ ) /* bottom */
168 tmpras
->RasPtr
[idx
] |= 0xFF;
170 D(bug("done outlining\n"));
175 D(bug("Getting outline pen\n"));
176 fi
.fillpen
= GetOutlinePen(rp
);
179 fi
.isfillable
= outline_isfillable
;
184 D(bug("Reading pixel\n"));
185 fi
.fillpen
= ReadPixel(rp
, x
, y
);
186 D(bug("pixel read\n"));
187 fi
.isfillable
= color_isfillable
;
190 fi
.rasptr
= tmpras
->RasPtr
;
194 fi
.orig_apen
= GetAPen(rp
);
195 fi
.orig_bpen
= GetBPen(rp
);
197 fi
.gfxbase
= GfxBase
;
199 D(bug("Calling filline\n"));
200 success
= filline(&fi
, x
, y
);
202 D(bug("fails: %d, pix written: %d\n", fail_count
, pix_written
));
204 SetAPen(rp
, fi
.orig_apen
);
206 ReturnBool("Flood", success
);
214 static VOID
settmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
, UBYTE state
)
216 ULONG idx
= COORD_TO_BYTEIDX(x
, y
, bpr
);
217 UBYTE mask
= XCOORD_TO_MASK( x
);
222 rasptr
[idx
] &= ~mask
;
227 static BOOL
gettmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
)
229 ULONG idx
= COORD_TO_BYTEIDX(x
, y
, bpr
);
230 UBYTE mask
= XCOORD_TO_MASK( x
);
233 /* D(bug("gettmpraspixel (%d, %d, %d): idx=%d, mask=%d, rasptr[idx]=%d, state=%d\n"
234 ,x, y, bpr, idx, mask, rasptr[idx], rasptr[idx] & mask));
236 state
= ((rasptr
[idx
] & mask
) != 0);
238 /* D(bug("Returning %d\n", state));
245 #define GfxBase (fi->gfxbase)
247 static BOOL
color_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
)
251 if (gettmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
))
253 /* D(bug("Pixel checked twice at (%d, %d)\n", x, y)); */
261 fill
= (fi
->fillpen
== ReadPixel(fi
->rp
, x
, y
));
267 static BOOL
outline_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
)
270 /* EnterFunc(bug("outline_isfillable(fi=%p, x=%d, y=%d)\n",
273 if (gettmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
))
275 /* D(bug("Pixel checked twice at (%d, %d)\n", x, y)); */
283 fill
= (fi
->fillpen
!= ReadPixel(fi
->rp
, x
, y
));
286 /* D(bug("fillpen: %d, pen: %d\n", fi->fillpen, ReadPixel(fi->rp, x, y)));
289 /* ReturnBool("outline_isfillable", fill);
296 static VOID
putfillpixel(struct fillinfo
*fi
, LONG x
, LONG y
)
299 #warning Implement use of patterns
302 #ifdef USE_WRITEPIXEL
303 ULONG pixval
, set_pixel
= 0UL;
305 if (fi
->rp
->AreaPtrn
)
307 set_pixel
= pattern_pen(fi
->rp
316 pixval
= GetAPen(fi
->rp
);
322 SetAPen(fi
->rp
, pixval
);
323 WritePixel(fi
->rp
, x
, y
);
328 settmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
, 1);
336 #define STACKSIZE 100
347 static VOID
init_stack(struct stack
*s
)
352 static BOOL
push(struct stack
*s
, LONG x
, LONG y
)
354 if (s
->current
== STACKSIZE
)
357 s
->items
[s
->current
].x
= x
;
358 s
->items
[s
->current
].y
= y
;
366 static BOOL
pop(struct stack
*s
, LONG
*xptr
, LONG
*yptr
)
374 *xptr
= s
->items
[s
->current
].x
;
375 *yptr
= s
->items
[s
->current
].y
;
381 static BOOL
filline(struct fillinfo
*fi
, LONG start_x
, LONG start_y
)
385 LONG rightmost_above
, rightmost_below
;
386 LONG leftmost_above
, leftmost_below
;
389 EnterFunc(bug("filline(fi=%p, start_x=%d, start_y=%d)\n"
390 ,fi
, start_x
, start_y
));
397 rightmost_above
= start_x
;
398 rightmost_below
= start_x
;
400 for (x
= start_x
+ 1; ; x
++)
403 if (fi
->isfillable(fi
, x
, start_y
))
405 putfillpixel(fi
, x
, start_y
);
408 if (x
> rightmost_above
)
410 if (fi
->isfillable(fi
, x
, start_y
- 1))
412 /* Find rightmost pixel */
414 for (rightmost_above
= x
; ; rightmost_above
++)
416 if (!fi
->isfillable(fi
, rightmost_above
+ 1, start_y
- 1))
421 if (!push(&stack
, rightmost_above
, start_y
- 1))
422 ReturnBool("filline (stack full)", FALSE
);
423 /* filline(fi, rightmost_above, start_y - 1);
430 if (x
> rightmost_below
)
432 if (fi
->isfillable(fi
, x
, start_y
+ 1))
434 /* Find rightmost pixel */
436 for (rightmost_below
= x
; ; rightmost_below
++)
438 if (!fi
->isfillable(fi
, rightmost_below
+ 1, start_y
+ 1))
443 if (!push(&stack
, rightmost_below
, start_y
+ 1))
444 ReturnBool("filline (stack full)", FALSE
);
446 /* filline(fi, rightmost_below, start_y + 1);
455 } /* for (scan right) */
461 leftmost_above
= start_x
+ 1;
462 leftmost_below
= start_x
+ 1;
464 for (x
= start_x
; ; x
-- )
468 if (fi
->isfillable(fi
, x
, start_y
))
470 putfillpixel(fi
, x
, start_y
);
473 if (x
<= leftmost_above
)
475 if (fi
->isfillable(fi
, x
, start_y
- 1))
477 /* Find rightmost pixel */
479 for (leftmost_above
= x
; ; leftmost_above
--)
481 if (!fi
->isfillable(fi
, leftmost_above
- 1, start_y
- 1))
486 if (!push(&stack
, leftmost_above
, start_y
- 1))
487 ReturnBool("filline (stack full)", FALSE
);
488 /* filline(fi, leftmost_above, start_y - 1);
495 if (x
< leftmost_below
)
497 if (fi
->isfillable(fi
, x
, start_y
+ 1))
499 /* Find rightmost pixel */
501 for (leftmost_below
= x
; ; leftmost_below
--)
503 if (!fi
->isfillable(fi
, leftmost_below
- 1, start_y
+ 1))
508 if (!push(&stack
, leftmost_below
, start_y
+ 1))
509 ReturnBool("filline (stack full)", FALSE
);
511 /* filline(fi, leftmost_below, start_y + 1);
520 } /* for (scan left) */
523 if (!pop(&stack
, &start_x
, &start_y
))
525 D(bug("\t\t\tpop(%d, %d)\n", start_x
, start_y
));
529 ReturnBool("filline", TRUE
);