From 39a6bce51e9b98808ca1b7e07d82aa79b7eb5712 Mon Sep 17 00:00:00 2001 From: Gaspar Capello Date: Tue, 8 Aug 2023 11:21:10 -0300 Subject: [PATCH] Fix overlapped shape padding between frame images on Packed sheet type (fix aseprite/aseprite#3993) Prior to this fix, the shape padding generated by 'Export Sprite Sheet' overlapped on some frame images when the following options were chosen: - Packed sheet type - Trim Cels = true - Spacing > 0 (shape padding > 0) --- gfx/packing_rects.cpp | 44 ++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/gfx/packing_rects.cpp b/gfx/packing_rects.cpp index 9b24e894d..7a1d25b51 100644 --- a/gfx/packing_rects.cpp +++ b/gfx/packing_rects.cpp @@ -1,5 +1,5 @@ // LAF Gfx Library -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2023 Igara Studio S.A. // Copyright (C) 2001-2014 David Capello // // This file is released under the terms of the MIT license. @@ -52,9 +52,11 @@ Size PackingRects::bestFit(base::task_token& token, bool fit = false; while (!token.canceled()) { if (w*h >= neededArea) { - fit = pack(Size(w, h), token); + Size sizeCandidate = Size(w + 2 * m_borderPadding, + h + 2 * m_borderPadding); + fit = pack(sizeCandidate, token); if (fit) { - size = Size(w, h); + size = sizeCandidate; break; } } @@ -101,25 +103,33 @@ bool PackingRects::pack(const Size& size, gfx::Rect& rc = *rcPtr; - // The rectangles are treated as its original size during placement, - // but occupies an extra border of pixels once its - // position has been determined. - // This ensures that all rectangles are padded by pixels, - // and are still placed correctly near edges, e.g. when remaining - // horizontal space is between and +. - for (int v=0; v<=m_bounds.h-rc.h; ++v) { - for (int u=0; u<=m_bounds.w-rc.w; ++u) { + // The rectangles are treated as its original size + + // conditional extra border of during placement. + for (int v = 0; v <= m_bounds.h - rc.h; ++v) { + int hShapePadding = + (v == (m_bounds.h - rc.h) ? 0 : m_shapePadding); + for (int u = 0; u <= m_bounds.w - rc.w; ++u) { if (token.canceled()) return false; - gfx::Rect possible(m_bounds.x + u, m_bounds.y + v, rc.w, rc.h); + // It's necessary to consider the as an + // integral part of the image size; otherwise, the region + // subtraction process may be incorrect, resulting in + // overlapping of shape padding between adjacent sprites. + // This fix resolves the special cases of exporting with + // sheet type 'Packed' + 'Trim Cels' true + + // 'Shape padding' > 0 + series of particular image sizes. + int wShapePadding = + (u == (m_bounds.w - rc.w) ? 0 : m_shapePadding); + gfx::Rect possible(m_bounds.x + u, + m_bounds.y + v, + rc.w + wShapePadding, + rc.h + hShapePadding); + Region::Overlap overlap = rgn.contains(possible); if (overlap == Region::In) { - rc = possible; - rgn.createSubtraction( - rgn, - gfx::Region(Rect(rc).inflate(m_shapePadding)) - ); + rc = Rect(m_bounds.x + u, m_bounds.y + v, rc.w, rc.h); + rgn.createSubtraction(rgn, gfx::Region(Rect(possible))); goto next_rc; } }