70#ifndef STB_INCLUDE_STB_RECT_PACK_H
71#define STB_INCLUDE_STB_RECT_PACK_H
73#define STB_RECT_PACK_VERSION 1
76#define STBRP_DEF static
78#define STBRP_DEF extern
89 typedef int stbrp_coord;
91#define STBRP__MAXVAL 0x7fffffff
132 STBRP_DEF
void stbrp_init_target(
stbrp_context* context,
int width,
int height,
stbrp_node* nodes,
int num_nodes);
153 STBRP_DEF
void stbrp_setup_allow_out_of_mem(
stbrp_context* context,
int allow_out_of_mem);
158 STBRP_DEF
void stbrp_setup_heuristic(
stbrp_context* context,
int heuristic);
165 STBRP_HEURISTIC_Skyline_default = 0,
166 STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
167 STBRP_HEURISTIC_Skyline_BF_sortHeight
206#define STBRP_SORT qsort
211#define STBRP_ASSERT assert
215#define STBRP__NOTUSED(v) (void)(v)
216#define STBRP__CDECL __cdecl
218#define STBRP__NOTUSED(v) (void)sizeof(v)
224 STBRP__INIT_skyline = 1
227STBRP_DEF
void stbrp_setup_heuristic(
stbrp_context* context,
int heuristic)
229 switch (context->init_mode) {
230 case STBRP__INIT_skyline:
231 STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
232 context->heuristic = heuristic;
239STBRP_DEF
void stbrp_setup_allow_out_of_mem(
stbrp_context* context,
int allow_out_of_mem)
241 if (allow_out_of_mem)
255 context->align = (context->width + context->num_nodes - 1) / context->num_nodes;
259STBRP_DEF
void stbrp_init_target(
stbrp_context* context,
int width,
int height,
stbrp_node* nodes,
int num_nodes)
263 for (i = 0; i < num_nodes - 1; ++i)
264 nodes[i].next = &nodes[i + 1];
265 nodes[i].next = NULL;
266 context->init_mode = STBRP__INIT_skyline;
267 context->heuristic = STBRP_HEURISTIC_Skyline_default;
268 context->free_head = &nodes[0];
269 context->active_head = &context->extra[0];
270 context->width = width;
271 context->height = height;
272 context->num_nodes = num_nodes;
273 stbrp_setup_allow_out_of_mem(context, 0);
276 context->extra[0].x = 0;
277 context->extra[0].y = 0;
278 context->extra[0].next = &context->extra[1];
279 context->extra[1].x = (stbrp_coord)width;
280 context->extra[1].y = (1 << 30);
281 context->extra[1].next = NULL;
289 int min_y, visited_width, waste_area;
293 STBRP_ASSERT(first->x <= x0);
297 while (node->next->x <= x0)
300 STBRP_ASSERT(node->next->x > x0);
303 STBRP_ASSERT(node->x <= x0);
308 while (node->x < x1) {
309 if (node->y > min_y) {
313 waste_area += visited_width * (node->y - min_y);
317 visited_width += node->next->x - x0;
319 visited_width += node->next->x - node->x;
323 int under_width = node->next->x - node->x;
324 if (under_width + visited_width > width)
325 under_width = width - visited_width;
326 waste_area += under_width * (min_y - node->y);
327 visited_width += under_width;
332 *pwaste = waste_area;
344 int best_waste = (1 << 30), best_x, best_y = (1 << 30);
346 stbrp_node** prev, * node, * tail, ** best = NULL;
349 width = (width + c->align - 1);
350 width -= width % c->align;
351 STBRP_ASSERT(width % c->align == 0);
354 if (width > c->width || height > c->height) {
360 node = c->active_head;
361 prev = &c->active_head;
362 while (node->x + width <= c->width) {
364 y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
365 if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) {
374 if (y + height <= c->height) {
376 if (y < best_y || (y == best_y && waste < best_waste)) {
387 best_x = (best == NULL) ? 0 : (*best)->x;
406 if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
407 tail = c->active_head;
408 node = c->active_head;
409 prev = &c->active_head;
411 while (tail->x < width)
414 int xpos = tail->x - width;
416 STBRP_ASSERT(xpos >= 0);
418 while (node->next->x <= xpos) {
422 STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
423 y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
424 if (y + height <= c->height) {
426 if (y < best_y || waste < best_waste || (waste == best_waste && xpos < best_x)) {
455 if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
456 res.prev_link = NULL;
461 node = context->free_head;
462 node->x = (stbrp_coord)res.x;
463 node->y = (stbrp_coord)(res.y + height);
465 context->free_head = node->next;
471 cur = *res.prev_link;
472 if (cur->x < res.x) {
479 *res.prev_link = node;
484 while (cur->next && cur->next->x <= res.x + width) {
487 cur->next = context->free_head;
488 context->free_head = cur;
495 if (cur->x < res.x + width)
496 cur->x = (stbrp_coord)(res.x + width);
499 cur = context->active_head;
500 while (cur->x < context->width) {
501 STBRP_ASSERT(cur->x < cur->next->x);
504 STBRP_ASSERT(cur->next == NULL);
508 cur = context->active_head;
513 cur = context->free_head;
518 STBRP_ASSERT(count == context->num_nodes + 2);
525static int STBRP__CDECL rect_height_compare(
const void* a,
const void* b)
533 return (p->w > q->w) ? -1 : (p->w < q->w);
536static int STBRP__CDECL rect_original_order(
const void* a,
const void* b)
540 return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
545 int i, all_rects_packed = 1;
548 for (i = 0; i < num_rects; ++i) {
549 rects[i].was_packed = i;
553 STBRP_SORT(rects, num_rects,
sizeof(rects[0]), rect_height_compare);
555 for (i = 0; i < num_rects; ++i) {
556 if (rects[i].w == 0 || rects[i].h == 0) {
557 rects[i].x = rects[i].y = 0;
560 stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
562 rects[i].x = (stbrp_coord)fr.x;
563 rects[i].y = (stbrp_coord)fr.y;
566 rects[i].x = rects[i].y = STBRP__MAXVAL;
572 STBRP_SORT(rects, num_rects,
sizeof(rects[0]), rect_original_order);
575 for (i = 0; i < num_rects; ++i) {
576 rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
577 if (!rects[i].was_packed)
578 all_rects_packed = 0;
582 return all_rects_packed;
Definition imstb_rectpack.h:337
Definition imstb_rectpack.h:182
Definition imstb_rectpack.h:176
Definition imstb_rectpack.h:120