From 60297cb9fa51dcc2c145fa9aeb86a924c59c8b76 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 3 Jun 2016 16:39:03 +0200 Subject: GRAPHICS: Add mask mode to FloodFill class and document the class. --- graphics/surface.cpp | 42 +++++++++++++++++++++++++++++++++++------- graphics/surface.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/graphics/surface.cpp b/graphics/surface.cpp index 2fe6a73010..c5d4cf0cbd 100644 --- a/graphics/surface.cpp +++ b/graphics/surface.cpp @@ -505,6 +505,9 @@ FloodFill::FloodFill(Graphics::Surface *surface, uint32 oldColor, uint32 fillCol _w = surface->w; _h = surface->h; + _mask = nullptr; + _maskMode = false; + _visited = (byte *)calloc(_w * _h, 1); } @@ -517,28 +520,45 @@ FloodFill::~FloodFill() { } free(_visited); + + if (_mask) + delete _mask; } void FloodFill::addSeed(int x, int y) { if (x >= 0 && x < _w && y >= 0 && y < _h) { if (!_visited[y * _w + x]) { _visited[y * _w + x] = 1; - void *p = _surface->getBasePtr(x, y); + void *src = _surface->getBasePtr(x, y); + void *dst; bool changed = false; + if (_maskMode) + dst = _mask->getBasePtr(x, y); + else + dst = src; + if (_surface->format.bytesPerPixel == 1) { - if (*((byte *)p) == _oldColor) { - *((byte *)p) = _fillColor; + if (*((byte *)src) == _oldColor) { + *((byte *)dst) = _maskMode ? 255 : _fillColor; changed = true; } } else if (_surface->format.bytesPerPixel == 2) { - if (READ_UINT16(p) == _oldColor) { - WRITE_UINT16(p, _fillColor); + if (READ_UINT16(src) == _oldColor) { + if (!_maskMode) + WRITE_UINT16(src, _fillColor); + else + *((byte *)dst) = 255; + changed = true; } } else if (_surface->format.bytesPerPixel == 4) { - if (READ_UINT32(p) == _oldColor) { - WRITE_UINT32(p, _fillColor); + if (READ_UINT32(src) == _oldColor) { + if (!_maskMode) + WRITE_UINT32(src, _fillColor); + else + *((byte *)dst) = 255; + changed = true; } } else { @@ -567,4 +587,12 @@ void FloodFill::fill() { } } +void FloodFill::fillMask() { + _mask = new Graphics::Surface(); + _mask->create(_w, _h, Graphics::PixelFormat::createFormatCLUT8()); // Uses calloc() + _maskMode = true; + + fill(); +} + } // End of namespace Graphics diff --git a/graphics/surface.h b/graphics/surface.h index e5685bf997..414a734683 100644 --- a/graphics/surface.h +++ b/graphics/surface.h @@ -343,19 +343,71 @@ struct SharedPtrSurfaceDeleter { } }; +/** + * Stack-based flood fill algorithm for arbitrary Surfaces. + * + * It could be used in 2 ways. One is to fill the pixels of oldColor + * with fillColor. Second is when the surface stays intact but another + * surface with mask is created, where filled colors are marked with 255. + * + * Before running fill() or fillMask(), the initial pixels must be addSeed + * with addSeed() method. + */ class FloodFill { public: + /** + * Construct a simple Surface object. + * + * @param surface Input surface + * @param oldColor Color on the surface to change + * @param fillColor Color to fill with + */ FloodFill(Surface *surface, uint32 oldColor, uint32 fillColor); ~FloodFill(); + + /** + * Add pixels to the fill queue. + * + * @param x The x coordinate of the pixel. + * @param y The x coordinate of the pixel. + */ void addSeed(int x, int y); + + /** + * Fill the surface as requested. + * + * It uses pixels which were added with addSeed() method. + * + * @see addSeed + */ void fill(); + /** + * Fill the mask. The mask is a CLUT8 Surface with pixels 0 and 255. + * 255 means that the pixel has been filled. + * + * It uses pixels which were added with addSeed() method. + * + * @see addSeed + */ + void fillMask(); + + /** + * Get the resulting mask. + * + * @see fillMask + */ + Surface *getMask() { return _mask; } + private: Common::List _queue; Surface *_surface; + Surface *_mask; uint32 _oldColor, _fillColor; byte *_visited; int _w, _h; + + bool _maskMode; }; } // End of namespace Graphics -- cgit v1.2.3