@mapka/shelf-pack 0.4.1 → 0.4.3

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/index.js CHANGED
@@ -1,32 +1,3 @@
1
- export default ShelfPack;
2
-
3
-
4
- /**
5
- * Create a new ShelfPack bin allocator.
6
- *
7
- * Uses the Shelf Best Height Fit algorithm from
8
- * http://clb.demon.fi/files/RectangleBinPack.pdf
9
- *
10
- * @class ShelfPack
11
- * @param {number} [w=64] Initial width of the sprite
12
- * @param {number} [h=64] Initial width of the sprite
13
- * @param {Object} [options]
14
- * @param {boolean} [options.autoResize=false] If `true`, the sprite will automatically grow
15
- * @example
16
- * var sprite = new ShelfPack(64, 64, { autoResize: false });
17
- */
18
- function ShelfPack(w, h, options) {
19
- options = options || {};
20
- this.w = w || 64;
21
- this.h = h || 64;
22
- this.autoResize = !!options.autoResize;
23
- this.shelves = [];
24
- this.freebins = [];
25
- this.stats = {};
26
- this.bins = {};
27
- this.maxId = 0;
28
- }
29
-
30
1
  /**
31
2
  * Bin object with `id`, `width`, `height` properties
32
3
  * @typedef {Object} BinShorthand
@@ -37,427 +8,452 @@ function ShelfPack(w, h, options) {
37
8
 
38
9
 
39
10
  /**
40
- * Bin object with `id`, `w`, `h` properties
41
- * @typedef {Object} Bin
42
- * @property {string} id Unique identifier for this bin
43
- * @property {number} width Width of the bin
44
- * @property {number} height Height of the bin
45
- */
46
-
47
-
48
- /**
49
- * Batch pack multiple bins into the sprite.
11
+ * Create a new ShelfPack bin allocator.
12
+ *
13
+ * Uses the Shelf Best Height Fit algorithm from
14
+ * http://clb.demon.fi/files/RectangleBinPack.pdf
50
15
  *
51
- * @param {Object[]} bins Array of requested bins - each object should have `width`, `height` (or `w`, `h`) properties
52
- * @param {Object} [options]
53
- * @param {boolean} [options.inPlace=false] If `true`, the supplied bin objects will be updated inplace with `x` and `y` properties
54
- * @returns {Bin[]} Array of allocated Bins - each Bin is an object with `id`, `x`, `y`, `w`, `h` properties
55
- * @noto Mutate input bins
56
16
  * @example
57
- * var bins = [
58
- * { id: 1, w: 12, h: 12 },
59
- * { id: 2, w: 12, h: 16 },
60
- * { id: 3, w: 12, h: 24 }
61
- * ];
62
- * var results = sprite.pack(bins, { inPlace: false });
17
+ * var sprite = new ShelfPack(64, 64, { autoResize: false });
63
18
  */
64
- ShelfPack.prototype.pack = function(bins, options) {
65
- bins = [].concat(bins);
66
- options = options || {};
67
-
68
- var results = [],
69
- w, h, id, allocation;
70
-
71
- for (var i = 0; i < bins.length; i++) {
72
- w = bins[i].w || bins[i].width;
73
- h = bins[i].h || bins[i].height;
74
- id = bins[i].id;
19
+ export default class ShelfPack {
20
+ /**
21
+ * @param {number} [w=64] Initial width of the sprite
22
+ * @param {number} [h=64] Initial width of the sprite
23
+ * @param {Object} [options]
24
+ * @param {boolean} [options.autoResize=false] If `true`, the sprite will automatically grow
25
+ */
26
+ constructor(w, h, options) {
27
+ options = options || {};
28
+ this.w = w || 64;
29
+ this.h = h || 64;
30
+ this.autoResize = !!options.autoResize;
31
+ this.shelves = [];
32
+ this.freebins = [];
33
+ this.stats = {};
34
+ this.bins = {};
35
+ this.maxId = 0;
36
+ }
75
37
 
76
- if (w && h) {
77
- allocation = this.packOne(w, h, id);
78
- if (!allocation) {
79
- continue;
38
+ /**
39
+ * Batch pack multiple bins into the sprite.
40
+ *
41
+ * @param {Object[]} bins Array of requested bins - each object should have `width`, `height` (or `w`, `h`) properties
42
+ * @param {Object} [options]
43
+ * @param {boolean} [options.inPlace=false] If `true`, the supplied bin objects will be updated inplace with `x` and `y` properties
44
+ * @returns {Bin[]} Array of allocated Bins - each Bin is an object with `id`, `x`, `y`, `w`, `h` properties
45
+ * @noto Mutate input bins
46
+ * @example
47
+ * var bins = [
48
+ * { id: 1, w: 12, h: 12 },
49
+ * { id: 2, w: 12, h: 16 },
50
+ * { id: 3, w: 12, h: 24 }
51
+ * ];
52
+ * var results = sprite.pack(bins, { inPlace: false });
53
+ */
54
+ pack(bins, options) {
55
+ bins = [].concat(bins);
56
+ options = options || {};
57
+
58
+ var results = [],
59
+ w, h, id, allocation;
60
+
61
+ for (var i = 0; i < bins.length; i++) {
62
+ w = bins[i].w || bins[i].width;
63
+ h = bins[i].h || bins[i].height;
64
+ id = bins[i].id;
65
+
66
+ if (w && h) {
67
+ allocation = this.packOne(w, h, id);
68
+ if (!allocation) {
69
+ continue;
70
+ }
71
+ if (options.inPlace) {
72
+ bins[i].x = allocation.x;
73
+ bins[i].y = allocation.y;
74
+ bins[i].id = allocation.id;
75
+ }
76
+ results.push(allocation);
80
77
  }
81
- if (options.inPlace) {
82
- bins[i].x = allocation.x;
83
- bins[i].y = allocation.y;
84
- bins[i].id = allocation.id;
85
- }
86
- results.push(allocation);
87
78
  }
88
- }
89
79
 
90
- this.shrink();
80
+ this.shrink();
91
81
 
92
- return results;
93
- };
82
+ return results;
83
+ }
94
84
 
95
85
 
96
- /**
97
- * Pack a single bin into the sprite.
98
- *
99
- * Each bin will have a unique identitifer.
100
- * If no identifier is supplied in the `id` parameter, one will be created.
101
- * Note: The supplied `id` is used as an object index, so numeric values are fastest!
102
- *
103
- * Bins are automatically refcounted (i.e. a newly packed Bin will have a refcount of 1).
104
- * When a bin is no longer needed, use the `ShelfPack.unref` function to mark it
105
- * as unused. When a Bin's refcount decrements to 0, the Bin will be marked
106
- * as free and its space may be reused by the packing code.
107
- *
108
- * @param {number} w Width of the bin to allocate
109
- * @param {number} h Height of the bin to allocate
110
- * @param {number|string} [id] Unique identifier for this bin, (if unsupplied, assume it's a new bin and create an id)
111
- * @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties, or `null` if allocation failed
112
- * @example
113
- * var results = sprite.packOne(12, 16, 'a');
114
- */
115
- ShelfPack.prototype.packOne = function(w, h, id) {
116
- var best = { freebin: -1, shelf: -1, waste: Infinity },
117
- y = 0,
118
- bin, shelf, waste, i;
119
-
120
- // if id was supplied, attempt a lookup..
121
- if (typeof id === 'string' || typeof id === 'number') {
122
- bin = this.getBin(id);
123
- if (bin) { // we packed this bin already
124
- this.ref(bin);
125
- return bin;
126
- }
127
- if (typeof id === 'number') {
128
- this.maxId = Math.max(id, this.maxId);
86
+ /**
87
+ * Pack a single bin into the sprite.
88
+ *
89
+ * Each bin will have a unique identitifer.
90
+ * If no identifier is supplied in the `id` parameter, one will be created.
91
+ * Note: The supplied `id` is used as an object index, so numeric values are fastest!
92
+ *
93
+ * Bins are automatically refcounted (i.e. a newly packed Bin will have a refcount of 1).
94
+ * When a bin is no longer needed, use the `ShelfPack.unref` function to mark it
95
+ * as unused. When a Bin's refcount decrements to 0, the Bin will be marked
96
+ * as free and its space may be reused by the packing code.
97
+ *
98
+ * @param {number} w Width of the bin to allocate
99
+ * @param {number} h Height of the bin to allocate
100
+ * @param {number|string} [id] Unique identifier for this bin, (if unsupplied, assume it's a new bin and create an id)
101
+ * @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties, or `null` if allocation failed
102
+ * @example
103
+ * var results = sprite.packOne(12, 16, 'a');
104
+ */
105
+ packOne(w, h, id) {
106
+ var best = { freebin: -1, shelf: -1, waste: Infinity },
107
+ y = 0,
108
+ bin, shelf, waste, i;
109
+
110
+ // if id was supplied, attempt a lookup..
111
+ if (typeof id === 'string' || typeof id === 'number') {
112
+ bin = this.getBin(id);
113
+ if (bin) { // we packed this bin already
114
+ this.ref(bin);
115
+ return bin;
116
+ }
117
+ if (typeof id === 'number') {
118
+ this.maxId = Math.max(id, this.maxId);
119
+ }
120
+ } else {
121
+ id = ++this.maxId;
129
122
  }
130
- } else {
131
- id = ++this.maxId;
132
- }
133
123
 
134
- // First try to reuse a free bin..
135
- for (i = 0; i < this.freebins.length; i++) {
136
- bin = this.freebins[i];
124
+ // First try to reuse a free bin..
125
+ for (i = 0; i < this.freebins.length; i++) {
126
+ bin = this.freebins[i];
137
127
 
138
- // exactly the right height and width, use it..
139
- if (h === bin.maxh && w === bin.maxw) {
140
- return this.allocFreebin(i, w, h, id);
141
- }
142
- // not enough height or width, skip it..
143
- if (h > bin.maxh || w > bin.maxw) {
144
- continue;
145
- }
146
- // extra height or width, minimize wasted area..
147
- if (h <= bin.maxh && w <= bin.maxw) {
148
- waste = (bin.maxw * bin.maxh) - (w * h);
149
- if (waste < best.waste) {
150
- best.waste = waste;
151
- best.freebin = i;
128
+ // exactly the right height and width, use it..
129
+ if (h === bin.maxh && w === bin.maxw) {
130
+ return this.allocFreebin(i, w, h, id);
131
+ }
132
+ // not enough height or width, skip it..
133
+ if (h > bin.maxh || w > bin.maxw) {
134
+ continue;
135
+ }
136
+ // extra height or width, minimize wasted area..
137
+ if (h <= bin.maxh && w <= bin.maxw) {
138
+ waste = (bin.maxw * bin.maxh) - (w * h);
139
+ if (waste < best.waste) {
140
+ best.waste = waste;
141
+ best.freebin = i;
142
+ }
152
143
  }
153
144
  }
154
- }
155
145
 
156
- // Next find the best shelf..
157
- for (i = 0; i < this.shelves.length; i++) {
158
- shelf = this.shelves[i];
159
- y += shelf.h;
146
+ // Next find the best shelf..
147
+ for (i = 0; i < this.shelves.length; i++) {
148
+ shelf = this.shelves[i];
149
+ y += shelf.h;
160
150
 
161
- // not enough width on this shelf, skip it..
162
- if (w > shelf.free) {
163
- continue;
164
- }
165
- // exactly the right height, pack it..
166
- if (h === shelf.h) {
167
- return this.allocShelf(i, w, h, id);
168
- }
169
- // not enough height, skip it..
170
- if (h > shelf.h) {
171
- continue;
172
- }
173
- // extra height, minimize wasted area..
174
- if (h < shelf.h) {
175
- waste = (shelf.h - h) * w;
176
- if (waste < best.waste) {
177
- best.freebin = -1;
178
- best.waste = waste;
179
- best.shelf = i;
151
+ // not enough width on this shelf, skip it..
152
+ if (w > shelf.free) {
153
+ continue;
154
+ }
155
+ // exactly the right height, pack it..
156
+ if (h === shelf.h) {
157
+ return this.allocShelf(i, w, h, id);
158
+ }
159
+ // not enough height, skip it..
160
+ if (h > shelf.h) {
161
+ continue;
162
+ }
163
+ // extra height, minimize wasted area..
164
+ if (h < shelf.h) {
165
+ waste = (shelf.h - h) * w;
166
+ if (waste < best.waste) {
167
+ best.freebin = -1;
168
+ best.waste = waste;
169
+ best.shelf = i;
170
+ }
180
171
  }
181
172
  }
182
- }
183
173
 
184
- if (best.freebin !== -1) {
185
- return this.allocFreebin(best.freebin, w, h, id);
186
- }
174
+ if (best.freebin !== -1) {
175
+ return this.allocFreebin(best.freebin, w, h, id);
176
+ }
187
177
 
188
- if (best.shelf !== -1) {
189
- return this.allocShelf(best.shelf, w, h, id);
190
- }
178
+ if (best.shelf !== -1) {
179
+ return this.allocShelf(best.shelf, w, h, id);
180
+ }
191
181
 
192
- // No free bins or shelves.. add shelf..
193
- if (h <= (this.h - y) && w <= this.w) {
194
- shelf = new Shelf(y, this.w, h);
195
- return this.allocShelf(this.shelves.push(shelf) - 1, w, h, id);
196
- }
182
+ // No free bins or shelves.. add shelf..
183
+ if (h <= (this.h - y) && w <= this.w) {
184
+ shelf = new Shelf(y, this.w, h);
185
+ return this.allocShelf(this.shelves.push(shelf) - 1, w, h, id);
186
+ }
197
187
 
198
- // No room for more shelves..
199
- // If `autoResize` option is set, grow the sprite as follows:
200
- // * double whichever sprite dimension is smaller (`w1` or `h1`)
201
- // * if sprite dimensions are equal, grow width before height
202
- // * accomodate very large bin requests (big `w` or `h`)
203
- if (this.autoResize) {
204
- var h1, h2, w1, w2;
188
+ // No room for more shelves..
189
+ // If `autoResize` option is set, grow the sprite as follows:
190
+ // * double whichever sprite dimension is smaller (`w1` or `h1`)
191
+ // * if sprite dimensions are equal, grow width before height
192
+ // * accomodate very large bin requests (big `w` or `h`)
193
+ if (this.autoResize) {
194
+ var h1, h2, w1, w2;
205
195
 
206
- h1 = h2 = this.h;
207
- w1 = w2 = this.w;
196
+ h1 = h2 = this.h;
197
+ w1 = w2 = this.w;
208
198
 
209
- if (w1 <= h1 || w > w1) { // grow width..
210
- w2 = Math.max(w, w1) * 2;
211
- }
212
- if (h1 < w1 || h > h1) { // grow height..
213
- h2 = Math.max(h, h1) * 2;
199
+ if (w1 <= h1 || w > w1) { // grow width..
200
+ w2 = Math.max(w, w1) * 2;
201
+ }
202
+ if (h1 < w1 || h > h1) { // grow height..
203
+ h2 = Math.max(h, h1) * 2;
204
+ }
205
+
206
+ this.resize(w2, h2);
207
+ return this.packOne(w, h, id); // retry
214
208
  }
215
209
 
216
- this.resize(w2, h2);
217
- return this.packOne(w, h, id); // retry
210
+ return null;
218
211
  }
219
212
 
220
- return null;
221
- };
222
213
 
214
+ /**
215
+ * Called by packOne() to allocate a bin by reusing an existing freebin
216
+ *
217
+ * @private
218
+ * @param {number} index Index into the `this.freebins` array
219
+ * @param {number} w Width of the bin to allocate
220
+ * @param {number} h Height of the bin to allocate
221
+ * @param {number|string} id Unique identifier for this bin
222
+ * @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties
223
+ * @example
224
+ * var bin = sprite.allocFreebin(0, 12, 16, 'a');
225
+ */
226
+ allocFreebin(index, w, h, id) {
227
+ var bin = this.freebins.splice(index, 1)[0];
228
+ bin.id = id;
229
+ bin.w = w;
230
+ bin.h = h;
231
+ bin.refcount = 0;
232
+ this.bins[id] = bin;
233
+ this.ref(bin);
234
+ return bin;
235
+ }
223
236
 
224
- /**
225
- * Called by packOne() to allocate a bin by reusing an existing freebin
226
- *
227
- * @private
228
- * @param {number} index Index into the `this.freebins` array
229
- * @param {number} w Width of the bin to allocate
230
- * @param {number} h Height of the bin to allocate
231
- * @param {number|string} id Unique identifier for this bin
232
- * @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties
233
- * @example
234
- * var bin = sprite.allocFreebin(0, 12, 16, 'a');
235
- */
236
- ShelfPack.prototype.allocFreebin = function (index, w, h, id) {
237
- var bin = this.freebins.splice(index, 1)[0];
238
- bin.id = id;
239
- bin.w = w;
240
- bin.h = h;
241
- bin.refcount = 0;
242
- this.bins[id] = bin;
243
- this.ref(bin);
244
- return bin;
245
- };
246
237
 
238
+ /**
239
+ * Called by `packOne() to allocate bin on an existing shelf
240
+ *
241
+ * @private
242
+ * @param {number} index Index into the `this.shelves` array
243
+ * @param {number} w Width of the bin to allocate
244
+ * @param {number} h Height of the bin to allocate
245
+ * @param {number|string} id Unique identifier for this bin
246
+ * @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties
247
+ * @example
248
+ * var results = sprite.allocShelf(0, 12, 16, 'a');
249
+ */
250
+ allocShelf(index, w, h, id) {
251
+ var shelf = this.shelves[index];
252
+ var bin = shelf.alloc(w, h, id);
253
+ this.bins[id] = bin;
254
+ this.ref(bin);
255
+ return bin;
256
+ }
247
257
 
248
- /**
249
- * Called by `packOne() to allocate bin on an existing shelf
250
- *
251
- * @private
252
- * @param {number} index Index into the `this.shelves` array
253
- * @param {number} w Width of the bin to allocate
254
- * @param {number} h Height of the bin to allocate
255
- * @param {number|string} id Unique identifier for this bin
256
- * @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties
257
- * @example
258
- * var results = sprite.allocShelf(0, 12, 16, 'a');
259
- */
260
- ShelfPack.prototype.allocShelf = function(index, w, h, id) {
261
- var shelf = this.shelves[index];
262
- var bin = shelf.alloc(w, h, id);
263
- this.bins[id] = bin;
264
- this.ref(bin);
265
- return bin;
266
- };
267
258
 
259
+ /**
260
+ * Shrink the width/height of the sprite to the bare minimum.
261
+ * Since shelf-pack doubles first width, then height when running out of shelf space
262
+ * this can result in fairly large unused space both in width and height if that happens
263
+ * towards the end of bin packing.
264
+ */
265
+ shrink() {
266
+ if (this.shelves.length > 0) {
267
+ var w2 = 0;
268
+ var h2 = 0;
269
+
270
+ for (var j = 0; j < this.shelves.length; j++) {
271
+ var shelf = this.shelves[j];
272
+ h2 += shelf.h;
273
+ w2 = Math.max(shelf.w - shelf.free, w2);
274
+ }
268
275
 
269
- /**
270
- * Shrink the width/height of the sprite to the bare minimum.
271
- * Since shelf-pack doubles first width, then height when running out of shelf space
272
- * this can result in fairly large unused space both in width and height if that happens
273
- * towards the end of bin packing.
274
- */
275
- ShelfPack.prototype.shrink = function() {
276
- if (this.shelves.length > 0) {
277
- var w2 = 0;
278
- var h2 = 0;
279
-
280
- for (var j = 0; j < this.shelves.length; j++) {
281
- var shelf = this.shelves[j];
282
- h2 += shelf.h;
283
- w2 = Math.max(shelf.w - shelf.free, w2);
276
+ this.resize(w2, h2);
284
277
  }
285
-
286
- this.resize(w2, h2);
287
278
  }
288
- };
289
279
 
290
280
 
291
- /**
292
- * Return a packed bin given its id, or undefined if the id is not found
293
- *
294
- * @param {number|string} id Unique identifier for this bin,
295
- * @returns {Bin} The requested bin, or undefined if not yet packed
296
- * @example
297
- * var b = sprite.getBin('a');
298
- */
299
- ShelfPack.prototype.getBin = function(id) {
300
- return this.bins[id];
301
- };
281
+ /**
282
+ * Return a packed bin given its id, or undefined if the id is not found
283
+ *
284
+ * @param {number|string} id Unique identifier for this bin,
285
+ * @returns {Bin} The requested bin, or undefined if not yet packed
286
+ * @example
287
+ * var b = sprite.getBin('a');
288
+ */
289
+ getBin(id) {
290
+ return this.bins[id];
291
+ }
302
292
 
303
293
 
304
- /**
305
- * Increment the ref count of a bin and update statistics.
306
- *
307
- * @param {Bin} bin Bin instance
308
- * @returns {number} New refcount of the bin
309
- * @example
310
- * var bin = sprite.getBin('a');
311
- * sprite.ref(bin);
312
- */
313
- ShelfPack.prototype.ref = function(bin) {
314
- if (++bin.refcount === 1) { // a new Bin.. record height in stats historgram..
315
- var h = bin.h;
316
- this.stats[h] = (this.stats[h] | 0) + 1;
294
+ /**
295
+ * Increment the ref count of a bin and update statistics.
296
+ *
297
+ * @param {Bin} bin Bin instance
298
+ * @returns {number} New refcount of the bin
299
+ * @example
300
+ * var bin = sprite.getBin('a');
301
+ * sprite.ref(bin);
302
+ */
303
+ ref(bin) {
304
+ if (++bin.refcount === 1) { // a new Bin.. record height in stats historgram..
305
+ var h = bin.h;
306
+ this.stats[h] = (this.stats[h] | 0) + 1;
307
+ }
308
+
309
+ return bin.refcount;
317
310
  }
318
311
 
319
- return bin.refcount;
320
- };
321
312
 
313
+ /**
314
+ * Decrement the ref count of a bin and update statistics.
315
+ * The bin will be automatically marked as free space once the refcount reaches 0.
316
+ *
317
+ * @param {Bin} bin Bin instance
318
+ * @returns {number} New refcount of the bin
319
+ * @example
320
+ * var bin = sprite.getBin('a');
321
+ * sprite.unref(bin);
322
+ */
323
+ unref(bin) {
324
+ if (bin.refcount === 0) {
325
+ return 0;
326
+ }
322
327
 
323
- /**
324
- * Decrement the ref count of a bin and update statistics.
325
- * The bin will be automatically marked as free space once the refcount reaches 0.
326
- *
327
- * @param {Bin} bin Bin instance
328
- * @returns {number} New refcount of the bin
329
- * @example
330
- * var bin = sprite.getBin('a');
331
- * sprite.unref(bin);
332
- */
333
- ShelfPack.prototype.unref = function(bin) {
334
- if (bin.refcount === 0) {
335
- return 0;
336
- }
328
+ if (--bin.refcount === 0) {
329
+ this.stats[bin.h]--;
330
+ delete this.bins[bin.id];
331
+ this.freebins.push(bin);
332
+ }
337
333
 
338
- if (--bin.refcount === 0) {
339
- this.stats[bin.h]--;
340
- delete this.bins[bin.id];
341
- this.freebins.push(bin);
334
+ return bin.refcount;
342
335
  }
343
336
 
344
- return bin.refcount;
345
- };
346
337
 
347
-
348
- /**
349
- * Clear the sprite. Resets everything and resets statistics.
350
- *
351
- * @example
352
- * sprite.clear();
353
- */
354
- ShelfPack.prototype.clear = function() {
355
- this.shelves = [];
356
- this.freebins = [];
357
- this.stats = {};
358
- this.bins = {};
359
- this.maxId = 0;
360
- };
338
+ /**
339
+ * Clear the sprite. Resets everything and resets statistics.
340
+ *
341
+ * @example
342
+ * sprite.clear();
343
+ */
344
+ clear() {
345
+ this.shelves = [];
346
+ this.freebins = [];
347
+ this.stats = {};
348
+ this.bins = {};
349
+ this.maxId = 0;
350
+ }
361
351
 
362
352
 
363
- /**
364
- * Resize the sprite.
365
- *
366
- * @param {number} w Requested new sprite width
367
- * @param {number} h Requested new sprite height
368
- * @returns {boolean} `true` if resize succeeded, `false` if failed
369
- * @example
370
- * sprite.resize(256, 256);
371
- */
372
- ShelfPack.prototype.resize = function(w, h) {
373
- this.w = w;
374
- this.h = h;
375
- for (var i = 0; i < this.shelves.length; i++) {
376
- this.shelves[i].resize(w);
353
+ /**
354
+ * Resize the sprite.
355
+ *
356
+ * @param {number} w Requested new sprite width
357
+ * @param {number} h Requested new sprite height
358
+ * @returns {boolean} `true` if resize succeeded, `false` if failed
359
+ * @example
360
+ * sprite.resize(256, 256);
361
+ */
362
+ resize(w, h) {
363
+ this.w = w;
364
+ this.h = h;
365
+ for (var i = 0; i < this.shelves.length; i++) {
366
+ this.shelves[i].resize(w);
367
+ }
368
+ return true;
377
369
  }
378
- return true;
379
- };
370
+ }
380
371
 
381
372
 
382
373
  /**
383
374
  * Create a new Shelf.
384
375
  *
385
376
  * @private
386
- * @class Shelf
387
- * @param {number} y Top coordinate of the new shelf
388
- * @param {number} w Width of the new shelf
389
- * @param {number} h Height of the new shelf
390
377
  * @example
391
378
  * var shelf = new Shelf(64, 512, 24);
392
379
  */
393
- function Shelf(y, w, h) {
394
- this.x = 0;
395
- this.y = y;
396
- this.w = this.free = w;
397
- this.h = h;
398
- }
380
+ class Shelf {
381
+ /**
382
+ * @param {number} y Top coordinate of the new shelf
383
+ * @param {number} w Width of the new shelf
384
+ * @param {number} h Height of the new shelf
385
+ */
386
+ constructor(y, w, h) {
387
+ this.x = 0;
388
+ this.y = y;
389
+ this.w = this.free = w;
390
+ this.h = h;
391
+ }
399
392
 
400
393
 
401
- /**
402
- * Allocate a single bin into the shelf.
403
- *
404
- * @private
405
- * @param {number} w Width of the bin to allocate
406
- * @param {number} h Height of the bin to allocate
407
- * @param {number|string} id Unique id of the bin to allocate
408
- * @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties, or `null` if allocation failed
409
- * @example
410
- * shelf.alloc(12, 16, 'a');
411
- */
412
- Shelf.prototype.alloc = function(w, h, id) {
413
- if (w > this.free || h > this.h) {
414
- return null;
394
+ /**
395
+ * Allocate a single bin into the shelf.
396
+ *
397
+ * @private
398
+ * @param {number} w Width of the bin to allocate
399
+ * @param {number} h Height of the bin to allocate
400
+ * @param {number|string} id Unique id of the bin to allocate
401
+ * @returns {Bin} Bin object with `id`, `x`, `y`, `w`, `h` properties, or `null` if allocation failed
402
+ * @example
403
+ * shelf.alloc(12, 16, 'a');
404
+ */
405
+ alloc(w, h, id) {
406
+ if (w > this.free || h > this.h) {
407
+ return null;
408
+ }
409
+ var x = this.x;
410
+ this.x += w;
411
+ this.free -= w;
412
+ return new Bin(id, x, this.y, w, h, w, this.h);
415
413
  }
416
- var x = this.x;
417
- this.x += w;
418
- this.free -= w;
419
- return new Bin(id, x, this.y, w, h, w, this.h);
420
- };
421
414
 
422
415
 
423
- /**
424
- * Resize the shelf.
425
- *
426
- * @private
427
- * @param {number} w Requested new width of the shelf
428
- * @returns {boolean} true
429
- * @example
430
- * shelf.resize(512);
431
- */
432
- Shelf.prototype.resize = function(w) {
433
- this.free += (w - this.w);
434
- this.w = w;
435
- return true;
436
- };
416
+ /**
417
+ * Resize the shelf.
418
+ *
419
+ * @private
420
+ * @param {number} w Requested new width of the shelf
421
+ * @returns {boolean} true
422
+ * @example
423
+ * shelf.resize(512);
424
+ */
425
+ resize(w) {
426
+ this.free += (w - this.w);
427
+ this.w = w;
428
+ return true;
429
+ }
430
+ }
437
431
 
438
432
 
439
433
  /**
440
434
  * Create a new Bin object.
441
435
  *
442
- * @class Bin
443
- * @param {number|string} id Unique id of the bin
444
- * @param {number} x Left coordinate of the bin
445
- * @param {number} y Top coordinate of the bin
446
- * @param {number} w Width of the bin
447
- * @param {number} h Height of the bin
448
- * @param {number} [maxw] Max width of the bin (defaults to `w` if not provided)
449
- * @param {number} [maxh] Max height of the bin (defaults to `h` if not provided)
450
436
  * @example
451
437
  * var bin = new Bin('a', 0, 0, 12, 16);
452
438
  */
453
- function Bin(id, x, y, w, h, maxw, maxh) {
454
- this.id = id;
455
- this.x = x;
456
- this.y = y;
457
- this.w = w;
458
- this.h = h;
459
- this.maxw = maxw || w;
460
- this.maxh = maxh || h;
461
- this.refcount = 0;
439
+ export class Bin {
440
+ /**
441
+ * @param {number|string} id Unique id of the bin
442
+ * @param {number} x Left coordinate of the bin
443
+ * @param {number} y Top coordinate of the bin
444
+ * @param {number} w Width of the bin
445
+ * @param {number} h Height of the bin
446
+ * @param {number} [maxw] Max width of the bin (defaults to `w` if not provided)
447
+ * @param {number} [maxh] Max height of the bin (defaults to `h` if not provided)
448
+ */
449
+ constructor(id, x, y, w, h, maxw, maxh) {
450
+ this.id = id;
451
+ this.x = x;
452
+ this.y = y;
453
+ this.w = w;
454
+ this.h = h;
455
+ this.maxw = maxw || w;
456
+ this.maxh = maxh || h;
457
+ this.refcount = 0;
458
+ }
462
459
  }
463
-