diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/nine_patch.cpp | 8 | ||||
-rw-r--r-- | graphics/surface.cpp | 105 | ||||
-rw-r--r-- | graphics/surface.h | 68 |
3 files changed, 177 insertions, 4 deletions
diff --git a/graphics/nine_patch.cpp b/graphics/nine_patch.cpp index fea0d8ae66..a193200208 100644 --- a/graphics/nine_patch.cpp +++ b/graphics/nine_patch.cpp @@ -59,13 +59,13 @@ NinePatchSide::~NinePatchSide() { bool NinePatchSide::init(Graphics::TransparentSurface *bmp, bool vertical) { - const int len = vertical ? bmp->h : bmp->w; - int i; - int s, t, n, z; + const uint len = vertical ? bmp->h : bmp->w; + uint i; + int s, t, z; _m.clear(); - for (i = 1, s = -1, t = 0, n = 0, z = -1; i < len; ++i) { + for (i = 1, s = -1, t = 0, z = -1; i < len; ++i) { int zz; uint8 r, g, b, a; uint32 *color = vertical ? (uint32 *)bmp->getBasePtr(0, i) : (uint32 *)bmp->getBasePtr(i, 0); diff --git a/graphics/surface.cpp b/graphics/surface.cpp index 67ed942b0b..699e1ccd22 100644 --- a/graphics/surface.cpp +++ b/graphics/surface.cpp @@ -498,4 +498,109 @@ Graphics::Surface *Surface::convertTo(const PixelFormat &dstFormat, const byte * return surface; } +FloodFill::FloodFill(Graphics::Surface *surface, uint32 oldColor, uint32 fillColor, bool maskMode) { + _surface = surface; + _oldColor = oldColor; + _fillColor = fillColor; + _w = surface->w; + _h = surface->h; + + _mask = nullptr; + _maskMode = maskMode; + + if (_maskMode) { + _mask = new Graphics::Surface(); + _mask->create(_w, _h, Graphics::PixelFormat::createFormatCLUT8()); // Uses calloc() + } + + _visited = (byte *)calloc(_w * _h, 1); +} + +FloodFill::~FloodFill() { + while(!_queue.empty()) { + Common::Point *p = _queue.front(); + + delete p; + _queue.pop_front(); + } + + 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 *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 *)src) == _oldColor) { + *((byte *)dst) = _maskMode ? 255 : _fillColor; + changed = true; + } + } else if (_surface->format.bytesPerPixel == 2) { + 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(src) == _oldColor) { + if (!_maskMode) + WRITE_UINT32(src, _fillColor); + else + *((byte *)dst) = 255; + + changed = true; + } + } else { + error("Unsupported bpp in FloodFill"); + } + + if (changed) { + Common::Point *pt = new Common::Point(x, y); + + _queue.push_back(pt); + } + } + } +} + +void FloodFill::fill() { + while (!_queue.empty()) { + Common::Point *p = _queue.front(); + _queue.pop_front(); + addSeed(p->x , p->y - 1); + addSeed(p->x - 1, p->y ); + addSeed(p->x , p->y + 1); + addSeed(p->x + 1, p->y ); + + delete p; + } +} + +void FloodFill::fillMask() { + _maskMode = true; + + if (!_mask) { + _mask = new Graphics::Surface(); + _mask->create(_w, _h, Graphics::PixelFormat::createFormatCLUT8()); // Uses calloc() + } + + fill(); +} + } // End of namespace Graphics diff --git a/graphics/surface.h b/graphics/surface.h index aaa386b168..87c5f52503 100644 --- a/graphics/surface.h +++ b/graphics/surface.h @@ -24,9 +24,11 @@ #define GRAPHICS_SURFACE_H #include "common/scummsys.h" +#include "common/list.h" namespace Common { struct Rect; +struct Point; } #include "graphics/pixelformat.h" @@ -341,6 +343,72 @@ 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, bool maskMode = false); + ~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<Common::Point *> _queue; + Surface *_surface; + Surface *_mask; + uint32 _oldColor, _fillColor; + byte *_visited; + int _w, _h; + + bool _maskMode; +}; } // End of namespace Graphics |