diff options
Diffstat (limited to 'engines/sci/gfx/resource/sci_picfill_aux.c')
-rw-r--r-- | engines/sci/gfx/resource/sci_picfill_aux.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/engines/sci/gfx/resource/sci_picfill_aux.c b/engines/sci/gfx/resource/sci_picfill_aux.c new file mode 100644 index 0000000000..70d8a822da --- /dev/null +++ b/engines/sci/gfx/resource/sci_picfill_aux.c @@ -0,0 +1,205 @@ +/*************************************************************************** + Copyright (C) 2004 Christoph Reichenbach <reichenb@colorado.edu> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public Licence as + published by the Free Software Foundaton; either version 2 of the + Licence, or (at your option) any later version. + + It is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + merchantibility or fitness for a particular purpose. See the + GNU General Public Licence for more details. + + You should have received a copy of the GNU General Public Licence + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +***************************************************************************/ + +/* Generic pic auxbuf filling code, to be included by sci_pic_0.c + * + * + * To use, define the following: + * AUXBUF_FILL: Name of the exported floodfill function + * AUXBUF_FILL_HELPER: Name of the helper function + * + * Define DRAW_SCALED to support scaled drawing, or leave it out for faster + * processing. + * + */ + +#define CLIPMASK_HARD_BOUND 0x80 /* ensures that we don't re-fill filled stuff */ + +static void +AUXBUF_FILL_HELPER(gfxr_pic_t *pic, int old_xl, int old_xr, int y, int dy, + int clipmask, int control, int sci_titlebar_size) +{ + int xl, xr; + int oldytotal = y * 320; +#ifdef DRAW_SCALED + unsigned const char fillmask = CLIPMASK_HARD_BOUND | 0x78; +#else + unsigned const char fillmask = CLIPMASK_HARD_BOUND | 0x84; +#endif + + do { + int ytotal = oldytotal + (320 * dy); + int xcont; + int state; + + y += dy; + + if (y < sci_titlebar_size || y > 199) + return; + + xl = old_xl; + if (!(pic->aux_map[ytotal + xl] & clipmask)) { /* go left */ + while (xl && !(pic->aux_map[ytotal + xl - 1] & clipmask)) + --xl; + } else /* go right and look for the first valid spot */ + while ((xl <= old_xr) && (pic->aux_map[ytotal + xl] & clipmask)) + ++xl; + + if (xl > old_xr) /* No fillable strip above the last one */ + return; + + if ((ytotal + xl) < 0) { fprintf(stderr,"AARGH-%d\n", __LINE__); BREAKPOINT(); } + + xr = xl; + while (xr < 320 && !(pic->aux_map[ytotal + xr] & clipmask)) { + pic->aux_map[ytotal + xr] |= fillmask; + ++xr; + } + + if ((ytotal + xr) > 64000) { fprintf(stderr,"AARGH-%d\n", __LINE__); + BREAKPOINT(); + } + + --xr; + + if (xr < xl) + return; + + /* Check whether we need to recurse on branches in the same direction */ + if ((y > sci_titlebar_size && dy < 0) + || (y < 199 && dy > 0)) { + + state = 0; + xcont = xr + 1; + while (xcont <= old_xr) { + if (pic->aux_map[ytotal + xcont] & clipmask) + state = 0; + else if (!state) { /* recurse */ + state = 1; + AUXBUF_FILL_HELPER(pic, xcont, old_xr, + y - dy, dy, clipmask, control, sci_titlebar_size); + } + ++xcont; + } + } + + /* Check whether we need to recurse on backward branches: */ + /* left */ + if (xl < old_xl - 1) { + state = 0; + for (xcont = old_xl - 1; xcont >= xl; xcont--) { + if (pic->aux_map[oldytotal + xcont] & clipmask) + state = xcont; + else if (state) { /* recurse */ + AUXBUF_FILL_HELPER(pic, xcont, state, + y, -dy, clipmask, control, sci_titlebar_size); + state = 0; + } + } + } + + /* right */ + if (xr > old_xr + 1) { + state = 0; + for (xcont = old_xr + 1; xcont <= xr; xcont++) { + if (pic->aux_map[oldytotal + xcont] & clipmask) + state = xcont; + else if (state) { /* recurse */ + AUXBUF_FILL_HELPER(pic, state, xcont, + y, -dy, clipmask, control, sci_titlebar_size); + state = 0; + } + } + } + + if ((ytotal + xl) < 0) { fprintf(stderr,"AARGH-%d\n", __LINE__); BREAKPOINT() } + if ((ytotal + xr+1) > 64000) { fprintf(stderr,"AARGH-%d\n", __LINE__); BREAKPOINT(); } + + if (control) + memset(pic->control_map->index_data + ytotal + xl, control, xr-xl+1); + + oldytotal = ytotal; + old_xr = xr; + old_xl = xl; + + } while (1); +} + + +static void +AUXBUF_FILL(gfxr_pic_t *pic, int x, int y, int clipmask, int control, int sci_titlebar_size) +{ + /* Fills the aux buffer and the control map (if control != 0) */ + int xl, xr; + int ytotal = y * 320; +#ifdef DRAW_SCALED + unsigned const char fillmask = 0x78; +#else + unsigned const char fillmask = 0x4; +#endif + +#ifndef DRAW_SCALED + if (!control || !(clipmask & 4)) + return; /* Without pic scaling, we only do this to fill the control map */ +#endif + + if (clipmask & 1) + clipmask = 1; /* vis */ + else if (clipmask & 2) + clipmask = 2; /* pri */ + else if (clipmask & 4) + clipmask = 4; /* ctl */ + else return; + +#ifdef DRAW_SCALED + clipmask |= fillmask; /* Bits 3-5 */ +#endif + + if (pic->aux_map[ytotal + x] & clipmask) + return; + + pic->aux_map[ytotal + x] |= fillmask; + + xl = x; + while (xl && !(pic->aux_map[ytotal + xl - 1] & clipmask)) { + --xl; + pic->aux_map[ytotal + xl] |= fillmask; + } + + xr = x; + while ((xr < 319) && !(pic->aux_map[ytotal + xr + 1] & clipmask)) { + ++xr; + pic->aux_map[ytotal + xr] |= fillmask; + } + + clipmask |= CLIPMASK_HARD_BOUND; /* Guarantee clipping */ + + if (control) /* Draw the same strip on the control map */ + memset(pic->control_map->index_data + ytotal + xl, control, xr - xl + 1); + + if (y > sci_titlebar_size) + AUXBUF_FILL_HELPER(pic, xl, xr, y, -1, clipmask, control, sci_titlebar_size); + + if (y < 199) + AUXBUF_FILL_HELPER(pic, xl, xr, y, +1, clipmask, control, sci_titlebar_size); +} + + +#undef CLIPMASK_HARD_BOUND |