55 #ifndef STB_INCLUDE_STB_RECT_PACK_H
56 #define STB_INCLUDE_STB_RECT_PACK_H
58 #define STB_RECT_PACK_VERSION 1
61 #define STBRP_DEF static
63 #define STBRP_DEF extern
74 #ifdef STBRP_LARGE_RECTS
192 #ifdef STB_RECT_PACK_IMPLEMENTATION
195 #define STBRP_SORT qsort
200 #define STBRP_ASSERT assert
204 #define STBRP__NOTUSED(v) (void)(v)
206 #define STBRP__NOTUSED(v) (void)sizeof(v)
211 STBRP__INIT_skyline = 1
217 case STBRP__INIT_skyline:
228 if (allow_out_of_mem)
249 #ifndef STBRP_LARGE_RECTS
250 STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
253 for (i=0; i < num_nodes-1; ++i)
254 nodes[i].next = &nodes[i+1];
255 nodes[i].
next = NULL;
256 context->
init_mode = STBRP__INIT_skyline;
270 #ifdef STBRP_LARGE_RECTS
271 context->
extra[1].
y = (1<<30);
273 context->
extra[1].
y = 65535;
283 int min_y, visited_width, waste_area;
287 STBRP_ASSERT(first->
x <= x0);
291 while (node->
next->
x <= x0)
294 STBRP_ASSERT(node->
next->
x > x0);
297 STBRP_ASSERT(node->
x <= x0);
302 while (node->
x < x1) {
303 if (node->
y > min_y) {
307 waste_area += visited_width * (node->
y - min_y);
311 visited_width += node->
next->
x -
x0;
313 visited_width += node->
next->
x - node->
x;
316 int under_width = node->
next->
x - node->
x;
317 if (under_width + visited_width > width)
318 under_width = width - visited_width;
319 waste_area += under_width * (min_y - node->
y);
320 visited_width += under_width;
325 *pwaste = waste_area;
335 static stbrp__findresult stbrp__skyline_find_best_pos(
stbrp_context *c,
int width,
int height)
337 int best_waste = (1<<30), best_x, best_y = (1 << 30);
338 stbrp__findresult fr;
339 stbrp_node **prev, *node, *tail, **best = NULL;
342 width = (width + c->
align - 1);
343 width -= width % c->
align;
344 STBRP_ASSERT(width % c->
align == 0);
350 y = stbrp__skyline_find_min_y(c, node, node->
x, width, &waste);
361 if (y < best_y || (y == best_y && waste < best_waste)) {
372 best_x = (best == NULL) ? 0 : (*best)->
x;
396 while (tail->
x < width)
399 int xpos = tail->
x -
width;
401 STBRP_ASSERT(xpos >= 0);
403 while (node->
next->
x <= xpos) {
407 STBRP_ASSERT(node->
next->
x > xpos && node->
x <= xpos);
408 y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
411 if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
413 STBRP_ASSERT(y <= best_y);
430 static stbrp__findresult stbrp__skyline_pack_rectangle(
stbrp_context *context,
int width,
int height)
433 stbrp__findresult
res = stbrp__skyline_find_best_pos(context, width, height);
440 if (res.prev_link == NULL || res.y + height > context->
height || context->
free_head == NULL) {
441 res.prev_link = NULL;
456 cur = *res.prev_link;
457 if (cur->
x < res.x) {
463 *res.prev_link = node;
468 while (cur->
next && cur->
next->
x <= res.x + width) {
479 if (cur->
x < res.x + width)
484 while (cur->
x < context->
width) {
485 STBRP_ASSERT(cur->
x < cur->
next->
x);
488 STBRP_ASSERT(cur->
next == NULL);
505 STBRP_ASSERT(count == context->
num_nodes+2);
512 static int rect_height_compare(
const void *
a,
const void *
b)
520 return (p->
w > q->
w) ? -1 : (p->
w < q->
w);
523 static int rect_width_compare(
const void *a,
const void *b)
531 return (p->
h > q->
h) ? -1 : (p->
h < q->
h);
534 static int rect_original_order(
const void *a,
const void *b)
541 #ifdef STBRP_LARGE_RECTS
542 #define STBRP__MAXVAL 0xffffffff
544 #define STBRP__MAXVAL 0xffff
552 for (i=0; i < num_rects; ++i) {
554 #ifndef STBRP_LARGE_RECTS
555 STBRP_ASSERT(rects[i].
w <= 0xffff && rects[i].
h <= 0xffff);
560 STBRP_SORT(rects, num_rects,
sizeof(rects[0]), rect_height_compare);
562 for (i=0; i < num_rects; ++i) {
563 if (rects[i].
w == 0 || rects[i].
h == 0) {
564 rects[i].
x = rects[i].
y = 0;
566 stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].
w, rects[i].
h);
571 rects[i].
x = rects[i].
y = STBRP__MAXVAL;
577 STBRP_SORT(rects, num_rects,
sizeof(rects[0]), rect_original_order);
580 for (i=0; i < num_rects; ++i)
581 rects[i].was_packed = !(rects[i].
x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);