void ToolLoopManager::calculateDirtyArea(ToolLoop* loop, const Points& points, Region& dirty_area) { dirty_area.clear(); if (points.size() > 0) { Point minpt, maxpt; calculateMinMax(points, minpt, maxpt); // Expand the dirty-area with the pen width Rect r1, r2; loop->getPointShape()->getModifiedArea(loop, minpt.x, minpt.y, r1); loop->getPointShape()->getModifiedArea(loop, maxpt.x, maxpt.y, r2); dirty_area.createUnion(dirty_area, Region(r1.createUnion(r2))); } // Apply offset mode Point offset(loop->getOffset()); dirty_area.offset(-offset); // Apply tiled mode TiledMode tiledMode = loop->getDocumentSettings()->getTiledMode(); if (tiledMode != TILED_NONE) { int w = loop->sprite()->width(); int h = loop->sprite()->height(); Region sprite_area(Rect(0, 0, w, h)); Region outside; outside.createSubtraction(dirty_area, sprite_area); switch (tiledMode) { case TILED_X_AXIS: outside.createIntersection(outside, Region(Rect(-w*10000, 0, w*20000, h))); break; case TILED_Y_AXIS: outside.createIntersection(outside, Region(Rect(0, -h*10000, w, h*20000))); break; } Rect outsideBounds = outside.getBounds(); if (outsideBounds.x < 0) outside.offset(w * (1+((-outsideBounds.x) / w)), 0); if (outsideBounds.y < 0) outside.offset(0, h * (1+((-outsideBounds.y) / h))); int x1 = outside.getBounds().x; while (true) { Region in_sprite; in_sprite.createIntersection(outside, sprite_area); outside.createSubtraction(outside, in_sprite); dirty_area.createUnion(dirty_area, in_sprite); outsideBounds = outside.getBounds(); if (outsideBounds.isEmpty()) break; else if (outsideBounds.x+outsideBounds.w > w) outside.offset(-w, 0); else if (outsideBounds.y+outsideBounds.h > h) outside.offset(x1-outsideBounds.x, -h); else break; } } }
void ToolLoopManager::calculateDirtyArea(const Points& points) { // Save the current dirty area if it's needed Region prevDirtyArea; if (m_toolLoop->getTracePolicy() == TracePolicy::Last) prevDirtyArea = m_dirtyArea; // Start with a fresh dirty area m_dirtyArea.clear(); if (points.size() > 0) { Point minpt, maxpt; calculateMinMax(points, minpt, maxpt); // Expand the dirty-area with the pen width Rect r1, r2; m_toolLoop->getPointShape()->getModifiedArea(m_toolLoop, minpt.x, minpt.y, r1); m_toolLoop->getPointShape()->getModifiedArea(m_toolLoop, maxpt.x, maxpt.y, r2); m_dirtyArea.createUnion(m_dirtyArea, Region(r1.createUnion(r2))); } // Apply offset mode Point offset(m_toolLoop->getOffset()); m_dirtyArea.offset(-offset); // Merge new dirty area with the previous one (for tools like line // or rectangle it's needed to redraw the previous position and // the new one) if (m_toolLoop->getTracePolicy() == TracePolicy::Last) m_dirtyArea.createUnion(m_dirtyArea, prevDirtyArea); // Apply tiled mode TiledMode tiledMode = m_toolLoop->getTiledMode(); if (tiledMode != TiledMode::NONE) { int w = m_toolLoop->sprite()->width(); int h = m_toolLoop->sprite()->height(); Region sprite_area(Rect(0, 0, w, h)); Region outside; outside.createSubtraction(m_dirtyArea, sprite_area); switch (tiledMode) { case TiledMode::X_AXIS: outside.createIntersection(outside, Region(Rect(-w*10000, 0, w*20000, h))); break; case TiledMode::Y_AXIS: outside.createIntersection(outside, Region(Rect(0, -h*10000, w, h*20000))); break; } Rect outsideBounds = outside.bounds(); if (outsideBounds.x < 0) outside.offset(w * (1+((-outsideBounds.x) / w)), 0); if (outsideBounds.y < 0) outside.offset(0, h * (1+((-outsideBounds.y) / h))); int x1 = outside.bounds().x; while (true) { Region in_sprite; in_sprite.createIntersection(outside, sprite_area); outside.createSubtraction(outside, in_sprite); m_dirtyArea.createUnion(m_dirtyArea, in_sprite); outsideBounds = outside.bounds(); if (outsideBounds.isEmpty()) break; else if (outsideBounds.x+outsideBounds.w > w) outside.offset(-w, 0); else if (outsideBounds.y+outsideBounds.h > h) outside.offset(x1-outsideBounds.x, -h); else break; } } }
// Strokes are relative to sprite origin. void ToolLoopManager::calculateDirtyArea(const Strokes& strokes) { // Save the current dirty area if it's needed Region prevDirtyArea; if (m_toolLoop->getTracePolicy() == TracePolicy::Last) prevDirtyArea = m_dirtyArea; // Start with a fresh dirty area m_dirtyArea.clear(); const Point celOrigin = m_toolLoop->getCelOrigin(); for (auto& stroke : strokes) { gfx::Rect strokeBounds = stroke.bounds(); if (strokeBounds.isEmpty()) continue; // Expand the dirty-area with the pen width Rect r1, r2; m_toolLoop->getPointShape()->getModifiedArea( m_toolLoop, strokeBounds.x - celOrigin.x, strokeBounds.y - celOrigin.y, r1); m_toolLoop->getPointShape()->getModifiedArea( m_toolLoop, strokeBounds.x+strokeBounds.w-1 - celOrigin.x, strokeBounds.y+strokeBounds.h-1 - celOrigin.y, r2); m_dirtyArea.createUnion(m_dirtyArea, Region(r1.createUnion(r2))); } // Make the dirty area relative to the sprite. m_dirtyArea.offset(celOrigin); // Merge new dirty area with the previous one (for tools like line // or rectangle it's needed to redraw the previous position and // the new one) if (m_toolLoop->getTracePolicy() == TracePolicy::Last) m_dirtyArea.createUnion(m_dirtyArea, prevDirtyArea); // Apply tiled mode TiledMode tiledMode = m_toolLoop->getTiledMode(); if (tiledMode != TiledMode::NONE) { int w = m_toolLoop->sprite()->width(); int h = m_toolLoop->sprite()->height(); Region sprite_area(Rect(0, 0, w, h)); Region outside; outside.createSubtraction(m_dirtyArea, sprite_area); switch (tiledMode) { case TiledMode::X_AXIS: outside.createIntersection(outside, Region(Rect(-w*10000, 0, w*20000, h))); break; case TiledMode::Y_AXIS: outside.createIntersection(outside, Region(Rect(0, -h*10000, w, h*20000))); break; } Rect outsideBounds = outside.bounds(); if (outsideBounds.x < 0) outside.offset(w * (1+((-outsideBounds.x) / w)), 0); if (outsideBounds.y < 0) outside.offset(0, h * (1+((-outsideBounds.y) / h))); int x1 = outside.bounds().x; while (true) { Region in_sprite; in_sprite.createIntersection(outside, sprite_area); outside.createSubtraction(outside, in_sprite); m_dirtyArea.createUnion(m_dirtyArea, in_sprite); outsideBounds = outside.bounds(); if (outsideBounds.isEmpty()) break; else if (outsideBounds.x+outsideBounds.w > w) outside.offset(-w, 0); else if (outsideBounds.y+outsideBounds.h > h) outside.offset(x1-outsideBounds.x, -h); else break; } } }