80#ifndef STB_INCLUDE_STB_RECT_PACK_H
81#define STB_INCLUDE_STB_RECT_PACK_H
83#define STB_RECT_PACK_VERSION 1
86#define STBRP_DEF static
88#define STBRP_DEF extern
99 typedef int stbrp_coord;
101#define STBRP__MAXVAL 0x7fffffff
142 STBRP_DEF
void stbrp_init_target(
stbrp_context* context,
int width,
int height,
stbrp_node* nodes,
int num_nodes);
163 STBRP_DEF
void stbrp_setup_allow_out_of_mem(
stbrp_context* context,
int allow_out_of_mem);
168 STBRP_DEF
void stbrp_setup_heuristic(
stbrp_context* context,
int heuristic);
175 STBRP_HEURISTIC_Skyline_default = 0,
176 STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
177 STBRP_HEURISTIC_Skyline_BF_sortHeight
216#define STBRP_SORT qsort
221#define STBRP_ASSERT assert
225#define STBRP__NOTUSED(v) (void)(v)
226#define STBRP__CDECL __cdecl
228#define STBRP__NOTUSED(v) (void)sizeof(v)
234 STBRP__INIT_skyline = 1
237STBRP_DEF
void stbrp_setup_heuristic(
stbrp_context* context,
int heuristic)
239 switch (context->init_mode) {
240 case STBRP__INIT_skyline:
241 STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
242 context->heuristic = heuristic;
249STBRP_DEF
void stbrp_setup_allow_out_of_mem(
stbrp_context* context,
int allow_out_of_mem)
251 if (allow_out_of_mem)
265 context->align = (context->width + context->num_nodes - 1) / context->num_nodes;
269STBRP_DEF
void stbrp_init_target(
stbrp_context* context,
int width,
int height,
stbrp_node* nodes,
int num_nodes)
273 for (i = 0; i < num_nodes - 1; ++i)
274 nodes[i].next = &nodes[i + 1];
275 nodes[i].next = NULL;
276 context->init_mode = STBRP__INIT_skyline;
277 context->heuristic = STBRP_HEURISTIC_Skyline_default;
278 context->free_head = &nodes[0];
279 context->active_head = &context->extra[0];
280 context->width = width;
281 context->height = height;
282 context->num_nodes = num_nodes;
283 stbrp_setup_allow_out_of_mem(context, 0);
286 context->extra[0].x = 0;
287 context->extra[0].y = 0;
288 context->extra[0].next = &context->extra[1];
289 context->extra[1].x = (stbrp_coord)width;
290 context->extra[1].y = (1 << 30);
291 context->extra[1].next = NULL;
299 int min_y, visited_width, waste_area;
303 STBRP_ASSERT(first->x <= x0);
307 while (node->next->x <= x0)
310 STBRP_ASSERT(node->next->x > x0);
313 STBRP_ASSERT(node->x <= x0);
318 while (node->x < x1) {
319 if (node->y > min_y) {
323 waste_area += visited_width * (node->y - min_y);
327 visited_width += node->next->x - x0;
329 visited_width += node->next->x - node->x;
333 int under_width = node->next->x - node->x;
334 if (under_width + visited_width > width)
335 under_width = width - visited_width;
336 waste_area += under_width * (min_y - node->y);
337 visited_width += under_width;
342 *pwaste = waste_area;
354 int best_waste = (1 << 30), best_x, best_y = (1 << 30);
356 stbrp_node** prev, * node, * tail, ** best = NULL;
359 width = (width + c->align - 1);
360 width -= width % c->align;
361 STBRP_ASSERT(width % c->align == 0);
364 if (width > c->width || height > c->height) {
370 node = c->active_head;
371 prev = &c->active_head;
372 while (node->x + width <= c->width) {
374 y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
375 if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) {
384 if (y + height <= c->height) {
386 if (y < best_y || (y == best_y && waste < best_waste)) {
397 best_x = (best == NULL) ? 0 : (*best)->x;
416 if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
417 tail = c->active_head;
418 node = c->active_head;
419 prev = &c->active_head;
421 while (tail->x < width)
424 int xpos = tail->x - width;
426 STBRP_ASSERT(xpos >= 0);
428 while (node->next->x <= xpos) {
432 STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
433 y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
434 if (y + height <= c->height) {
436 if (y < best_y || waste < best_waste || (waste == best_waste && xpos < best_x)) {
465 if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
466 res.prev_link = NULL;
471 node = context->free_head;
472 node->x = (stbrp_coord)res.x;
473 node->y = (stbrp_coord)(res.y + height);
475 context->free_head = node->next;
481 cur = *res.prev_link;
482 if (cur->x < res.x) {
489 *res.prev_link = node;
494 while (cur->next && cur->next->x <= res.x + width) {
497 cur->next = context->free_head;
498 context->free_head = cur;
505 if (cur->x < res.x + width)
506 cur->x = (stbrp_coord)(res.x + width);
509 cur = context->active_head;
510 while (cur->x < context->width) {
511 STBRP_ASSERT(cur->x < cur->next->x);
514 STBRP_ASSERT(cur->next == NULL);
518 cur = context->active_head;
523 cur = context->free_head;
528 STBRP_ASSERT(count == context->num_nodes + 2);
535static int STBRP__CDECL rect_height_compare(
const void* a,
const void* b)
543 return (p->w > q->w) ? -1 : (p->w < q->w);
546static int STBRP__CDECL rect_original_order(
const void* a,
const void* b)
550 return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
555 int i, all_rects_packed = 1;
558 for (i = 0; i < num_rects; ++i) {
559 rects[i].was_packed = i;
563 STBRP_SORT(rects, num_rects,
sizeof(rects[0]), rect_height_compare);
565 for (i = 0; i < num_rects; ++i) {
566 if (rects[i].w == 0 || rects[i].h == 0) {
567 rects[i].x = rects[i].y = 0;
570 stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
572 rects[i].x = (stbrp_coord)fr.x;
573 rects[i].y = (stbrp_coord)fr.y;
576 rects[i].x = rects[i].y = STBRP__MAXVAL;
582 STBRP_SORT(rects, num_rects,
sizeof(rects[0]), rect_original_order);
585 for (i = 0; i < num_rects; ++i) {
586 rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
587 if (!rects[i].was_packed)
588 all_rects_packed = 0;
592 return all_rects_packed;
Definition imstb_rectpack.h:347
Definition imstb_rectpack.h:192
Definition imstb_rectpack.h:186
Definition imstb_rectpack.h:130