Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trastercm.h"
Toshihiro Shimizu 890ddd
#include "toonz/fill.h"
Toshihiro Shimizu 890ddd
#include "toonz/ttilesaver.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
#include <stack></stack>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{ // Utility Function
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TPoint nearestInkNotDiagonal(const TRasterCM32P &r, const TPoint &p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixelCM32 *buf = (TPixelCM32 *)r->pixels(p.y) + p.x;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (p.x < r->getLx() - 1 && (!(buf + 1)->isPurePaint()))
Toshihiro Shimizu 890ddd
		return TPoint(p.x + 1, p.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (p.x > 0 && (!(buf - 1)->isPurePaint()))
Toshihiro Shimizu 890ddd
		return TPoint(p.x - 1, p.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (p.y < r->getLy() - 1 && (!(buf + r->getWrap())->isPurePaint()))
Toshihiro Shimizu 890ddd
		return TPoint(p.x, p.y + 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (p.y > 0 && (!(buf - r->getWrap())->isPurePaint()))
Toshihiro Shimizu 890ddd
		return TPoint(p.x, p.y - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TPoint(-1, -1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// dal punto x,y si espande a destra e a sinistra.
Toshihiro Shimizu 890ddd
// la riga ridisegnata va da *xa a *xb compresi
Toshihiro Shimizu 890ddd
// x1 <= *xa <= *xb <= x2
Toshihiro Shimizu 890ddd
// N.B. se non viene disegnato neanche un pixel *xa>*xb
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void fillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, int paint, TPalette *palette,
Toshihiro Shimizu 890ddd
			 TTileSaverCM32 *saver)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int tone, oldtone;
Toshihiro Shimizu 890ddd
	TPixelCM32 *pix, *pix0, *limit, *tmp_limit;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* vai a destra */
Toshihiro Shimizu 890ddd
	TPixelCM32 *line = r->pixels(p.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pix0 = line + p.x;
Toshihiro Shimizu 890ddd
	pix = pix0;
Toshihiro Shimizu 890ddd
	limit = line + r->getBounds().x1;
Toshihiro Shimizu 890ddd
	oldtone = pix->getTone();
Toshihiro Shimizu 890ddd
	tone = oldtone;
Toshihiro Shimizu 890ddd
	for (; pix <= limit; pix++) {
Toshihiro Shimizu 890ddd
		if (pix->getPaint() == paint)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		tone = pix->getTone();
Toshihiro Shimizu 890ddd
		if (tone > oldtone || tone == 0)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		oldtone = tone;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (tone == 0) {
Toshihiro Shimizu 890ddd
		tmp_limit = pix + 10; //edge stop fill == 10 per default
Toshihiro Shimizu 890ddd
		if (limit > tmp_limit)
Toshihiro Shimizu 890ddd
			limit = tmp_limit;
Toshihiro Shimizu 890ddd
		for (; pix <= limit; pix++) {
Toshihiro Shimizu 890ddd
			if (pix->getPaint() == paint)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			if (pix->getTone() != 0)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xb = p.x + pix - pix0 - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* vai a sinistra */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pix = pix0;
Toshihiro Shimizu 890ddd
	limit = line + r->getBounds().x0;
Toshihiro Shimizu 890ddd
	oldtone = pix->getTone();
Toshihiro Shimizu 890ddd
	tone = oldtone;
Toshihiro Shimizu 890ddd
	for (pix--; pix >= limit; pix--) {
Toshihiro Shimizu 890ddd
		if (pix->getPaint() == paint)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		tone = pix->getTone();
Toshihiro Shimizu 890ddd
		if (tone > oldtone || tone == 0)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		oldtone = tone;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (tone == 0) {
Toshihiro Shimizu 890ddd
		tmp_limit = pix - 10;
Toshihiro Shimizu 890ddd
		if (limit < tmp_limit)
Toshihiro Shimizu 890ddd
			limit = tmp_limit;
Toshihiro Shimizu 890ddd
		for (; pix >= limit; pix--) {
Toshihiro Shimizu 890ddd
			if (pix->getPaint() == paint)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			if (pix->getTone() != 0)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xa = p.x + pix - pix0 + 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (saver)
Toshihiro Shimizu 890ddd
		saver->save(TRect(xa, p.y, xb, p.y));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (xb >= xa) {
Toshihiro Shimizu 890ddd
		pix = line + xa;
Toshihiro Shimizu 890ddd
		int n;
Toshihiro Shimizu 890ddd
		for (n = 0; n < xb - xa + 1; n++, pix++) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (palette && pix->isPurePaint()) {
Toshihiro Shimizu 890ddd
				TPoint pInk = nearestInkNotDiagonal(r, TPoint(xa + n, p.y));
Toshihiro Shimizu 890ddd
				if (pInk != TPoint(-1, -1)) {
Toshihiro Shimizu 890ddd
					TPixelCM32 *pixInk = (TPixelCM32 *)r->getRawData() + (pInk.y * r->getWrap() + pInk.x);
Toshihiro Shimizu 890ddd
					if (pixInk->getInk() != paint && palette->getStyle(pixInk->getInk())->getFlags() != 0)
Toshihiro Shimizu 890ddd
						inkFill(r, pInk, paint, 0, saver);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			pix->setPaint(paint);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void findSegment(const TRaster32P &r, const TPoint &p, int &xa, int &xb, const TPixel32 &color)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int matte, oldmatte;
Toshihiro Shimizu 890ddd
	TPixel32 *pix, *pix0, *limit, *tmp_limit;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* vai a destra */
Toshihiro Shimizu 890ddd
	TPixel32 *line = r->pixels(p.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pix0 = line + p.x;
Toshihiro Shimizu 890ddd
	pix = pix0;
Toshihiro Shimizu 890ddd
	limit = line + r->getBounds().x1;
Toshihiro Shimizu 890ddd
	oldmatte = pix->m;
Toshihiro Shimizu 890ddd
	matte = oldmatte;
Toshihiro Shimizu 890ddd
	for (; pix <= limit; pix++) {
Toshihiro Shimizu 890ddd
		if (*pix == color)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		matte = pix->m;
Toshihiro Shimizu 890ddd
		if (matte < oldmatte || matte == 255)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		oldmatte = matte;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (matte == 0) {
Toshihiro Shimizu 890ddd
		tmp_limit = pix + 10; //edge stop fill == 10 per default
Toshihiro Shimizu 890ddd
		if (limit > tmp_limit)
Toshihiro Shimizu 890ddd
			limit = tmp_limit;
Toshihiro Shimizu 890ddd
		for (; pix <= limit; pix++) {
Toshihiro Shimizu 890ddd
			if (*pix == color)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			if (pix->m != 255)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	xb = p.x + pix - pix0 - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* vai a sinistra */
Toshihiro Shimizu 890ddd
	pix = pix0;
Toshihiro Shimizu 890ddd
	limit = line + r->getBounds().x0;
Toshihiro Shimizu 890ddd
	oldmatte = pix->m;
Toshihiro Shimizu 890ddd
	matte = oldmatte;
Toshihiro Shimizu 890ddd
	for (; pix >= limit; pix--) {
Toshihiro Shimizu 890ddd
		if (*pix == color)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		matte = pix->m;
Toshihiro Shimizu 890ddd
		if (matte < oldmatte || matte == 255)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		oldmatte = matte;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (matte == 0) {
Toshihiro Shimizu 890ddd
		tmp_limit = pix - 10;
Toshihiro Shimizu 890ddd
		if (limit < tmp_limit)
Toshihiro Shimizu 890ddd
			limit = tmp_limit;
Toshihiro Shimizu 890ddd
		for (; pix >= limit; pix--) {
Toshihiro Shimizu 890ddd
			if (*pix == color)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			if (pix->m != 255)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	xa = p.x + pix - pix0 + 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class FillSeed
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	int m_xa, m_xb;
Toshihiro Shimizu 890ddd
	int m_y, m_dy;
Toshihiro Shimizu 890ddd
	FillSeed(int xa, int xb, int y, int dy)
Toshihiro Shimizu 890ddd
		: m_xa(xa), m_xb(xb), m_y(y), m_dy(dy) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline int threshTone(const TPixelCM32 &pix, int fillDepth)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fillDepth == TPixelCM32::getMaxTone())
Toshihiro Shimizu 890ddd
		return pix.getTone();
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return ((pix.getTone()) > fillDepth) ? TPixelCM32::getMaxTone() : pix.getTone();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline int threshMatte(int matte, int fillDepth)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fillDepth == 255)
Toshihiro Shimizu 890ddd
		return matte;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return (matte < fillDepth) ? 255 : matte;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool isPixelInSegment(const vector<pair<int, int="">> &segments, int x)</pair<int,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (int i = 0; i < (int)segments.size(); i++) {
Toshihiro Shimizu 890ddd
		pair<int, int=""> segment = segments[i];</int,>
Toshihiro Shimizu 890ddd
		if (segment.first <= x && x <= segment.second)
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void insertSegment(vector<pair<int, int="">> &segments, const pair<int, int=""> segment)</int,></pair<int,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (int i = segments.size() - 1; i >= 0; i--) {
Toshihiro Shimizu 890ddd
		pair<int, int=""> app = segments[i];</int,>
Toshihiro Shimizu 890ddd
		if (segment.first <= app.first && app.second <= segment.second)
Toshihiro Shimizu 890ddd
			segments.erase(segments.begin() + i);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	segments.push_back(segment);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
} //namespace
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*-- 戻り値はsaveBoxが更新されたかどうか --*/
Toshihiro Shimizu 890ddd
bool fill(const TRasterCM32P &r, const FillParameters ¶ms, TTileSaverCM32 *saver)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixelCM32 *pix, *limit, *pix0, *oldpix;
Toshihiro Shimizu 890ddd
	int oldy, xa, xb, xc, xd, dy;
Toshihiro Shimizu 890ddd
	int oldxc, oldxd;
Toshihiro Shimizu 890ddd
	int tone, oldtone;
Toshihiro Shimizu 890ddd
	TPoint p = params.m_p;
Toshihiro Shimizu 890ddd
	int x = p.x, y = p.y;
Toshihiro Shimizu 890ddd
	int paint = params.m_styleId;
Toshihiro Shimizu 890ddd
	int fillDepth = params.m_shiftFill ? params.m_maxFillDepth : params.m_minFillDepth;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*-- getBoundsは画像全面 --*/
Toshihiro Shimizu 890ddd
	TRect bbbox = r->getBounds();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*- 画面外のクリックの場合はreturn -*/
Toshihiro Shimizu 890ddd
	if (!bbbox.contains(p))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	/*- 既に同じ色が塗られている場合はreturn -*/
Toshihiro Shimizu 890ddd
	if ((r->pixels(p.y) + p.x)->getPaint() == paint)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	/*- 「透明部分だけを塗る」オプションが有効で、既に色が付いている場合はreturn -*/
Toshihiro Shimizu 890ddd
	if (params.m_emptyOnly && (r->pixels(p.y) + p.x)->getPaint() != 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(fillDepth >= 0 && fillDepth < 16);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (TPixelCM32::getMaxTone()) {
Toshihiro Shimizu 890ddd
	case 15:
Toshihiro Shimizu 890ddd
		fillDepth = (15 - fillDepth);
Toshihiro Shimizu 890ddd
		CASE 255 : fillDepth = ((15 - fillDepth) << 4) | (15 - fillDepth);
Toshihiro Shimizu 890ddd
	DEFAULT:
Toshihiro Shimizu 890ddd
		assert(false);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*-- 四隅の色を見て、一つでも変わったらsaveBoxを更新する --*/
Toshihiro Shimizu 890ddd
	TPixelCM32 borderIndex[4];
Toshihiro Shimizu 890ddd
	TPixelCM32 *borderPix[4];
Toshihiro Shimizu 890ddd
	pix = r->pixels(0);
Toshihiro Shimizu 890ddd
	borderPix[0] = pix;
Toshihiro Shimizu 890ddd
	borderIndex[0] = *pix;
Toshihiro Shimizu 890ddd
	pix += r->getLx() - 1;
Toshihiro Shimizu 890ddd
	borderPix[1] = pix;
Toshihiro Shimizu 890ddd
	borderIndex[1] = *pix;
Toshihiro Shimizu 890ddd
	pix = r->pixels(r->getLy() - 1);
Toshihiro Shimizu 890ddd
	borderPix[2] = pix;
Toshihiro Shimizu 890ddd
	borderIndex[2] = *pix;
Toshihiro Shimizu 890ddd
	pix += r->getLx() - 1;
Toshihiro Shimizu 890ddd
	borderPix[3] = pix;
Toshihiro Shimizu 890ddd
	borderIndex[3] = *pix;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::stack<fillseed> seeds;</fillseed>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fillRow(r, p, xa, xb, paint, params.m_palette, saver);
Toshihiro Shimizu 890ddd
	seeds.push(FillSeed(xa, xb, y, 1));
Toshihiro Shimizu 890ddd
	seeds.push(FillSeed(xa, xb, y, -1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (!seeds.empty()) {
Toshihiro Shimizu 890ddd
		FillSeed fs = seeds.top();
Toshihiro Shimizu 890ddd
		seeds.pop();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		xa = fs.m_xa;
Toshihiro Shimizu 890ddd
		xb = fs.m_xb;
Toshihiro Shimizu 890ddd
		oldy = fs.m_y;
Toshihiro Shimizu 890ddd
		dy = fs.m_dy;
Toshihiro Shimizu 890ddd
		y = oldy + dy;
Toshihiro Shimizu 890ddd
		if (y > bbbox.y1 || y < bbbox.y0)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		pix = pix0 = r->pixels(y) + xa;
Toshihiro Shimizu 890ddd
		limit = r->pixels(y) + xb;
Toshihiro Shimizu 890ddd
		oldpix = r->pixels(oldy) + xa;
Toshihiro Shimizu 890ddd
		x = xa;
Toshihiro Shimizu 890ddd
		oldxd = (std::numeric_limits<int>::min)();</int>
Toshihiro Shimizu 890ddd
		oldxc = (std::numeric_limits<int>::max)();</int>
Toshihiro Shimizu 890ddd
		while (pix <= limit) {
Toshihiro Shimizu 890ddd
			oldtone = threshTone(*oldpix, fillDepth);
Toshihiro Shimizu 890ddd
			tone = threshTone(*pix, fillDepth);
Toshihiro Shimizu 890ddd
			if (pix->getPaint() != paint && tone <= oldtone && tone != 0) {
Toshihiro Shimizu 890ddd
				fillRow(r, TPoint(x, y), xc, xd, paint, params.m_palette, saver);
Toshihiro Shimizu 890ddd
				if (xc < xa)
Toshihiro Shimizu 890ddd
					seeds.push(FillSeed(xc, xa - 1, y, -dy));
Toshihiro Shimizu 890ddd
				if (xd > xb)
Toshihiro Shimizu 890ddd
					seeds.push(FillSeed(xb + 1, xd, y, -dy));
Toshihiro Shimizu 890ddd
				if (oldxd >= xc - 1)
Toshihiro Shimizu 890ddd
					oldxd = xd;
Toshihiro Shimizu 890ddd
				else {
Toshihiro Shimizu 890ddd
					if (oldxd >= 0)
Toshihiro Shimizu 890ddd
						seeds.push(FillSeed(oldxc, oldxd, y, dy));
Toshihiro Shimizu 890ddd
					oldxc = xc;
Toshihiro Shimizu 890ddd
					oldxd = xd;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				pix += xd - x + 1;
Toshihiro Shimizu 890ddd
				oldpix += xd - x + 1;
Toshihiro Shimizu 890ddd
				x += xd - x + 1;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				pix++;
Toshihiro Shimizu 890ddd
				oldpix++, x++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (oldxd > 0)
Toshihiro Shimizu 890ddd
			seeds.push(FillSeed(oldxc, oldxd, y, dy));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool saveBoxChanged = false;
Toshihiro Shimizu 890ddd
	for (int i = 0; i < 4; i++) {
Toshihiro Shimizu 890ddd
		if (!((*borderPix[i]) == borderIndex[i])) {
Toshihiro Shimizu 890ddd
			saveBoxChanged = true;
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return saveBoxChanged;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void fill(const TRaster32P &ras, const TRaster32P &ref, const FillParameters ¶ms, TTileSaverFullColor *saver)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixel32 *pix, *limit, *pix0, *oldpix;
Toshihiro Shimizu 890ddd
	int oldy, xa, xb, xc, xd, dy;
Toshihiro Shimizu 890ddd
	int oldxc, oldxd;
Toshihiro Shimizu 890ddd
	int matte, oldMatte;
Toshihiro Shimizu 890ddd
	int x = params.m_p.x, y = params.m_p.y;
Toshihiro Shimizu 890ddd
	TRaster32P workRas = ref ? ref : ras;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRect bbbox = workRas->getBounds();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!bbbox.contains(params.m_p))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPaletteP plt = params.m_palette;
Toshihiro Shimizu 890ddd
	TPixel32 color = plt->getStyle(params.m_styleId)->getMainColor();
Toshihiro Shimizu 890ddd
	int fillDepth = params.m_shiftFill ? params.m_maxFillDepth : params.m_minFillDepth;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(fillDepth >= 0 && fillDepth < 16);
Toshihiro Shimizu 890ddd
	fillDepth = ((15 - fillDepth) << 4) | (15 - fillDepth);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//looking for any  pure transparent pixel along the border; if after filling that pixel will be changed,
Toshihiro Shimizu 890ddd
	//it means that I filled the bg and the savebox needs to be recomputed!
Toshihiro Shimizu 890ddd
	TPixel32 borderIndex;
Toshihiro Shimizu 890ddd
	TPixel32 *borderPix = 0;
Toshihiro Shimizu 890ddd
	pix = workRas->pixels(0);
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < workRas->getLx(); i++, pix++) //border down
Toshihiro Shimizu 890ddd
		if (pix->m == 0) {
Toshihiro Shimizu 890ddd
			borderIndex = *pix;
Toshihiro Shimizu 890ddd
			borderPix = pix;
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	if (borderPix == 0) //not found in border down...try border up (avoid left and right borders...so unlikely)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		pix = workRas->pixels(workRas->getLy() - 1);
Toshihiro Shimizu 890ddd
		for (i = 0; i < workRas->getLx(); i++, pix++) //border up
Toshihiro Shimizu 890ddd
			if (pix->m == 0) {
Toshihiro Shimizu 890ddd
				borderIndex = *pix;
Toshihiro Shimizu 890ddd
				borderPix = pix;
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::stack<fillseed> seeds;</fillseed>
Toshihiro Shimizu 890ddd
	std::map<int, int="" vector<std::pair<int,="">>> segments;</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//fillRow(r, params.m_p, xa, xb, color ,saver);
Toshihiro Shimizu 890ddd
	findSegment(workRas, params.m_p, xa, xb, color);
Toshihiro Shimizu 890ddd
	segments[y].push_back(std::pair<int, int="">(xa, xb));</int,>
Toshihiro Shimizu 890ddd
	seeds.push(FillSeed(xa, xb, y, 1));
Toshihiro Shimizu 890ddd
	seeds.push(FillSeed(xa, xb, y, -1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (!seeds.empty()) {
Toshihiro Shimizu 890ddd
		FillSeed fs = seeds.top();
Toshihiro Shimizu 890ddd
		seeds.pop();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		xa = fs.m_xa;
Toshihiro Shimizu 890ddd
		xb = fs.m_xb;
Toshihiro Shimizu 890ddd
		oldy = fs.m_y;
Toshihiro Shimizu 890ddd
		dy = fs.m_dy;
Toshihiro Shimizu 890ddd
		y = oldy + dy;
Toshihiro Shimizu 890ddd
		if (y > bbbox.y1 || y < bbbox.y0)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		pix = pix0 = workRas->pixels(y) + xa;
Toshihiro Shimizu 890ddd
		limit = workRas->pixels(y) + xb;
Toshihiro Shimizu 890ddd
		oldpix = workRas->pixels(oldy) + xa;
Toshihiro Shimizu 890ddd
		x = xa;
Toshihiro Shimizu 890ddd
		oldxd = (std::numeric_limits<int>::min)();</int>
Toshihiro Shimizu 890ddd
		oldxc = (std::numeric_limits<int>::max)();</int>
Toshihiro Shimizu 890ddd
		while (pix <= limit) {
Toshihiro Shimizu 890ddd
			oldMatte = threshMatte(oldpix->m, fillDepth);
Toshihiro Shimizu 890ddd
			matte = threshMatte(pix->m, fillDepth);
Toshihiro Shimizu 890ddd
			bool test = false;
Toshihiro Shimizu 890ddd
			if (segments.find(y) != segments.end())
Toshihiro Shimizu 890ddd
				test = isPixelInSegment(segments[y], x);
Toshihiro Shimizu 890ddd
			if (*pix != color && !test && matte >= oldMatte && matte != 255) {
Toshihiro Shimizu 890ddd
				findSegment(workRas, TPoint(x, y), xc, xd, color);
Toshihiro Shimizu 890ddd
				//segments[y].push_back(std::pair<int,int>(xc, xd));</int,int>
Toshihiro Shimizu 890ddd
				insertSegment(segments[y], pair<int, int="">(xc, xd));</int,>
Toshihiro Shimizu 890ddd
				if (xc < xa)
Toshihiro Shimizu 890ddd
					seeds.push(FillSeed(xc, xa - 1, y, -dy));
Toshihiro Shimizu 890ddd
				if (xd > xb)
Toshihiro Shimizu 890ddd
					seeds.push(FillSeed(xb + 1, xd, y, -dy));
Toshihiro Shimizu 890ddd
				if (oldxd >= xc - 1)
Toshihiro Shimizu 890ddd
					oldxd = xd;
Toshihiro Shimizu 890ddd
				else {
Toshihiro Shimizu 890ddd
					if (oldxd >= 0)
Toshihiro Shimizu 890ddd
						seeds.push(FillSeed(oldxc, oldxd, y, dy));
Toshihiro Shimizu 890ddd
					oldxc = xc;
Toshihiro Shimizu 890ddd
					oldxd = xd;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				pix += xd - x + 1;
Toshihiro Shimizu 890ddd
				oldpix += xd - x + 1;
Toshihiro Shimizu 890ddd
				x += xd - x + 1;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				pix++;
Toshihiro Shimizu 890ddd
				oldpix++, x++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (oldxd > 0)
Toshihiro Shimizu 890ddd
			seeds.push(FillSeed(oldxc, oldxd, y, dy));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map<int, int="" vector<std::pair<int,="">>>::iterator it;</int,>
Toshihiro Shimizu 890ddd
	for (it = segments.begin(); it != segments.end(); it++) {
Toshihiro Shimizu 890ddd
		TPixel32 *line = ras->pixels(it->first);
Toshihiro Shimizu 890ddd
		TPixel32 *refLine = 0;
Toshihiro Shimizu 890ddd
		TPixel32 *refPix;
Toshihiro Shimizu 890ddd
		if (ref)
Toshihiro Shimizu 890ddd
			refLine = ref->pixels(it->first);
Toshihiro Shimizu 890ddd
		vector<std::pair<int, int="">> segmentVector = it->second;</std::pair<int,>
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)segmentVector.size(); i++) {
Toshihiro Shimizu 890ddd
			std::pair<int, int=""> segment = segmentVector[i];</int,>
Toshihiro Shimizu 890ddd
			if (segment.second >= segment.first) {
Toshihiro Shimizu 890ddd
				pix = line + segment.first;
Toshihiro Shimizu 890ddd
				if (ref)
Toshihiro Shimizu 890ddd
					refPix = refLine + segment.first;
Toshihiro Shimizu 890ddd
				int n;
Toshihiro Shimizu 890ddd
				for (n = 0; n < segment.second - segment.first + 1; n++, pix++) {
Toshihiro Shimizu 890ddd
					if (ref) {
Toshihiro Shimizu 890ddd
						*pix = *refPix;
Toshihiro Shimizu 890ddd
						refPix++;
Toshihiro Shimizu 890ddd
					} else
Toshihiro Shimizu 890ddd
						*pix = pix->m == 0 ? color : overPix(color, *pix);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void rectFill(const TRaster32P &ras, const TRect &r, const TPixel32 &color)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPoint nearestInk(const TRasterCM32P &r, const TPoint &p, int ray)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i, j;
Toshihiro Shimizu 890ddd
	TPixelCM32 *buf = (TPixelCM32 *)r->getRawData();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (j = tmax(p.y - ray, 0); j <= tmin(p.y + ray, r->getLy() - 1); j++)
Toshihiro Shimizu 890ddd
		for (i = tmax(p.x - ray, 0); i <= tmin(p.x + ray, r->getLx() - 1); i++)
Toshihiro Shimizu 890ddd
			if (!(buf + j * r->getWrap() + i)->isPurePaint())
Toshihiro Shimizu 890ddd
				return TPoint(i, j);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TPoint(-1, -1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void inkFill(const TRasterCM32P &r, const TPoint &pin, int ink, int searchRay,
Toshihiro Shimizu 890ddd
			 TTileSaverCM32 *saver, TRect *insideRect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	r->lock();
Toshihiro Shimizu 890ddd
	TPixelCM32 *pixels = (TPixelCM32 *)r->getRawData();
Toshihiro Shimizu 890ddd
	int oldInk;
Toshihiro Shimizu 890ddd
	TPoint p = pin;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((pixels + p.y * r->getWrap() + p.x)->isPurePaint() && (searchRay == 0 ||
Toshihiro Shimizu 890ddd
															   (p = nearestInk(r, p, searchRay)) == TPoint(-1, -1))) {
Toshihiro Shimizu 890ddd
		r->unlock();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (pix->getInk() == ink) {
Toshihiro Shimizu 890ddd
		r->unlock();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	oldInk = pix->getInk();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::stack<tpoint> seeds;</tpoint>
Toshihiro Shimizu 890ddd
	seeds.push(p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (!seeds.empty()) {
Toshihiro Shimizu 890ddd
		p = seeds.top();
Toshihiro Shimizu 890ddd
		seeds.pop();
Toshihiro Shimizu 890ddd
		if (!r->getBounds().contains(p))
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		if (insideRect && !insideRect->contains(p))
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);
Toshihiro Shimizu 890ddd
		if (pix->isPurePaint() || pix->getInk() != oldInk)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (saver)
Toshihiro Shimizu 890ddd
			saver->save(p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		pix->setInk(ink);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		seeds.push(TPoint(p.x - 1, p.y - 1));
Toshihiro Shimizu 890ddd
		seeds.push(TPoint(p.x - 1, p.y));
Toshihiro Shimizu 890ddd
		seeds.push(TPoint(p.x - 1, p.y + 1));
Toshihiro Shimizu 890ddd
		seeds.push(TPoint(p.x, p.y - 1));
Toshihiro Shimizu 890ddd
		seeds.push(TPoint(p.x, p.y + 1));
Toshihiro Shimizu 890ddd
		seeds.push(TPoint(p.x + 1, p.y - 1));
Toshihiro Shimizu 890ddd
		seeds.push(TPoint(p.x + 1, p.y));
Toshihiro Shimizu 890ddd
		seeds.push(TPoint(p.x + 1, p.y + 1));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	r->unlock();
Toshihiro Shimizu 890ddd
}