Merge pull request #1215 from TomDoingArt/Issue_1151_ResidualGapOnFillGaps
Issue 1151 residual gap on fill gaps
This commit is contained in:
commit
dbf0fc8da2
8 changed files with 491 additions and 174 deletions
|
@ -3717,6 +3717,12 @@ TThickCubic *TCubicStroke::generateCubic3D(const T3DPointD pointsArrayBegin[],
|
|||
TCubicStroke, cioe' uno stroke cubico. Da questo trova lo stroke
|
||||
quadratico.
|
||||
*/
|
||||
//! Returns a stroke from a vector of TThickPoints
|
||||
/*!
|
||||
Transforms an array of TThickPoints into an array of T3DPointDs
|
||||
which is used for a TCubicStroke, i.e. a cubic stroke.
|
||||
From this he finds the stroke quadratic.
|
||||
*/
|
||||
TStroke *TStroke::interpolate(const vector<TThickPoint> &points, double error,
|
||||
bool findCorners) {
|
||||
vector<T3DPointD> pointsArray3D;
|
||||
|
|
|
@ -73,6 +73,8 @@ class TTileSaverFullColor;
|
|||
|
||||
//=============================================================================
|
||||
|
||||
DVAPI void outputPixels(const std::string _str, const TRasterCM32P& r);
|
||||
|
||||
// returns true if the savebox is changed typically, if you fill the bg)
|
||||
DVAPI bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
||||
TTileSaverCM32 *saver = 0, bool fillGaps = false,
|
||||
|
@ -103,6 +105,12 @@ void DVAPI fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
|||
bool closeGaps = false, int closeStyleIndex = -1,
|
||||
double autoCloseDistance = -1.0);
|
||||
|
||||
void DVAPI finishGapLines(TRasterCM32P &rin, TRect &rect,
|
||||
const TRasterCM32P &rbefore,
|
||||
const TRasterCM32P &combined, TPalette *plt,
|
||||
int clickedColorStyle, int fillIndex,
|
||||
int closeColorStyle, bool closeGaps);
|
||||
|
||||
//=============================================================================
|
||||
//! The class AreaFiller allows to fill a raster area, delimited by rect or
|
||||
//! spline.
|
||||
|
|
|
@ -22,6 +22,9 @@ class TStroke;
|
|||
Genera degli stroke sulla base di un vettore di punti,
|
||||
questo vettore e' fatto di punti che vengono inseriti.
|
||||
Consente di visualizzare dei frammenti fatti dai punti che acquisisce.
|
||||
Generate strokes based on a vector of points,
|
||||
this vector is made of points that are inserted.
|
||||
Allows you to view fragments made from the points it acquires.
|
||||
*/
|
||||
class DVAPI StrokeGenerator {
|
||||
//! Vettore di TThickPoint
|
||||
|
|
|
@ -65,6 +65,10 @@ using namespace ToolUtils;
|
|||
#define POLYLINEFILL L"Polyline"
|
||||
#define FREEPICKFILL L"Freepick"
|
||||
|
||||
#define GAP_CLOSE_USED 4095
|
||||
#define GAP_CLOSE_TEMP 4094
|
||||
#define IGNORECOLORSTYLE 4093
|
||||
|
||||
TEnv::IntVar MinFillDepth("InknpaintMinFillDepth", 1);
|
||||
TEnv::IntVar MaxFillDepth("InknpaintMaxFillDepth", 10);
|
||||
TEnv::StringVar FillType("InknpaintFillType", "Normal");
|
||||
|
@ -153,6 +157,8 @@ bool applyAutoclose(const TToonzImageP &ti, int distance, int angle,
|
|||
ras = raux;
|
||||
if (!ras) return false;
|
||||
|
||||
//outputPixels("ras in applyAutoClose", ras);
|
||||
|
||||
TAutocloser ac(ras, distance, angle, newInkIndex, opacity);
|
||||
|
||||
std::vector<TAutocloser::Segment> segments;
|
||||
|
@ -465,14 +471,9 @@ class RasterFillUndo final : public TRasterUndo {
|
|||
|
||||
public:
|
||||
/*RasterFillUndo(TTileSetCM32 *tileSet, TPoint fillPoint,
|
||||
int paintId, int
|
||||
fillDepth,
|
||||
std::wstring
|
||||
fillType, bool isSegment,
|
||||
bool selective, bool
|
||||
isShiftFill,
|
||||
TXshSimpleLevel* sl,
|
||||
const TFrameId& fid)*/
|
||||
int paintId, int fillDepth, std::wstring fillType,
|
||||
bool isSegment, bool selective, bool isShiftFill,
|
||||
TXshSimpleLevel* sl, const TFrameId& fid)*/
|
||||
RasterFillUndo(TTileSetCM32 *tileSet, const FillParameters ¶ms,
|
||||
TXshSimpleLevel *sl, const TFrameId &fid, bool saveboxOnly,
|
||||
bool fillGaps, bool closeGaps, int closeStyleIndex,
|
||||
|
@ -585,13 +586,13 @@ public:
|
|||
TRasterCM32P ras = image->getRaster();
|
||||
|
||||
TRasterCM32P tempRaster;
|
||||
int styleIndex = 4094;
|
||||
int styleIndex = GAP_CLOSE_TEMP;
|
||||
if (m_fillGaps) {
|
||||
TToonzImageP tempTi = image->clone();
|
||||
tempRaster = tempTi->getRaster();
|
||||
TRectD doubleFillArea = convert(m_fillArea);
|
||||
applyAutoclose(tempTi, AutocloseDistance, AutocloseAngle,
|
||||
AutocloseOpacity, 4094, doubleFillArea, m_s);
|
||||
AutocloseOpacity, GAP_CLOSE_TEMP, doubleFillArea, m_s);
|
||||
} else {
|
||||
tempRaster = ras;
|
||||
}
|
||||
|
@ -603,25 +604,33 @@ public:
|
|||
else
|
||||
filler.strokeFill(m_s, m_paintId, m_onlyUnfilled, m_colorType != LINES,
|
||||
m_colorType != AREAS, m_fillArea);
|
||||
|
||||
|
||||
if (m_fillGaps) {
|
||||
|
||||
TRect rect = m_fillArea;
|
||||
finishGapLines(
|
||||
tempRaster,
|
||||
rect,
|
||||
ras,
|
||||
tempRaster,
|
||||
m_palette,
|
||||
0,
|
||||
m_paintId,
|
||||
m_closeStyleIndex,
|
||||
m_closeGaps);
|
||||
|
||||
TPixelCM32 *tempPix = tempRaster->pixels();
|
||||
TPixelCM32 *keepPix = ras->pixels();
|
||||
for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) {
|
||||
for (int tempX = 0; tempX < tempRaster->getLx();
|
||||
tempX++, tempPix++, keepPix++) {
|
||||
keepPix->setPaint(tempPix->getPaint());
|
||||
if (tempPix->getInk() != styleIndex) {
|
||||
if (m_colorType == AREAS && m_closeGaps &&
|
||||
tempPix->getInk() == 4095) {
|
||||
keepPix->setInk(m_closeStyleIndex);
|
||||
keepPix->setTone(tempPix->getTone());
|
||||
} else if (m_colorType != AREAS && tempPix->getInk() == 4095) {
|
||||
keepPix->setInk(m_paintId);
|
||||
keepPix->setTone(tempPix->getTone());
|
||||
} else if (tempPix->getInk() != 4095) {
|
||||
keepPix->setInk(tempPix->getInk());
|
||||
}
|
||||
if (tempPix->getInk() >= IGNORECOLORSTYLE || tempPix->getPaint() >= IGNORECOLORSTYLE) {
|
||||
continue;
|
||||
} else {
|
||||
keepPix->setInk(tempPix->getInk());
|
||||
keepPix->setPaint(tempPix->getPaint());
|
||||
keepPix->setTone(tempPix->getTone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -989,33 +998,37 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke,
|
|||
TRectD selArea = stroke ? stroke->getBBox() : area;
|
||||
|
||||
if (TToonzImageP ti = img) {
|
||||
// allargo di 1 la savebox, perche cosi' il rectfill di tutta l'immagine fa
|
||||
// una sola fillata
|
||||
// Widen the savebox by 1, because this is how the rectfill of the whole image does
|
||||
// a single fill
|
||||
TRect enlargedSavebox =
|
||||
fillOnlySavebox
|
||||
? ti->getSavebox().enlarge(1) * TRect(TPoint(0, 0), ti->getSize())
|
||||
: TRect(TPoint(0, 0), ti->getSize());
|
||||
TRect rasterFillArea =
|
||||
ToonzImageUtils::convertWorldToRaster(selArea, ti) * enlargedSavebox;
|
||||
|
||||
if (rasterFillArea.isEmpty()) return;
|
||||
|
||||
TRasterCM32P ras = ti->getRaster();
|
||||
/*-- tileSetでFill範囲のRectをUndoに格納しておく --*/
|
||||
/* Store the Rect of the Fill range in Undo with tileSet */
|
||||
TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize());
|
||||
tileSet->add(ras, rasterFillArea);
|
||||
|
||||
TRasterCM32P tempRaster;
|
||||
int styleIndex = 4094;
|
||||
int styleIndex = GAP_CLOSE_TEMP;
|
||||
|
||||
TToonzImageP tempTi = ti->clone();
|
||||
tempRaster = tempTi->getRaster();
|
||||
|
||||
if (fillGaps) {
|
||||
TToonzImageP tempTi = ti->clone();
|
||||
tempRaster = tempTi->getRaster();
|
||||
|
||||
applyAutoclose(tempTi, AutocloseDistance, AutocloseAngle,
|
||||
AutocloseOpacity, 4094, convert(rasterFillArea), stroke);
|
||||
} else {
|
||||
tempRaster = ras;
|
||||
AutocloseOpacity, GAP_CLOSE_TEMP, convert(rasterFillArea), stroke);
|
||||
|
||||
}
|
||||
|
||||
AreaFiller filler(tempRaster);
|
||||
|
||||
if (!stroke) {
|
||||
bool ret = filler.rectFill(rasterFillArea, cs, onlyUnfilled,
|
||||
colorType != LINES, colorType != AREAS);
|
||||
|
@ -1023,29 +1036,29 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke,
|
|||
delete tileSet;
|
||||
return;
|
||||
}
|
||||
} else
|
||||
|
||||
} else {
|
||||
filler.strokeFill(stroke, cs, onlyUnfilled, colorType != LINES,
|
||||
colorType != AREAS, rasterFillArea);
|
||||
}
|
||||
|
||||
if (fillGaps) {
|
||||
TPixelCM32 *tempPix = tempRaster->pixels();
|
||||
TPixelCM32 *keepPix = ras->pixels();
|
||||
for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) {
|
||||
for (int tempX = 0; tempX < tempRaster->getLx();
|
||||
tempX++, tempPix++, keepPix++) {
|
||||
keepPix->setPaint(tempPix->getPaint());
|
||||
if (tempPix->getInk() != styleIndex) {
|
||||
if (colorType == AREAS && closeGaps && tempPix->getInk() == 4095) {
|
||||
keepPix->setInk(closeStyleIndex);
|
||||
keepPix->setTone(tempPix->getTone());
|
||||
} else if (colorType != AREAS && tempPix->getInk() == 4095) {
|
||||
keepPix->setInk(cs);
|
||||
keepPix->setTone(tempPix->getTone());
|
||||
} else if (tempPix->getInk() != 4095) {
|
||||
keepPix->setInk(tempPix->getInk());
|
||||
}
|
||||
}
|
||||
TPixelCM32 *tempPix = tempRaster->pixels();
|
||||
TPixelCM32 *keepPix = ras->pixels();
|
||||
|
||||
|
||||
finishGapLines(tempRaster, rasterFillArea, ras, ras, ti->getPalette(), 0,
|
||||
cs, closeStyleIndex, closeGaps);
|
||||
|
||||
for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) {
|
||||
for (int tempX = 0; tempX < tempRaster->getLx();
|
||||
tempX++, tempPix++, keepPix++) {
|
||||
if (tempPix->getInk() < IGNORECOLORSTYLE) {
|
||||
keepPix->setInk(tempPix->getInk());
|
||||
}
|
||||
if (tempPix->getPaint() < IGNORECOLORSTYLE) {
|
||||
keepPix->setPaint(tempPix->getPaint());
|
||||
}
|
||||
keepPix->setTone(tempPix->getTone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1185,7 +1198,7 @@ void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms,
|
|||
|
||||
if (tileSaver.getTileSet()->getTileCount() != 0) {
|
||||
static int count = 0;
|
||||
TSystem::outputDebug("FILL" + std::to_string(count++) + "\n");
|
||||
TSystem::outputDebug("FILL" + std::to_string(count++));
|
||||
if (offs != TPoint())
|
||||
for (int i = 0; i < tileSet->getTileCount(); i++) {
|
||||
TTileSet::Tile *t = tileSet->editTile(i);
|
||||
|
@ -2000,7 +2013,14 @@ void AreaFillTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e,
|
|||
m_enabled = m_active = false;
|
||||
if (!isValid || m_track.isEmpty()) return;
|
||||
double pixelSize2 = m_parent->getPixelSize() * m_parent->getPixelSize();
|
||||
|
||||
if (m_type == FREEPICK){
|
||||
//strip off the first n points to allow the stroke to begin away from the initial click point where the color style will be selected.
|
||||
TPointD firstPoint = m_track.getFirstPoint();
|
||||
}
|
||||
// add the first point as also the last point, to form a complete loop.
|
||||
m_track.add(TThickPoint(m_firstPos, m_thick), pixelSize2);
|
||||
|
||||
m_track.filterPoints();
|
||||
double error = (m_isPath ? 20.0 : 30.0 / 11) * sqrt(pixelSize2);
|
||||
TStroke *stroke = m_track.makeStroke(error);
|
||||
|
@ -2587,8 +2607,8 @@ void FillTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
|||
invalidate();
|
||||
return;
|
||||
}
|
||||
TSystem::outputDebug("ok. pix=" + std::to_string(pix.getTone()) + "," +
|
||||
std::to_string(pix.getPaint()) + "\n");
|
||||
//TSystem::outputDebug("ok. pix=" + std::to_string(pix.getTone()) + "," +
|
||||
// std::to_string(pix.getPaint()));
|
||||
} else
|
||||
return;
|
||||
int closeStyleIndex = m_closeStyleIndex.getStyleIndex();
|
||||
|
|
|
@ -1799,7 +1799,7 @@ void FullColorFillToolOptionsBox::onGapSettingChanged(int index) {
|
|||
m_styleIndex->hide();
|
||||
m_styleIndexLabel->hide();
|
||||
m_rasterGapSlider->show();
|
||||
m_gapSliderLabel->hide();
|
||||
m_gapSliderLabel->show();
|
||||
} else if (index == 2) {
|
||||
m_styleIndex->show();
|
||||
m_styleIndexLabel->show();
|
||||
|
|
|
@ -20,11 +20,17 @@
|
|||
|
||||
#include <QDebug>
|
||||
|
||||
#include "tsystem.h"
|
||||
|
||||
extern TEnv::DoubleVar AutocloseDistance;
|
||||
extern TEnv::DoubleVar AutocloseAngle;
|
||||
extern TEnv::IntVar AutocloseInk;
|
||||
extern TEnv::IntVar AutocloseOpacity;
|
||||
|
||||
#define IGNORECOLORSTYLE 4093
|
||||
#define GAP_CLOSE_TEMP 4094
|
||||
#define GAP_CLOSE_USED 4095
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace { // Utility Function
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -47,14 +53,14 @@ inline TPoint nearestInkNotDiagonal(const TRasterCM32P &r, const TPoint &p) {
|
|||
}
|
||||
|
||||
//
|
||||
// from point x, y expands to the rightand left.
|
||||
// from point x, y expands to the right and left.
|
||||
// the redrawn line goes from* xa to* xb inclusive
|
||||
// x1 <= *xa <= *xb <= x2
|
||||
// N.B. if not even one pixel is drawn* 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.
|
||||
// in order to make the paint extend behind the line.
|
||||
|
||||
// Calculates the endpoints for the line of pixels in which to fill
|
||||
bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
||||
|
@ -72,10 +78,16 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
|||
oldtone = pix->getTone();
|
||||
tone = oldtone;
|
||||
for (; pix <= limit; pix++) {
|
||||
if (pix->getPaint() == paint) break;
|
||||
if (emptyOnly && pix->getPaint() != 0) break;
|
||||
if (pix->getPaint() == paint) {
|
||||
//break;
|
||||
}
|
||||
if (emptyOnly && pix->getPaint() != 0) {
|
||||
//break;
|
||||
}
|
||||
tone = pix->getTone();
|
||||
if (tone == 0) break;
|
||||
if (tone == 0) {
|
||||
break;
|
||||
}
|
||||
// prevent fill area from protruding behind the colored line
|
||||
if (tone > oldtone) {
|
||||
// not-yet-colored line case
|
||||
|
@ -94,8 +106,7 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
|||
TPixelCM32 *upPix = pix - r->getWrap();
|
||||
TPixelCM32 *downPix = pix + r->getWrap();
|
||||
if (upPix->getTone() > pix->getTone() &&
|
||||
downPix->getTone() > pix->getTone())
|
||||
continue;
|
||||
downPix->getTone() > pix->getTone()) continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -109,12 +120,14 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
|||
tmp_limit = pix + 10; // edge stop fill == 10 per default
|
||||
if (limit > tmp_limit) limit = tmp_limit;
|
||||
for (; pix <= limit; pix++) {
|
||||
if (pix->getPaint() == paint) break;
|
||||
if (pix->getTone() != 0) break;
|
||||
//if (pix->getPaint() == paint) break; // commented out for issue 1151
|
||||
if (pix->getTone() != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xb = p.x + pix - pix0 - 1;
|
||||
xb = p.x + pix - pix0 - 1; //go backward one pixel from the current pixel which triggered the boundary condition.
|
||||
|
||||
/* go left */
|
||||
|
||||
|
@ -123,15 +136,22 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
|||
oldtone = pix->getTone();
|
||||
tone = oldtone;
|
||||
for (pix--; pix >= limit; pix--) {
|
||||
if (pix->getPaint() == paint) break;
|
||||
if (emptyOnly && pix->getPaint() != 0) break;
|
||||
if (pix->getPaint() == paint) {
|
||||
break;
|
||||
}
|
||||
if (emptyOnly && pix->getPaint() != 0) {
|
||||
break;
|
||||
}
|
||||
tone = pix->getTone();
|
||||
if (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;
|
||||
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
|
||||
|
@ -145,8 +165,9 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
|||
TPixelCM32 *upPix = pix - r->getWrap();
|
||||
TPixelCM32 *downPix = pix + r->getWrap();
|
||||
if (upPix->getTone() > pix->getTone() &&
|
||||
downPix->getTone() > pix->getTone())
|
||||
continue;
|
||||
downPix->getTone() > pix->getTone()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -160,12 +181,14 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb,
|
|||
tmp_limit = pix - 10;
|
||||
if (limit < tmp_limit) limit = tmp_limit;
|
||||
for (; pix >= limit; pix--) {
|
||||
if (pix->getPaint() == paint) break;
|
||||
if (pix->getTone() != 0) break;
|
||||
//if (pix->getPaint() == paint) break; // commented out for issue 1151
|
||||
if (pix->getTone() != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xa = p.x + pix - pix0 + 1;
|
||||
xa = p.x + pix - pix0 + 1; //go backward one pixel from the current pixel which triggered the boundary condition.
|
||||
|
||||
return (xb >= xa);
|
||||
}
|
||||
|
@ -430,6 +453,44 @@ TRasterCM32P convertRaster2CM(const TRasterP &inputRaster) {
|
|||
return rout;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void outputPixels(const std::string _str, const TRasterCM32P &r) {
|
||||
r->lock();
|
||||
TPixelCM32* tempPix = r->pixels(0);
|
||||
std::cout << "\noutputPixels for:";
|
||||
std::cout << _str;
|
||||
std::cout << ", bbox is y : ";
|
||||
std::cout << r->getLy();
|
||||
std::cout << ",x:";
|
||||
std::cout << r->getLx();
|
||||
std::cout << "----";
|
||||
tempPix = tempPix + ((r->getLy()-1) * r->getLx());
|
||||
for (int tempY = r->getLy()-1; tempY >= 0; tempY--) {
|
||||
if (tempY < r->getLy() - 1) {
|
||||
tempPix = tempPix - 2 * r->getLx();
|
||||
}
|
||||
std::cout << "\ny:";
|
||||
std::cout << tempY;
|
||||
for (int tempX = 0; tempX < r->getLx();
|
||||
tempX++, tempPix++) {
|
||||
std::cout << "|x:";
|
||||
std::cout << tempX;
|
||||
std::cout << ":";
|
||||
std::cout << tempPix->getInk();
|
||||
std::cout << ".";
|
||||
std::cout << tempPix->getPaint();
|
||||
std::cout << ".";
|
||||
std::cout << tempPix->getTone();
|
||||
}
|
||||
}
|
||||
r->unlock();
|
||||
std::cout << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*-- The return value is whether the saveBox has been updated or not. --*/
|
||||
bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
||||
TTileSaverCM32 *saver, bool fillGaps, bool closeGaps,
|
||||
|
@ -449,9 +510,9 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
int paint = params.m_styleId;
|
||||
int fillDepth =
|
||||
params.m_shiftFill ? params.m_maxFillDepth : params.m_minFillDepth;
|
||||
TRasterCM32P tempRaster;
|
||||
int styleIndex = 4094;
|
||||
int fakeStyleIndex = 4095;
|
||||
TRasterCM32P tempRaster, cr, refCMRaster;
|
||||
int styleIndex = GAP_CLOSE_TEMP;
|
||||
int fakeStyleIndex = GAP_CLOSE_USED;
|
||||
if (autoCloseDistance < 0.0) autoCloseDistance = AutocloseDistance;
|
||||
|
||||
bool gapsClosed = false, refGapsClosed = false;
|
||||
|
@ -473,7 +534,10 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
if (!bbbox.contains(p)) return false;
|
||||
/*- If the same color has already been painted, return -*/
|
||||
int paintAtClickedPos = (tempRaster->pixels(p.y) + p.x)->getPaint();
|
||||
if (paintAtClickedPos == paint) return false;
|
||||
|
||||
if (paintAtClickedPos == paint) {
|
||||
return false;
|
||||
}
|
||||
/*- If the "paint only transparent areas" option is enabled and the area is
|
||||
* already colored, return
|
||||
* -*/
|
||||
|
@ -511,8 +575,8 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
}
|
||||
|
||||
if (fillGaps) {
|
||||
TRasterCM32P cr = convertRaster2CM(refRaster);
|
||||
TRasterCM32P refCMRaster = cr->clone();
|
||||
cr = convertRaster2CM(refRaster);
|
||||
refCMRaster = cr->clone();
|
||||
|
||||
refGapsClosed = TAutocloser(refCMRaster, autoCloseDistance,
|
||||
AutocloseAngle, styleIndex, AutocloseOpacity)
|
||||
|
@ -529,7 +593,7 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
refCMX++, refCMPix++, refPix++, tempPix++) {
|
||||
if (refCMPix->getInk() != styleIndex) continue;
|
||||
*refPix = color;
|
||||
if (closeGaps) {
|
||||
if (fillGaps) {
|
||||
tempPix->setInk(refCMPix->getInk());
|
||||
tempPix->setTone(refCMPix->getTone());
|
||||
}
|
||||
|
@ -539,7 +603,9 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
}
|
||||
}
|
||||
|
||||
if (fillGaps && !gapsClosed && !refGapsClosed) fillGaps = false;
|
||||
if (fillGaps && !gapsClosed && !refGapsClosed) {
|
||||
fillGaps = false;
|
||||
}
|
||||
|
||||
assert(fillDepth >= 0 && fillDepth < 16);
|
||||
|
||||
|
@ -580,23 +646,11 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
params.m_prevailing, params.m_emptyOnly)
|
||||
: calcRefFillRow(refRaster, p, xa, xb, color, clickedPosColor,
|
||||
fillDepth);
|
||||
|
||||
if (fillIt) fillRow(tempRaster, p, xa, xb, paint, params.m_palette, saver);
|
||||
if (xsheet) segments[y].push_back(std::pair<int, int>(xa, xb));
|
||||
seeds.push(FillSeed(xa, xb, y, 1));
|
||||
seeds.push(FillSeed(xa, xb, y, -1));
|
||||
// Set the ink on gaps that were used to 4095
|
||||
{
|
||||
TPixelCM32 *tempPix = tempRaster->pixels(0);
|
||||
tempPix += (y * tempRaster->getLx()) + xa - 1;
|
||||
int i = xa;
|
||||
while (i <= xb) {
|
||||
if (tempPix->getInk() == styleIndex) {
|
||||
tempPix->setInk(fakeStyleIndex);
|
||||
}
|
||||
tempPix++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
while (!seeds.empty()) {
|
||||
FillSeed fs = seeds.top();
|
||||
|
@ -647,19 +701,7 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
fillRow(tempRaster, TPoint(x, y), xc, xd, paint, params.m_palette,
|
||||
saver);
|
||||
if (xsheet) insertSegment(segments[y], std::pair<int, int>(xc, xd));
|
||||
// Set the ink on gaps that were used to 4095
|
||||
{
|
||||
TPixelCM32 *tempPix = tempRaster->pixels(0);
|
||||
tempPix += (y * tempRaster->getLx()) + xa - 1;
|
||||
int i = xa;
|
||||
while (i <= xb) {
|
||||
if (tempPix->getInk() == styleIndex) {
|
||||
tempPix->setInk(fakeStyleIndex);
|
||||
}
|
||||
tempPix++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -703,26 +745,27 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms,
|
|||
}
|
||||
|
||||
if (fillGaps) {
|
||||
TPixelCM32 *tempPix = tempRaster->pixels();
|
||||
TPixelCM32 *keepPix = r->pixels();
|
||||
finishGapLines(tempRaster, bbbox, r, refCMRaster, params.m_palette, paintAtClickedPos, paint, closeStyleIndex, closeGaps);
|
||||
TPixelCM32 *tempPix, *tempPixRestart;
|
||||
tempPixRestart = tempPix = tempRaster->pixels();
|
||||
TPixelCM32 *keepPix, *keepPixRestart;
|
||||
keepPixRestart = keepPix = r->pixels();
|
||||
int fillNeighbors = 0;
|
||||
int paintableNeighbors = 0;
|
||||
|
||||
for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) {
|
||||
for (int tempX = 0; tempX < tempRaster->getLx();
|
||||
tempX++, tempPix++, keepPix++) {
|
||||
if (tempPix->getInk() != styleIndex &&
|
||||
tempPix->getInk() != fakeStyleIndex)
|
||||
keepPix->setPaint(tempPix->getPaint());
|
||||
// This next line takes care of autopaint lines
|
||||
if (tempPix->getInk() != styleIndex) {
|
||||
if (closeGaps && tempPix->getInk() == fakeStyleIndex) {
|
||||
keepPix->setInk(closeStyleIndex);
|
||||
keepPix->setTone(tempPix->getTone());
|
||||
} else if (tempPix->getInk() != fakeStyleIndex) {
|
||||
keepPix->setInk(tempPix->getInk());
|
||||
}
|
||||
if (tempPix->getInk() >= IGNORECOLORSTYLE || tempPix->getPaint() >= IGNORECOLORSTYLE) {
|
||||
continue;
|
||||
}
|
||||
keepPix->setInk(tempPix->getInk());
|
||||
keepPix->setPaint(tempPix->getPaint());
|
||||
keepPix->setTone(tempPix->getTone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return saveBoxChanged;
|
||||
}
|
||||
|
||||
|
@ -949,8 +992,8 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
|||
TRaster32P refRas(bbbox.getSize());
|
||||
|
||||
TPixel32 gapColor = plt->getStyle(closeStyleIndex)->getMainColor();
|
||||
int styleIndex = 4094;
|
||||
int fakeStyleIndex = 4095;
|
||||
int styleIndex = GAP_CLOSE_TEMP;
|
||||
int fakeStyleIndex = GAP_CLOSE_USED;
|
||||
|
||||
if (xsheet) {
|
||||
ToonzScene *scene = xsheet->getScene();
|
||||
|
@ -975,9 +1018,10 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
|||
}
|
||||
|
||||
TRasterCM32P refCMRaster;
|
||||
TRasterCM32P cr;
|
||||
|
||||
if (fillGaps) {
|
||||
TRasterCM32P cr = convertRaster2CM(refRas);
|
||||
cr = convertRaster2CM(refRas);
|
||||
refCMRaster = cr->clone();
|
||||
fillGaps = TAutocloser(refCMRaster, autoCloseDistance, AutocloseAngle,
|
||||
styleIndex, AutocloseOpacity)
|
||||
|
@ -1019,20 +1063,6 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
|||
seeds.push(FillSeed(xa, xb, y, 1));
|
||||
seeds.push(FillSeed(xa, xb, y, -1));
|
||||
|
||||
if (fillGaps && closeGaps) {
|
||||
// Set the ink on gaps that were used to 4095
|
||||
TPixelCM32 *tempPix = refCMRaster->pixels(0);
|
||||
tempPix += (y * refCMRaster->getLx()) + xa - 1;
|
||||
int i = xa;
|
||||
while (i <= xb) {
|
||||
if (tempPix->getInk() == styleIndex) {
|
||||
tempPix->setInk(fakeStyleIndex);
|
||||
}
|
||||
tempPix++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
while (!seeds.empty()) {
|
||||
FillSeed fs = seeds.top();
|
||||
seeds.pop();
|
||||
|
@ -1083,19 +1113,6 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
|||
clickedPosColor, fillDepth);
|
||||
// insert segment to be filled
|
||||
insertSegment(segments[y], std::pair<int, int>(xc, xd));
|
||||
if (fillGaps && closeGaps) {
|
||||
// Set the ink on gaps that were used to 4095
|
||||
TPixelCM32 *tempPix = refCMRaster->pixels(0);
|
||||
tempPix += (y * refCMRaster->getLx()) + xa - 1;
|
||||
int i = xa;
|
||||
while (i <= xb) {
|
||||
if (tempPix->getInk() == styleIndex) {
|
||||
tempPix->setInk(fakeStyleIndex);
|
||||
}
|
||||
tempPix++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// create new fillSeed to invert direction, if needed
|
||||
if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy));
|
||||
|
@ -1158,14 +1175,59 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
|||
}
|
||||
}
|
||||
|
||||
if (fillGaps && closeGaps) {
|
||||
// final check for close gap pixels
|
||||
if (fillGaps) {
|
||||
|
||||
TPixelCM32 *tempPix = refCMRaster->pixels();
|
||||
TPixel32 *keepPix = ras->pixels();
|
||||
int fillNeighbors;
|
||||
for (int tempY = 0; tempY < refCMRaster->getLy(); tempY++) {
|
||||
for (int tempX = 0; tempX < refCMRaster->getLx();
|
||||
tempX++, tempPix++, keepPix++) {
|
||||
if (tempPix->getInk() == fakeStyleIndex) {
|
||||
*keepPix = gapColor;
|
||||
// if (tempPix->getInk() == fakeStyleIndex) {
|
||||
if (tempPix->getInk() == styleIndex) {
|
||||
// how many fill pixel neighbors for the current pixel?
|
||||
fillNeighbors = 0;
|
||||
if ((tempX > 0) && *(keepPix - 1) == color) fillNeighbors++; // west
|
||||
if (tempX < ras->getLx() - 1 && *(keepPix + 1) == color)
|
||||
fillNeighbors++; // east
|
||||
if (tempY < ras->getLy() - 1 && *(keepPix + ras->getWrap()) == color)
|
||||
fillNeighbors++; // north
|
||||
if (tempY > 0 && *(keepPix - ras->getWrap()) == color)
|
||||
fillNeighbors++; // south
|
||||
if (fillNeighbors < 1) {
|
||||
// no neighboring fill pixels, this is an unused gap close pixel
|
||||
continue;
|
||||
} else if (fillNeighbors > 3) {
|
||||
// too many neighboring fill pixels to be a gap close pixel
|
||||
// , convert it to a fill pixel
|
||||
*keepPix = color;
|
||||
} else {
|
||||
// does it have at least one unpainted pixel neighbor?
|
||||
if (((tempX > 0) && (tempPix - 1)->getInk() == 0 &&
|
||||
(*(keepPix - 1) == clickedPosColor)) // west
|
||||
|| (tempX < refCMRaster->getLx() - 1 &&
|
||||
(tempPix + 1)->getInk() == 0 &&
|
||||
*(keepPix + 1) == clickedPosColor) // east
|
||||
|| (tempY < refCMRaster->getLy() - 1 &&
|
||||
(tempPix + refCMRaster->getWrap())->getInk() == 0 &&
|
||||
*(keepPix + ras->getWrap()) == clickedPosColor) // north
|
||||
|| (tempY > 0 &&
|
||||
(tempPix - refCMRaster->getWrap())->getInk() == 0 &&
|
||||
*(keepPix - ras->getWrap()) == clickedPosColor) // south
|
||||
) {
|
||||
// yes, persist it as a gap close pixel
|
||||
if (closeGaps) {
|
||||
*keepPix = gapColor;
|
||||
} else {
|
||||
*keepPix = color;
|
||||
}
|
||||
} else {
|
||||
// it is not acting as a border pixel so convert it to a fill
|
||||
// pixel
|
||||
*keepPix = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
#include "tpixelutils.h"
|
||||
|
||||
#include <stack>
|
||||
#include <tsystem.h>
|
||||
|
||||
#define IGNORECOLORSTYLE 4093
|
||||
#define GAP_CLOSE_TEMP 4094
|
||||
#define GAP_CLOSE_USED 4095
|
||||
|
||||
using namespace SkeletonLut;
|
||||
|
||||
|
@ -79,8 +84,7 @@ void fillArea(const TRasterCM32P &ras, TRegion *r, int colorId,
|
|||
for (int k = from; k < to; k++, pix++) {
|
||||
if (fillPaints && (!onlyUnfilled || pix->getPaint() == 0))
|
||||
pix->setPaint(colorId);
|
||||
if (fillInks && pix->getInk() != 4094) pix->setInk(colorId);
|
||||
if (pix->getInk() == 4094) pix->setInk(4095);
|
||||
if (fillInks && pix->getInk() != GAP_CLOSE_TEMP) pix->setInk(colorId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,11 +96,12 @@ 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
|
||||
// in order to make the paint to protrude 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;
|
||||
params.m_p = seeds[i].first;
|
||||
// params.m_styleId = seeds[i].second;
|
||||
params.m_styleId = IGNORECOLORSTYLE;
|
||||
fill(r, params);
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +142,171 @@ bool areRectPixelsTransparent(TPixel32 *pixels, TRect rect, int wrap) {
|
|||
} // namespace
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void finishGapLine(const TRasterCM32P &r, const TRasterCM32P &combined,
|
||||
const TPoint &pin, int clickedColorStyle, int fillColorStyle,
|
||||
int closeColorStyle, int searchRay, TRect *insideRect,
|
||||
bool closeGaps) {
|
||||
r->lock();
|
||||
|
||||
TRasterCM32P myCombined;
|
||||
if (!combined.getPointer() || combined->isEmpty()) {
|
||||
myCombined = r;
|
||||
} else {
|
||||
myCombined = combined;
|
||||
}
|
||||
|
||||
TPixelCM32 *pixels = (TPixelCM32 *)r->getRawData();
|
||||
TPixelCM32 *combinedPixels = (TPixelCM32 *)myCombined->getRawData();
|
||||
;
|
||||
TPoint p = pin;
|
||||
int filledNeighbor = 0;
|
||||
int unfilledNeighbor = 0;
|
||||
int inkStyle = 0;
|
||||
int paintStyle = 0;
|
||||
int toneValue = 0;
|
||||
|
||||
TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);
|
||||
TPixelCM32 *pixc = combinedPixels + (p.y * myCombined->getWrap() + p.x);
|
||||
|
||||
std::stack<TPoint> gapLinePixels;
|
||||
std::stack<TPoint> seeds;
|
||||
seeds.push(p);
|
||||
|
||||
while (!seeds.empty()) {
|
||||
p = seeds.top();
|
||||
seeds.pop();
|
||||
|
||||
if (!r->getBounds().contains(p)) {
|
||||
continue;
|
||||
}
|
||||
if (insideRect && !insideRect->contains(p)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);
|
||||
TPixelCM32 *pixc = combinedPixels + (p.y * myCombined->getWrap() + p.x);
|
||||
|
||||
// handle gap close pixel
|
||||
if (pix->getInk() == GAP_CLOSE_USED) continue;
|
||||
if (pix->getInk() == GAP_CLOSE_TEMP) {
|
||||
pix->setInk(GAP_CLOSE_USED);
|
||||
// push to the gapLinePixels collection for later processing as a line
|
||||
gapLinePixels.push(p);
|
||||
|
||||
// push neighboring pixels into the seeds queue
|
||||
seeds.push(TPoint(p.x - 1, p.y - 1)); // sw
|
||||
seeds.push(TPoint(p.x - 1, p.y)); // west
|
||||
seeds.push(TPoint(p.x - 1, p.y + 1)); // nw
|
||||
seeds.push(TPoint(p.x, p.y - 1)); // south
|
||||
seeds.push(TPoint(p.x, p.y + 1)); // north
|
||||
seeds.push(TPoint(p.x + 1, p.y - 1)); // se
|
||||
seeds.push(TPoint(p.x + 1, p.y)); // east
|
||||
seeds.push(TPoint(p.x + 1, p.y + 1)); // ne
|
||||
continue;
|
||||
}
|
||||
// a neighboring filled pixel
|
||||
if (pix->getTone() > 0 && pix->getPaint() == fillColorStyle) {
|
||||
filledNeighbor++;
|
||||
continue;
|
||||
}
|
||||
// a neighboring fillable but unfilled pixel
|
||||
if ((pix->getTone() == 255 &&
|
||||
((pix->getPaint() == clickedColorStyle) || (pix->getPaint() == 0) ||
|
||||
(pix->getPaint() == IGNORECOLORSTYLE))) &&
|
||||
(pixc->getTone() == 255 && ((pixc->getPaint() == clickedColorStyle) ||
|
||||
(pixc->getPaint() == 0)))) {
|
||||
unfilledNeighbor++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// determine the final disposition of the gap line
|
||||
if (filledNeighbor > 0) {
|
||||
if (unfilledNeighbor > 0) {
|
||||
if (closeGaps) {
|
||||
inkStyle = closeColorStyle;
|
||||
paintStyle = fillColorStyle;
|
||||
toneValue = 0;
|
||||
} else {
|
||||
inkStyle = 0;
|
||||
paintStyle = fillColorStyle;
|
||||
toneValue = 255;
|
||||
}
|
||||
} else {
|
||||
inkStyle = 0;
|
||||
paintStyle = fillColorStyle;
|
||||
toneValue = 255;
|
||||
}
|
||||
} else {
|
||||
inkStyle = IGNORECOLORSTYLE;
|
||||
paintStyle = 0;
|
||||
toneValue = 0;
|
||||
}
|
||||
|
||||
// process the stored gap close line pixels
|
||||
while (!gapLinePixels.empty()) {
|
||||
p = gapLinePixels.top();
|
||||
gapLinePixels.pop();
|
||||
|
||||
TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);
|
||||
|
||||
pix->setInk(inkStyle);
|
||||
pix->setPaint(paintStyle);
|
||||
pix->setTone(toneValue);
|
||||
}
|
||||
|
||||
r->unlock();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This function finishes candidate gap lines that were created
|
||||
// during a fill process.
|
||||
// combined is the levels combined as is done for the "use visible" tool option
|
||||
void finishGapLines(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore,
|
||||
const TRasterCM32P &combined, TPalette *plt,
|
||||
int clickedColorStyle, int fillIndex, int closeColorStyle,
|
||||
bool closeGaps) {
|
||||
assert(plt);
|
||||
TRasterCM32P r = rin->extract(rect);
|
||||
assert(r->getSize() == rbefore->getSize());
|
||||
assert(r->getSize() == combined->getSize());
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < r->getLy(); i++) {
|
||||
TPixelCM32 *pix = r->pixels(i);
|
||||
TPixelCM32 *pixb = rbefore->pixels(i);
|
||||
for (j = 0; j < r->getLx(); j++, pix++, pixb++) {
|
||||
int paint = pix->getPaint();
|
||||
int tone = pix->getTone();
|
||||
int ink = pix->getInk();
|
||||
|
||||
if (ink == GAP_CLOSE_TEMP &&
|
||||
(
|
||||
// north
|
||||
(i < rin->getLy() - 1 &&
|
||||
(pix + rin->getWrap())->getPaint() == fillIndex &&
|
||||
(pix + rin->getWrap())->getPaint() !=
|
||||
(pixb + rbefore->getWrap())->getPaint())
|
||||
// south
|
||||
|| (i > 0 && (pix - rin->getWrap())->getPaint() == fillIndex &&
|
||||
(pix - rin->getWrap())->getPaint() !=
|
||||
(pixb - rbefore->getWrap())->getPaint())
|
||||
// east
|
||||
|| (j < rin->getLx() - 1 && (pix + 1)->getPaint() == fillIndex &&
|
||||
(pix + 1)->getPaint() != (pixb + 1)->getPaint())
|
||||
// west
|
||||
|| (j > 0 && (pix - 1)->getPaint() == fillIndex &&
|
||||
(pix - 1)->getPaint() != (pixb - 1)->getPaint()))) {
|
||||
finishGapLine(rin, combined, TPoint(j, i) + rect.getP00(),
|
||||
clickedColorStyle, fillIndex, closeColorStyle, 0, &rect,
|
||||
closeGaps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// AreaFiller
|
||||
|
||||
|
@ -154,10 +324,9 @@ AreaFiller::AreaFiller(const TRasterCM32P &ras)
|
|||
AreaFiller::~AreaFiller() { m_ras->unlock(); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// questa funzione viene chiamata dopo il fill rect delle aree, e colora gli
|
||||
// inchiostri di tipo "autoink"
|
||||
// che confinano con le aree appena fillate con il rect. rbefore e' il rect del
|
||||
// raster prima del rectfill.
|
||||
// This function is called after rect fill of the areas, and colors the
|
||||
// "autoink" type inks bordering the areas just filled with the rect.
|
||||
// rbefore is the rect of the raster before rectfill.
|
||||
void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore,
|
||||
TPalette *plt, int fillIndex) {
|
||||
assert(plt);
|
||||
|
@ -172,9 +341,36 @@ void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore,
|
|||
int paint = pix->getPaint();
|
||||
int tone = pix->getTone();
|
||||
int ink = pix->getInk();
|
||||
if (paint != pixb->getPaint() && paint == fillIndex && ink != paint &&
|
||||
plt->getStyle(ink)->getFlags() != 0)
|
||||
inkFill(rin, TPoint(j, i) + rect.getP00(), paint, 0, NULL, &rect);
|
||||
|
||||
/* new
|
||||
* Pseudocode:
|
||||
* Start the inkFill procedure at the current pixel if:
|
||||
* The ink colorstyle has autopaint enabled
|
||||
* The ink colorstyle is not already the same as the fill colorstyle
|
||||
* The paint colorstyle of a neighboring pixel:
|
||||
* is the same as the fill colorstyle
|
||||
* has changed from its prior version
|
||||
*/
|
||||
|
||||
if (plt->getStyle(ink)->getFlags() != 0 && ink != fillIndex &&
|
||||
(
|
||||
// north
|
||||
(i < r->getLy() - 1 &&
|
||||
(pix + r->getWrap())->getPaint() == fillIndex &&
|
||||
(pix + r->getWrap())->getPaint() !=
|
||||
(pixb + rbefore->getWrap())->getPaint())
|
||||
// south
|
||||
|| (i > 0 && (pix - r->getWrap())->getPaint() == fillIndex &&
|
||||
(pix - r->getWrap())->getPaint() !=
|
||||
(pixb - rbefore->getWrap())->getPaint())
|
||||
// east
|
||||
|| (j < r->getLx() - 1 && (pix + 1)->getPaint() == fillIndex &&
|
||||
(pix + 1)->getPaint() != (pixb + 1)->getPaint())
|
||||
// west
|
||||
|| (j > 0 && (pix - 1)->getPaint() == fillIndex &&
|
||||
(pix - 1)->getPaint() != (pixb - 1)->getPaint()))) {
|
||||
inkFill(rin, TPoint(j, i) + rect.getP00(), fillIndex, 0, NULL, &rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,19 +380,21 @@ void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore,
|
|||
bool AreaFiller::rectFill(const TRect &rect, int color, bool onlyUnfilled,
|
||||
bool fillPaints, bool fillInks) {
|
||||
// Synopsis:
|
||||
// This gets the color of the pixes at the edge of the rect
|
||||
// This gets the color of the pixels at the edge of the rect
|
||||
// Then fills in EVERYTHING with 'color'
|
||||
// Then uses the fill command to fill in the edges with their original color
|
||||
// This makes sure only the enclosed areas not on the edge get filled.
|
||||
/*- In case of FillInk only -*/
|
||||
|
||||
if (!fillPaints) {
|
||||
assert(fillInks);
|
||||
assert(m_ras->getBounds().contains(rect));
|
||||
for (int y = rect.y0; y <= rect.y1; y++) {
|
||||
TPixelCM32 *pix = m_ras->pixels(y) + rect.x0;
|
||||
for (int x = rect.x0; x <= rect.x1; x++, pix++) {
|
||||
if (pix->getInk() == 4094)
|
||||
pix->setInk(4095);
|
||||
if (pix->getInk() == GAP_CLOSE_TEMP)
|
||||
//pix->setInk(TEMP_GAP_CLOSE_WAS_USED);
|
||||
continue;
|
||||
else
|
||||
pix->setInk(color);
|
||||
}
|
||||
|
@ -249,18 +447,16 @@ bool AreaFiller::rectFill(const TRect &rect, int color, bool onlyUnfilled,
|
|||
for (x = r.x0; x <= r.x1; x++, pix++) {
|
||||
if (pix->getPaint() == 0) // BackgroundStyle
|
||||
pix->setPaint(color);
|
||||
if (fillInks && (pix->getInk() != 4094 && pix->getInk() != 4095))
|
||||
if (fillInks && (pix->getInk() != GAP_CLOSE_TEMP && pix->getInk() != GAP_CLOSE_USED))
|
||||
pix->setInk(color);
|
||||
if (pix->getInk() == 4094) pix->setInk(4095);
|
||||
}
|
||||
}
|
||||
else
|
||||
for (y = r.y0; y <= r.y1; y++, pix += m_wrap - dx - 1) {
|
||||
for (x = r.x0; x <= r.x1; x++, pix++) {
|
||||
pix->setPaint(color);
|
||||
if (fillInks && (pix->getInk() != 4094 && pix->getInk() != 4095))
|
||||
if (fillInks && (pix->getInk() != GAP_CLOSE_TEMP && pix->getInk() != GAP_CLOSE_USED))
|
||||
pix->setInk(color);
|
||||
if (pix->getInk() == 4094) pix->setInk(4095);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,14 +519,26 @@ void AreaFiller::strokeFill(TStroke *stroke, int colorId, bool onlyUnfilled,
|
|||
|
||||
TVectorImage app;
|
||||
app.addStroke(stroke);
|
||||
|
||||
app.findRegions();
|
||||
|
||||
//std::cout << "\nAreaFiller::strokeFill().fillArea()";
|
||||
|
||||
for (UINT i = 0; i < app.getRegionCount(); i++)
|
||||
fillArea(m_ras, app.getRegion(i), colorId, onlyUnfilled, fillPaints,
|
||||
fillInks);
|
||||
|
||||
//std::cout << "\nAreaFiller::strokeFill(), after fillArea()";
|
||||
//outputPixels("tempRaster", m_ras); // issue 1151
|
||||
|
||||
app.removeStroke(0);
|
||||
|
||||
stroke->transform(TTranslation(convert(-m_ras->getCenter())));
|
||||
restoreColors(m_ras, seeds);
|
||||
|
||||
//std::cout << "\nAreaFiller::strokeFill(), after restoreColors()";
|
||||
//outputPixels("tempRaster", m_ras); // issue 1151
|
||||
|
||||
m_ras->unlock();
|
||||
}
|
||||
|
||||
|
@ -412,7 +620,7 @@ void FullColorAreaFiller::rectFill(const TRect &rect,
|
|||
//=============================================================================
|
||||
// InkSegmenter
|
||||
|
||||
const int damInk = 4094;
|
||||
const int damInk = 4094; //same value as the tempoary gap close lines?
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -57,12 +57,15 @@ void StrokeGenerator::filterPoints() {
|
|||
|
||||
// filtra m_points iniziali: generalmente elevate variazioni di thickness
|
||||
// si hanno tra m_points[0] (al massimo m_points[1]) e i successivi)
|
||||
// filter initial m_points: usually large thickness variations
|
||||
// you have between m_points[0] (at most m_points[1]) and the following ones)
|
||||
int size1 = m_points.size();
|
||||
int kMin = 0;
|
||||
int kMax = std::min(
|
||||
4,
|
||||
size1 -
|
||||
2); // confronta 5 m_points iniziali con i successivi corrispondenti
|
||||
// compare initial 5 m_points with subsequent matched ones
|
||||
int k = kMax;
|
||||
for (k = kMax; k >= kMin; --k) {
|
||||
TThickPoint currPoint = m_points[k];
|
||||
|
@ -72,10 +75,12 @@ void StrokeGenerator::filterPoints() {
|
|||
if (deltaThick > 0.6 * dist) // deltaThick <= dist (condizione
|
||||
// approssimata di non-autocontenimento per
|
||||
// TTQ)
|
||||
// deltaThick <= dist (approximate non-self-contained condition for TTQ)
|
||||
{
|
||||
vector<TThickPoint>::iterator it1 = m_points.begin();
|
||||
vector<TThickPoint>::iterator it2 = it1 + k + 1;
|
||||
m_points.erase(it1, it2); // cancella da m_points[0] a m_points[k]
|
||||
// delete from m_points[0] to m_points[k]
|
||||
assert((int)m_points.size() == size1 - k - 1);
|
||||
break;
|
||||
}
|
||||
|
@ -83,11 +88,15 @@ void StrokeGenerator::filterPoints() {
|
|||
// filtra m_points finali: generalmente elevate variazioni di thickness
|
||||
// si hanno tra m_points[size - 1] (al massimo m_points[size - 2]) e i
|
||||
// predecessori)
|
||||
// filter final m_points: usually large thickness variations
|
||||
// have between m_points[size - 1] (at most m_points[size - 2]) and i
|
||||
// predecessors)
|
||||
int size2 = m_points.size();
|
||||
kMax = size2 - 1;
|
||||
kMin = std::max(
|
||||
kMax - 4,
|
||||
1); // confronta 5 m_points finali con i predecessori corrispondenti
|
||||
// compare final 5 m_points with matching ancestors
|
||||
k = kMin;
|
||||
for (k = kMin; k <= kMax; ++k) {
|
||||
TThickPoint currPoint = m_points[k];
|
||||
|
@ -100,6 +109,7 @@ void StrokeGenerator::filterPoints() {
|
|||
{
|
||||
int kTmp = k;
|
||||
while (k <= kMax) // cancella da m_points[k] a m_points[size2 - 1]
|
||||
// delete from m_points[k] to m_points[size2 - 1]
|
||||
{
|
||||
m_points.pop_back();
|
||||
++k;
|
||||
|
|
Loading…
Reference in a new issue