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
34 struct GfxBase
*gfxbase
;
37 static VOID
settmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
, UBYTE state
);
38 static BOOL
gettmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
);
40 static BOOL
filline(struct fillinfo
*fi
, LONG start_x
, LONG start_y
);
41 static BOOL
outline_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
);
42 static BOOL
color_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
);
45 static int fail_count
;
46 static int pix_written
;
49 /*****************************************************************************
52 #include <clib/graphics_protos.h>
57 AROS_LHA(struct RastPort
*, rp
, A1
),
58 AROS_LHA(ULONG
, mode
, D2
),
59 AROS_LHA(LONG
, x
, D0
),
60 AROS_LHA(LONG
, y
, D1
),
63 struct GfxBase
*, GfxBase
, 55, Graphics
)
66 Flood fill a RastPort.
69 rp - destination RastPort
70 mode - 0: fill adjacent pixels which don't have color of OPen.
71 1: fill adjacent pixels which have the same pen as of coordinate x,y.
72 x,y - coordinate to start filling.
77 The RastPort must have a TmpRas raster whose size is as large as of
89 27-11-96 digulla automatically created from
90 graphics_lib.fd and clib/graphics_protos.h
92 *****************************************************************************/
96 struct TmpRas
*tmpras
= rp
->TmpRas
;
97 ULONG bpr
, needed_size
;
103 EnterFunc(bug("Flood(rp=%p, mode=%d, x=%d, y=%d)\n"
111 /* Check for tmpras */
113 ReturnBool("Flood (No tmpras)", FALSE
);
115 if (NULL
!= rp
->Layer
)
117 fi
.rp_width
= rp
->Layer
->Width
;
118 fi
.rp_height
= rp
->Layer
->Height
;
122 fi
.rp_width
= GetBitMapAttr(rp
->BitMap
, BMA_WIDTH
);
123 fi
.rp_height
= GetBitMapAttr(rp
->BitMap
, BMA_HEIGHT
);
127 bpr
= WIDTH_TO_BYTES( fi
.rp_width
);
128 needed_size
= bpr
* fi
.rp_height
;
130 if (tmpras
->Size
< needed_size
)
131 ReturnBool("Flood (To small tmpras)", FALSE
);
134 /* Clear the needed part of tmpras */
138 !!! Maybe we should use BltClear() here, since
139 !!! tmpras allways reside in CHIP RAM
142 D(bug("Clearing tmpras\n"));
143 memset(tmpras
->RasPtr
, 0, needed_size
);
148 D(bug("Getting outline pen\n"));
149 fi
.fillpen
= GetOutlinePen(rp
);
152 fi
.isfillable
= outline_isfillable
;
157 D(bug("Reading pixel\n"));
158 fi
.fillpen
= ReadPixel(rp
, x
, y
);
159 D(bug("pixel read: %d\n", fi
.fillpen
));
160 fi
.isfillable
= color_isfillable
;
163 fi
.rasptr
= tmpras
->RasPtr
;
167 fi
.orig_apen
= GetAPen(rp
);
168 fi
.orig_bpen
= GetBPen(rp
);
170 fi
.gfxbase
= GfxBase
;
172 D(bug("Calling filline\n"));
173 success
= filline(&fi
, x
, y
);
175 D(bug("fails: %d, pix written: %d\n", fail_count
, pix_written
));
177 SetAPen(rp
, fi
.orig_apen
);
179 ReturnBool("Flood", success
);
187 static VOID
settmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
, UBYTE state
)
189 ULONG idx
= COORD_TO_BYTEIDX(x
, y
, bpr
);
190 UBYTE mask
= XCOORD_TO_MASK( x
);
195 rasptr
[idx
] &= ~mask
;
200 static BOOL
gettmpraspixel(BYTE
*rasptr
, LONG x
, LONG y
, ULONG bpr
)
202 ULONG idx
= COORD_TO_BYTEIDX(x
, y
, bpr
);
203 UBYTE mask
= XCOORD_TO_MASK( x
);
206 /* D(bug("gettmpraspixel (%d, %d, %d): idx=%d, mask=%d, rasptr[idx]=%d, state=%d\n"
207 ,x, y, bpr, idx, mask, rasptr[idx], rasptr[idx] & mask));
209 state
= ((rasptr
[idx
] & mask
) != 0);
211 /* D(bug("Returning %d\n", state));
218 #define GfxBase (fi->gfxbase)
220 static BOOL
color_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
)
224 if (x
< 0 || y
< 0 || x
>= fi
->rp_width
|| y
>= fi
->rp_height
)
227 if (gettmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
))
229 /* D(bug("Pixel checked twice at (%d, %d)\n", x, y)); */
237 fill
= (fi
->fillpen
== ReadPixel(fi
->rp
, x
, y
));
243 static BOOL
outline_isfillable(struct fillinfo
*fi
, LONG x
, LONG y
)
246 /* EnterFunc(bug("outline_isfillable(fi=%p, x=%d, y=%d)\n",
249 if (x
< 0 || y
< 0 || x
>= fi
->rp_width
|| y
>= fi
->rp_height
)
252 if (gettmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
))
254 /* D(bug("Pixel checked twice at (%d, %d)\n", x, y)); */
262 fill
= (fi
->fillpen
!= ReadPixel(fi
->rp
, x
, y
));
265 /* D(bug("fillpen: %d, pen: %d\n", fi->fillpen, ReadPixel(fi->rp, x, y)));
268 /* ReturnBool("outline_isfillable", fill);
275 static VOID
putfillpixel(struct fillinfo
*fi
, LONG x
, LONG y
)
278 /* TODO: Implement use of patterns */
280 #ifdef USE_WRITEPIXEL
281 ULONG pixval
, set_pixel
= 0UL;
283 if (fi
->rp
->AreaPtrn
)
285 set_pixel
= pattern_pen(fi
->rp
294 pixval
= GetAPen(fi
->rp
);
300 SetAPen(fi
->rp
, pixval
);
301 WritePixel(fi
->rp
, x
, y
);
306 settmpraspixel(fi
->rasptr
, x
, y
, fi
->bpr
, 1);
314 #define STACKSIZE 100
325 static VOID
init_stack(struct stack
*s
)
330 static BOOL
push(struct stack
*s
, LONG x
, LONG y
)
332 if (s
->current
== STACKSIZE
)
335 s
->items
[s
->current
].x
= x
;
336 s
->items
[s
->current
].y
= y
;
344 static BOOL
pop(struct stack
*s
, LONG
*xptr
, LONG
*yptr
)
352 *xptr
= s
->items
[s
->current
].x
;
353 *yptr
= s
->items
[s
->current
].y
;
359 static BOOL
filline(struct fillinfo
*fi
, LONG start_x
, LONG start_y
)
363 LONG rightmost_above
, rightmost_below
;
364 LONG leftmost_above
, leftmost_below
;
367 EnterFunc(bug("filline(fi=%p, start_x=%d, start_y=%d)\n"
368 ,fi
, start_x
, start_y
));
375 rightmost_above
= start_x
;
376 rightmost_below
= start_x
;
378 for (x
= start_x
+ 1; ; x
++)
381 if (fi
->isfillable(fi
, x
, start_y
))
383 putfillpixel(fi
, x
, start_y
);
386 if (x
> rightmost_above
)
388 if (fi
->isfillable(fi
, x
, start_y
- 1))
390 /* Find rightmost pixel */
392 for (rightmost_above
= x
; ; rightmost_above
++)
394 if (!fi
->isfillable(fi
, rightmost_above
+ 1, start_y
- 1))
399 if (!push(&stack
, rightmost_above
, start_y
- 1))
400 ReturnBool("filline (stack full)", FALSE
);
401 /* filline(fi, rightmost_above, start_y - 1);
408 if (x
> rightmost_below
)
410 if (fi
->isfillable(fi
, x
, start_y
+ 1))
412 /* Find rightmost pixel */
414 for (rightmost_below
= x
; ; rightmost_below
++)
416 if (!fi
->isfillable(fi
, rightmost_below
+ 1, start_y
+ 1))
421 if (!push(&stack
, rightmost_below
, start_y
+ 1))
422 ReturnBool("filline (stack full)", FALSE
);
424 /* filline(fi, rightmost_below, start_y + 1);
433 } /* for (scan right) */
439 leftmost_above
= start_x
+ 1;
440 leftmost_below
= start_x
+ 1;
442 for (x
= start_x
; ; x
-- )
446 if (fi
->isfillable(fi
, x
, start_y
))
448 putfillpixel(fi
, x
, start_y
);
451 if (x
<= leftmost_above
)
453 if (fi
->isfillable(fi
, x
, start_y
- 1))
455 /* Find rightmost pixel */
457 for (leftmost_above
= x
; ; leftmost_above
--)
459 if (!fi
->isfillable(fi
, leftmost_above
- 1, start_y
- 1))
464 if (!push(&stack
, leftmost_above
, start_y
- 1))
465 ReturnBool("filline (stack full)", FALSE
);
466 /* filline(fi, leftmost_above, start_y - 1);
473 if (x
< leftmost_below
)
475 if (fi
->isfillable(fi
, x
, start_y
+ 1))
477 /* Find rightmost pixel */
479 for (leftmost_below
= x
; ; leftmost_below
--)
481 if (!fi
->isfillable(fi
, leftmost_below
- 1, start_y
+ 1))
486 if (!push(&stack
, leftmost_below
, start_y
+ 1))
487 ReturnBool("filline (stack full)", FALSE
);
489 /* filline(fi, leftmost_below, start_y + 1);
498 } /* for (scan left) */
501 if (!pop(&stack
, &start_x
, &start_y
))
503 D(bug("\t\t\tpop(%d, %d)\n", start_x
, start_y
));
507 ReturnBool("filline", TRUE
);