git repos / blockattack-game

blame: source/code/Libs/imgui/imstb_rectpack.h

normal view · raw

1193b4be Poul Sander 2025-02-03 21:28 1
// [DEAR IMGUI]
1193b4be Poul Sander 2025-02-03 21:28 2
// This is a slightly modified version of stb_rect_pack.h 1.01.
1193b4be Poul Sander 2025-02-03 21:28 3
// Grep for [DEAR IMGUI] to find the changes.
1193b4be Poul Sander 2025-02-03 21:28 4
// 
1193b4be Poul Sander 2025-02-03 21:28 5
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
1193b4be Poul Sander 2025-02-03 21:28 6
// Sean Barrett 2014
1193b4be Poul Sander 2025-02-03 21:28 7
//
1193b4be Poul Sander 2025-02-03 21:28 8
// Useful for e.g. packing rectangular textures into an atlas.
1193b4be Poul Sander 2025-02-03 21:28 9
// Does not do rotation.
1193b4be Poul Sander 2025-02-03 21:28 10
//
1193b4be Poul Sander 2025-02-03 21:28 11
// Before #including,
1193b4be Poul Sander 2025-02-03 21:28 12
//
1193b4be Poul Sander 2025-02-03 21:28 13
//    #define STB_RECT_PACK_IMPLEMENTATION
1193b4be Poul Sander 2025-02-03 21:28 14
//
1193b4be Poul Sander 2025-02-03 21:28 15
// in the file that you want to have the implementation.
1193b4be Poul Sander 2025-02-03 21:28 16
//
1193b4be Poul Sander 2025-02-03 21:28 17
// Not necessarily the awesomest packing method, but better than
1193b4be Poul Sander 2025-02-03 21:28 18
// the totally naive one in stb_truetype (which is primarily what
1193b4be Poul Sander 2025-02-03 21:28 19
// this is meant to replace).
1193b4be Poul Sander 2025-02-03 21:28 20
//
1193b4be Poul Sander 2025-02-03 21:28 21
// Has only had a few tests run, may have issues.
1193b4be Poul Sander 2025-02-03 21:28 22
//
1193b4be Poul Sander 2025-02-03 21:28 23
// More docs to come.
1193b4be Poul Sander 2025-02-03 21:28 24
//
1193b4be Poul Sander 2025-02-03 21:28 25
// No memory allocations; uses qsort() and assert() from stdlib.
1193b4be Poul Sander 2025-02-03 21:28 26
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
1193b4be Poul Sander 2025-02-03 21:28 27
//
1193b4be Poul Sander 2025-02-03 21:28 28
// This library currently uses the Skyline Bottom-Left algorithm.
1193b4be Poul Sander 2025-02-03 21:28 29
//
1193b4be Poul Sander 2025-02-03 21:28 30
// Please note: better rectangle packers are welcome! Please
1193b4be Poul Sander 2025-02-03 21:28 31
// implement them to the same API, but with a different init
1193b4be Poul Sander 2025-02-03 21:28 32
// function.
1193b4be Poul Sander 2025-02-03 21:28 33
//
1193b4be Poul Sander 2025-02-03 21:28 34
// Credits
1193b4be Poul Sander 2025-02-03 21:28 35
//
1193b4be Poul Sander 2025-02-03 21:28 36
//  Library
1193b4be Poul Sander 2025-02-03 21:28 37
//    Sean Barrett
1193b4be Poul Sander 2025-02-03 21:28 38
//  Minor features
1193b4be Poul Sander 2025-02-03 21:28 39
//    Martins Mozeiko
1193b4be Poul Sander 2025-02-03 21:28 40
//    github:IntellectualKitty
1193b4be Poul Sander 2025-02-03 21:28 41
//
1193b4be Poul Sander 2025-02-03 21:28 42
//  Bugfixes / warning fixes
1193b4be Poul Sander 2025-02-03 21:28 43
//    Jeremy Jaussaud
1193b4be Poul Sander 2025-02-03 21:28 44
//    Fabian Giesen
1193b4be Poul Sander 2025-02-03 21:28 45
//
1193b4be Poul Sander 2025-02-03 21:28 46
// Version history:
1193b4be Poul Sander 2025-02-03 21:28 47
//
1193b4be Poul Sander 2025-02-03 21:28 48
//     1.01  (2021-07-11)  always use large rect mode, expose STBRP__MAXVAL in public section
1193b4be Poul Sander 2025-02-03 21:28 49
//     1.00  (2019-02-25)  avoid small space waste; gracefully fail too-wide rectangles
1193b4be Poul Sander 2025-02-03 21:28 50
//     0.99  (2019-02-07)  warning fixes
1193b4be Poul Sander 2025-02-03 21:28 51
//     0.11  (2017-03-03)  return packing success/fail result
1193b4be Poul Sander 2025-02-03 21:28 52
//     0.10  (2016-10-25)  remove cast-away-const to avoid warnings
1193b4be Poul Sander 2025-02-03 21:28 53
//     0.09  (2016-08-27)  fix compiler warnings
1193b4be Poul Sander 2025-02-03 21:28 54
//     0.08  (2015-09-13)  really fix bug with empty rects (w=0 or h=0)
1193b4be Poul Sander 2025-02-03 21:28 55
//     0.07  (2015-09-13)  fix bug with empty rects (w=0 or h=0)
1193b4be Poul Sander 2025-02-03 21:28 56
//     0.06  (2015-04-15)  added STBRP_SORT to allow replacing qsort
1193b4be Poul Sander 2025-02-03 21:28 57
//     0.05:  added STBRP_ASSERT to allow replacing assert
1193b4be Poul Sander 2025-02-03 21:28 58
//     0.04:  fixed minor bug in STBRP_LARGE_RECTS support
1193b4be Poul Sander 2025-02-03 21:28 59
//     0.01:  initial release
1193b4be Poul Sander 2025-02-03 21:28 60
//
1193b4be Poul Sander 2025-02-03 21:28 61
// LICENSE
1193b4be Poul Sander 2025-02-03 21:28 62
//
1193b4be Poul Sander 2025-02-03 21:28 63
//   See end of file for license information.
1193b4be Poul Sander 2025-02-03 21:28 64
1193b4be Poul Sander 2025-02-03 21:28 65
//////////////////////////////////////////////////////////////////////////////
1193b4be Poul Sander 2025-02-03 21:28 66
//
1193b4be Poul Sander 2025-02-03 21:28 67
//       INCLUDE SECTION
1193b4be Poul Sander 2025-02-03 21:28 68
//
1193b4be Poul Sander 2025-02-03 21:28 69
1193b4be Poul Sander 2025-02-03 21:28 70
#ifndef STB_INCLUDE_STB_RECT_PACK_H
1193b4be Poul Sander 2025-02-03 21:28 71
#define STB_INCLUDE_STB_RECT_PACK_H
1193b4be Poul Sander 2025-02-03 21:28 72
1193b4be Poul Sander 2025-02-03 21:28 73
#define STB_RECT_PACK_VERSION  1
1193b4be Poul Sander 2025-02-03 21:28 74
1193b4be Poul Sander 2025-02-03 21:28 75
#ifdef STBRP_STATIC
1193b4be Poul Sander 2025-02-03 21:28 76
#define STBRP_DEF static
1193b4be Poul Sander 2025-02-03 21:28 77
#else
1193b4be Poul Sander 2025-02-03 21:28 78
#define STBRP_DEF extern
1193b4be Poul Sander 2025-02-03 21:28 79
#endif
1193b4be Poul Sander 2025-02-03 21:28 80
1193b4be Poul Sander 2025-02-03 21:28 81
#ifdef __cplusplus
1193b4be Poul Sander 2025-02-03 21:28 82
extern "C" {
1193b4be Poul Sander 2025-02-03 21:28 83
#endif
1193b4be Poul Sander 2025-02-03 21:28 84
1193b4be Poul Sander 2025-02-03 21:28 85
typedef struct stbrp_context stbrp_context;
1193b4be Poul Sander 2025-02-03 21:28 86
typedef struct stbrp_node    stbrp_node;
1193b4be Poul Sander 2025-02-03 21:28 87
typedef struct stbrp_rect    stbrp_rect;
1193b4be Poul Sander 2025-02-03 21:28 88
1193b4be Poul Sander 2025-02-03 21:28 89
typedef int            stbrp_coord;
1193b4be Poul Sander 2025-02-03 21:28 90
1193b4be Poul Sander 2025-02-03 21:28 91
#define STBRP__MAXVAL  0x7fffffff
1193b4be Poul Sander 2025-02-03 21:28 92
// Mostly for internal use, but this is the maximum supported coordinate value.
1193b4be Poul Sander 2025-02-03 21:28 93
1193b4be Poul Sander 2025-02-03 21:28 94
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
1193b4be Poul Sander 2025-02-03 21:28 95
// Assign packed locations to rectangles. The rectangles are of type
1193b4be Poul Sander 2025-02-03 21:28 96
// 'stbrp_rect' defined below, stored in the array 'rects', and there
1193b4be Poul Sander 2025-02-03 21:28 97
// are 'num_rects' many of them.
1193b4be Poul Sander 2025-02-03 21:28 98
//
1193b4be Poul Sander 2025-02-03 21:28 99
// Rectangles which are successfully packed have the 'was_packed' flag
1193b4be Poul Sander 2025-02-03 21:28 100
// set to a non-zero value and 'x' and 'y' store the minimum location
1193b4be Poul Sander 2025-02-03 21:28 101
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
1193b4be Poul Sander 2025-02-03 21:28 102
// if you imagine y increasing downwards). Rectangles which do not fit
1193b4be Poul Sander 2025-02-03 21:28 103
// have the 'was_packed' flag set to 0.
1193b4be Poul Sander 2025-02-03 21:28 104
//
1193b4be Poul Sander 2025-02-03 21:28 105
// You should not try to access the 'rects' array from another thread
1193b4be Poul Sander 2025-02-03 21:28 106
// while this function is running, as the function temporarily reorders
1193b4be Poul Sander 2025-02-03 21:28 107
// the array while it executes.
1193b4be Poul Sander 2025-02-03 21:28 108
//
1193b4be Poul Sander 2025-02-03 21:28 109
// To pack into another rectangle, you need to call stbrp_init_target
1193b4be Poul Sander 2025-02-03 21:28 110
// again. To continue packing into the same rectangle, you can call
1193b4be Poul Sander 2025-02-03 21:28 111
// this function again. Calling this multiple times with multiple rect
1193b4be Poul Sander 2025-02-03 21:28 112
// arrays will probably produce worse packing results than calling it
1193b4be Poul Sander 2025-02-03 21:28 113
// a single time with the full rectangle array, but the option is
1193b4be Poul Sander 2025-02-03 21:28 114
// available.
1193b4be Poul Sander 2025-02-03 21:28 115
//
1193b4be Poul Sander 2025-02-03 21:28 116
// The function returns 1 if all of the rectangles were successfully
1193b4be Poul Sander 2025-02-03 21:28 117
// packed and 0 otherwise.
1193b4be Poul Sander 2025-02-03 21:28 118
1193b4be Poul Sander 2025-02-03 21:28 119
struct stbrp_rect
1193b4be Poul Sander 2025-02-03 21:28 120
{
1193b4be Poul Sander 2025-02-03 21:28 121
   // reserved for your use:
1193b4be Poul Sander 2025-02-03 21:28 122
   int            id;
1193b4be Poul Sander 2025-02-03 21:28 123
1193b4be Poul Sander 2025-02-03 21:28 124
   // input:
1193b4be Poul Sander 2025-02-03 21:28 125
   stbrp_coord    w, h;
1193b4be Poul Sander 2025-02-03 21:28 126
1193b4be Poul Sander 2025-02-03 21:28 127
   // output:
1193b4be Poul Sander 2025-02-03 21:28 128
   stbrp_coord    x, y;
1193b4be Poul Sander 2025-02-03 21:28 129
   int            was_packed;  // non-zero if valid packing
1193b4be Poul Sander 2025-02-03 21:28 130
1193b4be Poul Sander 2025-02-03 21:28 131
}; // 16 bytes, nominally
1193b4be Poul Sander 2025-02-03 21:28 132
1193b4be Poul Sander 2025-02-03 21:28 133
1193b4be Poul Sander 2025-02-03 21:28 134
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
1193b4be Poul Sander 2025-02-03 21:28 135
// Initialize a rectangle packer to:
1193b4be Poul Sander 2025-02-03 21:28 136
//    pack a rectangle that is 'width' by 'height' in dimensions
1193b4be Poul Sander 2025-02-03 21:28 137
//    using temporary storage provided by the array 'nodes', which is 'num_nodes' long
1193b4be Poul Sander 2025-02-03 21:28 138
//
1193b4be Poul Sander 2025-02-03 21:28 139
// You must call this function every time you start packing into a new target.
1193b4be Poul Sander 2025-02-03 21:28 140
//
1193b4be Poul Sander 2025-02-03 21:28 141
// There is no "shutdown" function. The 'nodes' memory must stay valid for
1193b4be Poul Sander 2025-02-03 21:28 142
// the following stbrp_pack_rects() call (or calls), but can be freed after
1193b4be Poul Sander 2025-02-03 21:28 143
// the call (or calls) finish.
1193b4be Poul Sander 2025-02-03 21:28 144
//
1193b4be Poul Sander 2025-02-03 21:28 145
// Note: to guarantee best results, either:
1193b4be Poul Sander 2025-02-03 21:28 146
//       1. make sure 'num_nodes' >= 'width'
1193b4be Poul Sander 2025-02-03 21:28 147
//   or  2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
1193b4be Poul Sander 2025-02-03 21:28 148
//
1193b4be Poul Sander 2025-02-03 21:28 149
// If you don't do either of the above things, widths will be quantized to multiples
1193b4be Poul Sander 2025-02-03 21:28 150
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
1193b4be Poul Sander 2025-02-03 21:28 151
//
1193b4be Poul Sander 2025-02-03 21:28 152
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
1193b4be Poul Sander 2025-02-03 21:28 153
// may run out of temporary storage and be unable to pack some rectangles.
1193b4be Poul Sander 2025-02-03 21:28 154
1193b4be Poul Sander 2025-02-03 21:28 155
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
1193b4be Poul Sander 2025-02-03 21:28 156
// Optionally call this function after init but before doing any packing to
1193b4be Poul Sander 2025-02-03 21:28 157
// change the handling of the out-of-temp-memory scenario, described above.
1193b4be Poul Sander 2025-02-03 21:28 158
// If you call init again, this will be reset to the default (false).
1193b4be Poul Sander 2025-02-03 21:28 159
1193b4be Poul Sander 2025-02-03 21:28 160
1193b4be Poul Sander 2025-02-03 21:28 161
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
1193b4be Poul Sander 2025-02-03 21:28 162
// Optionally select which packing heuristic the library should use. Different
1193b4be Poul Sander 2025-02-03 21:28 163
// heuristics will produce better/worse results for different data sets.
1193b4be Poul Sander 2025-02-03 21:28 164
// If you call init again, this will be reset to the default.
1193b4be Poul Sander 2025-02-03 21:28 165
1193b4be Poul Sander 2025-02-03 21:28 166
enum
1193b4be Poul Sander 2025-02-03 21:28 167
{
1193b4be Poul Sander 2025-02-03 21:28 168
   STBRP_HEURISTIC_Skyline_default=0,
1193b4be Poul Sander 2025-02-03 21:28 169
   STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
1193b4be Poul Sander 2025-02-03 21:28 170
   STBRP_HEURISTIC_Skyline_BF_sortHeight
1193b4be Poul Sander 2025-02-03 21:28 171
};
1193b4be Poul Sander 2025-02-03 21:28 172
1193b4be Poul Sander 2025-02-03 21:28 173
1193b4be Poul Sander 2025-02-03 21:28 174
//////////////////////////////////////////////////////////////////////////////
1193b4be Poul Sander 2025-02-03 21:28 175
//
1193b4be Poul Sander 2025-02-03 21:28 176
// the details of the following structures don't matter to you, but they must
1193b4be Poul Sander 2025-02-03 21:28 177
// be visible so you can handle the memory allocations for them
1193b4be Poul Sander 2025-02-03 21:28 178
1193b4be Poul Sander 2025-02-03 21:28 179
struct stbrp_node
1193b4be Poul Sander 2025-02-03 21:28 180
{
1193b4be Poul Sander 2025-02-03 21:28 181
   stbrp_coord  x,y;
1193b4be Poul Sander 2025-02-03 21:28 182
   stbrp_node  *next;
1193b4be Poul Sander 2025-02-03 21:28 183
};
1193b4be Poul Sander 2025-02-03 21:28 184
1193b4be Poul Sander 2025-02-03 21:28 185
struct stbrp_context
1193b4be Poul Sander 2025-02-03 21:28 186
{
1193b4be Poul Sander 2025-02-03 21:28 187
   int width;
1193b4be Poul Sander 2025-02-03 21:28 188
   int height;
1193b4be Poul Sander 2025-02-03 21:28 189
   int align;
1193b4be Poul Sander 2025-02-03 21:28 190
   int init_mode;
1193b4be Poul Sander 2025-02-03 21:28 191
   int heuristic;
1193b4be Poul Sander 2025-02-03 21:28 192
   int num_nodes;
1193b4be Poul Sander 2025-02-03 21:28 193
   stbrp_node *active_head;
1193b4be Poul Sander 2025-02-03 21:28 194
   stbrp_node *free_head;
1193b4be Poul Sander 2025-02-03 21:28 195
   stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
1193b4be Poul Sander 2025-02-03 21:28 196
};
1193b4be Poul Sander 2025-02-03 21:28 197
1193b4be Poul Sander 2025-02-03 21:28 198
#ifdef __cplusplus
1193b4be Poul Sander 2025-02-03 21:28 199
}
1193b4be Poul Sander 2025-02-03 21:28 200
#endif
1193b4be Poul Sander 2025-02-03 21:28 201
1193b4be Poul Sander 2025-02-03 21:28 202
#endif
1193b4be Poul Sander 2025-02-03 21:28 203
1193b4be Poul Sander 2025-02-03 21:28 204
//////////////////////////////////////////////////////////////////////////////
1193b4be Poul Sander 2025-02-03 21:28 205
//
1193b4be Poul Sander 2025-02-03 21:28 206
//     IMPLEMENTATION SECTION
1193b4be Poul Sander 2025-02-03 21:28 207
//
1193b4be Poul Sander 2025-02-03 21:28 208
1193b4be Poul Sander 2025-02-03 21:28 209
#ifdef STB_RECT_PACK_IMPLEMENTATION
1193b4be Poul Sander 2025-02-03 21:28 210
#ifndef STBRP_SORT
1193b4be Poul Sander 2025-02-03 21:28 211
#include <stdlib.h>
1193b4be Poul Sander 2025-02-03 21:28 212
#define STBRP_SORT qsort
1193b4be Poul Sander 2025-02-03 21:28 213
#endif
1193b4be Poul Sander 2025-02-03 21:28 214
1193b4be Poul Sander 2025-02-03 21:28 215
#ifndef STBRP_ASSERT
1193b4be Poul Sander 2025-02-03 21:28 216
#include <assert.h>
1193b4be Poul Sander 2025-02-03 21:28 217
#define STBRP_ASSERT assert
1193b4be Poul Sander 2025-02-03 21:28 218
#endif
1193b4be Poul Sander 2025-02-03 21:28 219
1193b4be Poul Sander 2025-02-03 21:28 220
#ifdef _MSC_VER
1193b4be Poul Sander 2025-02-03 21:28 221
#define STBRP__NOTUSED(v)  (void)(v)
1193b4be Poul Sander 2025-02-03 21:28 222
#define STBRP__CDECL       __cdecl
1193b4be Poul Sander 2025-02-03 21:28 223
#else
1193b4be Poul Sander 2025-02-03 21:28 224
#define STBRP__NOTUSED(v)  (void)sizeof(v)
1193b4be Poul Sander 2025-02-03 21:28 225
#define STBRP__CDECL
1193b4be Poul Sander 2025-02-03 21:28 226
#endif
1193b4be Poul Sander 2025-02-03 21:28 227
1193b4be Poul Sander 2025-02-03 21:28 228
enum
1193b4be Poul Sander 2025-02-03 21:28 229
{
1193b4be Poul Sander 2025-02-03 21:28 230
   STBRP__INIT_skyline = 1
1193b4be Poul Sander 2025-02-03 21:28 231
};
1193b4be Poul Sander 2025-02-03 21:28 232
1193b4be Poul Sander 2025-02-03 21:28 233
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
1193b4be Poul Sander 2025-02-03 21:28 234
{
1193b4be Poul Sander 2025-02-03 21:28 235
   switch (context->init_mode) {
1193b4be Poul Sander 2025-02-03 21:28 236
      case STBRP__INIT_skyline:
1193b4be Poul Sander 2025-02-03 21:28 237
         STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
1193b4be Poul Sander 2025-02-03 21:28 238
         context->heuristic = heuristic;
1193b4be Poul Sander 2025-02-03 21:28 239
         break;
1193b4be Poul Sander 2025-02-03 21:28 240
      default:
1193b4be Poul Sander 2025-02-03 21:28 241
         STBRP_ASSERT(0);
1193b4be Poul Sander 2025-02-03 21:28 242
   }
1193b4be Poul Sander 2025-02-03 21:28 243
}
1193b4be Poul Sander 2025-02-03 21:28 244
1193b4be Poul Sander 2025-02-03 21:28 245
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
1193b4be Poul Sander 2025-02-03 21:28 246
{
1193b4be Poul Sander 2025-02-03 21:28 247
   if (allow_out_of_mem)
1193b4be Poul Sander 2025-02-03 21:28 248
      // if it's ok to run out of memory, then don't bother aligning them;
1193b4be Poul Sander 2025-02-03 21:28 249
      // this gives better packing, but may fail due to OOM (even though
1193b4be Poul Sander 2025-02-03 21:28 250
      // the rectangles easily fit). @TODO a smarter approach would be to only
1193b4be Poul Sander 2025-02-03 21:28 251
      // quantize once we've hit OOM, then we could get rid of this parameter.
1193b4be Poul Sander 2025-02-03 21:28 252
      context->align = 1;
1193b4be Poul Sander 2025-02-03 21:28 253
   else {
1193b4be Poul Sander 2025-02-03 21:28 254
      // if it's not ok to run out of memory, then quantize the widths
1193b4be Poul Sander 2025-02-03 21:28 255
      // so that num_nodes is always enough nodes.
1193b4be Poul Sander 2025-02-03 21:28 256
      //
1193b4be Poul Sander 2025-02-03 21:28 257
      // I.e. num_nodes * align >= width
1193b4be Poul Sander 2025-02-03 21:28 258
      //                  align >= width / num_nodes
1193b4be Poul Sander 2025-02-03 21:28 259
      //                  align = ceil(width/num_nodes)
1193b4be Poul Sander 2025-02-03 21:28 260
1193b4be Poul Sander 2025-02-03 21:28 261
      context->align = (context->width + context->num_nodes-1) / context->num_nodes;
1193b4be Poul Sander 2025-02-03 21:28 262
   }
1193b4be Poul Sander 2025-02-03 21:28 263
}
1193b4be Poul Sander 2025-02-03 21:28 264
1193b4be Poul Sander 2025-02-03 21:28 265
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
1193b4be Poul Sander 2025-02-03 21:28 266
{
1193b4be Poul Sander 2025-02-03 21:28 267
   int i;
1193b4be Poul Sander 2025-02-03 21:28 268
1193b4be Poul Sander 2025-02-03 21:28 269
   for (i=0; i < num_nodes-1; ++i)
1193b4be Poul Sander 2025-02-03 21:28 270
      nodes[i].next = &nodes[i+1];
1193b4be Poul Sander 2025-02-03 21:28 271
   nodes[i].next = NULL;
1193b4be Poul Sander 2025-02-03 21:28 272
   context->init_mode = STBRP__INIT_skyline;
1193b4be Poul Sander 2025-02-03 21:28 273
   context->heuristic = STBRP_HEURISTIC_Skyline_default;
1193b4be Poul Sander 2025-02-03 21:28 274
   context->free_head = &nodes[0];
1193b4be Poul Sander 2025-02-03 21:28 275
   context->active_head = &context->extra[0];
1193b4be Poul Sander 2025-02-03 21:28 276
   context->width = width;
1193b4be Poul Sander 2025-02-03 21:28 277
   context->height = height;
1193b4be Poul Sander 2025-02-03 21:28 278
   context->num_nodes = num_nodes;
1193b4be Poul Sander 2025-02-03 21:28 279
   stbrp_setup_allow_out_of_mem(context, 0);
1193b4be Poul Sander 2025-02-03 21:28 280
1193b4be Poul Sander 2025-02-03 21:28 281
   // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
1193b4be Poul Sander 2025-02-03 21:28 282
   context->extra[0].x = 0;
1193b4be Poul Sander 2025-02-03 21:28 283
   context->extra[0].y = 0;
1193b4be Poul Sander 2025-02-03 21:28 284
   context->extra[0].next = &context->extra[1];
1193b4be Poul Sander 2025-02-03 21:28 285
   context->extra[1].x = (stbrp_coord) width;
1193b4be Poul Sander 2025-02-03 21:28 286
   context->extra[1].y = (1<<30);
1193b4be Poul Sander 2025-02-03 21:28 287
   context->extra[1].next = NULL;
1193b4be Poul Sander 2025-02-03 21:28 288
}
1193b4be Poul Sander 2025-02-03 21:28 289
1193b4be Poul Sander 2025-02-03 21:28 290
// find minimum y position if it starts at x1
1193b4be Poul Sander 2025-02-03 21:28 291
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
1193b4be Poul Sander 2025-02-03 21:28 292
{
1193b4be Poul Sander 2025-02-03 21:28 293
   stbrp_node *node = first;
1193b4be Poul Sander 2025-02-03 21:28 294
   int x1 = x0 + width;
1193b4be Poul Sander 2025-02-03 21:28 295
   int min_y, visited_width, waste_area;
1193b4be Poul Sander 2025-02-03 21:28 296
1193b4be Poul Sander 2025-02-03 21:28 297
   STBRP__NOTUSED(c);
1193b4be Poul Sander 2025-02-03 21:28 298
1193b4be Poul Sander 2025-02-03 21:28 299
   STBRP_ASSERT(first->x <= x0);
1193b4be Poul Sander 2025-02-03 21:28 300
1193b4be Poul Sander 2025-02-03 21:28 301
   #if 0
1193b4be Poul Sander 2025-02-03 21:28 302
   // skip in case we're past the node
1193b4be Poul Sander 2025-02-03 21:28 303
   while (node->next->x <= x0)
1193b4be Poul Sander 2025-02-03 21:28 304
      ++node;
1193b4be Poul Sander 2025-02-03 21:28 305
   #else
1193b4be Poul Sander 2025-02-03 21:28 306
   STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
1193b4be Poul Sander 2025-02-03 21:28 307
   #endif
1193b4be Poul Sander 2025-02-03 21:28 308
1193b4be Poul Sander 2025-02-03 21:28 309
   STBRP_ASSERT(node->x <= x0);
1193b4be Poul Sander 2025-02-03 21:28 310
1193b4be Poul Sander 2025-02-03 21:28 311
   min_y = 0;
1193b4be Poul Sander 2025-02-03 21:28 312
   waste_area = 0;
1193b4be Poul Sander 2025-02-03 21:28 313
   visited_width = 0;
1193b4be Poul Sander 2025-02-03 21:28 314
   while (node->x < x1) {
1193b4be Poul Sander 2025-02-03 21:28 315
      if (node->y > min_y) {
1193b4be Poul Sander 2025-02-03 21:28 316
         // raise min_y higher.
1193b4be Poul Sander 2025-02-03 21:28 317
         // we've accounted for all waste up to min_y,
1193b4be Poul Sander 2025-02-03 21:28 318
         // but we'll now add more waste for everything we've visted
1193b4be Poul Sander 2025-02-03 21:28 319
         waste_area += visited_width * (node->y - min_y);
1193b4be Poul Sander 2025-02-03 21:28 320
         min_y = node->y;
1193b4be Poul Sander 2025-02-03 21:28 321
         // the first time through, visited_width might be reduced
1193b4be Poul Sander 2025-02-03 21:28 322
         if (node->x < x0)
1193b4be Poul Sander 2025-02-03 21:28 323
            visited_width += node->next->x - x0;
1193b4be Poul Sander 2025-02-03 21:28 324
         else
1193b4be Poul Sander 2025-02-03 21:28 325
            visited_width += node->next->x - node->x;
1193b4be Poul Sander 2025-02-03 21:28 326
      } else {
1193b4be Poul Sander 2025-02-03 21:28 327
         // add waste area
1193b4be Poul Sander 2025-02-03 21:28 328
         int under_width = node->next->x - node->x;
1193b4be Poul Sander 2025-02-03 21:28 329
         if (under_width + visited_width > width)
1193b4be Poul Sander 2025-02-03 21:28 330
            under_width = width - visited_width;
1193b4be Poul Sander 2025-02-03 21:28 331
         waste_area += under_width * (min_y - node->y);
1193b4be Poul Sander 2025-02-03 21:28 332
         visited_width += under_width;
1193b4be Poul Sander 2025-02-03 21:28 333
      }
1193b4be Poul Sander 2025-02-03 21:28 334
      node = node->next;
1193b4be Poul Sander 2025-02-03 21:28 335
   }
1193b4be Poul Sander 2025-02-03 21:28 336
1193b4be Poul Sander 2025-02-03 21:28 337
   *pwaste = waste_area;
1193b4be Poul Sander 2025-02-03 21:28 338
   return min_y;
1193b4be Poul Sander 2025-02-03 21:28 339
}
1193b4be Poul Sander 2025-02-03 21:28 340
1193b4be Poul Sander 2025-02-03 21:28 341
typedef struct
1193b4be Poul Sander 2025-02-03 21:28 342
{
1193b4be Poul Sander 2025-02-03 21:28 343
   int x,y;
1193b4be Poul Sander 2025-02-03 21:28 344
   stbrp_node **prev_link;
1193b4be Poul Sander 2025-02-03 21:28 345
} stbrp__findresult;
1193b4be Poul Sander 2025-02-03 21:28 346
1193b4be Poul Sander 2025-02-03 21:28 347
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
1193b4be Poul Sander 2025-02-03 21:28 348
{
1193b4be Poul Sander 2025-02-03 21:28 349
   int best_waste = (1<<30), best_x, best_y = (1 << 30);
1193b4be Poul Sander 2025-02-03 21:28 350
   stbrp__findresult fr;
1193b4be Poul Sander 2025-02-03 21:28 351
   stbrp_node **prev, *node, *tail, **best = NULL;
1193b4be Poul Sander 2025-02-03 21:28 352
1193b4be Poul Sander 2025-02-03 21:28 353
   // align to multiple of c->align
1193b4be Poul Sander 2025-02-03 21:28 354
   width = (width + c->align - 1);
1193b4be Poul Sander 2025-02-03 21:28 355
   width -= width % c->align;
1193b4be Poul Sander 2025-02-03 21:28 356
   STBRP_ASSERT(width % c->align == 0);
1193b4be Poul Sander 2025-02-03 21:28 357
1193b4be Poul Sander 2025-02-03 21:28 358
   // if it can't possibly fit, bail immediately
1193b4be Poul Sander 2025-02-03 21:28 359
   if (width > c->width || height > c->height) {
1193b4be Poul Sander 2025-02-03 21:28 360
      fr.prev_link = NULL;
1193b4be Poul Sander 2025-02-03 21:28 361
      fr.x = fr.y = 0;
1193b4be Poul Sander 2025-02-03 21:28 362
      return fr;
1193b4be Poul Sander 2025-02-03 21:28 363
   }
1193b4be Poul Sander 2025-02-03 21:28 364
1193b4be Poul Sander 2025-02-03 21:28 365
   node = c->active_head;
1193b4be Poul Sander 2025-02-03 21:28 366
   prev = &c->active_head;
1193b4be Poul Sander 2025-02-03 21:28 367
   while (node->x + width <= c->width) {
1193b4be Poul Sander 2025-02-03 21:28 368
      int y,waste;
1193b4be Poul Sander 2025-02-03 21:28 369
      y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
1193b4be Poul Sander 2025-02-03 21:28 370
      if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
1193b4be Poul Sander 2025-02-03 21:28 371
         // bottom left
1193b4be Poul Sander 2025-02-03 21:28 372
         if (y < best_y) {
1193b4be Poul Sander 2025-02-03 21:28 373
            best_y = y;
1193b4be Poul Sander 2025-02-03 21:28 374
            best = prev;
1193b4be Poul Sander 2025-02-03 21:28 375
         }
1193b4be Poul Sander 2025-02-03 21:28 376
      } else {
1193b4be Poul Sander 2025-02-03 21:28 377
         // best-fit
1193b4be Poul Sander 2025-02-03 21:28 378
         if (y + height <= c->height) {
1193b4be Poul Sander 2025-02-03 21:28 379
            // can only use it if it first vertically
1193b4be Poul Sander 2025-02-03 21:28 380
            if (y < best_y || (y == best_y && waste < best_waste)) {
1193b4be Poul Sander 2025-02-03 21:28 381
               best_y = y;
1193b4be Poul Sander 2025-02-03 21:28 382
               best_waste = waste;
1193b4be Poul Sander 2025-02-03 21:28 383
               best = prev;
1193b4be Poul Sander 2025-02-03 21:28 384
            }
1193b4be Poul Sander 2025-02-03 21:28 385
         }
1193b4be Poul Sander 2025-02-03 21:28 386
      }
1193b4be Poul Sander 2025-02-03 21:28 387
      prev = &node->next;
1193b4be Poul Sander 2025-02-03 21:28 388
      node = node->next;
1193b4be Poul Sander 2025-02-03 21:28 389
   }
1193b4be Poul Sander 2025-02-03 21:28 390
1193b4be Poul Sander 2025-02-03 21:28 391
   best_x = (best == NULL) ? 0 : (*best)->x;
1193b4be Poul Sander 2025-02-03 21:28 392
1193b4be Poul Sander 2025-02-03 21:28 393
   // if doing best-fit (BF), we also have to try aligning right edge to each node position
1193b4be Poul Sander 2025-02-03 21:28 394
   //
1193b4be Poul Sander 2025-02-03 21:28 395
   // e.g, if fitting
1193b4be Poul Sander 2025-02-03 21:28 396
   //
1193b4be Poul Sander 2025-02-03 21:28 397
   //     ____________________
1193b4be Poul Sander 2025-02-03 21:28 398
   //    |____________________|
1193b4be Poul Sander 2025-02-03 21:28 399
   //
1193b4be Poul Sander 2025-02-03 21:28 400
   //            into
1193b4be Poul Sander 2025-02-03 21:28 401
   //
1193b4be Poul Sander 2025-02-03 21:28 402
   //   |                         |
1193b4be Poul Sander 2025-02-03 21:28 403
   //   |             ____________|
1193b4be Poul Sander 2025-02-03 21:28 404
   //   |____________|
1193b4be Poul Sander 2025-02-03 21:28 405
   //
1193b4be Poul Sander 2025-02-03 21:28 406
   // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
1193b4be Poul Sander 2025-02-03 21:28 407
   //
1193b4be Poul Sander 2025-02-03 21:28 408
   // This makes BF take about 2x the time
1193b4be Poul Sander 2025-02-03 21:28 409
1193b4be Poul Sander 2025-02-03 21:28 410
   if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
1193b4be Poul Sander 2025-02-03 21:28 411
      tail = c->active_head;
1193b4be Poul Sander 2025-02-03 21:28 412
      node = c->active_head;
1193b4be Poul Sander 2025-02-03 21:28 413
      prev = &c->active_head;
1193b4be Poul Sander 2025-02-03 21:28 414
      // find first node that's admissible
1193b4be Poul Sander 2025-02-03 21:28 415
      while (tail->x < width)
1193b4be Poul Sander 2025-02-03 21:28 416
         tail = tail->next;
1193b4be Poul Sander 2025-02-03 21:28 417
      while (tail) {
1193b4be Poul Sander 2025-02-03 21:28 418
         int xpos = tail->x - width;
1193b4be Poul Sander 2025-02-03 21:28 419
         int y,waste;
1193b4be Poul Sander 2025-02-03 21:28 420
         STBRP_ASSERT(xpos >= 0);
1193b4be Poul Sander 2025-02-03 21:28 421
         // find the left position that matches this
1193b4be Poul Sander 2025-02-03 21:28 422
         while (node->next->x <= xpos) {
1193b4be Poul Sander 2025-02-03 21:28 423
            prev = &node->next;
1193b4be Poul Sander 2025-02-03 21:28 424
            node = node->next;
1193b4be Poul Sander 2025-02-03 21:28 425
         }
1193b4be Poul Sander 2025-02-03 21:28 426
         STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
1193b4be Poul Sander 2025-02-03 21:28 427
         y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
1193b4be Poul Sander 2025-02-03 21:28 428
         if (y + height <= c->height) {
1193b4be Poul Sander 2025-02-03 21:28 429
            if (y <= best_y) {
1193b4be Poul Sander 2025-02-03 21:28 430
               if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
1193b4be Poul Sander 2025-02-03 21:28 431
                  best_x = xpos;
1193b4be Poul Sander 2025-02-03 21:28 432
                  //STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
1193b4be Poul Sander 2025-02-03 21:28 433
                  best_y = y;
1193b4be Poul Sander 2025-02-03 21:28 434
                  best_waste = waste;
1193b4be Poul Sander 2025-02-03 21:28 435
                  best = prev;
1193b4be Poul Sander 2025-02-03 21:28 436
               }
1193b4be Poul Sander 2025-02-03 21:28 437
            }
1193b4be Poul Sander 2025-02-03 21:28 438
         }
1193b4be Poul Sander 2025-02-03 21:28 439
         tail = tail->next;
1193b4be Poul Sander 2025-02-03 21:28 440
      }
1193b4be Poul Sander 2025-02-03 21:28 441
   }
1193b4be Poul Sander 2025-02-03 21:28 442
1193b4be Poul Sander 2025-02-03 21:28 443
   fr.prev_link = best;
1193b4be Poul Sander 2025-02-03 21:28 444
   fr.x = best_x;
1193b4be Poul Sander 2025-02-03 21:28 445
   fr.y = best_y;
1193b4be Poul Sander 2025-02-03 21:28 446
   return fr;
1193b4be Poul Sander 2025-02-03 21:28 447
}
1193b4be Poul Sander 2025-02-03 21:28 448
1193b4be Poul Sander 2025-02-03 21:28 449
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
1193b4be Poul Sander 2025-02-03 21:28 450
{
1193b4be Poul Sander 2025-02-03 21:28 451
   // find best position according to heuristic
1193b4be Poul Sander 2025-02-03 21:28 452
   stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
1193b4be Poul Sander 2025-02-03 21:28 453
   stbrp_node *node, *cur;
1193b4be Poul Sander 2025-02-03 21:28 454
1193b4be Poul Sander 2025-02-03 21:28 455
   // bail if:
1193b4be Poul Sander 2025-02-03 21:28 456
   //    1. it failed
1193b4be Poul Sander 2025-02-03 21:28 457
   //    2. the best node doesn't fit (we don't always check this)
1193b4be Poul Sander 2025-02-03 21:28 458
   //    3. we're out of memory
1193b4be Poul Sander 2025-02-03 21:28 459
   if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
1193b4be Poul Sander 2025-02-03 21:28 460
      res.prev_link = NULL;
1193b4be Poul Sander 2025-02-03 21:28 461
      return res;
1193b4be Poul Sander 2025-02-03 21:28 462
   }
1193b4be Poul Sander 2025-02-03 21:28 463
1193b4be Poul Sander 2025-02-03 21:28 464
   // on success, create new node
1193b4be Poul Sander 2025-02-03 21:28 465
   node = context->free_head;
1193b4be Poul Sander 2025-02-03 21:28 466
   node->x = (stbrp_coord) res.x;
1193b4be Poul Sander 2025-02-03 21:28 467
   node->y = (stbrp_coord) (res.y + height);
1193b4be Poul Sander 2025-02-03 21:28 468
1193b4be Poul Sander 2025-02-03 21:28 469
   context->free_head = node->next;
1193b4be Poul Sander 2025-02-03 21:28 470
1193b4be Poul Sander 2025-02-03 21:28 471
   // insert the new node into the right starting point, and
1193b4be Poul Sander 2025-02-03 21:28 472
   // let 'cur' point to the remaining nodes needing to be
1193b4be Poul Sander 2025-02-03 21:28 473
   // stiched back in
1193b4be Poul Sander 2025-02-03 21:28 474
1193b4be Poul Sander 2025-02-03 21:28 475
   cur = *res.prev_link;
1193b4be Poul Sander 2025-02-03 21:28 476
   if (cur->x < res.x) {
1193b4be Poul Sander 2025-02-03 21:28 477
      // preserve the existing one, so start testing with the next one
1193b4be Poul Sander 2025-02-03 21:28 478
      stbrp_node *next = cur->next;
1193b4be Poul Sander 2025-02-03 21:28 479
      cur->next = node;
1193b4be Poul Sander 2025-02-03 21:28 480
      cur = next;
1193b4be Poul Sander 2025-02-03 21:28 481
   } else {
1193b4be Poul Sander 2025-02-03 21:28 482
      *res.prev_link = node;
1193b4be Poul Sander 2025-02-03 21:28 483
   }
1193b4be Poul Sander 2025-02-03 21:28 484
1193b4be Poul Sander 2025-02-03 21:28 485
   // from here, traverse cur and free the nodes, until we get to one
1193b4be Poul Sander 2025-02-03 21:28 486
   // that shouldn't be freed
1193b4be Poul Sander 2025-02-03 21:28 487
   while (cur->next && cur->next->x <= res.x + width) {
1193b4be Poul Sander 2025-02-03 21:28 488
      stbrp_node *next = cur->next;
1193b4be Poul Sander 2025-02-03 21:28 489
      // move the current node to the free list
1193b4be Poul Sander 2025-02-03 21:28 490
      cur->next = context->free_head;
1193b4be Poul Sander 2025-02-03 21:28 491
      context->free_head = cur;
1193b4be Poul Sander 2025-02-03 21:28 492
      cur = next;
1193b4be Poul Sander 2025-02-03 21:28 493
   }
1193b4be Poul Sander 2025-02-03 21:28 494
1193b4be Poul Sander 2025-02-03 21:28 495
   // stitch the list back in
1193b4be Poul Sander 2025-02-03 21:28 496
   node->next = cur;
1193b4be Poul Sander 2025-02-03 21:28 497
1193b4be Poul Sander 2025-02-03 21:28 498
   if (cur->x < res.x + width)
1193b4be Poul Sander 2025-02-03 21:28 499
      cur->x = (stbrp_coord) (res.x + width);
1193b4be Poul Sander 2025-02-03 21:28 500
1193b4be Poul Sander 2025-02-03 21:28 501
#ifdef _DEBUG
1193b4be Poul Sander 2025-02-03 21:28 502
   cur = context->active_head;
1193b4be Poul Sander 2025-02-03 21:28 503
   while (cur->x < context->width) {
1193b4be Poul Sander 2025-02-03 21:28 504
      STBRP_ASSERT(cur->x < cur->next->x);
1193b4be Poul Sander 2025-02-03 21:28 505
      cur = cur->next;
1193b4be Poul Sander 2025-02-03 21:28 506
   }
1193b4be Poul Sander 2025-02-03 21:28 507
   STBRP_ASSERT(cur->next == NULL);
1193b4be Poul Sander 2025-02-03 21:28 508
1193b4be Poul Sander 2025-02-03 21:28 509
   {
1193b4be Poul Sander 2025-02-03 21:28 510
      int count=0;
1193b4be Poul Sander 2025-02-03 21:28 511
      cur = context->active_head;
1193b4be Poul Sander 2025-02-03 21:28 512
      while (cur) {
1193b4be Poul Sander 2025-02-03 21:28 513
         cur = cur->next;
1193b4be Poul Sander 2025-02-03 21:28 514
         ++count;
1193b4be Poul Sander 2025-02-03 21:28 515
      }
1193b4be Poul Sander 2025-02-03 21:28 516
      cur = context->free_head;
1193b4be Poul Sander 2025-02-03 21:28 517
      while (cur) {
1193b4be Poul Sander 2025-02-03 21:28 518
         cur = cur->next;
1193b4be Poul Sander 2025-02-03 21:28 519
         ++count;
1193b4be Poul Sander 2025-02-03 21:28 520
      }
1193b4be Poul Sander 2025-02-03 21:28 521
      STBRP_ASSERT(count == context->num_nodes+2);
1193b4be Poul Sander 2025-02-03 21:28 522
   }
1193b4be Poul Sander 2025-02-03 21:28 523
#endif
1193b4be Poul Sander 2025-02-03 21:28 524
1193b4be Poul Sander 2025-02-03 21:28 525
   return res;
1193b4be Poul Sander 2025-02-03 21:28 526
}
1193b4be Poul Sander 2025-02-03 21:28 527
1193b4be Poul Sander 2025-02-03 21:28 528
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
1193b4be Poul Sander 2025-02-03 21:28 529
{
1193b4be Poul Sander 2025-02-03 21:28 530
   const stbrp_rect *p = (const stbrp_rect *) a;
1193b4be Poul Sander 2025-02-03 21:28 531
   const stbrp_rect *q = (const stbrp_rect *) b;
1193b4be Poul Sander 2025-02-03 21:28 532
   if (p->h > q->h)
1193b4be Poul Sander 2025-02-03 21:28 533
      return -1;
1193b4be Poul Sander 2025-02-03 21:28 534
   if (p->h < q->h)
1193b4be Poul Sander 2025-02-03 21:28 535
      return  1;
1193b4be Poul Sander 2025-02-03 21:28 536
   return (p->w > q->w) ? -1 : (p->w < q->w);
1193b4be Poul Sander 2025-02-03 21:28 537
}
1193b4be Poul Sander 2025-02-03 21:28 538
1193b4be Poul Sander 2025-02-03 21:28 539
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
1193b4be Poul Sander 2025-02-03 21:28 540
{
1193b4be Poul Sander 2025-02-03 21:28 541
   const stbrp_rect *p = (const stbrp_rect *) a;
1193b4be Poul Sander 2025-02-03 21:28 542
   const stbrp_rect *q = (const stbrp_rect *) b;
1193b4be Poul Sander 2025-02-03 21:28 543
   return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
1193b4be Poul Sander 2025-02-03 21:28 544
}
1193b4be Poul Sander 2025-02-03 21:28 545
1193b4be Poul Sander 2025-02-03 21:28 546
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
1193b4be Poul Sander 2025-02-03 21:28 547
{
1193b4be Poul Sander 2025-02-03 21:28 548
   int i, all_rects_packed = 1;
1193b4be Poul Sander 2025-02-03 21:28 549
1193b4be Poul Sander 2025-02-03 21:28 550
   // we use the 'was_packed' field internally to allow sorting/unsorting
1193b4be Poul Sander 2025-02-03 21:28 551
   for (i=0; i < num_rects; ++i) {
1193b4be Poul Sander 2025-02-03 21:28 552
      rects[i].was_packed = i;
1193b4be Poul Sander 2025-02-03 21:28 553
   }
1193b4be Poul Sander 2025-02-03 21:28 554
1193b4be Poul Sander 2025-02-03 21:28 555
   // sort according to heuristic
1193b4be Poul Sander 2025-02-03 21:28 556
   STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
1193b4be Poul Sander 2025-02-03 21:28 557
1193b4be Poul Sander 2025-02-03 21:28 558
   for (i=0; i < num_rects; ++i) {
1193b4be Poul Sander 2025-02-03 21:28 559
      if (rects[i].w == 0 || rects[i].h == 0) {
1193b4be Poul Sander 2025-02-03 21:28 560
         rects[i].x = rects[i].y = 0;  // empty rect needs no space
1193b4be Poul Sander 2025-02-03 21:28 561
      } else {
1193b4be Poul Sander 2025-02-03 21:28 562
         stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
1193b4be Poul Sander 2025-02-03 21:28 563
         if (fr.prev_link) {
1193b4be Poul Sander 2025-02-03 21:28 564
            rects[i].x = (stbrp_coord) fr.x;
1193b4be Poul Sander 2025-02-03 21:28 565
            rects[i].y = (stbrp_coord) fr.y;
1193b4be Poul Sander 2025-02-03 21:28 566
         } else {
1193b4be Poul Sander 2025-02-03 21:28 567
            rects[i].x = rects[i].y = STBRP__MAXVAL;
1193b4be Poul Sander 2025-02-03 21:28 568
         }
1193b4be Poul Sander 2025-02-03 21:28 569
      }
1193b4be Poul Sander 2025-02-03 21:28 570
   }
1193b4be Poul Sander 2025-02-03 21:28 571
1193b4be Poul Sander 2025-02-03 21:28 572
   // unsort
1193b4be Poul Sander 2025-02-03 21:28 573
   STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
1193b4be Poul Sander 2025-02-03 21:28 574
1193b4be Poul Sander 2025-02-03 21:28 575
   // set was_packed flags and all_rects_packed status
1193b4be Poul Sander 2025-02-03 21:28 576
   for (i=0; i < num_rects; ++i) {
1193b4be Poul Sander 2025-02-03 21:28 577
      rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
1193b4be Poul Sander 2025-02-03 21:28 578
      if (!rects[i].was_packed)
1193b4be Poul Sander 2025-02-03 21:28 579
         all_rects_packed = 0;
1193b4be Poul Sander 2025-02-03 21:28 580
   }
1193b4be Poul Sander 2025-02-03 21:28 581
1193b4be Poul Sander 2025-02-03 21:28 582
   // return the all_rects_packed status
1193b4be Poul Sander 2025-02-03 21:28 583
   return all_rects_packed;
1193b4be Poul Sander 2025-02-03 21:28 584
}
1193b4be Poul Sander 2025-02-03 21:28 585
#endif
1193b4be Poul Sander 2025-02-03 21:28 586
1193b4be Poul Sander 2025-02-03 21:28 587
/*
1193b4be Poul Sander 2025-02-03 21:28 588
------------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 589
This software is available under 2 licenses -- choose whichever you prefer.
1193b4be Poul Sander 2025-02-03 21:28 590
------------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 591
ALTERNATIVE A - MIT License
1193b4be Poul Sander 2025-02-03 21:28 592
Copyright (c) 2017 Sean Barrett
1193b4be Poul Sander 2025-02-03 21:28 593
Permission is hereby granted, free of charge, to any person obtaining a copy of
1193b4be Poul Sander 2025-02-03 21:28 594
this software and associated documentation files (the "Software"), to deal in
1193b4be Poul Sander 2025-02-03 21:28 595
the Software without restriction, including without limitation the rights to
1193b4be Poul Sander 2025-02-03 21:28 596
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1193b4be Poul Sander 2025-02-03 21:28 597
of the Software, and to permit persons to whom the Software is furnished to do
1193b4be Poul Sander 2025-02-03 21:28 598
so, subject to the following conditions:
1193b4be Poul Sander 2025-02-03 21:28 599
The above copyright notice and this permission notice shall be included in all
1193b4be Poul Sander 2025-02-03 21:28 600
copies or substantial portions of the Software.
1193b4be Poul Sander 2025-02-03 21:28 601
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1193b4be Poul Sander 2025-02-03 21:28 602
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1193b4be Poul Sander 2025-02-03 21:28 603
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1193b4be Poul Sander 2025-02-03 21:28 604
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1193b4be Poul Sander 2025-02-03 21:28 605
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1193b4be Poul Sander 2025-02-03 21:28 606
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1193b4be Poul Sander 2025-02-03 21:28 607
SOFTWARE.
1193b4be Poul Sander 2025-02-03 21:28 608
------------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 609
ALTERNATIVE B - Public Domain (www.unlicense.org)
1193b4be Poul Sander 2025-02-03 21:28 610
This is free and unencumbered software released into the public domain.
1193b4be Poul Sander 2025-02-03 21:28 611
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
1193b4be Poul Sander 2025-02-03 21:28 612
software, either in source code form or as a compiled binary, for any purpose,
1193b4be Poul Sander 2025-02-03 21:28 613
commercial or non-commercial, and by any means.
1193b4be Poul Sander 2025-02-03 21:28 614
In jurisdictions that recognize copyright laws, the author or authors of this
1193b4be Poul Sander 2025-02-03 21:28 615
software dedicate any and all copyright interest in the software to the public
1193b4be Poul Sander 2025-02-03 21:28 616
domain. We make this dedication for the benefit of the public at large and to
1193b4be Poul Sander 2025-02-03 21:28 617
the detriment of our heirs and successors. We intend this dedication to be an
1193b4be Poul Sander 2025-02-03 21:28 618
overt act of relinquishment in perpetuity of all present and future rights to
1193b4be Poul Sander 2025-02-03 21:28 619
this software under copyright law.
1193b4be Poul Sander 2025-02-03 21:28 620
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1193b4be Poul Sander 2025-02-03 21:28 621
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1193b4be Poul Sander 2025-02-03 21:28 622
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1193b4be Poul Sander 2025-02-03 21:28 623
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1193b4be Poul Sander 2025-02-03 21:28 624
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1193b4be Poul Sander 2025-02-03 21:28 625
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1193b4be Poul Sander 2025-02-03 21:28 626
------------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 627
*/
1970-01-01 00:00 628