@mark1russell7/packing 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/skyline.ts CHANGED
@@ -156,6 +156,9 @@ export function packSkyline<T>(rects: Rect<T>[], outer: Rect<T>, options: Skylin
156
156
  /**
157
157
  * This function packs rectangles with a skyline in a free space. Each cell has a free range: the skyline is its start,
158
158
  * and `limit` is its end. A cell with less room than the lowest rectangle left goes to its next free range.
159
+ *
160
+ * A rectangle that needs more cells than the outer rectangle has goes at the left edge. Its y is the first y where each
161
+ * cell is free over its height. Then each cell starts after the rectangle, as in the plain skyline.
159
162
  */
160
163
  function packSkylineInSpace<T>(rects: Rect<T>[], outer: Rect<T>, order: SortOrder, space: FreeSpace): Rect<T> {
161
164
  const width = Math.floor(outer.size.x);
@@ -198,9 +201,29 @@ function packSkylineInSpace<T>(rects: Rect<T>[], outer: Rect<T>, order: SortOrde
198
201
  x = 0;
199
202
  y = 0;
200
203
  for (let i = 0; i < width; i++) if (Number.isFinite(skyline[i]!) && skyline[i]! > y) y = skyline[i]!;
204
+ // The rectangle covers each cell, thus it goes to the first y where each cell is free over its height
205
+ for (let moved = true; moved; ) {
206
+ moved = false;
207
+ for (let i = 0; i < width; i++) {
208
+ if (!Number.isFinite(skyline[i]!)) continue;
209
+ const [s, e] = rangeOf(i, y);
210
+ const next = s > y ? s : e < y + rh ? rangeOf(i, e)[0] : y;
211
+ if (next > y && Number.isFinite(next)) {
212
+ y = next;
213
+ moved = true;
214
+ }
215
+ }
216
+ }
201
217
  rect.position.set(x + ox, y + oy);
202
218
  rect.wasPacked = true;
203
- outer.size.y = Math.max(outer.size.y, y + rh);
219
+ const top = y + rh;
220
+ // Each cell starts after the rectangle. A cell with a range that ends before the top of the rectangle goes to its next range.
221
+ for (let i = 0; i < width; i++) {
222
+ if (!Number.isFinite(skyline[i]!)) continue;
223
+ if (top <= limit[i]!) skyline[i] = top;
224
+ else [skyline[i], limit[i]] = rangeOf(i, top);
225
+ }
226
+ outer.size.y = Math.max(outer.size.y, top);
204
227
  continue;
205
228
  }
206
229
  let found = findWindow(skyline, width, rw, limit, rh);