Fix Fill Behavior on Toonz Raster (#1540)
* fix raster fill * fix for one pixel width line case * fix rect fill
This commit is contained in:
parent
2a679ac119
commit
f9d3f02167
3 changed files with 81 additions and 10 deletions
|
@ -27,6 +27,7 @@ public:
|
|||
bool m_shiftFill;
|
||||
TPoint m_p;
|
||||
TPalette *m_palette;
|
||||
bool m_prevailing;
|
||||
|
||||
FillParameters()
|
||||
: m_styleId(0)
|
||||
|
@ -37,7 +38,8 @@ public:
|
|||
, m_maxFillDepth(0)
|
||||
, m_p()
|
||||
, m_shiftFill(false)
|
||||
, m_palette(0) {}
|
||||
, m_palette(0)
|
||||
, m_prevailing(true) {}
|
||||
FillParameters(const FillParameters ¶ms)
|
||||
: m_styleId(params.m_styleId)
|
||||
, m_fillType(params.m_fillType)
|
||||
|
@ -47,7 +49,8 @@ public:
|
|||
, m_maxFillDepth(params.m_maxFillDepth)
|
||||
, m_p(params.m_p)
|
||||
, m_shiftFill(params.m_shiftFill)
|
||||
, m_palette(params.m_palette) {}
|
||||
, m_palette(params.m_palette)
|
||||
, m_prevailing(params.m_prevailing) {}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -32,9 +32,14 @@ inline TPoint nearestInkNotDiagonal(const TRasterCM32P &r, const TPoint &p) {
|
|||
// la riga ridisegnata va da *xa a *xb compresi
|
||||
// x1 <= *xa <= *xb <= x2
|
||||
// N.B. se non viene disegnato neanche un pixel *xa>*xb
|
||||
//
|
||||
// "prevailing" is set to false on revert-filling the border of
|
||||
// region in the Rectangular, Freehand and Polyline fill procedures
|
||||
// in order to make the paint to protlude behind the line.
|
||||
|
||||
void fillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
||||
int paint, TPalette *palette, TTileSaverCM32 *saver) {
|
||||
int paint, TPalette *palette, TTileSaverCM32 *saver,
|
||||
bool prevailing = true) {
|
||||
int tone, oldtone;
|
||||
TPixelCM32 *pix, *pix0, *limit, *tmp_limit;
|
||||
|
||||
|
@ -49,7 +54,34 @@ void fillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
|||
for (; pix <= limit; pix++) {
|
||||
if (pix->getPaint() == paint) break;
|
||||
tone = pix->getTone();
|
||||
if (tone > oldtone || tone == 0) break;
|
||||
if (tone == 0) break;
|
||||
// prevent fill area from protruding behind the colored line
|
||||
if (tone > oldtone) {
|
||||
// not-yet-colored line case
|
||||
if (prevailing && !pix->isPurePaint() && pix->getInk() != pix->getPaint())
|
||||
break;
|
||||
while (pix != pix0) {
|
||||
// iterate back in order to leave the pixel with the lowest tone
|
||||
// unpainted
|
||||
pix--;
|
||||
// make the one-pixel-width semi-transparent line to be painted
|
||||
if (prevailing && pix->getInk() != pix->getPaint()) break;
|
||||
if (pix->getTone() > oldtone) {
|
||||
// check if the current pixel is NOT with the lowest tone among the
|
||||
// vertical neighbors as well
|
||||
if (p.y > 0 && p.y < r->getLy() - 1) {
|
||||
TPixelCM32 *upPix = pix - r->getWrap();
|
||||
TPixelCM32 *downPix = pix + r->getWrap();
|
||||
if (upPix->getTone() > pix->getTone() &&
|
||||
downPix->getTone() > pix->getTone())
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
pix++;
|
||||
break;
|
||||
}
|
||||
oldtone = tone;
|
||||
}
|
||||
if (tone == 0) {
|
||||
|
@ -72,7 +104,34 @@ void fillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
|||
for (pix--; pix >= limit; pix--) {
|
||||
if (pix->getPaint() == paint) break;
|
||||
tone = pix->getTone();
|
||||
if (tone > oldtone || tone == 0) break;
|
||||
if (tone == 0) break;
|
||||
// prevent fill area from protruding behind the colored line
|
||||
if (tone > oldtone) {
|
||||
// not-yet-colored line case
|
||||
if (prevailing && !pix->isPurePaint() && pix->getInk() != pix->getPaint())
|
||||
break;
|
||||
while (pix != pix0) {
|
||||
// iterate forward in order to leave the pixel with the lowest tone
|
||||
// unpainted
|
||||
pix++;
|
||||
// make the one-pixel-width semi-transparent line to be painted
|
||||
if (prevailing && pix->getInk() != pix->getPaint()) break;
|
||||
if (pix->getTone() > oldtone) {
|
||||
// check if the current pixel is NOT with the lowest tone among the
|
||||
// vertical neighbors as well
|
||||
if (p.y > 0 && p.y < r->getLy() - 1) {
|
||||
TPixelCM32 *upPix = pix - r->getWrap();
|
||||
TPixelCM32 *downPix = pix + r->getWrap();
|
||||
if (upPix->getTone() > pix->getTone() &&
|
||||
downPix->getTone() > pix->getTone())
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
pix--;
|
||||
break;
|
||||
}
|
||||
oldtone = tone;
|
||||
}
|
||||
if (tone == 0) {
|
||||
|
@ -234,7 +293,8 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
/*- 画面外のクリックの場合はreturn -*/
|
||||
if (!bbbox.contains(p)) return false;
|
||||
/*- 既に同じ色が塗られている場合はreturn -*/
|
||||
if ((r->pixels(p.y) + p.x)->getPaint() == paint) return false;
|
||||
int paintAtClickedPos = (r->pixels(p.y) + p.x)->getPaint();
|
||||
if (paintAtClickedPos == paint) return false;
|
||||
/*- 「透明部分だけを塗る」オプションが有効で、既に色が付いている場合はreturn
|
||||
* -*/
|
||||
if (params.m_emptyOnly && (r->pixels(p.y) + p.x)->getPaint() != 0)
|
||||
|
@ -252,7 +312,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
/*-- 四隅の色を見て、一つでも変わったらsaveBoxを更新する --*/
|
||||
TPixelCM32 borderIndex[4];
|
||||
TPixelCM32 *borderPix[4];
|
||||
|
@ -271,7 +330,7 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
|
||||
std::stack<FillSeed> seeds;
|
||||
|
||||
fillRow(r, p, xa, xb, paint, params.m_palette, saver);
|
||||
fillRow(r, p, xa, xb, paint, params.m_palette, saver, params.m_prevailing);
|
||||
seeds.push(FillSeed(xa, xb, y, 1));
|
||||
seeds.push(FillSeed(xa, xb, y, -1));
|
||||
|
||||
|
@ -294,8 +353,13 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
while (pix <= limit) {
|
||||
oldtone = threshTone(*oldpix, fillDepth);
|
||||
tone = threshTone(*pix, fillDepth);
|
||||
if (pix->getPaint() != paint && tone <= oldtone && tone != 0) {
|
||||
fillRow(r, TPoint(x, y), xc, xd, paint, params.m_palette, saver);
|
||||
// the last condition is added in order to prevent fill area from
|
||||
// protruding behind the colored line
|
||||
if (pix->getPaint() != paint && tone <= oldtone && tone != 0 &&
|
||||
(pix->getPaint() != pix->getInk() ||
|
||||
pix->getPaint() == paintAtClickedPos)) {
|
||||
fillRow(r, TPoint(x, y), xc, xd, paint, params.m_palette, saver,
|
||||
params.m_prevailing);
|
||||
if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy));
|
||||
if (xd > xb) seeds.push(FillSeed(xb + 1, xd, y, -dy));
|
||||
if (oldxd >= xc - 1)
|
||||
|
|
|
@ -69,6 +69,8 @@ void fillArea(const TRasterCM32P &ras, TRegion *r, int colorId,
|
|||
void restoreColors(const TRasterCM32P &r,
|
||||
const std::vector<std::pair<TPoint, int>> &seeds) {
|
||||
FillParameters params;
|
||||
// in order to make the paint to protlude behind the line
|
||||
params.m_prevailing = false;
|
||||
for (UINT i = 0; i < seeds.size(); i++) {
|
||||
params.m_p = seeds[i].first;
|
||||
params.m_styleId = seeds[i].second;
|
||||
|
@ -232,6 +234,8 @@ void AreaFiller::rectFill(const TRect &rect, int color, bool onlyUnfilled,
|
|||
// fillate.
|
||||
count1 = 0;
|
||||
FillParameters params;
|
||||
// in order to make the paint to protlude behind the line
|
||||
params.m_prevailing = false;
|
||||
if (r.x0 > 0)
|
||||
for (y = r.y0; y <= r.y1; y++) {
|
||||
params.m_p = TPoint(r.x0, y);
|
||||
|
|
Loading…
Reference in a new issue