aboutsummaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/nine_patch.cpp8
-rw-r--r--graphics/surface.cpp105
-rw-r--r--graphics/surface.h68
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