90 const QRect& mapBounds,
91 const FillOpacityFunc& fillOpacityFunc)
93 , m_size(mapBounds.size())
94 , m_numTiles(qCeil(static_cast<float>(m_size.width()) / TileSize),
95 qCeil(static_cast<float>(m_size.height()) / TileSize))
96 , m_fillOpacityFunc(fillOpacityFunc)
101 KIS_ASSERT((mapBounds.x() == 0) && (mapBounds.y() == 0) &&
102 "Gap closing fill assumes x and y start at coordinate (0, 0)");
104 Data defaultPixel {};
150 for (
int x = x1; x <= x2; ++x) {
151 if (isOpaque<true>(x, y)) {
152 gapDistanceSearch<true>(x, y, TransformNone);
153 gapDistanceSearch<true>(x, y, TransformRotateClockwiseMirrorHorizontally);
154 gapDistanceSearch<true>(x, y, TransformRotateClockwise);
155 gapDistanceSearch<true>(x, y, TransformMirrorHorizontally);
159 for (
int x = x1; x <= x2; ++x) {
160 if (isOpaque<false>(x, y)) {
161 gapDistanceSearch<false>(x, y, TransformNone);
162 gapDistanceSearch<false>(x, y, TransformRotateClockwiseMirrorHorizontally);
163 gapDistanceSearch<false>(x, y, TransformRotateClockwise);
164 gapDistanceSearch<false>(x, y, TransformMirrorHorizontally);
182#if KIS_GAP_MAP_MEASURE_ELAPSED_TIME
198 const bool tileOpaqueTopLeft = (nearbyTilesRect.left() == tile.x()) || (nearbyTilesRect.top() == tile.y()) ?
false : (*
tileFlagsPtr(tile.x() - 1, tile.y() - 1) &
TILE_HAS_OPAQUE_PIXELS) != 0;
199 const bool tileOpaqueBottomLeft = (nearbyTilesRect.left() == tile.x()) || (nearbyTilesRect.bottom() == tile.y()) ?
false : (*
tileFlagsPtr(tile.x() - 1, tile.y() + 1) &
TILE_HAS_OPAQUE_PIXELS) != 0;
203 if (! (tileOpaqueTopLeft || tileOpaqueTop || tileOpaqueLeft || tileOpaque || tileOpaqueBottomLeft || tileOpaqueBottom)) {
207#if KIS_GAP_MAP_MEASURE_ELAPSED_TIME
208 m_distanceElapsedNanos += timer.nsecsElapsed();
215 rect.setRight(qMin(rect.right(),
m_size.width() - 1));
216 rect.setBottom(qMin(rect.bottom(),
m_size.height() - 1));
223 const int guardBandVertical = qMin(guardBand, 31);
224 const int y1 = tileOpaqueTopLeft || tileOpaqueTop ? qMax(0, rect.top() - guardBandVertical) : rect.top();
225 const int y2 = tileOpaqueBottomLeft || tileOpaqueBottom ? qMin(rect.bottom() + guardBandVertical,
m_size.height() - 1) : rect.bottom();
226 const int x1Top = tileOpaqueTopLeft ? qMax(0, rect.left() - guardBand) : rect.left();
227 const int x1Middle = tileOpaqueLeft ? qMax(0, rect.left() - guardBand) : rect.left();
228 const int x1Bottom = tileOpaqueBottomLeft ? qMax(0, rect.left() - guardBand) : rect.left();
229 const int x2Top = tileOpaqueTop ? rect.right() : rect.left() - 1;
230 const int x2Middle = tileOpaque ? rect.right() : rect.left() - 1;
231 const int x2Bottom = tileOpaqueBottom ? rect.right() : rect.left() - 1;
234 const bool boundsCheck =
243 for (
int y = y1; y <= rect.top() - 1; ++y) {
247 for (
int y = rect.top(); y <= rect.bottom(); ++y) {
251 for (
int y = rect.bottom() + 1; y <= y2; ++y) {
255#if KIS_GAP_MAP_MEASURE_ELAPSED_TIME
256 m_distanceElapsedNanos += timer.nsecsElapsed();
283 if (isOpaque<BoundsCheck>(op(x, y, 0, -1)) ||
284 isOpaque<BoundsCheck>(op(x, y, 1, -1))) {
288 for (
int yoffs = 2; yoffs <
m_gapSize + 2; ++yoffs) {
289 const int yDistanceSq = (yoffs - 1) * (yoffs - 1);
291 for (
int xoffs = 0; xoffs <= yoffs; ++xoffs) {
292 const int offsetDistance = yDistanceSq + xoffs * xoffs;
298 if (isOpaque<BoundsCheck>(op(x, y, xoffs, -yoffs))) {
299 const float dx =
static_cast<float>(xoffs) / (yoffs - 1);
303 for (
int cy = 1; cy < yoffs; ++cy) {
307 if (
static_cast<int>(tx) > cx) {
336#if KIS_GAP_MAP_DEBUG_LOGGING_AND_ASSERTS
337 qDebug() <<
"lazyDistance() at (" << x <<
"," << y <<
")";
344 const QPoint topLeft(qMax(0, tx - 1),
346 const QPoint bottomRight(qMin(tx + 1,
m_numTiles.width() - 1),
348 const QRect nearbyTiles = QRect(topLeft, bottomRight);