payredu

Cross-platform ledger GUI written in c99
git clone git@getsh.org:payredu.git
Log | Files | Refs | README

nuklear.h (1162955B)


      1 /*
      2 /// # Nuklear
      3 /// ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif)
      4 ///
      5 /// ## Contents
      6 /// 1. About section
      7 /// 2. Highlights section
      8 /// 3. Features section
      9 /// 4. Usage section
     10 ///     1. Flags section
     11 ///     2. Constants section
     12 ///     3. Dependencies section
     13 /// 5. Example section
     14 /// 6. API section
     15 ///     1. Context section
     16 ///     2. Input section
     17 ///     3. Drawing section
     18 ///     4. Window section
     19 ///     5. Layouting section
     20 ///     6. Groups section
     21 ///     7. Tree section
     22 ///     8. Properties section
     23 /// 7. License section
     24 /// 8. Changelog section
     25 /// 9. Gallery section
     26 /// 10. Credits section
     27 ///
     28 /// ## About
     29 /// This is a minimal state immediate mode graphical user interface toolkit
     30 /// written in ANSI C and licensed under public domain. It was designed as a simple
     31 /// embeddable user interface for application and does not have any dependencies,
     32 /// a default renderbackend or OS window and input handling but instead provides a very modular
     33 /// library approach by using simple input state for input and draw
     34 /// commands describing primitive shapes as output. So instead of providing a
     35 /// layered library that tries to abstract over a number of platform and
     36 /// render backends it only focuses on the actual UI.
     37 ///
     38 /// ## Highlights
     39 /// - Graphical user interface toolkit
     40 /// - Single header library
     41 /// - Written in C89 (a.k.a. ANSI C or ISO C90)
     42 /// - Small codebase (~18kLOC)
     43 /// - Focus on portability, efficiency and simplicity
     44 /// - No dependencies (not even the standard library if not wanted)
     45 /// - Fully skinnable and customizable
     46 /// - Low memory footprint with total memory control if needed or wanted
     47 /// - UTF-8 support
     48 /// - No global or hidden state
     49 /// - Customizable library modules (you can compile and use only what you need)
     50 /// - Optional font baker and vertex buffer output
     51 /// - [Code available on github](https://github.com/Immediate-Mode-UI/Nuklear/)
     52 ///
     53 /// ## Features
     54 /// - Absolutely no platform dependent code
     55 /// - Memory management control ranging from/to
     56 ///     - Ease of use by allocating everything from standard library
     57 ///     - Control every byte of memory inside the library
     58 /// - Font handling control ranging from/to
     59 ///     - Use your own font implementation for everything
     60 ///     - Use this libraries internal font baking and handling API
     61 /// - Drawing output control ranging from/to
     62 ///     - Simple shapes for more high level APIs which already have drawing capabilities
     63 ///     - Hardware accessible anti-aliased vertex buffer output
     64 /// - Customizable colors and properties ranging from/to
     65 ///     - Simple changes to color by filling a simple color table
     66 ///     - Complete control with ability to use skinning to decorate widgets
     67 /// - Bendable UI library with widget ranging from/to
     68 ///     - Basic widgets like buttons, checkboxes, slider, ...
     69 ///     - Advanced widget like abstract comboboxes, contextual menus,...
     70 /// - Compile time configuration to only compile what you need
     71 ///     - Subset which can be used if you do not want to link or use the standard library
     72 /// - Can be easily modified to only update on user input instead of frame updates
     73 ///
     74 /// ## Usage
     75 /// This library is self contained in one single header file and can be used either
     76 /// in header only mode or in implementation mode. The header only mode is used
     77 /// by default when included and allows including this header in other headers
     78 /// and does not contain the actual implementation. <br /><br />
     79 ///
     80 /// The implementation mode requires to define  the preprocessor macro
     81 /// NK_IMPLEMENTATION in *one* .c/.cpp file before #including this file, e.g.:
     82 ///
     83 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C
     84 ///     #define NK_IMPLEMENTATION
     85 ///     #include "nuklear.h"
     86 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     87 ///
     88 /// Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
     89 /// below in header and implementation mode if you want to use additional functionality
     90 /// or need more control over the library.
     91 ///
     92 /// !!! WARNING
     93 ///     Every time nuklear is included define the same compiler flags. This very important not doing so could lead to compiler errors or even worse stack corruptions.
     94 ///
     95 /// ### Flags
     96 /// Flag                            | Description
     97 /// --------------------------------|------------------------------------------
     98 /// NK_PRIVATE                      | If defined declares all functions as static, so they can only be accessed inside the file that contains the implementation
     99 /// NK_INCLUDE_FIXED_TYPES          | If defined it will include header `<stdint.h>` for fixed sized types otherwise nuklear tries to select the correct type. If that fails it will throw a compiler error and you have to select the correct types yourself.
    100 /// NK_INCLUDE_DEFAULT_ALLOCATOR    | If defined it will include header `<stdlib.h>` and provide additional functions to use this library without caring for memory allocation control and therefore ease memory management.
    101 /// NK_INCLUDE_STANDARD_IO          | If defined it will include header `<stdio.h>` and provide additional functions depending on file loading.
    102 /// NK_INCLUDE_STANDARD_VARARGS     | If defined it will include header <stdarg.h> and provide additional functions depending on file loading.
    103 /// NK_INCLUDE_STANDARD_BOOL        | If defined it will include header `<stdbool.h>` for nk_bool otherwise nuklear defines nk_bool as int.
    104 /// NK_INCLUDE_VERTEX_BUFFER_OUTPUT | Defining this adds a vertex draw command list backend to this library, which allows you to convert queue commands into vertex draw commands. This is mainly if you need a hardware accessible format for OpenGL, DirectX, Vulkan, Metal,...
    105 /// NK_INCLUDE_FONT_BAKING          | Defining this adds `stb_truetype` and `stb_rect_pack` implementation to this library and provides font baking and rendering. If you already have font handling or do not want to use this font handler you don't have to define it.
    106 /// NK_INCLUDE_DEFAULT_FONT         | Defining this adds the default font: ProggyClean.ttf into this library which can be loaded into a font atlas and allows using this library without having a truetype font
    107 /// NK_INCLUDE_COMMAND_USERDATA     | Defining this adds a userdata pointer into each command. Can be useful for example if you want to provide custom shaders depending on the used widget. Can be combined with the style structures.
    108 /// NK_BUTTON_TRIGGER_ON_RELEASE    | Different platforms require button clicks occurring either on buttons being pressed (up to down) or released (down to up). By default this library will react on buttons being pressed, but if you define this it will only trigger if a button is released.
    109 /// NK_ZERO_COMMAND_MEMORY          | Defining this will zero out memory for each drawing command added to a drawing queue (inside nk_command_buffer_push). Zeroing command memory is very useful for fast checking (using memcmp) if command buffers are equal and avoid drawing frames when nothing on screen has changed since previous frame.
    110 /// NK_UINT_DRAW_INDEX              | Defining this will set the size of vertex index elements when using NK_VERTEX_BUFFER_OUTPUT to 32bit instead of the default of 16bit
    111 /// NK_KEYSTATE_BASED_INPUT         | Define this if your backend uses key state for each frame rather than key press/release events
    112 ///
    113 /// !!! WARNING
    114 ///     The following flags will pull in the standard C library:
    115 ///     - NK_INCLUDE_DEFAULT_ALLOCATOR
    116 ///     - NK_INCLUDE_STANDARD_IO
    117 ///     - NK_INCLUDE_STANDARD_VARARGS
    118 ///
    119 /// !!! WARNING
    120 ///     The following flags if defined need to be defined for both header and implementation:
    121 ///     - NK_INCLUDE_FIXED_TYPES
    122 ///     - NK_INCLUDE_DEFAULT_ALLOCATOR
    123 ///     - NK_INCLUDE_STANDARD_VARARGS
    124 ///     - NK_INCLUDE_STANDARD_BOOL
    125 ///     - NK_INCLUDE_VERTEX_BUFFER_OUTPUT
    126 ///     - NK_INCLUDE_FONT_BAKING
    127 ///     - NK_INCLUDE_DEFAULT_FONT
    128 ///     - NK_INCLUDE_STANDARD_VARARGS
    129 ///     - NK_INCLUDE_COMMAND_USERDATA
    130 ///     - NK_UINT_DRAW_INDEX
    131 ///
    132 /// ### Constants
    133 /// Define                          | Description
    134 /// --------------------------------|---------------------------------------
    135 /// NK_BUFFER_DEFAULT_INITIAL_SIZE  | Initial buffer size allocated by all buffers while using the default allocator functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't want to allocate the default 4k memory then redefine it.
    136 /// NK_MAX_NUMBER_BUFFER            | Maximum buffer size for the conversion buffer between float and string Under normal circumstances this should be more than sufficient.
    137 /// NK_INPUT_MAX                    | Defines the max number of bytes which can be added as text input in one frame. Under normal circumstances this should be more than sufficient.
    138 ///
    139 /// !!! WARNING
    140 ///     The following constants if defined need to be defined for both header and implementation:
    141 ///     - NK_MAX_NUMBER_BUFFER
    142 ///     - NK_BUFFER_DEFAULT_INITIAL_SIZE
    143 ///     - NK_INPUT_MAX
    144 ///
    145 /// ### Dependencies
    146 /// Function    | Description
    147 /// ------------|---------------------------------------------------------------
    148 /// NK_ASSERT   | If you don't define this, nuklear will use <assert.h> with assert().
    149 /// NK_MEMSET   | You can define this to 'memset' or your own memset implementation replacement. If not nuklear will use its own version.
    150 /// NK_MEMCPY   | You can define this to 'memcpy' or your own memcpy implementation replacement. If not nuklear will use its own version.
    151 /// NK_INV_SQRT | You can define this to your own inverse sqrt implementation replacement. If not nuklear will use its own slow and not highly accurate version.
    152 /// NK_SIN      | You can define this to 'sinf' or your own sine implementation replacement. If not nuklear will use its own approximation implementation.
    153 /// NK_COS      | You can define this to 'cosf' or your own cosine implementation replacement. If not nuklear will use its own approximation implementation.
    154 /// NK_STRTOD   | You can define this to `strtod` or your own string to double conversion implementation replacement. If not defined nuklear will use its own imprecise and possibly unsafe version (does not handle nan or infinity!).
    155 /// NK_DTOA     | You can define this to `dtoa` or your own double to string conversion implementation replacement. If not defined nuklear will use its own imprecise and possibly unsafe version (does not handle nan or infinity!).
    156 /// NK_VSNPRINTF| If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO` and want to be safe define this to `vsnprintf` on compilers supporting later versions of C or C++. By default nuklear will check for your stdlib version in C as well as compiler version in C++. if `vsnprintf` is available it will define it to `vsnprintf` directly. If not defined and if you have older versions of C or C++ it will be defined to `vsprintf` which is unsafe.
    157 ///
    158 /// !!! WARNING
    159 ///     The following dependencies will pull in the standard C library if not redefined:
    160 ///     - NK_ASSERT
    161 ///
    162 /// !!! WARNING
    163 ///     The following dependencies if defined need to be defined for both header and implementation:
    164 ///     - NK_ASSERT
    165 ///
    166 /// !!! WARNING
    167 ///     The following dependencies if defined need to be defined only for the implementation part:
    168 ///     - NK_MEMSET
    169 ///     - NK_MEMCPY
    170 ///     - NK_SQRT
    171 ///     - NK_SIN
    172 ///     - NK_COS
    173 ///     - NK_STRTOD
    174 ///     - NK_DTOA
    175 ///     - NK_VSNPRINTF
    176 ///
    177 /// ## Example
    178 ///
    179 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    180 /// // init gui state
    181 /// enum {EASY, HARD};
    182 /// static int op = EASY;
    183 /// static float value = 0.6f;
    184 /// static int i =  20;
    185 /// struct nk_context ctx;
    186 ///
    187 /// nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);
    188 /// if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220),
    189 ///     NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
    190 ///     // fixed widget pixel width
    191 ///     nk_layout_row_static(&ctx, 30, 80, 1);
    192 ///     if (nk_button_label(&ctx, "button")) {
    193 ///         // event handling
    194 ///     }
    195 ///
    196 ///     // fixed widget window ratio width
    197 ///     nk_layout_row_dynamic(&ctx, 30, 2);
    198 ///     if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY;
    199 ///     if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD;
    200 ///
    201 ///     // custom widget pixel width
    202 ///     nk_layout_row_begin(&ctx, NK_STATIC, 30, 2);
    203 ///     {
    204 ///         nk_layout_row_push(&ctx, 50);
    205 ///         nk_label(&ctx, "Volume:", NK_TEXT_LEFT);
    206 ///         nk_layout_row_push(&ctx, 110);
    207 ///         nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
    208 ///     }
    209 ///     nk_layout_row_end(&ctx);
    210 /// }
    211 /// nk_end(&ctx);
    212 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    213 ///
    214 /// ![](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png)
    215 ///
    216 /// ## API
    217 ///
    218 */
    219 #ifndef NK_SINGLE_FILE
    220   #define NK_SINGLE_FILE
    221 #endif
    222 
    223 #ifndef NK_NUKLEAR_H_
    224 #define NK_NUKLEAR_H_
    225 
    226 #ifdef __cplusplus
    227 extern "C" {
    228 #endif
    229 /*
    230  * ==============================================================
    231  *
    232  *                          CONSTANTS
    233  *
    234  * ===============================================================
    235  */
    236 #define NK_UNDEFINED (-1.0f)
    237 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
    238 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
    239 #ifndef NK_INPUT_MAX
    240   #define NK_INPUT_MAX 16
    241 #endif
    242 #ifndef NK_MAX_NUMBER_BUFFER
    243   #define NK_MAX_NUMBER_BUFFER 64
    244 #endif
    245 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
    246   #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
    247 #endif
    248 /*
    249  * ==============================================================
    250  *
    251  *                          HELPER
    252  *
    253  * ===============================================================
    254  */
    255 #ifndef NK_API
    256   #ifdef NK_PRIVATE
    257     #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
    258       #define NK_API static inline
    259     #elif defined(__cplusplus)
    260       #define NK_API static inline
    261     #else
    262       #define NK_API static
    263     #endif
    264   #else
    265     #define NK_API extern
    266   #endif
    267 #endif
    268 #ifndef NK_LIB
    269   #ifdef NK_SINGLE_FILE
    270     #define NK_LIB static
    271   #else
    272     #define NK_LIB extern
    273   #endif
    274 #endif
    275 
    276 #define NK_INTERN static
    277 #define NK_STORAGE static
    278 #define NK_GLOBAL static
    279 
    280 #define NK_FLAG(x) (1 << (x))
    281 #define NK_STRINGIFY(x) #x
    282 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
    283 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
    284 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
    285 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
    286 
    287 #ifdef _MSC_VER
    288   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
    289 #else
    290   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
    291 #endif
    292 
    293 #ifndef NK_STATIC_ASSERT
    294   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
    295 #endif
    296 
    297 #ifndef NK_FILE_LINE
    298 #ifdef _MSC_VER
    299   #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
    300 #else
    301   #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
    302 #endif
    303 #endif
    304 
    305 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
    306 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
    307 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
    308 
    309 #ifdef NK_INCLUDE_STANDARD_VARARGS
    310   #include <stdarg.h>
    311   #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
    312     #include <sal.h>
    313     #define NK_PRINTF_FORMAT_STRING _Printf_format_string_
    314   #else
    315     #define NK_PRINTF_FORMAT_STRING
    316   #endif
    317   #if defined(__GNUC__)
    318     #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1)))
    319     #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0)))
    320   #else
    321     #define NK_PRINTF_VARARG_FUNC(fmtargnumber)
    322     #define NK_PRINTF_VALIST_FUNC(fmtargnumber)
    323   #endif
    324 #endif
    325 
    326 /*
    327  * ===============================================================
    328  *
    329  *                          BASIC
    330  *
    331  * ===============================================================
    332  */
    333 #ifdef NK_INCLUDE_FIXED_TYPES
    334  #include <stdint.h>
    335  #define NK_INT8 int8_t
    336  #define NK_UINT8 uint8_t
    337  #define NK_INT16 int16_t
    338  #define NK_UINT16 uint16_t
    339  #define NK_INT32 int32_t
    340  #define NK_UINT32 uint32_t
    341  #define NK_SIZE_TYPE uintptr_t
    342  #define NK_POINTER_TYPE uintptr_t
    343 #else
    344   #ifndef NK_INT8
    345     #define NK_INT8 signed char
    346   #endif
    347   #ifndef NK_UINT8
    348     #define NK_UINT8 unsigned char
    349   #endif
    350   #ifndef NK_INT16
    351     #define NK_INT16 signed short
    352   #endif
    353   #ifndef NK_UINT16
    354     #define NK_UINT16 unsigned short
    355   #endif
    356   #ifndef NK_INT32
    357     #if defined(_MSC_VER)
    358       #define NK_INT32 __int32
    359     #else
    360       #define NK_INT32 signed int
    361     #endif
    362   #endif
    363   #ifndef NK_UINT32
    364     #if defined(_MSC_VER)
    365       #define NK_UINT32 unsigned __int32
    366     #else
    367       #define NK_UINT32 unsigned int
    368     #endif
    369   #endif
    370   #ifndef NK_SIZE_TYPE
    371     #if defined(_WIN64) && defined(_MSC_VER)
    372       #define NK_SIZE_TYPE unsigned __int64
    373     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
    374       #define NK_SIZE_TYPE unsigned __int32
    375     #elif defined(__GNUC__) || defined(__clang__)
    376       #if defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__)
    377         #define NK_SIZE_TYPE unsigned long
    378       #else
    379         #define NK_SIZE_TYPE unsigned int
    380       #endif
    381     #else
    382       #define NK_SIZE_TYPE unsigned long
    383     #endif
    384   #endif
    385   #ifndef NK_POINTER_TYPE
    386     #if defined(_WIN64) && defined(_MSC_VER)
    387       #define NK_POINTER_TYPE unsigned __int64
    388     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
    389       #define NK_POINTER_TYPE unsigned __int32
    390     #elif defined(__GNUC__) || defined(__clang__)
    391       #if defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__)
    392         #define NK_POINTER_TYPE unsigned long
    393       #else
    394         #define NK_POINTER_TYPE unsigned int
    395       #endif
    396     #else
    397       #define NK_POINTER_TYPE unsigned long
    398     #endif
    399   #endif
    400 #endif
    401 
    402 #ifndef NK_BOOL
    403   #ifdef NK_INCLUDE_STANDARD_BOOL
    404     #include <stdbool.h>
    405     #define NK_BOOL bool
    406   #else
    407     #define NK_BOOL int /* could be char, use int for drop-in replacement backwards compatibility */
    408   #endif
    409 #endif
    410 
    411 typedef NK_INT8 nk_char;
    412 typedef NK_UINT8 nk_uchar;
    413 typedef NK_UINT8 nk_byte;
    414 typedef NK_INT16 nk_short;
    415 typedef NK_UINT16 nk_ushort;
    416 typedef NK_INT32 nk_int;
    417 typedef NK_UINT32 nk_uint;
    418 typedef NK_SIZE_TYPE nk_size;
    419 typedef NK_POINTER_TYPE nk_ptr;
    420 typedef NK_BOOL nk_bool;
    421 
    422 typedef nk_uint nk_hash;
    423 typedef nk_uint nk_flags;
    424 typedef nk_uint nk_rune;
    425 
    426 /* Make sure correct type size:
    427  * This will fire with a negative subscript error if the type sizes
    428  * are set incorrectly by the compiler, and compile out if not */
    429 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
    430 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
    431 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
    432 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
    433 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
    434 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
    435 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
    436 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
    437 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
    438 #ifdef NK_INCLUDE_STANDARD_BOOL
    439 NK_STATIC_ASSERT(sizeof(nk_bool) == sizeof(bool));
    440 #else
    441 NK_STATIC_ASSERT(sizeof(nk_bool) >= 2);
    442 #endif
    443 
    444 /* ============================================================================
    445  *
    446  *                                  API
    447  *
    448  * =========================================================================== */
    449 struct nk_buffer;
    450 struct nk_allocator;
    451 struct nk_command_buffer;
    452 struct nk_draw_command;
    453 struct nk_convert_config;
    454 struct nk_style_item;
    455 struct nk_text_edit;
    456 struct nk_draw_list;
    457 struct nk_user_font;
    458 struct nk_panel;
    459 struct nk_context;
    460 struct nk_draw_vertex_layout_element;
    461 struct nk_style_button;
    462 struct nk_style_toggle;
    463 struct nk_style_selectable;
    464 struct nk_style_slide;
    465 struct nk_style_progress;
    466 struct nk_style_scrollbar;
    467 struct nk_style_edit;
    468 struct nk_style_property;
    469 struct nk_style_chart;
    470 struct nk_style_combo;
    471 struct nk_style_tab;
    472 struct nk_style_window_header;
    473 struct nk_style_window;
    474 
    475 enum {nk_false, nk_true};
    476 struct nk_color {nk_byte r,g,b,a;};
    477 struct nk_colorf {float r,g,b,a;};
    478 struct nk_vec2 {float x,y;};
    479 struct nk_vec2i {short x, y;};
    480 struct nk_rect {float x,y,w,h;};
    481 struct nk_recti {short x,y,w,h;};
    482 typedef char nk_glyph[NK_UTF_SIZE];
    483 typedef union {void *ptr; int id;} nk_handle;
    484 struct nk_image {nk_handle handle; nk_ushort w, h; nk_ushort region[4];};
    485 struct nk_nine_slice {struct nk_image img; nk_ushort l, t, r, b;};
    486 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
    487 struct nk_scroll {nk_uint x, y;};
    488 
    489 enum nk_heading         {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
    490 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
    491 enum nk_modify          {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
    492 enum nk_orientation     {NK_VERTICAL, NK_HORIZONTAL};
    493 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true};
    494 enum nk_show_states     {NK_HIDDEN = nk_false, NK_SHOWN = nk_true};
    495 enum nk_chart_type      {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX};
    496 enum nk_chart_event     {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02};
    497 enum nk_color_format    {NK_RGB, NK_RGBA};
    498 enum nk_popup_type      {NK_POPUP_STATIC, NK_POPUP_DYNAMIC};
    499 enum nk_layout_format   {NK_DYNAMIC, NK_STATIC};
    500 enum nk_tree_type       {NK_TREE_NODE, NK_TREE_TAB};
    501 
    502 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
    503 typedef void (*nk_plugin_free)(nk_handle, void *old);
    504 typedef nk_bool(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
    505 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
    506 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
    507 
    508 struct nk_allocator {
    509     nk_handle userdata;
    510     nk_plugin_alloc alloc;
    511     nk_plugin_free free;
    512 };
    513 enum nk_symbol_type {
    514     NK_SYMBOL_NONE,
    515     NK_SYMBOL_X,
    516     NK_SYMBOL_UNDERSCORE,
    517     NK_SYMBOL_CIRCLE_SOLID,
    518     NK_SYMBOL_CIRCLE_OUTLINE,
    519     NK_SYMBOL_RECT_SOLID,
    520     NK_SYMBOL_RECT_OUTLINE,
    521     NK_SYMBOL_TRIANGLE_UP,
    522     NK_SYMBOL_TRIANGLE_DOWN,
    523     NK_SYMBOL_TRIANGLE_LEFT,
    524     NK_SYMBOL_TRIANGLE_RIGHT,
    525     NK_SYMBOL_PLUS,
    526     NK_SYMBOL_MINUS,
    527     NK_SYMBOL_MAX
    528 };
    529 /* =============================================================================
    530  *
    531  *                                  CONTEXT
    532  *
    533  * =============================================================================*/
    534 /*/// ### Context
    535 /// Contexts are the main entry point and the majestro of nuklear and contain all required state.
    536 /// They are used for window, memory, input, style, stack, commands and time management and need
    537 /// to be passed into all nuklear GUI specific functions.
    538 ///
    539 /// #### Usage
    540 /// To use a context it first has to be initialized which can be achieved by calling
    541 /// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
    542 /// Each takes in a font handle and a specific way of handling memory. Memory control
    543 /// hereby ranges from standard library to just specifying a fixed sized block of memory
    544 /// which nuklear has to manage itself from.
    545 ///
    546 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    547 /// struct nk_context ctx;
    548 /// nk_init_xxx(&ctx, ...);
    549 /// while (1) {
    550 ///     // [...]
    551 ///     nk_clear(&ctx);
    552 /// }
    553 /// nk_free(&ctx);
    554 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    555 ///
    556 /// #### Reference
    557 /// Function            | Description
    558 /// --------------------|-------------------------------------------------------
    559 /// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free)
    560 /// __nk_init_fixed__   | Initializes context from single fixed size memory block
    561 /// __nk_init__         | Initializes context with memory allocator callbacks for alloc and free
    562 /// __nk_init_custom__  | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
    563 /// __nk_clear__        | Called at the end of the frame to reset and prepare the context for the next frame
    564 /// __nk_free__         | Shutdown and free all memory allocated inside the context
    565 /// __nk_set_user_data__| Utility function to pass user data to draw command
    566  */
    567 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
    568 /*/// #### nk_init_default
    569 /// Initializes a `nk_context` struct with a default standard library allocator.
    570 /// Should be used if you don't want to be bothered with memory management in nuklear.
    571 ///
    572 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    573 /// nk_bool nk_init_default(struct nk_context *ctx, const struct nk_user_font *font);
    574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    575 ///
    576 /// Parameter   | Description
    577 /// ------------|---------------------------------------------------------------
    578 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
    579 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
    580 ///
    581 /// Returns either `false(0)` on failure or `true(1)` on success.
    582 ///
    583 */
    584 NK_API nk_bool nk_init_default(struct nk_context*, const struct nk_user_font*);
    585 #endif
    586 /*/// #### nk_init_fixed
    587 /// Initializes a `nk_context` struct from single fixed size memory block
    588 /// Should be used if you want complete control over nuklear's memory management.
    589 /// Especially recommended for system with little memory or systems with virtual memory.
    590 /// For the later case you can just allocate for example 16MB of virtual memory
    591 /// and only the required amount of memory will actually be committed.
    592 ///
    593 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    594 /// nk_bool nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font);
    595 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    596 ///
    597 /// !!! Warning
    598 ///     make sure the passed memory block is aligned correctly for `nk_draw_commands`.
    599 ///
    600 /// Parameter   | Description
    601 /// ------------|--------------------------------------------------------------
    602 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
    603 /// __memory__  | Must point to a previously allocated memory block
    604 /// __size__    | Must contain the total size of __memory__
    605 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
    606 ///
    607 /// Returns either `false(0)` on failure or `true(1)` on success.
    608 */
    609 NK_API nk_bool nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
    610 /*/// #### nk_init
    611 /// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
    612 /// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
    613 /// interface to nuklear. Can be useful for cases like monitoring memory consumption.
    614 ///
    615 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    616 /// nk_bool nk_init(struct nk_context *ctx, struct nk_allocator *alloc, const struct nk_user_font *font);
    617 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    618 ///
    619 /// Parameter   | Description
    620 /// ------------|---------------------------------------------------------------
    621 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
    622 /// __alloc__   | Must point to a previously allocated memory allocator
    623 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
    624 ///
    625 /// Returns either `false(0)` on failure or `true(1)` on success.
    626 */
    627 NK_API nk_bool nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
    628 /*/// #### nk_init_custom
    629 /// Initializes a `nk_context` struct from two different either fixed or growing
    630 /// buffers. The first buffer is for allocating draw commands while the second buffer is
    631 /// used for allocating windows, panels and state tables.
    632 ///
    633 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    634 /// nk_bool nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font);
    635 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    636 ///
    637 /// Parameter   | Description
    638 /// ------------|---------------------------------------------------------------
    639 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
    640 /// __cmds__    | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
    641 /// __pool__    | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
    642 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
    643 ///
    644 /// Returns either `false(0)` on failure or `true(1)` on success.
    645 */
    646 NK_API nk_bool nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
    647 /*/// #### nk_clear
    648 /// Resets the context state at the end of the frame. This includes mostly
    649 /// garbage collector tasks like removing windows or table not called and therefore
    650 /// used anymore.
    651 ///
    652 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    653 /// void nk_clear(struct nk_context *ctx);
    654 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    655 ///
    656 /// Parameter   | Description
    657 /// ------------|-----------------------------------------------------------
    658 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    659 */
    660 NK_API void nk_clear(struct nk_context*);
    661 /*/// #### nk_free
    662 /// Frees all memory allocated by nuklear. Not needed if context was
    663 /// initialized with `nk_init_fixed`.
    664 ///
    665 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    666 /// void nk_free(struct nk_context *ctx);
    667 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    668 ///
    669 /// Parameter   | Description
    670 /// ------------|-----------------------------------------------------------
    671 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    672 */
    673 NK_API void nk_free(struct nk_context*);
    674 #ifdef NK_INCLUDE_COMMAND_USERDATA
    675 /*/// #### nk_set_user_data
    676 /// Sets the currently passed userdata passed down into each draw command.
    677 ///
    678 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    679 /// void nk_set_user_data(struct nk_context *ctx, nk_handle data);
    680 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    681 ///
    682 /// Parameter   | Description
    683 /// ------------|--------------------------------------------------------------
    684 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    685 /// __data__    | Handle with either pointer or index to be passed into every draw commands
    686 */
    687 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
    688 #endif
    689 /* =============================================================================
    690  *
    691  *                                  INPUT
    692  *
    693  * =============================================================================*/
    694 /*/// ### Input
    695 /// The input API is responsible for holding the current input state composed of
    696 /// mouse, key and text input states.
    697 /// It is worth noting that no direct OS or window handling is done in nuklear.
    698 /// Instead all input state has to be provided by platform specific code. This on one hand
    699 /// expects more work from the user and complicates usage but on the other hand
    700 /// provides simple abstraction over a big number of platforms, libraries and other
    701 /// already provided functionality.
    702 ///
    703 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    704 /// nk_input_begin(&ctx);
    705 /// while (GetEvent(&evt)) {
    706 ///     if (evt.type == MOUSE_MOVE)
    707 ///         nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
    708 ///     else if (evt.type == [...]) {
    709 ///         // [...]
    710 ///     }
    711 /// } nk_input_end(&ctx);
    712 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    713 ///
    714 /// #### Usage
    715 /// Input state needs to be provided to nuklear by first calling `nk_input_begin`
    716 /// which resets internal state like delta mouse position and button transitions.
    717 /// After `nk_input_begin` all current input state needs to be provided. This includes
    718 /// mouse motion, button and key pressed and released, text input and scrolling.
    719 /// Both event- or state-based input handling are supported by this API
    720 /// and should work without problems. Finally after all input state has been
    721 /// mirrored `nk_input_end` needs to be called to finish input process.
    722 ///
    723 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    724 /// struct nk_context ctx;
    725 /// nk_init_xxx(&ctx, ...);
    726 /// while (1) {
    727 ///     Event evt;
    728 ///     nk_input_begin(&ctx);
    729 ///     while (GetEvent(&evt)) {
    730 ///         if (evt.type == MOUSE_MOVE)
    731 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
    732 ///         else if (evt.type == [...]) {
    733 ///             // [...]
    734 ///         }
    735 ///     }
    736 ///     nk_input_end(&ctx);
    737 ///     // [...]
    738 ///     nk_clear(&ctx);
    739 /// } nk_free(&ctx);
    740 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    741 ///
    742 /// #### Reference
    743 /// Function            | Description
    744 /// --------------------|-------------------------------------------------------
    745 /// __nk_input_begin__  | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
    746 /// __nk_input_motion__ | Mirrors mouse cursor position
    747 /// __nk_input_key__    | Mirrors key state with either pressed or released
    748 /// __nk_input_button__ | Mirrors mouse button state with either pressed or released
    749 /// __nk_input_scroll__ | Mirrors mouse scroll values
    750 /// __nk_input_char__   | Adds a single ASCII text character into an internal text buffer
    751 /// __nk_input_glyph__  | Adds a single multi-byte UTF-8 character into an internal text buffer
    752 /// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer
    753 /// __nk_input_end__    | Ends the input mirroring process by calculating state changes. Don't call any `nk_input_xxx` function referenced above after this call
    754 */
    755 enum nk_keys {
    756     NK_KEY_NONE,
    757     NK_KEY_SHIFT,
    758     NK_KEY_CTRL,
    759     NK_KEY_DEL,
    760     NK_KEY_ENTER,
    761     NK_KEY_TAB,
    762     NK_KEY_BACKSPACE,
    763     NK_KEY_COPY,
    764     NK_KEY_CUT,
    765     NK_KEY_PASTE,
    766     NK_KEY_UP,
    767     NK_KEY_DOWN,
    768     NK_KEY_LEFT,
    769     NK_KEY_RIGHT,
    770     /* Shortcuts: text field */
    771     NK_KEY_TEXT_INSERT_MODE,
    772     NK_KEY_TEXT_REPLACE_MODE,
    773     NK_KEY_TEXT_RESET_MODE,
    774     NK_KEY_TEXT_LINE_START,
    775     NK_KEY_TEXT_LINE_END,
    776     NK_KEY_TEXT_START,
    777     NK_KEY_TEXT_END,
    778     NK_KEY_TEXT_UNDO,
    779     NK_KEY_TEXT_REDO,
    780     NK_KEY_TEXT_SELECT_ALL,
    781     NK_KEY_TEXT_WORD_LEFT,
    782     NK_KEY_TEXT_WORD_RIGHT,
    783     /* Shortcuts: scrollbar */
    784     NK_KEY_SCROLL_START,
    785     NK_KEY_SCROLL_END,
    786     NK_KEY_SCROLL_DOWN,
    787     NK_KEY_SCROLL_UP,
    788     NK_KEY_MAX
    789 };
    790 enum nk_buttons {
    791     NK_BUTTON_LEFT,
    792     NK_BUTTON_MIDDLE,
    793     NK_BUTTON_RIGHT,
    794     NK_BUTTON_DOUBLE,
    795     NK_BUTTON_MAX
    796 };
    797 /*/// #### nk_input_begin
    798 /// Begins the input mirroring process by resetting text, scroll
    799 /// mouse, previous mouse position and movement as well as key state transitions,
    800 ///
    801 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    802 /// void nk_input_begin(struct nk_context*);
    803 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    804 ///
    805 /// Parameter   | Description
    806 /// ------------|-----------------------------------------------------------
    807 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    808 */
    809 NK_API void nk_input_begin(struct nk_context*);
    810 /*/// #### nk_input_motion
    811 /// Mirrors current mouse position to nuklear
    812 ///
    813 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    814 /// void nk_input_motion(struct nk_context *ctx, int x, int y);
    815 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    816 ///
    817 /// Parameter   | Description
    818 /// ------------|-----------------------------------------------------------
    819 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    820 /// __x__       | Must hold an integer describing the current mouse cursor x-position
    821 /// __y__       | Must hold an integer describing the current mouse cursor y-position
    822 */
    823 NK_API void nk_input_motion(struct nk_context*, int x, int y);
    824 /*/// #### nk_input_key
    825 /// Mirrors the state of a specific key to nuklear
    826 ///
    827 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    828 /// void nk_input_key(struct nk_context*, enum nk_keys key, nk_bool down);
    829 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    830 ///
    831 /// Parameter   | Description
    832 /// ------------|-----------------------------------------------------------
    833 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    834 /// __key__     | Must be any value specified in enum `nk_keys` that needs to be mirrored
    835 /// __down__    | Must be 0 for key is up and 1 for key is down
    836 */
    837 NK_API void nk_input_key(struct nk_context*, enum nk_keys, nk_bool down);
    838 /*/// #### nk_input_button
    839 /// Mirrors the state of a specific mouse button to nuklear
    840 ///
    841 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    842 /// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, nk_bool down);
    843 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    844 ///
    845 /// Parameter   | Description
    846 /// ------------|-----------------------------------------------------------
    847 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    848 /// __btn__     | Must be any value specified in enum `nk_buttons` that needs to be mirrored
    849 /// __x__       | Must contain an integer describing mouse cursor x-position on click up/down
    850 /// __y__       | Must contain an integer describing mouse cursor y-position on click up/down
    851 /// __down__    | Must be 0 for key is up and 1 for key is down
    852 */
    853 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, nk_bool down);
    854 /*/// #### nk_input_scroll
    855 /// Copies the last mouse scroll value to nuklear. Is generally
    856 /// a scroll value. So does not have to come from mouse and could also originate
    857 /// TODO finish this sentence
    858 ///
    859 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    860 /// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val);
    861 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    862 ///
    863 /// Parameter   | Description
    864 /// ------------|-----------------------------------------------------------
    865 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    866 /// __val__     | vector with both X- as well as Y-scroll value
    867 */
    868 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
    869 /*/// #### nk_input_char
    870 /// Copies a single ASCII character into an internal text buffer
    871 /// This is basically a helper function to quickly push ASCII characters into
    872 /// nuklear.
    873 ///
    874 /// !!! Note
    875 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
    876 ///
    877 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    878 /// void nk_input_char(struct nk_context *ctx, char c);
    879 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    880 ///
    881 /// Parameter   | Description
    882 /// ------------|-----------------------------------------------------------
    883 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    884 /// __c__       | Must be a single ASCII character preferable one that can be printed
    885 */
    886 NK_API void nk_input_char(struct nk_context*, char);
    887 /*/// #### nk_input_glyph
    888 /// Converts an encoded unicode rune into UTF-8 and copies the result into an
    889 /// internal text buffer.
    890 ///
    891 /// !!! Note
    892 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
    893 ///
    894 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    895 /// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g);
    896 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    897 ///
    898 /// Parameter   | Description
    899 /// ------------|-----------------------------------------------------------
    900 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    901 /// __g__       | UTF-32 unicode codepoint
    902 */
    903 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
    904 /*/// #### nk_input_unicode
    905 /// Converts a unicode rune into UTF-8 and copies the result
    906 /// into an internal text buffer.
    907 /// !!! Note
    908 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
    909 ///
    910 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    911 /// void nk_input_unicode(struct nk_context*, nk_rune rune);
    912 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    913 ///
    914 /// Parameter   | Description
    915 /// ------------|-----------------------------------------------------------
    916 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    917 /// __rune__    | UTF-32 unicode codepoint
    918 */
    919 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
    920 /*/// #### nk_input_end
    921 /// End the input mirroring process by resetting mouse grabbing
    922 /// state to ensure the mouse cursor is not grabbed indefinitely.
    923 ///
    924 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    925 /// void nk_input_end(struct nk_context *ctx);
    926 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    927 ///
    928 /// Parameter   | Description
    929 /// ------------|-----------------------------------------------------------
    930 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    931 */
    932 NK_API void nk_input_end(struct nk_context*);
    933 /* =============================================================================
    934  *
    935  *                                  DRAWING
    936  *
    937  * =============================================================================*/
    938 /*/// ### Drawing
    939 /// This library was designed to be render backend agnostic so it does
    940 /// not draw anything to screen directly. Instead all drawn shapes, widgets
    941 /// are made of, are buffered into memory and make up a command queue.
    942 /// Each frame therefore fills the command buffer with draw commands
    943 /// that then need to be executed by the user and his own render backend.
    944 /// After that the command buffer needs to be cleared and a new frame can be
    945 /// started. It is probably important to note that the command buffer is the main
    946 /// drawing API and the optional vertex buffer API only takes this format and
    947 /// converts it into a hardware accessible format.
    948 ///
    949 /// #### Usage
    950 /// To draw all draw commands accumulated over a frame you need your own render
    951 /// backend able to draw a number of 2D primitives. This includes at least
    952 /// filled and stroked rectangles, circles, text, lines, triangles and scissors.
    953 /// As soon as this criterion is met you can iterate over each draw command
    954 /// and execute each draw command in a interpreter like fashion:
    955 ///
    956 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    957 /// const struct nk_command *cmd = 0;
    958 /// nk_foreach(cmd, &ctx) {
    959 ///     switch (cmd->type) {
    960 ///     case NK_COMMAND_LINE:
    961 ///         your_draw_line_function(...)
    962 ///         break;
    963 ///     case NK_COMMAND_RECT
    964 ///         your_draw_rect_function(...)
    965 ///         break;
    966 ///     case //...:
    967 ///         //[...]
    968 ///     }
    969 /// }
    970 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    971 ///
    972 /// In program flow context draw commands need to be executed after input has been
    973 /// gathered and the complete UI with windows and their contained widgets have
    974 /// been executed and before calling `nk_clear` which frees all previously
    975 /// allocated draw commands.
    976 ///
    977 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    978 /// struct nk_context ctx;
    979 /// nk_init_xxx(&ctx, ...);
    980 /// while (1) {
    981 ///     Event evt;
    982 ///     nk_input_begin(&ctx);
    983 ///     while (GetEvent(&evt)) {
    984 ///         if (evt.type == MOUSE_MOVE)
    985 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
    986 ///         else if (evt.type == [...]) {
    987 ///             [...]
    988 ///         }
    989 ///     }
    990 ///     nk_input_end(&ctx);
    991 ///     //
    992 ///     // [...]
    993 ///     //
    994 ///     const struct nk_command *cmd = 0;
    995 ///     nk_foreach(cmd, &ctx) {
    996 ///     switch (cmd->type) {
    997 ///     case NK_COMMAND_LINE:
    998 ///         your_draw_line_function(...)
    999 ///         break;
   1000 ///     case NK_COMMAND_RECT
   1001 ///         your_draw_rect_function(...)
   1002 ///         break;
   1003 ///     case ...:
   1004 ///         // [...]
   1005 ///     }
   1006 ///     nk_clear(&ctx);
   1007 /// }
   1008 /// nk_free(&ctx);
   1009 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1010 ///
   1011 /// You probably noticed that you have to draw all of the UI each frame which is
   1012 /// quite wasteful. While the actual UI updating loop is quite fast rendering
   1013 /// without actually needing it is not. So there are multiple things you could do.
   1014 ///
   1015 /// First is only update on input. This of course is only an option if your
   1016 /// application only depends on the UI and does not require any outside calculations.
   1017 /// If you actually only update on input make sure to update the UI two times each
   1018 /// frame and call `nk_clear` directly after the first pass and only draw in
   1019 /// the second pass. In addition it is recommended to also add additional timers
   1020 /// to make sure the UI is not drawn more than a fixed number of frames per second.
   1021 ///
   1022 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1023 /// struct nk_context ctx;
   1024 /// nk_init_xxx(&ctx, ...);
   1025 /// while (1) {
   1026 ///     // [...wait for input ]
   1027 ///     // [...do two UI passes ...]
   1028 ///     do_ui(...)
   1029 ///     nk_clear(&ctx);
   1030 ///     do_ui(...)
   1031 ///     //
   1032 ///     // draw
   1033 ///     const struct nk_command *cmd = 0;
   1034 ///     nk_foreach(cmd, &ctx) {
   1035 ///     switch (cmd->type) {
   1036 ///     case NK_COMMAND_LINE:
   1037 ///         your_draw_line_function(...)
   1038 ///         break;
   1039 ///     case NK_COMMAND_RECT
   1040 ///         your_draw_rect_function(...)
   1041 ///         break;
   1042 ///     case ...:
   1043 ///         //[...]
   1044 ///     }
   1045 ///     nk_clear(&ctx);
   1046 /// }
   1047 /// nk_free(&ctx);
   1048 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1049 ///
   1050 /// The second probably more applicable trick is to only draw if anything changed.
   1051 /// It is not really useful for applications with continuous draw loop but
   1052 /// quite useful for desktop applications. To actually get nuklear to only
   1053 /// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
   1054 /// allocate a memory buffer that will store each unique drawing output.
   1055 /// After each frame you compare the draw command memory inside the library
   1056 /// with your allocated buffer by memcmp. If memcmp detects differences
   1057 /// you have to copy the command buffer into the allocated buffer
   1058 /// and then draw like usual (this example uses fixed memory but you could
   1059 /// use dynamically allocated memory).
   1060 ///
   1061 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1062 /// //[... other defines ...]
   1063 /// #define NK_ZERO_COMMAND_MEMORY
   1064 /// #include "nuklear.h"
   1065 /// //
   1066 /// // setup context
   1067 /// struct nk_context ctx;
   1068 /// void *last = calloc(1,64*1024);
   1069 /// void *buf = calloc(1,64*1024);
   1070 /// nk_init_fixed(&ctx, buf, 64*1024);
   1071 /// //
   1072 /// // loop
   1073 /// while (1) {
   1074 ///     // [...input...]
   1075 ///     // [...ui...]
   1076 ///     void *cmds = nk_buffer_memory(&ctx.memory);
   1077 ///     if (memcmp(cmds, last, ctx.memory.allocated)) {
   1078 ///         memcpy(last,cmds,ctx.memory.allocated);
   1079 ///         const struct nk_command *cmd = 0;
   1080 ///         nk_foreach(cmd, &ctx) {
   1081 ///             switch (cmd->type) {
   1082 ///             case NK_COMMAND_LINE:
   1083 ///                 your_draw_line_function(...)
   1084 ///                 break;
   1085 ///             case NK_COMMAND_RECT
   1086 ///                 your_draw_rect_function(...)
   1087 ///                 break;
   1088 ///             case ...:
   1089 ///                 // [...]
   1090 ///             }
   1091 ///         }
   1092 ///     }
   1093 ///     nk_clear(&ctx);
   1094 /// }
   1095 /// nk_free(&ctx);
   1096 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1097 ///
   1098 /// Finally while using draw commands makes sense for higher abstracted platforms like
   1099 /// X11 and Win32 or drawing libraries it is often desirable to use graphics
   1100 /// hardware directly. Therefore it is possible to just define
   1101 /// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
   1102 /// To access the vertex output you first have to convert all draw commands into
   1103 /// vertexes by calling `nk_convert` which takes in your preferred vertex format.
   1104 /// After successfully converting all draw commands just iterate over and execute all
   1105 /// vertex draw commands:
   1106 ///
   1107 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1108 /// // fill configuration
   1109 /// struct your_vertex
   1110 /// {
   1111 ///     float pos[2]; // important to keep it to 2 floats
   1112 ///     float uv[2];
   1113 ///     unsigned char col[4];
   1114 /// };
   1115 /// struct nk_convert_config cfg = {};
   1116 /// static const struct nk_draw_vertex_layout_element vertex_layout[] = {
   1117 ///     {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
   1118 ///     {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
   1119 ///     {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
   1120 ///     {NK_VERTEX_LAYOUT_END}
   1121 /// };
   1122 /// cfg.shape_AA = NK_ANTI_ALIASING_ON;
   1123 /// cfg.line_AA = NK_ANTI_ALIASING_ON;
   1124 /// cfg.vertex_layout = vertex_layout;
   1125 /// cfg.vertex_size = sizeof(struct your_vertex);
   1126 /// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
   1127 /// cfg.circle_segment_count = 22;
   1128 /// cfg.curve_segment_count = 22;
   1129 /// cfg.arc_segment_count = 22;
   1130 /// cfg.global_alpha = 1.0f;
   1131 /// cfg.tex_null = dev->tex_null;
   1132 /// //
   1133 /// // setup buffers and convert
   1134 /// struct nk_buffer cmds, verts, idx;
   1135 /// nk_buffer_init_default(&cmds);
   1136 /// nk_buffer_init_default(&verts);
   1137 /// nk_buffer_init_default(&idx);
   1138 /// nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
   1139 /// //
   1140 /// // draw
   1141 /// nk_draw_foreach(cmd, &ctx, &cmds) {
   1142 /// if (!cmd->elem_count) continue;
   1143 ///     //[...]
   1144 /// }
   1145 /// nk_buffer_free(&cms);
   1146 /// nk_buffer_free(&verts);
   1147 /// nk_buffer_free(&idx);
   1148 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1149 ///
   1150 /// #### Reference
   1151 /// Function            | Description
   1152 /// --------------------|-------------------------------------------------------
   1153 /// __nk__begin__       | Returns the first draw command in the context draw command list to be drawn
   1154 /// __nk__next__        | Increments the draw command iterator to the next command inside the context draw command list
   1155 /// __nk_foreach__      | Iterates over each draw command inside the context draw command list
   1156 /// __nk_convert__      | Converts from the abstract draw commands list into a hardware accessible vertex format
   1157 /// __nk_draw_begin__   | Returns the first vertex command in the context vertex draw list to be executed
   1158 /// __nk__draw_next__   | Increments the vertex command iterator to the next command inside the context vertex command list
   1159 /// __nk__draw_end__    | Returns the end of the vertex draw list
   1160 /// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list
   1161 */
   1162 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON};
   1163 enum nk_convert_result {
   1164     NK_CONVERT_SUCCESS = 0,
   1165     NK_CONVERT_INVALID_PARAM = 1,
   1166     NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1),
   1167     NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2),
   1168     NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3)
   1169 };
   1170 struct nk_draw_null_texture {
   1171     nk_handle texture; /* texture handle to a texture with a white pixel */
   1172     struct nk_vec2 uv; /* coordinates to a white pixel in the texture  */
   1173 };
   1174 struct nk_convert_config {
   1175     float global_alpha; /* global alpha value */
   1176     enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
   1177     enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
   1178     unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
   1179     unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
   1180     unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
   1181     struct nk_draw_null_texture tex_null; /* handle to texture with a white pixel for shape drawing */
   1182     const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
   1183     nk_size vertex_size; /* sizeof one vertex for vertex packing */
   1184     nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
   1185 };
   1186 /*/// #### nk__begin
   1187 /// Returns a draw command list iterator to iterate all draw
   1188 /// commands accumulated over one frame.
   1189 ///
   1190 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1191 /// const struct nk_command* nk__begin(struct nk_context*);
   1192 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1193 ///
   1194 /// Parameter   | Description
   1195 /// ------------|-----------------------------------------------------------
   1196 /// __ctx__     | must point to an previously initialized `nk_context` struct at the end of a frame
   1197 ///
   1198 /// Returns draw command pointer pointing to the first command inside the draw command list
   1199 */
   1200 NK_API const struct nk_command* nk__begin(struct nk_context*);
   1201 /*/// #### nk__next
   1202 /// Returns draw command pointer pointing to the next command inside the draw command list
   1203 ///
   1204 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1205 /// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
   1206 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1207 ///
   1208 /// Parameter   | Description
   1209 /// ------------|-----------------------------------------------------------
   1210 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1211 /// __cmd__     | Must point to an previously a draw command either returned by `nk__begin` or `nk__next`
   1212 ///
   1213 /// Returns draw command pointer pointing to the next command inside the draw command list
   1214 */
   1215 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
   1216 /*/// #### nk_foreach
   1217 /// Iterates over each draw command inside the context draw command list
   1218 ///
   1219 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1220 /// #define nk_foreach(c, ctx)
   1221 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1222 ///
   1223 /// Parameter   | Description
   1224 /// ------------|-----------------------------------------------------------
   1225 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1226 /// __cmd__     | Command pointer initialized to NULL
   1227 ///
   1228 /// Iterates over each draw command inside the context draw command list
   1229 */
   1230 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
   1231 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   1232 /*/// #### nk_convert
   1233 /// Converts all internal draw commands into vertex draw commands and fills
   1234 /// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format
   1235 /// as well as some other configuration values have to be configured by filling out a
   1236 /// `nk_convert_config` struct.
   1237 ///
   1238 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1239 /// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
   1240 ///     struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
   1241 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1242 ///
   1243 /// Parameter   | Description
   1244 /// ------------|-----------------------------------------------------------
   1245 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1246 /// __cmds__    | Must point to a previously initialized buffer to hold converted vertex draw commands
   1247 /// __vertices__| Must point to a previously initialized buffer to hold all produced vertices
   1248 /// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices
   1249 /// __config__  | Must point to a filled out `nk_config` struct to configure the conversion process
   1250 ///
   1251 /// Returns one of enum nk_convert_result error codes
   1252 ///
   1253 /// Parameter                       | Description
   1254 /// --------------------------------|-----------------------------------------------------------
   1255 /// NK_CONVERT_SUCCESS              | Signals a successful draw command to vertex buffer conversion
   1256 /// NK_CONVERT_INVALID_PARAM        | An invalid argument was passed in the function call
   1257 /// NK_CONVERT_COMMAND_BUFFER_FULL  | The provided buffer for storing draw commands is full or failed to allocate more memory
   1258 /// NK_CONVERT_VERTEX_BUFFER_FULL   | The provided buffer for storing vertices is full or failed to allocate more memory
   1259 /// NK_CONVERT_ELEMENT_BUFFER_FULL  | The provided buffer for storing indices is full or failed to allocate more memory
   1260 */
   1261 NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
   1262 /*/// #### nk__draw_begin
   1263 /// Returns a draw vertex command buffer iterator to iterate over the vertex draw command buffer
   1264 ///
   1265 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1266 /// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
   1267 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1268 ///
   1269 /// Parameter   | Description
   1270 /// ------------|-----------------------------------------------------------
   1271 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1272 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
   1273 ///
   1274 /// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer
   1275 */
   1276 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
   1277 /*/// #### nk__draw_end
   1278 /// Returns the vertex draw command at the end of the vertex draw command buffer
   1279 ///
   1280 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1281 /// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf);
   1282 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1283 ///
   1284 /// Parameter   | Description
   1285 /// ------------|-----------------------------------------------------------
   1286 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1287 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
   1288 ///
   1289 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
   1290 */
   1291 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
   1292 /*/// #### nk__draw_next
   1293 /// Increments the vertex draw command buffer iterator
   1294 ///
   1295 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1296 /// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
   1297 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1298 ///
   1299 /// Parameter   | Description
   1300 /// ------------|-----------------------------------------------------------
   1301 /// __cmd__     | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
   1302 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
   1303 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1304 ///
   1305 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
   1306 */
   1307 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
   1308 /*/// #### nk_draw_foreach
   1309 /// Iterates over each vertex draw command inside a vertex draw command buffer
   1310 ///
   1311 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1312 /// #define nk_draw_foreach(cmd,ctx, b)
   1313 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1314 ///
   1315 /// Parameter   | Description
   1316 /// ------------|-----------------------------------------------------------
   1317 /// __cmd__     | `nk_draw_command`iterator set to NULL
   1318 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
   1319 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1320 */
   1321 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
   1322 #endif
   1323 /* =============================================================================
   1324  *
   1325  *                                  WINDOW
   1326  *
   1327  * =============================================================================
   1328 /// ### Window
   1329 /// Windows are the main persistent state used inside nuklear and are life time
   1330 /// controlled by simply "retouching" (i.e. calling) each window each frame.
   1331 /// All widgets inside nuklear can only be added inside the function pair `nk_begin_xxx`
   1332 /// and `nk_end`. Calling any widgets outside these two functions will result in an
   1333 /// assert in debug or no state change in release mode.<br /><br />
   1334 ///
   1335 /// Each window holds frame persistent state like position, size, flags, state tables,
   1336 /// and some garbage collected internal persistent widget state. Each window
   1337 /// is linked into a window stack list which determines the drawing and overlapping
   1338 /// order. The topmost window thereby is the currently active window.<br /><br />
   1339 ///
   1340 /// To change window position inside the stack occurs either automatically by
   1341 /// user input by being clicked on or programmatically by calling `nk_window_focus`.
   1342 /// Windows by default are visible unless explicitly being defined with flag
   1343 /// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
   1344 /// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
   1345 /// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.<br /><br />
   1346 ///
   1347 /// #### Usage
   1348 /// To create and keep a window you have to call one of the two `nk_begin_xxx`
   1349 /// functions to start window declarations and `nk_end` at the end. Furthermore it
   1350 /// is recommended to check the return value of `nk_begin_xxx` and only process
   1351 /// widgets inside the window if the value is not 0. Either way you have to call
   1352 /// `nk_end` at the end of window declarations. Furthermore, do not attempt to
   1353 /// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
   1354 /// in a segmentation fault.
   1355 ///
   1356 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1357 /// if (nk_begin_xxx(...) {
   1358 ///     // [... widgets ...]
   1359 /// }
   1360 /// nk_end(ctx);
   1361 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1362 ///
   1363 /// In the grand concept window and widget declarations need to occur after input
   1364 /// handling and before drawing to screen. Not doing so can result in higher
   1365 /// latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
   1366 /// is called at the end of the frame. While nuklear's default platform backends
   1367 /// already call `nk_clear` for you if you write your own backend not calling
   1368 /// `nk_clear` can cause asserts or even worse undefined behavior.
   1369 ///
   1370 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1371 /// struct nk_context ctx;
   1372 /// nk_init_xxx(&ctx, ...);
   1373 /// while (1) {
   1374 ///     Event evt;
   1375 ///     nk_input_begin(&ctx);
   1376 ///     while (GetEvent(&evt)) {
   1377 ///         if (evt.type == MOUSE_MOVE)
   1378 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
   1379 ///         else if (evt.type == [...]) {
   1380 ///             nk_input_xxx(...);
   1381 ///         }
   1382 ///     }
   1383 ///     nk_input_end(&ctx);
   1384 ///
   1385 ///     if (nk_begin_xxx(...) {
   1386 ///         //[...]
   1387 ///     }
   1388 ///     nk_end(ctx);
   1389 ///
   1390 ///     const struct nk_command *cmd = 0;
   1391 ///     nk_foreach(cmd, &ctx) {
   1392 ///     case NK_COMMAND_LINE:
   1393 ///         your_draw_line_function(...)
   1394 ///         break;
   1395 ///     case NK_COMMAND_RECT
   1396 ///         your_draw_rect_function(...)
   1397 ///         break;
   1398 ///     case //...:
   1399 ///         //[...]
   1400 ///     }
   1401 ///     nk_clear(&ctx);
   1402 /// }
   1403 /// nk_free(&ctx);
   1404 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1405 ///
   1406 /// #### Reference
   1407 /// Function                            | Description
   1408 /// ------------------------------------|----------------------------------------
   1409 /// nk_begin                            | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
   1410 /// nk_begin_titled                     | Extended window start with separated title and identifier to allow multiple windows with same name but not title
   1411 /// nk_end                              | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
   1412 //
   1413 /// nk_window_find                      | Finds and returns the window with give name
   1414 /// nk_window_get_bounds                | Returns a rectangle with screen position and size of the currently processed window.
   1415 /// nk_window_get_position              | Returns the position of the currently processed window
   1416 /// nk_window_get_size                  | Returns the size with width and height of the currently processed window
   1417 /// nk_window_get_width                 | Returns the width of the currently processed window
   1418 /// nk_window_get_height                | Returns the height of the currently processed window
   1419 /// nk_window_get_panel                 | Returns the underlying panel which contains all processing state of the current window
   1420 /// nk_window_get_content_region        | Returns the position and size of the currently visible and non-clipped space inside the currently processed window
   1421 /// nk_window_get_content_region_min    | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
   1422 /// nk_window_get_content_region_max    | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
   1423 /// nk_window_get_content_region_size   | Returns the size of the currently visible and non-clipped space inside the currently processed window
   1424 /// nk_window_get_canvas                | Returns the draw command buffer. Can be used to draw custom widgets
   1425 /// nk_window_get_scroll                | Gets the scroll offset of the current window
   1426 /// nk_window_has_focus                 | Returns if the currently processed window is currently active
   1427 /// nk_window_is_collapsed              | Returns if the window with given name is currently minimized/collapsed
   1428 /// nk_window_is_closed                 | Returns if the currently processed window was closed
   1429 /// nk_window_is_hidden                 | Returns if the currently processed window was hidden
   1430 /// nk_window_is_active                 | Same as nk_window_has_focus for some reason
   1431 /// nk_window_is_hovered                | Returns if the currently processed window is currently being hovered by mouse
   1432 /// nk_window_is_any_hovered            | Return if any window currently hovered
   1433 /// nk_item_is_any_active               | Returns if any window or widgets is currently hovered or active
   1434 //
   1435 /// nk_window_set_bounds                | Updates position and size of the currently processed window
   1436 /// nk_window_set_position              | Updates position of the currently process window
   1437 /// nk_window_set_size                  | Updates the size of the currently processed window
   1438 /// nk_window_set_focus                 | Set the currently processed window as active window
   1439 /// nk_window_set_scroll                | Sets the scroll offset of the current window
   1440 //
   1441 /// nk_window_close                     | Closes the window with given window name which deletes the window at the end of the frame
   1442 /// nk_window_collapse                  | Collapses the window with given window name
   1443 /// nk_window_collapse_if               | Collapses the window with given window name if the given condition was met
   1444 /// nk_window_show                      | Hides a visible or reshows a hidden window
   1445 /// nk_window_show_if                   | Hides/shows a window depending on condition
   1446 */
   1447 /*
   1448 /// #### nk_panel_flags
   1449 /// Flag                        | Description
   1450 /// ----------------------------|----------------------------------------
   1451 /// NK_WINDOW_BORDER            | Draws a border around the window to visually separate window from the background
   1452 /// NK_WINDOW_MOVABLE           | The movable flag indicates that a window can be moved by user input or by dragging the window header
   1453 /// NK_WINDOW_SCALABLE          | The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window
   1454 /// NK_WINDOW_CLOSABLE          | Adds a closable icon into the header
   1455 /// NK_WINDOW_MINIMIZABLE       | Adds a minimize icon into the header
   1456 /// NK_WINDOW_NO_SCROLLBAR      | Removes the scrollbar from the window
   1457 /// NK_WINDOW_TITLE             | Forces a header at the top at the window showing the title
   1458 /// NK_WINDOW_SCROLL_AUTO_HIDE  | Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame
   1459 /// NK_WINDOW_BACKGROUND        | Always keep window in the background
   1460 /// NK_WINDOW_SCALE_LEFT        | Puts window scaler in the left-bottom corner instead right-bottom
   1461 /// NK_WINDOW_NO_INPUT          | Prevents window of scaling, moving or getting focus
   1462 ///
   1463 /// #### nk_collapse_states
   1464 /// State           | Description
   1465 /// ----------------|-----------------------------------------------------------
   1466 /// __NK_MINIMIZED__| UI section is collased and not visible until maximized
   1467 /// __NK_MAXIMIZED__| UI section is extended and visible until minimized
   1468 /// <br /><br />
   1469 */
   1470 enum nk_panel_flags {
   1471     NK_WINDOW_BORDER            = NK_FLAG(0),
   1472     NK_WINDOW_MOVABLE           = NK_FLAG(1),
   1473     NK_WINDOW_SCALABLE          = NK_FLAG(2),
   1474     NK_WINDOW_CLOSABLE          = NK_FLAG(3),
   1475     NK_WINDOW_MINIMIZABLE       = NK_FLAG(4),
   1476     NK_WINDOW_NO_SCROLLBAR      = NK_FLAG(5),
   1477     NK_WINDOW_TITLE             = NK_FLAG(6),
   1478     NK_WINDOW_SCROLL_AUTO_HIDE  = NK_FLAG(7),
   1479     NK_WINDOW_BACKGROUND        = NK_FLAG(8),
   1480     NK_WINDOW_SCALE_LEFT        = NK_FLAG(9),
   1481     NK_WINDOW_NO_INPUT          = NK_FLAG(10)
   1482 };
   1483 /*/// #### nk_begin
   1484 /// Starts a new window; needs to be called every frame for every
   1485 /// window (unless hidden) or otherwise the window gets removed
   1486 ///
   1487 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1488 /// nk_bool nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
   1489 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1490 ///
   1491 /// Parameter   | Description
   1492 /// ------------|-----------------------------------------------------------
   1493 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1494 /// __title__   | Window title and identifier. Needs to be persistent over frames to identify the window
   1495 /// __bounds__  | Initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
   1496 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different window behaviors
   1497 ///
   1498 /// Returns `true(1)` if the window can be filled up with widgets from this point
   1499 /// until `nk_end` or `false(0)` otherwise for example if minimized
   1500 */
   1501 NK_API nk_bool nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
   1502 /*/// #### nk_begin_titled
   1503 /// Extended window start with separated title and identifier to allow multiple
   1504 /// windows with same title but not name
   1505 ///
   1506 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1507 /// nk_bool nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
   1508 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1509 ///
   1510 /// Parameter   | Description
   1511 /// ------------|-----------------------------------------------------------
   1512 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1513 /// __name__    | Window identifier. Needs to be persistent over frames to identify the window
   1514 /// __title__   | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
   1515 /// __bounds__  | Initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
   1516 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different window behaviors
   1517 ///
   1518 /// Returns `true(1)` if the window can be filled up with widgets from this point
   1519 /// until `nk_end` or `false(0)` otherwise for example if minimized
   1520 */
   1521 NK_API nk_bool nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
   1522 /*/// #### nk_end
   1523 /// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
   1524 /// All widget calls after this functions will result in asserts or no state changes
   1525 ///
   1526 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1527 /// void nk_end(struct nk_context *ctx);
   1528 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1529 ///
   1530 /// Parameter   | Description
   1531 /// ------------|-----------------------------------------------------------
   1532 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1533 */
   1534 NK_API void nk_end(struct nk_context *ctx);
   1535 /*/// #### nk_window_find
   1536 /// Finds and returns a window from passed name
   1537 ///
   1538 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1539 /// struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
   1540 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1541 ///
   1542 /// Parameter   | Description
   1543 /// ------------|-----------------------------------------------------------
   1544 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1545 /// __name__    | Window identifier
   1546 ///
   1547 /// Returns a `nk_window` struct pointing to the identified window or NULL if
   1548 /// no window with the given name was found
   1549 */
   1550 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
   1551 /*/// #### nk_window_get_bounds
   1552 /// Returns a rectangle with screen position and size of the currently processed window
   1553 ///
   1554 /// !!! WARNING
   1555 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1556 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1557 /// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
   1558 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1559 ///
   1560 /// Parameter   | Description
   1561 /// ------------|-----------------------------------------------------------
   1562 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1563 ///
   1564 /// Returns a `nk_rect` struct with window upper left window position and size
   1565 */
   1566 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
   1567 /*/// #### nk_window_get_position
   1568 /// Returns the position of the currently processed window.
   1569 ///
   1570 /// !!! WARNING
   1571 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1572 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1573 /// struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
   1574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1575 ///
   1576 /// Parameter   | Description
   1577 /// ------------|-----------------------------------------------------------
   1578 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1579 ///
   1580 /// Returns a `nk_vec2` struct with window upper left position
   1581 */
   1582 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
   1583 /*/// #### nk_window_get_size
   1584 /// Returns the size with width and height of the currently processed window.
   1585 ///
   1586 /// !!! WARNING
   1587 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1588 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1589 /// struct nk_vec2 nk_window_get_size(const struct nk_context *ctx);
   1590 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1591 ///
   1592 /// Parameter   | Description
   1593 /// ------------|-----------------------------------------------------------
   1594 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1595 ///
   1596 /// Returns a `nk_vec2` struct with window width and height
   1597 */
   1598 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*);
   1599 /*/// #### nk_window_get_width
   1600 /// Returns the width of the currently processed window.
   1601 ///
   1602 /// !!! WARNING
   1603 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1604 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1605 /// float nk_window_get_width(const struct nk_context *ctx);
   1606 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1607 ///
   1608 /// Parameter   | Description
   1609 /// ------------|-----------------------------------------------------------
   1610 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1611 ///
   1612 /// Returns the current window width
   1613 */
   1614 NK_API float nk_window_get_width(const struct nk_context*);
   1615 /*/// #### nk_window_get_height
   1616 /// Returns the height of the currently processed window.
   1617 ///
   1618 /// !!! WARNING
   1619 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1620 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1621 /// float nk_window_get_height(const struct nk_context *ctx);
   1622 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1623 ///
   1624 /// Parameter   | Description
   1625 /// ------------|-----------------------------------------------------------
   1626 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1627 ///
   1628 /// Returns the current window height
   1629 */
   1630 NK_API float nk_window_get_height(const struct nk_context*);
   1631 /*/// #### nk_window_get_panel
   1632 /// Returns the underlying panel which contains all processing state of the current window.
   1633 ///
   1634 /// !!! WARNING
   1635 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1636 /// !!! WARNING
   1637 ///     Do not keep the returned panel pointer around, it is only valid until `nk_end`
   1638 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1639 /// struct nk_panel* nk_window_get_panel(struct nk_context *ctx);
   1640 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1641 ///
   1642 /// Parameter   | Description
   1643 /// ------------|-----------------------------------------------------------
   1644 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1645 ///
   1646 /// Returns a pointer to window internal `nk_panel` state.
   1647 */
   1648 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*);
   1649 /*/// #### nk_window_get_content_region
   1650 /// Returns the position and size of the currently visible and non-clipped space
   1651 /// inside the currently processed window.
   1652 ///
   1653 /// !!! WARNING
   1654 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1655 ///
   1656 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1657 /// struct nk_rect nk_window_get_content_region(struct nk_context *ctx);
   1658 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1659 ///
   1660 /// Parameter   | Description
   1661 /// ------------|-----------------------------------------------------------
   1662 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1663 ///
   1664 /// Returns `nk_rect` struct with screen position and size (no scrollbar offset)
   1665 /// of the visible space inside the current window
   1666 */
   1667 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*);
   1668 /*/// #### nk_window_get_content_region_min
   1669 /// Returns the upper left position of the currently visible and non-clipped
   1670 /// space inside the currently processed window.
   1671 ///
   1672 /// !!! WARNING
   1673 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1674 ///
   1675 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1676 /// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx);
   1677 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1678 ///
   1679 /// Parameter   | Description
   1680 /// ------------|-----------------------------------------------------------
   1681 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1682 ///
   1683 /// returns `nk_vec2` struct with  upper left screen position (no scrollbar offset)
   1684 /// of the visible space inside the current window
   1685 */
   1686 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*);
   1687 /*/// #### nk_window_get_content_region_max
   1688 /// Returns the lower right screen position of the currently visible and
   1689 /// non-clipped space inside the currently processed window.
   1690 ///
   1691 /// !!! WARNING
   1692 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1693 ///
   1694 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1695 /// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx);
   1696 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1697 ///
   1698 /// Parameter   | Description
   1699 /// ------------|-----------------------------------------------------------
   1700 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1701 ///
   1702 /// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset)
   1703 /// of the visible space inside the current window
   1704 */
   1705 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*);
   1706 /*/// #### nk_window_get_content_region_size
   1707 /// Returns the size of the currently visible and non-clipped space inside the
   1708 /// currently processed window
   1709 ///
   1710 /// !!! WARNING
   1711 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1712 ///
   1713 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1714 /// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx);
   1715 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1716 ///
   1717 /// Parameter   | Description
   1718 /// ------------|-----------------------------------------------------------
   1719 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1720 ///
   1721 /// Returns `nk_vec2` struct with size the visible space inside the current window
   1722 */
   1723 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*);
   1724 /*/// #### nk_window_get_canvas
   1725 /// Returns the draw command buffer. Can be used to draw custom widgets
   1726 /// !!! WARNING
   1727 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1728 /// !!! WARNING
   1729 ///     Do not keep the returned command buffer pointer around it is only valid until `nk_end`
   1730 ///
   1731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1732 /// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx);
   1733 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1734 ///
   1735 /// Parameter   | Description
   1736 /// ------------|-----------------------------------------------------------
   1737 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1738 ///
   1739 /// Returns a pointer to window internal `nk_command_buffer` struct used as
   1740 /// drawing canvas. Can be used to do custom drawing.
   1741 */
   1742 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*);
   1743 /*/// #### nk_window_get_scroll
   1744 /// Gets the scroll offset for the current window
   1745 /// !!! WARNING
   1746 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1747 ///
   1748 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1749 /// void nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y);
   1750 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1751 ///
   1752 /// Parameter    | Description
   1753 /// -------------|-----------------------------------------------------------
   1754 /// __ctx__      | Must point to an previously initialized `nk_context` struct
   1755 /// __offset_x__ | A pointer to the x offset output (or NULL to ignore)
   1756 /// __offset_y__ | A pointer to the y offset output (or NULL to ignore)
   1757 */
   1758 NK_API void nk_window_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
   1759 /*/// #### nk_window_has_focus
   1760 /// Returns if the currently processed window is currently active
   1761 /// !!! WARNING
   1762 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1763 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1764 /// nk_bool nk_window_has_focus(const struct nk_context *ctx);
   1765 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1766 ///
   1767 /// Parameter   | Description
   1768 /// ------------|-----------------------------------------------------------
   1769 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1770 ///
   1771 /// Returns `false(0)` if current window is not active or `true(1)` if it is
   1772 */
   1773 NK_API nk_bool nk_window_has_focus(const struct nk_context*);
   1774 /*/// #### nk_window_is_hovered
   1775 /// Return if the current window is being hovered
   1776 /// !!! WARNING
   1777 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1778 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1779 /// nk_bool nk_window_is_hovered(struct nk_context *ctx);
   1780 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1781 ///
   1782 /// Parameter   | Description
   1783 /// ------------|-----------------------------------------------------------
   1784 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1785 ///
   1786 /// Returns `true(1)` if current window is hovered or `false(0)` otherwise
   1787 */
   1788 NK_API nk_bool nk_window_is_hovered(struct nk_context*);
   1789 /*/// #### nk_window_is_collapsed
   1790 /// Returns if the window with given name is currently minimized/collapsed
   1791 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1792 /// nk_bool nk_window_is_collapsed(struct nk_context *ctx, const char *name);
   1793 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1794 ///
   1795 /// Parameter   | Description
   1796 /// ------------|-----------------------------------------------------------
   1797 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1798 /// __name__    | Identifier of window you want to check if it is collapsed
   1799 ///
   1800 /// Returns `true(1)` if current window is minimized and `false(0)` if window not
   1801 /// found or is not minimized
   1802 */
   1803 NK_API nk_bool nk_window_is_collapsed(struct nk_context *ctx, const char *name);
   1804 /*/// #### nk_window_is_closed
   1805 /// Returns if the window with given name was closed by calling `nk_close`
   1806 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1807 /// nk_bool nk_window_is_closed(struct nk_context *ctx, const char *name);
   1808 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1809 ///
   1810 /// Parameter   | Description
   1811 /// ------------|-----------------------------------------------------------
   1812 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1813 /// __name__    | Identifier of window you want to check if it is closed
   1814 ///
   1815 /// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed
   1816 */
   1817 NK_API nk_bool nk_window_is_closed(struct nk_context*, const char*);
   1818 /*/// #### nk_window_is_hidden
   1819 /// Returns if the window with given name is hidden
   1820 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1821 /// nk_bool nk_window_is_hidden(struct nk_context *ctx, const char *name);
   1822 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1823 ///
   1824 /// Parameter   | Description
   1825 /// ------------|-----------------------------------------------------------
   1826 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1827 /// __name__    | Identifier of window you want to check if it is hidden
   1828 ///
   1829 /// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible
   1830 */
   1831 NK_API nk_bool nk_window_is_hidden(struct nk_context*, const char*);
   1832 /*/// #### nk_window_is_active
   1833 /// Same as nk_window_has_focus for some reason
   1834 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1835 /// nk_bool nk_window_is_active(struct nk_context *ctx, const char *name);
   1836 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1837 ///
   1838 /// Parameter   | Description
   1839 /// ------------|-----------------------------------------------------------
   1840 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1841 /// __name__    | Identifier of window you want to check if it is active
   1842 ///
   1843 /// Returns `true(1)` if current window is active or `false(0)` window not found or not active
   1844 */
   1845 NK_API nk_bool nk_window_is_active(struct nk_context*, const char*);
   1846 /*/// #### nk_window_is_any_hovered
   1847 /// Returns if the any window is being hovered
   1848 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1849 /// nk_bool nk_window_is_any_hovered(struct nk_context*);
   1850 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1851 ///
   1852 /// Parameter   | Description
   1853 /// ------------|-----------------------------------------------------------
   1854 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1855 ///
   1856 /// Returns `true(1)` if any window is hovered or `false(0)` otherwise
   1857 */
   1858 NK_API nk_bool nk_window_is_any_hovered(struct nk_context*);
   1859 /*/// #### nk_item_is_any_active
   1860 /// Returns if the any window is being hovered or any widget is currently active.
   1861 /// Can be used to decide if input should be processed by UI or your specific input handling.
   1862 /// Example could be UI and 3D camera to move inside a 3D space.
   1863 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1864 /// nk_bool nk_item_is_any_active(struct nk_context*);
   1865 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1866 ///
   1867 /// Parameter   | Description
   1868 /// ------------|-----------------------------------------------------------
   1869 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1870 ///
   1871 /// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise
   1872 */
   1873 NK_API nk_bool nk_item_is_any_active(struct nk_context*);
   1874 /*/// #### nk_window_set_bounds
   1875 /// Updates position and size of window with passed in name
   1876 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1877 /// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
   1878 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1879 ///
   1880 /// Parameter   | Description
   1881 /// ------------|-----------------------------------------------------------
   1882 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1883 /// __name__    | Identifier of the window to modify both position and size
   1884 /// __bounds__  | Must point to a `nk_rect` struct with the new position and size
   1885 */
   1886 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
   1887 /*/// #### nk_window_set_position
   1888 /// Updates position of window with passed name
   1889 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1890 /// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
   1891 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1892 ///
   1893 /// Parameter   | Description
   1894 /// ------------|-----------------------------------------------------------
   1895 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1896 /// __name__    | Identifier of the window to modify both position
   1897 /// __pos__     | Must point to a `nk_vec2` struct with the new position
   1898 */
   1899 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
   1900 /*/// #### nk_window_set_size
   1901 /// Updates size of window with passed in name
   1902 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1903 /// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
   1904 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1905 ///
   1906 /// Parameter   | Description
   1907 /// ------------|-----------------------------------------------------------
   1908 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1909 /// __name__    | Identifier of the window to modify both window size
   1910 /// __size__    | Must point to a `nk_vec2` struct with new window size
   1911 */
   1912 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
   1913 /*/// #### nk_window_set_focus
   1914 /// Sets the window with given name as active
   1915 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1916 /// void nk_window_set_focus(struct nk_context*, const char *name);
   1917 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1918 ///
   1919 /// Parameter   | Description
   1920 /// ------------|-----------------------------------------------------------
   1921 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1922 /// __name__    | Identifier of the window to set focus on
   1923 */
   1924 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
   1925 /*/// #### nk_window_set_scroll
   1926 /// Sets the scroll offset for the current window
   1927 /// !!! WARNING
   1928 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1929 ///
   1930 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1931 /// void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y);
   1932 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1933 ///
   1934 /// Parameter    | Description
   1935 /// -------------|-----------------------------------------------------------
   1936 /// __ctx__      | Must point to an previously initialized `nk_context` struct
   1937 /// __offset_x__ | The x offset to scroll to
   1938 /// __offset_y__ | The y offset to scroll to
   1939 */
   1940 NK_API void nk_window_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
   1941 /*/// #### nk_window_close
   1942 /// Closes a window and marks it for being freed at the end of the frame
   1943 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1944 /// void nk_window_close(struct nk_context *ctx, const char *name);
   1945 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1946 ///
   1947 /// Parameter   | Description
   1948 /// ------------|-----------------------------------------------------------
   1949 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1950 /// __name__    | Identifier of the window to close
   1951 */
   1952 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
   1953 /*/// #### nk_window_collapse
   1954 /// Updates collapse state of a window with given name
   1955 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1956 /// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
   1957 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1958 ///
   1959 /// Parameter   | Description
   1960 /// ------------|-----------------------------------------------------------
   1961 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1962 /// __name__    | Identifier of the window to close
   1963 /// __state__   | value out of nk_collapse_states section
   1964 */
   1965 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
   1966 /*/// #### nk_window_collapse_if
   1967 /// Updates collapse state of a window with given name if given condition is met
   1968 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1969 /// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
   1970 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1971 ///
   1972 /// Parameter   | Description
   1973 /// ------------|-----------------------------------------------------------
   1974 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1975 /// __name__    | Identifier of the window to either collapse or maximize
   1976 /// __state__   | value out of nk_collapse_states section the window should be put into
   1977 /// __cond__    | condition that has to be met to actually commit the collapse state change
   1978 */
   1979 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
   1980 /*/// #### nk_window_show
   1981 /// updates visibility state of a window with given name
   1982 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1983 /// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
   1984 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1985 ///
   1986 /// Parameter   | Description
   1987 /// ------------|-----------------------------------------------------------
   1988 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1989 /// __name__    | Identifier of the window to either collapse or maximize
   1990 /// __state__   | state with either visible or hidden to modify the window with
   1991 */
   1992 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
   1993 /*/// #### nk_window_show_if
   1994 /// Updates visibility state of a window with given name if a given condition is met
   1995 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1996 /// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
   1997 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1998 ///
   1999 /// Parameter   | Description
   2000 /// ------------|-----------------------------------------------------------
   2001 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2002 /// __name__    | Identifier of the window to either hide or show
   2003 /// __state__   | state with either visible or hidden to modify the window with
   2004 /// __cond__    | condition that has to be met to actually commit the visbility state change
   2005 */
   2006 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
   2007 /* =============================================================================
   2008  *
   2009  *                                  LAYOUT
   2010  *
   2011  * =============================================================================
   2012 /// ### Layouting
   2013 /// Layouting in general describes placing widget inside a window with position and size.
   2014 /// While in this particular implementation there are five different APIs for layouting
   2015 /// each with different trade offs between control and ease of use. <br /><br />
   2016 ///
   2017 /// All layouting methods in this library are based around the concept of a row.
   2018 /// A row has a height the window content grows by and a number of columns and each
   2019 /// layouting method specifies how each widget is placed inside the row.
   2020 /// After a row has been allocated by calling a layouting functions and then
   2021 /// filled with widgets will advance an internal pointer over the allocated row. <br /><br />
   2022 ///
   2023 /// To actually define a layout you just call the appropriate layouting function
   2024 /// and each subsequent widget call will place the widget as specified. Important
   2025 /// here is that if you define more widgets then columns defined inside the layout
   2026 /// functions it will allocate the next row without you having to make another layouting <br /><br />
   2027 /// call.
   2028 ///
   2029 /// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
   2030 /// is that you have to define the row height for each. However the row height
   2031 /// often depends on the height of the font. <br /><br />
   2032 ///
   2033 /// To fix that internally nuklear uses a minimum row height that is set to the
   2034 /// height plus padding of currently active font and overwrites the row height
   2035 /// value if zero. <br /><br />
   2036 ///
   2037 /// If you manually want to change the minimum row height then
   2038 /// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to
   2039 /// reset it back to be derived from font height. <br /><br />
   2040 ///
   2041 /// Also if you change the font in nuklear it will automatically change the minimum
   2042 /// row height for you and. This means if you change the font but still want
   2043 /// a minimum row height smaller than the font you have to repush your value. <br /><br />
   2044 ///
   2045 /// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
   2046 /// layouting method in combination with a cassowary constraint solver (there are
   2047 /// some versions on github with permissive license model) to take over all control over widget
   2048 /// layouting yourself. However for quick and dirty layouting using all the other layouting
   2049 /// functions should be fine.
   2050 ///
   2051 /// #### Usage
   2052 /// 1.  __nk_layout_row_dynamic__<br /><br />
   2053 ///     The easiest layouting function is `nk_layout_row_dynamic`. It provides each
   2054 ///     widgets with same horizontal space inside the row and dynamically grows
   2055 ///     if the owning window grows in width. So the number of columns dictates
   2056 ///     the size of each widget dynamically by formula:
   2057 ///
   2058 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2059 ///     widget_width = (window_width - padding - spacing) * (1/colum_count)
   2060 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2061 ///
   2062 ///     Just like all other layouting APIs if you define more widget than columns this
   2063 ///     library will allocate a new row and keep all layouting parameters previously
   2064 ///     defined.
   2065 ///
   2066 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2067 ///     if (nk_begin_xxx(...) {
   2068 ///         // first row with height: 30 composed of two widgets
   2069 ///         nk_layout_row_dynamic(&ctx, 30, 2);
   2070 ///         nk_widget(...);
   2071 ///         nk_widget(...);
   2072 ///         //
   2073 ///         // second row with same parameter as defined above
   2074 ///         nk_widget(...);
   2075 ///         nk_widget(...);
   2076 ///         //
   2077 ///         // third row uses 0 for height which will use auto layouting
   2078 ///         nk_layout_row_dynamic(&ctx, 0, 2);
   2079 ///         nk_widget(...);
   2080 ///         nk_widget(...);
   2081 ///     }
   2082 ///     nk_end(...);
   2083 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2084 ///
   2085 /// 2.  __nk_layout_row_static__<br /><br />
   2086 ///     Another easy layouting function is `nk_layout_row_static`. It provides each
   2087 ///     widget with same horizontal pixel width inside the row and does not grow
   2088 ///     if the owning window scales smaller or bigger.
   2089 ///
   2090 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2091 ///     if (nk_begin_xxx(...) {
   2092 ///         // first row with height: 30 composed of two widgets with width: 80
   2093 ///         nk_layout_row_static(&ctx, 30, 80, 2);
   2094 ///         nk_widget(...);
   2095 ///         nk_widget(...);
   2096 ///         //
   2097 ///         // second row with same parameter as defined above
   2098 ///         nk_widget(...);
   2099 ///         nk_widget(...);
   2100 ///         //
   2101 ///         // third row uses 0 for height which will use auto layouting
   2102 ///         nk_layout_row_static(&ctx, 0, 80, 2);
   2103 ///         nk_widget(...);
   2104 ///         nk_widget(...);
   2105 ///     }
   2106 ///     nk_end(...);
   2107 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2108 ///
   2109 /// 3.  __nk_layout_row_xxx__<br /><br />
   2110 ///     A little bit more advanced layouting API are functions `nk_layout_row_begin`,
   2111 ///     `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
   2112 ///     specify each column pixel or window ratio in a row. It supports either
   2113 ///     directly setting per column pixel width or widget window ratio but not
   2114 ///     both. Furthermore it is a immediate mode API so each value is directly
   2115 ///     pushed before calling a widget. Therefore the layout is not automatically
   2116 ///     repeating like the last two layouting functions.
   2117 ///
   2118 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2119 ///     if (nk_begin_xxx(...) {
   2120 ///         // first row with height: 25 composed of two widgets with width 60 and 40
   2121 ///         nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
   2122 ///         nk_layout_row_push(ctx, 60);
   2123 ///         nk_widget(...);
   2124 ///         nk_layout_row_push(ctx, 40);
   2125 ///         nk_widget(...);
   2126 ///         nk_layout_row_end(ctx);
   2127 ///         //
   2128 ///         // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
   2129 ///         nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
   2130 ///         nk_layout_row_push(ctx, 0.25f);
   2131 ///         nk_widget(...);
   2132 ///         nk_layout_row_push(ctx, 0.75f);
   2133 ///         nk_widget(...);
   2134 ///         nk_layout_row_end(ctx);
   2135 ///         //
   2136 ///         // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75
   2137 ///         nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
   2138 ///         nk_layout_row_push(ctx, 0.25f);
   2139 ///         nk_widget(...);
   2140 ///         nk_layout_row_push(ctx, 0.75f);
   2141 ///         nk_widget(...);
   2142 ///         nk_layout_row_end(ctx);
   2143 ///     }
   2144 ///     nk_end(...);
   2145 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2146 ///
   2147 /// 4.  __nk_layout_row__<br /><br />
   2148 ///     The array counterpart to API nk_layout_row_xxx is the single nk_layout_row
   2149 ///     functions. Instead of pushing either pixel or window ratio for every widget
   2150 ///     it allows to define it by array. The trade of for less control is that
   2151 ///     `nk_layout_row` is automatically repeating. Otherwise the behavior is the
   2152 ///     same.
   2153 ///
   2154 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2155 ///     if (nk_begin_xxx(...) {
   2156 ///         // two rows with height: 30 composed of two widgets with width 60 and 40
   2157 ///         const float ratio[] = {60,40};
   2158 ///         nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
   2159 ///         nk_widget(...);
   2160 ///         nk_widget(...);
   2161 ///         nk_widget(...);
   2162 ///         nk_widget(...);
   2163 ///         //
   2164 ///         // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
   2165 ///         const float ratio[] = {0.25, 0.75};
   2166 ///         nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
   2167 ///         nk_widget(...);
   2168 ///         nk_widget(...);
   2169 ///         nk_widget(...);
   2170 ///         nk_widget(...);
   2171 ///         //
   2172 ///         // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75
   2173 ///         const float ratio[] = {0.25, 0.75};
   2174 ///         nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
   2175 ///         nk_widget(...);
   2176 ///         nk_widget(...);
   2177 ///         nk_widget(...);
   2178 ///         nk_widget(...);
   2179 ///     }
   2180 ///     nk_end(...);
   2181 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2182 ///
   2183 /// 5.  __nk_layout_row_template_xxx__<br /><br />
   2184 ///     The most complex and second most flexible API is a simplified flexbox version without
   2185 ///     line wrapping and weights for dynamic widgets. It is an immediate mode API but
   2186 ///     unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
   2187 ///     before calling the templated widgets.
   2188 ///     The row template layout has three different per widget size specifier. The first
   2189 ///     one is the `nk_layout_row_template_push_static`  with fixed widget pixel width.
   2190 ///     They do not grow if the row grows and will always stay the same.
   2191 ///     The second size specifier is `nk_layout_row_template_push_variable`
   2192 ///     which defines a minimum widget size but it also can grow if more space is available
   2193 ///     not taken by other widgets.
   2194 ///     Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic`
   2195 ///     which are completely flexible and unlike variable widgets can even shrink
   2196 ///     to zero if not enough space is provided.
   2197 ///
   2198 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2199 ///     if (nk_begin_xxx(...) {
   2200 ///         // two rows with height: 30 composed of three widgets
   2201 ///         nk_layout_row_template_begin(ctx, 30);
   2202 ///         nk_layout_row_template_push_dynamic(ctx);
   2203 ///         nk_layout_row_template_push_variable(ctx, 80);
   2204 ///         nk_layout_row_template_push_static(ctx, 80);
   2205 ///         nk_layout_row_template_end(ctx);
   2206 ///         //
   2207 ///         // first row
   2208 ///         nk_widget(...); // dynamic widget can go to zero if not enough space
   2209 ///         nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
   2210 ///         nk_widget(...); // static widget with fixed 80 pixel width
   2211 ///         //
   2212 ///         // second row same layout
   2213 ///         nk_widget(...);
   2214 ///         nk_widget(...);
   2215 ///         nk_widget(...);
   2216 ///     }
   2217 ///     nk_end(...);
   2218 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2219 ///
   2220 /// 6.  __nk_layout_space_xxx__<br /><br />
   2221 ///     Finally the most flexible API directly allows you to place widgets inside the
   2222 ///     window. The space layout API is an immediate mode API which does not support
   2223 ///     row auto repeat and directly sets position and size of a widget. Position
   2224 ///     and size hereby can be either specified as ratio of allocated space or
   2225 ///     allocated space local position and pixel size. Since this API is quite
   2226 ///     powerful there are a number of utility functions to get the available space
   2227 ///     and convert between local allocated space and screen space.
   2228 ///
   2229 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2230 ///     if (nk_begin_xxx(...) {
   2231 ///         // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
   2232 ///         nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
   2233 ///         nk_layout_space_push(ctx, nk_rect(0,0,150,200));
   2234 ///         nk_widget(...);
   2235 ///         nk_layout_space_push(ctx, nk_rect(200,200,100,200));
   2236 ///         nk_widget(...);
   2237 ///         nk_layout_space_end(ctx);
   2238 ///         //
   2239 ///         // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
   2240 ///         nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
   2241 ///         nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
   2242 ///         nk_widget(...);
   2243 ///         nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
   2244 ///         nk_widget(...);
   2245 ///     }
   2246 ///     nk_end(...);
   2247 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2248 ///
   2249 /// #### Reference
   2250 /// Function                                | Description
   2251 /// ----------------------------------------|------------------------------------
   2252 /// nk_layout_set_min_row_height            | Set the currently used minimum row height to a specified value
   2253 /// nk_layout_reset_min_row_height          | Resets the currently used minimum row height to font height
   2254 /// nk_layout_widget_bounds                 | Calculates current width a static layout row can fit inside a window
   2255 /// nk_layout_ratio_from_pixel              | Utility functions to calculate window ratio from pixel size
   2256 //
   2257 /// nk_layout_row_dynamic                   | Current layout is divided into n same sized growing columns
   2258 /// nk_layout_row_static                    | Current layout is divided into n same fixed sized columns
   2259 /// nk_layout_row_begin                     | Starts a new row with given height and number of columns
   2260 /// nk_layout_row_push                      | Pushes another column with given size or window ratio
   2261 /// nk_layout_row_end                       | Finished previously started row
   2262 /// nk_layout_row                           | Specifies row columns in array as either window ratio or size
   2263 //
   2264 /// nk_layout_row_template_begin            | Begins the row template declaration
   2265 /// nk_layout_row_template_push_dynamic     | Adds a dynamic column that dynamically grows and can go to zero if not enough space
   2266 /// nk_layout_row_template_push_variable    | Adds a variable column that dynamically grows but does not shrink below specified pixel width
   2267 /// nk_layout_row_template_push_static      | Adds a static column that does not grow and will always have the same size
   2268 /// nk_layout_row_template_end              | Marks the end of the row template
   2269 //
   2270 /// nk_layout_space_begin                   | Begins a new layouting space that allows to specify each widgets position and size
   2271 /// nk_layout_space_push                    | Pushes position and size of the next widget in own coordinate space either as pixel or ratio
   2272 /// nk_layout_space_end                     | Marks the end of the layouting space
   2273 //
   2274 /// nk_layout_space_bounds                  | Callable after nk_layout_space_begin and returns total space allocated
   2275 /// nk_layout_space_to_screen               | Converts vector from nk_layout_space coordinate space into screen space
   2276 /// nk_layout_space_to_local                | Converts vector from screen space into nk_layout_space coordinates
   2277 /// nk_layout_space_rect_to_screen          | Converts rectangle from nk_layout_space coordinate space into screen space
   2278 /// nk_layout_space_rect_to_local           | Converts rectangle from screen space into nk_layout_space coordinates
   2279 */
   2280 /*/// #### nk_layout_set_min_row_height
   2281 /// Sets the currently used minimum row height.
   2282 /// !!! WARNING
   2283 ///     The passed height needs to include both your preferred row height
   2284 ///     as well as padding. No internal padding is added.
   2285 ///
   2286 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2287 /// void nk_layout_set_min_row_height(struct nk_context*, float height);
   2288 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2289 ///
   2290 /// Parameter   | Description
   2291 /// ------------|-----------------------------------------------------------
   2292 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2293 /// __height__  | New minimum row height to be used for auto generating the row height
   2294 */
   2295 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height);
   2296 /*/// #### nk_layout_reset_min_row_height
   2297 /// Reset the currently used minimum row height back to `font_height + text_padding + padding`
   2298 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2299 /// void nk_layout_reset_min_row_height(struct nk_context*);
   2300 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2301 ///
   2302 /// Parameter   | Description
   2303 /// ------------|-----------------------------------------------------------
   2304 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2305 */
   2306 NK_API void nk_layout_reset_min_row_height(struct nk_context*);
   2307 /*/// #### nk_layout_widget_bounds
   2308 /// Returns the width of the next row allocate by one of the layouting functions
   2309 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2310 /// struct nk_rect nk_layout_widget_bounds(struct nk_context*);
   2311 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2312 ///
   2313 /// Parameter   | Description
   2314 /// ------------|-----------------------------------------------------------
   2315 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2316 ///
   2317 /// Return `nk_rect` with both position and size of the next row
   2318 */
   2319 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*);
   2320 /*/// #### nk_layout_ratio_from_pixel
   2321 /// Utility functions to calculate window ratio from pixel size
   2322 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2323 /// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
   2324 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2325 ///
   2326 /// Parameter   | Description
   2327 /// ------------|-----------------------------------------------------------
   2328 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2329 /// __pixel__   | Pixel_width to convert to window ratio
   2330 ///
   2331 /// Returns `nk_rect` with both position and size of the next row
   2332 */
   2333 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
   2334 /*/// #### nk_layout_row_dynamic
   2335 /// Sets current row layout to share horizontal space
   2336 /// between @cols number of widgets evenly. Once called all subsequent widget
   2337 /// calls greater than @cols will allocate a new row with same layout.
   2338 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2339 /// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
   2340 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2341 ///
   2342 /// Parameter   | Description
   2343 /// ------------|-----------------------------------------------------------
   2344 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2345 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2346 /// __columns__ | Number of widget inside row
   2347 */
   2348 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
   2349 /*/// #### nk_layout_row_static
   2350 /// Sets current row layout to fill @cols number of widgets
   2351 /// in row with same @item_width horizontal size. Once called all subsequent widget
   2352 /// calls greater than @cols will allocate a new row with same layout.
   2353 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2354 /// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
   2355 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2356 ///
   2357 /// Parameter   | Description
   2358 /// ------------|-----------------------------------------------------------
   2359 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2360 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2361 /// __width__   | Holds pixel width of each widget in the row
   2362 /// __columns__ | Number of widget inside row
   2363 */
   2364 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
   2365 /*/// #### nk_layout_row_begin
   2366 /// Starts a new dynamic or fixed row with given height and columns.
   2367 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2368 /// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
   2369 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2370 ///
   2371 /// Parameter   | Description
   2372 /// ------------|-----------------------------------------------------------
   2373 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2374 /// __fmt__     | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
   2375 /// __height__  | holds height of each widget in row or zero for auto layouting
   2376 /// __columns__ | Number of widget inside row
   2377 */
   2378 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
   2379 /*/// #### nk_layout_row_push
   2380 /// Specifies either window ratio or width of a single column
   2381 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2382 /// void nk_layout_row_push(struct nk_context*, float value);
   2383 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2384 ///
   2385 /// Parameter   | Description
   2386 /// ------------|-----------------------------------------------------------
   2387 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2388 /// __value__   | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call
   2389 */
   2390 NK_API void nk_layout_row_push(struct nk_context*, float value);
   2391 /*/// #### nk_layout_row_end
   2392 /// Finished previously started row
   2393 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2394 /// void nk_layout_row_end(struct nk_context*);
   2395 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2396 ///
   2397 /// Parameter   | Description
   2398 /// ------------|-----------------------------------------------------------
   2399 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2400 */
   2401 NK_API void nk_layout_row_end(struct nk_context*);
   2402 /*/// #### nk_layout_row
   2403 /// Specifies row columns in array as either window ratio or size
   2404 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2405 /// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
   2406 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2407 ///
   2408 /// Parameter   | Description
   2409 /// ------------|-----------------------------------------------------------
   2410 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2411 /// __fmt__     | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
   2412 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2413 /// __columns__ | Number of widget inside row
   2414 */
   2415 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
   2416 /*/// #### nk_layout_row_template_begin
   2417 /// Begins the row template declaration
   2418 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2419 /// void nk_layout_row_template_begin(struct nk_context*, float row_height);
   2420 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2421 ///
   2422 /// Parameter   | Description
   2423 /// ------------|-----------------------------------------------------------
   2424 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2425 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2426 */
   2427 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
   2428 /*/// #### nk_layout_row_template_push_dynamic
   2429 /// Adds a dynamic column that dynamically grows and can go to zero if not enough space
   2430 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2431 /// void nk_layout_row_template_push_dynamic(struct nk_context*);
   2432 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2433 ///
   2434 /// Parameter   | Description
   2435 /// ------------|-----------------------------------------------------------
   2436 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2437 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2438 */
   2439 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*);
   2440 /*/// #### nk_layout_row_template_push_variable
   2441 /// Adds a variable column that dynamically grows but does not shrink below specified pixel width
   2442 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2443 /// void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
   2444 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2445 ///
   2446 /// Parameter   | Description
   2447 /// ------------|-----------------------------------------------------------
   2448 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2449 /// __width__   | Holds the minimum pixel width the next column must always be
   2450 */
   2451 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
   2452 /*/// #### nk_layout_row_template_push_static
   2453 /// Adds a static column that does not grow and will always have the same size
   2454 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2455 /// void nk_layout_row_template_push_static(struct nk_context*, float width);
   2456 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2457 ///
   2458 /// Parameter   | Description
   2459 /// ------------|-----------------------------------------------------------
   2460 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2461 /// __width__   | Holds the absolute pixel width value the next column must be
   2462 */
   2463 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
   2464 /*/// #### nk_layout_row_template_end
   2465 /// Marks the end of the row template
   2466 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2467 /// void nk_layout_row_template_end(struct nk_context*);
   2468 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2469 ///
   2470 /// Parameter   | Description
   2471 /// ------------|-----------------------------------------------------------
   2472 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2473 */
   2474 NK_API void nk_layout_row_template_end(struct nk_context*);
   2475 /*/// #### nk_layout_space_begin
   2476 /// Begins a new layouting space that allows to specify each widgets position and size.
   2477 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2478 /// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
   2479 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2480 ///
   2481 /// Parameter   | Description
   2482 /// ------------|-----------------------------------------------------------
   2483 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2484 /// __fmt__     | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
   2485 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2486 /// __columns__ | Number of widgets inside row
   2487 */
   2488 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
   2489 /*/// #### nk_layout_space_push
   2490 /// Pushes position and size of the next widget in own coordinate space either as pixel or ratio
   2491 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2492 /// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds);
   2493 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2494 ///
   2495 /// Parameter   | Description
   2496 /// ------------|-----------------------------------------------------------
   2497 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2498 /// __bounds__  | Position and size in laoyut space local coordinates
   2499 */
   2500 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds);
   2501 /*/// #### nk_layout_space_end
   2502 /// Marks the end of the layout space
   2503 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2504 /// void nk_layout_space_end(struct nk_context*);
   2505 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2506 ///
   2507 /// Parameter   | Description
   2508 /// ------------|-----------------------------------------------------------
   2509 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2510 */
   2511 NK_API void nk_layout_space_end(struct nk_context*);
   2512 /*/// #### nk_layout_space_bounds
   2513 /// Utility function to calculate total space allocated for `nk_layout_space`
   2514 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2515 /// struct nk_rect nk_layout_space_bounds(struct nk_context*);
   2516 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2517 ///
   2518 /// Parameter   | Description
   2519 /// ------------|-----------------------------------------------------------
   2520 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2521 ///
   2522 /// Returns `nk_rect` holding the total space allocated
   2523 */
   2524 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*);
   2525 /*/// #### nk_layout_space_to_screen
   2526 /// Converts vector from nk_layout_space coordinate space into screen space
   2527 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2528 /// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
   2529 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2530 ///
   2531 /// Parameter   | Description
   2532 /// ------------|-----------------------------------------------------------
   2533 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2534 /// __vec__     | Position to convert from layout space into screen coordinate space
   2535 ///
   2536 /// Returns transformed `nk_vec2` in screen space coordinates
   2537 */
   2538 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
   2539 /*/// #### nk_layout_space_to_local
   2540 /// Converts vector from layout space into screen space
   2541 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2542 /// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
   2543 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2544 ///
   2545 /// Parameter   | Description
   2546 /// ------------|-----------------------------------------------------------
   2547 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2548 /// __vec__     | Position to convert from screen space into layout coordinate space
   2549 ///
   2550 /// Returns transformed `nk_vec2` in layout space coordinates
   2551 */
   2552 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
   2553 /*/// #### nk_layout_space_rect_to_screen
   2554 /// Converts rectangle from screen space into layout space
   2555 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2556 /// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
   2557 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2558 ///
   2559 /// Parameter   | Description
   2560 /// ------------|-----------------------------------------------------------
   2561 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2562 /// __bounds__  | Rectangle to convert from layout space into screen space
   2563 ///
   2564 /// Returns transformed `nk_rect` in screen space coordinates
   2565 */
   2566 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
   2567 /*/// #### nk_layout_space_rect_to_local
   2568 /// Converts rectangle from layout space into screen space
   2569 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2570 /// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
   2571 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2572 ///
   2573 /// Parameter   | Description
   2574 /// ------------|-----------------------------------------------------------
   2575 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2576 /// __bounds__  | Rectangle to convert from layout space into screen space
   2577 ///
   2578 /// Returns transformed `nk_rect` in layout space coordinates
   2579 */
   2580 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
   2581 
   2582 /*/// #### nk_spacer
   2583 /// Spacer is a dummy widget that consumes space as usual but doesn't draw anything
   2584 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2585 /// void nk_spacer(struct nk_context* );
   2586 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2587 ///
   2588 /// Parameter   | Description
   2589 /// ------------|-----------------------------------------------------------
   2590 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2591 ///
   2592 */
   2593 NK_API void nk_spacer(struct nk_context* );
   2594 
   2595 
   2596 /* =============================================================================
   2597  *
   2598  *                                  GROUP
   2599  *
   2600  * =============================================================================
   2601 /// ### Groups
   2602 /// Groups are basically windows inside windows. They allow to subdivide space
   2603 /// in a window to layout widgets as a group. Almost all more complex widget
   2604 /// layouting requirements can be solved using groups and basic layouting
   2605 /// fuctionality. Groups just like windows are identified by an unique name and
   2606 /// internally keep track of scrollbar offsets by default. However additional
   2607 /// versions are provided to directly manage the scrollbar.
   2608 ///
   2609 /// #### Usage
   2610 /// To create a group you have to call one of the three `nk_group_begin_xxx`
   2611 /// functions to start group declarations and `nk_group_end` at the end. Furthermore it
   2612 /// is required to check the return value of `nk_group_begin_xxx` and only process
   2613 /// widgets inside the window if the value is not 0.
   2614 /// Nesting groups is possible and even encouraged since many layouting schemes
   2615 /// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end`
   2616 /// to be only called if the corresponding `nk_group_begin_xxx` call does not return 0:
   2617 ///
   2618 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2619 /// if (nk_group_begin_xxx(ctx, ...) {
   2620 ///     // [... widgets ...]
   2621 ///     nk_group_end(ctx);
   2622 /// }
   2623 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2624 ///
   2625 /// In the grand concept groups can be called after starting a window
   2626 /// with `nk_begin_xxx` and before calling `nk_end`:
   2627 ///
   2628 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2629 /// struct nk_context ctx;
   2630 /// nk_init_xxx(&ctx, ...);
   2631 /// while (1) {
   2632 ///     // Input
   2633 ///     Event evt;
   2634 ///     nk_input_begin(&ctx);
   2635 ///     while (GetEvent(&evt)) {
   2636 ///         if (evt.type == MOUSE_MOVE)
   2637 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
   2638 ///         else if (evt.type == [...]) {
   2639 ///             nk_input_xxx(...);
   2640 ///         }
   2641 ///     }
   2642 ///     nk_input_end(&ctx);
   2643 ///     //
   2644 ///     // Window
   2645 ///     if (nk_begin_xxx(...) {
   2646 ///         // [...widgets...]
   2647 ///         nk_layout_row_dynamic(...);
   2648 ///         if (nk_group_begin_xxx(ctx, ...) {
   2649 ///             //[... widgets ...]
   2650 ///             nk_group_end(ctx);
   2651 ///         }
   2652 ///     }
   2653 ///     nk_end(ctx);
   2654 ///     //
   2655 ///     // Draw
   2656 ///     const struct nk_command *cmd = 0;
   2657 ///     nk_foreach(cmd, &ctx) {
   2658 ///     switch (cmd->type) {
   2659 ///     case NK_COMMAND_LINE:
   2660 ///         your_draw_line_function(...)
   2661 ///         break;
   2662 ///     case NK_COMMAND_RECT
   2663 ///         your_draw_rect_function(...)
   2664 ///         break;
   2665 ///     case ...:
   2666 ///         // [...]
   2667 ///     }
   2668 ///     nk_clear(&ctx);
   2669 /// }
   2670 /// nk_free(&ctx);
   2671 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2672 /// #### Reference
   2673 /// Function                        | Description
   2674 /// --------------------------------|-------------------------------------------
   2675 /// nk_group_begin                  | Start a new group with internal scrollbar handling
   2676 /// nk_group_begin_titled           | Start a new group with separated name and title and internal scrollbar handling
   2677 /// nk_group_end                    | Ends a group. Should only be called if nk_group_begin returned non-zero
   2678 /// nk_group_scrolled_offset_begin  | Start a new group with manual separated handling of scrollbar x- and y-offset
   2679 /// nk_group_scrolled_begin         | Start a new group with manual scrollbar handling
   2680 /// nk_group_scrolled_end           | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero
   2681 /// nk_group_get_scroll             | Gets the scroll offset for the given group
   2682 /// nk_group_set_scroll             | Sets the scroll offset for the given group
   2683 */
   2684 /*/// #### nk_group_begin
   2685 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
   2686 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2687 /// nk_bool nk_group_begin(struct nk_context*, const char *title, nk_flags);
   2688 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2689 ///
   2690 /// Parameter   | Description
   2691 /// ------------|-----------------------------------------------------------
   2692 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2693 /// __title__   | Must be an unique identifier for this group that is also used for the group header
   2694 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different group behaviors
   2695 ///
   2696 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2697 */
   2698 NK_API nk_bool nk_group_begin(struct nk_context*, const char *title, nk_flags);
   2699 /*/// #### nk_group_begin_titled
   2700 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
   2701 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2702 /// nk_bool nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
   2703 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2704 ///
   2705 /// Parameter   | Description
   2706 /// ------------|-----------------------------------------------------------
   2707 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2708 /// __id__      | Must be an unique identifier for this group
   2709 /// __title__   | Group header title
   2710 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different group behaviors
   2711 ///
   2712 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2713 */
   2714 NK_API nk_bool nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
   2715 /*/// #### nk_group_end
   2716 /// Ends a widget group
   2717 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2718 /// void nk_group_end(struct nk_context*);
   2719 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2720 ///
   2721 /// Parameter   | Description
   2722 /// ------------|-----------------------------------------------------------
   2723 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2724 */
   2725 NK_API void nk_group_end(struct nk_context*);
   2726 /*/// #### nk_group_scrolled_offset_begin
   2727 /// starts a new widget group. requires a previous layouting function to specify
   2728 /// a size. Does not keep track of scrollbar.
   2729 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2730 /// nk_bool nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
   2731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2732 ///
   2733 /// Parameter   | Description
   2734 /// ------------|-----------------------------------------------------------
   2735 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2736 /// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally.
   2737 /// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically
   2738 /// __title__   | Window unique group title used to both identify and display in the group header
   2739 /// __flags__   | Window flags from the nk_panel_flags section
   2740 ///
   2741 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2742 */
   2743 NK_API nk_bool nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
   2744 /*/// #### nk_group_scrolled_begin
   2745 /// Starts a new widget group. requires a previous
   2746 /// layouting function to specify a size. Does not keep track of scrollbar.
   2747 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2748 /// nk_bool nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
   2749 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2750 ///
   2751 /// Parameter   | Description
   2752 /// ------------|-----------------------------------------------------------
   2753 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2754 /// __off__     | Both x- and y- scroll offset. Allows for manual scrollbar control
   2755 /// __title__   | Window unique group title used to both identify and display in the group header
   2756 /// __flags__   | Window flags from nk_panel_flags section
   2757 ///
   2758 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2759 */
   2760 NK_API nk_bool nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
   2761 /*/// #### nk_group_scrolled_end
   2762 /// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin.
   2763 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2764 /// void nk_group_scrolled_end(struct nk_context*);
   2765 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2766 ///
   2767 /// Parameter   | Description
   2768 /// ------------|-----------------------------------------------------------
   2769 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2770 */
   2771 NK_API void nk_group_scrolled_end(struct nk_context*);
   2772 /*/// #### nk_group_get_scroll
   2773 /// Gets the scroll position of the given group.
   2774 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2775 /// void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset);
   2776 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2777 ///
   2778 /// Parameter    | Description
   2779 /// -------------|-----------------------------------------------------------
   2780 /// __ctx__      | Must point to an previously initialized `nk_context` struct
   2781 /// __id__       | The id of the group to get the scroll position of
   2782 /// __x_offset__ | A pointer to the x offset output (or NULL to ignore)
   2783 /// __y_offset__ | A pointer to the y offset output (or NULL to ignore)
   2784 */
   2785 NK_API void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset);
   2786 /*/// #### nk_group_set_scroll
   2787 /// Sets the scroll position of the given group.
   2788 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2789 /// void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset);
   2790 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2791 ///
   2792 /// Parameter    | Description
   2793 /// -------------|-----------------------------------------------------------
   2794 /// __ctx__      | Must point to an previously initialized `nk_context` struct
   2795 /// __id__       | The id of the group to scroll
   2796 /// __x_offset__ | The x offset to scroll to
   2797 /// __y_offset__ | The y offset to scroll to
   2798 */
   2799 NK_API void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset);
   2800 /* =============================================================================
   2801  *
   2802  *                                  TREE
   2803  *
   2804  * =============================================================================
   2805 /// ### Tree
   2806 /// Trees represent two different concept. First the concept of a collapsible
   2807 /// UI section that can be either in a hidden or visible state. They allow the UI
   2808 /// user to selectively minimize the current set of visible UI to comprehend.
   2809 /// The second concept are tree widgets for visual UI representation of trees.<br /><br />
   2810 ///
   2811 /// Trees thereby can be nested for tree representations and multiple nested
   2812 /// collapsible UI sections. All trees are started by calling of the
   2813 /// `nk_tree_xxx_push_tree` functions and ended by calling one of the
   2814 /// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label
   2815 /// and optionally an image to be displayed and the initial collapse state from
   2816 /// the nk_collapse_states section.<br /><br />
   2817 ///
   2818 /// The runtime state of the tree is either stored outside the library by the caller
   2819 /// or inside which requires a unique ID. The unique ID can either be generated
   2820 /// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`,
   2821 /// by `__FILE__` and a user provided ID generated for example by loop index with
   2822 /// function `nk_tree_push_id` or completely provided from outside by user with
   2823 /// function `nk_tree_push_hashed`.
   2824 ///
   2825 /// #### Usage
   2826 /// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx`
   2827 /// functions to start a collapsible UI section and `nk_tree_xxx_pop` to mark the
   2828 /// end.
   2829 /// Each starting function will either return `false(0)` if the tree is collapsed
   2830 /// or hidden and therefore does not need to be filled with content or `true(1)`
   2831 /// if visible and required to be filled.
   2832 ///
   2833 /// !!! Note
   2834 ///     The tree header does not require and layouting function and instead
   2835 ///     calculates a auto height based on the currently used font size
   2836 ///
   2837 /// The tree ending functions only need to be called if the tree content is
   2838 /// actually visible. So make sure the tree push function is guarded by `if`
   2839 /// and the pop call is only taken if the tree is visible.
   2840 ///
   2841 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2842 /// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) {
   2843 ///     nk_layout_row_dynamic(...);
   2844 ///     nk_widget(...);
   2845 ///     nk_tree_pop(ctx);
   2846 /// }
   2847 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2848 ///
   2849 /// #### Reference
   2850 /// Function                    | Description
   2851 /// ----------------------------|-------------------------------------------
   2852 /// nk_tree_push                | Start a collapsible UI section with internal state management
   2853 /// nk_tree_push_id             | Start a collapsible UI section with internal state management callable in a look
   2854 /// nk_tree_push_hashed         | Start a collapsible UI section with internal state management with full control over internal unique ID use to store state
   2855 /// nk_tree_image_push          | Start a collapsible UI section with image and label header
   2856 /// nk_tree_image_push_id       | Start a collapsible UI section with image and label header and internal state management callable in a look
   2857 /// nk_tree_image_push_hashed   | Start a collapsible UI section with image and label header and internal state management with full control over internal unique ID use to store state
   2858 /// nk_tree_pop                 | Ends a collapsible UI section
   2859 //
   2860 /// nk_tree_state_push          | Start a collapsible UI section with external state management
   2861 /// nk_tree_state_image_push    | Start a collapsible UI section with image and label header and external state management
   2862 /// nk_tree_state_pop           | Ends a collapsabale UI section
   2863 ///
   2864 /// #### nk_tree_type
   2865 /// Flag            | Description
   2866 /// ----------------|----------------------------------------
   2867 /// NK_TREE_NODE    | Highlighted tree header to mark a collapsible UI section
   2868 /// NK_TREE_TAB     | Non-highlighted tree header closer to tree representations
   2869 */
   2870 /*/// #### nk_tree_push
   2871 /// Starts a collapsible UI section with internal state management
   2872 /// !!! WARNING
   2873 ///     To keep track of the runtime tree collapsible state this function uses
   2874 ///     defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
   2875 ///     to call this function in a loop please use `nk_tree_push_id` or
   2876 ///     `nk_tree_push_hashed` instead.
   2877 ///
   2878 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2879 /// #define nk_tree_push(ctx, type, title, state)
   2880 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2881 ///
   2882 /// Parameter   | Description
   2883 /// ------------|-----------------------------------------------------------
   2884 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2885 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2886 /// __title__   | Label printed in the tree header
   2887 /// __state__   | Initial tree state value out of nk_collapse_states
   2888 ///
   2889 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2890 */
   2891 #define nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
   2892 /*/// #### nk_tree_push_id
   2893 /// Starts a collapsible UI section with internal state management callable in a look
   2894 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2895 /// #define nk_tree_push_id(ctx, type, title, state, id)
   2896 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2897 ///
   2898 /// Parameter   | Description
   2899 /// ------------|-----------------------------------------------------------
   2900 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2901 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2902 /// __title__   | Label printed in the tree header
   2903 /// __state__   | Initial tree state value out of nk_collapse_states
   2904 /// __id__      | Loop counter index if this function is called in a loop
   2905 ///
   2906 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2907 */
   2908 #define nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
   2909 /*/// #### nk_tree_push_hashed
   2910 /// Start a collapsible UI section with internal state management with full
   2911 /// control over internal unique ID used to store state
   2912 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2913 /// nk_bool nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
   2914 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2915 ///
   2916 /// Parameter   | Description
   2917 /// ------------|-----------------------------------------------------------
   2918 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2919 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2920 /// __title__   | Label printed in the tree header
   2921 /// __state__   | Initial tree state value out of nk_collapse_states
   2922 /// __hash__    | Memory block or string to generate the ID from
   2923 /// __len__     | Size of passed memory block or string in __hash__
   2924 /// __seed__    | Seeding value if this function is called in a loop or default to `0`
   2925 ///
   2926 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2927 */
   2928 NK_API nk_bool nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
   2929 /*/// #### nk_tree_image_push
   2930 /// Start a collapsible UI section with image and label header
   2931 /// !!! WARNING
   2932 ///     To keep track of the runtime tree collapsible state this function uses
   2933 ///     defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
   2934 ///     to call this function in a loop please use `nk_tree_image_push_id` or
   2935 ///     `nk_tree_image_push_hashed` instead.
   2936 ///
   2937 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2938 /// #define nk_tree_image_push(ctx, type, img, title, state)
   2939 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2940 //
   2941 /// Parameter   | Description
   2942 /// ------------|-----------------------------------------------------------
   2943 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2944 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2945 /// __img__     | Image to display inside the header on the left of the label
   2946 /// __title__   | Label printed in the tree header
   2947 /// __state__   | Initial tree state value out of nk_collapse_states
   2948 ///
   2949 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2950 */
   2951 #define nk_tree_image_push(ctx, type, img, title, state) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
   2952 /*/// #### nk_tree_image_push_id
   2953 /// Start a collapsible UI section with image and label header and internal state
   2954 /// management callable in a look
   2955 ///
   2956 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2957 /// #define nk_tree_image_push_id(ctx, type, img, title, state, id)
   2958 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2959 ///
   2960 /// Parameter   | Description
   2961 /// ------------|-----------------------------------------------------------
   2962 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2963 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2964 /// __img__     | Image to display inside the header on the left of the label
   2965 /// __title__   | Label printed in the tree header
   2966 /// __state__   | Initial tree state value out of nk_collapse_states
   2967 /// __id__      | Loop counter index if this function is called in a loop
   2968 ///
   2969 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2970 */
   2971 #define nk_tree_image_push_id(ctx, type, img, title, state, id) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
   2972 /*/// #### nk_tree_image_push_hashed
   2973 /// Start a collapsible UI section with internal state management with full
   2974 /// control over internal unique ID used to store state
   2975 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2976 /// nk_bool nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
   2977 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2978 ///
   2979 /// Parameter   | Description
   2980 /// ------------|-----------------------------------------------------------
   2981 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2982 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2983 /// __img__     | Image to display inside the header on the left of the label
   2984 /// __title__   | Label printed in the tree header
   2985 /// __state__   | Initial tree state value out of nk_collapse_states
   2986 /// __hash__    | Memory block or string to generate the ID from
   2987 /// __len__     | Size of passed memory block or string in __hash__
   2988 /// __seed__    | Seeding value if this function is called in a loop or default to `0`
   2989 ///
   2990 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2991 */
   2992 NK_API nk_bool nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
   2993 /*/// #### nk_tree_pop
   2994 /// Ends a collapsabale UI section
   2995 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2996 /// void nk_tree_pop(struct nk_context*);
   2997 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2998 ///
   2999 /// Parameter   | Description
   3000 /// ------------|-----------------------------------------------------------
   3001 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
   3002 */
   3003 NK_API void nk_tree_pop(struct nk_context*);
   3004 /*/// #### nk_tree_state_push
   3005 /// Start a collapsible UI section with external state management
   3006 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3007 /// nk_bool nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
   3008 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3009 ///
   3010 /// Parameter   | Description
   3011 /// ------------|-----------------------------------------------------------
   3012 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
   3013 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   3014 /// __title__   | Label printed in the tree header
   3015 /// __state__   | Persistent state to update
   3016 ///
   3017 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   3018 */
   3019 NK_API nk_bool nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
   3020 /*/// #### nk_tree_state_image_push
   3021 /// Start a collapsible UI section with image and label header and external state management
   3022 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3023 /// nk_bool nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
   3024 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3025 ///
   3026 /// Parameter   | Description
   3027 /// ------------|-----------------------------------------------------------
   3028 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
   3029 /// __img__     | Image to display inside the header on the left of the label
   3030 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   3031 /// __title__   | Label printed in the tree header
   3032 /// __state__   | Persistent state to update
   3033 ///
   3034 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   3035 */
   3036 NK_API nk_bool nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
   3037 /*/// #### nk_tree_state_pop
   3038 /// Ends a collapsabale UI section
   3039 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3040 /// void nk_tree_state_pop(struct nk_context*);
   3041 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3042 ///
   3043 /// Parameter   | Description
   3044 /// ------------|-----------------------------------------------------------
   3045 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
   3046 */
   3047 NK_API void nk_tree_state_pop(struct nk_context*);
   3048 
   3049 #define nk_tree_element_push(ctx, type, title, state, sel) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
   3050 #define nk_tree_element_push_id(ctx, type, title, state, sel, id) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
   3051 NK_API nk_bool nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, const char *hash, int len, int seed);
   3052 NK_API nk_bool nk_tree_element_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, const char *hash, int len,int seed);
   3053 NK_API void nk_tree_element_pop(struct nk_context*);
   3054 
   3055 /* =============================================================================
   3056  *
   3057  *                                  LIST VIEW
   3058  *
   3059  * ============================================================================= */
   3060 struct nk_list_view {
   3061 /* public: */
   3062     int begin, end, count;
   3063 /* private: */
   3064     int total_height;
   3065     struct nk_context *ctx;
   3066     nk_uint *scroll_pointer;
   3067     nk_uint scroll_value;
   3068 };
   3069 NK_API nk_bool nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
   3070 NK_API void nk_list_view_end(struct nk_list_view*);
   3071 /* =============================================================================
   3072  *
   3073  *                                  WIDGET
   3074  *
   3075  * ============================================================================= */
   3076 enum nk_widget_layout_states {
   3077     NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
   3078     NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
   3079     NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
   3080 };
   3081 enum nk_widget_states {
   3082     NK_WIDGET_STATE_MODIFIED    = NK_FLAG(1),
   3083     NK_WIDGET_STATE_INACTIVE    = NK_FLAG(2), /* widget is neither active nor hovered */
   3084     NK_WIDGET_STATE_ENTERED     = NK_FLAG(3), /* widget has been hovered on the current frame */
   3085     NK_WIDGET_STATE_HOVER       = NK_FLAG(4), /* widget is being hovered */
   3086     NK_WIDGET_STATE_ACTIVED     = NK_FLAG(5),/* widget is currently activated */
   3087     NK_WIDGET_STATE_LEFT        = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
   3088     NK_WIDGET_STATE_HOVERED     = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */
   3089     NK_WIDGET_STATE_ACTIVE      = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */
   3090 };
   3091 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
   3092 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2);
   3093 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
   3094 NK_API struct nk_vec2 nk_widget_position(struct nk_context*);
   3095 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
   3096 NK_API float nk_widget_width(struct nk_context*);
   3097 NK_API float nk_widget_height(struct nk_context*);
   3098 NK_API nk_bool nk_widget_is_hovered(struct nk_context*);
   3099 NK_API nk_bool nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons);
   3100 NK_API nk_bool nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, nk_bool down);
   3101 NK_API void nk_spacing(struct nk_context*, int cols);
   3102 /* =============================================================================
   3103  *
   3104  *                                  TEXT
   3105  *
   3106  * ============================================================================= */
   3107 enum nk_text_align {
   3108     NK_TEXT_ALIGN_LEFT        = 0x01,
   3109     NK_TEXT_ALIGN_CENTERED    = 0x02,
   3110     NK_TEXT_ALIGN_RIGHT       = 0x04,
   3111     NK_TEXT_ALIGN_TOP         = 0x08,
   3112     NK_TEXT_ALIGN_MIDDLE      = 0x10,
   3113     NK_TEXT_ALIGN_BOTTOM      = 0x20
   3114 };
   3115 enum nk_text_alignment {
   3116     NK_TEXT_LEFT        = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT,
   3117     NK_TEXT_CENTERED    = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED,
   3118     NK_TEXT_RIGHT       = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT
   3119 };
   3120 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
   3121 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
   3122 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
   3123 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
   3124 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
   3125 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
   3126 NK_API void nk_label_wrap(struct nk_context*, const char*);
   3127 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
   3128 NK_API void nk_image(struct nk_context*, struct nk_image);
   3129 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color);
   3130 #ifdef NK_INCLUDE_STANDARD_VARARGS
   3131 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3);
   3132 NK_API void nk_labelf_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(4);
   3133 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2);
   3134 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3);
   3135 NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
   3136 NK_API void nk_labelfv_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(4);
   3137 NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
   3138 NK_API void nk_labelfv_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
   3139 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
   3140 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
   3141 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
   3142 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
   3143 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
   3144 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
   3145 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
   3146 #endif
   3147 /* =============================================================================
   3148  *
   3149  *                                  BUTTON
   3150  *
   3151  * ============================================================================= */
   3152 NK_API nk_bool nk_button_text(struct nk_context*, const char *title, int len);
   3153 NK_API nk_bool nk_button_label(struct nk_context*, const char *title);
   3154 NK_API nk_bool nk_button_color(struct nk_context*, struct nk_color);
   3155 NK_API nk_bool nk_button_symbol(struct nk_context*, enum nk_symbol_type);
   3156 NK_API nk_bool nk_button_image(struct nk_context*, struct nk_image img);
   3157 NK_API nk_bool nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
   3158 NK_API nk_bool nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3159 NK_API nk_bool nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
   3160 NK_API nk_bool nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
   3161 NK_API nk_bool nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
   3162 NK_API nk_bool nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
   3163 NK_API nk_bool nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
   3164 NK_API nk_bool nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
   3165 NK_API nk_bool nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3166 NK_API nk_bool nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
   3167 NK_API nk_bool nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
   3168 NK_API nk_bool nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
   3169 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior);
   3170 NK_API nk_bool nk_button_push_behavior(struct nk_context*, enum nk_button_behavior);
   3171 NK_API nk_bool nk_button_pop_behavior(struct nk_context*);
   3172 /* =============================================================================
   3173  *
   3174  *                                  CHECKBOX
   3175  *
   3176  * ============================================================================= */
   3177 NK_API nk_bool nk_check_label(struct nk_context*, const char*, nk_bool active);
   3178 NK_API nk_bool nk_check_text(struct nk_context*, const char*, int, nk_bool active);
   3179 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
   3180 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
   3181 NK_API nk_bool nk_checkbox_label(struct nk_context*, const char*, nk_bool *active);
   3182 NK_API nk_bool nk_checkbox_text(struct nk_context*, const char*, int, nk_bool *active);
   3183 NK_API nk_bool nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
   3184 NK_API nk_bool nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
   3185 /* =============================================================================
   3186  *
   3187  *                                  RADIO BUTTON
   3188  *
   3189  * ============================================================================= */
   3190 NK_API nk_bool nk_radio_label(struct nk_context*, const char*, nk_bool *active);
   3191 NK_API nk_bool nk_radio_text(struct nk_context*, const char*, int, nk_bool *active);
   3192 NK_API nk_bool nk_option_label(struct nk_context*, const char*, nk_bool active);
   3193 NK_API nk_bool nk_option_text(struct nk_context*, const char*, int, nk_bool active);
   3194 /* =============================================================================
   3195  *
   3196  *                                  SELECTABLE
   3197  *
   3198  * ============================================================================= */
   3199 NK_API nk_bool nk_selectable_label(struct nk_context*, const char*, nk_flags align, nk_bool *value);
   3200 NK_API nk_bool nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, nk_bool *value);
   3201 NK_API nk_bool nk_selectable_image_label(struct nk_context*,struct nk_image,  const char*, nk_flags align, nk_bool *value);
   3202 NK_API nk_bool nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, nk_bool *value);
   3203 NK_API nk_bool nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type,  const char*, nk_flags align, nk_bool *value);
   3204 NK_API nk_bool nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, nk_bool *value);
   3205 
   3206 NK_API nk_bool nk_select_label(struct nk_context*, const char*, nk_flags align, nk_bool value);
   3207 NK_API nk_bool nk_select_text(struct nk_context*, const char*, int, nk_flags align, nk_bool value);
   3208 NK_API nk_bool nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, nk_bool value);
   3209 NK_API nk_bool nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, nk_bool value);
   3210 NK_API nk_bool nk_select_symbol_label(struct nk_context*,enum nk_symbol_type,  const char*, nk_flags align, nk_bool value);
   3211 NK_API nk_bool nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, nk_bool value);
   3212 
   3213 /* =============================================================================
   3214  *
   3215  *                                  SLIDER
   3216  *
   3217  * ============================================================================= */
   3218 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
   3219 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
   3220 NK_API nk_bool nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
   3221 NK_API nk_bool nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
   3222 /* =============================================================================
   3223  *
   3224  *                                  PROGRESSBAR
   3225  *
   3226  * ============================================================================= */
   3227 NK_API nk_bool nk_progress(struct nk_context*, nk_size *cur, nk_size max, nk_bool modifyable);
   3228 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, nk_bool modifyable);
   3229 
   3230 /* =============================================================================
   3231  *
   3232  *                                  COLOR PICKER
   3233  *
   3234  * ============================================================================= */
   3235 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format);
   3236 NK_API nk_bool nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format);
   3237 /* =============================================================================
   3238  *
   3239  *                                  PROPERTIES
   3240  *
   3241  * =============================================================================
   3242 /// ### Properties
   3243 /// Properties are the main value modification widgets in Nuklear. Changing a value
   3244 /// can be achieved by dragging, adding/removing incremental steps on button click
   3245 /// or by directly typing a number.
   3246 ///
   3247 /// #### Usage
   3248 /// Each property requires a unique name for identification that is also used for
   3249 /// displaying a label. If you want to use the same name multiple times make sure
   3250 /// add a '#' before your name. The '#' will not be shown but will generate a
   3251 /// unique ID. Each property also takes in a minimum and maximum value. If you want
   3252 /// to make use of the complete number range of a type just use the provided
   3253 /// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for
   3254 /// `nk_property_int` and `nk_propertyi`. In additional each property takes in
   3255 /// a increment value that will be added or subtracted if either the increment
   3256 /// decrement button is clicked. Finally there is a value for increment per pixel
   3257 /// dragged that is added or subtracted from the value.
   3258 ///
   3259 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3260 /// int value = 0;
   3261 /// struct nk_context ctx;
   3262 /// nk_init_xxx(&ctx, ...);
   3263 /// while (1) {
   3264 ///     // Input
   3265 ///     Event evt;
   3266 ///     nk_input_begin(&ctx);
   3267 ///     while (GetEvent(&evt)) {
   3268 ///         if (evt.type == MOUSE_MOVE)
   3269 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
   3270 ///         else if (evt.type == [...]) {
   3271 ///             nk_input_xxx(...);
   3272 ///         }
   3273 ///     }
   3274 ///     nk_input_end(&ctx);
   3275 ///     //
   3276 ///     // Window
   3277 ///     if (nk_begin_xxx(...) {
   3278 ///         // Property
   3279 ///         nk_layout_row_dynamic(...);
   3280 ///         nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1);
   3281 ///     }
   3282 ///     nk_end(ctx);
   3283 ///     //
   3284 ///     // Draw
   3285 ///     const struct nk_command *cmd = 0;
   3286 ///     nk_foreach(cmd, &ctx) {
   3287 ///     switch (cmd->type) {
   3288 ///     case NK_COMMAND_LINE:
   3289 ///         your_draw_line_function(...)
   3290 ///         break;
   3291 ///     case NK_COMMAND_RECT
   3292 ///         your_draw_rect_function(...)
   3293 ///         break;
   3294 ///     case ...:
   3295 ///         // [...]
   3296 ///     }
   3297 ///     nk_clear(&ctx);
   3298 /// }
   3299 /// nk_free(&ctx);
   3300 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3301 ///
   3302 /// #### Reference
   3303 /// Function            | Description
   3304 /// --------------------|-------------------------------------------
   3305 /// nk_property_int     | Integer property directly modifying a passed in value
   3306 /// nk_property_float   | Float property directly modifying a passed in value
   3307 /// nk_property_double  | Double property directly modifying a passed in value
   3308 /// nk_propertyi        | Integer property returning the modified int value
   3309 /// nk_propertyf        | Float property returning the modified float value
   3310 /// nk_propertyd        | Double property returning the modified double value
   3311 ///
   3312 */
   3313 /*/// #### nk_property_int
   3314 /// Integer property directly modifying a passed in value
   3315 /// !!! WARNING
   3316 ///     To generate a unique property ID using the same label make sure to insert
   3317 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3318 ///
   3319 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3320 /// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
   3321 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3322 ///
   3323 /// Parameter           | Description
   3324 /// --------------------|-----------------------------------------------------------
   3325 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3326 /// __name__            | String used both as a label as well as a unique identifier
   3327 /// __min__             | Minimum value not allowed to be underflown
   3328 /// __val__             | Integer pointer to be modified
   3329 /// __max__             | Maximum value not allowed to be overflown
   3330 /// __step__            | Increment added and subtracted on increment and decrement button
   3331 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3332 */
   3333 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
   3334 /*/// #### nk_property_float
   3335 /// Float property directly modifying a passed in value
   3336 /// !!! WARNING
   3337 ///     To generate a unique property ID using the same label make sure to insert
   3338 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3339 ///
   3340 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3341 /// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
   3342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3343 ///
   3344 /// Parameter           | Description
   3345 /// --------------------|-----------------------------------------------------------
   3346 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3347 /// __name__            | String used both as a label as well as a unique identifier
   3348 /// __min__             | Minimum value not allowed to be underflown
   3349 /// __val__             | Float pointer to be modified
   3350 /// __max__             | Maximum value not allowed to be overflown
   3351 /// __step__            | Increment added and subtracted on increment and decrement button
   3352 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3353 */
   3354 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
   3355 /*/// #### nk_property_double
   3356 /// Double property directly modifying a passed in value
   3357 /// !!! WARNING
   3358 ///     To generate a unique property ID using the same label make sure to insert
   3359 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3360 ///
   3361 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3362 /// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel);
   3363 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3364 ///
   3365 /// Parameter           | Description
   3366 /// --------------------|-----------------------------------------------------------
   3367 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3368 /// __name__            | String used both as a label as well as a unique identifier
   3369 /// __min__             | Minimum value not allowed to be underflown
   3370 /// __val__             | Double pointer to be modified
   3371 /// __max__             | Maximum value not allowed to be overflown
   3372 /// __step__            | Increment added and subtracted on increment and decrement button
   3373 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3374 */
   3375 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
   3376 /*/// #### nk_propertyi
   3377 /// Integer property modifying a passed in value and returning the new value
   3378 /// !!! WARNING
   3379 ///     To generate a unique property ID using the same label make sure to insert
   3380 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3381 ///
   3382 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3383 /// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel);
   3384 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3385 ///
   3386 /// Parameter           | Description
   3387 /// --------------------|-----------------------------------------------------------
   3388 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3389 /// __name__            | String used both as a label as well as a unique identifier
   3390 /// __min__             | Minimum value not allowed to be underflown
   3391 /// __val__             | Current integer value to be modified and returned
   3392 /// __max__             | Maximum value not allowed to be overflown
   3393 /// __step__            | Increment added and subtracted on increment and decrement button
   3394 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3395 ///
   3396 /// Returns the new modified integer value
   3397 */
   3398 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
   3399 /*/// #### nk_propertyf
   3400 /// Float property modifying a passed in value and returning the new value
   3401 /// !!! WARNING
   3402 ///     To generate a unique property ID using the same label make sure to insert
   3403 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3404 ///
   3405 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3406 /// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel);
   3407 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3408 ///
   3409 /// Parameter           | Description
   3410 /// --------------------|-----------------------------------------------------------
   3411 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3412 /// __name__            | String used both as a label as well as a unique identifier
   3413 /// __min__             | Minimum value not allowed to be underflown
   3414 /// __val__             | Current float value to be modified and returned
   3415 /// __max__             | Maximum value not allowed to be overflown
   3416 /// __step__            | Increment added and subtracted on increment and decrement button
   3417 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3418 ///
   3419 /// Returns the new modified float value
   3420 */
   3421 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
   3422 /*/// #### nk_propertyd
   3423 /// Float property modifying a passed in value and returning the new value
   3424 /// !!! WARNING
   3425 ///     To generate a unique property ID using the same label make sure to insert
   3426 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3427 ///
   3428 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3429 /// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel);
   3430 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3431 ///
   3432 /// Parameter           | Description
   3433 /// --------------------|-----------------------------------------------------------
   3434 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3435 /// __name__            | String used both as a label as well as a unique identifier
   3436 /// __min__             | Minimum value not allowed to be underflown
   3437 /// __val__             | Current double value to be modified and returned
   3438 /// __max__             | Maximum value not allowed to be overflown
   3439 /// __step__            | Increment added and subtracted on increment and decrement button
   3440 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3441 ///
   3442 /// Returns the new modified double value
   3443 */
   3444 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
   3445 /* =============================================================================
   3446  *
   3447  *                                  TEXT EDIT
   3448  *
   3449  * ============================================================================= */
   3450 enum nk_edit_flags {
   3451     NK_EDIT_DEFAULT                 = 0,
   3452     NK_EDIT_READ_ONLY               = NK_FLAG(0),
   3453     NK_EDIT_AUTO_SELECT             = NK_FLAG(1),
   3454     NK_EDIT_SIG_ENTER               = NK_FLAG(2),
   3455     NK_EDIT_ALLOW_TAB               = NK_FLAG(3),
   3456     NK_EDIT_NO_CURSOR               = NK_FLAG(4),
   3457     NK_EDIT_SELECTABLE              = NK_FLAG(5),
   3458     NK_EDIT_CLIPBOARD               = NK_FLAG(6),
   3459     NK_EDIT_CTRL_ENTER_NEWLINE      = NK_FLAG(7),
   3460     NK_EDIT_NO_HORIZONTAL_SCROLL    = NK_FLAG(8),
   3461     NK_EDIT_ALWAYS_INSERT_MODE      = NK_FLAG(9),
   3462     NK_EDIT_MULTILINE               = NK_FLAG(10),
   3463     NK_EDIT_GOTO_END_ON_ACTIVATE    = NK_FLAG(11)
   3464 };
   3465 enum nk_edit_types {
   3466     NK_EDIT_SIMPLE  = NK_EDIT_ALWAYS_INSERT_MODE,
   3467     NK_EDIT_FIELD   = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD,
   3468     NK_EDIT_BOX     = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD,
   3469     NK_EDIT_EDITOR  = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD
   3470 };
   3471 enum nk_edit_events {
   3472     NK_EDIT_ACTIVE      = NK_FLAG(0), /* edit widget is currently being modified */
   3473     NK_EDIT_INACTIVE    = NK_FLAG(1), /* edit widget is not active and is not being modified */
   3474     NK_EDIT_ACTIVATED   = NK_FLAG(2), /* edit widget went from state inactive to state active */
   3475     NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
   3476     NK_EDIT_COMMITED    = NK_FLAG(4) /* edit widget has received an enter and lost focus */
   3477 };
   3478 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
   3479 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
   3480 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
   3481 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
   3482 NK_API void nk_edit_unfocus(struct nk_context*);
   3483 /* =============================================================================
   3484  *
   3485  *                                  CHART
   3486  *
   3487  * ============================================================================= */
   3488 NK_API nk_bool nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
   3489 NK_API nk_bool nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
   3490 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
   3491 NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value);
   3492 NK_API nk_flags nk_chart_push(struct nk_context*, float);
   3493 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
   3494 NK_API void nk_chart_end(struct nk_context*);
   3495 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
   3496 NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset);
   3497 /* =============================================================================
   3498  *
   3499  *                                  POPUP
   3500  *
   3501  * ============================================================================= */
   3502 NK_API nk_bool nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
   3503 NK_API void nk_popup_close(struct nk_context*);
   3504 NK_API void nk_popup_end(struct nk_context*);
   3505 NK_API void nk_popup_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
   3506 NK_API void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
   3507 /* =============================================================================
   3508  *
   3509  *                                  COMBOBOX
   3510  *
   3511  * ============================================================================= */
   3512 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
   3513 NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size);
   3514 NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size);
   3515 NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size);
   3516 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
   3517 NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size);
   3518 NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size);
   3519 NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size);
   3520 /* =============================================================================
   3521  *
   3522  *                                  ABSTRACT COMBOBOX
   3523  *
   3524  * ============================================================================= */
   3525 NK_API nk_bool nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
   3526 NK_API nk_bool nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
   3527 NK_API nk_bool nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
   3528 NK_API nk_bool nk_combo_begin_symbol(struct nk_context*,  enum nk_symbol_type,  struct nk_vec2 size);
   3529 NK_API nk_bool nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
   3530 NK_API nk_bool nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
   3531 NK_API nk_bool nk_combo_begin_image(struct nk_context*, struct nk_image img,  struct nk_vec2 size);
   3532 NK_API nk_bool nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
   3533 NK_API nk_bool nk_combo_begin_image_text(struct nk_context*,  const char *selected, int, struct nk_image, struct nk_vec2 size);
   3534 NK_API nk_bool nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
   3535 NK_API nk_bool nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
   3536 NK_API nk_bool nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
   3537 NK_API nk_bool nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
   3538 NK_API nk_bool nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
   3539 NK_API nk_bool nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3540 NK_API void nk_combo_close(struct nk_context*);
   3541 NK_API void nk_combo_end(struct nk_context*);
   3542 /* =============================================================================
   3543  *
   3544  *                                  CONTEXTUAL
   3545  *
   3546  * ============================================================================= */
   3547 NK_API nk_bool nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
   3548 NK_API nk_bool nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
   3549 NK_API nk_bool nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
   3550 NK_API nk_bool nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
   3551 NK_API nk_bool nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
   3552 NK_API nk_bool nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
   3553 NK_API nk_bool nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3554 NK_API void nk_contextual_close(struct nk_context*);
   3555 NK_API void nk_contextual_end(struct nk_context*);
   3556 /* =============================================================================
   3557  *
   3558  *                                  TOOLTIP
   3559  *
   3560  * ============================================================================= */
   3561 NK_API void nk_tooltip(struct nk_context*, const char*);
   3562 #ifdef NK_INCLUDE_STANDARD_VARARGS
   3563 NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2);
   3564 NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
   3565 #endif
   3566 NK_API nk_bool nk_tooltip_begin(struct nk_context*, float width);
   3567 NK_API void nk_tooltip_end(struct nk_context*);
   3568 /* =============================================================================
   3569  *
   3570  *                                  MENU
   3571  *
   3572  * ============================================================================= */
   3573 NK_API void nk_menubar_begin(struct nk_context*);
   3574 NK_API void nk_menubar_end(struct nk_context*);
   3575 NK_API nk_bool nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
   3576 NK_API nk_bool nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
   3577 NK_API nk_bool nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
   3578 NK_API nk_bool nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
   3579 NK_API nk_bool nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
   3580 NK_API nk_bool nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
   3581 NK_API nk_bool nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
   3582 NK_API nk_bool nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
   3583 NK_API nk_bool nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
   3584 NK_API nk_bool nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
   3585 NK_API nk_bool nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
   3586 NK_API nk_bool nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
   3587 NK_API nk_bool nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3588 NK_API nk_bool nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
   3589 NK_API void nk_menu_close(struct nk_context*);
   3590 NK_API void nk_menu_end(struct nk_context*);
   3591 /* =============================================================================
   3592  *
   3593  *                                  STYLE
   3594  *
   3595  * ============================================================================= */
   3596 enum nk_style_colors {
   3597     NK_COLOR_TEXT,
   3598     NK_COLOR_WINDOW,
   3599     NK_COLOR_HEADER,
   3600     NK_COLOR_BORDER,
   3601     NK_COLOR_BUTTON,
   3602     NK_COLOR_BUTTON_HOVER,
   3603     NK_COLOR_BUTTON_ACTIVE,
   3604     NK_COLOR_TOGGLE,
   3605     NK_COLOR_TOGGLE_HOVER,
   3606     NK_COLOR_TOGGLE_CURSOR,
   3607     NK_COLOR_SELECT,
   3608     NK_COLOR_SELECT_ACTIVE,
   3609     NK_COLOR_SLIDER,
   3610     NK_COLOR_SLIDER_CURSOR,
   3611     NK_COLOR_SLIDER_CURSOR_HOVER,
   3612     NK_COLOR_SLIDER_CURSOR_ACTIVE,
   3613     NK_COLOR_PROPERTY,
   3614     NK_COLOR_EDIT,
   3615     NK_COLOR_EDIT_CURSOR,
   3616     NK_COLOR_COMBO,
   3617     NK_COLOR_CHART,
   3618     NK_COLOR_CHART_COLOR,
   3619     NK_COLOR_CHART_COLOR_HIGHLIGHT,
   3620     NK_COLOR_SCROLLBAR,
   3621     NK_COLOR_SCROLLBAR_CURSOR,
   3622     NK_COLOR_SCROLLBAR_CURSOR_HOVER,
   3623     NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,
   3624     NK_COLOR_TAB_HEADER,
   3625     NK_COLOR_COUNT
   3626 };
   3627 enum nk_style_cursor {
   3628     NK_CURSOR_ARROW,
   3629     NK_CURSOR_TEXT,
   3630     NK_CURSOR_MOVE,
   3631     NK_CURSOR_RESIZE_VERTICAL,
   3632     NK_CURSOR_RESIZE_HORIZONTAL,
   3633     NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT,
   3634     NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT,
   3635     NK_CURSOR_COUNT
   3636 };
   3637 NK_API void nk_style_default(struct nk_context*);
   3638 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
   3639 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
   3640 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
   3641 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors);
   3642 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
   3643 NK_API nk_bool nk_style_set_cursor(struct nk_context*, enum nk_style_cursor);
   3644 NK_API void nk_style_show_cursor(struct nk_context*);
   3645 NK_API void nk_style_hide_cursor(struct nk_context*);
   3646 
   3647 NK_API nk_bool nk_style_push_font(struct nk_context*, const struct nk_user_font*);
   3648 NK_API nk_bool nk_style_push_float(struct nk_context*, float*, float);
   3649 NK_API nk_bool nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
   3650 NK_API nk_bool nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item);
   3651 NK_API nk_bool nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
   3652 NK_API nk_bool nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
   3653 
   3654 NK_API nk_bool nk_style_pop_font(struct nk_context*);
   3655 NK_API nk_bool nk_style_pop_float(struct nk_context*);
   3656 NK_API nk_bool nk_style_pop_vec2(struct nk_context*);
   3657 NK_API nk_bool nk_style_pop_style_item(struct nk_context*);
   3658 NK_API nk_bool nk_style_pop_flags(struct nk_context*);
   3659 NK_API nk_bool nk_style_pop_color(struct nk_context*);
   3660 /* =============================================================================
   3661  *
   3662  *                                  COLOR
   3663  *
   3664  * ============================================================================= */
   3665 NK_API struct nk_color nk_rgb(int r, int g, int b);
   3666 NK_API struct nk_color nk_rgb_iv(const int *rgb);
   3667 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
   3668 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
   3669 NK_API struct nk_color nk_rgb_fv(const float *rgb);
   3670 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c);
   3671 NK_API struct nk_color nk_rgb_hex(const char *rgb);
   3672 
   3673 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
   3674 NK_API struct nk_color nk_rgba_u32(nk_uint);
   3675 NK_API struct nk_color nk_rgba_iv(const int *rgba);
   3676 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
   3677 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
   3678 NK_API struct nk_color nk_rgba_fv(const float *rgba);
   3679 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c);
   3680 NK_API struct nk_color nk_rgba_hex(const char *rgb);
   3681 
   3682 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a);
   3683 NK_API struct nk_colorf nk_hsva_colorfv(float *c);
   3684 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in);
   3685 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in);
   3686 
   3687 NK_API struct nk_color nk_hsv(int h, int s, int v);
   3688 NK_API struct nk_color nk_hsv_iv(const int *hsv);
   3689 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
   3690 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
   3691 NK_API struct nk_color nk_hsv_fv(const float *hsv);
   3692 
   3693 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
   3694 NK_API struct nk_color nk_hsva_iv(const int *hsva);
   3695 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
   3696 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
   3697 NK_API struct nk_color nk_hsva_fv(const float *hsva);
   3698 
   3699 /* color (conversion nuklear --> user) */
   3700 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
   3701 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
   3702 NK_API struct nk_colorf nk_color_cf(struct nk_color);
   3703 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
   3704 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
   3705 
   3706 NK_API nk_uint nk_color_u32(struct nk_color);
   3707 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
   3708 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
   3709 
   3710 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
   3711 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
   3712 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
   3713 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
   3714 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
   3715 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
   3716 
   3717 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
   3718 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
   3719 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
   3720 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
   3721 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
   3722 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
   3723 /* =============================================================================
   3724  *
   3725  *                                  IMAGE
   3726  *
   3727  * ============================================================================= */
   3728 NK_API nk_handle nk_handle_ptr(void*);
   3729 NK_API nk_handle nk_handle_id(int);
   3730 NK_API struct nk_image nk_image_handle(nk_handle);
   3731 NK_API struct nk_image nk_image_ptr(void*);
   3732 NK_API struct nk_image nk_image_id(int);
   3733 NK_API nk_bool nk_image_is_subimage(const struct nk_image* img);
   3734 NK_API struct nk_image nk_subimage_ptr(void*, nk_ushort w, nk_ushort h, struct nk_rect sub_region);
   3735 NK_API struct nk_image nk_subimage_id(int, nk_ushort w, nk_ushort h, struct nk_rect sub_region);
   3736 NK_API struct nk_image nk_subimage_handle(nk_handle, nk_ushort w, nk_ushort h, struct nk_rect sub_region);
   3737 /* =============================================================================
   3738  *
   3739  *                                  9-SLICE
   3740  *
   3741  * ============================================================================= */
   3742 NK_API struct nk_nine_slice nk_nine_slice_handle(nk_handle, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
   3743 NK_API struct nk_nine_slice nk_nine_slice_ptr(void*, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
   3744 NK_API struct nk_nine_slice nk_nine_slice_id(int, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
   3745 NK_API int nk_nine_slice_is_sub9slice(const struct nk_nine_slice* img);
   3746 NK_API struct nk_nine_slice nk_sub9slice_ptr(void*, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
   3747 NK_API struct nk_nine_slice nk_sub9slice_id(int, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
   3748 NK_API struct nk_nine_slice nk_sub9slice_handle(nk_handle, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
   3749 /* =============================================================================
   3750  *
   3751  *                                  MATH
   3752  *
   3753  * ============================================================================= */
   3754 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
   3755 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
   3756 
   3757 NK_API struct nk_vec2 nk_vec2(float x, float y);
   3758 NK_API struct nk_vec2 nk_vec2i(int x, int y);
   3759 NK_API struct nk_vec2 nk_vec2v(const float *xy);
   3760 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
   3761 
   3762 NK_API struct nk_rect nk_get_null_rect(void);
   3763 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
   3764 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
   3765 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
   3766 NK_API struct nk_rect nk_rectv(const float *xywh);
   3767 NK_API struct nk_rect nk_rectiv(const int *xywh);
   3768 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
   3769 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
   3770 /* =============================================================================
   3771  *
   3772  *                                  STRING
   3773  *
   3774  * ============================================================================= */
   3775 NK_API int nk_strlen(const char *str);
   3776 NK_API int nk_stricmp(const char *s1, const char *s2);
   3777 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
   3778 NK_API int nk_strtoi(const char *str, const char **endptr);
   3779 NK_API float nk_strtof(const char *str, const char **endptr);
   3780 #ifndef NK_STRTOD
   3781 #define NK_STRTOD nk_strtod
   3782 NK_API double nk_strtod(const char *str, const char **endptr);
   3783 #endif
   3784 NK_API int nk_strfilter(const char *text, const char *regexp);
   3785 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
   3786 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
   3787 /* =============================================================================
   3788  *
   3789  *                                  UTF-8
   3790  *
   3791  * ============================================================================= */
   3792 NK_API int nk_utf_decode(const char*, nk_rune*, int);
   3793 NK_API int nk_utf_encode(nk_rune, char*, int);
   3794 NK_API int nk_utf_len(const char*, int byte_len);
   3795 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
   3796 /* ===============================================================
   3797  *
   3798  *                          FONT
   3799  *
   3800  * ===============================================================*/
   3801 /*/// ### Font
   3802 /// Font handling in this library was designed to be quite customizable and lets
   3803 /// you decide what you want to use and what you want to provide. There are three
   3804 /// different ways to use the font atlas. The first two will use your font
   3805 /// handling scheme and only requires essential data to run nuklear. The next
   3806 /// slightly more advanced features is font handling with vertex buffer output.
   3807 /// Finally the most complex API wise is using nuklear's font baking API.
   3808 //
   3809 /// #### Using your own implementation without vertex buffer output
   3810 /// 
   3811 /// So first up the easiest way to do font handling is by just providing a
   3812 /// `nk_user_font` struct which only requires the height in pixel of the used
   3813 /// font and a callback to calculate the width of a string. This way of handling
   3814 /// fonts is best fitted for using the normal draw shape command API where you
   3815 /// do all the text drawing yourself and the library does not require any kind
   3816 /// of deeper knowledge about which font handling mechanism you use.
   3817 /// IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
   3818 /// over the complete life time! I know this sucks but it is currently the only
   3819 /// way to switch between fonts.
   3820 ///
   3821 /// ```c
   3822 ///     float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
   3823 ///     {
   3824 ///         your_font_type *type = handle.ptr;
   3825 ///         float text_width = ...;
   3826 ///         return text_width;
   3827 ///     }
   3828 ///
   3829 ///     struct nk_user_font font;
   3830 ///     font.userdata.ptr = &your_font_class_or_struct;
   3831 ///     font.height = your_font_height;
   3832 ///     font.width = your_text_width_calculation;
   3833 /// 
   3834 ///     struct nk_context ctx;
   3835 ///     nk_init_default(&ctx, &font);
   3836 /// ```
   3837 /// #### Using your own implementation with vertex buffer output
   3838 /// 
   3839 /// While the first approach works fine if you don't want to use the optional
   3840 /// vertex buffer output it is not enough if you do. To get font handling working
   3841 /// for these cases you have to provide two additional parameters inside the
   3842 /// `nk_user_font`. First a texture atlas handle used to draw text as subimages
   3843 /// of a bigger font atlas texture and a callback to query a character's glyph
   3844 /// information (offset, size, ...). So it is still possible to provide your own
   3845 /// font and use the vertex buffer output.
   3846 ///
   3847 /// ```c
   3848 ///     float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
   3849 ///     {
   3850 ///         your_font_type *type = handle.ptr;
   3851 ///         float text_width = ...;
   3852 ///         return text_width;
   3853 ///     }
   3854 ///     void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
   3855 ///     {
   3856 ///         your_font_type *type = handle.ptr;
   3857 ///         glyph.width = ...;
   3858 ///         glyph.height = ...;
   3859 ///         glyph.xadvance = ...;
   3860 ///         glyph.uv[0].x = ...;
   3861 ///         glyph.uv[0].y = ...;
   3862 ///         glyph.uv[1].x = ...;
   3863 ///         glyph.uv[1].y = ...;
   3864 ///         glyph.offset.x = ...;
   3865 ///         glyph.offset.y = ...;
   3866 ///     }
   3867 /// 
   3868 ///     struct nk_user_font font;
   3869 ///     font.userdata.ptr = &your_font_class_or_struct;
   3870 ///     font.height = your_font_height;
   3871 ///     font.width = your_text_width_calculation;
   3872 ///     font.query = query_your_font_glyph;
   3873 ///     font.texture.id = your_font_texture;
   3874 /// 
   3875 ///     struct nk_context ctx;
   3876 ///     nk_init_default(&ctx, &font);
   3877 /// ```
   3878 ///
   3879 /// #### Nuklear font baker
   3880 /// 
   3881 /// The final approach if you do not have a font handling functionality or don't
   3882 /// want to use it in this library is by using the optional font baker.
   3883 /// The font baker APIs can be used to create a font plus font atlas texture
   3884 /// and can be used with or without the vertex buffer output.
   3885 /// 
   3886 /// It still uses the `nk_user_font` struct and the two different approaches
   3887 /// previously stated still work. The font baker is not located inside
   3888 /// `nk_context` like all other systems since it can be understood as more of
   3889 /// an extension to nuklear and does not really depend on any `nk_context` state.
   3890 /// 
   3891 /// Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
   3892 /// functions. If you don't care about memory just call the default version
   3893 /// `nk_font_atlas_init_default` which will allocate all memory from the standard library.
   3894 /// If you want to control memory allocation but you don't care if the allocated
   3895 /// memory is temporary and therefore can be freed directly after the baking process
   3896 /// is over or permanent you can call `nk_font_atlas_init`.
   3897 /// 
   3898 /// After successfully initializing the font baker you can add Truetype(.ttf) fonts from
   3899 /// different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
   3900 /// functions. Adding font will permanently store each font, font config and ttf memory block(!)
   3901 /// inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
   3902 /// the font baker by for example adding additional fonts you can call
   3903 /// `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
   3904 /// 
   3905 /// As soon as you added all fonts you wanted you can now start the baking process
   3906 /// for every selected glyph to image by calling `nk_font_atlas_bake`.
   3907 /// The baking process returns image memory, width and height which can be used to
   3908 /// either create your own image object or upload it to any graphics library.
   3909 /// No matter which case you finally have to call `nk_font_atlas_end` which
   3910 /// will free all temporary memory including the font atlas image so make sure
   3911 /// you created our texture beforehand. `nk_font_atlas_end` requires a handle
   3912 /// to your font texture or object and optionally fills a `struct nk_draw_null_texture`
   3913 /// which can be used for the optional vertex output. If you don't want it just
   3914 /// set the argument to `NULL`.
   3915 /// 
   3916 /// At this point you are done and if you don't want to reuse the font atlas you
   3917 /// can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
   3918 /// memory. Finally if you don't use the font atlas and any of it's fonts anymore
   3919 /// you need to call `nk_font_atlas_clear` to free all memory still being used.
   3920 /// 
   3921 /// ```c
   3922 ///     struct nk_font_atlas atlas;
   3923 ///     nk_font_atlas_init_default(&atlas);
   3924 ///     nk_font_atlas_begin(&atlas);
   3925 ///     nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
   3926 ///     nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
   3927 ///     const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
   3928 ///     nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
   3929 /// 
   3930 ///     struct nk_context ctx;
   3931 ///     nk_init_default(&ctx, &font->handle);
   3932 ///     while (1) {
   3933 /// 
   3934 ///     }
   3935 ///     nk_font_atlas_clear(&atlas);
   3936 /// ```
   3937 /// The font baker API is probably the most complex API inside this library and
   3938 /// I would suggest reading some of my examples `example/` to get a grip on how
   3939 /// to use the font atlas. There are a number of details I left out. For example
   3940 /// how to merge fonts, configure a font with `nk_font_config` to use other languages,
   3941 /// use another texture coordinate format and a lot more:
   3942 ///
   3943 /// ```c
   3944 ///     struct nk_font_config cfg = nk_font_config(font_pixel_height);
   3945 ///     cfg.merge_mode = nk_false or nk_true;
   3946 ///     cfg.range = nk_font_korean_glyph_ranges();
   3947 ///     cfg.coord_type = NK_COORD_PIXEL;
   3948 ///     nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
   3949 /// ```
   3950 */
   3951 struct nk_user_font_glyph;
   3952 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
   3953 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
   3954                                     struct nk_user_font_glyph *glyph,
   3955                                     nk_rune codepoint, nk_rune next_codepoint);
   3956 
   3957 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT)
   3958 struct nk_user_font_glyph {
   3959     struct nk_vec2 uv[2];
   3960     /* texture coordinates */
   3961     struct nk_vec2 offset;
   3962     /* offset between top left and glyph */
   3963     float width, height;
   3964     /* size of the glyph  */
   3965     float xadvance;
   3966     /* offset to the next glyph */
   3967 };
   3968 #endif
   3969 
   3970 struct nk_user_font {
   3971     nk_handle userdata;
   3972     /* user provided font handle */
   3973     float height;
   3974     /* max height of the font */
   3975     nk_text_width_f width;
   3976     /* font string width in pixel callback */
   3977 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   3978     nk_query_font_glyph_f query;
   3979     /* font glyph callback to query drawing info */
   3980     nk_handle texture;
   3981     /* texture handle to the used font atlas or texture */
   3982 #endif
   3983 };
   3984 
   3985 #ifdef NK_INCLUDE_FONT_BAKING
   3986 enum nk_font_coord_type {
   3987     NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
   3988     NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
   3989 };
   3990 
   3991 struct nk_font;
   3992 struct nk_baked_font {
   3993     float height;
   3994     /* height of the font  */
   3995     float ascent, descent;
   3996     /* font glyphs ascent and descent  */
   3997     nk_rune glyph_offset;
   3998     /* glyph array offset inside the font glyph baking output array  */
   3999     nk_rune glyph_count;
   4000     /* number of glyphs of this font inside the glyph baking array output */
   4001     const nk_rune *ranges;
   4002     /* font codepoint ranges as pairs of (from/to) and 0 as last element */
   4003 };
   4004 
   4005 struct nk_font_config {
   4006     struct nk_font_config *next;
   4007     /* NOTE: only used internally */
   4008     void *ttf_blob;
   4009     /* pointer to loaded TTF file memory block.
   4010      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
   4011     nk_size ttf_size;
   4012     /* size of the loaded TTF file memory block
   4013      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
   4014 
   4015     unsigned char ttf_data_owned_by_atlas;
   4016     /* used inside font atlas: default to: 0*/
   4017     unsigned char merge_mode;
   4018     /* merges this font into the last font */
   4019     unsigned char pixel_snap;
   4020     /* align every character to pixel boundary (if true set oversample (1,1)) */
   4021     unsigned char oversample_v, oversample_h;
   4022     /* rasterize at high quality for sub-pixel position */
   4023     unsigned char padding[3];
   4024 
   4025     float size;
   4026     /* baked pixel height of the font */
   4027     enum nk_font_coord_type coord_type;
   4028     /* texture coordinate format with either pixel or UV coordinates */
   4029     struct nk_vec2 spacing;
   4030     /* extra pixel spacing between glyphs  */
   4031     const nk_rune *range;
   4032     /* list of unicode ranges (2 values per range, zero terminated) */
   4033     struct nk_baked_font *font;
   4034     /* font to setup in the baking process: NOTE: not needed for font atlas */
   4035     nk_rune fallback_glyph;
   4036     /* fallback glyph to use if a given rune is not found */
   4037     struct nk_font_config *n;
   4038     struct nk_font_config *p;
   4039 };
   4040 
   4041 struct nk_font_glyph {
   4042     nk_rune codepoint;
   4043     float xadvance;
   4044     float x0, y0, x1, y1, w, h;
   4045     float u0, v0, u1, v1;
   4046 };
   4047 
   4048 struct nk_font {
   4049     struct nk_font *next;
   4050     struct nk_user_font handle;
   4051     struct nk_baked_font info;
   4052     float scale;
   4053     struct nk_font_glyph *glyphs;
   4054     const struct nk_font_glyph *fallback;
   4055     nk_rune fallback_codepoint;
   4056     nk_handle texture;
   4057     struct nk_font_config *config;
   4058 };
   4059 
   4060 enum nk_font_atlas_format {
   4061     NK_FONT_ATLAS_ALPHA8,
   4062     NK_FONT_ATLAS_RGBA32
   4063 };
   4064 
   4065 struct nk_font_atlas {
   4066     void *pixel;
   4067     int tex_width;
   4068     int tex_height;
   4069 
   4070     struct nk_allocator permanent;
   4071     struct nk_allocator temporary;
   4072 
   4073     struct nk_recti custom;
   4074     struct nk_cursor cursors[NK_CURSOR_COUNT];
   4075 
   4076     int glyph_count;
   4077     struct nk_font_glyph *glyphs;
   4078     struct nk_font *default_font;
   4079     struct nk_font *fonts;
   4080     struct nk_font_config *config;
   4081     int font_num;
   4082 };
   4083 
   4084 /* some language glyph codepoint ranges */
   4085 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
   4086 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
   4087 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
   4088 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
   4089 
   4090 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   4091 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
   4092 #endif
   4093 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
   4094 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
   4095 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
   4096 NK_API struct nk_font_config nk_font_config(float pixel_height);
   4097 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
   4098 #ifdef NK_INCLUDE_DEFAULT_FONT
   4099 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
   4100 #endif
   4101 NK_API struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config);
   4102 #ifdef NK_INCLUDE_STANDARD_IO
   4103 NK_API struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*);
   4104 #endif
   4105 NK_API struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*);
   4106 NK_API struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config);
   4107 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
   4108 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
   4109 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
   4110 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
   4111 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
   4112 
   4113 #endif
   4114 
   4115 /* ==============================================================
   4116  *
   4117  *                          MEMORY BUFFER
   4118  *
   4119  * ===============================================================*/
   4120 /*/// ### Memory Buffer
   4121 /// A basic (double)-buffer with linear allocation and resetting as only
   4122 /// freeing policy. The buffer's main purpose is to control all memory management
   4123 /// inside the GUI toolkit and still leave memory control as much as possible in
   4124 /// the hand of the user while also making sure the library is easy to use if
   4125 /// not as much control is needed.
   4126 /// In general all memory inside this library can be provided from the user in
   4127 /// three different ways.
   4128 /// 
   4129 /// The first way and the one providing most control is by just passing a fixed
   4130 /// size memory block. In this case all control lies in the hand of the user
   4131 /// since he can exactly control where the memory comes from and how much memory
   4132 /// the library should consume. Of course using the fixed size API removes the
   4133 /// ability to automatically resize a buffer if not enough memory is provided so
   4134 /// you have to take over the resizing. While being a fixed sized buffer sounds
   4135 /// quite limiting, it is very effective in this library since the actual memory
   4136 /// consumption is quite stable and has a fixed upper bound for a lot of cases.
   4137 /// 
   4138 /// If you don't want to think about how much memory the library should allocate
   4139 /// at all time or have a very dynamic UI with unpredictable memory consumption
   4140 /// habits but still want control over memory allocation you can use the dynamic
   4141 /// allocator based API. The allocator consists of two callbacks for allocating
   4142 /// and freeing memory and optional userdata so you can plugin your own allocator.
   4143 /// 
   4144 /// The final and easiest way can be used by defining
   4145 /// NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
   4146 /// allocation functions malloc and free and takes over complete control over
   4147 /// memory in this library.
   4148 */
   4149 struct nk_memory_status {
   4150     void *memory;
   4151     unsigned int type;
   4152     nk_size size;
   4153     nk_size allocated;
   4154     nk_size needed;
   4155     nk_size calls;
   4156 };
   4157 
   4158 enum nk_allocation_type {
   4159     NK_BUFFER_FIXED,
   4160     NK_BUFFER_DYNAMIC
   4161 };
   4162 
   4163 enum nk_buffer_allocation_type {
   4164     NK_BUFFER_FRONT,
   4165     NK_BUFFER_BACK,
   4166     NK_BUFFER_MAX
   4167 };
   4168 
   4169 struct nk_buffer_marker {
   4170     nk_bool active;
   4171     nk_size offset;
   4172 };
   4173 
   4174 struct nk_memory {void *ptr;nk_size size;};
   4175 struct nk_buffer {
   4176     struct nk_buffer_marker marker[NK_BUFFER_MAX];
   4177     /* buffer marker to free a buffer to a certain offset */
   4178     struct nk_allocator pool;
   4179     /* allocator callback for dynamic buffers */
   4180     enum nk_allocation_type type;
   4181     /* memory management type */
   4182     struct nk_memory memory;
   4183     /* memory and size of the current memory block */
   4184     float grow_factor;
   4185     /* growing factor for dynamic memory management */
   4186     nk_size allocated;
   4187     /* total amount of memory allocated */
   4188     nk_size needed;
   4189     /* totally consumed memory given that enough memory is present */
   4190     nk_size calls;
   4191     /* number of allocation calls */
   4192     nk_size size;
   4193     /* current size of the buffer */
   4194 };
   4195 
   4196 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   4197 NK_API void nk_buffer_init_default(struct nk_buffer*);
   4198 #endif
   4199 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
   4200 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
   4201 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
   4202 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
   4203 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
   4204 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type);
   4205 NK_API void nk_buffer_clear(struct nk_buffer*);
   4206 NK_API void nk_buffer_free(struct nk_buffer*);
   4207 NK_API void *nk_buffer_memory(struct nk_buffer*);
   4208 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
   4209 NK_API nk_size nk_buffer_total(struct nk_buffer*);
   4210 
   4211 /* ==============================================================
   4212  *
   4213  *                          STRING
   4214  *
   4215  * ===============================================================*/
   4216 /*  Basic string buffer which is only used in context with the text editor
   4217  *  to manage and manipulate dynamic or fixed size string content. This is _NOT_
   4218  *  the default string handling method. The only instance you should have any contact
   4219  *  with this API is if you interact with an `nk_text_edit` object inside one of the
   4220  *  copy and paste functions and even there only for more advanced cases. */
   4221 struct nk_str {
   4222     struct nk_buffer buffer;
   4223     int len; /* in codepoints/runes/glyphs */
   4224 };
   4225 
   4226 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   4227 NK_API void nk_str_init_default(struct nk_str*);
   4228 #endif
   4229 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
   4230 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
   4231 NK_API void nk_str_clear(struct nk_str*);
   4232 NK_API void nk_str_free(struct nk_str*);
   4233 
   4234 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
   4235 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
   4236 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
   4237 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
   4238 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
   4239 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
   4240 
   4241 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
   4242 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
   4243 
   4244 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
   4245 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
   4246 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
   4247 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
   4248 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
   4249 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
   4250 
   4251 NK_API void nk_str_remove_chars(struct nk_str*, int len);
   4252 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
   4253 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
   4254 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
   4255 
   4256 NK_API char *nk_str_at_char(struct nk_str*, int pos);
   4257 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
   4258 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
   4259 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
   4260 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
   4261 
   4262 NK_API char *nk_str_get(struct nk_str*);
   4263 NK_API const char *nk_str_get_const(const struct nk_str*);
   4264 NK_API int nk_str_len(struct nk_str*);
   4265 NK_API int nk_str_len_char(struct nk_str*);
   4266 
   4267 /*===============================================================
   4268  *
   4269  *                      TEXT EDITOR
   4270  *
   4271  * ===============================================================*/
   4272 /*/// ### Text Editor
   4273 /// Editing text in this library is handled by either `nk_edit_string` or
   4274 /// `nk_edit_buffer`. But like almost everything in this library there are multiple
   4275 /// ways of doing it and a balance between control and ease of use with memory
   4276 /// as well as functionality controlled by flags.
   4277 ///
   4278 /// This library generally allows three different levels of memory control:
   4279 /// First of is the most basic way of just providing a simple char array with
   4280 /// string length. This method is probably the easiest way of handling simple
   4281 /// user text input. Main upside is complete control over memory while the biggest
   4282 /// downside in comparison with the other two approaches is missing undo/redo.
   4283 ///
   4284 /// For UIs that require undo/redo the second way was created. It is based on
   4285 /// a fixed size nk_text_edit struct, which has an internal undo/redo stack.
   4286 /// This is mainly useful if you want something more like a text editor but don't want
   4287 /// to have a dynamically growing buffer.
   4288 ///
   4289 /// The final way is using a dynamically growing nk_text_edit struct, which
   4290 /// has both a default version if you don't care where memory comes from and an
   4291 /// allocator version if you do. While the text editor is quite powerful for its
   4292 /// complexity I would not recommend editing gigabytes of data with it.
   4293 /// It is rather designed for uses cases which make sense for a GUI library not for
   4294 /// an full blown text editor.
   4295  */
   4296 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
   4297 #define NK_TEXTEDIT_UNDOSTATECOUNT     99
   4298 #endif
   4299 
   4300 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
   4301 #define NK_TEXTEDIT_UNDOCHARCOUNT      999
   4302 #endif
   4303 
   4304 struct nk_text_edit;
   4305 struct nk_clipboard {
   4306     nk_handle userdata;
   4307     nk_plugin_paste paste;
   4308     nk_plugin_copy copy;
   4309 };
   4310 
   4311 struct nk_text_undo_record {
   4312    int where;
   4313    short insert_length;
   4314    short delete_length;
   4315    short char_storage;
   4316 };
   4317 
   4318 struct nk_text_undo_state {
   4319    struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT];
   4320    nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT];
   4321    short undo_point;
   4322    short redo_point;
   4323    short undo_char_point;
   4324    short redo_char_point;
   4325 };
   4326 
   4327 enum nk_text_edit_type {
   4328     NK_TEXT_EDIT_SINGLE_LINE,
   4329     NK_TEXT_EDIT_MULTI_LINE
   4330 };
   4331 
   4332 enum nk_text_edit_mode {
   4333     NK_TEXT_EDIT_MODE_VIEW,
   4334     NK_TEXT_EDIT_MODE_INSERT,
   4335     NK_TEXT_EDIT_MODE_REPLACE
   4336 };
   4337 
   4338 struct nk_text_edit {
   4339     struct nk_clipboard clip;
   4340     struct nk_str string;
   4341     nk_plugin_filter filter;
   4342     struct nk_vec2 scrollbar;
   4343 
   4344     int cursor;
   4345     int select_start;
   4346     int select_end;
   4347     unsigned char mode;
   4348     unsigned char cursor_at_end_of_line;
   4349     unsigned char initialized;
   4350     unsigned char has_preferred_x;
   4351     unsigned char single_line;
   4352     unsigned char active;
   4353     unsigned char padding1;
   4354     float preferred_x;
   4355     struct nk_text_undo_state undo;
   4356 };
   4357 
   4358 /* filter function */
   4359 NK_API nk_bool nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
   4360 NK_API nk_bool nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
   4361 NK_API nk_bool nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
   4362 NK_API nk_bool nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
   4363 NK_API nk_bool nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
   4364 NK_API nk_bool nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
   4365 NK_API nk_bool nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
   4366 
   4367 /* text editor */
   4368 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   4369 NK_API void nk_textedit_init_default(struct nk_text_edit*);
   4370 #endif
   4371 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
   4372 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
   4373 NK_API void nk_textedit_free(struct nk_text_edit*);
   4374 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
   4375 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
   4376 NK_API void nk_textedit_delete_selection(struct nk_text_edit*);
   4377 NK_API void nk_textedit_select_all(struct nk_text_edit*);
   4378 NK_API nk_bool nk_textedit_cut(struct nk_text_edit*);
   4379 NK_API nk_bool nk_textedit_paste(struct nk_text_edit*, char const*, int len);
   4380 NK_API void nk_textedit_undo(struct nk_text_edit*);
   4381 NK_API void nk_textedit_redo(struct nk_text_edit*);
   4382 
   4383 /* ===============================================================
   4384  *
   4385  *                          DRAWING
   4386  *
   4387  * ===============================================================*/
   4388 /*/// ### Drawing
   4389 /// This library was designed to be render backend agnostic so it does
   4390 /// not draw anything to screen. Instead all drawn shapes, widgets
   4391 /// are made of, are buffered into memory and make up a command queue.
   4392 /// Each frame therefore fills the command buffer with draw commands
   4393 /// that then need to be executed by the user and his own render backend.
   4394 /// After that the command buffer needs to be cleared and a new frame can be
   4395 /// started. It is probably important to note that the command buffer is the main
   4396 /// drawing API and the optional vertex buffer API only takes this format and
   4397 /// converts it into a hardware accessible format.
   4398 /// 
   4399 /// To use the command queue to draw your own widgets you can access the
   4400 /// command buffer of each window by calling `nk_window_get_canvas` after
   4401 /// previously having called `nk_begin`:
   4402 /// 
   4403 /// ```c
   4404 ///     void draw_red_rectangle_widget(struct nk_context *ctx)
   4405 ///     {
   4406 ///         struct nk_command_buffer *canvas;
   4407 ///         struct nk_input *input = &ctx->input;
   4408 ///         canvas = nk_window_get_canvas(ctx);
   4409 /// 
   4410 ///         struct nk_rect space;
   4411 ///         enum nk_widget_layout_states state;
   4412 ///         state = nk_widget(&space, ctx);
   4413 ///         if (!state) return;
   4414 /// 
   4415 ///         if (state != NK_WIDGET_ROM)
   4416 ///             update_your_widget_by_user_input(...);
   4417 ///         nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
   4418 ///     }
   4419 /// 
   4420 ///     if (nk_begin(...)) {
   4421 ///         nk_layout_row_dynamic(ctx, 25, 1);
   4422 ///         draw_red_rectangle_widget(ctx);
   4423 ///     }
   4424 ///     nk_end(..)
   4425 /// 
   4426 /// ```
   4427 /// Important to know if you want to create your own widgets is the `nk_widget`
   4428 /// call. It allocates space on the panel reserved for this widget to be used,
   4429 /// but also returns the state of the widget space. If your widget is not seen and does
   4430 /// not have to be updated it is '0' and you can just return. If it only has
   4431 /// to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
   4432 /// update and draw your widget. The reason for separating is to only draw and
   4433 /// update what is actually necessary which is crucial for performance.
   4434 */
   4435 enum nk_command_type {
   4436     NK_COMMAND_NOP,
   4437     NK_COMMAND_SCISSOR,
   4438     NK_COMMAND_LINE,
   4439     NK_COMMAND_CURVE,
   4440     NK_COMMAND_RECT,
   4441     NK_COMMAND_RECT_FILLED,
   4442     NK_COMMAND_RECT_MULTI_COLOR,
   4443     NK_COMMAND_CIRCLE,
   4444     NK_COMMAND_CIRCLE_FILLED,
   4445     NK_COMMAND_ARC,
   4446     NK_COMMAND_ARC_FILLED,
   4447     NK_COMMAND_TRIANGLE,
   4448     NK_COMMAND_TRIANGLE_FILLED,
   4449     NK_COMMAND_POLYGON,
   4450     NK_COMMAND_POLYGON_FILLED,
   4451     NK_COMMAND_POLYLINE,
   4452     NK_COMMAND_TEXT,
   4453     NK_COMMAND_IMAGE,
   4454     NK_COMMAND_CUSTOM
   4455 };
   4456 
   4457 /* command base and header of every command inside the buffer */
   4458 struct nk_command {
   4459     enum nk_command_type type;
   4460     nk_size next;
   4461 #ifdef NK_INCLUDE_COMMAND_USERDATA
   4462     nk_handle userdata;
   4463 #endif
   4464 };
   4465 
   4466 struct nk_command_scissor {
   4467     struct nk_command header;
   4468     short x, y;
   4469     unsigned short w, h;
   4470 };
   4471 
   4472 struct nk_command_line {
   4473     struct nk_command header;
   4474     unsigned short line_thickness;
   4475     struct nk_vec2i begin;
   4476     struct nk_vec2i end;
   4477     struct nk_color color;
   4478 };
   4479 
   4480 struct nk_command_curve {
   4481     struct nk_command header;
   4482     unsigned short line_thickness;
   4483     struct nk_vec2i begin;
   4484     struct nk_vec2i end;
   4485     struct nk_vec2i ctrl[2];
   4486     struct nk_color color;
   4487 };
   4488 
   4489 struct nk_command_rect {
   4490     struct nk_command header;
   4491     unsigned short rounding;
   4492     unsigned short line_thickness;
   4493     short x, y;
   4494     unsigned short w, h;
   4495     struct nk_color color;
   4496 };
   4497 
   4498 struct nk_command_rect_filled {
   4499     struct nk_command header;
   4500     unsigned short rounding;
   4501     short x, y;
   4502     unsigned short w, h;
   4503     struct nk_color color;
   4504 };
   4505 
   4506 struct nk_command_rect_multi_color {
   4507     struct nk_command header;
   4508     short x, y;
   4509     unsigned short w, h;
   4510     struct nk_color left;
   4511     struct nk_color top;
   4512     struct nk_color bottom;
   4513     struct nk_color right;
   4514 };
   4515 
   4516 struct nk_command_triangle {
   4517     struct nk_command header;
   4518     unsigned short line_thickness;
   4519     struct nk_vec2i a;
   4520     struct nk_vec2i b;
   4521     struct nk_vec2i c;
   4522     struct nk_color color;
   4523 };
   4524 
   4525 struct nk_command_triangle_filled {
   4526     struct nk_command header;
   4527     struct nk_vec2i a;
   4528     struct nk_vec2i b;
   4529     struct nk_vec2i c;
   4530     struct nk_color color;
   4531 };
   4532 
   4533 struct nk_command_circle {
   4534     struct nk_command header;
   4535     short x, y;
   4536     unsigned short line_thickness;
   4537     unsigned short w, h;
   4538     struct nk_color color;
   4539 };
   4540 
   4541 struct nk_command_circle_filled {
   4542     struct nk_command header;
   4543     short x, y;
   4544     unsigned short w, h;
   4545     struct nk_color color;
   4546 };
   4547 
   4548 struct nk_command_arc {
   4549     struct nk_command header;
   4550     short cx, cy;
   4551     unsigned short r;
   4552     unsigned short line_thickness;
   4553     float a[2];
   4554     struct nk_color color;
   4555 };
   4556 
   4557 struct nk_command_arc_filled {
   4558     struct nk_command header;
   4559     short cx, cy;
   4560     unsigned short r;
   4561     float a[2];
   4562     struct nk_color color;
   4563 };
   4564 
   4565 struct nk_command_polygon {
   4566     struct nk_command header;
   4567     struct nk_color color;
   4568     unsigned short line_thickness;
   4569     unsigned short point_count;
   4570     struct nk_vec2i points[1];
   4571 };
   4572 
   4573 struct nk_command_polygon_filled {
   4574     struct nk_command header;
   4575     struct nk_color color;
   4576     unsigned short point_count;
   4577     struct nk_vec2i points[1];
   4578 };
   4579 
   4580 struct nk_command_polyline {
   4581     struct nk_command header;
   4582     struct nk_color color;
   4583     unsigned short line_thickness;
   4584     unsigned short point_count;
   4585     struct nk_vec2i points[1];
   4586 };
   4587 
   4588 struct nk_command_image {
   4589     struct nk_command header;
   4590     short x, y;
   4591     unsigned short w, h;
   4592     struct nk_image img;
   4593     struct nk_color col;
   4594 };
   4595 
   4596 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
   4597     unsigned short w, unsigned short h, nk_handle callback_data);
   4598 struct nk_command_custom {
   4599     struct nk_command header;
   4600     short x, y;
   4601     unsigned short w, h;
   4602     nk_handle callback_data;
   4603     nk_command_custom_callback callback;
   4604 };
   4605 
   4606 struct nk_command_text {
   4607     struct nk_command header;
   4608     const struct nk_user_font *font;
   4609     struct nk_color background;
   4610     struct nk_color foreground;
   4611     short x, y;
   4612     unsigned short w, h;
   4613     float height;
   4614     int length;
   4615     char string[1];
   4616 };
   4617 
   4618 enum nk_command_clipping {
   4619     NK_CLIPPING_OFF = nk_false,
   4620     NK_CLIPPING_ON = nk_true
   4621 };
   4622 
   4623 struct nk_command_buffer {
   4624     struct nk_buffer *base;
   4625     struct nk_rect clip;
   4626     int use_clipping;
   4627     nk_handle userdata;
   4628     nk_size begin, end, last;
   4629 };
   4630 
   4631 /* shape outlines */
   4632 NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color);
   4633 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
   4634 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
   4635 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
   4636 NK_API void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color);
   4637 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
   4638 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
   4639 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
   4640 
   4641 /* filled shades */
   4642 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
   4643 NK_API void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
   4644 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
   4645 NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color);
   4646 NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color);
   4647 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
   4648 
   4649 /* misc */
   4650 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
   4651 NK_API void nk_draw_nine_slice(struct nk_command_buffer*, struct nk_rect, const struct nk_nine_slice*, struct nk_color);
   4652 NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color);
   4653 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
   4654 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
   4655 
   4656 /* ===============================================================
   4657  *
   4658  *                          INPUT
   4659  *
   4660  * ===============================================================*/
   4661 struct nk_mouse_button {
   4662     nk_bool down;
   4663     unsigned int clicked;
   4664     struct nk_vec2 clicked_pos;
   4665 };
   4666 struct nk_mouse {
   4667     struct nk_mouse_button buttons[NK_BUTTON_MAX];
   4668     struct nk_vec2 pos;
   4669 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
   4670     struct nk_vec2 down_pos;
   4671 #endif
   4672     struct nk_vec2 prev;
   4673     struct nk_vec2 delta;
   4674     struct nk_vec2 scroll_delta;
   4675     unsigned char grab;
   4676     unsigned char grabbed;
   4677     unsigned char ungrab;
   4678 };
   4679 
   4680 struct nk_key {
   4681     nk_bool down;
   4682     unsigned int clicked;
   4683 };
   4684 struct nk_keyboard {
   4685     struct nk_key keys[NK_KEY_MAX];
   4686     char text[NK_INPUT_MAX];
   4687     int text_len;
   4688 };
   4689 
   4690 struct nk_input {
   4691     struct nk_keyboard keyboard;
   4692     struct nk_mouse mouse;
   4693 };
   4694 
   4695 NK_API nk_bool nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
   4696 NK_API nk_bool nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
   4697 NK_API nk_bool nk_input_has_mouse_click_in_button_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
   4698 NK_API nk_bool nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, nk_bool down);
   4699 NK_API nk_bool nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
   4700 NK_API nk_bool nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, nk_bool down);
   4701 NK_API nk_bool nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
   4702 NK_API nk_bool nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
   4703 NK_API nk_bool nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
   4704 NK_API nk_bool nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
   4705 NK_API nk_bool nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
   4706 NK_API nk_bool nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
   4707 NK_API nk_bool nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
   4708 NK_API nk_bool nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
   4709 NK_API nk_bool nk_input_is_key_released(const struct nk_input*, enum nk_keys);
   4710 NK_API nk_bool nk_input_is_key_down(const struct nk_input*, enum nk_keys);
   4711 
   4712 /* ===============================================================
   4713  *
   4714  *                          DRAW LIST
   4715  *
   4716  * ===============================================================*/
   4717 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   4718 /* ### Draw List
   4719 /// The optional vertex buffer draw list provides a 2D drawing context
   4720 /// with antialiasing functionality which takes basic filled or outlined shapes
   4721 /// or a path and outputs vertexes, elements and draw commands.
   4722 /// The actual draw list API is not required to be used directly while using this
   4723 /// library since converting the default library draw command output is done by
   4724 /// just calling `nk_convert` but I decided to still make this library accessible
   4725 /// since it can be useful.
   4726 /// 
   4727 /// The draw list is based on a path buffering and polygon and polyline
   4728 /// rendering API which allows a lot of ways to draw 2D content to screen.
   4729 /// In fact it is probably more powerful than needed but allows even more crazy
   4730 /// things than this library provides by default.
   4731 */
   4732 #ifdef NK_UINT_DRAW_INDEX
   4733 typedef nk_uint nk_draw_index;
   4734 #else
   4735 typedef nk_ushort nk_draw_index;
   4736 #endif
   4737 enum nk_draw_list_stroke {
   4738     NK_STROKE_OPEN = nk_false,
   4739     /* build up path has no connection back to the beginning */
   4740     NK_STROKE_CLOSED = nk_true
   4741     /* build up path has a connection back to the beginning */
   4742 };
   4743 
   4744 enum nk_draw_vertex_layout_attribute {
   4745     NK_VERTEX_POSITION,
   4746     NK_VERTEX_COLOR,
   4747     NK_VERTEX_TEXCOORD,
   4748     NK_VERTEX_ATTRIBUTE_COUNT
   4749 };
   4750 
   4751 enum nk_draw_vertex_layout_format {
   4752     NK_FORMAT_SCHAR,
   4753     NK_FORMAT_SSHORT,
   4754     NK_FORMAT_SINT,
   4755     NK_FORMAT_UCHAR,
   4756     NK_FORMAT_USHORT,
   4757     NK_FORMAT_UINT,
   4758     NK_FORMAT_FLOAT,
   4759     NK_FORMAT_DOUBLE,
   4760 
   4761 NK_FORMAT_COLOR_BEGIN,
   4762     NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
   4763     NK_FORMAT_R16G15B16,
   4764     NK_FORMAT_R32G32B32,
   4765 
   4766     NK_FORMAT_R8G8B8A8,
   4767     NK_FORMAT_B8G8R8A8,
   4768     NK_FORMAT_R16G15B16A16,
   4769     NK_FORMAT_R32G32B32A32,
   4770     NK_FORMAT_R32G32B32A32_FLOAT,
   4771     NK_FORMAT_R32G32B32A32_DOUBLE,
   4772 
   4773     NK_FORMAT_RGB32,
   4774     NK_FORMAT_RGBA32,
   4775 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
   4776     NK_FORMAT_COUNT
   4777 };
   4778 
   4779 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
   4780 struct nk_draw_vertex_layout_element {
   4781     enum nk_draw_vertex_layout_attribute attribute;
   4782     enum nk_draw_vertex_layout_format format;
   4783     nk_size offset;
   4784 };
   4785 
   4786 struct nk_draw_command {
   4787     unsigned int elem_count;
   4788     /* number of elements in the current draw batch */
   4789     struct nk_rect clip_rect;
   4790     /* current screen clipping rectangle */
   4791     nk_handle texture;
   4792     /* current texture to set */
   4793 #ifdef NK_INCLUDE_COMMAND_USERDATA
   4794     nk_handle userdata;
   4795 #endif
   4796 };
   4797 
   4798 struct nk_draw_list {
   4799     struct nk_rect clip_rect;
   4800     struct nk_vec2 circle_vtx[12];
   4801     struct nk_convert_config config;
   4802 
   4803     struct nk_buffer *buffer;
   4804     struct nk_buffer *vertices;
   4805     struct nk_buffer *elements;
   4806 
   4807     unsigned int element_count;
   4808     unsigned int vertex_count;
   4809     unsigned int cmd_count;
   4810     nk_size cmd_offset;
   4811 
   4812     unsigned int path_count;
   4813     unsigned int path_offset;
   4814 
   4815     enum nk_anti_aliasing line_AA;
   4816     enum nk_anti_aliasing shape_AA;
   4817 
   4818 #ifdef NK_INCLUDE_COMMAND_USERDATA
   4819     nk_handle userdata;
   4820 #endif
   4821 };
   4822 
   4823 /* draw list */
   4824 NK_API void nk_draw_list_init(struct nk_draw_list*);
   4825 NK_API void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, enum nk_anti_aliasing line_aa,enum nk_anti_aliasing shape_aa);
   4826 
   4827 /* drawing */
   4828 #define nk_draw_list_foreach(cmd, can, b) for((cmd)=nk__draw_list_begin(can, b); (cmd)!=0; (cmd)=nk__draw_list_next(cmd, b, can))
   4829 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
   4830 NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*);
   4831 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
   4832 
   4833 /* path */
   4834 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
   4835 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
   4836 NK_API void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max);
   4837 NK_API void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments);
   4838 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
   4839 NK_API void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments);
   4840 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
   4841 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
   4842 
   4843 /* stroke */
   4844 NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness);
   4845 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
   4846 NK_API void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness);
   4847 NK_API void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness);
   4848 NK_API void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness);
   4849 NK_API void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing);
   4850 
   4851 /* fill */
   4852 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
   4853 NK_API void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
   4854 NK_API void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color);
   4855 NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs);
   4856 NK_API void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing);
   4857 
   4858 /* misc */
   4859 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
   4860 NK_API void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color);
   4861 #ifdef NK_INCLUDE_COMMAND_USERDATA
   4862 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
   4863 #endif
   4864 
   4865 #endif
   4866 
   4867 /* ===============================================================
   4868  *
   4869  *                          GUI
   4870  *
   4871  * ===============================================================*/
   4872 enum nk_style_item_type {
   4873     NK_STYLE_ITEM_COLOR,
   4874     NK_STYLE_ITEM_IMAGE,
   4875     NK_STYLE_ITEM_NINE_SLICE
   4876 };
   4877 
   4878 union nk_style_item_data {
   4879     struct nk_color color;
   4880     struct nk_image image;
   4881     struct nk_nine_slice slice;
   4882 };
   4883 
   4884 struct nk_style_item {
   4885     enum nk_style_item_type type;
   4886     union nk_style_item_data data;
   4887 };
   4888 
   4889 struct nk_style_text {
   4890     struct nk_color color;
   4891     struct nk_vec2 padding;
   4892 };
   4893 
   4894 struct nk_style_button {
   4895     /* background */
   4896     struct nk_style_item normal;
   4897     struct nk_style_item hover;
   4898     struct nk_style_item active;
   4899     struct nk_color border_color;
   4900 
   4901     /* text */
   4902     struct nk_color text_background;
   4903     struct nk_color text_normal;
   4904     struct nk_color text_hover;
   4905     struct nk_color text_active;
   4906     nk_flags text_alignment;
   4907 
   4908     /* properties */
   4909     float border;
   4910     float rounding;
   4911     struct nk_vec2 padding;
   4912     struct nk_vec2 image_padding;
   4913     struct nk_vec2 touch_padding;
   4914 
   4915     /* optional user callbacks */
   4916     nk_handle userdata;
   4917     void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata);
   4918     void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
   4919 };
   4920 
   4921 struct nk_style_toggle {
   4922     /* background */
   4923     struct nk_style_item normal;
   4924     struct nk_style_item hover;
   4925     struct nk_style_item active;
   4926     struct nk_color border_color;
   4927 
   4928     /* cursor */
   4929     struct nk_style_item cursor_normal;
   4930     struct nk_style_item cursor_hover;
   4931 
   4932     /* text */
   4933     struct nk_color text_normal;
   4934     struct nk_color text_hover;
   4935     struct nk_color text_active;
   4936     struct nk_color text_background;
   4937     nk_flags text_alignment;
   4938 
   4939     /* properties */
   4940     struct nk_vec2 padding;
   4941     struct nk_vec2 touch_padding;
   4942     float spacing;
   4943     float border;
   4944 
   4945     /* optional user callbacks */
   4946     nk_handle userdata;
   4947     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   4948     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   4949 };
   4950 
   4951 struct nk_style_selectable {
   4952     /* background (inactive) */
   4953     struct nk_style_item normal;
   4954     struct nk_style_item hover;
   4955     struct nk_style_item pressed;
   4956 
   4957     /* background (active) */
   4958     struct nk_style_item normal_active;
   4959     struct nk_style_item hover_active;
   4960     struct nk_style_item pressed_active;
   4961 
   4962     /* text color (inactive) */
   4963     struct nk_color text_normal;
   4964     struct nk_color text_hover;
   4965     struct nk_color text_pressed;
   4966 
   4967     /* text color (active) */
   4968     struct nk_color text_normal_active;
   4969     struct nk_color text_hover_active;
   4970     struct nk_color text_pressed_active;
   4971     struct nk_color text_background;
   4972     nk_flags text_alignment;
   4973 
   4974     /* properties */
   4975     float rounding;
   4976     struct nk_vec2 padding;
   4977     struct nk_vec2 touch_padding;
   4978     struct nk_vec2 image_padding;
   4979 
   4980     /* optional user callbacks */
   4981     nk_handle userdata;
   4982     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   4983     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   4984 };
   4985 
   4986 struct nk_style_slider {
   4987     /* background */
   4988     struct nk_style_item normal;
   4989     struct nk_style_item hover;
   4990     struct nk_style_item active;
   4991     struct nk_color border_color;
   4992 
   4993     /* background bar */
   4994     struct nk_color bar_normal;
   4995     struct nk_color bar_hover;
   4996     struct nk_color bar_active;
   4997     struct nk_color bar_filled;
   4998 
   4999     /* cursor */
   5000     struct nk_style_item cursor_normal;
   5001     struct nk_style_item cursor_hover;
   5002     struct nk_style_item cursor_active;
   5003 
   5004     /* properties */
   5005     float border;
   5006     float rounding;
   5007     float bar_height;
   5008     struct nk_vec2 padding;
   5009     struct nk_vec2 spacing;
   5010     struct nk_vec2 cursor_size;
   5011 
   5012     /* optional buttons */
   5013     int show_buttons;
   5014     struct nk_style_button inc_button;
   5015     struct nk_style_button dec_button;
   5016     enum nk_symbol_type inc_symbol;
   5017     enum nk_symbol_type dec_symbol;
   5018 
   5019     /* optional user callbacks */
   5020     nk_handle userdata;
   5021     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   5022     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   5023 };
   5024 
   5025 struct nk_style_progress {
   5026     /* background */
   5027     struct nk_style_item normal;
   5028     struct nk_style_item hover;
   5029     struct nk_style_item active;
   5030     struct nk_color border_color;
   5031 
   5032     /* cursor */
   5033     struct nk_style_item cursor_normal;
   5034     struct nk_style_item cursor_hover;
   5035     struct nk_style_item cursor_active;
   5036     struct nk_color cursor_border_color;
   5037 
   5038     /* properties */
   5039     float rounding;
   5040     float border;
   5041     float cursor_border;
   5042     float cursor_rounding;
   5043     struct nk_vec2 padding;
   5044 
   5045     /* optional user callbacks */
   5046     nk_handle userdata;
   5047     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   5048     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   5049 };
   5050 
   5051 struct nk_style_scrollbar {
   5052     /* background */
   5053     struct nk_style_item normal;
   5054     struct nk_style_item hover;
   5055     struct nk_style_item active;
   5056     struct nk_color border_color;
   5057 
   5058     /* cursor */
   5059     struct nk_style_item cursor_normal;
   5060     struct nk_style_item cursor_hover;
   5061     struct nk_style_item cursor_active;
   5062     struct nk_color cursor_border_color;
   5063 
   5064     /* properties */
   5065     float border;
   5066     float rounding;
   5067     float border_cursor;
   5068     float rounding_cursor;
   5069     struct nk_vec2 padding;
   5070 
   5071     /* optional buttons */
   5072     int show_buttons;
   5073     struct nk_style_button inc_button;
   5074     struct nk_style_button dec_button;
   5075     enum nk_symbol_type inc_symbol;
   5076     enum nk_symbol_type dec_symbol;
   5077 
   5078     /* optional user callbacks */
   5079     nk_handle userdata;
   5080     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   5081     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   5082 };
   5083 
   5084 struct nk_style_edit {
   5085     /* background */
   5086     struct nk_style_item normal;
   5087     struct nk_style_item hover;
   5088     struct nk_style_item active;
   5089     struct nk_color border_color;
   5090     struct nk_style_scrollbar scrollbar;
   5091 
   5092     /* cursor  */
   5093     struct nk_color cursor_normal;
   5094     struct nk_color cursor_hover;
   5095     struct nk_color cursor_text_normal;
   5096     struct nk_color cursor_text_hover;
   5097 
   5098     /* text (unselected) */
   5099     struct nk_color text_normal;
   5100     struct nk_color text_hover;
   5101     struct nk_color text_active;
   5102 
   5103     /* text (selected) */
   5104     struct nk_color selected_normal;
   5105     struct nk_color selected_hover;
   5106     struct nk_color selected_text_normal;
   5107     struct nk_color selected_text_hover;
   5108 
   5109     /* properties */
   5110     float border;
   5111     float rounding;
   5112     float cursor_size;
   5113     struct nk_vec2 scrollbar_size;
   5114     struct nk_vec2 padding;
   5115     float row_padding;
   5116 };
   5117 
   5118 struct nk_style_property {
   5119     /* background */
   5120     struct nk_style_item normal;
   5121     struct nk_style_item hover;
   5122     struct nk_style_item active;
   5123     struct nk_color border_color;
   5124 
   5125     /* text */
   5126     struct nk_color label_normal;
   5127     struct nk_color label_hover;
   5128     struct nk_color label_active;
   5129 
   5130     /* symbols */
   5131     enum nk_symbol_type sym_left;
   5132     enum nk_symbol_type sym_right;
   5133 
   5134     /* properties */
   5135     float border;
   5136     float rounding;
   5137     struct nk_vec2 padding;
   5138 
   5139     struct nk_style_edit edit;
   5140     struct nk_style_button inc_button;
   5141     struct nk_style_button dec_button;
   5142 
   5143     /* optional user callbacks */
   5144     nk_handle userdata;
   5145     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   5146     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   5147 };
   5148 
   5149 struct nk_style_chart {
   5150     /* colors */
   5151     struct nk_style_item background;
   5152     struct nk_color border_color;
   5153     struct nk_color selected_color;
   5154     struct nk_color color;
   5155 
   5156     /* properties */
   5157     float border;
   5158     float rounding;
   5159     struct nk_vec2 padding;
   5160 };
   5161 
   5162 struct nk_style_combo {
   5163     /* background */
   5164     struct nk_style_item normal;
   5165     struct nk_style_item hover;
   5166     struct nk_style_item active;
   5167     struct nk_color border_color;
   5168 
   5169     /* label */
   5170     struct nk_color label_normal;
   5171     struct nk_color label_hover;
   5172     struct nk_color label_active;
   5173 
   5174     /* symbol */
   5175     struct nk_color symbol_normal;
   5176     struct nk_color symbol_hover;
   5177     struct nk_color symbol_active;
   5178 
   5179     /* button */
   5180     struct nk_style_button button;
   5181     enum nk_symbol_type sym_normal;
   5182     enum nk_symbol_type sym_hover;
   5183     enum nk_symbol_type sym_active;
   5184 
   5185     /* properties */
   5186     float border;
   5187     float rounding;
   5188     struct nk_vec2 content_padding;
   5189     struct nk_vec2 button_padding;
   5190     struct nk_vec2 spacing;
   5191 };
   5192 
   5193 struct nk_style_tab {
   5194     /* background */
   5195     struct nk_style_item background;
   5196     struct nk_color border_color;
   5197     struct nk_color text;
   5198 
   5199     /* button */
   5200     struct nk_style_button tab_maximize_button;
   5201     struct nk_style_button tab_minimize_button;
   5202     struct nk_style_button node_maximize_button;
   5203     struct nk_style_button node_minimize_button;
   5204     enum nk_symbol_type sym_minimize;
   5205     enum nk_symbol_type sym_maximize;
   5206 
   5207     /* properties */
   5208     float border;
   5209     float rounding;
   5210     float indent;
   5211     struct nk_vec2 padding;
   5212     struct nk_vec2 spacing;
   5213 };
   5214 
   5215 enum nk_style_header_align {
   5216     NK_HEADER_LEFT,
   5217     NK_HEADER_RIGHT
   5218 };
   5219 struct nk_style_window_header {
   5220     /* background */
   5221     struct nk_style_item normal;
   5222     struct nk_style_item hover;
   5223     struct nk_style_item active;
   5224 
   5225     /* button */
   5226     struct nk_style_button close_button;
   5227     struct nk_style_button minimize_button;
   5228     enum nk_symbol_type close_symbol;
   5229     enum nk_symbol_type minimize_symbol;
   5230     enum nk_symbol_type maximize_symbol;
   5231 
   5232     /* title */
   5233     struct nk_color label_normal;
   5234     struct nk_color label_hover;
   5235     struct nk_color label_active;
   5236 
   5237     /* properties */
   5238     enum nk_style_header_align align;
   5239     struct nk_vec2 padding;
   5240     struct nk_vec2 label_padding;
   5241     struct nk_vec2 spacing;
   5242 };
   5243 
   5244 struct nk_style_window {
   5245     struct nk_style_window_header header;
   5246     struct nk_style_item fixed_background;
   5247     struct nk_color background;
   5248 
   5249     struct nk_color border_color;
   5250     struct nk_color popup_border_color;
   5251     struct nk_color combo_border_color;
   5252     struct nk_color contextual_border_color;
   5253     struct nk_color menu_border_color;
   5254     struct nk_color group_border_color;
   5255     struct nk_color tooltip_border_color;
   5256     struct nk_style_item scaler;
   5257 
   5258     float border;
   5259     float combo_border;
   5260     float contextual_border;
   5261     float menu_border;
   5262     float group_border;
   5263     float tooltip_border;
   5264     float popup_border;
   5265     float min_row_height_padding;
   5266 
   5267     float rounding;
   5268     struct nk_vec2 spacing;
   5269     struct nk_vec2 scrollbar_size;
   5270     struct nk_vec2 min_size;
   5271 
   5272     struct nk_vec2 padding;
   5273     struct nk_vec2 group_padding;
   5274     struct nk_vec2 popup_padding;
   5275     struct nk_vec2 combo_padding;
   5276     struct nk_vec2 contextual_padding;
   5277     struct nk_vec2 menu_padding;
   5278     struct nk_vec2 tooltip_padding;
   5279 };
   5280 
   5281 struct nk_style {
   5282     const struct nk_user_font *font;
   5283     const struct nk_cursor *cursors[NK_CURSOR_COUNT];
   5284     const struct nk_cursor *cursor_active;
   5285     struct nk_cursor *cursor_last;
   5286     int cursor_visible;
   5287 
   5288     struct nk_style_text text;
   5289     struct nk_style_button button;
   5290     struct nk_style_button contextual_button;
   5291     struct nk_style_button menu_button;
   5292     struct nk_style_toggle option;
   5293     struct nk_style_toggle checkbox;
   5294     struct nk_style_selectable selectable;
   5295     struct nk_style_slider slider;
   5296     struct nk_style_progress progress;
   5297     struct nk_style_property property;
   5298     struct nk_style_edit edit;
   5299     struct nk_style_chart chart;
   5300     struct nk_style_scrollbar scrollh;
   5301     struct nk_style_scrollbar scrollv;
   5302     struct nk_style_tab tab;
   5303     struct nk_style_combo combo;
   5304     struct nk_style_window window;
   5305 };
   5306 
   5307 NK_API struct nk_style_item nk_style_item_color(struct nk_color);
   5308 NK_API struct nk_style_item nk_style_item_image(struct nk_image img);
   5309 NK_API struct nk_style_item nk_style_item_nine_slice(struct nk_nine_slice slice);
   5310 NK_API struct nk_style_item nk_style_item_hide(void);
   5311 
   5312 /*==============================================================
   5313  *                          PANEL
   5314  * =============================================================*/
   5315 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
   5316 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
   5317 #endif
   5318 #ifndef NK_CHART_MAX_SLOT
   5319 #define NK_CHART_MAX_SLOT 4
   5320 #endif
   5321 
   5322 enum nk_panel_type {
   5323     NK_PANEL_NONE       = 0,
   5324     NK_PANEL_WINDOW     = NK_FLAG(0),
   5325     NK_PANEL_GROUP      = NK_FLAG(1),
   5326     NK_PANEL_POPUP      = NK_FLAG(2),
   5327     NK_PANEL_CONTEXTUAL = NK_FLAG(4),
   5328     NK_PANEL_COMBO      = NK_FLAG(5),
   5329     NK_PANEL_MENU       = NK_FLAG(6),
   5330     NK_PANEL_TOOLTIP    = NK_FLAG(7)
   5331 };
   5332 enum nk_panel_set {
   5333     NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP,
   5334     NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP,
   5335     NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP
   5336 };
   5337 
   5338 struct nk_chart_slot {
   5339     enum nk_chart_type type;
   5340     struct nk_color color;
   5341     struct nk_color highlight;
   5342     float min, max, range;
   5343     int count;
   5344     struct nk_vec2 last;
   5345     int index;
   5346 };
   5347 
   5348 struct nk_chart {
   5349     int slot;
   5350     float x, y, w, h;
   5351     struct nk_chart_slot slots[NK_CHART_MAX_SLOT];
   5352 };
   5353 
   5354 enum nk_panel_row_layout_type {
   5355     NK_LAYOUT_DYNAMIC_FIXED = 0,
   5356     NK_LAYOUT_DYNAMIC_ROW,
   5357     NK_LAYOUT_DYNAMIC_FREE,
   5358     NK_LAYOUT_DYNAMIC,
   5359     NK_LAYOUT_STATIC_FIXED,
   5360     NK_LAYOUT_STATIC_ROW,
   5361     NK_LAYOUT_STATIC_FREE,
   5362     NK_LAYOUT_STATIC,
   5363     NK_LAYOUT_TEMPLATE,
   5364     NK_LAYOUT_COUNT
   5365 };
   5366 struct nk_row_layout {
   5367     enum nk_panel_row_layout_type type;
   5368     int index;
   5369     float height;
   5370     float min_height;
   5371     int columns;
   5372     const float *ratio;
   5373     float item_width;
   5374     float item_height;
   5375     float item_offset;
   5376     float filled;
   5377     struct nk_rect item;
   5378     int tree_depth;
   5379     float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS];
   5380 };
   5381 
   5382 struct nk_popup_buffer {
   5383     nk_size begin;
   5384     nk_size parent;
   5385     nk_size last;
   5386     nk_size end;
   5387     nk_bool active;
   5388 };
   5389 
   5390 struct nk_menu_state {
   5391     float x, y, w, h;
   5392     struct nk_scroll offset;
   5393 };
   5394 
   5395 struct nk_panel {
   5396     enum nk_panel_type type;
   5397     nk_flags flags;
   5398     struct nk_rect bounds;
   5399     nk_uint *offset_x;
   5400     nk_uint *offset_y;
   5401     float at_x, at_y, max_x;
   5402     float footer_height;
   5403     float header_height;
   5404     float border;
   5405     unsigned int has_scrolling;
   5406     struct nk_rect clip;
   5407     struct nk_menu_state menu;
   5408     struct nk_row_layout row;
   5409     struct nk_chart chart;
   5410     struct nk_command_buffer *buffer;
   5411     struct nk_panel *parent;
   5412 };
   5413 
   5414 /*==============================================================
   5415  *                          WINDOW
   5416  * =============================================================*/
   5417 #ifndef NK_WINDOW_MAX_NAME
   5418 #define NK_WINDOW_MAX_NAME 64
   5419 #endif
   5420 
   5421 struct nk_table;
   5422 enum nk_window_flags {
   5423     NK_WINDOW_PRIVATE       = NK_FLAG(11),
   5424     NK_WINDOW_DYNAMIC       = NK_WINDOW_PRIVATE,
   5425     /* special window type growing up in height while being filled to a certain maximum height */
   5426     NK_WINDOW_ROM           = NK_FLAG(12),
   5427     /* sets window widgets into a read only mode and does not allow input changes */
   5428     NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT,
   5429     /* prevents all interaction caused by input to either window or widgets inside */
   5430     NK_WINDOW_HIDDEN        = NK_FLAG(13),
   5431     /* Hides window and stops any window interaction and drawing */
   5432     NK_WINDOW_CLOSED        = NK_FLAG(14),
   5433     /* Directly closes and frees the window at the end of the frame */
   5434     NK_WINDOW_MINIMIZED     = NK_FLAG(15),
   5435     /* marks the window as minimized */
   5436     NK_WINDOW_REMOVE_ROM    = NK_FLAG(16)
   5437     /* Removes read only mode at the end of the window */
   5438 };
   5439 
   5440 struct nk_popup_state {
   5441     struct nk_window *win;
   5442     enum nk_panel_type type;
   5443     struct nk_popup_buffer buf;
   5444     nk_hash name;
   5445     nk_bool active;
   5446     unsigned combo_count;
   5447     unsigned con_count, con_old;
   5448     unsigned active_con;
   5449     struct nk_rect header;
   5450 };
   5451 
   5452 struct nk_edit_state {
   5453     nk_hash name;
   5454     unsigned int seq;
   5455     unsigned int old;
   5456     int active, prev;
   5457     int cursor;
   5458     int sel_start;
   5459     int sel_end;
   5460     struct nk_scroll scrollbar;
   5461     unsigned char mode;
   5462     unsigned char single_line;
   5463 };
   5464 
   5465 struct nk_property_state {
   5466     int active, prev;
   5467     char buffer[NK_MAX_NUMBER_BUFFER];
   5468     int length;
   5469     int cursor;
   5470     int select_start;
   5471     int select_end;
   5472     nk_hash name;
   5473     unsigned int seq;
   5474     unsigned int old;
   5475     int state;
   5476 };
   5477 
   5478 struct nk_window {
   5479     unsigned int seq;
   5480     nk_hash name;
   5481     char name_string[NK_WINDOW_MAX_NAME];
   5482     nk_flags flags;
   5483 
   5484     struct nk_rect bounds;
   5485     struct nk_scroll scrollbar;
   5486     struct nk_command_buffer buffer;
   5487     struct nk_panel *layout;
   5488     float scrollbar_hiding_timer;
   5489 
   5490     /* persistent widget state */
   5491     struct nk_property_state property;
   5492     struct nk_popup_state popup;
   5493     struct nk_edit_state edit;
   5494     unsigned int scrolled;
   5495 
   5496     struct nk_table *tables;
   5497     unsigned int table_count;
   5498 
   5499     /* window list hooks */
   5500     struct nk_window *next;
   5501     struct nk_window *prev;
   5502     struct nk_window *parent;
   5503 };
   5504 
   5505 /*==============================================================
   5506  *                          STACK
   5507  * =============================================================*/
   5508 /*/// ### Stack
   5509 /// The style modifier stack can be used to temporarily change a
   5510 /// property inside `nk_style`. For example if you want a special
   5511 /// red button you can temporarily push the old button color onto a stack
   5512 /// draw the button with a red color and then you just pop the old color
   5513 /// back from the stack:
   5514 /// 
   5515 ///     nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
   5516 ///     nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
   5517 ///     nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
   5518 ///     nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
   5519 /// 
   5520 ///     nk_button(...);
   5521 /// 
   5522 ///     nk_style_pop_style_item(ctx);
   5523 ///     nk_style_pop_style_item(ctx);
   5524 ///     nk_style_pop_style_item(ctx);
   5525 ///     nk_style_pop_vec2(ctx);
   5526 /// 
   5527 /// Nuklear has a stack for style_items, float properties, vector properties,
   5528 /// flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
   5529 /// which can be changed at compile time.
   5530  */
   5531 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
   5532 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
   5533 #endif
   5534 
   5535 #ifndef NK_FONT_STACK_SIZE
   5536 #define NK_FONT_STACK_SIZE 8
   5537 #endif
   5538 
   5539 #ifndef NK_STYLE_ITEM_STACK_SIZE
   5540 #define NK_STYLE_ITEM_STACK_SIZE 16
   5541 #endif
   5542 
   5543 #ifndef NK_FLOAT_STACK_SIZE
   5544 #define NK_FLOAT_STACK_SIZE 32
   5545 #endif
   5546 
   5547 #ifndef NK_VECTOR_STACK_SIZE
   5548 #define NK_VECTOR_STACK_SIZE 16
   5549 #endif
   5550 
   5551 #ifndef NK_FLAGS_STACK_SIZE
   5552 #define NK_FLAGS_STACK_SIZE 32
   5553 #endif
   5554 
   5555 #ifndef NK_COLOR_STACK_SIZE
   5556 #define NK_COLOR_STACK_SIZE 32
   5557 #endif
   5558 
   5559 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
   5560     struct nk_config_stack_##name##_element {\
   5561         prefix##_##type *address;\
   5562         prefix##_##type old_value;\
   5563     }
   5564 #define NK_CONFIG_STACK(type,size)\
   5565     struct nk_config_stack_##type {\
   5566         int head;\
   5567         struct nk_config_stack_##type##_element elements[size];\
   5568     }
   5569 
   5570 #define nk_float float
   5571 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
   5572 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
   5573 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
   5574 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags);
   5575 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
   5576 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
   5577 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
   5578 
   5579 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE);
   5580 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE);
   5581 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE);
   5582 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE);
   5583 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE);
   5584 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE);
   5585 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE);
   5586 
   5587 struct nk_configuration_stacks {
   5588     struct nk_config_stack_style_item style_items;
   5589     struct nk_config_stack_float floats;
   5590     struct nk_config_stack_vec2 vectors;
   5591     struct nk_config_stack_flags flags;
   5592     struct nk_config_stack_color colors;
   5593     struct nk_config_stack_user_font fonts;
   5594     struct nk_config_stack_button_behavior button_behaviors;
   5595 };
   5596 
   5597 /*==============================================================
   5598  *                          CONTEXT
   5599  * =============================================================*/
   5600 #define NK_VALUE_PAGE_CAPACITY \
   5601     (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
   5602 
   5603 struct nk_table {
   5604     unsigned int seq;
   5605     unsigned int size;
   5606     nk_hash keys[NK_VALUE_PAGE_CAPACITY];
   5607     nk_uint values[NK_VALUE_PAGE_CAPACITY];
   5608     struct nk_table *next, *prev;
   5609 };
   5610 
   5611 union nk_page_data {
   5612     struct nk_table tbl;
   5613     struct nk_panel pan;
   5614     struct nk_window win;
   5615 };
   5616 
   5617 struct nk_page_element {
   5618     union nk_page_data data;
   5619     struct nk_page_element *next;
   5620     struct nk_page_element *prev;
   5621 };
   5622 
   5623 struct nk_page {
   5624     unsigned int size;
   5625     struct nk_page *next;
   5626     struct nk_page_element win[1];
   5627 };
   5628 
   5629 struct nk_pool {
   5630     struct nk_allocator alloc;
   5631     enum nk_allocation_type type;
   5632     unsigned int page_count;
   5633     struct nk_page *pages;
   5634     struct nk_page_element *freelist;
   5635     unsigned capacity;
   5636     nk_size size;
   5637     nk_size cap;
   5638 };
   5639 
   5640 struct nk_context {
   5641 /* public: can be accessed freely */
   5642     struct nk_input input;
   5643     struct nk_style style;
   5644     struct nk_buffer memory;
   5645     struct nk_clipboard clip;
   5646     nk_flags last_widget_state;
   5647     enum nk_button_behavior button_behavior;
   5648     struct nk_configuration_stacks stacks;
   5649     float delta_time_seconds;
   5650 
   5651 /* private:
   5652     should only be accessed if you
   5653     know what you are doing */
   5654 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   5655     struct nk_draw_list draw_list;
   5656 #endif
   5657 #ifdef NK_INCLUDE_COMMAND_USERDATA
   5658     nk_handle userdata;
   5659 #endif
   5660     /* text editor objects are quite big because of an internal
   5661      * undo/redo stack. Therefore it does not make sense to have one for
   5662      * each window for temporary use cases, so I only provide *one* instance
   5663      * for all windows. This works because the content is cleared anyway */
   5664     struct nk_text_edit text_edit;
   5665     /* draw buffer used for overlay drawing operation like cursor */
   5666     struct nk_command_buffer overlay;
   5667 
   5668     /* windows */
   5669     int build;
   5670     int use_pool;
   5671     struct nk_pool pool;
   5672     struct nk_window *begin;
   5673     struct nk_window *end;
   5674     struct nk_window *active;
   5675     struct nk_window *current;
   5676     struct nk_page_element *freelist;
   5677     unsigned int count;
   5678     unsigned int seq;
   5679 };
   5680 
   5681 /* ==============================================================
   5682  *                          MATH
   5683  * =============================================================== */
   5684 #define NK_PI 3.141592654f
   5685 #define NK_UTF_INVALID 0xFFFD
   5686 #define NK_MAX_FLOAT_PRECISION 2
   5687 
   5688 #define NK_UNUSED(x) ((void)(x))
   5689 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
   5690 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
   5691 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
   5692 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
   5693 #define NK_INBOX(px, py, x, y, w, h)\
   5694     (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
   5695 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
   5696     ((x1 < (x0 + w0)) && (x0 < (x1 + w1)) && \
   5697     (y1 < (y0 + h0)) && (y0 < (y1 + h1)))
   5698 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
   5699     (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
   5700 
   5701 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
   5702 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
   5703 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
   5704 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
   5705 
   5706 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
   5707 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
   5708 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
   5709 
   5710 /* ==============================================================
   5711  *                          ALIGNMENT
   5712  * =============================================================== */
   5713 /* Pointer to Integer type conversion for pointer alignment */
   5714 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
   5715 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
   5716 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
   5717 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
   5718 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
   5719 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
   5720 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
   5721 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
   5722 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
   5723 #else /* generates warning but works */
   5724 # define NK_UINT_TO_PTR(x) ((void*)(x))
   5725 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
   5726 #endif
   5727 
   5728 #define NK_ALIGN_PTR(x, mask)\
   5729     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
   5730 #define NK_ALIGN_PTR_BACK(x, mask)\
   5731     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
   5732 
   5733 #if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)
   5734 #define NK_OFFSETOF(st,m) (__builtin_offsetof(st,m))
   5735 #else
   5736 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
   5737 #endif
   5738 
   5739 #ifdef __cplusplus
   5740 }
   5741 #endif
   5742 
   5743 #ifdef __cplusplus
   5744 template<typename T> struct nk_alignof;
   5745 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
   5746 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
   5747 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
   5748     diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
   5749 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
   5750 #else
   5751 #define NK_ALIGNOF(t) NK_OFFSETOF(struct {char c; t _h;}, _h)
   5752 #endif
   5753 
   5754 #define NK_CONTAINER_OF(ptr,type,member)\
   5755     (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
   5756 
   5757 
   5758 
   5759 #endif /* NK_NUKLEAR_H_ */
   5760 
   5761 #ifdef NK_IMPLEMENTATION
   5762 
   5763 #ifndef NK_INTERNAL_H
   5764 #define NK_INTERNAL_H
   5765 
   5766 #ifndef NK_POOL_DEFAULT_CAPACITY
   5767 #define NK_POOL_DEFAULT_CAPACITY 16
   5768 #endif
   5769 
   5770 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
   5771 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
   5772 #endif
   5773 
   5774 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
   5775 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
   5776 #endif
   5777 
   5778 /* standard library headers */
   5779 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   5780 #include <stdlib.h> /* malloc, free */
   5781 #endif
   5782 #ifdef NK_INCLUDE_STANDARD_IO
   5783 #include <stdio.h> /* fopen, fclose,... */
   5784 #endif
   5785 #ifdef NK_INCLUDE_STANDARD_VARARGS
   5786 #include <stdarg.h> /* valist, va_start, va_end, ... */
   5787 #endif
   5788 #ifndef NK_ASSERT
   5789 #include <assert.h>
   5790 #define NK_ASSERT(expr) assert(expr)
   5791 #endif
   5792 
   5793 #define NK_DEFAULT (-1)
   5794 
   5795 #ifndef NK_VSNPRINTF
   5796 /* If your compiler does support `vsnprintf` I would highly recommend
   5797  * defining this to vsnprintf instead since `vsprintf` is basically
   5798  * unbelievable unsafe and should *NEVER* be used. But I have to support
   5799  * it since C89 only provides this unsafe version. */
   5800   #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
   5801       (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
   5802       (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
   5803       (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
   5804        defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
   5805       #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
   5806   #else
   5807     #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
   5808   #endif
   5809 #endif
   5810 
   5811 #define NK_SCHAR_MIN (-127)
   5812 #define NK_SCHAR_MAX 127
   5813 #define NK_UCHAR_MIN 0
   5814 #define NK_UCHAR_MAX 256
   5815 #define NK_SSHORT_MIN (-32767)
   5816 #define NK_SSHORT_MAX 32767
   5817 #define NK_USHORT_MIN 0
   5818 #define NK_USHORT_MAX 65535
   5819 #define NK_SINT_MIN (-2147483647)
   5820 #define NK_SINT_MAX 2147483647
   5821 #define NK_UINT_MIN 0
   5822 #define NK_UINT_MAX 4294967295u
   5823 
   5824 /* Make sure correct type size:
   5825  * This will fire with a negative subscript error if the type sizes
   5826  * are set incorrectly by the compiler, and compile out if not */
   5827 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
   5828 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
   5829 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
   5830 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
   5831 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
   5832 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
   5833 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
   5834 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
   5835 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
   5836 #ifdef NK_INCLUDE_STANDARD_BOOL
   5837 NK_STATIC_ASSERT(sizeof(nk_bool) == sizeof(bool));
   5838 #else
   5839 NK_STATIC_ASSERT(sizeof(nk_bool) == 4);
   5840 #endif
   5841 
   5842 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
   5843 #define NK_FLOAT_PRECISION 0.00000000000001
   5844 
   5845 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
   5846 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
   5847 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
   5848 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
   5849 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
   5850 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
   5851 
   5852 /* widget */
   5853 #define nk_widget_state_reset(s)\
   5854     if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
   5855         (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
   5856     else (*(s)) = NK_WIDGET_STATE_INACTIVE;
   5857 
   5858 /* math */
   5859 #ifndef NK_INV_SQRT
   5860 NK_LIB float nk_inv_sqrt(float n);
   5861 #endif
   5862 #ifndef NK_SIN
   5863 NK_LIB float nk_sin(float x);
   5864 #endif
   5865 #ifndef NK_COS
   5866 NK_LIB float nk_cos(float x);
   5867 #endif
   5868 NK_LIB nk_uint nk_round_up_pow2(nk_uint v);
   5869 NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount);
   5870 NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad);
   5871 NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1);
   5872 NK_LIB double nk_pow(double x, int n);
   5873 NK_LIB int nk_ifloord(double x);
   5874 NK_LIB int nk_ifloorf(float x);
   5875 NK_LIB int nk_iceilf(float x);
   5876 NK_LIB int nk_log10(double n);
   5877 
   5878 /* util */
   5879 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
   5880 NK_LIB nk_bool nk_is_lower(int c);
   5881 NK_LIB nk_bool nk_is_upper(int c);
   5882 NK_LIB int nk_to_upper(int c);
   5883 NK_LIB int nk_to_lower(int c);
   5884 
   5885 #ifndef NK_MEMCPY
   5886 NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n);
   5887 #endif
   5888 #ifndef NK_MEMSET
   5889 NK_LIB void nk_memset(void *ptr, int c0, nk_size size);
   5890 #endif
   5891 NK_LIB void nk_zero(void *ptr, nk_size size);
   5892 NK_LIB char *nk_itoa(char *s, long n);
   5893 NK_LIB int nk_string_float_limit(char *string, int prec);
   5894 #ifndef NK_DTOA
   5895 NK_LIB char *nk_dtoa(char *s, double n);
   5896 #endif
   5897 NK_LIB int nk_text_clamp(const struct nk_user_font *font, const char *text, int text_len, float space, int *glyphs, float *text_width, nk_rune *sep_list, int sep_count);
   5898 NK_LIB struct nk_vec2 nk_text_calculate_text_bounds(const struct nk_user_font *font, const char *begin, int byte_len, float row_height, const char **remaining, struct nk_vec2 *out_offset, int *glyphs, int op);
   5899 #ifdef NK_INCLUDE_STANDARD_VARARGS
   5900 NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args);
   5901 #endif
   5902 #ifdef NK_INCLUDE_STANDARD_IO
   5903 NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc);
   5904 #endif
   5905 
   5906 /* buffer */
   5907 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   5908 NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size);
   5909 NK_LIB void nk_mfree(nk_handle unused, void *ptr);
   5910 #endif
   5911 NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type);
   5912 NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align);
   5913 NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size);
   5914 
   5915 /* draw */
   5916 NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip);
   5917 NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b);
   5918 NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size);
   5919 NK_LIB void nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, struct nk_rect content, struct nk_color background, struct nk_color foreground, float border_width, const struct nk_user_font *font);
   5920 
   5921 /* buffering */
   5922 NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
   5923 NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win);
   5924 NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win);
   5925 NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*);
   5926 NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
   5927 NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w);
   5928 NK_LIB void nk_build(struct nk_context *ctx);
   5929 
   5930 /* text editor */
   5931 NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter);
   5932 NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
   5933 NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
   5934 NK_LIB void nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, const struct nk_user_font *font, float row_height);
   5935 
   5936 /* window */
   5937 enum nk_window_insert_location {
   5938     NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
   5939     NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
   5940 };
   5941 NK_LIB void *nk_create_window(struct nk_context *ctx);
   5942 NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*);
   5943 NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win);
   5944 NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name);
   5945 NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc);
   5946 
   5947 /* pool */
   5948 NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity);
   5949 NK_LIB void nk_pool_free(struct nk_pool *pool);
   5950 NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size);
   5951 NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool);
   5952 
   5953 /* page-element */
   5954 NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx);
   5955 NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem);
   5956 NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem);
   5957 
   5958 /* table */
   5959 NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx);
   5960 NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
   5961 NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
   5962 NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl);
   5963 NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value);
   5964 NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name);
   5965 
   5966 /* panel */
   5967 NK_LIB void *nk_create_panel(struct nk_context *ctx);
   5968 NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan);
   5969 NK_LIB nk_bool nk_panel_has_header(nk_flags flags, const char *title);
   5970 NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type);
   5971 NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type);
   5972 NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type);
   5973 NK_LIB nk_bool nk_panel_is_sub(enum nk_panel_type type);
   5974 NK_LIB nk_bool nk_panel_is_nonblock(enum nk_panel_type type);
   5975 NK_LIB nk_bool nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type);
   5976 NK_LIB void nk_panel_end(struct nk_context *ctx);
   5977 
   5978 /* layout */
   5979 NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns);
   5980 NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols);
   5981 NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width);
   5982 NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win);
   5983 NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify);
   5984 NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx);
   5985 NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx);
   5986 
   5987 /* popup */
   5988 NK_LIB nk_bool nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type);
   5989 
   5990 /* text */
   5991 struct nk_text {
   5992     struct nk_vec2 padding;
   5993     struct nk_color background;
   5994     struct nk_color text;
   5995 };
   5996 NK_LIB void nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, nk_flags a, const struct nk_user_font *f);
   5997 NK_LIB void nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, const struct nk_user_font *f);
   5998 
   5999 /* button */
   6000 NK_LIB nk_bool nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior);
   6001 NK_LIB const struct nk_style_item* nk_draw_button(struct nk_command_buffer *out, const struct nk_rect *bounds, nk_flags state, const struct nk_style_button *style);
   6002 NK_LIB nk_bool nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, const struct nk_style_button *style, const struct nk_input *in, enum nk_button_behavior behavior, struct nk_rect *content);
   6003 NK_LIB void nk_draw_button_text(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const char *txt, int len, nk_flags text_alignment, const struct nk_user_font *font);
   6004 NK_LIB nk_bool nk_do_button_text(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *string, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
   6005 NK_LIB void nk_draw_button_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, enum nk_symbol_type type, const struct nk_user_font *font);
   6006 NK_LIB nk_bool nk_do_button_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
   6007 NK_LIB void nk_draw_button_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const struct nk_image *img);
   6008 NK_LIB nk_bool nk_do_button_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, enum nk_button_behavior b, const struct nk_style_button *style, const struct nk_input *in);
   6009 NK_LIB void nk_draw_button_text_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, const char *str, int len, enum nk_symbol_type type, const struct nk_user_font *font);
   6010 NK_LIB nk_bool nk_do_button_text_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, const char *str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
   6011 NK_LIB void nk_draw_button_text_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, const char *str, int len, const struct nk_user_font *font, const struct nk_image *img);
   6012 NK_LIB nk_bool nk_do_button_text_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, const char* str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
   6013 
   6014 /* toggle */
   6015 enum nk_toggle_type {
   6016     NK_TOGGLE_CHECK,
   6017     NK_TOGGLE_OPTION
   6018 };
   6019 NK_LIB nk_bool nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, nk_bool active);
   6020 NK_LIB void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, nk_bool active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
   6021 NK_LIB void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, nk_bool active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
   6022 NK_LIB nk_bool nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, nk_bool *active, const char *str, int len, enum nk_toggle_type type, const struct nk_style_toggle *style, const struct nk_input *in, const struct nk_user_font *font);
   6023 
   6024 /* progress */
   6025 NK_LIB nk_size nk_progress_behavior(nk_flags *state, struct nk_input *in, struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, nk_bool modifiable);
   6026 NK_LIB void nk_draw_progress(struct nk_command_buffer *out, nk_flags state, const struct nk_style_progress *style, const struct nk_rect *bounds, const struct nk_rect *scursor, nk_size value, nk_size max);
   6027 NK_LIB nk_size nk_do_progress(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_size value, nk_size max, nk_bool modifiable, const struct nk_style_progress *style, struct nk_input *in);
   6028 
   6029 /* slider */
   6030 NK_LIB float nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, struct nk_rect *visual_cursor, struct nk_input *in, struct nk_rect bounds, float slider_min, float slider_max, float slider_value, float slider_step, float slider_steps);
   6031 NK_LIB void nk_draw_slider(struct nk_command_buffer *out, nk_flags state, const struct nk_style_slider *style, const struct nk_rect *bounds, const struct nk_rect *visual_cursor, float min, float value, float max);
   6032 NK_LIB float nk_do_slider(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, float min, float val, float max, float step, const struct nk_style_slider *style, struct nk_input *in, const struct nk_user_font *font);
   6033 
   6034 /* scrollbar */
   6035 NK_LIB float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o);
   6036 NK_LIB void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll);
   6037 NK_LIB float nk_do_scrollbarv(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
   6038 NK_LIB float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
   6039 
   6040 /* selectable */
   6041 NK_LIB void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, nk_bool active, const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, const char *string, int len, nk_flags align, const struct nk_user_font *font);
   6042 NK_LIB nk_bool nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
   6043 NK_LIB nk_bool nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
   6044 
   6045 /* edit */
   6046 NK_LIB void nk_edit_draw_text(struct nk_command_buffer *out, const struct nk_style_edit *style, float pos_x, float pos_y, float x_offset, const char *text, int byte_len, float row_height, const struct nk_user_font *font, struct nk_color background, struct nk_color foreground, nk_bool is_selected);
   6047 NK_LIB nk_flags nk_do_edit(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, struct nk_text_edit *edit, const struct nk_style_edit *style, struct nk_input *in, const struct nk_user_font *font);
   6048 
   6049 /* color-picker */
   6050 NK_LIB nk_bool nk_color_picker_behavior(nk_flags *state, const struct nk_rect *bounds, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf *color, const struct nk_input *in);
   6051 NK_LIB void nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf col);
   6052 NK_LIB nk_bool nk_do_color_picker(nk_flags *state, struct nk_command_buffer *out, struct nk_colorf *col, enum nk_color_format fmt, struct nk_rect bounds, struct nk_vec2 padding, const struct nk_input *in, const struct nk_user_font *font);
   6053 
   6054 /* property */
   6055 enum nk_property_status {
   6056     NK_PROPERTY_DEFAULT,
   6057     NK_PROPERTY_EDIT,
   6058     NK_PROPERTY_DRAG
   6059 };
   6060 enum nk_property_filter {
   6061     NK_FILTER_INT,
   6062     NK_FILTER_FLOAT
   6063 };
   6064 enum nk_property_kind {
   6065     NK_PROPERTY_INT,
   6066     NK_PROPERTY_FLOAT,
   6067     NK_PROPERTY_DOUBLE
   6068 };
   6069 union nk_property {
   6070     int i;
   6071     float f;
   6072     double d;
   6073 };
   6074 struct nk_property_variant {
   6075     enum nk_property_kind kind;
   6076     union nk_property value;
   6077     union nk_property min_value;
   6078     union nk_property max_value;
   6079     union nk_property step;
   6080 };
   6081 NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step);
   6082 NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step);
   6083 NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step);
   6084 
   6085 NK_LIB void nk_drag_behavior(nk_flags *state, const struct nk_input *in, struct nk_rect drag, struct nk_property_variant *variant, float inc_per_pixel);
   6086 NK_LIB void nk_property_behavior(nk_flags *ws, const struct nk_input *in, struct nk_rect property,  struct nk_rect label, struct nk_rect edit, struct nk_rect empty, int *state, struct nk_property_variant *variant, float inc_per_pixel);
   6087 NK_LIB void nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, const char *name, int len, const struct nk_user_font *font);
   6088 NK_LIB void nk_do_property(nk_flags *ws, struct nk_command_buffer *out, struct nk_rect property, const char *name, struct nk_property_variant *variant, float inc_per_pixel, char *buffer, int *len, int *state, int *cursor, int *select_begin, int *select_end, const struct nk_style_property *style, enum nk_property_filter filter, struct nk_input *in, const struct nk_user_font *font, struct nk_text_edit *text_edit, enum nk_button_behavior behavior);
   6089 NK_LIB void nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, float inc_per_pixel, const enum nk_property_filter filter);
   6090 
   6091 #ifdef NK_INCLUDE_FONT_BAKING
   6092 
   6093 #define STB_RECT_PACK_IMPLEMENTATION
   6094 #define STB_TRUETYPE_IMPLEMENTATION
   6095 
   6096 /* Allow consumer to define own STBTT_malloc/STBTT_free, and use the font atlas' allocator otherwise */
   6097 #ifndef STBTT_malloc
   6098 static void*
   6099 nk_stbtt_malloc(nk_size size, void *user_data) {
   6100 	struct nk_allocator *alloc = (struct nk_allocator *) user_data;
   6101 	return alloc->alloc(alloc->userdata, 0, size);
   6102 }
   6103 
   6104 static void
   6105 nk_stbtt_free(void *ptr, void *user_data) {
   6106 	struct nk_allocator *alloc = (struct nk_allocator *) user_data;
   6107 	alloc->free(alloc->userdata, ptr);
   6108 }
   6109 
   6110 #define STBTT_malloc(x,u)  nk_stbtt_malloc(x,u)
   6111 #define STBTT_free(x,u)    nk_stbtt_free(x,u)
   6112 
   6113 #endif /* STBTT_malloc */
   6114 
   6115 #endif /* NK_INCLUDE_FONT_BAKING */
   6116 
   6117 #endif
   6118 
   6119 
   6120 
   6121 
   6122 
   6123 /* ===============================================================
   6124  *
   6125  *                              MATH
   6126  *
   6127  * ===============================================================*/
   6128 /*/// ### Math
   6129 ///  Since nuklear is supposed to work on all systems providing floating point
   6130 ///  math without any dependencies I also had to implement my own math functions
   6131 ///  for sqrt, sin and cos. Since the actual highly accurate implementations for
   6132 ///  the standard library functions are quite complex and I do not need high
   6133 ///  precision for my use cases I use approximations.
   6134 ///
   6135 ///  Sqrt
   6136 ///  ----
   6137 ///  For square root nuklear uses the famous fast inverse square root:
   6138 ///  https://en.wikipedia.org/wiki/Fast_inverse_square_root with
   6139 ///  slightly tweaked magic constant. While on today's hardware it is
   6140 ///  probably not faster it is still fast and accurate enough for
   6141 ///  nuklear's use cases. IMPORTANT: this requires float format IEEE 754
   6142 ///
   6143 ///  Sine/Cosine
   6144 ///  -----------
   6145 ///  All constants inside both function are generated Remez's minimax
   6146 ///  approximations for value range 0...2*PI. The reason why I decided to
   6147 ///  approximate exactly that range is that nuklear only needs sine and
   6148 ///  cosine to generate circles which only requires that exact range.
   6149 ///  In addition I used Remez instead of Taylor for additional precision:
   6150 ///  www.lolengine.net/blog/2011/12/21/better-function-approximations.
   6151 ///
   6152 ///  The tool I used to generate constants for both sine and cosine
   6153 ///  (it can actually approximate a lot more functions) can be
   6154 ///  found here: www.lolengine.net/wiki/oss/lolremez
   6155 */
   6156 #ifndef NK_INV_SQRT
   6157 #define NK_INV_SQRT nk_inv_sqrt
   6158 NK_LIB float
   6159 nk_inv_sqrt(float n)
   6160 {
   6161     float x2;
   6162     const float threehalfs = 1.5f;
   6163     union {nk_uint i; float f;} conv = {0};
   6164     conv.f = n;
   6165     x2 = n * 0.5f;
   6166     conv.i = 0x5f375A84 - (conv.i >> 1);
   6167     conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
   6168     return conv.f;
   6169 }
   6170 #endif
   6171 #ifndef NK_SIN
   6172 #define NK_SIN nk_sin
   6173 NK_LIB float
   6174 nk_sin(float x)
   6175 {
   6176     NK_STORAGE const float a0 = +1.91059300966915117e-31f;
   6177     NK_STORAGE const float a1 = +1.00086760103908896f;
   6178     NK_STORAGE const float a2 = -1.21276126894734565e-2f;
   6179     NK_STORAGE const float a3 = -1.38078780785773762e-1f;
   6180     NK_STORAGE const float a4 = -2.67353392911981221e-2f;
   6181     NK_STORAGE const float a5 = +2.08026600266304389e-2f;
   6182     NK_STORAGE const float a6 = -3.03996055049204407e-3f;
   6183     NK_STORAGE const float a7 = +1.38235642404333740e-4f;
   6184     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
   6185 }
   6186 #endif
   6187 #ifndef NK_COS
   6188 #define NK_COS nk_cos
   6189 NK_LIB float
   6190 nk_cos(float x)
   6191 {
   6192     /* New implementation. Also generated using lolremez. */
   6193     /* Old version significantly deviated from expected results. */
   6194     NK_STORAGE const float a0 = 9.9995999154986614e-1f;
   6195     NK_STORAGE const float a1 = 1.2548995793001028e-3f;
   6196     NK_STORAGE const float a2 = -5.0648546280678015e-1f;
   6197     NK_STORAGE const float a3 = 1.2942246466519995e-2f;
   6198     NK_STORAGE const float a4 = 2.8668384702547972e-2f;
   6199     NK_STORAGE const float a5 = 7.3726485210586547e-3f;
   6200     NK_STORAGE const float a6 = -3.8510875386947414e-3f;
   6201     NK_STORAGE const float a7 = 4.7196604604366623e-4f;
   6202     NK_STORAGE const float a8 = -1.8776444013090451e-5f;
   6203     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8)))))));
   6204 }
   6205 #endif
   6206 NK_LIB nk_uint
   6207 nk_round_up_pow2(nk_uint v)
   6208 {
   6209     v--;
   6210     v |= v >> 1;
   6211     v |= v >> 2;
   6212     v |= v >> 4;
   6213     v |= v >> 8;
   6214     v |= v >> 16;
   6215     v++;
   6216     return v;
   6217 }
   6218 NK_LIB double
   6219 nk_pow(double x, int n)
   6220 {
   6221     /*  check the sign of n */
   6222     double r = 1;
   6223     int plus = n >= 0;
   6224     n = (plus) ? n : -n;
   6225     while (n > 0) {
   6226         if ((n & 1) == 1)
   6227             r *= x;
   6228         n /= 2;
   6229         x *= x;
   6230     }
   6231     return plus ? r : 1.0 / r;
   6232 }
   6233 NK_LIB int
   6234 nk_ifloord(double x)
   6235 {
   6236     x = (double)((int)x - ((x < 0.0) ? 1 : 0));
   6237     return (int)x;
   6238 }
   6239 NK_LIB int
   6240 nk_ifloorf(float x)
   6241 {
   6242     x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
   6243     return (int)x;
   6244 }
   6245 NK_LIB int
   6246 nk_iceilf(float x)
   6247 {
   6248     if (x >= 0) {
   6249         int i = (int)x;
   6250         return (x > i) ? i+1: i;
   6251     } else {
   6252         int t = (int)x;
   6253         float r = x - (float)t;
   6254         return (r > 0.0f) ? t+1: t;
   6255     }
   6256 }
   6257 NK_LIB int
   6258 nk_log10(double n)
   6259 {
   6260     int neg;
   6261     int ret;
   6262     int exp = 0;
   6263 
   6264     neg = (n < 0) ? 1 : 0;
   6265     ret = (neg) ? (int)-n : (int)n;
   6266     while ((ret / 10) > 0) {
   6267         ret /= 10;
   6268         exp++;
   6269     }
   6270     if (neg) exp = -exp;
   6271     return exp;
   6272 }
   6273 NK_API struct nk_rect
   6274 nk_get_null_rect(void)
   6275 {
   6276     return nk_null_rect;
   6277 }
   6278 NK_API struct nk_rect
   6279 nk_rect(float x, float y, float w, float h)
   6280 {
   6281     struct nk_rect r;
   6282     r.x = x; r.y = y;
   6283     r.w = w; r.h = h;
   6284     return r;
   6285 }
   6286 NK_API struct nk_rect
   6287 nk_recti(int x, int y, int w, int h)
   6288 {
   6289     struct nk_rect r;
   6290     r.x = (float)x;
   6291     r.y = (float)y;
   6292     r.w = (float)w;
   6293     r.h = (float)h;
   6294     return r;
   6295 }
   6296 NK_API struct nk_rect
   6297 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
   6298 {
   6299     return nk_rect(pos.x, pos.y, size.x, size.y);
   6300 }
   6301 NK_API struct nk_rect
   6302 nk_rectv(const float *r)
   6303 {
   6304     return nk_rect(r[0], r[1], r[2], r[3]);
   6305 }
   6306 NK_API struct nk_rect
   6307 nk_rectiv(const int *r)
   6308 {
   6309     return nk_recti(r[0], r[1], r[2], r[3]);
   6310 }
   6311 NK_API struct nk_vec2
   6312 nk_rect_pos(struct nk_rect r)
   6313 {
   6314     struct nk_vec2 ret;
   6315     ret.x = r.x; ret.y = r.y;
   6316     return ret;
   6317 }
   6318 NK_API struct nk_vec2
   6319 nk_rect_size(struct nk_rect r)
   6320 {
   6321     struct nk_vec2 ret;
   6322     ret.x = r.w; ret.y = r.h;
   6323     return ret;
   6324 }
   6325 NK_LIB struct nk_rect
   6326 nk_shrink_rect(struct nk_rect r, float amount)
   6327 {
   6328     struct nk_rect res;
   6329     r.w = NK_MAX(r.w, 2 * amount);
   6330     r.h = NK_MAX(r.h, 2 * amount);
   6331     res.x = r.x + amount;
   6332     res.y = r.y + amount;
   6333     res.w = r.w - 2 * amount;
   6334     res.h = r.h - 2 * amount;
   6335     return res;
   6336 }
   6337 NK_LIB struct nk_rect
   6338 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
   6339 {
   6340     r.w = NK_MAX(r.w, 2 * pad.x);
   6341     r.h = NK_MAX(r.h, 2 * pad.y);
   6342     r.x += pad.x; r.y += pad.y;
   6343     r.w -= 2 * pad.x;
   6344     r.h -= 2 * pad.y;
   6345     return r;
   6346 }
   6347 NK_API struct nk_vec2
   6348 nk_vec2(float x, float y)
   6349 {
   6350     struct nk_vec2 ret;
   6351     ret.x = x; ret.y = y;
   6352     return ret;
   6353 }
   6354 NK_API struct nk_vec2
   6355 nk_vec2i(int x, int y)
   6356 {
   6357     struct nk_vec2 ret;
   6358     ret.x = (float)x;
   6359     ret.y = (float)y;
   6360     return ret;
   6361 }
   6362 NK_API struct nk_vec2
   6363 nk_vec2v(const float *v)
   6364 {
   6365     return nk_vec2(v[0], v[1]);
   6366 }
   6367 NK_API struct nk_vec2
   6368 nk_vec2iv(const int *v)
   6369 {
   6370     return nk_vec2i(v[0], v[1]);
   6371 }
   6372 NK_LIB void
   6373 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
   6374     float x1, float y1)
   6375 {
   6376     NK_ASSERT(a);
   6377     NK_ASSERT(clip);
   6378     clip->x = NK_MAX(a->x, x0);
   6379     clip->y = NK_MAX(a->y, y0);
   6380     clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
   6381     clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
   6382     clip->w = NK_MAX(0, clip->w);
   6383     clip->h = NK_MAX(0, clip->h);
   6384 }
   6385 
   6386 NK_API void
   6387 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
   6388     float pad_x, float pad_y, enum nk_heading direction)
   6389 {
   6390     float w_half, h_half;
   6391     NK_ASSERT(result);
   6392 
   6393     r.w = NK_MAX(2 * pad_x, r.w);
   6394     r.h = NK_MAX(2 * pad_y, r.h);
   6395     r.w = r.w - 2 * pad_x;
   6396     r.h = r.h - 2 * pad_y;
   6397 
   6398     r.x = r.x + pad_x;
   6399     r.y = r.y + pad_y;
   6400 
   6401     w_half = r.w / 2.0f;
   6402     h_half = r.h / 2.0f;
   6403 
   6404     if (direction == NK_UP) {
   6405         result[0] = nk_vec2(r.x + w_half, r.y);
   6406         result[1] = nk_vec2(r.x + r.w, r.y + r.h);
   6407         result[2] = nk_vec2(r.x, r.y + r.h);
   6408     } else if (direction == NK_RIGHT) {
   6409         result[0] = nk_vec2(r.x, r.y);
   6410         result[1] = nk_vec2(r.x + r.w, r.y + h_half);
   6411         result[2] = nk_vec2(r.x, r.y + r.h);
   6412     } else if (direction == NK_DOWN) {
   6413         result[0] = nk_vec2(r.x, r.y);
   6414         result[1] = nk_vec2(r.x + r.w, r.y);
   6415         result[2] = nk_vec2(r.x + w_half, r.y + r.h);
   6416     } else {
   6417         result[0] = nk_vec2(r.x, r.y + h_half);
   6418         result[1] = nk_vec2(r.x + r.w, r.y);
   6419         result[2] = nk_vec2(r.x + r.w, r.y + r.h);
   6420     }
   6421 }
   6422 
   6423 
   6424 
   6425 
   6426 
   6427 /* ===============================================================
   6428  *
   6429  *                              UTIL
   6430  *
   6431  * ===============================================================*/
   6432 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
   6433 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
   6434 NK_LIB nk_bool nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
   6435 NK_LIB nk_bool nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
   6436 NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
   6437 NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
   6438 
   6439 #ifndef NK_MEMCPY
   6440 #define NK_MEMCPY nk_memcopy
   6441 NK_LIB void*
   6442 nk_memcopy(void *dst0, const void *src0, nk_size length)
   6443 {
   6444     nk_ptr t;
   6445     char *dst = (char*)dst0;
   6446     const char *src = (const char*)src0;
   6447     if (length == 0 || dst == src)
   6448         goto done;
   6449 
   6450     #define nk_word int
   6451     #define nk_wsize sizeof(nk_word)
   6452     #define nk_wmask (nk_wsize-1)
   6453     #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
   6454     #define NK_TLOOP1(s) do { s; } while (--t)
   6455 
   6456     if (dst < src) {
   6457         t = (nk_ptr)src; /* only need low bits */
   6458         if ((t | (nk_ptr)dst) & nk_wmask) {
   6459             if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
   6460                 t = length;
   6461             else
   6462                 t = nk_wsize - (t & nk_wmask);
   6463             length -= t;
   6464             NK_TLOOP1(*dst++ = *src++);
   6465         }
   6466         t = length / nk_wsize;
   6467         NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
   6468             src += nk_wsize; dst += nk_wsize);
   6469         t = length & nk_wmask;
   6470         NK_TLOOP(*dst++ = *src++);
   6471     } else {
   6472         src += length;
   6473         dst += length;
   6474         t = (nk_ptr)src;
   6475         if ((t | (nk_ptr)dst) & nk_wmask) {
   6476             if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
   6477                 t = length;
   6478             else
   6479                 t &= nk_wmask;
   6480             length -= t;
   6481             NK_TLOOP1(*--dst = *--src);
   6482         }
   6483         t = length / nk_wsize;
   6484         NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
   6485             *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
   6486         t = length & nk_wmask;
   6487         NK_TLOOP(*--dst = *--src);
   6488     }
   6489     #undef nk_word
   6490     #undef nk_wsize
   6491     #undef nk_wmask
   6492     #undef NK_TLOOP
   6493     #undef NK_TLOOP1
   6494 done:
   6495     return (dst0);
   6496 }
   6497 #endif
   6498 #ifndef NK_MEMSET
   6499 #define NK_MEMSET nk_memset
   6500 NK_LIB void
   6501 nk_memset(void *ptr, int c0, nk_size size)
   6502 {
   6503     #define nk_word unsigned
   6504     #define nk_wsize sizeof(nk_word)
   6505     #define nk_wmask (nk_wsize - 1)
   6506     nk_byte *dst = (nk_byte*)ptr;
   6507     unsigned c = 0;
   6508     nk_size t = 0;
   6509 
   6510     if ((c = (nk_byte)c0) != 0) {
   6511         c = (c << 8) | c; /* at least 16-bits  */
   6512         if (sizeof(unsigned int) > 2)
   6513             c = (c << 16) | c; /* at least 32-bits*/
   6514     }
   6515 
   6516     /* too small of a word count */
   6517     dst = (nk_byte*)ptr;
   6518     if (size < 3 * nk_wsize) {
   6519         while (size--) *dst++ = (nk_byte)c0;
   6520         return;
   6521     }
   6522 
   6523     /* align destination */
   6524     if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
   6525         t = nk_wsize -t;
   6526         size -= t;
   6527         do {
   6528             *dst++ = (nk_byte)c0;
   6529         } while (--t != 0);
   6530     }
   6531 
   6532     /* fill word */
   6533     t = size / nk_wsize;
   6534     do {
   6535         *(nk_word*)((void*)dst) = c;
   6536         dst += nk_wsize;
   6537     } while (--t != 0);
   6538 
   6539     /* fill trailing bytes */
   6540     t = (size & nk_wmask);
   6541     if (t != 0) {
   6542         do {
   6543             *dst++ = (nk_byte)c0;
   6544         } while (--t != 0);
   6545     }
   6546 
   6547     #undef nk_word
   6548     #undef nk_wsize
   6549     #undef nk_wmask
   6550 }
   6551 #endif
   6552 NK_LIB void
   6553 nk_zero(void *ptr, nk_size size)
   6554 {
   6555     NK_ASSERT(ptr);
   6556     NK_MEMSET(ptr, 0, size);
   6557 }
   6558 NK_API int
   6559 nk_strlen(const char *str)
   6560 {
   6561     int siz = 0;
   6562     NK_ASSERT(str);
   6563     while (str && *str++ != '\0') siz++;
   6564     return siz;
   6565 }
   6566 NK_API int
   6567 nk_strtoi(const char *str, const char **endptr)
   6568 {
   6569     int neg = 1;
   6570     const char *p = str;
   6571     int value = 0;
   6572 
   6573     NK_ASSERT(str);
   6574     if (!str) return 0;
   6575 
   6576     /* skip whitespace */
   6577     while (*p == ' ') p++;
   6578     if (*p == '-') {
   6579         neg = -1;
   6580         p++;
   6581     }
   6582     while (*p && *p >= '0' && *p <= '9') {
   6583         value = value * 10 + (int) (*p - '0');
   6584         p++;
   6585     }
   6586     if (endptr)
   6587         *endptr = p;
   6588     return neg*value;
   6589 }
   6590 NK_API double
   6591 nk_strtod(const char *str, const char **endptr)
   6592 {
   6593     double m;
   6594     double neg = 1.0;
   6595     const char *p = str;
   6596     double value = 0;
   6597     double number = 0;
   6598 
   6599     NK_ASSERT(str);
   6600     if (!str) return 0;
   6601 
   6602     /* skip whitespace */
   6603     while (*p == ' ') p++;
   6604     if (*p == '-') {
   6605         neg = -1.0;
   6606         p++;
   6607     }
   6608 
   6609     while (*p && *p != '.' && *p != 'e') {
   6610         value = value * 10.0 + (double) (*p - '0');
   6611         p++;
   6612     }
   6613 
   6614     if (*p == '.') {
   6615         p++;
   6616         for(m = 0.1; *p && *p != 'e'; p++ ) {
   6617             value = value + (double) (*p - '0') * m;
   6618             m *= 0.1;
   6619         }
   6620     }
   6621     if (*p == 'e') {
   6622         int i, pow, div;
   6623         p++;
   6624         if (*p == '-') {
   6625             div = nk_true;
   6626             p++;
   6627         } else if (*p == '+') {
   6628             div = nk_false;
   6629             p++;
   6630         } else div = nk_false;
   6631 
   6632         for (pow = 0; *p; p++)
   6633             pow = pow * 10 + (int) (*p - '0');
   6634 
   6635         for (m = 1.0, i = 0; i < pow; i++)
   6636             m *= 10.0;
   6637 
   6638         if (div)
   6639             value /= m;
   6640         else value *= m;
   6641     }
   6642     number = value * neg;
   6643     if (endptr)
   6644         *endptr = p;
   6645     return number;
   6646 }
   6647 NK_API float
   6648 nk_strtof(const char *str, const char **endptr)
   6649 {
   6650     float float_value;
   6651     double double_value;
   6652     double_value = NK_STRTOD(str, endptr);
   6653     float_value = (float)double_value;
   6654     return float_value;
   6655 }
   6656 NK_API int
   6657 nk_stricmp(const char *s1, const char *s2)
   6658 {
   6659     nk_int c1,c2,d;
   6660     do {
   6661         c1 = *s1++;
   6662         c2 = *s2++;
   6663         d = c1 - c2;
   6664         while (d) {
   6665             if (c1 <= 'Z' && c1 >= 'A') {
   6666                 d += ('a' - 'A');
   6667                 if (!d) break;
   6668             }
   6669             if (c2 <= 'Z' && c2 >= 'A') {
   6670                 d -= ('a' - 'A');
   6671                 if (!d) break;
   6672             }
   6673             return ((d >= 0) << 1) - 1;
   6674         }
   6675     } while (c1);
   6676     return 0;
   6677 }
   6678 NK_API int
   6679 nk_stricmpn(const char *s1, const char *s2, int n)
   6680 {
   6681     int c1,c2,d;
   6682     NK_ASSERT(n >= 0);
   6683     do {
   6684         c1 = *s1++;
   6685         c2 = *s2++;
   6686         if (!n--) return 0;
   6687 
   6688         d = c1 - c2;
   6689         while (d) {
   6690             if (c1 <= 'Z' && c1 >= 'A') {
   6691                 d += ('a' - 'A');
   6692                 if (!d) break;
   6693             }
   6694             if (c2 <= 'Z' && c2 >= 'A') {
   6695                 d -= ('a' - 'A');
   6696                 if (!d) break;
   6697             }
   6698             return ((d >= 0) << 1) - 1;
   6699         }
   6700     } while (c1);
   6701     return 0;
   6702 }
   6703 NK_INTERN int
   6704 nk_str_match_here(const char *regexp, const char *text)
   6705 {
   6706     if (regexp[0] == '\0')
   6707         return 1;
   6708     if (regexp[1] == '*')
   6709         return nk_str_match_star(regexp[0], regexp+2, text);
   6710     if (regexp[0] == '$' && regexp[1] == '\0')
   6711         return *text == '\0';
   6712     if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
   6713         return nk_str_match_here(regexp+1, text+1);
   6714     return 0;
   6715 }
   6716 NK_INTERN int
   6717 nk_str_match_star(int c, const char *regexp, const char *text)
   6718 {
   6719     do {/* a '* matches zero or more instances */
   6720         if (nk_str_match_here(regexp, text))
   6721             return 1;
   6722     } while (*text != '\0' && (*text++ == c || c == '.'));
   6723     return 0;
   6724 }
   6725 NK_API int
   6726 nk_strfilter(const char *text, const char *regexp)
   6727 {
   6728     /*
   6729     c    matches any literal character c
   6730     .    matches any single character
   6731     ^    matches the beginning of the input string
   6732     $    matches the end of the input string
   6733     *    matches zero or more occurrences of the previous character*/
   6734     if (regexp[0] == '^')
   6735         return nk_str_match_here(regexp+1, text);
   6736     do {    /* must look even if string is empty */
   6737         if (nk_str_match_here(regexp, text))
   6738             return 1;
   6739     } while (*text++ != '\0');
   6740     return 0;
   6741 }
   6742 NK_API int
   6743 nk_strmatch_fuzzy_text(const char *str, int str_len,
   6744     const char *pattern, int *out_score)
   6745 {
   6746     /* Returns true if each character in pattern is found sequentially within str
   6747      * if found then out_score is also set. Score value has no intrinsic meaning.
   6748      * Range varies with pattern. Can only compare scores with same search pattern. */
   6749 
   6750     /* bonus for adjacent matches */
   6751     #define NK_ADJACENCY_BONUS 5
   6752     /* bonus if match occurs after a separator */
   6753     #define NK_SEPARATOR_BONUS 10
   6754     /* bonus if match is uppercase and prev is lower */
   6755     #define NK_CAMEL_BONUS 10
   6756     /* penalty applied for every letter in str before the first match */
   6757     #define NK_LEADING_LETTER_PENALTY (-3)
   6758     /* maximum penalty for leading letters */
   6759     #define NK_MAX_LEADING_LETTER_PENALTY (-9)
   6760     /* penalty for every letter that doesn't matter */
   6761     #define NK_UNMATCHED_LETTER_PENALTY (-1)
   6762 
   6763     /* loop variables */
   6764     int score = 0;
   6765     char const * pattern_iter = pattern;
   6766     int str_iter = 0;
   6767     int prev_matched = nk_false;
   6768     int prev_lower = nk_false;
   6769     /* true so if first letter match gets separator bonus*/
   6770     int prev_separator = nk_true;
   6771 
   6772     /* use "best" matched letter if multiple string letters match the pattern */
   6773     char const * best_letter = 0;
   6774     int best_letter_score = 0;
   6775 
   6776     /* loop over strings */
   6777     NK_ASSERT(str);
   6778     NK_ASSERT(pattern);
   6779     if (!str || !str_len || !pattern) return 0;
   6780     while (str_iter < str_len)
   6781     {
   6782         const char pattern_letter = *pattern_iter;
   6783         const char str_letter = str[str_iter];
   6784 
   6785         int next_match = *pattern_iter != '\0' &&
   6786             nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
   6787         int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
   6788 
   6789         int advanced = next_match && best_letter;
   6790         int pattern_repeat = best_letter && *pattern_iter != '\0';
   6791         pattern_repeat = pattern_repeat &&
   6792             nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
   6793 
   6794         if (advanced || pattern_repeat) {
   6795             score += best_letter_score;
   6796             best_letter = 0;
   6797             best_letter_score = 0;
   6798         }
   6799 
   6800         if (next_match || rematch)
   6801         {
   6802             int new_score = 0;
   6803             /* Apply penalty for each letter before the first pattern match */
   6804             if (pattern_iter == pattern) {
   6805                 int count = (int)(&str[str_iter] - str);
   6806                 int penalty = NK_LEADING_LETTER_PENALTY * count;
   6807                 if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
   6808                     penalty = NK_MAX_LEADING_LETTER_PENALTY;
   6809 
   6810                 score += penalty;
   6811             }
   6812 
   6813             /* apply bonus for consecutive bonuses */
   6814             if (prev_matched)
   6815                 new_score += NK_ADJACENCY_BONUS;
   6816 
   6817             /* apply bonus for matches after a separator */
   6818             if (prev_separator)
   6819                 new_score += NK_SEPARATOR_BONUS;
   6820 
   6821             /* apply bonus across camel case boundaries */
   6822             if (prev_lower && nk_is_upper(str_letter))
   6823                 new_score += NK_CAMEL_BONUS;
   6824 
   6825             /* update pattern iter IFF the next pattern letter was matched */
   6826             if (next_match)
   6827                 ++pattern_iter;
   6828 
   6829             /* update best letter in str which may be for a "next" letter or a rematch */
   6830             if (new_score >= best_letter_score) {
   6831                 /* apply penalty for now skipped letter */
   6832                 if (best_letter != 0)
   6833                     score += NK_UNMATCHED_LETTER_PENALTY;
   6834 
   6835                 best_letter = &str[str_iter];
   6836                 best_letter_score = new_score;
   6837             }
   6838             prev_matched = nk_true;
   6839         } else {
   6840             score += NK_UNMATCHED_LETTER_PENALTY;
   6841             prev_matched = nk_false;
   6842         }
   6843 
   6844         /* separators should be more easily defined */
   6845         prev_lower = nk_is_lower(str_letter) != 0;
   6846         prev_separator = str_letter == '_' || str_letter == ' ';
   6847 
   6848         ++str_iter;
   6849     }
   6850 
   6851     /* apply score for last match */
   6852     if (best_letter)
   6853         score += best_letter_score;
   6854 
   6855     /* did not match full pattern */
   6856     if (*pattern_iter != '\0')
   6857         return nk_false;
   6858 
   6859     if (out_score)
   6860         *out_score = score;
   6861     return nk_true;
   6862 }
   6863 NK_API int
   6864 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
   6865 {
   6866     return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);
   6867 }
   6868 NK_LIB int
   6869 nk_string_float_limit(char *string, int prec)
   6870 {
   6871     int dot = 0;
   6872     char *c = string;
   6873     while (*c) {
   6874         if (*c == '.') {
   6875             dot = 1;
   6876             c++;
   6877             continue;
   6878         }
   6879         if (dot == (prec+1)) {
   6880             *c = 0;
   6881             break;
   6882         }
   6883         if (dot > 0) dot++;
   6884         c++;
   6885     }
   6886     return (int)(c - string);
   6887 }
   6888 NK_INTERN void
   6889 nk_strrev_ascii(char *s)
   6890 {
   6891     int len = nk_strlen(s);
   6892     int end = len / 2;
   6893     int i = 0;
   6894     char t;
   6895     for (; i < end; ++i) {
   6896         t = s[i];
   6897         s[i] = s[len - 1 - i];
   6898         s[len -1 - i] = t;
   6899     }
   6900 }
   6901 NK_LIB char*
   6902 nk_itoa(char *s, long n)
   6903 {
   6904     long i = 0;
   6905     if (n == 0) {
   6906         s[i++] = '0';
   6907         s[i] = 0;
   6908         return s;
   6909     }
   6910     if (n < 0) {
   6911         s[i++] = '-';
   6912         n = -n;
   6913     }
   6914     while (n > 0) {
   6915         s[i++] = (char)('0' + (n % 10));
   6916         n /= 10;
   6917     }
   6918     s[i] = 0;
   6919     if (s[0] == '-')
   6920         ++s;
   6921 
   6922     nk_strrev_ascii(s);
   6923     return s;
   6924 }
   6925 #ifndef NK_DTOA
   6926 #define NK_DTOA nk_dtoa
   6927 NK_LIB char*
   6928 nk_dtoa(char *s, double n)
   6929 {
   6930     int useExp = 0;
   6931     int digit = 0, m = 0, m1 = 0;
   6932     char *c = s;
   6933     int neg = 0;
   6934 
   6935     NK_ASSERT(s);
   6936     if (!s) return 0;
   6937 
   6938     if (n == 0.0) {
   6939         s[0] = '0'; s[1] = '\0';
   6940         return s;
   6941     }
   6942 
   6943     neg = (n < 0);
   6944     if (neg) n = -n;
   6945 
   6946     /* calculate magnitude */
   6947     m = nk_log10(n);
   6948     useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
   6949     if (neg) *(c++) = '-';
   6950 
   6951     /* set up for scientific notation */
   6952     if (useExp) {
   6953         if (m < 0)
   6954            m -= 1;
   6955         n = n / (double)nk_pow(10.0, m);
   6956         m1 = m;
   6957         m = 0;
   6958     }
   6959     if (m < 1.0) {
   6960         m = 0;
   6961     }
   6962 
   6963     /* convert the number */
   6964     while (n > NK_FLOAT_PRECISION || m >= 0) {
   6965         double weight = nk_pow(10.0, m);
   6966         if (weight > 0) {
   6967             double t = (double)n / weight;
   6968             digit = nk_ifloord(t);
   6969             n -= ((double)digit * weight);
   6970             *(c++) = (char)('0' + (char)digit);
   6971         }
   6972         if (m == 0 && n > 0)
   6973             *(c++) = '.';
   6974         m--;
   6975     }
   6976 
   6977     if (useExp) {
   6978         /* convert the exponent */
   6979         int i, j;
   6980         *(c++) = 'e';
   6981         if (m1 > 0) {
   6982             *(c++) = '+';
   6983         } else {
   6984             *(c++) = '-';
   6985             m1 = -m1;
   6986         }
   6987         m = 0;
   6988         while (m1 > 0) {
   6989             *(c++) = (char)('0' + (char)(m1 % 10));
   6990             m1 /= 10;
   6991             m++;
   6992         }
   6993         c -= m;
   6994         for (i = 0, j = m-1; i<j; i++, j--) {
   6995             /* swap without temporary */
   6996             c[i] ^= c[j];
   6997             c[j] ^= c[i];
   6998             c[i] ^= c[j];
   6999         }
   7000         c += m;
   7001     }
   7002     *(c) = '\0';
   7003     return s;
   7004 }
   7005 #endif
   7006 #ifdef NK_INCLUDE_STANDARD_VARARGS
   7007 #ifndef NK_INCLUDE_STANDARD_IO
   7008 NK_INTERN int
   7009 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
   7010 {
   7011     enum nk_arg_type {
   7012         NK_ARG_TYPE_CHAR,
   7013         NK_ARG_TYPE_SHORT,
   7014         NK_ARG_TYPE_DEFAULT,
   7015         NK_ARG_TYPE_LONG
   7016     };
   7017     enum nk_arg_flags {
   7018         NK_ARG_FLAG_LEFT = 0x01,
   7019         NK_ARG_FLAG_PLUS = 0x02,
   7020         NK_ARG_FLAG_SPACE = 0x04,
   7021         NK_ARG_FLAG_NUM = 0x10,
   7022         NK_ARG_FLAG_ZERO = 0x20
   7023     };
   7024 
   7025     char number_buffer[NK_MAX_NUMBER_BUFFER];
   7026     enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
   7027     int precision = NK_DEFAULT;
   7028     int width = NK_DEFAULT;
   7029     nk_flags flag = 0;
   7030 
   7031     int len = 0;
   7032     int result = -1;
   7033     const char *iter = fmt;
   7034 
   7035     NK_ASSERT(buf);
   7036     NK_ASSERT(buf_size);
   7037     if (!buf || !buf_size || !fmt) return 0;
   7038     for (iter = fmt; *iter && len < buf_size; iter++) {
   7039         /* copy all non-format characters */
   7040         while (*iter && (*iter != '%') && (len < buf_size))
   7041             buf[len++] = *iter++;
   7042         if (!(*iter) || len >= buf_size) break;
   7043         iter++;
   7044 
   7045         /* flag arguments */
   7046         while (*iter) {
   7047             if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
   7048             else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
   7049             else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
   7050             else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
   7051             else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
   7052             else break;
   7053             iter++;
   7054         }
   7055 
   7056         /* width argument */
   7057         width = NK_DEFAULT;
   7058         if (*iter >= '1' && *iter <= '9') {
   7059             const char *end;
   7060             width = nk_strtoi(iter, &end);
   7061             if (end == iter)
   7062                 width = -1;
   7063             else iter = end;
   7064         } else if (*iter == '*') {
   7065             width = va_arg(args, int);
   7066             iter++;
   7067         }
   7068 
   7069         /* precision argument */
   7070         precision = NK_DEFAULT;
   7071         if (*iter == '.') {
   7072             iter++;
   7073             if (*iter == '*') {
   7074                 precision = va_arg(args, int);
   7075                 iter++;
   7076             } else {
   7077                 const char *end;
   7078                 precision = nk_strtoi(iter, &end);
   7079                 if (end == iter)
   7080                     precision = -1;
   7081                 else iter = end;
   7082             }
   7083         }
   7084 
   7085         /* length modifier */
   7086         if (*iter == 'h') {
   7087             if (*(iter+1) == 'h') {
   7088                 arg_type = NK_ARG_TYPE_CHAR;
   7089                 iter++;
   7090             } else arg_type = NK_ARG_TYPE_SHORT;
   7091             iter++;
   7092         } else if (*iter == 'l') {
   7093             arg_type = NK_ARG_TYPE_LONG;
   7094             iter++;
   7095         } else arg_type = NK_ARG_TYPE_DEFAULT;
   7096 
   7097         /* specifier */
   7098         if (*iter == '%') {
   7099             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
   7100             NK_ASSERT(precision == NK_DEFAULT);
   7101             NK_ASSERT(width == NK_DEFAULT);
   7102             if (len < buf_size)
   7103                 buf[len++] = '%';
   7104         } else if (*iter == 's') {
   7105             /* string  */
   7106             const char *str = va_arg(args, const char*);
   7107             NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
   7108             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
   7109             NK_ASSERT(precision == NK_DEFAULT);
   7110             NK_ASSERT(width == NK_DEFAULT);
   7111             if (str == buf) return -1;
   7112             while (str && *str && len < buf_size)
   7113                 buf[len++] = *str++;
   7114         } else if (*iter == 'n') {
   7115             /* current length callback */
   7116             signed int *n = va_arg(args, int*);
   7117             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
   7118             NK_ASSERT(precision == NK_DEFAULT);
   7119             NK_ASSERT(width == NK_DEFAULT);
   7120             if (n) *n = len;
   7121         } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
   7122             /* signed integer */
   7123             long value = 0;
   7124             const char *num_iter;
   7125             int num_len, num_print, padding;
   7126             int cur_precision = NK_MAX(precision, 1);
   7127             int cur_width = NK_MAX(width, 0);
   7128 
   7129             /* retrieve correct value type */
   7130             if (arg_type == NK_ARG_TYPE_CHAR)
   7131                 value = (signed char)va_arg(args, int);
   7132             else if (arg_type == NK_ARG_TYPE_SHORT)
   7133                 value = (signed short)va_arg(args, int);
   7134             else if (arg_type == NK_ARG_TYPE_LONG)
   7135                 value = va_arg(args, signed long);
   7136             else if (*iter == 'c')
   7137                 value = (unsigned char)va_arg(args, int);
   7138             else value = va_arg(args, signed int);
   7139 
   7140             /* convert number to string */
   7141             nk_itoa(number_buffer, value);
   7142             num_len = nk_strlen(number_buffer);
   7143             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
   7144             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
   7145                 padding = NK_MAX(padding-1, 0);
   7146 
   7147             /* fill left padding up to a total of `width` characters */
   7148             if (!(flag & NK_ARG_FLAG_LEFT)) {
   7149                 while (padding-- > 0 && (len < buf_size)) {
   7150                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
   7151                         buf[len++] = '0';
   7152                     else buf[len++] = ' ';
   7153                 }
   7154             }
   7155 
   7156             /* copy string value representation into buffer */
   7157             if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
   7158                 buf[len++] = '+';
   7159             else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
   7160                 buf[len++] = ' ';
   7161 
   7162             /* fill up to precision number of digits with '0' */
   7163             num_print = NK_MAX(cur_precision, num_len);
   7164             while (precision && (num_print > num_len) && (len < buf_size)) {
   7165                 buf[len++] = '0';
   7166                 num_print--;
   7167             }
   7168 
   7169             /* copy string value representation into buffer */
   7170             num_iter = number_buffer;
   7171             while (precision && *num_iter && len < buf_size)
   7172                 buf[len++] = *num_iter++;
   7173 
   7174             /* fill right padding up to width characters */
   7175             if (flag & NK_ARG_FLAG_LEFT) {
   7176                 while ((padding-- > 0) && (len < buf_size))
   7177                     buf[len++] = ' ';
   7178             }
   7179         } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
   7180             /* unsigned integer */
   7181             unsigned long value = 0;
   7182             int num_len = 0, num_print, padding = 0;
   7183             int cur_precision = NK_MAX(precision, 1);
   7184             int cur_width = NK_MAX(width, 0);
   7185             unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
   7186 
   7187             /* print oct/hex/dec value */
   7188             const char *upper_output_format = "0123456789ABCDEF";
   7189             const char *lower_output_format = "0123456789abcdef";
   7190             const char *output_format = (*iter == 'x') ?
   7191                 lower_output_format: upper_output_format;
   7192 
   7193             /* retrieve correct value type */
   7194             if (arg_type == NK_ARG_TYPE_CHAR)
   7195                 value = (unsigned char)va_arg(args, int);
   7196             else if (arg_type == NK_ARG_TYPE_SHORT)
   7197                 value = (unsigned short)va_arg(args, int);
   7198             else if (arg_type == NK_ARG_TYPE_LONG)
   7199                 value = va_arg(args, unsigned long);
   7200             else value = va_arg(args, unsigned int);
   7201 
   7202             do {
   7203                 /* convert decimal number into hex/oct number */
   7204                 int digit = output_format[value % base];
   7205                 if (num_len < NK_MAX_NUMBER_BUFFER)
   7206                     number_buffer[num_len++] = (char)digit;
   7207                 value /= base;
   7208             } while (value > 0);
   7209 
   7210             num_print = NK_MAX(cur_precision, num_len);
   7211             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
   7212             if (flag & NK_ARG_FLAG_NUM)
   7213                 padding = NK_MAX(padding-1, 0);
   7214 
   7215             /* fill left padding up to a total of `width` characters */
   7216             if (!(flag & NK_ARG_FLAG_LEFT)) {
   7217                 while ((padding-- > 0) && (len < buf_size)) {
   7218                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
   7219                         buf[len++] = '0';
   7220                     else buf[len++] = ' ';
   7221                 }
   7222             }
   7223 
   7224             /* fill up to precision number of digits */
   7225             if (num_print && (flag & NK_ARG_FLAG_NUM)) {
   7226                 if ((*iter == 'o') && (len < buf_size)) {
   7227                     buf[len++] = '0';
   7228                 } else if ((*iter == 'x') && ((len+1) < buf_size)) {
   7229                     buf[len++] = '0';
   7230                     buf[len++] = 'x';
   7231                 } else if ((*iter == 'X') && ((len+1) < buf_size)) {
   7232                     buf[len++] = '0';
   7233                     buf[len++] = 'X';
   7234                 }
   7235             }
   7236             while (precision && (num_print > num_len) && (len < buf_size)) {
   7237                 buf[len++] = '0';
   7238                 num_print--;
   7239             }
   7240 
   7241             /* reverse number direction */
   7242             while (num_len > 0) {
   7243                 if (precision && (len < buf_size))
   7244                     buf[len++] = number_buffer[num_len-1];
   7245                 num_len--;
   7246             }
   7247 
   7248             /* fill right padding up to width characters */
   7249             if (flag & NK_ARG_FLAG_LEFT) {
   7250                 while ((padding-- > 0) && (len < buf_size))
   7251                     buf[len++] = ' ';
   7252             }
   7253         } else if (*iter == 'f') {
   7254             /* floating point */
   7255             const char *num_iter;
   7256             int cur_precision = (precision < 0) ? 6: precision;
   7257             int prefix, cur_width = NK_MAX(width, 0);
   7258             double value = va_arg(args, double);
   7259             int num_len = 0, frac_len = 0, dot = 0;
   7260             int padding = 0;
   7261 
   7262             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
   7263             NK_DTOA(number_buffer, value);
   7264             num_len = nk_strlen(number_buffer);
   7265 
   7266             /* calculate padding */
   7267             num_iter = number_buffer;
   7268             while (*num_iter && *num_iter != '.')
   7269                 num_iter++;
   7270 
   7271             prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
   7272             padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
   7273             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
   7274                 padding = NK_MAX(padding-1, 0);
   7275 
   7276             /* fill left padding up to a total of `width` characters */
   7277             if (!(flag & NK_ARG_FLAG_LEFT)) {
   7278                 while (padding-- > 0 && (len < buf_size)) {
   7279                     if (flag & NK_ARG_FLAG_ZERO)
   7280                         buf[len++] = '0';
   7281                     else buf[len++] = ' ';
   7282                 }
   7283             }
   7284 
   7285             /* copy string value representation into buffer */
   7286             num_iter = number_buffer;
   7287             if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
   7288                 buf[len++] = '+';
   7289             else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
   7290                 buf[len++] = ' ';
   7291             while (*num_iter) {
   7292                 if (dot) frac_len++;
   7293                 if (len < buf_size)
   7294                     buf[len++] = *num_iter;
   7295                 if (*num_iter == '.') dot = 1;
   7296                 if (frac_len >= cur_precision) break;
   7297                 num_iter++;
   7298             }
   7299 
   7300             /* fill number up to precision */
   7301             while (frac_len < cur_precision) {
   7302                 if (!dot && len < buf_size) {
   7303                     buf[len++] = '.';
   7304                     dot = 1;
   7305                 }
   7306                 if (len < buf_size)
   7307                     buf[len++] = '0';
   7308                 frac_len++;
   7309             }
   7310 
   7311             /* fill right padding up to width characters */
   7312             if (flag & NK_ARG_FLAG_LEFT) {
   7313                 while ((padding-- > 0) && (len < buf_size))
   7314                     buf[len++] = ' ';
   7315             }
   7316         } else {
   7317             /* Specifier not supported: g,G,e,E,p,z */
   7318             NK_ASSERT(0 && "specifier is not supported!");
   7319             return result;
   7320         }
   7321     }
   7322     buf[(len >= buf_size)?(buf_size-1):len] = 0;
   7323     result = (len >= buf_size)?-1:len;
   7324     return result;
   7325 }
   7326 #endif
   7327 NK_LIB int
   7328 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
   7329 {
   7330     int result = -1;
   7331     NK_ASSERT(buf);
   7332     NK_ASSERT(buf_size);
   7333     if (!buf || !buf_size || !fmt) return 0;
   7334 #ifdef NK_INCLUDE_STANDARD_IO
   7335     result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
   7336     result = (result >= buf_size) ? -1: result;
   7337     buf[buf_size-1] = 0;
   7338 #else
   7339     result = nk_vsnprintf(buf, buf_size, fmt, args);
   7340 #endif
   7341     return result;
   7342 }
   7343 #endif
   7344 NK_API nk_hash
   7345 nk_murmur_hash(const void * key, int len, nk_hash seed)
   7346 {
   7347     /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
   7348     #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
   7349 
   7350     nk_uint h1 = seed;
   7351     nk_uint k1;
   7352     const nk_byte *data = (const nk_byte*)key;
   7353     const nk_byte *keyptr = data;
   7354     nk_byte *k1ptr;
   7355     const int bsize = sizeof(k1);
   7356     const int nblocks = len/4;
   7357 
   7358     const nk_uint c1 = 0xcc9e2d51;
   7359     const nk_uint c2 = 0x1b873593;
   7360     const nk_byte *tail;
   7361     int i;
   7362 
   7363     /* body */
   7364     if (!key) return 0;
   7365     for (i = 0; i < nblocks; ++i, keyptr += bsize) {
   7366         k1ptr = (nk_byte*)&k1;
   7367         k1ptr[0] = keyptr[0];
   7368         k1ptr[1] = keyptr[1];
   7369         k1ptr[2] = keyptr[2];
   7370         k1ptr[3] = keyptr[3];
   7371 
   7372         k1 *= c1;
   7373         k1 = NK_ROTL(k1,15);
   7374         k1 *= c2;
   7375 
   7376         h1 ^= k1;
   7377         h1 = NK_ROTL(h1,13);
   7378         h1 = h1*5+0xe6546b64;
   7379     }
   7380 
   7381     /* tail */
   7382     tail = (const nk_byte*)(data + nblocks*4);
   7383     k1 = 0;
   7384     switch (len & 3) {
   7385         case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
   7386         case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
   7387         case 1: k1 ^= tail[0];
   7388             k1 *= c1;
   7389             k1 = NK_ROTL(k1,15);
   7390             k1 *= c2;
   7391             h1 ^= k1;
   7392             break;
   7393         default: break;
   7394     }
   7395 
   7396     /* finalization */
   7397     h1 ^= (nk_uint)len;
   7398     /* fmix32 */
   7399     h1 ^= h1 >> 16;
   7400     h1 *= 0x85ebca6b;
   7401     h1 ^= h1 >> 13;
   7402     h1 *= 0xc2b2ae35;
   7403     h1 ^= h1 >> 16;
   7404 
   7405     #undef NK_ROTL
   7406     return h1;
   7407 }
   7408 #ifdef NK_INCLUDE_STANDARD_IO
   7409 NK_LIB char*
   7410 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
   7411 {
   7412     char *buf;
   7413     FILE *fd;
   7414     long ret;
   7415 
   7416     NK_ASSERT(path);
   7417     NK_ASSERT(siz);
   7418     NK_ASSERT(alloc);
   7419     if (!path || !siz || !alloc)
   7420         return 0;
   7421 
   7422     fd = fopen(path, "rb");
   7423     if (!fd) return 0;
   7424     fseek(fd, 0, SEEK_END);
   7425     ret = ftell(fd);
   7426     if (ret < 0) {
   7427         fclose(fd);
   7428         return 0;
   7429     }
   7430     *siz = (nk_size)ret;
   7431     fseek(fd, 0, SEEK_SET);
   7432     buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
   7433     NK_ASSERT(buf);
   7434     if (!buf) {
   7435         fclose(fd);
   7436         return 0;
   7437     }
   7438     *siz = (nk_size)fread(buf, 1,*siz, fd);
   7439     fclose(fd);
   7440     return buf;
   7441 }
   7442 #endif
   7443 NK_LIB int
   7444 nk_text_clamp(const struct nk_user_font *font, const char *text,
   7445     int text_len, float space, int *glyphs, float *text_width,
   7446     nk_rune *sep_list, int sep_count)
   7447 {
   7448     int i = 0;
   7449     int glyph_len = 0;
   7450     float last_width = 0;
   7451     nk_rune unicode = 0;
   7452     float width = 0;
   7453     int len = 0;
   7454     int g = 0;
   7455     float s;
   7456 
   7457     int sep_len = 0;
   7458     int sep_g = 0;
   7459     float sep_width = 0;
   7460     sep_count = NK_MAX(sep_count,0);
   7461 
   7462     glyph_len = nk_utf_decode(text, &unicode, text_len);
   7463     while (glyph_len && (width < space) && (len < text_len)) {
   7464         len += glyph_len;
   7465         s = font->width(font->userdata, font->height, text, len);
   7466         for (i = 0; i < sep_count; ++i) {
   7467             if (unicode != sep_list[i]) continue;
   7468             sep_width = last_width = width;
   7469             sep_g = g+1;
   7470             sep_len = len;
   7471             break;
   7472         }
   7473         if (i == sep_count){
   7474             last_width = sep_width = width;
   7475             sep_g = g+1;
   7476         }
   7477         width = s;
   7478         glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
   7479         g++;
   7480     }
   7481     if (len >= text_len) {
   7482         *glyphs = g;
   7483         *text_width = last_width;
   7484         return len;
   7485     } else {
   7486         *glyphs = sep_g;
   7487         *text_width = sep_width;
   7488         return (!sep_len) ? len: sep_len;
   7489     }
   7490 }
   7491 NK_LIB struct nk_vec2
   7492 nk_text_calculate_text_bounds(const struct nk_user_font *font,
   7493     const char *begin, int byte_len, float row_height, const char **remaining,
   7494     struct nk_vec2 *out_offset, int *glyphs, int op)
   7495 {
   7496     float line_height = row_height;
   7497     struct nk_vec2 text_size = nk_vec2(0,0);
   7498     float line_width = 0.0f;
   7499 
   7500     float glyph_width;
   7501     int glyph_len = 0;
   7502     nk_rune unicode = 0;
   7503     int text_len = 0;
   7504     if (!begin || byte_len <= 0 || !font)
   7505         return nk_vec2(0,row_height);
   7506 
   7507     glyph_len = nk_utf_decode(begin, &unicode, byte_len);
   7508     if (!glyph_len) return text_size;
   7509     glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
   7510 
   7511     *glyphs = 0;
   7512     while ((text_len < byte_len) && glyph_len) {
   7513         if (unicode == '\n') {
   7514             text_size.x = NK_MAX(text_size.x, line_width);
   7515             text_size.y += line_height;
   7516             line_width = 0;
   7517             *glyphs+=1;
   7518             if (op == NK_STOP_ON_NEW_LINE)
   7519                 break;
   7520 
   7521             text_len++;
   7522             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
   7523             continue;
   7524         }
   7525 
   7526         if (unicode == '\r') {
   7527             text_len++;
   7528             *glyphs+=1;
   7529             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
   7530             continue;
   7531         }
   7532 
   7533         *glyphs = *glyphs + 1;
   7534         text_len += glyph_len;
   7535         line_width += (float)glyph_width;
   7536         glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
   7537         glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
   7538         continue;
   7539     }
   7540 
   7541     if (text_size.x < line_width)
   7542         text_size.x = line_width;
   7543     if (out_offset)
   7544         *out_offset = nk_vec2(line_width, text_size.y + line_height);
   7545     if (line_width > 0 || text_size.y == 0.0f)
   7546         text_size.y += line_height;
   7547     if (remaining)
   7548         *remaining = begin+text_len;
   7549     return text_size;
   7550 }
   7551 
   7552 
   7553 
   7554 
   7555 
   7556 /* ==============================================================
   7557  *
   7558  *                          COLOR
   7559  *
   7560  * ===============================================================*/
   7561 NK_INTERN int
   7562 nk_parse_hex(const char *p, int length)
   7563 {
   7564     int i = 0;
   7565     int len = 0;
   7566     while (len < length) {
   7567         i <<= 4;
   7568         if (p[len] >= 'a' && p[len] <= 'f')
   7569             i += ((p[len] - 'a') + 10);
   7570         else if (p[len] >= 'A' && p[len] <= 'F')
   7571             i += ((p[len] - 'A') + 10);
   7572         else i += (p[len] - '0');
   7573         len++;
   7574     }
   7575     return i;
   7576 }
   7577 NK_API struct nk_color
   7578 nk_rgba(int r, int g, int b, int a)
   7579 {
   7580     struct nk_color ret;
   7581     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
   7582     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
   7583     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
   7584     ret.a = (nk_byte)NK_CLAMP(0, a, 255);
   7585     return ret;
   7586 }
   7587 NK_API struct nk_color
   7588 nk_rgb_hex(const char *rgb)
   7589 {
   7590     struct nk_color col;
   7591     const char *c = rgb;
   7592     if (*c == '#') c++;
   7593     col.r = (nk_byte)nk_parse_hex(c, 2);
   7594     col.g = (nk_byte)nk_parse_hex(c+2, 2);
   7595     col.b = (nk_byte)nk_parse_hex(c+4, 2);
   7596     col.a = 255;
   7597     return col;
   7598 }
   7599 NK_API struct nk_color
   7600 nk_rgba_hex(const char *rgb)
   7601 {
   7602     struct nk_color col;
   7603     const char *c = rgb;
   7604     if (*c == '#') c++;
   7605     col.r = (nk_byte)nk_parse_hex(c, 2);
   7606     col.g = (nk_byte)nk_parse_hex(c+2, 2);
   7607     col.b = (nk_byte)nk_parse_hex(c+4, 2);
   7608     col.a = (nk_byte)nk_parse_hex(c+6, 2);
   7609     return col;
   7610 }
   7611 NK_API void
   7612 nk_color_hex_rgba(char *output, struct nk_color col)
   7613 {
   7614     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
   7615     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
   7616     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
   7617     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
   7618     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
   7619     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
   7620     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
   7621     output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
   7622     output[7] = (char)NK_TO_HEX((col.a & 0x0F));
   7623     output[8] = '\0';
   7624     #undef NK_TO_HEX
   7625 }
   7626 NK_API void
   7627 nk_color_hex_rgb(char *output, struct nk_color col)
   7628 {
   7629     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
   7630     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
   7631     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
   7632     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
   7633     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
   7634     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
   7635     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
   7636     output[6] = '\0';
   7637     #undef NK_TO_HEX
   7638 }
   7639 NK_API struct nk_color
   7640 nk_rgba_iv(const int *c)
   7641 {
   7642     return nk_rgba(c[0], c[1], c[2], c[3]);
   7643 }
   7644 NK_API struct nk_color
   7645 nk_rgba_bv(const nk_byte *c)
   7646 {
   7647     return nk_rgba(c[0], c[1], c[2], c[3]);
   7648 }
   7649 NK_API struct nk_color
   7650 nk_rgb(int r, int g, int b)
   7651 {
   7652     struct nk_color ret;
   7653     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
   7654     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
   7655     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
   7656     ret.a = (nk_byte)255;
   7657     return ret;
   7658 }
   7659 NK_API struct nk_color
   7660 nk_rgb_iv(const int *c)
   7661 {
   7662     return nk_rgb(c[0], c[1], c[2]);
   7663 }
   7664 NK_API struct nk_color
   7665 nk_rgb_bv(const nk_byte* c)
   7666 {
   7667     return nk_rgb(c[0], c[1], c[2]);
   7668 }
   7669 NK_API struct nk_color
   7670 nk_rgba_u32(nk_uint in)
   7671 {
   7672     struct nk_color ret;
   7673     ret.r = (in & 0xFF);
   7674     ret.g = ((in >> 8) & 0xFF);
   7675     ret.b = ((in >> 16) & 0xFF);
   7676     ret.a = (nk_byte)((in >> 24) & 0xFF);
   7677     return ret;
   7678 }
   7679 NK_API struct nk_color
   7680 nk_rgba_f(float r, float g, float b, float a)
   7681 {
   7682     struct nk_color ret;
   7683     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
   7684     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
   7685     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
   7686     ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
   7687     return ret;
   7688 }
   7689 NK_API struct nk_color
   7690 nk_rgba_fv(const float *c)
   7691 {
   7692     return nk_rgba_f(c[0], c[1], c[2], c[3]);
   7693 }
   7694 NK_API struct nk_color
   7695 nk_rgba_cf(struct nk_colorf c)
   7696 {
   7697     return nk_rgba_f(c.r, c.g, c.b, c.a);
   7698 }
   7699 NK_API struct nk_color
   7700 nk_rgb_f(float r, float g, float b)
   7701 {
   7702     struct nk_color ret;
   7703     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
   7704     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
   7705     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
   7706     ret.a = 255;
   7707     return ret;
   7708 }
   7709 NK_API struct nk_color
   7710 nk_rgb_fv(const float *c)
   7711 {
   7712     return nk_rgb_f(c[0], c[1], c[2]);
   7713 }
   7714 NK_API struct nk_color
   7715 nk_rgb_cf(struct nk_colorf c)
   7716 {
   7717     return nk_rgb_f(c.r, c.g, c.b);
   7718 }
   7719 NK_API struct nk_color
   7720 nk_hsv(int h, int s, int v)
   7721 {
   7722     return nk_hsva(h, s, v, 255);
   7723 }
   7724 NK_API struct nk_color
   7725 nk_hsv_iv(const int *c)
   7726 {
   7727     return nk_hsv(c[0], c[1], c[2]);
   7728 }
   7729 NK_API struct nk_color
   7730 nk_hsv_bv(const nk_byte *c)
   7731 {
   7732     return nk_hsv(c[0], c[1], c[2]);
   7733 }
   7734 NK_API struct nk_color
   7735 nk_hsv_f(float h, float s, float v)
   7736 {
   7737     return nk_hsva_f(h, s, v, 1.0f);
   7738 }
   7739 NK_API struct nk_color
   7740 nk_hsv_fv(const float *c)
   7741 {
   7742     return nk_hsv_f(c[0], c[1], c[2]);
   7743 }
   7744 NK_API struct nk_color
   7745 nk_hsva(int h, int s, int v, int a)
   7746 {
   7747     float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
   7748     float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
   7749     float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
   7750     float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
   7751     return nk_hsva_f(hf, sf, vf, af);
   7752 }
   7753 NK_API struct nk_color
   7754 nk_hsva_iv(const int *c)
   7755 {
   7756     return nk_hsva(c[0], c[1], c[2], c[3]);
   7757 }
   7758 NK_API struct nk_color
   7759 nk_hsva_bv(const nk_byte *c)
   7760 {
   7761     return nk_hsva(c[0], c[1], c[2], c[3]);
   7762 }
   7763 NK_API struct nk_colorf
   7764 nk_hsva_colorf(float h, float s, float v, float a)
   7765 {
   7766     int i;
   7767     float p, q, t, f;
   7768     struct nk_colorf out = {0,0,0,0};
   7769     if (s <= 0.0f) {
   7770         out.r = v; out.g = v; out.b = v; out.a = a;
   7771         return out;
   7772     }
   7773     h = h / (60.0f/360.0f);
   7774     i = (int)h;
   7775     f = h - (float)i;
   7776     p = v * (1.0f - s);
   7777     q = v * (1.0f - (s * f));
   7778     t = v * (1.0f - s * (1.0f - f));
   7779 
   7780     switch (i) {
   7781     case 0: default: out.r = v; out.g = t; out.b = p; break;
   7782     case 1: out.r = q; out.g = v; out.b = p; break;
   7783     case 2: out.r = p; out.g = v; out.b = t; break;
   7784     case 3: out.r = p; out.g = q; out.b = v; break;
   7785     case 4: out.r = t; out.g = p; out.b = v; break;
   7786     case 5: out.r = v; out.g = p; out.b = q; break;}
   7787     out.a = a;
   7788     return out;
   7789 }
   7790 NK_API struct nk_colorf
   7791 nk_hsva_colorfv(float *c)
   7792 {
   7793     return nk_hsva_colorf(c[0], c[1], c[2], c[3]);
   7794 }
   7795 NK_API struct nk_color
   7796 nk_hsva_f(float h, float s, float v, float a)
   7797 {
   7798     struct nk_colorf c = nk_hsva_colorf(h, s, v, a);
   7799     return nk_rgba_f(c.r, c.g, c.b, c.a);
   7800 }
   7801 NK_API struct nk_color
   7802 nk_hsva_fv(const float *c)
   7803 {
   7804     return nk_hsva_f(c[0], c[1], c[2], c[3]);
   7805 }
   7806 NK_API nk_uint
   7807 nk_color_u32(struct nk_color in)
   7808 {
   7809     nk_uint out = (nk_uint)in.r;
   7810     out |= ((nk_uint)in.g << 8);
   7811     out |= ((nk_uint)in.b << 16);
   7812     out |= ((nk_uint)in.a << 24);
   7813     return out;
   7814 }
   7815 NK_API void
   7816 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
   7817 {
   7818     NK_STORAGE const float s = 1.0f/255.0f;
   7819     *r = (float)in.r * s;
   7820     *g = (float)in.g * s;
   7821     *b = (float)in.b * s;
   7822     *a = (float)in.a * s;
   7823 }
   7824 NK_API void
   7825 nk_color_fv(float *c, struct nk_color in)
   7826 {
   7827     nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
   7828 }
   7829 NK_API struct nk_colorf
   7830 nk_color_cf(struct nk_color in)
   7831 {
   7832     struct nk_colorf o;
   7833     nk_color_f(&o.r, &o.g, &o.b, &o.a, in);
   7834     return o;
   7835 }
   7836 NK_API void
   7837 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
   7838 {
   7839     NK_STORAGE const double s = 1.0/255.0;
   7840     *r = (double)in.r * s;
   7841     *g = (double)in.g * s;
   7842     *b = (double)in.b * s;
   7843     *a = (double)in.a * s;
   7844 }
   7845 NK_API void
   7846 nk_color_dv(double *c, struct nk_color in)
   7847 {
   7848     nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
   7849 }
   7850 NK_API void
   7851 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
   7852 {
   7853     float a;
   7854     nk_color_hsva_f(out_h, out_s, out_v, &a, in);
   7855 }
   7856 NK_API void
   7857 nk_color_hsv_fv(float *out, struct nk_color in)
   7858 {
   7859     float a;
   7860     nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
   7861 }
   7862 NK_API void
   7863 nk_colorf_hsva_f(float *out_h, float *out_s,
   7864     float *out_v, float *out_a, struct nk_colorf in)
   7865 {
   7866     float chroma;
   7867     float K = 0.0f;
   7868     if (in.g < in.b) {
   7869         const float t = in.g; in.g = in.b; in.b = t;
   7870         K = -1.f;
   7871     }
   7872     if (in.r < in.g) {
   7873         const float t = in.r; in.r = in.g; in.g = t;
   7874         K = -2.f/6.0f - K;
   7875     }
   7876     chroma = in.r - ((in.g < in.b) ? in.g: in.b);
   7877     *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f));
   7878     *out_s = chroma / (in.r + 1e-20f);
   7879     *out_v = in.r;
   7880     *out_a = in.a;
   7881 
   7882 }
   7883 NK_API void
   7884 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
   7885 {
   7886     nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in);
   7887 }
   7888 NK_API void
   7889 nk_color_hsva_f(float *out_h, float *out_s,
   7890     float *out_v, float *out_a, struct nk_color in)
   7891 {
   7892     struct nk_colorf col;
   7893     nk_color_f(&col.r,&col.g,&col.b,&col.a, in);
   7894     nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col);
   7895 }
   7896 NK_API void
   7897 nk_color_hsva_fv(float *out, struct nk_color in)
   7898 {
   7899     nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
   7900 }
   7901 NK_API void
   7902 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
   7903                 int *out_a, struct nk_color in)
   7904 {
   7905     float h,s,v,a;
   7906     nk_color_hsva_f(&h, &s, &v, &a, in);
   7907     *out_h = (nk_byte)(h * 255.0f);
   7908     *out_s = (nk_byte)(s * 255.0f);
   7909     *out_v = (nk_byte)(v * 255.0f);
   7910     *out_a = (nk_byte)(a * 255.0f);
   7911 }
   7912 NK_API void
   7913 nk_color_hsva_iv(int *out, struct nk_color in)
   7914 {
   7915     nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
   7916 }
   7917 NK_API void
   7918 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
   7919 {
   7920     int tmp[4];
   7921     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
   7922     out[0] = (nk_byte)tmp[0];
   7923     out[1] = (nk_byte)tmp[1];
   7924     out[2] = (nk_byte)tmp[2];
   7925     out[3] = (nk_byte)tmp[3];
   7926 }
   7927 NK_API void
   7928 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
   7929 {
   7930     int tmp[4];
   7931     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
   7932     *h = (nk_byte)tmp[0];
   7933     *s = (nk_byte)tmp[1];
   7934     *v = (nk_byte)tmp[2];
   7935     *a = (nk_byte)tmp[3];
   7936 }
   7937 NK_API void
   7938 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
   7939 {
   7940     int a;
   7941     nk_color_hsva_i(out_h, out_s, out_v, &a, in);
   7942 }
   7943 NK_API void
   7944 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
   7945 {
   7946     int tmp[4];
   7947     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
   7948     *out_h = (nk_byte)tmp[0];
   7949     *out_s = (nk_byte)tmp[1];
   7950     *out_v = (nk_byte)tmp[2];
   7951 }
   7952 NK_API void
   7953 nk_color_hsv_iv(int *out, struct nk_color in)
   7954 {
   7955     nk_color_hsv_i(&out[0], &out[1], &out[2], in);
   7956 }
   7957 NK_API void
   7958 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
   7959 {
   7960     int tmp[4];
   7961     nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
   7962     out[0] = (nk_byte)tmp[0];
   7963     out[1] = (nk_byte)tmp[1];
   7964     out[2] = (nk_byte)tmp[2];
   7965 }
   7966 
   7967 
   7968 
   7969 
   7970 
   7971 /* ===============================================================
   7972  *
   7973  *                              UTF-8
   7974  *
   7975  * ===============================================================*/
   7976 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
   7977 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
   7978 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
   7979 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
   7980 
   7981 NK_INTERN int
   7982 nk_utf_validate(nk_rune *u, int i)
   7983 {
   7984     NK_ASSERT(u);
   7985     if (!u) return 0;
   7986     if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
   7987          NK_BETWEEN(*u, 0xD800, 0xDFFF))
   7988             *u = NK_UTF_INVALID;
   7989     for (i = 1; *u > nk_utfmax[i]; ++i);
   7990     return i;
   7991 }
   7992 NK_INTERN nk_rune
   7993 nk_utf_decode_byte(char c, int *i)
   7994 {
   7995     NK_ASSERT(i);
   7996     if (!i) return 0;
   7997     for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
   7998         if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
   7999             return (nk_byte)(c & ~nk_utfmask[*i]);
   8000     }
   8001     return 0;
   8002 }
   8003 NK_API int
   8004 nk_utf_decode(const char *c, nk_rune *u, int clen)
   8005 {
   8006     int i, j, len, type=0;
   8007     nk_rune udecoded;
   8008 
   8009     NK_ASSERT(c);
   8010     NK_ASSERT(u);
   8011 
   8012     if (!c || !u) return 0;
   8013     if (!clen) return 0;
   8014     *u = NK_UTF_INVALID;
   8015 
   8016     udecoded = nk_utf_decode_byte(c[0], &len);
   8017     if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
   8018         return 1;
   8019 
   8020     for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
   8021         udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
   8022         if (type != 0)
   8023             return j;
   8024     }
   8025     if (j < len)
   8026         return 0;
   8027     *u = udecoded;
   8028     nk_utf_validate(u, len);
   8029     return len;
   8030 }
   8031 NK_INTERN char
   8032 nk_utf_encode_byte(nk_rune u, int i)
   8033 {
   8034     return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
   8035 }
   8036 NK_API int
   8037 nk_utf_encode(nk_rune u, char *c, int clen)
   8038 {
   8039     int len, i;
   8040     len = nk_utf_validate(&u, 0);
   8041     if (clen < len || !len || len > NK_UTF_SIZE)
   8042         return 0;
   8043 
   8044     for (i = len - 1; i != 0; --i) {
   8045         c[i] = nk_utf_encode_byte(u, 0);
   8046         u >>= 6;
   8047     }
   8048     c[0] = nk_utf_encode_byte(u, len);
   8049     return len;
   8050 }
   8051 NK_API int
   8052 nk_utf_len(const char *str, int len)
   8053 {
   8054     const char *text;
   8055     int glyphs = 0;
   8056     int text_len;
   8057     int glyph_len;
   8058     int src_len = 0;
   8059     nk_rune unicode;
   8060 
   8061     NK_ASSERT(str);
   8062     if (!str || !len) return 0;
   8063 
   8064     text = str;
   8065     text_len = len;
   8066     glyph_len = nk_utf_decode(text, &unicode, text_len);
   8067     while (glyph_len && src_len < len) {
   8068         glyphs++;
   8069         src_len = src_len + glyph_len;
   8070         glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
   8071     }
   8072     return glyphs;
   8073 }
   8074 NK_API const char*
   8075 nk_utf_at(const char *buffer, int length, int index,
   8076     nk_rune *unicode, int *len)
   8077 {
   8078     int i = 0;
   8079     int src_len = 0;
   8080     int glyph_len = 0;
   8081     const char *text;
   8082     int text_len;
   8083 
   8084     NK_ASSERT(buffer);
   8085     NK_ASSERT(unicode);
   8086     NK_ASSERT(len);
   8087 
   8088     if (!buffer || !unicode || !len) return 0;
   8089     if (index < 0) {
   8090         *unicode = NK_UTF_INVALID;
   8091         *len = 0;
   8092         return 0;
   8093     }
   8094 
   8095     text = buffer;
   8096     text_len = length;
   8097     glyph_len = nk_utf_decode(text, unicode, text_len);
   8098     while (glyph_len) {
   8099         if (i == index) {
   8100             *len = glyph_len;
   8101             break;
   8102         }
   8103 
   8104         i++;
   8105         src_len = src_len + glyph_len;
   8106         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
   8107     }
   8108     if (i != index) return 0;
   8109     return buffer + src_len;
   8110 }
   8111 
   8112 
   8113 
   8114 
   8115 
   8116 /* ==============================================================
   8117  *
   8118  *                          BUFFER
   8119  *
   8120  * ===============================================================*/
   8121 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   8122 NK_LIB void*
   8123 nk_malloc(nk_handle unused, void *old,nk_size size)
   8124 {
   8125     NK_UNUSED(unused);
   8126     NK_UNUSED(old);
   8127     return malloc(size);
   8128 }
   8129 NK_LIB void
   8130 nk_mfree(nk_handle unused, void *ptr)
   8131 {
   8132     NK_UNUSED(unused);
   8133     free(ptr);
   8134 }
   8135 NK_API void
   8136 nk_buffer_init_default(struct nk_buffer *buffer)
   8137 {
   8138     struct nk_allocator alloc;
   8139     alloc.userdata.ptr = 0;
   8140     alloc.alloc = nk_malloc;
   8141     alloc.free = nk_mfree;
   8142     nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
   8143 }
   8144 #endif
   8145 
   8146 NK_API void
   8147 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
   8148     nk_size initial_size)
   8149 {
   8150     NK_ASSERT(b);
   8151     NK_ASSERT(a);
   8152     NK_ASSERT(initial_size);
   8153     if (!b || !a || !initial_size) return;
   8154 
   8155     nk_zero(b, sizeof(*b));
   8156     b->type = NK_BUFFER_DYNAMIC;
   8157     b->memory.ptr = a->alloc(a->userdata,0, initial_size);
   8158     b->memory.size = initial_size;
   8159     b->size = initial_size;
   8160     b->grow_factor = 2.0f;
   8161     b->pool = *a;
   8162 }
   8163 NK_API void
   8164 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
   8165 {
   8166     NK_ASSERT(b);
   8167     NK_ASSERT(m);
   8168     NK_ASSERT(size);
   8169     if (!b || !m || !size) return;
   8170 
   8171     nk_zero(b, sizeof(*b));
   8172     b->type = NK_BUFFER_FIXED;
   8173     b->memory.ptr = m;
   8174     b->memory.size = size;
   8175     b->size = size;
   8176 }
   8177 NK_LIB void*
   8178 nk_buffer_align(void *unaligned,
   8179     nk_size align, nk_size *alignment,
   8180     enum nk_buffer_allocation_type type)
   8181 {
   8182     void *memory = 0;
   8183     switch (type) {
   8184     default:
   8185     case NK_BUFFER_MAX:
   8186     case NK_BUFFER_FRONT:
   8187         if (align) {
   8188             memory = NK_ALIGN_PTR(unaligned, align);
   8189             *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
   8190         } else {
   8191             memory = unaligned;
   8192             *alignment = 0;
   8193         }
   8194         break;
   8195     case NK_BUFFER_BACK:
   8196         if (align) {
   8197             memory = NK_ALIGN_PTR_BACK(unaligned, align);
   8198             *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
   8199         } else {
   8200             memory = unaligned;
   8201             *alignment = 0;
   8202         }
   8203         break;
   8204     }
   8205     return memory;
   8206 }
   8207 NK_LIB void*
   8208 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
   8209 {
   8210     void *temp;
   8211     nk_size buffer_size;
   8212 
   8213     NK_ASSERT(b);
   8214     NK_ASSERT(size);
   8215     if (!b || !size || !b->pool.alloc || !b->pool.free)
   8216         return 0;
   8217 
   8218     buffer_size = b->memory.size;
   8219     temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
   8220     NK_ASSERT(temp);
   8221     if (!temp) return 0;
   8222 
   8223     *size = capacity;
   8224     if (temp != b->memory.ptr) {
   8225         NK_MEMCPY(temp, b->memory.ptr, buffer_size);
   8226         b->pool.free(b->pool.userdata, b->memory.ptr);
   8227     }
   8228 
   8229     if (b->size == buffer_size) {
   8230         /* no back buffer so just set correct size */
   8231         b->size = capacity;
   8232         return temp;
   8233     } else {
   8234         /* copy back buffer to the end of the new buffer */
   8235         void *dst, *src;
   8236         nk_size back_size;
   8237         back_size = buffer_size - b->size;
   8238         dst = nk_ptr_add(void, temp, capacity - back_size);
   8239         src = nk_ptr_add(void, temp, b->size);
   8240         NK_MEMCPY(dst, src, back_size);
   8241         b->size = capacity - back_size;
   8242     }
   8243     return temp;
   8244 }
   8245 NK_LIB void*
   8246 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
   8247     nk_size size, nk_size align)
   8248 {
   8249     int full;
   8250     nk_size alignment;
   8251     void *unaligned;
   8252     void *memory;
   8253 
   8254     NK_ASSERT(b);
   8255     NK_ASSERT(size);
   8256     if (!b || !size) return 0;
   8257     b->needed += size;
   8258 
   8259     /* calculate total size with needed alignment + size */
   8260     if (type == NK_BUFFER_FRONT)
   8261         unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
   8262     else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
   8263     memory = nk_buffer_align(unaligned, align, &alignment, type);
   8264 
   8265     /* check if buffer has enough memory*/
   8266     if (type == NK_BUFFER_FRONT)
   8267         full = ((b->allocated + size + alignment) > b->size);
   8268     else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
   8269 
   8270     if (full) {
   8271         nk_size capacity;
   8272         if (b->type != NK_BUFFER_DYNAMIC)
   8273             return 0;
   8274         NK_ASSERT(b->pool.alloc && b->pool.free);
   8275         if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
   8276             return 0;
   8277 
   8278         /* buffer is full so allocate bigger buffer if dynamic */
   8279         capacity = (nk_size)((float)b->memory.size * b->grow_factor);
   8280         capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
   8281         b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
   8282         if (!b->memory.ptr) return 0;
   8283 
   8284         /* align newly allocated pointer */
   8285         if (type == NK_BUFFER_FRONT)
   8286             unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
   8287         else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
   8288         memory = nk_buffer_align(unaligned, align, &alignment, type);
   8289     }
   8290     if (type == NK_BUFFER_FRONT)
   8291         b->allocated += size + alignment;
   8292     else b->size -= (size + alignment);
   8293     b->needed += alignment;
   8294     b->calls++;
   8295     return memory;
   8296 }
   8297 NK_API void
   8298 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type,
   8299     const void *memory, nk_size size, nk_size align)
   8300 {
   8301     void *mem = nk_buffer_alloc(b, type, size, align);
   8302     if (!mem) return;
   8303     NK_MEMCPY(mem, memory, size);
   8304 }
   8305 NK_API void
   8306 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
   8307 {
   8308     NK_ASSERT(buffer);
   8309     if (!buffer) return;
   8310     buffer->marker[type].active = nk_true;
   8311     if (type == NK_BUFFER_BACK)
   8312         buffer->marker[type].offset = buffer->size;
   8313     else buffer->marker[type].offset = buffer->allocated;
   8314 }
   8315 NK_API void
   8316 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
   8317 {
   8318     NK_ASSERT(buffer);
   8319     if (!buffer) return;
   8320     if (type == NK_BUFFER_BACK) {
   8321         /* reset back buffer either back to marker or empty */
   8322         buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
   8323         if (buffer->marker[type].active)
   8324             buffer->size = buffer->marker[type].offset;
   8325         else buffer->size = buffer->memory.size;
   8326         buffer->marker[type].active = nk_false;
   8327     } else {
   8328         /* reset front buffer either back to back marker or empty */
   8329         buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
   8330         if (buffer->marker[type].active)
   8331             buffer->allocated = buffer->marker[type].offset;
   8332         else buffer->allocated = 0;
   8333         buffer->marker[type].active = nk_false;
   8334     }
   8335 }
   8336 NK_API void
   8337 nk_buffer_clear(struct nk_buffer *b)
   8338 {
   8339     NK_ASSERT(b);
   8340     if (!b) return;
   8341     b->allocated = 0;
   8342     b->size = b->memory.size;
   8343     b->calls = 0;
   8344     b->needed = 0;
   8345 }
   8346 NK_API void
   8347 nk_buffer_free(struct nk_buffer *b)
   8348 {
   8349     NK_ASSERT(b);
   8350     if (!b || !b->memory.ptr) return;
   8351     if (b->type == NK_BUFFER_FIXED) return;
   8352     if (!b->pool.free) return;
   8353     NK_ASSERT(b->pool.free);
   8354     b->pool.free(b->pool.userdata, b->memory.ptr);
   8355 }
   8356 NK_API void
   8357 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
   8358 {
   8359     NK_ASSERT(b);
   8360     NK_ASSERT(s);
   8361     if (!s || !b) return;
   8362     s->allocated = b->allocated;
   8363     s->size =  b->memory.size;
   8364     s->needed = b->needed;
   8365     s->memory = b->memory.ptr;
   8366     s->calls = b->calls;
   8367 }
   8368 NK_API void*
   8369 nk_buffer_memory(struct nk_buffer *buffer)
   8370 {
   8371     NK_ASSERT(buffer);
   8372     if (!buffer) return 0;
   8373     return buffer->memory.ptr;
   8374 }
   8375 NK_API const void*
   8376 nk_buffer_memory_const(const struct nk_buffer *buffer)
   8377 {
   8378     NK_ASSERT(buffer);
   8379     if (!buffer) return 0;
   8380     return buffer->memory.ptr;
   8381 }
   8382 NK_API nk_size
   8383 nk_buffer_total(struct nk_buffer *buffer)
   8384 {
   8385     NK_ASSERT(buffer);
   8386     if (!buffer) return 0;
   8387     return buffer->memory.size;
   8388 }
   8389 
   8390 
   8391 
   8392 
   8393 
   8394 /* ===============================================================
   8395  *
   8396  *                              STRING
   8397  *
   8398  * ===============================================================*/
   8399 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   8400 NK_API void
   8401 nk_str_init_default(struct nk_str *str)
   8402 {
   8403     struct nk_allocator alloc;
   8404     alloc.userdata.ptr = 0;
   8405     alloc.alloc = nk_malloc;
   8406     alloc.free = nk_mfree;
   8407     nk_buffer_init(&str->buffer, &alloc, 32);
   8408     str->len = 0;
   8409 }
   8410 #endif
   8411 
   8412 NK_API void
   8413 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
   8414 {
   8415     nk_buffer_init(&str->buffer, alloc, size);
   8416     str->len = 0;
   8417 }
   8418 NK_API void
   8419 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
   8420 {
   8421     nk_buffer_init_fixed(&str->buffer, memory, size);
   8422     str->len = 0;
   8423 }
   8424 NK_API int
   8425 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
   8426 {
   8427     char *mem;
   8428     NK_ASSERT(s);
   8429     NK_ASSERT(str);
   8430     if (!s || !str || !len) return 0;
   8431     mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
   8432     if (!mem) return 0;
   8433     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
   8434     s->len += nk_utf_len(str, len);
   8435     return len;
   8436 }
   8437 NK_API int
   8438 nk_str_append_str_char(struct nk_str *s, const char *str)
   8439 {
   8440     return nk_str_append_text_char(s, str, nk_strlen(str));
   8441 }
   8442 NK_API int
   8443 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
   8444 {
   8445     int i = 0;
   8446     int byte_len = 0;
   8447     nk_rune unicode;
   8448     if (!str || !text || !len) return 0;
   8449     for (i = 0; i < len; ++i)
   8450         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
   8451     nk_str_append_text_char(str, text, byte_len);
   8452     return len;
   8453 }
   8454 NK_API int
   8455 nk_str_append_str_utf8(struct nk_str *str, const char *text)
   8456 {
   8457     int byte_len = 0;
   8458     int num_runes = 0;
   8459     int glyph_len = 0;
   8460     nk_rune unicode;
   8461     if (!str || !text) return 0;
   8462 
   8463     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
   8464     while (unicode != '\0' && glyph_len) {
   8465         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
   8466         byte_len += glyph_len;
   8467         num_runes++;
   8468     }
   8469     nk_str_append_text_char(str, text, byte_len);
   8470     return num_runes;
   8471 }
   8472 NK_API int
   8473 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
   8474 {
   8475     int i = 0;
   8476     int byte_len = 0;
   8477     nk_glyph glyph;
   8478 
   8479     NK_ASSERT(str);
   8480     if (!str || !text || !len) return 0;
   8481     for (i = 0; i < len; ++i) {
   8482         byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
   8483         if (!byte_len) break;
   8484         nk_str_append_text_char(str, glyph, byte_len);
   8485     }
   8486     return len;
   8487 }
   8488 NK_API int
   8489 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
   8490 {
   8491     int i = 0;
   8492     nk_glyph glyph;
   8493     int byte_len;
   8494     NK_ASSERT(str);
   8495     if (!str || !runes) return 0;
   8496     while (runes[i] != '\0') {
   8497         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
   8498         nk_str_append_text_char(str, glyph, byte_len);
   8499         i++;
   8500     }
   8501     return i;
   8502 }
   8503 NK_API int
   8504 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
   8505 {
   8506     int i;
   8507     void *mem;
   8508     char *src;
   8509     char *dst;
   8510 
   8511     int copylen;
   8512     NK_ASSERT(s);
   8513     NK_ASSERT(str);
   8514     NK_ASSERT(len >= 0);
   8515     if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
   8516     if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
   8517         (s->buffer.type == NK_BUFFER_FIXED)) return 0;
   8518 
   8519     copylen = (int)s->buffer.allocated - pos;
   8520     if (!copylen) {
   8521         nk_str_append_text_char(s, str, len);
   8522         return 1;
   8523     }
   8524     mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
   8525     if (!mem) return 0;
   8526 
   8527     /* memmove */
   8528     NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
   8529     NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
   8530     dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
   8531     src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
   8532     for (i = 0; i < copylen; ++i) *dst-- = *src--;
   8533     mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
   8534     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
   8535     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
   8536     return 1;
   8537 }
   8538 NK_API int
   8539 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
   8540 {
   8541     int glyph_len;
   8542     nk_rune unicode;
   8543     const char *begin;
   8544     const char *buffer;
   8545 
   8546     NK_ASSERT(str);
   8547     NK_ASSERT(cstr);
   8548     NK_ASSERT(len);
   8549     if (!str || !cstr || !len) return 0;
   8550     begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
   8551     if (!str->len)
   8552         return nk_str_append_text_char(str, cstr, len);
   8553     buffer = nk_str_get_const(str);
   8554     if (!begin) return 0;
   8555     return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
   8556 }
   8557 NK_API int
   8558 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
   8559 {
   8560     return nk_str_insert_text_utf8(str, pos, text, len);
   8561 }
   8562 NK_API int
   8563 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
   8564 {
   8565     return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
   8566 }
   8567 NK_API int
   8568 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
   8569 {
   8570     int i = 0;
   8571     int byte_len = 0;
   8572     nk_rune unicode;
   8573 
   8574     NK_ASSERT(str);
   8575     NK_ASSERT(text);
   8576     if (!str || !text || !len) return 0;
   8577     for (i = 0; i < len; ++i)
   8578         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
   8579     nk_str_insert_at_rune(str, pos, text, byte_len);
   8580     return len;
   8581 }
   8582 NK_API int
   8583 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
   8584 {
   8585     int byte_len = 0;
   8586     int num_runes = 0;
   8587     int glyph_len = 0;
   8588     nk_rune unicode;
   8589     if (!str || !text) return 0;
   8590 
   8591     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
   8592     while (unicode != '\0' && glyph_len) {
   8593         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
   8594         byte_len += glyph_len;
   8595         num_runes++;
   8596     }
   8597     nk_str_insert_at_rune(str, pos, text, byte_len);
   8598     return num_runes;
   8599 }
   8600 NK_API int
   8601 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
   8602 {
   8603     int i = 0;
   8604     int byte_len = 0;
   8605     nk_glyph glyph;
   8606 
   8607     NK_ASSERT(str);
   8608     if (!str || !runes || !len) return 0;
   8609     for (i = 0; i < len; ++i) {
   8610         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
   8611         if (!byte_len) break;
   8612         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
   8613     }
   8614     return len;
   8615 }
   8616 NK_API int
   8617 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
   8618 {
   8619     int i = 0;
   8620     nk_glyph glyph;
   8621     int byte_len;
   8622     NK_ASSERT(str);
   8623     if (!str || !runes) return 0;
   8624     while (runes[i] != '\0') {
   8625         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
   8626         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
   8627         i++;
   8628     }
   8629     return i;
   8630 }
   8631 NK_API void
   8632 nk_str_remove_chars(struct nk_str *s, int len)
   8633 {
   8634     NK_ASSERT(s);
   8635     NK_ASSERT(len >= 0);
   8636     if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
   8637     NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
   8638     s->buffer.allocated -= (nk_size)len;
   8639     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
   8640 }
   8641 NK_API void
   8642 nk_str_remove_runes(struct nk_str *str, int len)
   8643 {
   8644     int index;
   8645     const char *begin;
   8646     const char *end;
   8647     nk_rune unicode;
   8648 
   8649     NK_ASSERT(str);
   8650     NK_ASSERT(len >= 0);
   8651     if (!str || len < 0) return;
   8652     if (len >= str->len) {
   8653         str->len = 0;
   8654         return;
   8655     }
   8656 
   8657     index = str->len - len;
   8658     begin = nk_str_at_rune(str, index, &unicode, &len);
   8659     end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
   8660     nk_str_remove_chars(str, (int)(end-begin)+1);
   8661 }
   8662 NK_API void
   8663 nk_str_delete_chars(struct nk_str *s, int pos, int len)
   8664 {
   8665     NK_ASSERT(s);
   8666     if (!s || !len || (nk_size)pos > s->buffer.allocated ||
   8667         (nk_size)(pos + len) > s->buffer.allocated) return;
   8668 
   8669     if ((nk_size)(pos + len) < s->buffer.allocated) {
   8670         /* memmove */
   8671         char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
   8672         char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
   8673         NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
   8674         NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
   8675         s->buffer.allocated -= (nk_size)len;
   8676     } else nk_str_remove_chars(s, len);
   8677     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
   8678 }
   8679 NK_API void
   8680 nk_str_delete_runes(struct nk_str *s, int pos, int len)
   8681 {
   8682     char *temp;
   8683     nk_rune unicode;
   8684     char *begin;
   8685     char *end;
   8686     int unused;
   8687 
   8688     NK_ASSERT(s);
   8689     NK_ASSERT(s->len >= pos + len);
   8690     if (s->len < pos + len)
   8691         len = NK_CLAMP(0, (s->len - pos), s->len);
   8692     if (!len) return;
   8693 
   8694     temp = (char *)s->buffer.memory.ptr;
   8695     begin = nk_str_at_rune(s, pos, &unicode, &unused);
   8696     if (!begin) return;
   8697     s->buffer.memory.ptr = begin;
   8698     end = nk_str_at_rune(s, len, &unicode, &unused);
   8699     s->buffer.memory.ptr = temp;
   8700     if (!end) return;
   8701     nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
   8702 }
   8703 NK_API char*
   8704 nk_str_at_char(struct nk_str *s, int pos)
   8705 {
   8706     NK_ASSERT(s);
   8707     if (!s || pos > (int)s->buffer.allocated) return 0;
   8708     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
   8709 }
   8710 NK_API char*
   8711 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
   8712 {
   8713     int i = 0;
   8714     int src_len = 0;
   8715     int glyph_len = 0;
   8716     char *text;
   8717     int text_len;
   8718 
   8719     NK_ASSERT(str);
   8720     NK_ASSERT(unicode);
   8721     NK_ASSERT(len);
   8722 
   8723     if (!str || !unicode || !len) return 0;
   8724     if (pos < 0) {
   8725         *unicode = 0;
   8726         *len = 0;
   8727         return 0;
   8728     }
   8729 
   8730     text = (char*)str->buffer.memory.ptr;
   8731     text_len = (int)str->buffer.allocated;
   8732     glyph_len = nk_utf_decode(text, unicode, text_len);
   8733     while (glyph_len) {
   8734         if (i == pos) {
   8735             *len = glyph_len;
   8736             break;
   8737         }
   8738 
   8739         i++;
   8740         src_len = src_len + glyph_len;
   8741         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
   8742     }
   8743     if (i != pos) return 0;
   8744     return text + src_len;
   8745 }
   8746 NK_API const char*
   8747 nk_str_at_char_const(const struct nk_str *s, int pos)
   8748 {
   8749     NK_ASSERT(s);
   8750     if (!s || pos > (int)s->buffer.allocated) return 0;
   8751     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
   8752 }
   8753 NK_API const char*
   8754 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
   8755 {
   8756     int i = 0;
   8757     int src_len = 0;
   8758     int glyph_len = 0;
   8759     char *text;
   8760     int text_len;
   8761 
   8762     NK_ASSERT(str);
   8763     NK_ASSERT(unicode);
   8764     NK_ASSERT(len);
   8765 
   8766     if (!str || !unicode || !len) return 0;
   8767     if (pos < 0) {
   8768         *unicode = 0;
   8769         *len = 0;
   8770         return 0;
   8771     }
   8772 
   8773     text = (char*)str->buffer.memory.ptr;
   8774     text_len = (int)str->buffer.allocated;
   8775     glyph_len = nk_utf_decode(text, unicode, text_len);
   8776     while (glyph_len) {
   8777         if (i == pos) {
   8778             *len = glyph_len;
   8779             break;
   8780         }
   8781 
   8782         i++;
   8783         src_len = src_len + glyph_len;
   8784         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
   8785     }
   8786     if (i != pos) return 0;
   8787     return text + src_len;
   8788 }
   8789 NK_API nk_rune
   8790 nk_str_rune_at(const struct nk_str *str, int pos)
   8791 {
   8792     int len;
   8793     nk_rune unicode = 0;
   8794     nk_str_at_const(str, pos, &unicode, &len);
   8795     return unicode;
   8796 }
   8797 NK_API char*
   8798 nk_str_get(struct nk_str *s)
   8799 {
   8800     NK_ASSERT(s);
   8801     if (!s || !s->len || !s->buffer.allocated) return 0;
   8802     return (char*)s->buffer.memory.ptr;
   8803 }
   8804 NK_API const char*
   8805 nk_str_get_const(const struct nk_str *s)
   8806 {
   8807     NK_ASSERT(s);
   8808     if (!s || !s->len || !s->buffer.allocated) return 0;
   8809     return (const char*)s->buffer.memory.ptr;
   8810 }
   8811 NK_API int
   8812 nk_str_len(struct nk_str *s)
   8813 {
   8814     NK_ASSERT(s);
   8815     if (!s || !s->len || !s->buffer.allocated) return 0;
   8816     return s->len;
   8817 }
   8818 NK_API int
   8819 nk_str_len_char(struct nk_str *s)
   8820 {
   8821     NK_ASSERT(s);
   8822     if (!s || !s->len || !s->buffer.allocated) return 0;
   8823     return (int)s->buffer.allocated;
   8824 }
   8825 NK_API void
   8826 nk_str_clear(struct nk_str *str)
   8827 {
   8828     NK_ASSERT(str);
   8829     nk_buffer_clear(&str->buffer);
   8830     str->len = 0;
   8831 }
   8832 NK_API void
   8833 nk_str_free(struct nk_str *str)
   8834 {
   8835     NK_ASSERT(str);
   8836     nk_buffer_free(&str->buffer);
   8837     str->len = 0;
   8838 }
   8839 
   8840 
   8841 
   8842 
   8843 
   8844 /* ==============================================================
   8845  *
   8846  *                          DRAW
   8847  *
   8848  * ===============================================================*/
   8849 NK_LIB void
   8850 nk_command_buffer_init(struct nk_command_buffer *cb,
   8851     struct nk_buffer *b, enum nk_command_clipping clip)
   8852 {
   8853     NK_ASSERT(cb);
   8854     NK_ASSERT(b);
   8855     if (!cb || !b) return;
   8856     cb->base = b;
   8857     cb->use_clipping = (int)clip;
   8858     cb->begin = b->allocated;
   8859     cb->end = b->allocated;
   8860     cb->last = b->allocated;
   8861 }
   8862 NK_LIB void
   8863 nk_command_buffer_reset(struct nk_command_buffer *b)
   8864 {
   8865     NK_ASSERT(b);
   8866     if (!b) return;
   8867     b->begin = 0;
   8868     b->end = 0;
   8869     b->last = 0;
   8870     b->clip = nk_null_rect;
   8871 #ifdef NK_INCLUDE_COMMAND_USERDATA
   8872     b->userdata.ptr = 0;
   8873 #endif
   8874 }
   8875 NK_LIB void*
   8876 nk_command_buffer_push(struct nk_command_buffer* b,
   8877     enum nk_command_type t, nk_size size)
   8878 {
   8879     NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
   8880     struct nk_command *cmd;
   8881     nk_size alignment;
   8882     void *unaligned;
   8883     void *memory;
   8884 
   8885     NK_ASSERT(b);
   8886     NK_ASSERT(b->base);
   8887     if (!b) return 0;
   8888     cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
   8889     if (!cmd) return 0;
   8890 
   8891     /* make sure the offset to the next command is aligned */
   8892     b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
   8893     unaligned = (nk_byte*)cmd + size;
   8894     memory = NK_ALIGN_PTR(unaligned, align);
   8895     alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
   8896 #ifdef NK_ZERO_COMMAND_MEMORY
   8897     NK_MEMSET(cmd, 0, size + alignment);
   8898 #endif
   8899 
   8900     cmd->type = t;
   8901     cmd->next = b->base->allocated + alignment;
   8902 #ifdef NK_INCLUDE_COMMAND_USERDATA
   8903     cmd->userdata = b->userdata;
   8904 #endif
   8905     b->end = cmd->next;
   8906     return cmd;
   8907 }
   8908 NK_API void
   8909 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
   8910 {
   8911     struct nk_command_scissor *cmd;
   8912     NK_ASSERT(b);
   8913     if (!b) return;
   8914 
   8915     b->clip.x = r.x;
   8916     b->clip.y = r.y;
   8917     b->clip.w = r.w;
   8918     b->clip.h = r.h;
   8919     cmd = (struct nk_command_scissor*)
   8920         nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
   8921 
   8922     if (!cmd) return;
   8923     cmd->x = (short)r.x;
   8924     cmd->y = (short)r.y;
   8925     cmd->w = (unsigned short)NK_MAX(0, r.w);
   8926     cmd->h = (unsigned short)NK_MAX(0, r.h);
   8927 }
   8928 NK_API void
   8929 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
   8930     float x1, float y1, float line_thickness, struct nk_color c)
   8931 {
   8932     struct nk_command_line *cmd;
   8933     NK_ASSERT(b);
   8934     if (!b || line_thickness <= 0) return;
   8935     cmd = (struct nk_command_line*)
   8936         nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
   8937     if (!cmd) return;
   8938     cmd->line_thickness = (unsigned short)line_thickness;
   8939     cmd->begin.x = (short)x0;
   8940     cmd->begin.y = (short)y0;
   8941     cmd->end.x = (short)x1;
   8942     cmd->end.y = (short)y1;
   8943     cmd->color = c;
   8944 }
   8945 NK_API void
   8946 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
   8947     float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
   8948     float bx, float by, float line_thickness, struct nk_color col)
   8949 {
   8950     struct nk_command_curve *cmd;
   8951     NK_ASSERT(b);
   8952     if (!b || col.a == 0 || line_thickness <= 0) return;
   8953 
   8954     cmd = (struct nk_command_curve*)
   8955         nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
   8956     if (!cmd) return;
   8957     cmd->line_thickness = (unsigned short)line_thickness;
   8958     cmd->begin.x = (short)ax;
   8959     cmd->begin.y = (short)ay;
   8960     cmd->ctrl[0].x = (short)ctrl0x;
   8961     cmd->ctrl[0].y = (short)ctrl0y;
   8962     cmd->ctrl[1].x = (short)ctrl1x;
   8963     cmd->ctrl[1].y = (short)ctrl1y;
   8964     cmd->end.x = (short)bx;
   8965     cmd->end.y = (short)by;
   8966     cmd->color = col;
   8967 }
   8968 NK_API void
   8969 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
   8970     float rounding, float line_thickness, struct nk_color c)
   8971 {
   8972     struct nk_command_rect *cmd;
   8973     NK_ASSERT(b);
   8974     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
   8975     if (b->use_clipping) {
   8976         const struct nk_rect *clip = &b->clip;
   8977         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
   8978             clip->x, clip->y, clip->w, clip->h)) return;
   8979     }
   8980     cmd = (struct nk_command_rect*)
   8981         nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
   8982     if (!cmd) return;
   8983     cmd->rounding = (unsigned short)rounding;
   8984     cmd->line_thickness = (unsigned short)line_thickness;
   8985     cmd->x = (short)rect.x;
   8986     cmd->y = (short)rect.y;
   8987     cmd->w = (unsigned short)NK_MAX(0, rect.w);
   8988     cmd->h = (unsigned short)NK_MAX(0, rect.h);
   8989     cmd->color = c;
   8990 }
   8991 NK_API void
   8992 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
   8993     float rounding, struct nk_color c)
   8994 {
   8995     struct nk_command_rect_filled *cmd;
   8996     NK_ASSERT(b);
   8997     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
   8998     if (b->use_clipping) {
   8999         const struct nk_rect *clip = &b->clip;
   9000         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
   9001             clip->x, clip->y, clip->w, clip->h)) return;
   9002     }
   9003 
   9004     cmd = (struct nk_command_rect_filled*)
   9005         nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
   9006     if (!cmd) return;
   9007     cmd->rounding = (unsigned short)rounding;
   9008     cmd->x = (short)rect.x;
   9009     cmd->y = (short)rect.y;
   9010     cmd->w = (unsigned short)NK_MAX(0, rect.w);
   9011     cmd->h = (unsigned short)NK_MAX(0, rect.h);
   9012     cmd->color = c;
   9013 }
   9014 NK_API void
   9015 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
   9016     struct nk_color left, struct nk_color top, struct nk_color right,
   9017     struct nk_color bottom)
   9018 {
   9019     struct nk_command_rect_multi_color *cmd;
   9020     NK_ASSERT(b);
   9021     if (!b || rect.w == 0 || rect.h == 0) return;
   9022     if (b->use_clipping) {
   9023         const struct nk_rect *clip = &b->clip;
   9024         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
   9025             clip->x, clip->y, clip->w, clip->h)) return;
   9026     }
   9027 
   9028     cmd = (struct nk_command_rect_multi_color*)
   9029         nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
   9030     if (!cmd) return;
   9031     cmd->x = (short)rect.x;
   9032     cmd->y = (short)rect.y;
   9033     cmd->w = (unsigned short)NK_MAX(0, rect.w);
   9034     cmd->h = (unsigned short)NK_MAX(0, rect.h);
   9035     cmd->left = left;
   9036     cmd->top = top;
   9037     cmd->right = right;
   9038     cmd->bottom = bottom;
   9039 }
   9040 NK_API void
   9041 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
   9042     float line_thickness, struct nk_color c)
   9043 {
   9044     struct nk_command_circle *cmd;
   9045     if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
   9046     if (b->use_clipping) {
   9047         const struct nk_rect *clip = &b->clip;
   9048         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
   9049             return;
   9050     }
   9051 
   9052     cmd = (struct nk_command_circle*)
   9053         nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
   9054     if (!cmd) return;
   9055     cmd->line_thickness = (unsigned short)line_thickness;
   9056     cmd->x = (short)r.x;
   9057     cmd->y = (short)r.y;
   9058     cmd->w = (unsigned short)NK_MAX(r.w, 0);
   9059     cmd->h = (unsigned short)NK_MAX(r.h, 0);
   9060     cmd->color = c;
   9061 }
   9062 NK_API void
   9063 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
   9064 {
   9065     struct nk_command_circle_filled *cmd;
   9066     NK_ASSERT(b);
   9067     if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
   9068     if (b->use_clipping) {
   9069         const struct nk_rect *clip = &b->clip;
   9070         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
   9071             return;
   9072     }
   9073 
   9074     cmd = (struct nk_command_circle_filled*)
   9075         nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
   9076     if (!cmd) return;
   9077     cmd->x = (short)r.x;
   9078     cmd->y = (short)r.y;
   9079     cmd->w = (unsigned short)NK_MAX(r.w, 0);
   9080     cmd->h = (unsigned short)NK_MAX(r.h, 0);
   9081     cmd->color = c;
   9082 }
   9083 NK_API void
   9084 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
   9085     float a_min, float a_max, float line_thickness, struct nk_color c)
   9086 {
   9087     struct nk_command_arc *cmd;
   9088     if (!b || c.a == 0 || line_thickness <= 0) return;
   9089     cmd = (struct nk_command_arc*)
   9090         nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
   9091     if (!cmd) return;
   9092     cmd->line_thickness = (unsigned short)line_thickness;
   9093     cmd->cx = (short)cx;
   9094     cmd->cy = (short)cy;
   9095     cmd->r = (unsigned short)radius;
   9096     cmd->a[0] = a_min;
   9097     cmd->a[1] = a_max;
   9098     cmd->color = c;
   9099 }
   9100 NK_API void
   9101 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
   9102     float a_min, float a_max, struct nk_color c)
   9103 {
   9104     struct nk_command_arc_filled *cmd;
   9105     NK_ASSERT(b);
   9106     if (!b || c.a == 0) return;
   9107     cmd = (struct nk_command_arc_filled*)
   9108         nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
   9109     if (!cmd) return;
   9110     cmd->cx = (short)cx;
   9111     cmd->cy = (short)cy;
   9112     cmd->r = (unsigned short)radius;
   9113     cmd->a[0] = a_min;
   9114     cmd->a[1] = a_max;
   9115     cmd->color = c;
   9116 }
   9117 NK_API void
   9118 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
   9119     float y1, float x2, float y2, float line_thickness, struct nk_color c)
   9120 {
   9121     struct nk_command_triangle *cmd;
   9122     NK_ASSERT(b);
   9123     if (!b || c.a == 0 || line_thickness <= 0) return;
   9124     if (b->use_clipping) {
   9125         const struct nk_rect *clip = &b->clip;
   9126         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
   9127             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
   9128             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
   9129             return;
   9130     }
   9131 
   9132     cmd = (struct nk_command_triangle*)
   9133         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
   9134     if (!cmd) return;
   9135     cmd->line_thickness = (unsigned short)line_thickness;
   9136     cmd->a.x = (short)x0;
   9137     cmd->a.y = (short)y0;
   9138     cmd->b.x = (short)x1;
   9139     cmd->b.y = (short)y1;
   9140     cmd->c.x = (short)x2;
   9141     cmd->c.y = (short)y2;
   9142     cmd->color = c;
   9143 }
   9144 NK_API void
   9145 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
   9146     float y1, float x2, float y2, struct nk_color c)
   9147 {
   9148     struct nk_command_triangle_filled *cmd;
   9149     NK_ASSERT(b);
   9150     if (!b || c.a == 0) return;
   9151     if (!b) return;
   9152     if (b->use_clipping) {
   9153         const struct nk_rect *clip = &b->clip;
   9154         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
   9155             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
   9156             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
   9157             return;
   9158     }
   9159 
   9160     cmd = (struct nk_command_triangle_filled*)
   9161         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
   9162     if (!cmd) return;
   9163     cmd->a.x = (short)x0;
   9164     cmd->a.y = (short)y0;
   9165     cmd->b.x = (short)x1;
   9166     cmd->b.y = (short)y1;
   9167     cmd->c.x = (short)x2;
   9168     cmd->c.y = (short)y2;
   9169     cmd->color = c;
   9170 }
   9171 NK_API void
   9172 nk_stroke_polygon(struct nk_command_buffer *b,  float *points, int point_count,
   9173     float line_thickness, struct nk_color col)
   9174 {
   9175     int i;
   9176     nk_size size = 0;
   9177     struct nk_command_polygon *cmd;
   9178 
   9179     NK_ASSERT(b);
   9180     if (!b || col.a == 0 || line_thickness <= 0) return;
   9181     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
   9182     cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
   9183     if (!cmd) return;
   9184     cmd->color = col;
   9185     cmd->line_thickness = (unsigned short)line_thickness;
   9186     cmd->point_count = (unsigned short)point_count;
   9187     for (i = 0; i < point_count; ++i) {
   9188         cmd->points[i].x = (short)points[i*2];
   9189         cmd->points[i].y = (short)points[i*2+1];
   9190     }
   9191 }
   9192 NK_API void
   9193 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
   9194     struct nk_color col)
   9195 {
   9196     int i;
   9197     nk_size size = 0;
   9198     struct nk_command_polygon_filled *cmd;
   9199 
   9200     NK_ASSERT(b);
   9201     if (!b || col.a == 0) return;
   9202     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
   9203     cmd = (struct nk_command_polygon_filled*)
   9204         nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
   9205     if (!cmd) return;
   9206     cmd->color = col;
   9207     cmd->point_count = (unsigned short)point_count;
   9208     for (i = 0; i < point_count; ++i) {
   9209         cmd->points[i].x = (short)points[i*2+0];
   9210         cmd->points[i].y = (short)points[i*2+1];
   9211     }
   9212 }
   9213 NK_API void
   9214 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count,
   9215     float line_thickness, struct nk_color col)
   9216 {
   9217     int i;
   9218     nk_size size = 0;
   9219     struct nk_command_polyline *cmd;
   9220 
   9221     NK_ASSERT(b);
   9222     if (!b || col.a == 0 || line_thickness <= 0) return;
   9223     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
   9224     cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
   9225     if (!cmd) return;
   9226     cmd->color = col;
   9227     cmd->point_count = (unsigned short)point_count;
   9228     cmd->line_thickness = (unsigned short)line_thickness;
   9229     for (i = 0; i < point_count; ++i) {
   9230         cmd->points[i].x = (short)points[i*2];
   9231         cmd->points[i].y = (short)points[i*2+1];
   9232     }
   9233 }
   9234 NK_API void
   9235 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
   9236     const struct nk_image *img, struct nk_color col)
   9237 {
   9238     struct nk_command_image *cmd;
   9239     NK_ASSERT(b);
   9240     if (!b) return;
   9241     if (b->use_clipping) {
   9242         const struct nk_rect *c = &b->clip;
   9243         if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
   9244             return;
   9245     }
   9246 
   9247     cmd = (struct nk_command_image*)
   9248         nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
   9249     if (!cmd) return;
   9250     cmd->x = (short)r.x;
   9251     cmd->y = (short)r.y;
   9252     cmd->w = (unsigned short)NK_MAX(0, r.w);
   9253     cmd->h = (unsigned short)NK_MAX(0, r.h);
   9254     cmd->img = *img;
   9255     cmd->col = col;
   9256 }
   9257 NK_API void
   9258 nk_draw_nine_slice(struct nk_command_buffer *b, struct nk_rect r,
   9259     const struct nk_nine_slice *slc, struct nk_color col)
   9260 {
   9261     struct nk_image img;
   9262     const struct nk_image *slcimg = (const struct nk_image*)slc;
   9263     nk_ushort rgnX, rgnY, rgnW, rgnH;
   9264     rgnX = slcimg->region[0];
   9265     rgnY = slcimg->region[1];
   9266     rgnW = slcimg->region[2];
   9267     rgnH = slcimg->region[3];
   9268 
   9269     /* top-left */
   9270     img.handle = slcimg->handle;
   9271     img.w = slcimg->w;
   9272     img.h = slcimg->h;
   9273     img.region[0] = rgnX;
   9274     img.region[1] = rgnY;
   9275     img.region[2] = slc->l;
   9276     img.region[3] = slc->t;
   9277 
   9278     nk_draw_image(b,
   9279         nk_rect(r.x, r.y, (float)slc->l, (float)slc->t),
   9280         &img, col);
   9281 
   9282 #define IMG_RGN(x, y, w, h) img.region[0] = (nk_ushort)(x); img.region[1] = (nk_ushort)(y); img.region[2] = (nk_ushort)(w); img.region[3] = (nk_ushort)(h);
   9283 
   9284     /* top-center */
   9285     IMG_RGN(rgnX + slc->l, rgnY, rgnW - slc->l - slc->r, slc->t);
   9286     nk_draw_image(b,
   9287         nk_rect(r.x + (float)slc->l, r.y, (float)(r.w - slc->l - slc->r), (float)slc->t),
   9288         &img, col);
   9289 
   9290     /* top-right */
   9291     IMG_RGN(rgnX + rgnW - slc->r, rgnY, slc->r, slc->t);
   9292     nk_draw_image(b,
   9293         nk_rect(r.x + r.w - (float)slc->r, r.y, (float)slc->r, (float)slc->t),
   9294         &img, col);
   9295 
   9296     /* center-left */
   9297     IMG_RGN(rgnX, rgnY + slc->t, slc->l, rgnH - slc->t - slc->b);
   9298     nk_draw_image(b,
   9299         nk_rect(r.x, r.y + (float)slc->t, (float)slc->l, (float)(r.h - slc->t - slc->b)),
   9300         &img, col);
   9301 
   9302     /* center */
   9303     IMG_RGN(rgnX + slc->l, rgnY + slc->t, rgnW - slc->l - slc->r, rgnH - slc->t - slc->b);
   9304     nk_draw_image(b,
   9305         nk_rect(r.x + (float)slc->l, r.y + (float)slc->t, (float)(r.w - slc->l - slc->r), (float)(r.h - slc->t - slc->b)),
   9306         &img, col);
   9307 
   9308     /* center-right */
   9309     IMG_RGN(rgnX + rgnW - slc->r, rgnY + slc->t, slc->r, rgnH - slc->t - slc->b);
   9310     nk_draw_image(b,
   9311         nk_rect(r.x + r.w - (float)slc->r, r.y + (float)slc->t, (float)slc->r, (float)(r.h - slc->t - slc->b)),
   9312         &img, col);
   9313 
   9314     /* bottom-left */
   9315     IMG_RGN(rgnX, rgnY + rgnH - slc->b, slc->l, slc->b);
   9316     nk_draw_image(b,
   9317         nk_rect(r.x, r.y + r.h - (float)slc->b, (float)slc->l, (float)slc->b),
   9318         &img, col);
   9319 
   9320     /* bottom-center */
   9321     IMG_RGN(rgnX + slc->l, rgnY + rgnH - slc->b, rgnW - slc->l - slc->r, slc->b);
   9322     nk_draw_image(b,
   9323         nk_rect(r.x + (float)slc->l, r.y + r.h - (float)slc->b, (float)(r.w - slc->l - slc->r), (float)slc->b),
   9324         &img, col);
   9325 
   9326     /* bottom-right */
   9327     IMG_RGN(rgnX + rgnW - slc->r, rgnY + rgnH - slc->b, slc->r, slc->b);
   9328     nk_draw_image(b,
   9329         nk_rect(r.x + r.w - (float)slc->r, r.y + r.h - (float)slc->b, (float)slc->r, (float)slc->b),
   9330         &img, col);
   9331 
   9332 #undef IMG_RGN
   9333 }
   9334 NK_API void
   9335 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
   9336     nk_command_custom_callback cb, nk_handle usr)
   9337 {
   9338     struct nk_command_custom *cmd;
   9339     NK_ASSERT(b);
   9340     if (!b) return;
   9341     if (b->use_clipping) {
   9342         const struct nk_rect *c = &b->clip;
   9343         if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
   9344             return;
   9345     }
   9346 
   9347     cmd = (struct nk_command_custom*)
   9348         nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
   9349     if (!cmd) return;
   9350     cmd->x = (short)r.x;
   9351     cmd->y = (short)r.y;
   9352     cmd->w = (unsigned short)NK_MAX(0, r.w);
   9353     cmd->h = (unsigned short)NK_MAX(0, r.h);
   9354     cmd->callback_data = usr;
   9355     cmd->callback = cb;
   9356 }
   9357 NK_API void
   9358 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
   9359     const char *string, int length, const struct nk_user_font *font,
   9360     struct nk_color bg, struct nk_color fg)
   9361 {
   9362     float text_width = 0;
   9363     struct nk_command_text *cmd;
   9364 
   9365     NK_ASSERT(b);
   9366     NK_ASSERT(font);
   9367     if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
   9368     if (b->use_clipping) {
   9369         const struct nk_rect *c = &b->clip;
   9370         if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
   9371             return;
   9372     }
   9373 
   9374     /* make sure text fits inside bounds */
   9375     text_width = font->width(font->userdata, font->height, string, length);
   9376     if (text_width > r.w){
   9377         int glyphs = 0;
   9378         float txt_width = (float)text_width;
   9379         length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
   9380     }
   9381 
   9382     if (!length) return;
   9383     cmd = (struct nk_command_text*)
   9384         nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
   9385     if (!cmd) return;
   9386     cmd->x = (short)r.x;
   9387     cmd->y = (short)r.y;
   9388     cmd->w = (unsigned short)r.w;
   9389     cmd->h = (unsigned short)r.h;
   9390     cmd->background = bg;
   9391     cmd->foreground = fg;
   9392     cmd->font = font;
   9393     cmd->length = length;
   9394     cmd->height = font->height;
   9395     NK_MEMCPY(cmd->string, string, (nk_size)length);
   9396     cmd->string[length] = '\0';
   9397 }
   9398 
   9399 
   9400 
   9401 
   9402 
   9403 /* ===============================================================
   9404  *
   9405  *                              VERTEX
   9406  *
   9407  * ===============================================================*/
   9408 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   9409 NK_API void
   9410 nk_draw_list_init(struct nk_draw_list *list)
   9411 {
   9412     nk_size i = 0;
   9413     NK_ASSERT(list);
   9414     if (!list) return;
   9415     nk_zero(list, sizeof(*list));
   9416     for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
   9417         const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
   9418         list->circle_vtx[i].x = (float)NK_COS(a);
   9419         list->circle_vtx[i].y = (float)NK_SIN(a);
   9420     }
   9421 }
   9422 NK_API void
   9423 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
   9424     struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
   9425     enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
   9426 {
   9427     NK_ASSERT(canvas);
   9428     NK_ASSERT(config);
   9429     NK_ASSERT(cmds);
   9430     NK_ASSERT(vertices);
   9431     NK_ASSERT(elements);
   9432     if (!canvas || !config || !cmds || !vertices || !elements)
   9433         return;
   9434 
   9435     canvas->buffer = cmds;
   9436     canvas->config = *config;
   9437     canvas->elements = elements;
   9438     canvas->vertices = vertices;
   9439     canvas->line_AA = line_aa;
   9440     canvas->shape_AA = shape_aa;
   9441     canvas->clip_rect = nk_null_rect;
   9442 
   9443     canvas->cmd_offset = 0;
   9444     canvas->element_count = 0;
   9445     canvas->vertex_count = 0;
   9446     canvas->cmd_offset = 0;
   9447     canvas->cmd_count = 0;
   9448     canvas->path_count = 0;
   9449 }
   9450 NK_API const struct nk_draw_command*
   9451 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
   9452 {
   9453     nk_byte *memory;
   9454     nk_size offset;
   9455     const struct nk_draw_command *cmd;
   9456 
   9457     NK_ASSERT(buffer);
   9458     if (!buffer || !buffer->size || !canvas->cmd_count)
   9459         return 0;
   9460 
   9461     memory = (nk_byte*)buffer->memory.ptr;
   9462     offset = buffer->memory.size - canvas->cmd_offset;
   9463     cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
   9464     return cmd;
   9465 }
   9466 NK_API const struct nk_draw_command*
   9467 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
   9468 {
   9469     nk_size size;
   9470     nk_size offset;
   9471     nk_byte *memory;
   9472     const struct nk_draw_command *end;
   9473 
   9474     NK_ASSERT(buffer);
   9475     NK_ASSERT(canvas);
   9476     if (!buffer || !canvas)
   9477         return 0;
   9478 
   9479     memory = (nk_byte*)buffer->memory.ptr;
   9480     size = buffer->memory.size;
   9481     offset = size - canvas->cmd_offset;
   9482     end = nk_ptr_add(const struct nk_draw_command, memory, offset);
   9483     end -= (canvas->cmd_count-1);
   9484     return end;
   9485 }
   9486 NK_API const struct nk_draw_command*
   9487 nk__draw_list_next(const struct nk_draw_command *cmd,
   9488     const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
   9489 {
   9490     const struct nk_draw_command *end;
   9491     NK_ASSERT(buffer);
   9492     NK_ASSERT(canvas);
   9493     if (!cmd || !buffer || !canvas)
   9494         return 0;
   9495 
   9496     end = nk__draw_list_end(canvas, buffer);
   9497     if (cmd <= end) return 0;
   9498     return (cmd-1);
   9499 }
   9500 NK_INTERN struct nk_vec2*
   9501 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
   9502 {
   9503     struct nk_vec2 *points;
   9504     NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
   9505     NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
   9506     points = (struct nk_vec2*)
   9507         nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
   9508                         point_size * (nk_size)count, point_align);
   9509 
   9510     if (!points) return 0;
   9511     if (!list->path_offset) {
   9512         void *memory = nk_buffer_memory(list->buffer);
   9513         list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
   9514     }
   9515     list->path_count += (unsigned int)count;
   9516     return points;
   9517 }
   9518 NK_INTERN struct nk_vec2
   9519 nk_draw_list_path_last(struct nk_draw_list *list)
   9520 {
   9521     void *memory;
   9522     struct nk_vec2 *point;
   9523     NK_ASSERT(list->path_count);
   9524     memory = nk_buffer_memory(list->buffer);
   9525     point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
   9526     point += (list->path_count-1);
   9527     return *point;
   9528 }
   9529 NK_INTERN struct nk_draw_command*
   9530 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
   9531     nk_handle texture)
   9532 {
   9533     NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
   9534     NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
   9535     struct nk_draw_command *cmd;
   9536 
   9537     NK_ASSERT(list);
   9538     cmd = (struct nk_draw_command*)
   9539         nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
   9540 
   9541     if (!cmd) return 0;
   9542     if (!list->cmd_count) {
   9543         nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
   9544         nk_size total = nk_buffer_total(list->buffer);
   9545         memory = nk_ptr_add(nk_byte, memory, total);
   9546         list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
   9547     }
   9548 
   9549     cmd->elem_count = 0;
   9550     cmd->clip_rect = clip;
   9551     cmd->texture = texture;
   9552 #ifdef NK_INCLUDE_COMMAND_USERDATA
   9553     cmd->userdata = list->userdata;
   9554 #endif
   9555 
   9556     list->cmd_count++;
   9557     list->clip_rect = clip;
   9558     return cmd;
   9559 }
   9560 NK_INTERN struct nk_draw_command*
   9561 nk_draw_list_command_last(struct nk_draw_list *list)
   9562 {
   9563     void *memory;
   9564     nk_size size;
   9565     struct nk_draw_command *cmd;
   9566     NK_ASSERT(list->cmd_count);
   9567 
   9568     memory = nk_buffer_memory(list->buffer);
   9569     size = nk_buffer_total(list->buffer);
   9570     cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
   9571     return (cmd - (list->cmd_count-1));
   9572 }
   9573 NK_INTERN void
   9574 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
   9575 {
   9576     NK_ASSERT(list);
   9577     if (!list) return;
   9578     if (!list->cmd_count) {
   9579         nk_draw_list_push_command(list, rect, list->config.tex_null.texture);
   9580     } else {
   9581         struct nk_draw_command *prev = nk_draw_list_command_last(list);
   9582         if (prev->elem_count == 0)
   9583             prev->clip_rect = rect;
   9584         nk_draw_list_push_command(list, rect, prev->texture);
   9585     }
   9586 }
   9587 NK_INTERN void
   9588 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
   9589 {
   9590     NK_ASSERT(list);
   9591     if (!list) return;
   9592     if (!list->cmd_count) {
   9593         nk_draw_list_push_command(list, nk_null_rect, texture);
   9594     } else {
   9595         struct nk_draw_command *prev = nk_draw_list_command_last(list);
   9596         if (prev->elem_count == 0) {
   9597             prev->texture = texture;
   9598         #ifdef NK_INCLUDE_COMMAND_USERDATA
   9599             prev->userdata = list->userdata;
   9600         #endif
   9601     } else if (prev->texture.id != texture.id
   9602         #ifdef NK_INCLUDE_COMMAND_USERDATA
   9603             || prev->userdata.id != list->userdata.id
   9604         #endif
   9605         ) nk_draw_list_push_command(list, prev->clip_rect, texture);
   9606     }
   9607 }
   9608 #ifdef NK_INCLUDE_COMMAND_USERDATA
   9609 NK_API void
   9610 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
   9611 {
   9612     list->userdata = userdata;
   9613 }
   9614 #endif
   9615 NK_INTERN void*
   9616 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
   9617 {
   9618     void *vtx;
   9619     NK_ASSERT(list);
   9620     if (!list) return 0;
   9621     vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
   9622         list->config.vertex_size*count, list->config.vertex_alignment);
   9623     if (!vtx) return 0;
   9624     list->vertex_count += (unsigned int)count;
   9625 
   9626     /* This assert triggers because your are drawing a lot of stuff and nuklear
   9627      * defined `nk_draw_index` as `nk_ushort` to safe space be default.
   9628      *
   9629      * So you reached the maximum number of indices or rather vertexes.
   9630      * To solve this issue please change typedef `nk_draw_index` to `nk_uint`
   9631      * and don't forget to specify the new element size in your drawing
   9632      * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements`
   9633      * instead of specifying `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`.
   9634      * Sorry for the inconvenience. */
   9635     if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX &&
   9636         "To many vertices for 16-bit vertex indices. Please read comment above on how to solve this problem"));
   9637     return vtx;
   9638 }
   9639 NK_INTERN nk_draw_index*
   9640 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
   9641 {
   9642     nk_draw_index *ids;
   9643     struct nk_draw_command *cmd;
   9644     NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
   9645     NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
   9646     NK_ASSERT(list);
   9647     if (!list) return 0;
   9648 
   9649     ids = (nk_draw_index*)
   9650         nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
   9651     if (!ids) return 0;
   9652     cmd = nk_draw_list_command_last(list);
   9653     list->element_count += (unsigned int)count;
   9654     cmd->elem_count += (unsigned int)count;
   9655     return ids;
   9656 }
   9657 NK_INTERN int
   9658 nk_draw_vertex_layout_element_is_end_of_layout(
   9659     const struct nk_draw_vertex_layout_element *element)
   9660 {
   9661     return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
   9662             element->format == NK_FORMAT_COUNT);
   9663 }
   9664 NK_INTERN void
   9665 nk_draw_vertex_color(void *attr, const float *vals,
   9666     enum nk_draw_vertex_layout_format format)
   9667 {
   9668     /* if this triggers you tried to provide a value format for a color */
   9669     float val[4];
   9670     NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
   9671     NK_ASSERT(format <= NK_FORMAT_COLOR_END);
   9672     if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
   9673 
   9674     val[0] = NK_SATURATE(vals[0]);
   9675     val[1] = NK_SATURATE(vals[1]);
   9676     val[2] = NK_SATURATE(vals[2]);
   9677     val[3] = NK_SATURATE(vals[3]);
   9678 
   9679     switch (format) {
   9680     default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
   9681     case NK_FORMAT_R8G8B8A8:
   9682     case NK_FORMAT_R8G8B8: {
   9683         struct nk_color col = nk_rgba_fv(val);
   9684         NK_MEMCPY(attr, &col.r, sizeof(col));
   9685     } break;
   9686     case NK_FORMAT_B8G8R8A8: {
   9687         struct nk_color col = nk_rgba_fv(val);
   9688         struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
   9689         NK_MEMCPY(attr, &bgra, sizeof(bgra));
   9690     } break;
   9691     case NK_FORMAT_R16G15B16: {
   9692         nk_ushort col[3];
   9693         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
   9694         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
   9695         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
   9696         NK_MEMCPY(attr, col, sizeof(col));
   9697     } break;
   9698     case NK_FORMAT_R16G15B16A16: {
   9699         nk_ushort col[4];
   9700         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
   9701         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
   9702         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
   9703         col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX);
   9704         NK_MEMCPY(attr, col, sizeof(col));
   9705     } break;
   9706     case NK_FORMAT_R32G32B32: {
   9707         nk_uint col[3];
   9708         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
   9709         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
   9710         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
   9711         NK_MEMCPY(attr, col, sizeof(col));
   9712     } break;
   9713     case NK_FORMAT_R32G32B32A32: {
   9714         nk_uint col[4];
   9715         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
   9716         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
   9717         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
   9718         col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX);
   9719         NK_MEMCPY(attr, col, sizeof(col));
   9720     } break;
   9721     case NK_FORMAT_R32G32B32A32_FLOAT:
   9722         NK_MEMCPY(attr, val, sizeof(float)*4);
   9723         break;
   9724     case NK_FORMAT_R32G32B32A32_DOUBLE: {
   9725         double col[4];
   9726         col[0] = (double)val[0];
   9727         col[1] = (double)val[1];
   9728         col[2] = (double)val[2];
   9729         col[3] = (double)val[3];
   9730         NK_MEMCPY(attr, col, sizeof(col));
   9731     } break;
   9732     case NK_FORMAT_RGB32:
   9733     case NK_FORMAT_RGBA32: {
   9734         struct nk_color col = nk_rgba_fv(val);
   9735         nk_uint color = nk_color_u32(col);
   9736         NK_MEMCPY(attr, &color, sizeof(color));
   9737     } break; }
   9738 }
   9739 NK_INTERN void
   9740 nk_draw_vertex_element(void *dst, const float *values, int value_count,
   9741     enum nk_draw_vertex_layout_format format)
   9742 {
   9743     int value_index;
   9744     void *attribute = dst;
   9745     /* if this triggers you tried to provide a color format for a value */
   9746     NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
   9747     if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
   9748     for (value_index = 0; value_index < value_count; ++value_index) {
   9749         switch (format) {
   9750         default: NK_ASSERT(0 && "invalid vertex layout format"); break;
   9751         case NK_FORMAT_SCHAR: {
   9752             char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX);
   9753             NK_MEMCPY(attribute, &value, sizeof(value));
   9754             attribute = (void*)((char*)attribute + sizeof(char));
   9755         } break;
   9756         case NK_FORMAT_SSHORT: {
   9757             nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX);
   9758             NK_MEMCPY(attribute, &value, sizeof(value));
   9759             attribute = (void*)((char*)attribute + sizeof(value));
   9760         } break;
   9761         case NK_FORMAT_SINT: {
   9762             nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX);
   9763             NK_MEMCPY(attribute, &value, sizeof(value));
   9764             attribute = (void*)((char*)attribute + sizeof(nk_int));
   9765         } break;
   9766         case NK_FORMAT_UCHAR: {
   9767             unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX);
   9768             NK_MEMCPY(attribute, &value, sizeof(value));
   9769             attribute = (void*)((char*)attribute + sizeof(unsigned char));
   9770         } break;
   9771         case NK_FORMAT_USHORT: {
   9772             nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX);
   9773             NK_MEMCPY(attribute, &value, sizeof(value));
   9774             attribute = (void*)((char*)attribute + sizeof(value));
   9775             } break;
   9776         case NK_FORMAT_UINT: {
   9777             nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX);
   9778             NK_MEMCPY(attribute, &value, sizeof(value));
   9779             attribute = (void*)((char*)attribute + sizeof(nk_uint));
   9780         } break;
   9781         case NK_FORMAT_FLOAT:
   9782             NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
   9783             attribute = (void*)((char*)attribute + sizeof(float));
   9784             break;
   9785         case NK_FORMAT_DOUBLE: {
   9786             double value = (double)values[value_index];
   9787             NK_MEMCPY(attribute, &value, sizeof(value));
   9788             attribute = (void*)((char*)attribute + sizeof(double));
   9789             } break;
   9790         }
   9791     }
   9792 }
   9793 NK_INTERN void*
   9794 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
   9795     struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
   9796 {
   9797     void *result = (void*)((char*)dst + config->vertex_size);
   9798     const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
   9799     while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
   9800         void *address = (void*)((char*)dst + elem_iter->offset);
   9801         switch (elem_iter->attribute) {
   9802         case NK_VERTEX_ATTRIBUTE_COUNT:
   9803         default: NK_ASSERT(0 && "wrong element attribute"); break;
   9804         case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
   9805         case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
   9806         case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
   9807         }
   9808         elem_iter++;
   9809     }
   9810     return result;
   9811 }
   9812 NK_API void
   9813 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
   9814     const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
   9815     float thickness, enum nk_anti_aliasing aliasing)
   9816 {
   9817     nk_size count;
   9818     int thick_line;
   9819     struct nk_colorf col;
   9820     struct nk_colorf col_trans;
   9821     NK_ASSERT(list);
   9822     if (!list || points_count < 2) return;
   9823 
   9824     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
   9825     count = points_count;
   9826     if (!closed) count = points_count-1;
   9827     thick_line = thickness > 1.0f;
   9828 
   9829 #ifdef NK_INCLUDE_COMMAND_USERDATA
   9830     nk_draw_list_push_userdata(list, list->userdata);
   9831 #endif
   9832 
   9833     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
   9834     nk_color_fv(&col.r, color);
   9835     col_trans = col;
   9836     col_trans.a = 0;
   9837 
   9838     if (aliasing == NK_ANTI_ALIASING_ON) {
   9839         /* ANTI-ALIASED STROKE */
   9840         const float AA_SIZE = 1.0f;
   9841         NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
   9842         NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
   9843 
   9844         /* allocate vertices and elements  */
   9845         nk_size i1 = 0;
   9846         nk_size vertex_offset;
   9847         nk_size index = list->vertex_count;
   9848 
   9849         const nk_size idx_count = (thick_line) ?  (count * 18) : (count * 12);
   9850         const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
   9851 
   9852         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
   9853         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
   9854 
   9855         nk_size size;
   9856         struct nk_vec2 *normals, *temp;
   9857         if (!vtx || !ids) return;
   9858 
   9859         /* temporary allocate normals + points */
   9860         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
   9861         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
   9862         size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
   9863         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
   9864         if (!normals) return;
   9865         temp = normals + points_count;
   9866 
   9867         /* make sure vertex pointer is still correct */
   9868         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
   9869 
   9870         /* calculate normals */
   9871         for (i1 = 0; i1 < count; ++i1) {
   9872             const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
   9873             struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
   9874             float len;
   9875 
   9876             /* vec2 inverted length  */
   9877             len = nk_vec2_len_sqr(diff);
   9878             if (len != 0.0f)
   9879                 len = NK_INV_SQRT(len);
   9880             else len = 1.0f;
   9881 
   9882             diff = nk_vec2_muls(diff, len);
   9883             normals[i1].x = diff.y;
   9884             normals[i1].y = -diff.x;
   9885         }
   9886 
   9887         if (!closed)
   9888             normals[points_count-1] = normals[points_count-2];
   9889 
   9890         if (!thick_line) {
   9891             nk_size idx1, i;
   9892             if (!closed) {
   9893                 struct nk_vec2 d;
   9894                 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
   9895                 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
   9896                 d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
   9897                 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
   9898                 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
   9899             }
   9900 
   9901             /* fill elements */
   9902             idx1 = index;
   9903             for (i1 = 0; i1 < count; i1++) {
   9904                 struct nk_vec2 dm;
   9905                 float dmr2;
   9906                 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
   9907                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
   9908 
   9909                 /* average normals */
   9910                 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
   9911                 dmr2 = dm.x * dm.x + dm.y* dm.y;
   9912                 if (dmr2 > 0.000001f) {
   9913                     float scale = 1.0f/dmr2;
   9914                     scale = NK_MIN(100.0f, scale);
   9915                     dm = nk_vec2_muls(dm, scale);
   9916                 }
   9917 
   9918                 dm = nk_vec2_muls(dm, AA_SIZE);
   9919                 temp[i2*2+0] = nk_vec2_add(points[i2], dm);
   9920                 temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
   9921 
   9922                 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
   9923                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
   9924                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
   9925                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
   9926                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
   9927                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
   9928                 ids += 12;
   9929                 idx1 = idx2;
   9930             }
   9931 
   9932             /* fill vertices */
   9933             for (i = 0; i < points_count; ++i) {
   9934                 const struct nk_vec2 uv = list->config.tex_null.uv;
   9935                 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
   9936                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
   9937                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
   9938             }
   9939         } else {
   9940             nk_size idx1, i;
   9941             const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
   9942             if (!closed) {
   9943                 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
   9944                 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
   9945 
   9946                 temp[0] = nk_vec2_add(points[0], d1);
   9947                 temp[1] = nk_vec2_add(points[0], d2);
   9948                 temp[2] = nk_vec2_sub(points[0], d2);
   9949                 temp[3] = nk_vec2_sub(points[0], d1);
   9950 
   9951                 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
   9952                 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
   9953 
   9954                 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
   9955                 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
   9956                 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
   9957                 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
   9958             }
   9959 
   9960             /* add all elements */
   9961             idx1 = index;
   9962             for (i1 = 0; i1 < count; ++i1) {
   9963                 struct nk_vec2 dm_out, dm_in;
   9964                 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
   9965                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
   9966 
   9967                 /* average normals */
   9968                 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
   9969                 float dmr2 = dm.x * dm.x + dm.y* dm.y;
   9970                 if (dmr2 > 0.000001f) {
   9971                     float scale = 1.0f/dmr2;
   9972                     scale = NK_MIN(100.0f, scale);
   9973                     dm = nk_vec2_muls(dm, scale);
   9974                 }
   9975 
   9976                 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
   9977                 dm_in = nk_vec2_muls(dm, half_inner_thickness);
   9978                 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
   9979                 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
   9980                 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
   9981                 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
   9982 
   9983                 /* add indexes */
   9984                 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
   9985                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
   9986                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
   9987                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
   9988                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
   9989                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
   9990                 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
   9991                 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
   9992                 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
   9993                 ids += 18;
   9994                 idx1 = idx2;
   9995             }
   9996 
   9997             /* add vertices */
   9998             for (i = 0; i < points_count; ++i) {
   9999                 const struct nk_vec2 uv = list->config.tex_null.uv;
  10000                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
  10001                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
  10002                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
  10003                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
  10004             }
  10005         }
  10006         /* free temporary normals + points */
  10007         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
  10008     } else {
  10009         /* NON ANTI-ALIASED STROKE */
  10010         nk_size i1 = 0;
  10011         nk_size idx = list->vertex_count;
  10012         const nk_size idx_count = count * 6;
  10013         const nk_size vtx_count = count * 4;
  10014         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
  10015         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
  10016         if (!vtx || !ids) return;
  10017 
  10018         for (i1 = 0; i1 < count; ++i1) {
  10019             float dx, dy;
  10020             const struct nk_vec2 uv = list->config.tex_null.uv;
  10021             const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
  10022             const struct nk_vec2 p1 = points[i1];
  10023             const struct nk_vec2 p2 = points[i2];
  10024             struct nk_vec2 diff = nk_vec2_sub(p2, p1);
  10025             float len;
  10026 
  10027             /* vec2 inverted length  */
  10028             len = nk_vec2_len_sqr(diff);
  10029             if (len != 0.0f)
  10030                 len = NK_INV_SQRT(len);
  10031             else len = 1.0f;
  10032             diff = nk_vec2_muls(diff, len);
  10033 
  10034             /* add vertices */
  10035             dx = diff.x * (thickness * 0.5f);
  10036             dy = diff.y * (thickness * 0.5f);
  10037 
  10038             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
  10039             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
  10040             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
  10041             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
  10042 
  10043             ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
  10044             ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
  10045             ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
  10046 
  10047             ids += 6;
  10048             idx += 4;
  10049         }
  10050     }
  10051 }
  10052 NK_API void
  10053 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
  10054     const struct nk_vec2 *points, const unsigned int points_count,
  10055     struct nk_color color, enum nk_anti_aliasing aliasing)
  10056 {
  10057     struct nk_colorf col;
  10058     struct nk_colorf col_trans;
  10059 
  10060     NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
  10061     NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
  10062     NK_ASSERT(list);
  10063     if (!list || points_count < 3) return;
  10064 
  10065 #ifdef NK_INCLUDE_COMMAND_USERDATA
  10066     nk_draw_list_push_userdata(list, list->userdata);
  10067 #endif
  10068 
  10069     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
  10070     nk_color_fv(&col.r, color);
  10071     col_trans = col;
  10072     col_trans.a = 0;
  10073 
  10074     if (aliasing == NK_ANTI_ALIASING_ON) {
  10075         nk_size i = 0;
  10076         nk_size i0 = 0;
  10077         nk_size i1 = 0;
  10078 
  10079         const float AA_SIZE = 1.0f;
  10080         nk_size vertex_offset = 0;
  10081         nk_size index = list->vertex_count;
  10082 
  10083         const nk_size idx_count = (points_count-2)*3 + points_count*6;
  10084         const nk_size vtx_count = (points_count*2);
  10085 
  10086         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
  10087         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
  10088 
  10089         nk_size size = 0;
  10090         struct nk_vec2 *normals = 0;
  10091         unsigned int vtx_inner_idx = (unsigned int)(index + 0);
  10092         unsigned int vtx_outer_idx = (unsigned int)(index + 1);
  10093         if (!vtx || !ids) return;
  10094 
  10095         /* temporary allocate normals */
  10096         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
  10097         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
  10098         size = pnt_size * points_count;
  10099         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
  10100         if (!normals) return;
  10101         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
  10102 
  10103         /* add elements */
  10104         for (i = 2; i < points_count; i++) {
  10105             ids[0] = (nk_draw_index)(vtx_inner_idx);
  10106             ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
  10107             ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
  10108             ids += 3;
  10109         }
  10110 
  10111         /* compute normals */
  10112         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
  10113             struct nk_vec2 p0 = points[i0];
  10114             struct nk_vec2 p1 = points[i1];
  10115             struct nk_vec2 diff = nk_vec2_sub(p1, p0);
  10116 
  10117             /* vec2 inverted length  */
  10118             float len = nk_vec2_len_sqr(diff);
  10119             if (len != 0.0f)
  10120                 len = NK_INV_SQRT(len);
  10121             else len = 1.0f;
  10122             diff = nk_vec2_muls(diff, len);
  10123 
  10124             normals[i0].x = diff.y;
  10125             normals[i0].y = -diff.x;
  10126         }
  10127 
  10128         /* add vertices + indexes */
  10129         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
  10130             const struct nk_vec2 uv = list->config.tex_null.uv;
  10131             struct nk_vec2 n0 = normals[i0];
  10132             struct nk_vec2 n1 = normals[i1];
  10133             struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
  10134             float dmr2 = dm.x*dm.x + dm.y*dm.y;
  10135             if (dmr2 > 0.000001f) {
  10136                 float scale = 1.0f / dmr2;
  10137                 scale = NK_MIN(scale, 100.0f);
  10138                 dm = nk_vec2_muls(dm, scale);
  10139             }
  10140             dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
  10141 
  10142             /* add vertices */
  10143             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
  10144             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
  10145 
  10146             /* add indexes */
  10147             ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
  10148             ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
  10149             ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
  10150             ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
  10151             ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
  10152             ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
  10153             ids += 6;
  10154         }
  10155         /* free temporary normals + points */
  10156         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
  10157     } else {
  10158         nk_size i = 0;
  10159         nk_size index = list->vertex_count;
  10160         const nk_size idx_count = (points_count-2)*3;
  10161         const nk_size vtx_count = points_count;
  10162         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
  10163         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
  10164 
  10165         if (!vtx || !ids) return;
  10166         for (i = 0; i < vtx_count; ++i)
  10167             vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.tex_null.uv, col);
  10168         for (i = 2; i < points_count; ++i) {
  10169             ids[0] = (nk_draw_index)index;
  10170             ids[1] = (nk_draw_index)(index+ i - 1);
  10171             ids[2] = (nk_draw_index)(index+i);
  10172             ids += 3;
  10173         }
  10174     }
  10175 }
  10176 NK_API void
  10177 nk_draw_list_path_clear(struct nk_draw_list *list)
  10178 {
  10179     NK_ASSERT(list);
  10180     if (!list) return;
  10181     nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
  10182     list->path_count = 0;
  10183     list->path_offset = 0;
  10184 }
  10185 NK_API void
  10186 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
  10187 {
  10188     struct nk_vec2 *points = 0;
  10189     struct nk_draw_command *cmd = 0;
  10190     NK_ASSERT(list);
  10191     if (!list) return;
  10192     if (!list->cmd_count)
  10193         nk_draw_list_add_clip(list, nk_null_rect);
  10194 
  10195     cmd = nk_draw_list_command_last(list);
  10196     if (cmd && cmd->texture.ptr != list->config.tex_null.texture.ptr)
  10197         nk_draw_list_push_image(list, list->config.tex_null.texture);
  10198 
  10199     points = nk_draw_list_alloc_path(list, 1);
  10200     if (!points) return;
  10201     points[0] = pos;
  10202 }
  10203 NK_API void
  10204 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
  10205     float radius, int a_min, int a_max)
  10206 {
  10207     int a = 0;
  10208     NK_ASSERT(list);
  10209     if (!list) return;
  10210     if (a_min <= a_max) {
  10211         for (a = a_min; a <= a_max; a++) {
  10212             const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
  10213             const float x = center.x + c.x * radius;
  10214             const float y = center.y + c.y * radius;
  10215             nk_draw_list_path_line_to(list, nk_vec2(x, y));
  10216         }
  10217     }
  10218 }
  10219 NK_API void
  10220 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
  10221     float radius, float a_min, float a_max, unsigned int segments)
  10222 {
  10223     unsigned int i = 0;
  10224     NK_ASSERT(list);
  10225     if (!list) return;
  10226     if (radius == 0.0f) return;
  10227 
  10228     /*  This algorithm for arc drawing relies on these two trigonometric identities[1]:
  10229             sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
  10230             cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
  10231 
  10232         Two coordinates (x, y) of a point on a circle centered on
  10233         the origin can be written in polar form as:
  10234             x = r * cos(a)
  10235             y = r * sin(a)
  10236         where r is the radius of the circle,
  10237             a is the angle between (x, y) and the origin.
  10238 
  10239         This allows us to rotate the coordinates around the
  10240         origin by an angle b using the following transformation:
  10241             x' = r * cos(a + b) = x * cos(b) - y * sin(b)
  10242             y' = r * sin(a + b) = y * cos(b) + x * sin(b)
  10243 
  10244         [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
  10245     */
  10246     {const float d_angle = (a_max - a_min) / (float)segments;
  10247     const float sin_d = (float)NK_SIN(d_angle);
  10248     const float cos_d = (float)NK_COS(d_angle);
  10249 
  10250     float cx = (float)NK_COS(a_min) * radius;
  10251     float cy = (float)NK_SIN(a_min) * radius;
  10252     for(i = 0; i <= segments; ++i) {
  10253         float new_cx, new_cy;
  10254         const float x = center.x + cx;
  10255         const float y = center.y + cy;
  10256         nk_draw_list_path_line_to(list, nk_vec2(x, y));
  10257 
  10258         new_cx = cx * cos_d - cy * sin_d;
  10259         new_cy = cy * cos_d + cx * sin_d;
  10260         cx = new_cx;
  10261         cy = new_cy;
  10262     }}
  10263 }
  10264 NK_API void
  10265 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
  10266     struct nk_vec2 b, float rounding)
  10267 {
  10268     float r;
  10269     NK_ASSERT(list);
  10270     if (!list) return;
  10271     r = rounding;
  10272     r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
  10273     r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
  10274 
  10275     if (r == 0.0f) {
  10276         nk_draw_list_path_line_to(list, a);
  10277         nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
  10278         nk_draw_list_path_line_to(list, b);
  10279         nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
  10280     } else {
  10281         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
  10282         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
  10283         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
  10284         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
  10285     }
  10286 }
  10287 NK_API void
  10288 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
  10289     struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
  10290 {
  10291     float t_step;
  10292     unsigned int i_step;
  10293     struct nk_vec2 p1;
  10294 
  10295     NK_ASSERT(list);
  10296     NK_ASSERT(list->path_count);
  10297     if (!list || !list->path_count) return;
  10298     num_segments = NK_MAX(num_segments, 1);
  10299 
  10300     p1 = nk_draw_list_path_last(list);
  10301     t_step = 1.0f/(float)num_segments;
  10302     for (i_step = 1; i_step <= num_segments; ++i_step) {
  10303         float t = t_step * (float)i_step;
  10304         float u = 1.0f - t;
  10305         float w1 = u*u*u;
  10306         float w2 = 3*u*u*t;
  10307         float w3 = 3*u*t*t;
  10308         float w4 = t * t *t;
  10309         float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
  10310         float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
  10311         nk_draw_list_path_line_to(list, nk_vec2(x,y));
  10312     }
  10313 }
  10314 NK_API void
  10315 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
  10316 {
  10317     struct nk_vec2 *points;
  10318     NK_ASSERT(list);
  10319     if (!list) return;
  10320     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
  10321     nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
  10322     nk_draw_list_path_clear(list);
  10323 }
  10324 NK_API void
  10325 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
  10326     enum nk_draw_list_stroke closed, float thickness)
  10327 {
  10328     struct nk_vec2 *points;
  10329     NK_ASSERT(list);
  10330     if (!list) return;
  10331     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
  10332     nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
  10333         closed, thickness, list->config.line_AA);
  10334     nk_draw_list_path_clear(list);
  10335 }
  10336 NK_API void
  10337 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
  10338     struct nk_vec2 b, struct nk_color col, float thickness)
  10339 {
  10340     NK_ASSERT(list);
  10341     if (!list || !col.a) return;
  10342     if (list->line_AA == NK_ANTI_ALIASING_ON) {
  10343         nk_draw_list_path_line_to(list, a);
  10344         nk_draw_list_path_line_to(list, b);
  10345     } else {
  10346         nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
  10347         nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
  10348     }
  10349     nk_draw_list_path_stroke(list,  col, NK_STROKE_OPEN, thickness);
  10350 }
  10351 NK_API void
  10352 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
  10353     struct nk_color col, float rounding)
  10354 {
  10355     NK_ASSERT(list);
  10356     if (!list || !col.a) return;
  10357 
  10358     if (list->line_AA == NK_ANTI_ALIASING_ON) {
  10359         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
  10360             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
  10361     } else {
  10362         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
  10363             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
  10364     } nk_draw_list_path_fill(list,  col);
  10365 }
  10366 NK_API void
  10367 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
  10368     struct nk_color col, float rounding, float thickness)
  10369 {
  10370     NK_ASSERT(list);
  10371     if (!list || !col.a) return;
  10372     if (list->line_AA == NK_ANTI_ALIASING_ON) {
  10373         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
  10374             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
  10375     } else {
  10376         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
  10377             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
  10378     } nk_draw_list_path_stroke(list,  col, NK_STROKE_CLOSED, thickness);
  10379 }
  10380 NK_API void
  10381 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
  10382     struct nk_color left, struct nk_color top, struct nk_color right,
  10383     struct nk_color bottom)
  10384 {
  10385     void *vtx;
  10386     struct nk_colorf col_left, col_top;
  10387     struct nk_colorf col_right, col_bottom;
  10388     nk_draw_index *idx;
  10389     nk_draw_index index;
  10390 
  10391     nk_color_fv(&col_left.r, left);
  10392     nk_color_fv(&col_right.r, right);
  10393     nk_color_fv(&col_top.r, top);
  10394     nk_color_fv(&col_bottom.r, bottom);
  10395 
  10396     NK_ASSERT(list);
  10397     if (!list) return;
  10398 
  10399     nk_draw_list_push_image(list, list->config.tex_null.texture);
  10400     index = (nk_draw_index)list->vertex_count;
  10401     vtx = nk_draw_list_alloc_vertices(list, 4);
  10402     idx = nk_draw_list_alloc_elements(list, 6);
  10403     if (!vtx || !idx) return;
  10404 
  10405     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
  10406     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
  10407     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
  10408 
  10409     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.tex_null.uv, col_left);
  10410     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.tex_null.uv, col_top);
  10411     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.tex_null.uv, col_right);
  10412     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.tex_null.uv, col_bottom);
  10413 }
  10414 NK_API void
  10415 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
  10416     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
  10417 {
  10418     NK_ASSERT(list);
  10419     if (!list || !col.a) return;
  10420     nk_draw_list_path_line_to(list, a);
  10421     nk_draw_list_path_line_to(list, b);
  10422     nk_draw_list_path_line_to(list, c);
  10423     nk_draw_list_path_fill(list, col);
  10424 }
  10425 NK_API void
  10426 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
  10427     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
  10428 {
  10429     NK_ASSERT(list);
  10430     if (!list || !col.a) return;
  10431     nk_draw_list_path_line_to(list, a);
  10432     nk_draw_list_path_line_to(list, b);
  10433     nk_draw_list_path_line_to(list, c);
  10434     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
  10435 }
  10436 NK_API void
  10437 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
  10438     float radius, struct nk_color col, unsigned int segs)
  10439 {
  10440     float a_max;
  10441     NK_ASSERT(list);
  10442     if (!list || !col.a) return;
  10443     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
  10444     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
  10445     nk_draw_list_path_fill(list, col);
  10446 }
  10447 NK_API void
  10448 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
  10449     float radius, struct nk_color col, unsigned int segs, float thickness)
  10450 {
  10451     float a_max;
  10452     NK_ASSERT(list);
  10453     if (!list || !col.a) return;
  10454     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
  10455     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
  10456     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
  10457 }
  10458 NK_API void
  10459 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
  10460     struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
  10461     struct nk_color col, unsigned int segments, float thickness)
  10462 {
  10463     NK_ASSERT(list);
  10464     if (!list || !col.a) return;
  10465     nk_draw_list_path_line_to(list, p0);
  10466     nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
  10467     nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
  10468 }
  10469 NK_INTERN void
  10470 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
  10471     struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
  10472     struct nk_color color)
  10473 {
  10474     void *vtx;
  10475     struct nk_vec2 uvb;
  10476     struct nk_vec2 uvd;
  10477     struct nk_vec2 b;
  10478     struct nk_vec2 d;
  10479 
  10480     struct nk_colorf col;
  10481     nk_draw_index *idx;
  10482     nk_draw_index index;
  10483     NK_ASSERT(list);
  10484     if (!list) return;
  10485 
  10486     nk_color_fv(&col.r, color);
  10487     uvb = nk_vec2(uvc.x, uva.y);
  10488     uvd = nk_vec2(uva.x, uvc.y);
  10489     b = nk_vec2(c.x, a.y);
  10490     d = nk_vec2(a.x, c.y);
  10491 
  10492     index = (nk_draw_index)list->vertex_count;
  10493     vtx = nk_draw_list_alloc_vertices(list, 4);
  10494     idx = nk_draw_list_alloc_elements(list, 6);
  10495     if (!vtx || !idx) return;
  10496 
  10497     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
  10498     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
  10499     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
  10500 
  10501     vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
  10502     vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
  10503     vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
  10504     vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
  10505 }
  10506 NK_API void
  10507 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
  10508     struct nk_rect rect, struct nk_color color)
  10509 {
  10510     NK_ASSERT(list);
  10511     if (!list) return;
  10512     /* push new command with given texture */
  10513     nk_draw_list_push_image(list, texture.handle);
  10514     if (nk_image_is_subimage(&texture)) {
  10515         /* add region inside of the texture  */
  10516         struct nk_vec2 uv[2];
  10517         uv[0].x = (float)texture.region[0]/(float)texture.w;
  10518         uv[0].y = (float)texture.region[1]/(float)texture.h;
  10519         uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
  10520         uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
  10521         nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
  10522             nk_vec2(rect.x + rect.w, rect.y + rect.h),  uv[0], uv[1], color);
  10523     } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
  10524             nk_vec2(rect.x + rect.w, rect.y + rect.h),
  10525             nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
  10526 }
  10527 NK_API void
  10528 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
  10529     struct nk_rect rect, const char *text, int len, float font_height,
  10530     struct nk_color fg)
  10531 {
  10532     float x = 0;
  10533     int text_len = 0;
  10534     nk_rune unicode = 0;
  10535     nk_rune next = 0;
  10536     int glyph_len = 0;
  10537     int next_glyph_len = 0;
  10538     struct nk_user_font_glyph g;
  10539 
  10540     NK_ASSERT(list);
  10541     if (!list || !len || !text) return;
  10542     if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
  10543         list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
  10544 
  10545     nk_draw_list_push_image(list, font->texture);
  10546     x = rect.x;
  10547     glyph_len = nk_utf_decode(text, &unicode, len);
  10548     if (!glyph_len) return;
  10549 
  10550     /* draw every glyph image */
  10551     fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
  10552     while (text_len < len && glyph_len) {
  10553         float gx, gy, gh, gw;
  10554         float char_width = 0;
  10555         if (unicode == NK_UTF_INVALID) break;
  10556 
  10557         /* query currently drawn glyph information */
  10558         next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
  10559         font->query(font->userdata, font_height, &g, unicode,
  10560                     (next == NK_UTF_INVALID) ? '\0' : next);
  10561 
  10562         /* calculate and draw glyph drawing rectangle and image */
  10563         gx = x + g.offset.x;
  10564         gy = rect.y + g.offset.y;
  10565         gw = g.width; gh = g.height;
  10566         char_width = g.xadvance;
  10567         nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
  10568             g.uv[0], g.uv[1], fg);
  10569 
  10570         /* offset next glyph */
  10571         text_len += glyph_len;
  10572         x += char_width;
  10573         glyph_len = next_glyph_len;
  10574         unicode = next;
  10575     }
  10576 }
  10577 NK_API nk_flags
  10578 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
  10579     struct nk_buffer *vertices, struct nk_buffer *elements,
  10580     const struct nk_convert_config *config)
  10581 {
  10582     nk_flags res = NK_CONVERT_SUCCESS;
  10583     const struct nk_command *cmd;
  10584     NK_ASSERT(ctx);
  10585     NK_ASSERT(cmds);
  10586     NK_ASSERT(vertices);
  10587     NK_ASSERT(elements);
  10588     NK_ASSERT(config);
  10589     NK_ASSERT(config->vertex_layout);
  10590     NK_ASSERT(config->vertex_size);
  10591     if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
  10592         return NK_CONVERT_INVALID_PARAM;
  10593 
  10594     nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
  10595         config->line_AA, config->shape_AA);
  10596     nk_foreach(cmd, ctx)
  10597     {
  10598 #ifdef NK_INCLUDE_COMMAND_USERDATA
  10599         ctx->draw_list.userdata = cmd->userdata;
  10600 #endif
  10601         switch (cmd->type) {
  10602         case NK_COMMAND_NOP: break;
  10603         case NK_COMMAND_SCISSOR: {
  10604             const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
  10605             nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
  10606         } break;
  10607         case NK_COMMAND_LINE: {
  10608             const struct nk_command_line *l = (const struct nk_command_line*)cmd;
  10609             nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
  10610                 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
  10611         } break;
  10612         case NK_COMMAND_CURVE: {
  10613             const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
  10614             nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
  10615                 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
  10616                 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
  10617                 config->curve_segment_count, q->line_thickness);
  10618         } break;
  10619         case NK_COMMAND_RECT: {
  10620             const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
  10621             nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
  10622                 r->color, (float)r->rounding, r->line_thickness);
  10623         } break;
  10624         case NK_COMMAND_RECT_FILLED: {
  10625             const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
  10626             nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
  10627                 r->color, (float)r->rounding);
  10628         } break;
  10629         case NK_COMMAND_RECT_MULTI_COLOR: {
  10630             const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
  10631             nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
  10632                 r->left, r->top, r->right, r->bottom);
  10633         } break;
  10634         case NK_COMMAND_CIRCLE: {
  10635             const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
  10636             nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
  10637                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
  10638                 config->circle_segment_count, c->line_thickness);
  10639         } break;
  10640         case NK_COMMAND_CIRCLE_FILLED: {
  10641             const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
  10642             nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
  10643                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
  10644                 config->circle_segment_count);
  10645         } break;
  10646         case NK_COMMAND_ARC: {
  10647             const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
  10648             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
  10649             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
  10650                 c->a[0], c->a[1], config->arc_segment_count);
  10651             nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
  10652         } break;
  10653         case NK_COMMAND_ARC_FILLED: {
  10654             const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
  10655             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
  10656             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
  10657                 c->a[0], c->a[1], config->arc_segment_count);
  10658             nk_draw_list_path_fill(&ctx->draw_list, c->color);
  10659         } break;
  10660         case NK_COMMAND_TRIANGLE: {
  10661             const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
  10662             nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
  10663                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
  10664                 t->line_thickness);
  10665         } break;
  10666         case NK_COMMAND_TRIANGLE_FILLED: {
  10667             const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
  10668             nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
  10669                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
  10670         } break;
  10671         case NK_COMMAND_POLYGON: {
  10672             int i;
  10673             const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
  10674             for (i = 0; i < p->point_count; ++i) {
  10675                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
  10676                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
  10677             }
  10678             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
  10679         } break;
  10680         case NK_COMMAND_POLYGON_FILLED: {
  10681             int i;
  10682             const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
  10683             for (i = 0; i < p->point_count; ++i) {
  10684                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
  10685                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
  10686             }
  10687             nk_draw_list_path_fill(&ctx->draw_list, p->color);
  10688         } break;
  10689         case NK_COMMAND_POLYLINE: {
  10690             int i;
  10691             const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
  10692             for (i = 0; i < p->point_count; ++i) {
  10693                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
  10694                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
  10695             }
  10696             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
  10697         } break;
  10698         case NK_COMMAND_TEXT: {
  10699             const struct nk_command_text *t = (const struct nk_command_text*)cmd;
  10700             nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
  10701                 t->string, t->length, t->height, t->foreground);
  10702         } break;
  10703         case NK_COMMAND_IMAGE: {
  10704             const struct nk_command_image *i = (const struct nk_command_image*)cmd;
  10705             nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
  10706         } break;
  10707         case NK_COMMAND_CUSTOM: {
  10708             const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
  10709             c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
  10710         } break;
  10711         default: break;
  10712         }
  10713     }
  10714     res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
  10715     res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
  10716     res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
  10717     return res;
  10718 }
  10719 NK_API const struct nk_draw_command*
  10720 nk__draw_begin(const struct nk_context *ctx,
  10721     const struct nk_buffer *buffer)
  10722 {
  10723     return nk__draw_list_begin(&ctx->draw_list, buffer);
  10724 }
  10725 NK_API const struct nk_draw_command*
  10726 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
  10727 {
  10728     return nk__draw_list_end(&ctx->draw_list, buffer);
  10729 }
  10730 NK_API const struct nk_draw_command*
  10731 nk__draw_next(const struct nk_draw_command *cmd,
  10732     const struct nk_buffer *buffer, const struct nk_context *ctx)
  10733 {
  10734     return nk__draw_list_next(cmd, buffer, &ctx->draw_list);
  10735 }
  10736 #endif
  10737 
  10738 
  10739 /*  stb_rect_pack.h - v1.01 - public domain - rectangle packing */
  10740 /*  Sean Barrett 2014 */
  10741 /*  */
  10742 /*  Useful for e.g. packing rectangular textures into an atlas. */
  10743 /*  Does not do rotation. */
  10744 /*  */
  10745 /*  Before #including, */
  10746 /*  */
  10747 /*     #define STB_RECT_PACK_IMPLEMENTATION */
  10748 /*  */
  10749 /*  in the file that you want to have the implementation. */
  10750 /*  */
  10751 /*  Not necessarily the awesomest packing method, but better than */
  10752 /*  the totally naive one in stb_truetype (which is primarily what */
  10753 /*  this is meant to replace). */
  10754 /*  */
  10755 /*  Has only had a few tests run, may have issues. */
  10756 /*  */
  10757 /*  More docs to come. */
  10758 /*  */
  10759 /*  No memory allocations; uses qsort() and assert() from stdlib. */
  10760 /*  Can override those by defining STBRP_SORT and STBRP_ASSERT. */
  10761 /*  */
  10762 /*  This library currently uses the Skyline Bottom-Left algorithm. */
  10763 /*  */
  10764 /*  Please note: better rectangle packers are welcome! Please */
  10765 /*  implement them to the same API, but with a different init */
  10766 /*  function. */
  10767 /*  */
  10768 /*  Credits */
  10769 /*  */
  10770 /*   Library */
  10771 /*     Sean Barrett */
  10772 /*   Minor features */
  10773 /*     Martins Mozeiko */
  10774 /*     github:IntellectualKitty */
  10775 /*  */
  10776 /*   Bugfixes / warning fixes */
  10777 /*     Jeremy Jaussaud */
  10778 /*     Fabian Giesen */
  10779 /*  */
  10780 /*  Version history: */
  10781 /*  */
  10782 /*      1.01  (2021-07-11)  always use large rect mode, expose STBRP__MAXVAL in public section */
  10783 /*      1.00  (2019-02-25)  avoid small space waste; gracefully fail too-wide rectangles */
  10784 /*      0.99  (2019-02-07)  warning fixes */
  10785 /*      0.11  (2017-03-03)  return packing success/fail result */
  10786 /*      0.10  (2016-10-25)  remove cast-away-const to avoid warnings */
  10787 /*      0.09  (2016-08-27)  fix compiler warnings */
  10788 /*      0.08  (2015-09-13)  really fix bug with empty rects (w=0 or h=0) */
  10789 /*      0.07  (2015-09-13)  fix bug with empty rects (w=0 or h=0) */
  10790 /*      0.06  (2015-04-15)  added STBRP_SORT to allow replacing qsort */
  10791 /*      0.05:  added STBRP_ASSERT to allow replacing assert */
  10792 /*      0.04:  fixed minor bug in STBRP_LARGE_RECTS support */
  10793 /*      0.01:  initial release */
  10794 /*  */
  10795 /*  LICENSE */
  10796 /*  */
  10797 /*    See end of file for license information. */
  10798 
  10799 /* //////////////////////////////////////////////////////////////////////////// */
  10800 /*  */
  10801 /*        INCLUDE SECTION */
  10802 /*  */
  10803 
  10804 #ifndef STB_INCLUDE_STB_RECT_PACK_H
  10805 #define STB_INCLUDE_STB_RECT_PACK_H
  10806 
  10807 #define STB_RECT_PACK_VERSION  1
  10808 
  10809 #ifdef STBRP_STATIC
  10810 #define STBRP_DEF static
  10811 #else
  10812 #define STBRP_DEF extern
  10813 #endif
  10814 
  10815 #ifdef __cplusplus
  10816 extern "C" {
  10817 #endif
  10818 
  10819 typedef struct stbrp_context stbrp_context;
  10820 typedef struct stbrp_node    stbrp_node;
  10821 typedef struct stbrp_rect    stbrp_rect;
  10822 
  10823 typedef int            stbrp_coord;
  10824 
  10825 #define STBRP__MAXVAL  0x7fffffff
  10826 /*  Mostly for internal use, but this is the maximum supported coordinate value. */
  10827 
  10828 STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
  10829 /*  Assign packed locations to rectangles. The rectangles are of type */
  10830 /*  'stbrp_rect' defined below, stored in the array 'rects', and there */
  10831 /*  are 'num_rects' many of them. */
  10832 /*  */
  10833 /*  Rectangles which are successfully packed have the 'was_packed' flag */
  10834 /*  set to a non-zero value and 'x' and 'y' store the minimum location */
  10835 /*  on each axis (i.e. bottom-left in cartesian coordinates, top-left */
  10836 /*  if you imagine y increasing downwards). Rectangles which do not fit */
  10837 /*  have the 'was_packed' flag set to 0. */
  10838 /*  */
  10839 /*  You should not try to access the 'rects' array from another thread */
  10840 /*  while this function is running, as the function temporarily reorders */
  10841 /*  the array while it executes. */
  10842 /*  */
  10843 /*  To pack into another rectangle, you need to call stbrp_init_target */
  10844 /*  again. To continue packing into the same rectangle, you can call */
  10845 /*  this function again. Calling this multiple times with multiple rect */
  10846 /*  arrays will probably produce worse packing results than calling it */
  10847 /*  a single time with the full rectangle array, but the option is */
  10848 /*  available. */
  10849 /*  */
  10850 /*  The function returns 1 if all of the rectangles were successfully */
  10851 /*  packed and 0 otherwise. */
  10852 
  10853 struct stbrp_rect
  10854 {
  10855    /*  reserved for your use: */
  10856    int            id;
  10857 
  10858    /*  input: */
  10859    stbrp_coord    w, h;
  10860 
  10861    /*  output: */
  10862    stbrp_coord    x, y;
  10863    int            was_packed;  /*  non-zero if valid packing */
  10864 
  10865 }; /*  16 bytes, nominally */
  10866 
  10867 
  10868 STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
  10869 /*  Initialize a rectangle packer to: */
  10870 /*     pack a rectangle that is 'width' by 'height' in dimensions */
  10871 /*     using temporary storage provided by the array 'nodes', which is 'num_nodes' long */
  10872 /*  */
  10873 /*  You must call this function every time you start packing into a new target. */
  10874 /*  */
  10875 /*  There is no "shutdown" function. The 'nodes' memory must stay valid for */
  10876 /*  the following stbrp_pack_rects() call (or calls), but can be freed after */
  10877 /*  the call (or calls) finish. */
  10878 /*  */
  10879 /*  Note: to guarantee best results, either: */
  10880 /*        1. make sure 'num_nodes' >= 'width' */
  10881 /*    or  2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' */
  10882 /*  */
  10883 /*  If you don't do either of the above things, widths will be quantized to multiples */
  10884 /*  of small integers to guarantee the algorithm doesn't run out of temporary storage. */
  10885 /*  */
  10886 /*  If you do #2, then the non-quantized algorithm will be used, but the algorithm */
  10887 /*  may run out of temporary storage and be unable to pack some rectangles. */
  10888 
  10889 STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
  10890 /*  Optionally call this function after init but before doing any packing to */
  10891 /*  change the handling of the out-of-temp-memory scenario, described above. */
  10892 /*  If you call init again, this will be reset to the default (false). */
  10893 
  10894 
  10895 STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
  10896 /*  Optionally select which packing heuristic the library should use. Different */
  10897 /*  heuristics will produce better/worse results for different data sets. */
  10898 /*  If you call init again, this will be reset to the default. */
  10899 
  10900 enum
  10901 {
  10902    STBRP_HEURISTIC_Skyline_default=0,
  10903    STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
  10904    STBRP_HEURISTIC_Skyline_BF_sortHeight
  10905 };
  10906 
  10907 
  10908 /* //////////////////////////////////////////////////////////////////////////// */
  10909 /*  */
  10910 /*  the details of the following structures don't matter to you, but they must */
  10911 /*  be visible so you can handle the memory allocations for them */
  10912 
  10913 struct stbrp_node
  10914 {
  10915    stbrp_coord  x,y;
  10916    stbrp_node  *next;
  10917 };
  10918 
  10919 struct stbrp_context
  10920 {
  10921    int width;
  10922    int height;
  10923    int align;
  10924    int init_mode;
  10925    int heuristic;
  10926    int num_nodes;
  10927    stbrp_node *active_head;
  10928    stbrp_node *free_head;
  10929    stbrp_node extra[2]; /*  we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
  10930 };
  10931 
  10932 #ifdef __cplusplus
  10933 }
  10934 #endif
  10935 
  10936 #endif
  10937 
  10938 /* //////////////////////////////////////////////////////////////////////////// */
  10939 /*  */
  10940 /*      IMPLEMENTATION SECTION */
  10941 /*  */
  10942 
  10943 #ifdef STB_RECT_PACK_IMPLEMENTATION
  10944 #ifndef STBRP_SORT
  10945 #include <stdlib.h>
  10946 #define STBRP_SORT qsort
  10947 #endif
  10948 
  10949 #ifndef STBRP_ASSERT
  10950 #include <assert.h>
  10951 #define STBRP_ASSERT assert
  10952 #endif
  10953 
  10954 #ifdef _MSC_VER
  10955 #define STBRP__NOTUSED(v)  (void)(v)
  10956 #define STBRP__CDECL       __cdecl
  10957 #else
  10958 #define STBRP__NOTUSED(v)  (void)sizeof(v)
  10959 #define STBRP__CDECL
  10960 #endif
  10961 
  10962 enum
  10963 {
  10964    STBRP__INIT_skyline = 1
  10965 };
  10966 
  10967 STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
  10968 {
  10969    switch (context->init_mode) {
  10970       case STBRP__INIT_skyline:
  10971          STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
  10972          context->heuristic = heuristic;
  10973          break;
  10974       default:
  10975          STBRP_ASSERT(0);
  10976    }
  10977 }
  10978 
  10979 STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
  10980 {
  10981    if (allow_out_of_mem)
  10982       /*  if it's ok to run out of memory, then don't bother aligning them; */
  10983       /*  this gives better packing, but may fail due to OOM (even though */
  10984       /*  the rectangles easily fit). @TODO a smarter approach would be to only */
  10985       /*  quantize once we've hit OOM, then we could get rid of this parameter. */
  10986       context->align = 1;
  10987    else {
  10988       /*  if it's not ok to run out of memory, then quantize the widths */
  10989       /*  so that num_nodes is always enough nodes. */
  10990       /*  */
  10991       /*  I.e. num_nodes * align >= width */
  10992       /*                   align >= width / num_nodes */
  10993       /*                   align = ceil(width/num_nodes) */
  10994 
  10995       context->align = (context->width + context->num_nodes-1) / context->num_nodes;
  10996    }
  10997 }
  10998 
  10999 STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
  11000 {
  11001    int i;
  11002 
  11003    for (i=0; i < num_nodes-1; ++i)
  11004       nodes[i].next = &nodes[i+1];
  11005    nodes[i].next = NULL;
  11006    context->init_mode = STBRP__INIT_skyline;
  11007    context->heuristic = STBRP_HEURISTIC_Skyline_default;
  11008    context->free_head = &nodes[0];
  11009    context->active_head = &context->extra[0];
  11010    context->width = width;
  11011    context->height = height;
  11012    context->num_nodes = num_nodes;
  11013    stbrp_setup_allow_out_of_mem(context, 0);
  11014 
  11015    /*  node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
  11016    context->extra[0].x = 0;
  11017    context->extra[0].y = 0;
  11018    context->extra[0].next = &context->extra[1];
  11019    context->extra[1].x = (stbrp_coord) width;
  11020    context->extra[1].y = (1<<30);
  11021    context->extra[1].next = NULL;
  11022 }
  11023 
  11024 /*  find minimum y position if it starts at x1 */
  11025 static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
  11026 {
  11027    stbrp_node *node = first;
  11028    int x1 = x0 + width;
  11029    int min_y, visited_width, waste_area;
  11030 
  11031    STBRP__NOTUSED(c);
  11032 
  11033    STBRP_ASSERT(first->x <= x0);
  11034 
  11035    #if 0
  11036    /*  skip in case we're past the node */
  11037    while (node->next->x <= x0)
  11038       ++node;
  11039    #else
  11040    STBRP_ASSERT(node->next->x > x0); /*  we ended up handling this in the caller for efficiency */
  11041    #endif
  11042 
  11043    STBRP_ASSERT(node->x <= x0);
  11044 
  11045    min_y = 0;
  11046    waste_area = 0;
  11047    visited_width = 0;
  11048    while (node->x < x1) {
  11049       if (node->y > min_y) {
  11050          /*  raise min_y higher. */
  11051          /*  we've accounted for all waste up to min_y, */
  11052          /*  but we'll now add more waste for everything we've visted */
  11053          waste_area += visited_width * (node->y - min_y);
  11054          min_y = node->y;
  11055          /*  the first time through, visited_width might be reduced */
  11056          if (node->x < x0)
  11057             visited_width += node->next->x - x0;
  11058          else
  11059             visited_width += node->next->x - node->x;
  11060       } else {
  11061          /*  add waste area */
  11062          int under_width = node->next->x - node->x;
  11063          if (under_width + visited_width > width)
  11064             under_width = width - visited_width;
  11065          waste_area += under_width * (min_y - node->y);
  11066          visited_width += under_width;
  11067       }
  11068       node = node->next;
  11069    }
  11070 
  11071    *pwaste = waste_area;
  11072    return min_y;
  11073 }
  11074 
  11075 typedef struct
  11076 {
  11077    int x,y;
  11078    stbrp_node **prev_link;
  11079 } stbrp__findresult;
  11080 
  11081 static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
  11082 {
  11083    int best_waste = (1<<30), best_x, best_y = (1 << 30);
  11084    stbrp__findresult fr;
  11085    stbrp_node **prev, *node, *tail, **best = NULL;
  11086 
  11087    /*  align to multiple of c->align */
  11088    width = (width + c->align - 1);
  11089    width -= width % c->align;
  11090    STBRP_ASSERT(width % c->align == 0);
  11091 
  11092    /*  if it can't possibly fit, bail immediately */
  11093    if (width > c->width || height > c->height) {
  11094       fr.prev_link = NULL;
  11095       fr.x = fr.y = 0;
  11096       return fr;
  11097    }
  11098 
  11099    node = c->active_head;
  11100    prev = &c->active_head;
  11101    while (node->x + width <= c->width) {
  11102       int y,waste;
  11103       y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
  11104       if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { /*  actually just want to test BL */
  11105          /*  bottom left */
  11106          if (y < best_y) {
  11107             best_y = y;
  11108             best = prev;
  11109          }
  11110       } else {
  11111          /*  best-fit */
  11112          if (y + height <= c->height) {
  11113             /*  can only use it if it first vertically */
  11114             if (y < best_y || (y == best_y && waste < best_waste)) {
  11115                best_y = y;
  11116                best_waste = waste;
  11117                best = prev;
  11118             }
  11119          }
  11120       }
  11121       prev = &node->next;
  11122       node = node->next;
  11123    }
  11124 
  11125    best_x = (best == NULL) ? 0 : (*best)->x;
  11126 
  11127    /*  if doing best-fit (BF), we also have to try aligning right edge to each node position */
  11128    /*  */
  11129    /*  e.g, if fitting */
  11130    /*  */
  11131    /*      ____________________ */
  11132    /*     |____________________| */
  11133    /*  */
  11134    /*             into */
  11135    /*  */
  11136    /*    |                         | */
  11137    /*    |             ____________| */
  11138    /*    |____________| */
  11139    /*  */
  11140    /*  then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
  11141    /*  */
  11142    /*  This makes BF take about 2x the time */
  11143 
  11144    if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
  11145       tail = c->active_head;
  11146       node = c->active_head;
  11147       prev = &c->active_head;
  11148       /*  find first node that's admissible */
  11149       while (tail->x < width)
  11150          tail = tail->next;
  11151       while (tail) {
  11152          int xpos = tail->x - width;
  11153          int y,waste;
  11154          STBRP_ASSERT(xpos >= 0);
  11155          /*  find the left position that matches this */
  11156          while (node->next->x <= xpos) {
  11157             prev = &node->next;
  11158             node = node->next;
  11159          }
  11160          STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
  11161          y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
  11162          if (y + height <= c->height) {
  11163             if (y <= best_y) {
  11164                if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
  11165                   best_x = xpos;
  11166                   STBRP_ASSERT(y <= best_y);
  11167                   best_y = y;
  11168                   best_waste = waste;
  11169                   best = prev;
  11170                }
  11171             }
  11172          }
  11173          tail = tail->next;
  11174       }
  11175    }
  11176 
  11177    fr.prev_link = best;
  11178    fr.x = best_x;
  11179    fr.y = best_y;
  11180    return fr;
  11181 }
  11182 
  11183 static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
  11184 {
  11185    /*  find best position according to heuristic */
  11186    stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
  11187    stbrp_node *node, *cur;
  11188 
  11189    /*  bail if: */
  11190    /*     1. it failed */
  11191    /*     2. the best node doesn't fit (we don't always check this) */
  11192    /*     3. we're out of memory */
  11193    if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
  11194       res.prev_link = NULL;
  11195       return res;
  11196    }
  11197 
  11198    /*  on success, create new node */
  11199    node = context->free_head;
  11200    node->x = (stbrp_coord) res.x;
  11201    node->y = (stbrp_coord) (res.y + height);
  11202 
  11203    context->free_head = node->next;
  11204 
  11205    /*  insert the new node into the right starting point, and */
  11206    /*  let 'cur' point to the remaining nodes needing to be */
  11207    /*  stiched back in */
  11208 
  11209    cur = *res.prev_link;
  11210    if (cur->x < res.x) {
  11211       /*  preserve the existing one, so start testing with the next one */
  11212       stbrp_node *next = cur->next;
  11213       cur->next = node;
  11214       cur = next;
  11215    } else {
  11216       *res.prev_link = node;
  11217    }
  11218 
  11219    /*  from here, traverse cur and free the nodes, until we get to one */
  11220    /*  that shouldn't be freed */
  11221    while (cur->next && cur->next->x <= res.x + width) {
  11222       stbrp_node *next = cur->next;
  11223       /*  move the current node to the free list */
  11224       cur->next = context->free_head;
  11225       context->free_head = cur;
  11226       cur = next;
  11227    }
  11228 
  11229    /*  stitch the list back in */
  11230    node->next = cur;
  11231 
  11232    if (cur->x < res.x + width)
  11233       cur->x = (stbrp_coord) (res.x + width);
  11234 
  11235 #ifdef _DEBUG
  11236    cur = context->active_head;
  11237    while (cur->x < context->width) {
  11238       STBRP_ASSERT(cur->x < cur->next->x);
  11239       cur = cur->next;
  11240    }
  11241    STBRP_ASSERT(cur->next == NULL);
  11242 
  11243    {
  11244       int count=0;
  11245       cur = context->active_head;
  11246       while (cur) {
  11247          cur = cur->next;
  11248          ++count;
  11249       }
  11250       cur = context->free_head;
  11251       while (cur) {
  11252          cur = cur->next;
  11253          ++count;
  11254       }
  11255       STBRP_ASSERT(count == context->num_nodes+2);
  11256    }
  11257 #endif
  11258 
  11259    return res;
  11260 }
  11261 
  11262 static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
  11263 {
  11264    const stbrp_rect *p = (const stbrp_rect *) a;
  11265    const stbrp_rect *q = (const stbrp_rect *) b;
  11266    if (p->h > q->h)
  11267       return -1;
  11268    if (p->h < q->h)
  11269       return  1;
  11270    return (p->w > q->w) ? -1 : (p->w < q->w);
  11271 }
  11272 
  11273 static int STBRP__CDECL rect_original_order(const void *a, const void *b)
  11274 {
  11275    const stbrp_rect *p = (const stbrp_rect *) a;
  11276    const stbrp_rect *q = (const stbrp_rect *) b;
  11277    return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
  11278 }
  11279 
  11280 STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
  11281 {
  11282    int i, all_rects_packed = 1;
  11283 
  11284    /*  we use the 'was_packed' field internally to allow sorting/unsorting */
  11285    for (i=0; i < num_rects; ++i) {
  11286       rects[i].was_packed = i;
  11287    }
  11288 
  11289    /*  sort according to heuristic */
  11290    STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
  11291 
  11292    for (i=0; i < num_rects; ++i) {
  11293       if (rects[i].w == 0 || rects[i].h == 0) {
  11294          rects[i].x = rects[i].y = 0;  /*  empty rect needs no space */
  11295       } else {
  11296          stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
  11297          if (fr.prev_link) {
  11298             rects[i].x = (stbrp_coord) fr.x;
  11299             rects[i].y = (stbrp_coord) fr.y;
  11300          } else {
  11301             rects[i].x = rects[i].y = STBRP__MAXVAL;
  11302          }
  11303       }
  11304    }
  11305 
  11306    /*  unsort */
  11307    STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
  11308 
  11309    /*  set was_packed flags and all_rects_packed status */
  11310    for (i=0; i < num_rects; ++i) {
  11311       rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
  11312       if (!rects[i].was_packed)
  11313          all_rects_packed = 0;
  11314    }
  11315 
  11316    /*  return the all_rects_packed status */
  11317    return all_rects_packed;
  11318 }
  11319 #endif
  11320 
  11321 /*
  11322 ------------------------------------------------------------------------------
  11323 This software is available under 2 licenses -- choose whichever you prefer.
  11324 ------------------------------------------------------------------------------
  11325 ALTERNATIVE A - MIT License
  11326 Copyright (c) 2017 Sean Barrett
  11327 Permission is hereby granted, free of charge, to any person obtaining a copy of
  11328 this software and associated documentation files (the "Software"), to deal in
  11329 the Software without restriction, including without limitation the rights to
  11330 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  11331 of the Software, and to permit persons to whom the Software is furnished to do
  11332 so, subject to the following conditions:
  11333 The above copyright notice and this permission notice shall be included in all
  11334 copies or substantial portions of the Software.
  11335 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11336 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  11337 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  11338 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  11339 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  11340 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  11341 SOFTWARE.
  11342 ------------------------------------------------------------------------------
  11343 ALTERNATIVE B - Public Domain (www.unlicense.org)
  11344 This is free and unencumbered software released into the public domain.
  11345 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
  11346 software, either in source code form or as a compiled binary, for any purpose,
  11347 commercial or non-commercial, and by any means.
  11348 In jurisdictions that recognize copyright laws, the author or authors of this
  11349 software dedicate any and all copyright interest in the software to the public
  11350 domain. We make this dedication for the benefit of the public at large and to
  11351 the detriment of our heirs and successors. We intend this dedication to be an
  11352 overt act of relinquishment in perpetuity of all present and future rights to
  11353 this software under copyright law.
  11354 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11355 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  11356 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  11357 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  11358 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  11359 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  11360 ------------------------------------------------------------------------------
  11361 */
  11362 
  11363 /*  stb_truetype.h - v1.26 - public domain */
  11364 /*  authored from 2009-2021 by Sean Barrett / RAD Game Tools */
  11365 /*  */
  11366 /*  ======================================================================= */
  11367 /*  */
  11368 /*     NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES */
  11369 /*  */
  11370 /*  This library does no range checking of the offsets found in the file, */
  11371 /*  meaning an attacker can use it to read arbitrary memory. */
  11372 /*  */
  11373 /*  ======================================================================= */
  11374 /*  */
  11375 /*    This library processes TrueType files: */
  11376 /*         parse files */
  11377 /*         extract glyph metrics */
  11378 /*         extract glyph shapes */
  11379 /*         render glyphs to one-channel bitmaps with antialiasing (box filter) */
  11380 /*         render glyphs to one-channel SDF bitmaps (signed-distance field/function) */
  11381 /*  */
  11382 /*    Todo: */
  11383 /*         non-MS cmaps */
  11384 /*         crashproof on bad data */
  11385 /*         hinting? (no longer patented) */
  11386 /*         cleartype-style AA? */
  11387 /*         optimize: use simple memory allocator for intermediates */
  11388 /*         optimize: build edge-list directly from curves */
  11389 /*         optimize: rasterize directly from curves? */
  11390 /*  */
  11391 /*  ADDITIONAL CONTRIBUTORS */
  11392 /*  */
  11393 /*    Mikko Mononen: compound shape support, more cmap formats */
  11394 /*    Tor Andersson: kerning, subpixel rendering */
  11395 /*    Dougall Johnson: OpenType / Type 2 font handling */
  11396 /*    Daniel Ribeiro Maciel: basic GPOS-based kerning */
  11397 /*  */
  11398 /*    Misc other: */
  11399 /*        Ryan Gordon */
  11400 /*        Simon Glass */
  11401 /*        github:IntellectualKitty */
  11402 /*        Imanol Celaya */
  11403 /*        Daniel Ribeiro Maciel */
  11404 /*  */
  11405 /*    Bug/warning reports/fixes: */
  11406 /*        "Zer" on mollyrocket       Fabian "ryg" Giesen   github:NiLuJe */
  11407 /*        Cass Everitt               Martins Mozeiko       github:aloucks */
  11408 /*        stoiko (Haemimont Games)   Cap Petschulat        github:oyvindjam */
  11409 /*        Brian Hook                 Omar Cornut           github:vassvik */
  11410 /*        Walter van Niftrik         Ryan Griege */
  11411 /*        David Gow                  Peter LaValle */
  11412 /*        David Given                Sergey Popov */
  11413 /*        Ivan-Assen Ivanov          Giumo X. Clanjor */
  11414 /*        Anthony Pesch              Higor Euripedes */
  11415 /*        Johan Duparc               Thomas Fields */
  11416 /*        Hou Qiming                 Derek Vinyard */
  11417 /*        Rob Loach                  Cort Stratton */
  11418 /*        Kenney Phillis Jr.         Brian Costabile */
  11419 /*        Ken Voskuil (kaesve) */
  11420 /*  */
  11421 /*  VERSION HISTORY */
  11422 /*  */
  11423 /*    1.26 (2021-08-28) fix broken rasterizer */
  11424 /*    1.25 (2021-07-11) many fixes */
  11425 /*    1.24 (2020-02-05) fix warning */
  11426 /*    1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) */
  11427 /*    1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined */
  11428 /*    1.21 (2019-02-25) fix warning */
  11429 /*    1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() */
  11430 /*    1.19 (2018-02-11) GPOS kerning, STBTT_fmod */
  11431 /*    1.18 (2018-01-29) add missing function */
  11432 /*    1.17 (2017-07-23) make more arguments const; doc fix */
  11433 /*    1.16 (2017-07-12) SDF support */
  11434 /*    1.15 (2017-03-03) make more arguments const */
  11435 /*    1.14 (2017-01-16) num-fonts-in-TTC function */
  11436 /*    1.13 (2017-01-02) support OpenType fonts, certain Apple fonts */
  11437 /*    1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual */
  11438 /*    1.11 (2016-04-02) fix unused-variable warning */
  11439 /*    1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef */
  11440 /*    1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly */
  11441 /*    1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges */
  11442 /*    1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; */
  11443 /*                      variant PackFontRanges to pack and render in separate phases; */
  11444 /*                      fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); */
  11445 /*                      fixed an assert() bug in the new rasterizer */
  11446 /*                      replace assert() with STBTT_assert() in new rasterizer */
  11447 /*  */
  11448 /*    Full history can be found at the end of this file. */
  11449 /*  */
  11450 /*  LICENSE */
  11451 /*  */
  11452 /*    See end of file for license information. */
  11453 /*  */
  11454 /*  USAGE */
  11455 /*  */
  11456 /*    Include this file in whatever places need to refer to it. In ONE C/C++ */
  11457 /*    file, write: */
  11458 /*       #define STB_TRUETYPE_IMPLEMENTATION */
  11459 /*    before the #include of this file. This expands out the actual */
  11460 /*    implementation into that C/C++ file. */
  11461 /*  */
  11462 /*    To make the implementation private to the file that generates the implementation, */
  11463 /*       #define STBTT_STATIC */
  11464 /*  */
  11465 /*    Simple 3D API (don't ship this, but it's fine for tools and quick start) */
  11466 /*            stbtt_BakeFontBitmap()               -- bake a font to a bitmap for use as texture */
  11467 /*            stbtt_GetBakedQuad()                 -- compute quad to draw for a given char */
  11468 /*  */
  11469 /*    Improved 3D API (more shippable): */
  11470 /*            #include "stb_rect_pack.h"           -- optional, but you really want it */
  11471 /*            stbtt_PackBegin() */
  11472 /*            stbtt_PackSetOversampling()          -- for improved quality on small fonts */
  11473 /*            stbtt_PackFontRanges()               -- pack and renders */
  11474 /*            stbtt_PackEnd() */
  11475 /*            stbtt_GetPackedQuad() */
  11476 /*  */
  11477 /*    "Load" a font file from a memory buffer (you have to keep the buffer loaded) */
  11478 /*            stbtt_InitFont() */
  11479 /*            stbtt_GetFontOffsetForIndex()        -- indexing for TTC font collections */
  11480 /*            stbtt_GetNumberOfFonts()             -- number of fonts for TTC font collections */
  11481 /*  */
  11482 /*    Render a unicode codepoint to a bitmap */
  11483 /*            stbtt_GetCodepointBitmap()           -- allocates and returns a bitmap */
  11484 /*            stbtt_MakeCodepointBitmap()          -- renders into bitmap you provide */
  11485 /*            stbtt_GetCodepointBitmapBox()        -- how big the bitmap must be */
  11486 /*  */
  11487 /*    Character advance/positioning */
  11488 /*            stbtt_GetCodepointHMetrics() */
  11489 /*            stbtt_GetFontVMetrics() */
  11490 /*            stbtt_GetFontVMetricsOS2() */
  11491 /*            stbtt_GetCodepointKernAdvance() */
  11492 /*  */
  11493 /*    Starting with version 1.06, the rasterizer was replaced with a new, */
  11494 /*    faster and generally-more-precise rasterizer. The new rasterizer more */
  11495 /*    accurately measures pixel coverage for anti-aliasing, except in the case */
  11496 /*    where multiple shapes overlap, in which case it overestimates the AA pixel */
  11497 /*    coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If */
  11498 /*    this turns out to be a problem, you can re-enable the old rasterizer with */
  11499 /*         #define STBTT_RASTERIZER_VERSION 1 */
  11500 /*    which will incur about a 15% speed hit. */
  11501 /*  */
  11502 /*  ADDITIONAL DOCUMENTATION */
  11503 /*  */
  11504 /*    Immediately after this block comment are a series of sample programs. */
  11505 /*  */
  11506 /*    After the sample programs is the "header file" section. This section */
  11507 /*    includes documentation for each API function. */
  11508 /*  */
  11509 /*    Some important concepts to understand to use this library: */
  11510 /*  */
  11511 /*       Codepoint */
  11512 /*          Characters are defined by unicode codepoints, e.g. 65 is */
  11513 /*          uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is */
  11514 /*          the hiragana for "ma". */
  11515 /*  */
  11516 /*       Glyph */
  11517 /*          A visual character shape (every codepoint is rendered as */
  11518 /*          some glyph) */
  11519 /*  */
  11520 /*       Glyph index */
  11521 /*          A font-specific integer ID representing a glyph */
  11522 /*  */
  11523 /*       Baseline */
  11524 /*          Glyph shapes are defined relative to a baseline, which is the */
  11525 /*          bottom of uppercase characters. Characters extend both above */
  11526 /*          and below the baseline. */
  11527 /*  */
  11528 /*       Current Point */
  11529 /*          As you draw text to the screen, you keep track of a "current point" */
  11530 /*          which is the origin of each character. The current point's vertical */
  11531 /*          position is the baseline. Even "baked fonts" use this model. */
  11532 /*  */
  11533 /*       Vertical Font Metrics */
  11534 /*          The vertical qualities of the font, used to vertically position */
  11535 /*          and space the characters. See docs for stbtt_GetFontVMetrics. */
  11536 /*  */
  11537 /*       Font Size in Pixels or Points */
  11538 /*          The preferred interface for specifying font sizes in stb_truetype */
  11539 /*          is to specify how tall the font's vertical extent should be in pixels. */
  11540 /*          If that sounds good enough, skip the next paragraph. */
  11541 /*  */
  11542 /*          Most font APIs instead use "points", which are a common typographic */
  11543 /*          measurement for describing font size, defined as 72 points per inch. */
  11544 /*          stb_truetype provides a point API for compatibility. However, true */
  11545 /*          "per inch" conventions don't make much sense on computer displays */
  11546 /*          since different monitors have different number of pixels per */
  11547 /*          inch. For example, Windows traditionally uses a convention that */
  11548 /*          there are 96 pixels per inch, thus making 'inch' measurements have */
  11549 /*          nothing to do with inches, and thus effectively defining a point to */
  11550 /*          be 1.333 pixels. Additionally, the TrueType font data provides */
  11551 /*          an explicit scale factor to scale a given font's glyphs to points, */
  11552 /*          but the author has observed that this scale factor is often wrong */
  11553 /*          for non-commercial fonts, thus making fonts scaled in points */
  11554 /*          according to the TrueType spec incoherently sized in practice. */
  11555 /*  */
  11556 /*  DETAILED USAGE: */
  11557 /*  */
  11558 /*   Scale: */
  11559 /*     Select how high you want the font to be, in points or pixels. */
  11560 /*     Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute */
  11561 /*     a scale factor SF that will be used by all other functions. */
  11562 /*  */
  11563 /*   Baseline: */
  11564 /*     You need to select a y-coordinate that is the baseline of where */
  11565 /*     your text will appear. Call GetFontBoundingBox to get the baseline-relative */
  11566 /*     bounding box for all characters. SF*-y0 will be the distance in pixels */
  11567 /*     that the worst-case character could extend above the baseline, so if */
  11568 /*     you want the top edge of characters to appear at the top of the */
  11569 /*     screen where y=0, then you would set the baseline to SF*-y0. */
  11570 /*  */
  11571 /*   Current point: */
  11572 /*     Set the current point where the first character will appear. The */
  11573 /*     first character could extend left of the current point; this is font */
  11574 /*     dependent. You can either choose a current point that is the leftmost */
  11575 /*     point and hope, or add some padding, or check the bounding box or */
  11576 /*     left-side-bearing of the first character to be displayed and set */
  11577 /*     the current point based on that. */
  11578 /*  */
  11579 /*   Displaying a character: */
  11580 /*     Compute the bounding box of the character. It will contain signed values */
  11581 /*     relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1, */
  11582 /*     then the character should be displayed in the rectangle from */
  11583 /*     <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1). */
  11584 /*  */
  11585 /*   Advancing for the next character: */
  11586 /*     Call GlyphHMetrics, and compute 'current_point += SF * advance'. */
  11587 /*  */
  11588 /*  */
  11589 /*  ADVANCED USAGE */
  11590 /*  */
  11591 /*    Quality: */
  11592 /*  */
  11593 /*     - Use the functions with Subpixel at the end to allow your characters */
  11594 /*       to have subpixel positioning. Since the font is anti-aliased, not */
  11595 /*       hinted, this is very import for quality. (This is not possible with */
  11596 /*       baked fonts.) */
  11597 /*  */
  11598 /*     - Kerning is now supported, and if you're supporting subpixel rendering */
  11599 /*       then kerning is worth using to give your text a polished look. */
  11600 /*  */
  11601 /*    Performance: */
  11602 /*  */
  11603 /*     - Convert Unicode codepoints to glyph indexes and operate on the glyphs; */
  11604 /*       if you don't do this, stb_truetype is forced to do the conversion on */
  11605 /*       every call. */
  11606 /*  */
  11607 /*     - There are a lot of memory allocations. We should modify it to take */
  11608 /*       a temp buffer and allocate from the temp buffer (without freeing), */
  11609 /*       should help performance a lot. */
  11610 /*  */
  11611 /*  NOTES */
  11612 /*  */
  11613 /*    The system uses the raw data found in the .ttf file without changing it */
  11614 /*    and without building auxiliary data structures. This is a bit inefficient */
  11615 /*    on little-endian systems (the data is big-endian), but assuming you're */
  11616 /*    caching the bitmaps or glyph shapes this shouldn't be a big deal. */
  11617 /*  */
  11618 /*    It appears to be very hard to programmatically determine what font a */
  11619 /*    given file is in a general way. I provide an API for this, but I don't */
  11620 /*    recommend it. */
  11621 /*  */
  11622 /*  */
  11623 /*  PERFORMANCE MEASUREMENTS FOR 1.06: */
  11624 /*  */
  11625 /*                       32-bit     64-bit */
  11626 /*    Previous release:  8.83 s     7.68 s */
  11627 /*    Pool allocations:  7.72 s     6.34 s */
  11628 /*    Inline sort     :  6.54 s     5.65 s */
  11629 /*    New rasterizer  :  5.63 s     5.00 s */
  11630 
  11631 /* //////////////////////////////////////////////////////////////////////////// */
  11632 /* //////////////////////////////////////////////////////////////////////////// */
  11633 /* // */
  11634 /* //  SAMPLE PROGRAMS */
  11635 /* // */
  11636 /*  */
  11637 /*   Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless. */
  11638 /*   See "tests/truetype_demo_win32.c" for a complete version. */
  11639 #if 0
  11640 #define STB_TRUETYPE_IMPLEMENTATION  /*  force following include to generate implementation */
  11641 #include "stb_truetype.h"
  11642 
  11643 unsigned char ttf_buffer[1<<20];
  11644 unsigned char temp_bitmap[512*512];
  11645 
  11646 stbtt_bakedchar cdata[96]; /*  ASCII 32..126 is 95 glyphs */
  11647 GLuint ftex;
  11648 
  11649 void my_stbtt_initfont(void)
  11650 {
  11651    fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
  11652    stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); /*  no guarantee this fits! */
  11653    /*  can free ttf_buffer at this point */
  11654    glGenTextures(1, &ftex);
  11655    glBindTexture(GL_TEXTURE_2D, ftex);
  11656    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
  11657    /*  can free temp_bitmap at this point */
  11658    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  11659 }
  11660 
  11661 void my_stbtt_print(float x, float y, char *text)
  11662 {
  11663    /*  assume orthographic projection with units = screen pixels, origin at top left */
  11664    glEnable(GL_BLEND);
  11665    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  11666    glEnable(GL_TEXTURE_2D);
  11667    glBindTexture(GL_TEXTURE_2D, ftex);
  11668    glBegin(GL_QUADS);
  11669    while (*text) {
  11670       if (*text >= 32 && *text < 128) {
  11671          stbtt_aligned_quad q;
  11672          stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);/* 1=opengl & d3d10+,0=d3d9 */
  11673          glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
  11674          glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
  11675          glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
  11676          glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
  11677       }
  11678       ++text;
  11679    }
  11680    glEnd();
  11681 }
  11682 #endif
  11683 /*  */
  11684 /*  */
  11685 /* //////////////////////////////////////////////////////////////////////////// */
  11686 /*  */
  11687 /*  Complete program (this compiles): get a single bitmap, print as ASCII art */
  11688 /*  */
  11689 #if 0
  11690 #include <stdio.h>
  11691 #define STB_TRUETYPE_IMPLEMENTATION  /*  force following include to generate implementation */
  11692 #include "stb_truetype.h"
  11693 
  11694 char ttf_buffer[1<<25];
  11695 
  11696 int main(int argc, char **argv)
  11697 {
  11698    stbtt_fontinfo font;
  11699    unsigned char *bitmap;
  11700    int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
  11701 
  11702    fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
  11703 
  11704    stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
  11705    bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
  11706 
  11707    for (j=0; j < h; ++j) {
  11708       for (i=0; i < w; ++i)
  11709          putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
  11710       putchar('\n');
  11711    }
  11712    return 0;
  11713 }
  11714 #endif
  11715 /*  */
  11716 /*  Output: */
  11717 /*  */
  11718 /*      .ii. */
  11719 /*     @@@@@@. */
  11720 /*    V@Mio@@o */
  11721 /*    :i.  V@V */
  11722 /*      :oM@@M */
  11723 /*    :@@@MM@M */
  11724 /*    @@o  o@M */
  11725 /*   :@@.  M@M */
  11726 /*    @@@o@@@@ */
  11727 /*    :M@@V:@@. */
  11728 /*  */
  11729 /* //////////////////////////////////////////////////////////////////////////// */
  11730 /*  */
  11731 /*  Complete program: print "Hello World!" banner, with bugs */
  11732 /*  */
  11733 #if 0
  11734 char buffer[24<<20];
  11735 unsigned char screen[20][79];
  11736 
  11737 int main(int arg, char **argv)
  11738 {
  11739    stbtt_fontinfo font;
  11740    int i,j,ascent,baseline,ch=0;
  11741    float scale, xpos=2; /*  leave a little padding in case the character extends left */
  11742    char *text = "Heljo World!"; /*  intentionally misspelled to show 'lj' brokenness */
  11743 
  11744    fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
  11745    stbtt_InitFont(&font, buffer, 0);
  11746 
  11747    scale = stbtt_ScaleForPixelHeight(&font, 15);
  11748    stbtt_GetFontVMetrics(&font, &ascent,0,0);
  11749    baseline = (int) (ascent*scale);
  11750 
  11751    while (text[ch]) {
  11752       int advance,lsb,x0,y0,x1,y1;
  11753       float x_shift = xpos - (float) floor(xpos);
  11754       stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
  11755       stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
  11756       stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
  11757       /*  note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong */
  11758       /*  because this API is really for baking character bitmaps into textures. if you want to render */
  11759       /*  a sequence of characters, you really need to render each bitmap to a temp buffer, then */
  11760       /*  "alpha blend" that into the working buffer */
  11761       xpos += (advance * scale);
  11762       if (text[ch+1])
  11763          xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
  11764       ++ch;
  11765    }
  11766 
  11767    for (j=0; j < 20; ++j) {
  11768       for (i=0; i < 78; ++i)
  11769          putchar(" .:ioVM@"[screen[j][i]>>5]);
  11770       putchar('\n');
  11771    }
  11772 
  11773    return 0;
  11774 }
  11775 #endif
  11776 
  11777 
  11778 /* //////////////////////////////////////////////////////////////////////////// */
  11779 /* //////////////////////////////////////////////////////////////////////////// */
  11780 /* // */
  11781 /* //   INTEGRATION WITH YOUR CODEBASE */
  11782 /* // */
  11783 /* //   The following sections allow you to supply alternate definitions */
  11784 /* //   of C library functions used by stb_truetype, e.g. if you don't */
  11785 /* //   link with the C runtime library. */
  11786 
  11787 #ifdef STB_TRUETYPE_IMPLEMENTATION
  11788    /*  #define your own (u)stbtt_int8/16/32 before including to override this */
  11789    #ifndef stbtt_uint8
  11790    typedef unsigned char   stbtt_uint8;
  11791    typedef signed   char   stbtt_int8;
  11792    typedef unsigned short  stbtt_uint16;
  11793    typedef signed   short  stbtt_int16;
  11794    typedef unsigned int    stbtt_uint32;
  11795    typedef signed   int    stbtt_int32;
  11796    #endif
  11797 
  11798    typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
  11799    typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
  11800 
  11801    /*  e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h */
  11802    #ifndef STBTT_ifloor
  11803    #include <math.h>
  11804    #define STBTT_ifloor(x)   ((int) floor(x))
  11805    #define STBTT_iceil(x)    ((int) ceil(x))
  11806    #endif
  11807 
  11808    #ifndef STBTT_sqrt
  11809    #include <math.h>
  11810    #define STBTT_sqrt(x)      sqrt(x)
  11811    #define STBTT_pow(x,y)     pow(x,y)
  11812    #endif
  11813 
  11814    #ifndef STBTT_fmod
  11815    #include <math.h>
  11816    #define STBTT_fmod(x,y)    fmod(x,y)
  11817    #endif
  11818 
  11819    #ifndef STBTT_cos
  11820    #include <math.h>
  11821    #define STBTT_cos(x)       cos(x)
  11822    #define STBTT_acos(x)      acos(x)
  11823    #endif
  11824 
  11825    #ifndef STBTT_fabs
  11826    #include <math.h>
  11827    #define STBTT_fabs(x)      fabs(x)
  11828    #endif
  11829 
  11830    /*  #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h */
  11831    #ifndef STBTT_malloc
  11832    #include <stdlib.h>
  11833    #define STBTT_malloc(x,u)  ((void)(u),malloc(x))
  11834    #define STBTT_free(x,u)    ((void)(u),free(x))
  11835    #endif
  11836 
  11837    #ifndef STBTT_assert
  11838    #include <assert.h>
  11839    #define STBTT_assert(x)    assert(x)
  11840    #endif
  11841 
  11842    #ifndef STBTT_strlen
  11843    #include <string.h>
  11844    #define STBTT_strlen(x)    strlen(x)
  11845    #endif
  11846 
  11847    #ifndef STBTT_memcpy
  11848    #include <string.h>
  11849    #define STBTT_memcpy       memcpy
  11850    #define STBTT_memset       memset
  11851    #endif
  11852 #endif
  11853 
  11854 /* ///////////////////////////////////////////////////////////////////////////// */
  11855 /* ///////////////////////////////////////////////////////////////////////////// */
  11856 /* // */
  11857 /* //   INTERFACE */
  11858 /* // */
  11859 /* // */
  11860 
  11861 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
  11862 #define __STB_INCLUDE_STB_TRUETYPE_H__
  11863 
  11864 #ifdef STBTT_STATIC
  11865 #define STBTT_DEF static
  11866 #else
  11867 #define STBTT_DEF extern
  11868 #endif
  11869 
  11870 #ifdef __cplusplus
  11871 extern "C" {
  11872 #endif
  11873 
  11874 /*  private structure */
  11875 typedef struct
  11876 {
  11877    unsigned char *data;
  11878    int cursor;
  11879    int size;
  11880 } stbtt__buf;
  11881 
  11882 /* //////////////////////////////////////////////////////////////////////////// */
  11883 /*  */
  11884 /*  TEXTURE BAKING API */
  11885 /*  */
  11886 /*  If you use this API, you only have to call two functions ever. */
  11887 /*  */
  11888 
  11889 typedef struct
  11890 {
  11891    unsigned short x0,y0,x1,y1; /*  coordinates of bbox in bitmap */
  11892    float xoff,yoff,xadvance;
  11893 } stbtt_bakedchar;
  11894 
  11895 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,  /*  font location (use offset=0 for plain .ttf) */
  11896                                 float pixel_height,                     /*  height of font in pixels */
  11897                                 unsigned char *pixels, int pw, int ph,  /*  bitmap to be filled in */
  11898                                 int first_char, int num_chars,          /*  characters to bake */
  11899                                 stbtt_bakedchar *chardata);             /*  you allocate this, it's num_chars long */
  11900 /*  if return is positive, the first unused row of the bitmap */
  11901 /*  if return is negative, returns the negative of the number of characters that fit */
  11902 /*  if return is 0, no characters fit and no rows were used */
  11903 /*  This uses a very crappy packing. */
  11904 
  11905 typedef struct
  11906 {
  11907    float x0,y0,s0,t0; /*  top-left */
  11908    float x1,y1,s1,t1; /*  bottom-right */
  11909 } stbtt_aligned_quad;
  11910 
  11911 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph,  /*  same data as above */
  11912                                int char_index,             /*  character to display */
  11913                                float *xpos, float *ypos,   /*  pointers to current position in screen pixel space */
  11914                                stbtt_aligned_quad *q,      /*  output: quad to draw */
  11915                                int opengl_fillrule);       /*  true if opengl fill rule; false if DX9 or earlier */
  11916 /*  Call GetBakedQuad with char_index = 'character - first_char', and it */
  11917 /*  creates the quad you need to draw and advances the current position. */
  11918 /*  */
  11919 /*  The coordinate system used assumes y increases downwards. */
  11920 /*  */
  11921 /*  Characters will extend both above and below the current position; */
  11922 /*  see discussion of "BASELINE" above. */
  11923 /*  */
  11924 /*  It's inefficient; you might want to c&p it and optimize it. */
  11925 
  11926 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
  11927 /*  Query the font vertical metrics without having to create a font first. */
  11928 
  11929 
  11930 /* //////////////////////////////////////////////////////////////////////////// */
  11931 /*  */
  11932 /*  NEW TEXTURE BAKING API */
  11933 /*  */
  11934 /*  This provides options for packing multiple fonts into one atlas, not */
  11935 /*  perfectly but better than nothing. */
  11936 
  11937 typedef struct
  11938 {
  11939    unsigned short x0,y0,x1,y1; /*  coordinates of bbox in bitmap */
  11940    float xoff,yoff,xadvance;
  11941    float xoff2,yoff2;
  11942 } stbtt_packedchar;
  11943 
  11944 typedef struct stbtt_pack_context stbtt_pack_context;
  11945 typedef struct stbtt_fontinfo stbtt_fontinfo;
  11946 #ifndef STB_RECT_PACK_VERSION
  11947 typedef struct stbrp_rect stbrp_rect;
  11948 #endif
  11949 
  11950 STBTT_DEF int  stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
  11951 /*  Initializes a packing context stored in the passed-in stbtt_pack_context. */
  11952 /*  Future calls using this context will pack characters into the bitmap passed */
  11953 /*  in here: a 1-channel bitmap that is width * height. stride_in_bytes is */
  11954 /*  the distance from one row to the next (or 0 to mean they are packed tightly */
  11955 /*  together). "padding" is the amount of padding to leave between each */
  11956 /*  character (normally you want '1' for bitmaps you'll use as textures with */
  11957 /*  bilinear filtering). */
  11958 /*  */
  11959 /*  Returns 0 on failure, 1 on success. */
  11960 
  11961 STBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc);
  11962 /*  Cleans up the packing context and frees all memory. */
  11963 
  11964 #define STBTT_POINT_SIZE(x)   (-(x))
  11965 
  11966 STBTT_DEF int  stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
  11967                                 int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
  11968 /*  Creates character bitmaps from the font_index'th font found in fontdata (use */
  11969 /*  font_index=0 if you don't know what that is). It creates num_chars_in_range */
  11970 /*  bitmaps for characters with unicode values starting at first_unicode_char_in_range */
  11971 /*  and increasing. Data for how to render them is stored in chardata_for_range; */
  11972 /*  pass these to stbtt_GetPackedQuad to get back renderable quads. */
  11973 /*  */
  11974 /*  font_size is the full height of the character from ascender to descender, */
  11975 /*  as computed by stbtt_ScaleForPixelHeight. To use a point size as computed */
  11976 /*  by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() */
  11977 /*  and pass that result as 'font_size': */
  11978 /*        ...,                  20 , ... // font max minus min y is 20 pixels tall */
  11979 /*        ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall */
  11980 
  11981 typedef struct
  11982 {
  11983    float font_size;
  11984    int first_unicode_codepoint_in_range;  /*  if non-zero, then the chars are continuous, and this is the first codepoint */
  11985    int *array_of_unicode_codepoints;       /*  if non-zero, then this is an array of unicode codepoints */
  11986    int num_chars;
  11987    stbtt_packedchar *chardata_for_range; /*  output */
  11988    unsigned char h_oversample, v_oversample; /*  don't set these, they're used internally */
  11989 } stbtt_pack_range;
  11990 
  11991 STBTT_DEF int  stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
  11992 /*  Creates character bitmaps from multiple ranges of characters stored in */
  11993 /*  ranges. This will usually create a better-packed bitmap than multiple */
  11994 /*  calls to stbtt_PackFontRange. Note that you can call this multiple */
  11995 /*  times within a single PackBegin/PackEnd. */
  11996 
  11997 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
  11998 /*  Oversampling a font increases the quality by allowing higher-quality subpixel */
  11999 /*  positioning, and is especially valuable at smaller text sizes. */
  12000 /*  */
  12001 /*  This function sets the amount of oversampling for all following calls to */
  12002 /*  stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given */
  12003 /*  pack context. The default (no oversampling) is achieved by h_oversample=1 */
  12004 /*  and v_oversample=1. The total number of pixels required is */
  12005 /*  h_oversample*v_oversample larger than the default; for example, 2x2 */
  12006 /*  oversampling requires 4x the storage of 1x1. For best results, render */
  12007 /*  oversampled textures with bilinear filtering. Look at the readme in */
  12008 /*  stb/tests/oversample for information about oversampled fonts */
  12009 /*  */
  12010 /*  To use with PackFontRangesGather etc., you must set it before calls */
  12011 /*  call to PackFontRangesGatherRects. */
  12012 
  12013 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
  12014 /*  If skip != 0, this tells stb_truetype to skip any codepoints for which */
  12015 /*  there is no corresponding glyph. If skip=0, which is the default, then */
  12016 /*  codepoints without a glyph recived the font's "missing character" glyph, */
  12017 /*  typically an empty box by convention. */
  12018 
  12019 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph,  /*  same data as above */
  12020                                int char_index,             /*  character to display */
  12021                                float *xpos, float *ypos,   /*  pointers to current position in screen pixel space */
  12022                                stbtt_aligned_quad *q,      /*  output: quad to draw */
  12023                                int align_to_integer);
  12024 
  12025 STBTT_DEF int  stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
  12026 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
  12027 STBTT_DEF int  stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
  12028 /*  Calling these functions in sequence is roughly equivalent to calling */
  12029 /*  stbtt_PackFontRanges(). If you more control over the packing of multiple */
  12030 /*  fonts, or if you want to pack custom data into a font texture, take a look */
  12031 /*  at the source to of stbtt_PackFontRanges() and create a custom version */
  12032 /*  using these functions, e.g. call GatherRects multiple times, */
  12033 /*  building up a single array of rects, then call PackRects once, */
  12034 /*  then call RenderIntoRects repeatedly. This may result in a */
  12035 /*  better packing than calling PackFontRanges multiple times */
  12036 /*  (or it may not). */
  12037 
  12038 /*  this is an opaque structure that you shouldn't mess with which holds */
  12039 /*  all the context needed from PackBegin to PackEnd. */
  12040 struct stbtt_pack_context {
  12041    void *user_allocator_context;
  12042    void *pack_info;
  12043    int   width;
  12044    int   height;
  12045    int   stride_in_bytes;
  12046    int   padding;
  12047    int   skip_missing;
  12048    unsigned int   h_oversample, v_oversample;
  12049    unsigned char *pixels;
  12050    void  *nodes;
  12051 };
  12052 
  12053 /* //////////////////////////////////////////////////////////////////////////// */
  12054 /*  */
  12055 /*  FONT LOADING */
  12056 /*  */
  12057 /*  */
  12058 
  12059 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
  12060 /*  This function will determine the number of fonts in a font file.  TrueType */
  12061 /*  collection (.ttc) files may contain multiple fonts, while TrueType font */
  12062 /*  (.ttf) files only contain one font. The number of fonts can be used for */
  12063 /*  indexing with the previous function where the index is between zero and one */
  12064 /*  less than the total fonts. If an error occurs, -1 is returned. */
  12065 
  12066 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
  12067 /*  Each .ttf/.ttc file may have more than one font. Each font has a sequential */
  12068 /*  index number starting from 0. Call this function to get the font offset for */
  12069 /*  a given index; it returns -1 if the index is out of range. A regular .ttf */
  12070 /*  file will only define one font and it always be at offset 0, so it will */
  12071 /*  return '0' for index 0, and -1 for all other indices. */
  12072 
  12073 /*  The following structure is defined publicly so you can declare one on */
  12074 /*  the stack or as a global or etc, but you should treat it as opaque. */
  12075 struct stbtt_fontinfo
  12076 {
  12077    void           * userdata;
  12078    unsigned char  * data;              /*  pointer to .ttf file */
  12079    int              fontstart;         /*  offset of start of font */
  12080 
  12081    int numGlyphs;                     /*  number of glyphs, needed for range checking */
  12082 
  12083    int loca,head,glyf,hhea,hmtx,kern,gpos,svg; /*  table locations as offset from start of .ttf */
  12084    int index_map;                     /*  a cmap mapping for our chosen character encoding */
  12085    int indexToLocFormat;              /*  format needed to map from glyph index to glyph */
  12086 
  12087    stbtt__buf cff;                    /*  cff font data */
  12088    stbtt__buf charstrings;            /*  the charstring index */
  12089    stbtt__buf gsubrs;                 /*  global charstring subroutines index */
  12090    stbtt__buf subrs;                  /*  private charstring subroutines index */
  12091    stbtt__buf fontdicts;              /*  array of font dicts */
  12092    stbtt__buf fdselect;               /*  map from glyph to fontdict */
  12093 };
  12094 
  12095 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
  12096 /*  Given an offset into the file that defines a font, this function builds */
  12097 /*  the necessary cached info for the rest of the system. You must allocate */
  12098 /*  the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't */
  12099 /*  need to do anything special to free it, because the contents are pure */
  12100 /*  value data with no additional data structures. Returns 0 on failure. */
  12101 
  12102 
  12103 /* //////////////////////////////////////////////////////////////////////////// */
  12104 /*  */
  12105 /*  CHARACTER TO GLYPH-INDEX CONVERSIOn */
  12106 
  12107 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
  12108 /*  If you're going to perform multiple operations on the same character */
  12109 /*  and you want a speed-up, call this function with the character you're */
  12110 /*  going to process, then use glyph-based functions instead of the */
  12111 /*  codepoint-based functions. */
  12112 /*  Returns 0 if the character codepoint is not defined in the font. */
  12113 
  12114 
  12115 /* //////////////////////////////////////////////////////////////////////////// */
  12116 /*  */
  12117 /*  CHARACTER PROPERTIES */
  12118 /*  */
  12119 
  12120 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
  12121 /*  computes a scale factor to produce a font whose "height" is 'pixels' tall. */
  12122 /*  Height is measured as the distance from the highest ascender to the lowest */
  12123 /*  descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics */
  12124 /*  and computing: */
  12125 /*        scale = pixels / (ascent - descent) */
  12126 /*  so if you prefer to measure height by the ascent only, use a similar calculation. */
  12127 
  12128 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
  12129 /*  computes a scale factor to produce a font whose EM size is mapped to */
  12130 /*  'pixels' tall. This is probably what traditional APIs compute, but */
  12131 /*  I'm not positive. */
  12132 
  12133 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
  12134 /*  ascent is the coordinate above the baseline the font extends; descent */
  12135 /*  is the coordinate below the baseline the font extends (i.e. it is typically negative) */
  12136 /*  lineGap is the spacing between one row's descent and the next row's ascent... */
  12137 /*  so you should advance the vertical position by "*ascent - *descent + *lineGap" */
  12138 /*    these are expressed in unscaled coordinates, so you must multiply by */
  12139 /*    the scale factor for a given size */
  12140 
  12141 STBTT_DEF int  stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
  12142 /*  analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 */
  12143 /*  table (specific to MS/Windows TTF files). */
  12144 /*  */
  12145 /*  Returns 1 on success (table present), 0 on failure. */
  12146 
  12147 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
  12148 /*  the bounding box around all possible characters */
  12149 
  12150 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
  12151 /*  leftSideBearing is the offset from the current horizontal position to the left edge of the character */
  12152 /*  advanceWidth is the offset from the current horizontal position to the next horizontal position */
  12153 /*    these are expressed in unscaled coordinates */
  12154 
  12155 STBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
  12156 /*  an additional amount to add to the 'advance' value between ch1 and ch2 */
  12157 
  12158 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
  12159 /*  Gets the bounding box of the visible part of the glyph, in unscaled coordinates */
  12160 
  12161 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
  12162 STBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
  12163 STBTT_DEF int  stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
  12164 /*  as above, but takes one or more glyph indices for greater efficiency */
  12165 
  12166 typedef struct stbtt_kerningentry
  12167 {
  12168    int glyph1; /*  use stbtt_FindGlyphIndex */
  12169    int glyph2;
  12170    int advance;
  12171 } stbtt_kerningentry;
  12172 
  12173 STBTT_DEF int  stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
  12174 STBTT_DEF int  stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
  12175 /*  Retrieves a complete list of all of the kerning pairs provided by the font */
  12176 /*  stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. */
  12177 /*  The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) */
  12178 
  12179 /* //////////////////////////////////////////////////////////////////////////// */
  12180 /*  */
  12181 /*  GLYPH SHAPES (you probably don't need these, but they have to go before */
  12182 /*  the bitmaps for C declaration-order reasons) */
  12183 /*  */
  12184 
  12185 #ifndef STBTT_vmove /*  you can predefine these to use different values (but why?) */
  12186    enum {
  12187       STBTT_vmove=1,
  12188       STBTT_vline,
  12189       STBTT_vcurve,
  12190       STBTT_vcubic
  12191    };
  12192 #endif
  12193 
  12194 #ifndef stbtt_vertex /*  you can predefine this to use different values */
  12195                    /*  (we share this with other code at RAD) */
  12196    #define stbtt_vertex_type short /*  can't use stbtt_int16 because that's not visible in the header file */
  12197    typedef struct
  12198    {
  12199       stbtt_vertex_type x,y,cx,cy,cx1,cy1;
  12200       unsigned char type,padding;
  12201    } stbtt_vertex;
  12202 #endif
  12203 
  12204 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
  12205 /*  returns non-zero if nothing is drawn for this glyph */
  12206 
  12207 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
  12208 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
  12209 /*  returns # of vertices and fills *vertices with the pointer to them */
  12210 /*    these are expressed in "unscaled" coordinates */
  12211 /*  */
  12212 /*  The shape is a series of contours. Each one starts with */
  12213 /*  a STBTT_moveto, then consists of a series of mixed */
  12214 /*  STBTT_lineto and STBTT_curveto segments. A lineto */
  12215 /*  draws a line from previous endpoint to its x,y; a curveto */
  12216 /*  draws a quadratic bezier from previous endpoint to */
  12217 /*  its x,y, using cx,cy as the bezier control point. */
  12218 
  12219 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
  12220 /*  frees the data allocated above */
  12221 
  12222 STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
  12223 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
  12224 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
  12225 /*  fills svg with the character's SVG data. */
  12226 /*  returns data size or 0 if SVG not found. */
  12227 
  12228 /* //////////////////////////////////////////////////////////////////////////// */
  12229 /*  */
  12230 /*  BITMAP RENDERING */
  12231 /*  */
  12232 
  12233 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
  12234 /*  frees the bitmap allocated below */
  12235 
  12236 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
  12237 /*  allocates a large-enough single-channel 8bpp bitmap and renders the */
  12238 /*  specified character/glyph at the specified scale into it, with */
  12239 /*  antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). */
  12240 /*  *width & *height are filled out with the width & height of the bitmap, */
  12241 /*  which is stored left-to-right, top-to-bottom. */
  12242 /*  */
  12243 /*  xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap */
  12244 
  12245 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
  12246 /*  the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel */
  12247 /*  shift for the character */
  12248 
  12249 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
  12250 /*  the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap */
  12251 /*  in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap */
  12252 /*  is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the */
  12253 /*  width and height and positioning info for it first. */
  12254 
  12255 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
  12256 /*  same as stbtt_MakeCodepointBitmap, but you can specify a subpixel */
  12257 /*  shift for the character */
  12258 
  12259 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
  12260 /*  same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering */
  12261 /*  is performed (see stbtt_PackSetOversampling) */
  12262 
  12263 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
  12264 /*  get the bbox of the bitmap centered around the glyph origin; so the */
  12265 /*  bitmap width is ix1-ix0, height is iy1-iy0, and location to place */
  12266 /*  the bitmap top left is (leftSideBearing*scale,iy0). */
  12267 /*  (Note that the bitmap uses y-increases-down, but the shape uses */
  12268 /*  y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) */
  12269 
  12270 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
  12271 /*  same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel */
  12272 /*  shift for the character */
  12273 
  12274 /*  the following functions are equivalent to the above functions, but operate */
  12275 /*  on glyph indices instead of Unicode codepoints (for efficiency) */
  12276 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
  12277 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
  12278 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
  12279 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
  12280 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
  12281 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
  12282 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
  12283 
  12284 
  12285 /*  @TODO: don't expose this structure */
  12286 typedef struct
  12287 {
  12288    int w,h,stride;
  12289    unsigned char *pixels;
  12290 } stbtt__bitmap;
  12291 
  12292 /*  rasterize a shape with quadratic beziers into a bitmap */
  12293 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result,        /*  1-channel bitmap to draw into */
  12294                                float flatness_in_pixels,     /*  allowable error of curve in pixels */
  12295                                stbtt_vertex *vertices,       /*  array of vertices defining shape */
  12296                                int num_verts,                /*  number of vertices in above array */
  12297                                float scale_x, float scale_y, /*  scale applied to input vertices */
  12298                                float shift_x, float shift_y, /*  translation applied to input vertices */
  12299                                int x_off, int y_off,         /*  another translation applied to input */
  12300                                int invert,                   /*  if non-zero, vertically flip shape */
  12301                                void *userdata);              /*  context for to STBTT_MALLOC */
  12302 
  12303 /* //////////////////////////////////////////////////////////////////////////// */
  12304 /*  */
  12305 /*  Signed Distance Function (or Field) rendering */
  12306 
  12307 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
  12308 /*  frees the SDF bitmap allocated below */
  12309 
  12310 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
  12311 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
  12312 /*  These functions compute a discretized SDF field for a single character, suitable for storing */
  12313 /*  in a single-channel texture, sampling with bilinear filtering, and testing against */
  12314 /*  larger than some threshold to produce scalable fonts. */
  12315 /*         info              --  the font */
  12316 /*         scale             --  controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap */
  12317 /*         glyph/codepoint   --  the character to generate the SDF for */
  12318 /*         padding           --  extra "pixels" around the character which are filled with the distance to the character (not 0), */
  12319 /*                                  which allows effects like bit outlines */
  12320 /*         onedge_value      --  value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) */
  12321 /*         pixel_dist_scale  --  what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) */
  12322 /*                                  if positive, > onedge_value is inside; if negative, < onedge_value is inside */
  12323 /*         width,height      --  output height & width of the SDF bitmap (including padding) */
  12324 /*         xoff,yoff         --  output origin of the character */
  12325 /*         return value      --  a 2D array of bytes 0..255, width*height in size */
  12326 /*  */
  12327 /*  pixel_dist_scale & onedge_value are a scale & bias that allows you to make */
  12328 /*  optimal use of the limited 0..255 for your application, trading off precision */
  12329 /*  and special effects. SDF values outside the range 0..255 are clamped to 0..255. */
  12330 /*  */
  12331 /*  Example: */
  12332 /*       scale = stbtt_ScaleForPixelHeight(22) */
  12333 /*       padding = 5 */
  12334 /*       onedge_value = 180 */
  12335 /*       pixel_dist_scale = 180/5.0 = 36.0 */
  12336 /*  */
  12337 /*       This will create an SDF bitmap in which the character is about 22 pixels */
  12338 /*       high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled */
  12339 /*       shape, sample the SDF at each pixel and fill the pixel if the SDF value */
  12340 /*       is greater than or equal to 180/255. (You'll actually want to antialias, */
  12341 /*       which is beyond the scope of this example.) Additionally, you can compute */
  12342 /*       offset outlines (e.g. to stroke the character border inside & outside, */
  12343 /*       or only outside). For example, to fill outside the character up to 3 SDF */
  12344 /*       pixels, you would compare against (180-36.0*3)/255 = 72/255. The above */
  12345 /*       choice of variables maps a range from 5 pixels outside the shape to */
  12346 /*       2 pixels inside the shape to 0..255; this is intended primarily for apply */
  12347 /*       outside effects only (the interior range is needed to allow proper */
  12348 /*       antialiasing of the font at *smaller* sizes) */
  12349 /*  */
  12350 /*  The function computes the SDF analytically at each SDF pixel, not by e.g. */
  12351 /*  building a higher-res bitmap and approximating it. In theory the quality */
  12352 /*  should be as high as possible for an SDF of this size & representation, but */
  12353 /*  unclear if this is true in practice (perhaps building a higher-res bitmap */
  12354 /*  and computing from that can allow drop-out prevention). */
  12355 /*  */
  12356 /*  The algorithm has not been optimized at all, so expect it to be slow */
  12357 /*  if computing lots of characters or very large sizes. */
  12358 
  12359 
  12360 
  12361 /* //////////////////////////////////////////////////////////////////////////// */
  12362 /*  */
  12363 /*  Finding the right font... */
  12364 /*  */
  12365 /*  You should really just solve this offline, keep your own tables */
  12366 /*  of what font is what, and don't try to get it out of the .ttf file. */
  12367 /*  That's because getting it out of the .ttf file is really hard, because */
  12368 /*  the names in the file can appear in many possible encodings, in many */
  12369 /*  possible languages, and e.g. if you need a case-insensitive comparison, */
  12370 /*  the details of that depend on the encoding & language in a complex way */
  12371 /*  (actually underspecified in truetype, but also gigantic). */
  12372 /*  */
  12373 /*  But you can use the provided functions in two possible ways: */
  12374 /*      stbtt_FindMatchingFont() will use *case-sensitive* comparisons on */
  12375 /*              unicode-encoded names to try to find the font you want; */
  12376 /*              you can run this before calling stbtt_InitFont() */
  12377 /*  */
  12378 /*      stbtt_GetFontNameString() lets you get any of the various strings */
  12379 /*              from the file yourself and do your own comparisons on them. */
  12380 /*              You have to have called stbtt_InitFont() first. */
  12381 
  12382 
  12383 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
  12384 /*  returns the offset (not index) of the font that matches, or -1 if none */
  12385 /*    if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". */
  12386 /*    if you use any other flag, use a font name like "Arial"; this checks */
  12387 /*      the 'macStyle' header field; i don't know if fonts set this consistently */
  12388 #define STBTT_MACSTYLE_DONTCARE     0
  12389 #define STBTT_MACSTYLE_BOLD         1
  12390 #define STBTT_MACSTYLE_ITALIC       2
  12391 #define STBTT_MACSTYLE_UNDERSCORE   4
  12392 #define STBTT_MACSTYLE_NONE         8   /*  <= not same as 0, this makes us check the bitfield is 0 */
  12393 
  12394 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
  12395 /*  returns 1/0 whether the first string interpreted as utf8 is identical to */
  12396 /*  the second string interpreted as big-endian utf16... useful for strings from next func */
  12397 
  12398 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
  12399 /*  returns the string (which may be big-endian double byte, e.g. for unicode) */
  12400 /*  and puts the length in bytes in *length. */
  12401 /*  */
  12402 /*  some of the values for the IDs are below; for more see the truetype spec: */
  12403 /*      http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html */
  12404 /*      http://www.microsoft.com/typography/otspec/name.htm */
  12405 
  12406 enum { /*  platformID */
  12407    STBTT_PLATFORM_ID_UNICODE   =0,
  12408    STBTT_PLATFORM_ID_MAC       =1,
  12409    STBTT_PLATFORM_ID_ISO       =2,
  12410    STBTT_PLATFORM_ID_MICROSOFT =3
  12411 };
  12412 
  12413 enum { /*  encodingID for STBTT_PLATFORM_ID_UNICODE */
  12414    STBTT_UNICODE_EID_UNICODE_1_0    =0,
  12415    STBTT_UNICODE_EID_UNICODE_1_1    =1,
  12416    STBTT_UNICODE_EID_ISO_10646      =2,
  12417    STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
  12418    STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
  12419 };
  12420 
  12421 enum { /*  encodingID for STBTT_PLATFORM_ID_MICROSOFT */
  12422    STBTT_MS_EID_SYMBOL        =0,
  12423    STBTT_MS_EID_UNICODE_BMP   =1,
  12424    STBTT_MS_EID_SHIFTJIS      =2,
  12425    STBTT_MS_EID_UNICODE_FULL  =10
  12426 };
  12427 
  12428 enum { /*  encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes */
  12429    STBTT_MAC_EID_ROMAN        =0,   STBTT_MAC_EID_ARABIC       =4,
  12430    STBTT_MAC_EID_JAPANESE     =1,   STBTT_MAC_EID_HEBREW       =5,
  12431    STBTT_MAC_EID_CHINESE_TRAD =2,   STBTT_MAC_EID_GREEK        =6,
  12432    STBTT_MAC_EID_KOREAN       =3,   STBTT_MAC_EID_RUSSIAN      =7
  12433 };
  12434 
  12435 enum { /*  languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... */
  12436        /*  problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
  12437    STBTT_MS_LANG_ENGLISH     =0x0409,   STBTT_MS_LANG_ITALIAN     =0x0410,
  12438    STBTT_MS_LANG_CHINESE     =0x0804,   STBTT_MS_LANG_JAPANESE    =0x0411,
  12439    STBTT_MS_LANG_DUTCH       =0x0413,   STBTT_MS_LANG_KOREAN      =0x0412,
  12440    STBTT_MS_LANG_FRENCH      =0x040c,   STBTT_MS_LANG_RUSSIAN     =0x0419,
  12441    STBTT_MS_LANG_GERMAN      =0x0407,   STBTT_MS_LANG_SPANISH     =0x0409,
  12442    STBTT_MS_LANG_HEBREW      =0x040d,   STBTT_MS_LANG_SWEDISH     =0x041D
  12443 };
  12444 
  12445 enum { /*  languageID for STBTT_PLATFORM_ID_MAC */
  12446    STBTT_MAC_LANG_ENGLISH      =0 ,   STBTT_MAC_LANG_JAPANESE     =11,
  12447    STBTT_MAC_LANG_ARABIC       =12,   STBTT_MAC_LANG_KOREAN       =23,
  12448    STBTT_MAC_LANG_DUTCH        =4 ,   STBTT_MAC_LANG_RUSSIAN      =32,
  12449    STBTT_MAC_LANG_FRENCH       =1 ,   STBTT_MAC_LANG_SPANISH      =6 ,
  12450    STBTT_MAC_LANG_GERMAN       =2 ,   STBTT_MAC_LANG_SWEDISH      =5 ,
  12451    STBTT_MAC_LANG_HEBREW       =10,   STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
  12452    STBTT_MAC_LANG_ITALIAN      =3 ,   STBTT_MAC_LANG_CHINESE_TRAD =19
  12453 };
  12454 
  12455 #ifdef __cplusplus
  12456 }
  12457 #endif
  12458 
  12459 #endif /*  __STB_INCLUDE_STB_TRUETYPE_H__ */
  12460 
  12461 /* ///////////////////////////////////////////////////////////////////////////// */
  12462 /* ///////////////////////////////////////////////////////////////////////////// */
  12463 /* // */
  12464 /* //   IMPLEMENTATION */
  12465 /* // */
  12466 /* // */
  12467 
  12468 #ifdef STB_TRUETYPE_IMPLEMENTATION
  12469 
  12470 #ifndef STBTT_MAX_OVERSAMPLE
  12471 #define STBTT_MAX_OVERSAMPLE   8
  12472 #endif
  12473 
  12474 #if STBTT_MAX_OVERSAMPLE > 255
  12475 #error "STBTT_MAX_OVERSAMPLE cannot be > 255"
  12476 #endif
  12477 
  12478 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
  12479 
  12480 #ifndef STBTT_RASTERIZER_VERSION
  12481 #define STBTT_RASTERIZER_VERSION 2
  12482 #endif
  12483 
  12484 #ifdef _MSC_VER
  12485 #define STBTT__NOTUSED(v)  (void)(v)
  12486 #else
  12487 #define STBTT__NOTUSED(v)  (void)sizeof(v)
  12488 #endif
  12489 
  12490 /* //////////////////////////////////////////////////////////////////////// */
  12491 /*  */
  12492 /*  stbtt__buf helpers to parse data from file */
  12493 /*  */
  12494 
  12495 static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
  12496 {
  12497    if (b->cursor >= b->size)
  12498       return 0;
  12499    return b->data[b->cursor++];
  12500 }
  12501 
  12502 static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
  12503 {
  12504    if (b->cursor >= b->size)
  12505       return 0;
  12506    return b->data[b->cursor];
  12507 }
  12508 
  12509 static void stbtt__buf_seek(stbtt__buf *b, int o)
  12510 {
  12511    STBTT_assert(!(o > b->size || o < 0));
  12512    b->cursor = (o > b->size || o < 0) ? b->size : o;
  12513 }
  12514 
  12515 static void stbtt__buf_skip(stbtt__buf *b, int o)
  12516 {
  12517    stbtt__buf_seek(b, b->cursor + o);
  12518 }
  12519 
  12520 static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
  12521 {
  12522    stbtt_uint32 v = 0;
  12523    int i;
  12524    STBTT_assert(n >= 1 && n <= 4);
  12525    for (i = 0; i < n; i++)
  12526       v = (v << 8) | stbtt__buf_get8(b);
  12527    return v;
  12528 }
  12529 
  12530 static stbtt__buf stbtt__new_buf(const void *p, size_t size)
  12531 {
  12532    stbtt__buf r;
  12533    STBTT_assert(size < 0x40000000);
  12534    r.data = (stbtt_uint8*) p;
  12535    r.size = (int) size;
  12536    r.cursor = 0;
  12537    return r;
  12538 }
  12539 
  12540 #define stbtt__buf_get16(b)  stbtt__buf_get((b), 2)
  12541 #define stbtt__buf_get32(b)  stbtt__buf_get((b), 4)
  12542 
  12543 static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
  12544 {
  12545    stbtt__buf r = stbtt__new_buf(NULL, 0);
  12546    if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
  12547    r.data = b->data + o;
  12548    r.size = s;
  12549    return r;
  12550 }
  12551 
  12552 static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
  12553 {
  12554    int count, start, offsize;
  12555    start = b->cursor;
  12556    count = stbtt__buf_get16(b);
  12557    if (count) {
  12558       offsize = stbtt__buf_get8(b);
  12559       STBTT_assert(offsize >= 1 && offsize <= 4);
  12560       stbtt__buf_skip(b, offsize * count);
  12561       stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
  12562    }
  12563    return stbtt__buf_range(b, start, b->cursor - start);
  12564 }
  12565 
  12566 static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
  12567 {
  12568    int b0 = stbtt__buf_get8(b);
  12569    if (b0 >= 32 && b0 <= 246)       return b0 - 139;
  12570    else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
  12571    else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
  12572    else if (b0 == 28)               return stbtt__buf_get16(b);
  12573    else if (b0 == 29)               return stbtt__buf_get32(b);
  12574    STBTT_assert(0);
  12575    return 0;
  12576 }
  12577 
  12578 static void stbtt__cff_skip_operand(stbtt__buf *b) {
  12579    int v, b0 = stbtt__buf_peek8(b);
  12580    STBTT_assert(b0 >= 28);
  12581    if (b0 == 30) {
  12582       stbtt__buf_skip(b, 1);
  12583       while (b->cursor < b->size) {
  12584          v = stbtt__buf_get8(b);
  12585          if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
  12586             break;
  12587       }
  12588    } else {
  12589       stbtt__cff_int(b);
  12590    }
  12591 }
  12592 
  12593 static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
  12594 {
  12595    stbtt__buf_seek(b, 0);
  12596    while (b->cursor < b->size) {
  12597       int start = b->cursor, end, op;
  12598       while (stbtt__buf_peek8(b) >= 28)
  12599          stbtt__cff_skip_operand(b);
  12600       end = b->cursor;
  12601       op = stbtt__buf_get8(b);
  12602       if (op == 12)  op = stbtt__buf_get8(b) | 0x100;
  12603       if (op == key) return stbtt__buf_range(b, start, end-start);
  12604    }
  12605    return stbtt__buf_range(b, 0, 0);
  12606 }
  12607 
  12608 static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
  12609 {
  12610    int i;
  12611    stbtt__buf operands = stbtt__dict_get(b, key);
  12612    for (i = 0; i < outcount && operands.cursor < operands.size; i++)
  12613       out[i] = stbtt__cff_int(&operands);
  12614 }
  12615 
  12616 static int stbtt__cff_index_count(stbtt__buf *b)
  12617 {
  12618    stbtt__buf_seek(b, 0);
  12619    return stbtt__buf_get16(b);
  12620 }
  12621 
  12622 static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
  12623 {
  12624    int count, offsize, start, end;
  12625    stbtt__buf_seek(&b, 0);
  12626    count = stbtt__buf_get16(&b);
  12627    offsize = stbtt__buf_get8(&b);
  12628    STBTT_assert(i >= 0 && i < count);
  12629    STBTT_assert(offsize >= 1 && offsize <= 4);
  12630    stbtt__buf_skip(&b, i*offsize);
  12631    start = stbtt__buf_get(&b, offsize);
  12632    end = stbtt__buf_get(&b, offsize);
  12633    return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
  12634 }
  12635 
  12636 /* //////////////////////////////////////////////////////////////////////// */
  12637 /*  */
  12638 /*  accessors to parse data from file */
  12639 /*  */
  12640 
  12641 /*  on platforms that don't allow misaligned reads, if we want to allow */
  12642 /*  truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE */
  12643 
  12644 #define ttBYTE(p)     (* (stbtt_uint8 *) (p))
  12645 #define ttCHAR(p)     (* (stbtt_int8 *) (p))
  12646 #define ttFixed(p)    ttLONG(p)
  12647 
  12648 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
  12649 static stbtt_int16 ttSHORT(stbtt_uint8 *p)   { return p[0]*256 + p[1]; }
  12650 static stbtt_uint32 ttULONG(stbtt_uint8 *p)  { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
  12651 static stbtt_int32 ttLONG(stbtt_uint8 *p)    { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
  12652 
  12653 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
  12654 #define stbtt_tag(p,str)           stbtt_tag4(p,str[0],str[1],str[2],str[3])
  12655 
  12656 static int stbtt__isfont(stbtt_uint8 *font)
  12657 {
  12658    /*  check the version number */
  12659    if (stbtt_tag4(font, '1',0,0,0))  return 1; /*  TrueType 1 */
  12660    if (stbtt_tag(font, "typ1"))   return 1; /*  TrueType with type 1 font -- we don't support this! */
  12661    if (stbtt_tag(font, "OTTO"))   return 1; /*  OpenType with CFF */
  12662    if (stbtt_tag4(font, 0,1,0,0)) return 1; /*  OpenType 1.0 */
  12663    if (stbtt_tag(font, "true"))   return 1; /*  Apple specification for TrueType fonts */
  12664    return 0;
  12665 }
  12666 
  12667 /*  @OPTIMIZE: binary search */
  12668 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
  12669 {
  12670    stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
  12671    stbtt_uint32 tabledir = fontstart + 12;
  12672    stbtt_int32 i;
  12673    for (i=0; i < num_tables; ++i) {
  12674       stbtt_uint32 loc = tabledir + 16*i;
  12675       if (stbtt_tag(data+loc+0, tag))
  12676          return ttULONG(data+loc+8);
  12677    }
  12678    return 0;
  12679 }
  12680 
  12681 static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
  12682 {
  12683    /*  if it's just a font, there's only one valid index */
  12684    if (stbtt__isfont(font_collection))
  12685       return index == 0 ? 0 : -1;
  12686 
  12687    /*  check if it's a TTC */
  12688    if (stbtt_tag(font_collection, "ttcf")) {
  12689       /*  version 1? */
  12690       if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
  12691          stbtt_int32 n = ttLONG(font_collection+8);
  12692          if (index >= n)
  12693             return -1;
  12694          return ttULONG(font_collection+12+index*4);
  12695       }
  12696    }
  12697    return -1;
  12698 }
  12699 
  12700 static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
  12701 {
  12702    /*  if it's just a font, there's only one valid font */
  12703    if (stbtt__isfont(font_collection))
  12704       return 1;
  12705 
  12706    /*  check if it's a TTC */
  12707    if (stbtt_tag(font_collection, "ttcf")) {
  12708       /*  version 1? */
  12709       if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
  12710          return ttLONG(font_collection+8);
  12711       }
  12712    }
  12713    return 0;
  12714 }
  12715 
  12716 static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
  12717 {
  12718    stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
  12719    stbtt__buf pdict;
  12720    stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
  12721    if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
  12722    pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
  12723    stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
  12724    if (!subrsoff) return stbtt__new_buf(NULL, 0);
  12725    stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
  12726    return stbtt__cff_get_index(&cff);
  12727 }
  12728 
  12729 /*  since most people won't use this, find this table the first time it's needed */
  12730 static int stbtt__get_svg(stbtt_fontinfo *info)
  12731 {
  12732    stbtt_uint32 t;
  12733    if (info->svg < 0) {
  12734       t = stbtt__find_table(info->data, info->fontstart, "SVG ");
  12735       if (t) {
  12736          stbtt_uint32 offset = ttULONG(info->data + t + 2);
  12737          info->svg = t + offset;
  12738       } else {
  12739          info->svg = 0;
  12740       }
  12741    }
  12742    return info->svg;
  12743 }
  12744 
  12745 static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
  12746 {
  12747    stbtt_uint32 cmap, t;
  12748    stbtt_int32 i,numTables;
  12749 
  12750    info->data = data;
  12751    info->fontstart = fontstart;
  12752    info->cff = stbtt__new_buf(NULL, 0);
  12753 
  12754    cmap = stbtt__find_table(data, fontstart, "cmap");       /*  required */
  12755    info->loca = stbtt__find_table(data, fontstart, "loca"); /*  required */
  12756    info->head = stbtt__find_table(data, fontstart, "head"); /*  required */
  12757    info->glyf = stbtt__find_table(data, fontstart, "glyf"); /*  required */
  12758    info->hhea = stbtt__find_table(data, fontstart, "hhea"); /*  required */
  12759    info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); /*  required */
  12760    info->kern = stbtt__find_table(data, fontstart, "kern"); /*  not required */
  12761    info->gpos = stbtt__find_table(data, fontstart, "GPOS"); /*  not required */
  12762 
  12763    if (!cmap || !info->head || !info->hhea || !info->hmtx)
  12764       return 0;
  12765    if (info->glyf) {
  12766       /*  required for truetype */
  12767       if (!info->loca) return 0;
  12768    } else {
  12769       /*  initialization for CFF / Type2 fonts (OTF) */
  12770       stbtt__buf b, topdict, topdictidx;
  12771       stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
  12772       stbtt_uint32 cff;
  12773 
  12774       cff = stbtt__find_table(data, fontstart, "CFF ");
  12775       if (!cff) return 0;
  12776 
  12777       info->fontdicts = stbtt__new_buf(NULL, 0);
  12778       info->fdselect = stbtt__new_buf(NULL, 0);
  12779 
  12780       /*  @TODO this should use size from table (not 512MB) */
  12781       info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
  12782       b = info->cff;
  12783 
  12784       /*  read the header */
  12785       stbtt__buf_skip(&b, 2);
  12786       stbtt__buf_seek(&b, stbtt__buf_get8(&b)); /*  hdrsize */
  12787 
  12788       /*  @TODO the name INDEX could list multiple fonts, */
  12789       /*  but we just use the first one. */
  12790       stbtt__cff_get_index(&b);  /*  name INDEX */
  12791       topdictidx = stbtt__cff_get_index(&b);
  12792       topdict = stbtt__cff_index_get(topdictidx, 0);
  12793       stbtt__cff_get_index(&b);  /*  string INDEX */
  12794       info->gsubrs = stbtt__cff_get_index(&b);
  12795 
  12796       stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
  12797       stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
  12798       stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
  12799       stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
  12800       info->subrs = stbtt__get_subrs(b, topdict);
  12801 
  12802       /*  we only support Type 2 charstrings */
  12803       if (cstype != 2) return 0;
  12804       if (charstrings == 0) return 0;
  12805 
  12806       if (fdarrayoff) {
  12807          /*  looks like a CID font */
  12808          if (!fdselectoff) return 0;
  12809          stbtt__buf_seek(&b, fdarrayoff);
  12810          info->fontdicts = stbtt__cff_get_index(&b);
  12811          info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
  12812       }
  12813 
  12814       stbtt__buf_seek(&b, charstrings);
  12815       info->charstrings = stbtt__cff_get_index(&b);
  12816    }
  12817 
  12818    t = stbtt__find_table(data, fontstart, "maxp");
  12819    if (t)
  12820       info->numGlyphs = ttUSHORT(data+t+4);
  12821    else
  12822       info->numGlyphs = 0xffff;
  12823 
  12824    info->svg = -1;
  12825 
  12826    /*  find a cmap encoding table we understand *now* to avoid searching */
  12827    /*  later. (todo: could make this installable) */
  12828    /*  the same regardless of glyph. */
  12829    numTables = ttUSHORT(data + cmap + 2);
  12830    info->index_map = 0;
  12831    for (i=0; i < numTables; ++i) {
  12832       stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
  12833       /*  find an encoding we understand: */
  12834       switch(ttUSHORT(data+encoding_record)) {
  12835          case STBTT_PLATFORM_ID_MICROSOFT:
  12836             switch (ttUSHORT(data+encoding_record+2)) {
  12837                case STBTT_MS_EID_UNICODE_BMP:
  12838                case STBTT_MS_EID_UNICODE_FULL:
  12839                   /*  MS/Unicode */
  12840                   info->index_map = cmap + ttULONG(data+encoding_record+4);
  12841                   break;
  12842             }
  12843             break;
  12844         case STBTT_PLATFORM_ID_UNICODE:
  12845             /*  Mac/iOS has these */
  12846             /*  all the encodingIDs are unicode, so we don't bother to check it */
  12847             info->index_map = cmap + ttULONG(data+encoding_record+4);
  12848             break;
  12849       }
  12850    }
  12851    if (info->index_map == 0)
  12852       return 0;
  12853 
  12854    info->indexToLocFormat = ttUSHORT(data+info->head + 50);
  12855    return 1;
  12856 }
  12857 
  12858 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
  12859 {
  12860    stbtt_uint8 *data = info->data;
  12861    stbtt_uint32 index_map = info->index_map;
  12862 
  12863    stbtt_uint16 format = ttUSHORT(data + index_map + 0);
  12864    if (format == 0) { /*  apple byte encoding */
  12865       stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
  12866       if (unicode_codepoint < bytes-6)
  12867          return ttBYTE(data + index_map + 6 + unicode_codepoint);
  12868       return 0;
  12869    } else if (format == 6) {
  12870       stbtt_uint32 first = ttUSHORT(data + index_map + 6);
  12871       stbtt_uint32 count = ttUSHORT(data + index_map + 8);
  12872       if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
  12873          return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
  12874       return 0;
  12875    } else if (format == 2) {
  12876       STBTT_assert(0); /*  @TODO: high-byte mapping for japanese/chinese/korean */
  12877       return 0;
  12878    } else if (format == 4) { /*  standard mapping for windows fonts: binary search collection of ranges */
  12879       stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
  12880       stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
  12881       stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
  12882       stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
  12883 
  12884       /*  do a binary search of the segments */
  12885       stbtt_uint32 endCount = index_map + 14;
  12886       stbtt_uint32 search = endCount;
  12887 
  12888       if (unicode_codepoint > 0xffff)
  12889          return 0;
  12890 
  12891       /*  they lie from endCount .. endCount + segCount */
  12892       /*  but searchRange is the nearest power of two, so... */
  12893       if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
  12894          search += rangeShift*2;
  12895 
  12896       /*  now decrement to bias correctly to find smallest */
  12897       search -= 2;
  12898       while (entrySelector) {
  12899          stbtt_uint16 end;
  12900          searchRange >>= 1;
  12901          end = ttUSHORT(data + search + searchRange*2);
  12902          if (unicode_codepoint > end)
  12903             search += searchRange*2;
  12904          --entrySelector;
  12905       }
  12906       search += 2;
  12907 
  12908       {
  12909          stbtt_uint16 offset, start, last;
  12910          stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
  12911 
  12912          start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
  12913          last = ttUSHORT(data + endCount + 2*item);
  12914          if (unicode_codepoint < start || unicode_codepoint > last)
  12915             return 0;
  12916 
  12917          offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
  12918          if (offset == 0)
  12919             return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
  12920 
  12921          return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
  12922       }
  12923    } else if (format == 12 || format == 13) {
  12924       stbtt_uint32 ngroups = ttULONG(data+index_map+12);
  12925       stbtt_int32 low,high;
  12926       low = 0; high = (stbtt_int32)ngroups;
  12927       /*  Binary search the right group. */
  12928       while (low < high) {
  12929          stbtt_int32 mid = low + ((high-low) >> 1); /*  rounds down, so low <= mid < high */
  12930          stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
  12931          stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
  12932          if ((stbtt_uint32) unicode_codepoint < start_char)
  12933             high = mid;
  12934          else if ((stbtt_uint32) unicode_codepoint > end_char)
  12935             low = mid+1;
  12936          else {
  12937             stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
  12938             if (format == 12)
  12939                return start_glyph + unicode_codepoint-start_char;
  12940             else /*  format == 13 */
  12941                return start_glyph;
  12942          }
  12943       }
  12944       return 0; /*  not found */
  12945    }
  12946    /*  @TODO */
  12947    STBTT_assert(0);
  12948    return 0;
  12949 }
  12950 
  12951 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
  12952 {
  12953    return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
  12954 }
  12955 
  12956 static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
  12957 {
  12958    v->type = type;
  12959    v->x = (stbtt_int16) x;
  12960    v->y = (stbtt_int16) y;
  12961    v->cx = (stbtt_int16) cx;
  12962    v->cy = (stbtt_int16) cy;
  12963 }
  12964 
  12965 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
  12966 {
  12967    int g1,g2;
  12968 
  12969    STBTT_assert(!info->cff.size);
  12970 
  12971    if (glyph_index >= info->numGlyphs) return -1; /*  glyph index out of range */
  12972    if (info->indexToLocFormat >= 2)    return -1; /*  unknown index->glyph map format */
  12973 
  12974    if (info->indexToLocFormat == 0) {
  12975       g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
  12976       g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
  12977    } else {
  12978       g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
  12979       g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
  12980    }
  12981 
  12982    return g1==g2 ? -1 : g1; /*  if length is 0, return -1 */
  12983 }
  12984 
  12985 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
  12986 
  12987 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
  12988 {
  12989    if (info->cff.size) {
  12990       stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
  12991    } else {
  12992       int g = stbtt__GetGlyfOffset(info, glyph_index);
  12993       if (g < 0) return 0;
  12994 
  12995       if (x0) *x0 = ttSHORT(info->data + g + 2);
  12996       if (y0) *y0 = ttSHORT(info->data + g + 4);
  12997       if (x1) *x1 = ttSHORT(info->data + g + 6);
  12998       if (y1) *y1 = ttSHORT(info->data + g + 8);
  12999    }
  13000    return 1;
  13001 }
  13002 
  13003 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
  13004 {
  13005    return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
  13006 }
  13007 
  13008 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
  13009 {
  13010    stbtt_int16 numberOfContours;
  13011    int g;
  13012    if (info->cff.size)
  13013       return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
  13014    g = stbtt__GetGlyfOffset(info, glyph_index);
  13015    if (g < 0) return 1;
  13016    numberOfContours = ttSHORT(info->data + g);
  13017    return numberOfContours == 0;
  13018 }
  13019 
  13020 static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
  13021     stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
  13022 {
  13023    if (start_off) {
  13024       if (was_off)
  13025          stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
  13026       stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
  13027    } else {
  13028       if (was_off)
  13029          stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
  13030       else
  13031          stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
  13032    }
  13033    return num_vertices;
  13034 }
  13035 
  13036 static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
  13037 {
  13038    stbtt_int16 numberOfContours;
  13039    stbtt_uint8 *endPtsOfContours;
  13040    stbtt_uint8 *data = info->data;
  13041    stbtt_vertex *vertices=0;
  13042    int num_vertices=0;
  13043    int g = stbtt__GetGlyfOffset(info, glyph_index);
  13044 
  13045    *pvertices = NULL;
  13046 
  13047    if (g < 0) return 0;
  13048 
  13049    numberOfContours = ttSHORT(data + g);
  13050 
  13051    if (numberOfContours > 0) {
  13052       stbtt_uint8 flags=0,flagcount;
  13053       stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
  13054       stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
  13055       stbtt_uint8 *points;
  13056       endPtsOfContours = (data + g + 10);
  13057       ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
  13058       points = data + g + 10 + numberOfContours * 2 + 2 + ins;
  13059 
  13060       n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
  13061 
  13062       m = n + 2*numberOfContours;  /*  a loose bound on how many vertices we might need */
  13063       vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
  13064       if (vertices == 0)
  13065          return 0;
  13066 
  13067       next_move = 0;
  13068       flagcount=0;
  13069 
  13070       /*  in first pass, we load uninterpreted data into the allocated array */
  13071       /*  above, shifted to the end of the array so we won't overwrite it when */
  13072       /*  we create our final data starting from the front */
  13073 
  13074       off = m - n; /*  starting offset for uninterpreted data, regardless of how m ends up being calculated */
  13075 
  13076       /*  first load flags */
  13077 
  13078       for (i=0; i < n; ++i) {
  13079          if (flagcount == 0) {
  13080             flags = *points++;
  13081             if (flags & 8)
  13082                flagcount = *points++;
  13083          } else
  13084             --flagcount;
  13085          vertices[off+i].type = flags;
  13086       }
  13087 
  13088       /*  now load x coordinates */
  13089       x=0;
  13090       for (i=0; i < n; ++i) {
  13091          flags = vertices[off+i].type;
  13092          if (flags & 2) {
  13093             stbtt_int16 dx = *points++;
  13094             x += (flags & 16) ? dx : -dx; /*  ??? */
  13095          } else {
  13096             if (!(flags & 16)) {
  13097                x = x + (stbtt_int16) (points[0]*256 + points[1]);
  13098                points += 2;
  13099             }
  13100          }
  13101          vertices[off+i].x = (stbtt_int16) x;
  13102       }
  13103 
  13104       /*  now load y coordinates */
  13105       y=0;
  13106       for (i=0; i < n; ++i) {
  13107          flags = vertices[off+i].type;
  13108          if (flags & 4) {
  13109             stbtt_int16 dy = *points++;
  13110             y += (flags & 32) ? dy : -dy; /*  ??? */
  13111          } else {
  13112             if (!(flags & 32)) {
  13113                y = y + (stbtt_int16) (points[0]*256 + points[1]);
  13114                points += 2;
  13115             }
  13116          }
  13117          vertices[off+i].y = (stbtt_int16) y;
  13118       }
  13119 
  13120       /*  now convert them to our format */
  13121       num_vertices=0;
  13122       sx = sy = cx = cy = scx = scy = 0;
  13123       for (i=0; i < n; ++i) {
  13124          flags = vertices[off+i].type;
  13125          x     = (stbtt_int16) vertices[off+i].x;
  13126          y     = (stbtt_int16) vertices[off+i].y;
  13127 
  13128          if (next_move == i) {
  13129             if (i != 0)
  13130                num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
  13131 
  13132             /*  now start the new one */
  13133             start_off = !(flags & 1);
  13134             if (start_off) {
  13135                /*  if we start off with an off-curve point, then when we need to find a point on the curve */
  13136                /*  where we can start, and we need to save some state for when we wraparound. */
  13137                scx = x;
  13138                scy = y;
  13139                if (!(vertices[off+i+1].type & 1)) {
  13140                   /*  next point is also a curve point, so interpolate an on-point curve */
  13141                   sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
  13142                   sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
  13143                } else {
  13144                   /*  otherwise just use the next point as our start point */
  13145                   sx = (stbtt_int32) vertices[off+i+1].x;
  13146                   sy = (stbtt_int32) vertices[off+i+1].y;
  13147                   ++i; /*  we're using point i+1 as the starting point, so skip it */
  13148                }
  13149             } else {
  13150                sx = x;
  13151                sy = y;
  13152             }
  13153             stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
  13154             was_off = 0;
  13155             next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
  13156             ++j;
  13157          } else {
  13158             if (!(flags & 1)) { /*  if it's a curve */
  13159                if (was_off) /*  two off-curve control points in a row means interpolate an on-curve midpoint */
  13160                   stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
  13161                cx = x;
  13162                cy = y;
  13163                was_off = 1;
  13164             } else {
  13165                if (was_off)
  13166                   stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
  13167                else
  13168                   stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
  13169                was_off = 0;
  13170             }
  13171          }
  13172       }
  13173       num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
  13174    } else if (numberOfContours < 0) {
  13175       /*  Compound shapes. */
  13176       int more = 1;
  13177       stbtt_uint8 *comp = data + g + 10;
  13178       num_vertices = 0;
  13179       vertices = 0;
  13180       while (more) {
  13181          stbtt_uint16 flags, gidx;
  13182          int comp_num_verts = 0, i;
  13183          stbtt_vertex *comp_verts = 0, *tmp = 0;
  13184          float mtx[6] = {1,0,0,1,0,0}, m, n;
  13185 
  13186          flags = ttSHORT(comp); comp+=2;
  13187          gidx = ttSHORT(comp); comp+=2;
  13188 
  13189          if (flags & 2) { /*  XY values */
  13190             if (flags & 1) { /*  shorts */
  13191                mtx[4] = ttSHORT(comp); comp+=2;
  13192                mtx[5] = ttSHORT(comp); comp+=2;
  13193             } else {
  13194                mtx[4] = ttCHAR(comp); comp+=1;
  13195                mtx[5] = ttCHAR(comp); comp+=1;
  13196             }
  13197          }
  13198          else {
  13199             /*  @TODO handle matching point */
  13200             STBTT_assert(0);
  13201          }
  13202          if (flags & (1<<3)) { /*  WE_HAVE_A_SCALE */
  13203             mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
  13204             mtx[1] = mtx[2] = 0;
  13205          } else if (flags & (1<<6)) { /*  WE_HAVE_AN_X_AND_YSCALE */
  13206             mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
  13207             mtx[1] = mtx[2] = 0;
  13208             mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
  13209          } else if (flags & (1<<7)) { /*  WE_HAVE_A_TWO_BY_TWO */
  13210             mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
  13211             mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
  13212             mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
  13213             mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
  13214          }
  13215 
  13216          /*  Find transformation scales. */
  13217          m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
  13218          n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
  13219 
  13220          /*  Get indexed glyph. */
  13221          comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
  13222          if (comp_num_verts > 0) {
  13223             /*  Transform vertices. */
  13224             for (i = 0; i < comp_num_verts; ++i) {
  13225                stbtt_vertex* v = &comp_verts[i];
  13226                stbtt_vertex_type x,y;
  13227                x=v->x; y=v->y;
  13228                v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
  13229                v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
  13230                x=v->cx; y=v->cy;
  13231                v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
  13232                v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
  13233             }
  13234             /*  Append vertices. */
  13235             tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
  13236             if (!tmp) {
  13237                if (vertices) STBTT_free(vertices, info->userdata);
  13238                if (comp_verts) STBTT_free(comp_verts, info->userdata);
  13239                return 0;
  13240             }
  13241             if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
  13242             STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
  13243             if (vertices) STBTT_free(vertices, info->userdata);
  13244             vertices = tmp;
  13245             STBTT_free(comp_verts, info->userdata);
  13246             num_vertices += comp_num_verts;
  13247          }
  13248          /*  More components ? */
  13249          more = flags & (1<<5);
  13250       }
  13251    } else {
  13252       /*  numberOfCounters == 0, do nothing */
  13253    }
  13254 
  13255    *pvertices = vertices;
  13256    return num_vertices;
  13257 }
  13258 
  13259 typedef struct
  13260 {
  13261    int bounds;
  13262    int started;
  13263    float first_x, first_y;
  13264    float x, y;
  13265    stbtt_int32 min_x, max_x, min_y, max_y;
  13266 
  13267    stbtt_vertex *pvertices;
  13268    int num_vertices;
  13269 } stbtt__csctx;
  13270 
  13271 #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
  13272 
  13273 static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
  13274 {
  13275    if (x > c->max_x || !c->started) c->max_x = x;
  13276    if (y > c->max_y || !c->started) c->max_y = y;
  13277    if (x < c->min_x || !c->started) c->min_x = x;
  13278    if (y < c->min_y || !c->started) c->min_y = y;
  13279    c->started = 1;
  13280 }
  13281 
  13282 static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
  13283 {
  13284    if (c->bounds) {
  13285       stbtt__track_vertex(c, x, y);
  13286       if (type == STBTT_vcubic) {
  13287          stbtt__track_vertex(c, cx, cy);
  13288          stbtt__track_vertex(c, cx1, cy1);
  13289       }
  13290    } else {
  13291       stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
  13292       c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
  13293       c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
  13294    }
  13295    c->num_vertices++;
  13296 }
  13297 
  13298 static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
  13299 {
  13300    if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
  13301       stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
  13302 }
  13303 
  13304 static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
  13305 {
  13306    stbtt__csctx_close_shape(ctx);
  13307    ctx->first_x = ctx->x = ctx->x + dx;
  13308    ctx->first_y = ctx->y = ctx->y + dy;
  13309    stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
  13310 }
  13311 
  13312 static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
  13313 {
  13314    ctx->x += dx;
  13315    ctx->y += dy;
  13316    stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
  13317 }
  13318 
  13319 static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
  13320 {
  13321    float cx1 = ctx->x + dx1;
  13322    float cy1 = ctx->y + dy1;
  13323    float cx2 = cx1 + dx2;
  13324    float cy2 = cy1 + dy2;
  13325    ctx->x = cx2 + dx3;
  13326    ctx->y = cy2 + dy3;
  13327    stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
  13328 }
  13329 
  13330 static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
  13331 {
  13332    int count = stbtt__cff_index_count(&idx);
  13333    int bias = 107;
  13334    if (count >= 33900)
  13335       bias = 32768;
  13336    else if (count >= 1240)
  13337       bias = 1131;
  13338    n += bias;
  13339    if (n < 0 || n >= count)
  13340       return stbtt__new_buf(NULL, 0);
  13341    return stbtt__cff_index_get(idx, n);
  13342 }
  13343 
  13344 static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
  13345 {
  13346    stbtt__buf fdselect = info->fdselect;
  13347    int nranges, start, end, v, fmt, fdselector = -1, i;
  13348 
  13349    stbtt__buf_seek(&fdselect, 0);
  13350    fmt = stbtt__buf_get8(&fdselect);
  13351    if (fmt == 0) {
  13352       /*  untested */
  13353       stbtt__buf_skip(&fdselect, glyph_index);
  13354       fdselector = stbtt__buf_get8(&fdselect);
  13355    } else if (fmt == 3) {
  13356       nranges = stbtt__buf_get16(&fdselect);
  13357       start = stbtt__buf_get16(&fdselect);
  13358       for (i = 0; i < nranges; i++) {
  13359          v = stbtt__buf_get8(&fdselect);
  13360          end = stbtt__buf_get16(&fdselect);
  13361          if (glyph_index >= start && glyph_index < end) {
  13362             fdselector = v;
  13363             break;
  13364          }
  13365          start = end;
  13366       }
  13367    }
  13368    if (fdselector == -1) stbtt__new_buf(NULL, 0);
  13369    return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
  13370 }
  13371 
  13372 static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
  13373 {
  13374    int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
  13375    int has_subrs = 0, clear_stack;
  13376    float s[48];
  13377    stbtt__buf subr_stack[10], subrs = info->subrs, b;
  13378    float f;
  13379 
  13380 #define STBTT__CSERR(s) (0)
  13381 
  13382    /*  this currently ignores the initial width value, which isn't needed if we have hmtx */
  13383    b = stbtt__cff_index_get(info->charstrings, glyph_index);
  13384    while (b.cursor < b.size) {
  13385       i = 0;
  13386       clear_stack = 1;
  13387       b0 = stbtt__buf_get8(&b);
  13388       switch (b0) {
  13389       /*  @TODO implement hinting */
  13390       case 0x13: /*  hintmask */
  13391       case 0x14: /*  cntrmask */
  13392          if (in_header)
  13393             maskbits += (sp / 2); /*  implicit "vstem" */
  13394          in_header = 0;
  13395          stbtt__buf_skip(&b, (maskbits + 7) / 8);
  13396          break;
  13397 
  13398       case 0x01: /*  hstem */
  13399       case 0x03: /*  vstem */
  13400       case 0x12: /*  hstemhm */
  13401       case 0x17: /*  vstemhm */
  13402          maskbits += (sp / 2);
  13403          break;
  13404 
  13405       case 0x15: /*  rmoveto */
  13406          in_header = 0;
  13407          if (sp < 2) return STBTT__CSERR("rmoveto stack");
  13408          stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
  13409          break;
  13410       case 0x04: /*  vmoveto */
  13411          in_header = 0;
  13412          if (sp < 1) return STBTT__CSERR("vmoveto stack");
  13413          stbtt__csctx_rmove_to(c, 0, s[sp-1]);
  13414          break;
  13415       case 0x16: /*  hmoveto */
  13416          in_header = 0;
  13417          if (sp < 1) return STBTT__CSERR("hmoveto stack");
  13418          stbtt__csctx_rmove_to(c, s[sp-1], 0);
  13419          break;
  13420 
  13421       case 0x05: /*  rlineto */
  13422          if (sp < 2) return STBTT__CSERR("rlineto stack");
  13423          for (; i + 1 < sp; i += 2)
  13424             stbtt__csctx_rline_to(c, s[i], s[i+1]);
  13425          break;
  13426 
  13427       /*  hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical */
  13428       /*  starting from a different place. */
  13429 
  13430       case 0x07: /*  vlineto */
  13431          if (sp < 1) return STBTT__CSERR("vlineto stack");
  13432          goto vlineto;
  13433       case 0x06: /*  hlineto */
  13434          if (sp < 1) return STBTT__CSERR("hlineto stack");
  13435          for (;;) {
  13436             if (i >= sp) break;
  13437             stbtt__csctx_rline_to(c, s[i], 0);
  13438             i++;
  13439       vlineto:
  13440             if (i >= sp) break;
  13441             stbtt__csctx_rline_to(c, 0, s[i]);
  13442             i++;
  13443          }
  13444          break;
  13445 
  13446       case 0x1F: /*  hvcurveto */
  13447          if (sp < 4) return STBTT__CSERR("hvcurveto stack");
  13448          goto hvcurveto;
  13449       case 0x1E: /*  vhcurveto */
  13450          if (sp < 4) return STBTT__CSERR("vhcurveto stack");
  13451          for (;;) {
  13452             if (i + 3 >= sp) break;
  13453             stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
  13454             i += 4;
  13455       hvcurveto:
  13456             if (i + 3 >= sp) break;
  13457             stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
  13458             i += 4;
  13459          }
  13460          break;
  13461 
  13462       case 0x08: /*  rrcurveto */
  13463          if (sp < 6) return STBTT__CSERR("rcurveline stack");
  13464          for (; i + 5 < sp; i += 6)
  13465             stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
  13466          break;
  13467 
  13468       case 0x18: /*  rcurveline */
  13469          if (sp < 8) return STBTT__CSERR("rcurveline stack");
  13470          for (; i + 5 < sp - 2; i += 6)
  13471             stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
  13472          if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
  13473          stbtt__csctx_rline_to(c, s[i], s[i+1]);
  13474          break;
  13475 
  13476       case 0x19: /*  rlinecurve */
  13477          if (sp < 8) return STBTT__CSERR("rlinecurve stack");
  13478          for (; i + 1 < sp - 6; i += 2)
  13479             stbtt__csctx_rline_to(c, s[i], s[i+1]);
  13480          if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
  13481          stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
  13482          break;
  13483 
  13484       case 0x1A: /*  vvcurveto */
  13485       case 0x1B: /*  hhcurveto */
  13486          if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
  13487          f = 0.0;
  13488          if (sp & 1) { f = s[i]; i++; }
  13489          for (; i + 3 < sp; i += 4) {
  13490             if (b0 == 0x1B)
  13491                stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
  13492             else
  13493                stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
  13494             f = 0.0;
  13495          }
  13496          break;
  13497 
  13498       case 0x0A: /*  callsubr */
  13499          if (!has_subrs) {
  13500             if (info->fdselect.size)
  13501                subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
  13502             has_subrs = 1;
  13503          }
  13504          /*  FALLTHROUGH */
  13505       case 0x1D: /*  callgsubr */
  13506          if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
  13507          v = (int) s[--sp];
  13508          if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
  13509          subr_stack[subr_stack_height++] = b;
  13510          b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
  13511          if (b.size == 0) return STBTT__CSERR("subr not found");
  13512          b.cursor = 0;
  13513          clear_stack = 0;
  13514          break;
  13515 
  13516       case 0x0B: /*  return */
  13517          if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
  13518          b = subr_stack[--subr_stack_height];
  13519          clear_stack = 0;
  13520          break;
  13521 
  13522       case 0x0E: /*  endchar */
  13523          stbtt__csctx_close_shape(c);
  13524          return 1;
  13525 
  13526       case 0x0C: { /*  two-byte escape */
  13527          float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
  13528          float dx, dy;
  13529          int b1 = stbtt__buf_get8(&b);
  13530          switch (b1) {
  13531          /*  @TODO These "flex" implementations ignore the flex-depth and resolution, */
  13532          /*  and always draw beziers. */
  13533          case 0x22: /*  hflex */
  13534             if (sp < 7) return STBTT__CSERR("hflex stack");
  13535             dx1 = s[0];
  13536             dx2 = s[1];
  13537             dy2 = s[2];
  13538             dx3 = s[3];
  13539             dx4 = s[4];
  13540             dx5 = s[5];
  13541             dx6 = s[6];
  13542             stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
  13543             stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
  13544             break;
  13545 
  13546          case 0x23: /*  flex */
  13547             if (sp < 13) return STBTT__CSERR("flex stack");
  13548             dx1 = s[0];
  13549             dy1 = s[1];
  13550             dx2 = s[2];
  13551             dy2 = s[3];
  13552             dx3 = s[4];
  13553             dy3 = s[5];
  13554             dx4 = s[6];
  13555             dy4 = s[7];
  13556             dx5 = s[8];
  13557             dy5 = s[9];
  13558             dx6 = s[10];
  13559             dy6 = s[11];
  13560             /* fd is s[12] */
  13561             stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
  13562             stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
  13563             break;
  13564 
  13565          case 0x24: /*  hflex1 */
  13566             if (sp < 9) return STBTT__CSERR("hflex1 stack");
  13567             dx1 = s[0];
  13568             dy1 = s[1];
  13569             dx2 = s[2];
  13570             dy2 = s[3];
  13571             dx3 = s[4];
  13572             dx4 = s[5];
  13573             dx5 = s[6];
  13574             dy5 = s[7];
  13575             dx6 = s[8];
  13576             stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
  13577             stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
  13578             break;
  13579 
  13580          case 0x25: /*  flex1 */
  13581             if (sp < 11) return STBTT__CSERR("flex1 stack");
  13582             dx1 = s[0];
  13583             dy1 = s[1];
  13584             dx2 = s[2];
  13585             dy2 = s[3];
  13586             dx3 = s[4];
  13587             dy3 = s[5];
  13588             dx4 = s[6];
  13589             dy4 = s[7];
  13590             dx5 = s[8];
  13591             dy5 = s[9];
  13592             dx6 = dy6 = s[10];
  13593             dx = dx1+dx2+dx3+dx4+dx5;
  13594             dy = dy1+dy2+dy3+dy4+dy5;
  13595             if (STBTT_fabs(dx) > STBTT_fabs(dy))
  13596                dy6 = -dy;
  13597             else
  13598                dx6 = -dx;
  13599             stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
  13600             stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
  13601             break;
  13602 
  13603          default:
  13604             return STBTT__CSERR("unimplemented");
  13605          }
  13606       } break;
  13607 
  13608       default:
  13609          if (b0 != 255 && b0 != 28 && b0 < 32)
  13610             return STBTT__CSERR("reserved operator");
  13611 
  13612          /*  push immediate */
  13613          if (b0 == 255) {
  13614             f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
  13615          } else {
  13616             stbtt__buf_skip(&b, -1);
  13617             f = (float)(stbtt_int16)stbtt__cff_int(&b);
  13618          }
  13619          if (sp >= 48) return STBTT__CSERR("push stack overflow");
  13620          s[sp++] = f;
  13621          clear_stack = 0;
  13622          break;
  13623       }
  13624       if (clear_stack) sp = 0;
  13625    }
  13626    return STBTT__CSERR("no endchar");
  13627 
  13628 #undef STBTT__CSERR
  13629 }
  13630 
  13631 static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
  13632 {
  13633    /*  runs the charstring twice, once to count and once to output (to avoid realloc) */
  13634    stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
  13635    stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
  13636    if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
  13637       *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
  13638       output_ctx.pvertices = *pvertices;
  13639       if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
  13640          STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
  13641          return output_ctx.num_vertices;
  13642       }
  13643    }
  13644    *pvertices = NULL;
  13645    return 0;
  13646 }
  13647 
  13648 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
  13649 {
  13650    stbtt__csctx c = STBTT__CSCTX_INIT(1);
  13651    int r = stbtt__run_charstring(info, glyph_index, &c);
  13652    if (x0)  *x0 = r ? c.min_x : 0;
  13653    if (y0)  *y0 = r ? c.min_y : 0;
  13654    if (x1)  *x1 = r ? c.max_x : 0;
  13655    if (y1)  *y1 = r ? c.max_y : 0;
  13656    return r ? c.num_vertices : 0;
  13657 }
  13658 
  13659 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
  13660 {
  13661    if (!info->cff.size)
  13662       return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
  13663    else
  13664       return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
  13665 }
  13666 
  13667 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
  13668 {
  13669    stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
  13670    if (glyph_index < numOfLongHorMetrics) {
  13671       if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*glyph_index);
  13672       if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
  13673    } else {
  13674       if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
  13675       if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
  13676    }
  13677 }
  13678 
  13679 STBTT_DEF int  stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
  13680 {
  13681    stbtt_uint8 *data = info->data + info->kern;
  13682 
  13683    /*  we only look at the first table. it must be 'horizontal' and format 0. */
  13684    if (!info->kern)
  13685       return 0;
  13686    if (ttUSHORT(data+2) < 1) /*  number of tables, need at least 1 */
  13687       return 0;
  13688    if (ttUSHORT(data+8) != 1) /*  horizontal flag must be set in format */
  13689       return 0;
  13690 
  13691    return ttUSHORT(data+10);
  13692 }
  13693 
  13694 STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
  13695 {
  13696    stbtt_uint8 *data = info->data + info->kern;
  13697    int k, length;
  13698 
  13699    /*  we only look at the first table. it must be 'horizontal' and format 0. */
  13700    if (!info->kern)
  13701       return 0;
  13702    if (ttUSHORT(data+2) < 1) /*  number of tables, need at least 1 */
  13703       return 0;
  13704    if (ttUSHORT(data+8) != 1) /*  horizontal flag must be set in format */
  13705       return 0;
  13706 
  13707    length = ttUSHORT(data+10);
  13708    if (table_length < length)
  13709       length = table_length;
  13710 
  13711    for (k = 0; k < length; k++)
  13712    {
  13713       table[k].glyph1 = ttUSHORT(data+18+(k*6));
  13714       table[k].glyph2 = ttUSHORT(data+20+(k*6));
  13715       table[k].advance = ttSHORT(data+22+(k*6));
  13716    }
  13717 
  13718    return length;
  13719 }
  13720 
  13721 static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
  13722 {
  13723    stbtt_uint8 *data = info->data + info->kern;
  13724    stbtt_uint32 needle, straw;
  13725    int l, r, m;
  13726 
  13727    /*  we only look at the first table. it must be 'horizontal' and format 0. */
  13728    if (!info->kern)
  13729       return 0;
  13730    if (ttUSHORT(data+2) < 1) /*  number of tables, need at least 1 */
  13731       return 0;
  13732    if (ttUSHORT(data+8) != 1) /*  horizontal flag must be set in format */
  13733       return 0;
  13734 
  13735    l = 0;
  13736    r = ttUSHORT(data+10) - 1;
  13737    needle = glyph1 << 16 | glyph2;
  13738    while (l <= r) {
  13739       m = (l + r) >> 1;
  13740       straw = ttULONG(data+18+(m*6)); /*  note: unaligned read */
  13741       if (needle < straw)
  13742          r = m - 1;
  13743       else if (needle > straw)
  13744          l = m + 1;
  13745       else
  13746          return ttSHORT(data+22+(m*6));
  13747    }
  13748    return 0;
  13749 }
  13750 
  13751 static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
  13752 {
  13753    stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
  13754    switch (coverageFormat) {
  13755       case 1: {
  13756          stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
  13757 
  13758          /*  Binary search. */
  13759          stbtt_int32 l=0, r=glyphCount-1, m;
  13760          int straw, needle=glyph;
  13761          while (l <= r) {
  13762             stbtt_uint8 *glyphArray = coverageTable + 4;
  13763             stbtt_uint16 glyphID;
  13764             m = (l + r) >> 1;
  13765             glyphID = ttUSHORT(glyphArray + 2 * m);
  13766             straw = glyphID;
  13767             if (needle < straw)
  13768                r = m - 1;
  13769             else if (needle > straw)
  13770                l = m + 1;
  13771             else {
  13772                return m;
  13773             }
  13774          }
  13775          break;
  13776       }
  13777 
  13778       case 2: {
  13779          stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
  13780          stbtt_uint8 *rangeArray = coverageTable + 4;
  13781 
  13782          /*  Binary search. */
  13783          stbtt_int32 l=0, r=rangeCount-1, m;
  13784          int strawStart, strawEnd, needle=glyph;
  13785          while (l <= r) {
  13786             stbtt_uint8 *rangeRecord;
  13787             m = (l + r) >> 1;
  13788             rangeRecord = rangeArray + 6 * m;
  13789             strawStart = ttUSHORT(rangeRecord);
  13790             strawEnd = ttUSHORT(rangeRecord + 2);
  13791             if (needle < strawStart)
  13792                r = m - 1;
  13793             else if (needle > strawEnd)
  13794                l = m + 1;
  13795             else {
  13796                stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
  13797                return startCoverageIndex + glyph - strawStart;
  13798             }
  13799          }
  13800          break;
  13801       }
  13802 
  13803       default: return -1; /*  unsupported */
  13804    }
  13805 
  13806    return -1;
  13807 }
  13808 
  13809 static stbtt_int32  stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
  13810 {
  13811    stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
  13812    switch (classDefFormat)
  13813    {
  13814       case 1: {
  13815          stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
  13816          stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
  13817          stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
  13818 
  13819          if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
  13820             return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
  13821          break;
  13822       }
  13823 
  13824       case 2: {
  13825          stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
  13826          stbtt_uint8 *classRangeRecords = classDefTable + 4;
  13827 
  13828          /*  Binary search. */
  13829          stbtt_int32 l=0, r=classRangeCount-1, m;
  13830          int strawStart, strawEnd, needle=glyph;
  13831          while (l <= r) {
  13832             stbtt_uint8 *classRangeRecord;
  13833             m = (l + r) >> 1;
  13834             classRangeRecord = classRangeRecords + 6 * m;
  13835             strawStart = ttUSHORT(classRangeRecord);
  13836             strawEnd = ttUSHORT(classRangeRecord + 2);
  13837             if (needle < strawStart)
  13838                r = m - 1;
  13839             else if (needle > strawEnd)
  13840                l = m + 1;
  13841             else
  13842                return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
  13843          }
  13844          break;
  13845       }
  13846 
  13847       default:
  13848          return -1; /*  Unsupported definition type, return an error. */
  13849    }
  13850 
  13851    /*  "All glyphs not assigned to a class fall into class 0". (OpenType spec) */
  13852    return 0;
  13853 }
  13854 
  13855 /*  Define to STBTT_assert(x) if you want to break on unimplemented formats. */
  13856 #define STBTT_GPOS_TODO_assert(x)
  13857 
  13858 static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
  13859 {
  13860    stbtt_uint16 lookupListOffset;
  13861    stbtt_uint8 *lookupList;
  13862    stbtt_uint16 lookupCount;
  13863    stbtt_uint8 *data;
  13864    stbtt_int32 i, sti;
  13865 
  13866    if (!info->gpos) return 0;
  13867 
  13868    data = info->data + info->gpos;
  13869 
  13870    if (ttUSHORT(data+0) != 1) return 0; /*  Major version 1 */
  13871    if (ttUSHORT(data+2) != 0) return 0; /*  Minor version 0 */
  13872 
  13873    lookupListOffset = ttUSHORT(data+8);
  13874    lookupList = data + lookupListOffset;
  13875    lookupCount = ttUSHORT(lookupList);
  13876 
  13877    for (i=0; i<lookupCount; ++i) {
  13878       stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
  13879       stbtt_uint8 *lookupTable = lookupList + lookupOffset;
  13880 
  13881       stbtt_uint16 lookupType = ttUSHORT(lookupTable);
  13882       stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
  13883       stbtt_uint8 *subTableOffsets = lookupTable + 6;
  13884       if (lookupType != 2) /*  Pair Adjustment Positioning Subtable */
  13885          continue;
  13886 
  13887       for (sti=0; sti<subTableCount; sti++) {
  13888          stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
  13889          stbtt_uint8 *table = lookupTable + subtableOffset;
  13890          stbtt_uint16 posFormat = ttUSHORT(table);
  13891          stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
  13892          stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
  13893          if (coverageIndex == -1) continue;
  13894 
  13895          switch (posFormat) {
  13896             case 1: {
  13897                stbtt_int32 l, r, m;
  13898                int straw, needle;
  13899                stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
  13900                stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
  13901                if (valueFormat1 == 4 && valueFormat2 == 0) { /*  Support more formats? */
  13902                   stbtt_int32 valueRecordPairSizeInBytes = 2;
  13903                   stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
  13904                   stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
  13905                   stbtt_uint8 *pairValueTable = table + pairPosOffset;
  13906                   stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
  13907                   stbtt_uint8 *pairValueArray = pairValueTable + 2;
  13908 
  13909                   if (coverageIndex >= pairSetCount) return 0;
  13910 
  13911                   needle=glyph2;
  13912                   r=pairValueCount-1;
  13913                   l=0;
  13914 
  13915                   /*  Binary search. */
  13916                   while (l <= r) {
  13917                      stbtt_uint16 secondGlyph;
  13918                      stbtt_uint8 *pairValue;
  13919                      m = (l + r) >> 1;
  13920                      pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
  13921                      secondGlyph = ttUSHORT(pairValue);
  13922                      straw = secondGlyph;
  13923                      if (needle < straw)
  13924                         r = m - 1;
  13925                      else if (needle > straw)
  13926                         l = m + 1;
  13927                      else {
  13928                         stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
  13929                         return xAdvance;
  13930                      }
  13931                   }
  13932                } else
  13933                   return 0;
  13934                break;
  13935             }
  13936 
  13937             case 2: {
  13938                stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
  13939                stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
  13940                if (valueFormat1 == 4 && valueFormat2 == 0) { /*  Support more formats? */
  13941                   stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
  13942                   stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
  13943                   int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
  13944                   int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
  13945 
  13946                   stbtt_uint16 class1Count = ttUSHORT(table + 12);
  13947                   stbtt_uint16 class2Count = ttUSHORT(table + 14);
  13948                   stbtt_uint8 *class1Records, *class2Records;
  13949                   stbtt_int16 xAdvance;
  13950 
  13951                   if (glyph1class < 0 || glyph1class >= class1Count) return 0; /*  malformed */
  13952                   if (glyph2class < 0 || glyph2class >= class2Count) return 0; /*  malformed */
  13953 
  13954                   class1Records = table + 16;
  13955                   class2Records = class1Records + 2 * (glyph1class * class2Count);
  13956                   xAdvance = ttSHORT(class2Records + 2 * glyph2class);
  13957                   return xAdvance;
  13958                } else
  13959                   return 0;
  13960                break;
  13961             }
  13962 
  13963             default:
  13964                return 0; /*  Unsupported position format */
  13965          }
  13966       }
  13967    }
  13968 
  13969    return 0;
  13970 }
  13971 
  13972 STBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
  13973 {
  13974    int xAdvance = 0;
  13975 
  13976    if (info->gpos)
  13977       xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
  13978    else if (info->kern)
  13979       xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
  13980 
  13981    return xAdvance;
  13982 }
  13983 
  13984 STBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
  13985 {
  13986    if (!info->kern && !info->gpos) /*  if no kerning table, don't waste time looking up both codepoint->glyphs */
  13987       return 0;
  13988    return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
  13989 }
  13990 
  13991 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
  13992 {
  13993    stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
  13994 }
  13995 
  13996 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
  13997 {
  13998    if (ascent ) *ascent  = ttSHORT(info->data+info->hhea + 4);
  13999    if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
  14000    if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
  14001 }
  14002 
  14003 STBTT_DEF int  stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
  14004 {
  14005    int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
  14006    if (!tab)
  14007       return 0;
  14008    if (typoAscent ) *typoAscent  = ttSHORT(info->data+tab + 68);
  14009    if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
  14010    if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
  14011    return 1;
  14012 }
  14013 
  14014 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
  14015 {
  14016    *x0 = ttSHORT(info->data + info->head + 36);
  14017    *y0 = ttSHORT(info->data + info->head + 38);
  14018    *x1 = ttSHORT(info->data + info->head + 40);
  14019    *y1 = ttSHORT(info->data + info->head + 42);
  14020 }
  14021 
  14022 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
  14023 {
  14024    int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
  14025    return (float) height / fheight;
  14026 }
  14027 
  14028 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
  14029 {
  14030    int unitsPerEm = ttUSHORT(info->data + info->head + 18);
  14031    return pixels / unitsPerEm;
  14032 }
  14033 
  14034 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
  14035 {
  14036    STBTT_free(v, info->userdata);
  14037 }
  14038 
  14039 STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
  14040 {
  14041    int i;
  14042    stbtt_uint8 *data = info->data;
  14043    stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
  14044 
  14045    int numEntries = ttUSHORT(svg_doc_list);
  14046    stbtt_uint8 *svg_docs = svg_doc_list + 2;
  14047 
  14048    for(i=0; i<numEntries; i++) {
  14049       stbtt_uint8 *svg_doc = svg_docs + (12 * i);
  14050       if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
  14051          return svg_doc;
  14052    }
  14053    return 0;
  14054 }
  14055 
  14056 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
  14057 {
  14058    stbtt_uint8 *data = info->data;
  14059    stbtt_uint8 *svg_doc;
  14060 
  14061    if (info->svg == 0)
  14062       return 0;
  14063 
  14064    svg_doc = stbtt_FindSVGDoc(info, gl);
  14065    if (svg_doc != NULL) {
  14066       *svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
  14067       return ttULONG(svg_doc + 8);
  14068    } else {
  14069       return 0;
  14070    }
  14071 }
  14072 
  14073 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
  14074 {
  14075    return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
  14076 }
  14077 
  14078 /* //////////////////////////////////////////////////////////////////////////// */
  14079 /*  */
  14080 /*  antialiasing software rasterizer */
  14081 /*  */
  14082 
  14083 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
  14084 {
  14085    int x0=0,y0=0,x1,y1; /*  =0 suppresses compiler warning */
  14086    if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
  14087       /*  e.g. space character */
  14088       if (ix0) *ix0 = 0;
  14089       if (iy0) *iy0 = 0;
  14090       if (ix1) *ix1 = 0;
  14091       if (iy1) *iy1 = 0;
  14092    } else {
  14093       /*  move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
  14094       if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
  14095       if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
  14096       if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
  14097       if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
  14098    }
  14099 }
  14100 
  14101 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
  14102 {
  14103    stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
  14104 }
  14105 
  14106 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
  14107 {
  14108    stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
  14109 }
  14110 
  14111 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
  14112 {
  14113    stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
  14114 }
  14115 
  14116 /* //////////////////////////////////////////////////////////////////////////// */
  14117 /*  */
  14118 /*   Rasterizer */
  14119 
  14120 typedef struct stbtt__hheap_chunk
  14121 {
  14122    struct stbtt__hheap_chunk *next;
  14123 } stbtt__hheap_chunk;
  14124 
  14125 typedef struct stbtt__hheap
  14126 {
  14127    struct stbtt__hheap_chunk *head;
  14128    void   *first_free;
  14129    int    num_remaining_in_head_chunk;
  14130 } stbtt__hheap;
  14131 
  14132 static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
  14133 {
  14134    if (hh->first_free) {
  14135       void *p = hh->first_free;
  14136       hh->first_free = * (void **) p;
  14137       return p;
  14138    } else {
  14139       if (hh->num_remaining_in_head_chunk == 0) {
  14140          int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
  14141          stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
  14142          if (c == NULL)
  14143             return NULL;
  14144          c->next = hh->head;
  14145          hh->head = c;
  14146          hh->num_remaining_in_head_chunk = count;
  14147       }
  14148       --hh->num_remaining_in_head_chunk;
  14149       return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
  14150    }
  14151 }
  14152 
  14153 static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
  14154 {
  14155    *(void **) p = hh->first_free;
  14156    hh->first_free = p;
  14157 }
  14158 
  14159 static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
  14160 {
  14161    stbtt__hheap_chunk *c = hh->head;
  14162    while (c) {
  14163       stbtt__hheap_chunk *n = c->next;
  14164       STBTT_free(c, userdata);
  14165       c = n;
  14166    }
  14167 }
  14168 
  14169 typedef struct stbtt__edge {
  14170    float x0,y0, x1,y1;
  14171    int invert;
  14172 } stbtt__edge;
  14173 
  14174 
  14175 typedef struct stbtt__active_edge
  14176 {
  14177    struct stbtt__active_edge *next;
  14178    #if STBTT_RASTERIZER_VERSION==1
  14179    int x,dx;
  14180    float ey;
  14181    int direction;
  14182    #elif STBTT_RASTERIZER_VERSION==2
  14183    float fx,fdx,fdy;
  14184    float direction;
  14185    float sy;
  14186    float ey;
  14187    #else
  14188    #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
  14189    #endif
  14190 } stbtt__active_edge;
  14191 
  14192 #if STBTT_RASTERIZER_VERSION == 1
  14193 #define STBTT_FIXSHIFT   10
  14194 #define STBTT_FIX        (1 << STBTT_FIXSHIFT)
  14195 #define STBTT_FIXMASK    (STBTT_FIX-1)
  14196 
  14197 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
  14198 {
  14199    stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
  14200    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
  14201    STBTT_assert(z != NULL);
  14202    if (!z) return z;
  14203 
  14204    /*  round dx down to avoid overshooting */
  14205    if (dxdy < 0)
  14206       z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
  14207    else
  14208       z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
  14209 
  14210    z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); /*  use z->dx so when we offset later it's by the same amount */
  14211    z->x -= off_x * STBTT_FIX;
  14212 
  14213    z->ey = e->y1;
  14214    z->next = 0;
  14215    z->direction = e->invert ? 1 : -1;
  14216    return z;
  14217 }
  14218 #elif STBTT_RASTERIZER_VERSION == 2
  14219 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
  14220 {
  14221    stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
  14222    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
  14223    STBTT_assert(z != NULL);
  14224    /* STBTT_assert(e->y0 <= start_point); */
  14225    if (!z) return z;
  14226    z->fdx = dxdy;
  14227    z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
  14228    z->fx = e->x0 + dxdy * (start_point - e->y0);
  14229    z->fx -= off_x;
  14230    z->direction = e->invert ? 1.0f : -1.0f;
  14231    z->sy = e->y0;
  14232    z->ey = e->y1;
  14233    z->next = 0;
  14234    return z;
  14235 }
  14236 #else
  14237 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
  14238 #endif
  14239 
  14240 #if STBTT_RASTERIZER_VERSION == 1
  14241 /*  note: this routine clips fills that extend off the edges... ideally this */
  14242 /*  wouldn't happen, but it could happen if the truetype glyph bounding boxes */
  14243 /*  are wrong, or if the user supplies a too-small bitmap */
  14244 static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
  14245 {
  14246    /*  non-zero winding fill */
  14247    int x0=0, w=0;
  14248 
  14249    while (e) {
  14250       if (w == 0) {
  14251          /*  if we're currently at zero, we need to record the edge start point */
  14252          x0 = e->x; w += e->direction;
  14253       } else {
  14254          int x1 = e->x; w += e->direction;
  14255          /*  if we went to zero, we need to draw */
  14256          if (w == 0) {
  14257             int i = x0 >> STBTT_FIXSHIFT;
  14258             int j = x1 >> STBTT_FIXSHIFT;
  14259 
  14260             if (i < len && j >= 0) {
  14261                if (i == j) {
  14262                   /*  x0,x1 are the same pixel, so compute combined coverage */
  14263                   scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
  14264                } else {
  14265                   if (i >= 0) /*  add antialiasing for x0 */
  14266                      scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
  14267                   else
  14268                      i = -1; /*  clip */
  14269 
  14270                   if (j < len) /*  add antialiasing for x1 */
  14271                      scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
  14272                   else
  14273                      j = len; /*  clip */
  14274 
  14275                   for (++i; i < j; ++i) /*  fill pixels between x0 and x1 */
  14276                      scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
  14277                }
  14278             }
  14279          }
  14280       }
  14281 
  14282       e = e->next;
  14283    }
  14284 }
  14285 
  14286 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
  14287 {
  14288    stbtt__hheap hh = { 0, 0, 0 };
  14289    stbtt__active_edge *active = NULL;
  14290    int y,j=0;
  14291    int max_weight = (255 / vsubsample);  /*  weight per vertical scanline */
  14292    int s; /*  vertical subsample index */
  14293    unsigned char scanline_data[512], *scanline;
  14294 
  14295    if (result->w > 512)
  14296       scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
  14297    else
  14298       scanline = scanline_data;
  14299 
  14300    y = off_y * vsubsample;
  14301    e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
  14302 
  14303    while (j < result->h) {
  14304       STBTT_memset(scanline, 0, result->w);
  14305       for (s=0; s < vsubsample; ++s) {
  14306          /*  find center of pixel for this scanline */
  14307          float scan_y = y + 0.5f;
  14308          stbtt__active_edge **step = &active;
  14309 
  14310          /*  update all active edges; */
  14311          /*  remove all active edges that terminate before the center of this scanline */
  14312          while (*step) {
  14313             stbtt__active_edge * z = *step;
  14314             if (z->ey <= scan_y) {
  14315                *step = z->next; /*  delete from list */
  14316                STBTT_assert(z->direction);
  14317                z->direction = 0;
  14318                stbtt__hheap_free(&hh, z);
  14319             } else {
  14320                z->x += z->dx; /*  advance to position for current scanline */
  14321                step = &((*step)->next); /*  advance through list */
  14322             }
  14323          }
  14324 
  14325          /*  resort the list if needed */
  14326          for(;;) {
  14327             int changed=0;
  14328             step = &active;
  14329             while (*step && (*step)->next) {
  14330                if ((*step)->x > (*step)->next->x) {
  14331                   stbtt__active_edge *t = *step;
  14332                   stbtt__active_edge *q = t->next;
  14333 
  14334                   t->next = q->next;
  14335                   q->next = t;
  14336                   *step = q;
  14337                   changed = 1;
  14338                }
  14339                step = &(*step)->next;
  14340             }
  14341             if (!changed) break;
  14342          }
  14343 
  14344          /*  insert all edges that start before the center of this scanline -- omit ones that also end on this scanline */
  14345          while (e->y0 <= scan_y) {
  14346             if (e->y1 > scan_y) {
  14347                stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
  14348                if (z != NULL) {
  14349                   /*  find insertion point */
  14350                   if (active == NULL)
  14351                      active = z;
  14352                   else if (z->x < active->x) {
  14353                      /*  insert at front */
  14354                      z->next = active;
  14355                      active = z;
  14356                   } else {
  14357                      /*  find thing to insert AFTER */
  14358                      stbtt__active_edge *p = active;
  14359                      while (p->next && p->next->x < z->x)
  14360                         p = p->next;
  14361                      /*  at this point, p->next->x is NOT < z->x */
  14362                      z->next = p->next;
  14363                      p->next = z;
  14364                   }
  14365                }
  14366             }
  14367             ++e;
  14368          }
  14369 
  14370          /*  now process all active edges in XOR fashion */
  14371          if (active)
  14372             stbtt__fill_active_edges(scanline, result->w, active, max_weight);
  14373 
  14374          ++y;
  14375       }
  14376       STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
  14377       ++j;
  14378    }
  14379 
  14380    stbtt__hheap_cleanup(&hh, userdata);
  14381 
  14382    if (scanline != scanline_data)
  14383       STBTT_free(scanline, userdata);
  14384 }
  14385 
  14386 #elif STBTT_RASTERIZER_VERSION == 2
  14387 
  14388 /*  the edge passed in here does not cross the vertical line at x or the vertical line at x+1 */
  14389 /*  (i.e. it has already been clipped to those) */
  14390 static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
  14391 {
  14392    if (y0 == y1) return;
  14393    STBTT_assert(y0 < y1);
  14394    STBTT_assert(e->sy <= e->ey);
  14395    if (y0 > e->ey) return;
  14396    if (y1 < e->sy) return;
  14397    if (y0 < e->sy) {
  14398       x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
  14399       y0 = e->sy;
  14400    }
  14401    if (y1 > e->ey) {
  14402       x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
  14403       y1 = e->ey;
  14404    }
  14405 
  14406    if (x0 == x)
  14407       STBTT_assert(x1 <= x+1);
  14408    else if (x0 == x+1)
  14409       STBTT_assert(x1 >= x);
  14410    else if (x0 <= x)
  14411       STBTT_assert(x1 <= x);
  14412    else if (x0 >= x+1)
  14413       STBTT_assert(x1 >= x+1);
  14414    else
  14415       STBTT_assert(x1 >= x && x1 <= x+1);
  14416 
  14417    if (x0 <= x && x1 <= x)
  14418       scanline[x] += e->direction * (y1-y0);
  14419    else if (x0 >= x+1 && x1 >= x+1)
  14420       ;
  14421    else {
  14422       STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
  14423       scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); /*  coverage = 1 - average x position */
  14424    }
  14425 }
  14426 
  14427 static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
  14428 {
  14429    STBTT_assert(top_width >= 0);
  14430    STBTT_assert(bottom_width >= 0);
  14431    return (top_width + bottom_width) / 2.0f * height;
  14432 }
  14433 
  14434 static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
  14435 {
  14436    return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
  14437 }
  14438 
  14439 static float stbtt__sized_triangle_area(float height, float width)
  14440 {
  14441    return height * width / 2;
  14442 }
  14443 
  14444 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
  14445 {
  14446    float y_bottom = y_top+1;
  14447 
  14448    while (e) {
  14449       /*  brute force every pixel */
  14450 
  14451       /*  compute intersection points with top & bottom */
  14452       STBTT_assert(e->ey >= y_top);
  14453 
  14454       if (e->fdx == 0) {
  14455          float x0 = e->fx;
  14456          if (x0 < len) {
  14457             if (x0 >= 0) {
  14458                stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
  14459                stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
  14460             } else {
  14461                stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
  14462             }
  14463          }
  14464       } else {
  14465          float x0 = e->fx;
  14466          float dx = e->fdx;
  14467          float xb = x0 + dx;
  14468          float x_top, x_bottom;
  14469          float sy0,sy1;
  14470          float dy = e->fdy;
  14471          STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
  14472 
  14473          /*  compute endpoints of line segment clipped to this scanline (if the */
  14474          /*  line segment starts on this scanline. x0 is the intersection of the */
  14475          /*  line with y_top, but that may be off the line segment. */
  14476          if (e->sy > y_top) {
  14477             x_top = x0 + dx * (e->sy - y_top);
  14478             sy0 = e->sy;
  14479          } else {
  14480             x_top = x0;
  14481             sy0 = y_top;
  14482          }
  14483          if (e->ey < y_bottom) {
  14484             x_bottom = x0 + dx * (e->ey - y_top);
  14485             sy1 = e->ey;
  14486          } else {
  14487             x_bottom = xb;
  14488             sy1 = y_bottom;
  14489          }
  14490 
  14491          if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
  14492             /*  from here on, we don't have to range check x values */
  14493 
  14494             if ((int) x_top == (int) x_bottom) {
  14495                float height;
  14496                /*  simple case, only spans one pixel */
  14497                int x = (int) x_top;
  14498                height = (sy1 - sy0) * e->direction;
  14499                STBTT_assert(x >= 0 && x < len);
  14500                scanline[x]      += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
  14501                scanline_fill[x] += height; /*  everything right of this pixel is filled */
  14502             } else {
  14503                int x,x1,x2;
  14504                float y_crossing, y_final, step, sign, area;
  14505                /*  covers 2+ pixels */
  14506                if (x_top > x_bottom) {
  14507                   /*  flip scanline vertically; signed area is the same */
  14508                   float t;
  14509                   sy0 = y_bottom - (sy0 - y_top);
  14510                   sy1 = y_bottom - (sy1 - y_top);
  14511                   t = sy0, sy0 = sy1, sy1 = t;
  14512                   t = x_bottom, x_bottom = x_top, x_top = t;
  14513                   dx = -dx;
  14514                   dy = -dy;
  14515                   t = x0, x0 = xb, xb = t;
  14516                }
  14517                STBTT_assert(dy >= 0);
  14518                STBTT_assert(dx >= 0);
  14519 
  14520                x1 = (int) x_top;
  14521                x2 = (int) x_bottom;
  14522                /*  compute intersection with y axis at x1+1 */
  14523                y_crossing = y_top + dy * (x1+1 - x0);
  14524 
  14525                /*  compute intersection with y axis at x2 */
  14526                y_final = y_top + dy * (x2 - x0);
  14527 
  14528                /*            x1    x_top                            x2    x_bottom */
  14529                /*      y_top  +------|-----+------------+------------+--------|---+------------+ */
  14530                /*             |            |            |            |            |            | */
  14531                /*             |            |            |            |            |            | */
  14532                /*        sy0  |      Txxxxx|............|............|............|............| */
  14533                /*  y_crossing |            *xxxxx.......|............|............|............| */
  14534                /*             |            |     xxxxx..|............|............|............| */
  14535                /*             |            |     /-   xx*xxxx........|............|............| */
  14536                /*             |            | dy <       |    xxxxxx..|............|............| */
  14537                /*    y_final  |            |     \-     |          xx*xxx.........|............| */
  14538                /*        sy1  |            |            |            |   xxxxxB...|............| */
  14539                /*             |            |            |            |            |            | */
  14540                /*             |            |            |            |            |            | */
  14541                /*   y_bottom  +------------+------------+------------+------------+------------+ */
  14542                /*  */
  14543                /*  goal is to measure the area covered by '.' in each pixel */
  14544 
  14545                /*  if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 */
  14546                /*  @TODO: maybe test against sy1 rather than y_bottom? */
  14547                if (y_crossing > y_bottom)
  14548                   y_crossing = y_bottom;
  14549 
  14550                sign = e->direction;
  14551 
  14552                /*  area of the rectangle covered from sy0..y_crossing */
  14553                area = sign * (y_crossing-sy0);
  14554 
  14555                /*  area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) */
  14556                scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
  14557 
  14558                /*  check if final y_crossing is blown up; no test case for this */
  14559                if (y_final > y_bottom) {
  14560                   y_final = y_bottom;
  14561                   dy = (y_final - y_crossing ) / (x2 - (x1+1)); /*  if denom=0, y_final = y_crossing, so y_final <= y_bottom */
  14562                }
  14563 
  14564                /*  in second pixel, area covered by line segment found in first pixel */
  14565                /*  is always a rectangle 1 wide * the height of that line segment; this */
  14566                /*  is exactly what the variable 'area' stores. it also gets a contribution */
  14567                /*  from the line segment within it. the THIRD pixel will get the first */
  14568                /*  pixel's rectangle contribution, the second pixel's rectangle contribution, */
  14569                /*  and its own contribution. the 'own contribution' is the same in every pixel except */
  14570                /*  the leftmost and rightmost, a trapezoid that slides down in each pixel. */
  14571                /*  the second pixel's contribution to the third pixel will be the */
  14572                /*  rectangle 1 wide times the height change in the second pixel, which is dy. */
  14573 
  14574                step = sign * dy * 1; /*  dy is dy/dx, change in y for every 1 change in x, */
  14575                /*  which multiplied by 1-pixel-width is how much pixel area changes for each step in x */
  14576                /*  so the area advances by 'step' every time */
  14577 
  14578                for (x = x1+1; x < x2; ++x) {
  14579                   scanline[x] += area + step/2; /*  area of trapezoid is 1*step/2 */
  14580                   area += step;
  14581                }
  14582                STBTT_assert(STBTT_fabs(area) <= 1.01f); /*  accumulated error from area += step unless we round step down */
  14583                STBTT_assert(sy1 > y_final-0.01f);
  14584 
  14585                /*  area covered in the last pixel is the rectangle from all the pixels to the left, */
  14586                /*  plus the trapezoid filled by the line segment in this pixel all the way to the right edge */
  14587                scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
  14588 
  14589                /*  the rest of the line is filled based on the total height of the line segment in this pixel */
  14590                scanline_fill[x2] += sign * (sy1-sy0);
  14591             }
  14592          } else {
  14593             /*  if edge goes outside of box we're drawing, we require */
  14594             /*  clipping logic. since this does not match the intended use */
  14595             /*  of this library, we use a different, very slow brute */
  14596             /*  force implementation */
  14597             /*  note though that this does happen some of the time because */
  14598             /*  x_top and x_bottom can be extrapolated at the top & bottom of */
  14599             /*  the shape and actually lie outside the bounding box */
  14600             int x;
  14601             for (x=0; x < len; ++x) {
  14602                /*  cases: */
  14603                /*  */
  14604                /*  there can be up to two intersections with the pixel. any intersection */
  14605                /*  with left or right edges can be handled by splitting into two (or three) */
  14606                /*  regions. intersections with top & bottom do not necessitate case-wise logic. */
  14607                /*  */
  14608                /*  the old way of doing this found the intersections with the left & right edges, */
  14609                /*  then used some simple logic to produce up to three segments in sorted order */
  14610                /*  from top-to-bottom. however, this had a problem: if an x edge was epsilon */
  14611                /*  across the x border, then the corresponding y position might not be distinct */
  14612                /*  from the other y segment, and it might ignored as an empty segment. to avoid */
  14613                /*  that, we need to explicitly produce segments based on x positions. */
  14614 
  14615                /*  rename variables to clearly-defined pairs */
  14616                float y0 = y_top;
  14617                float x1 = (float) (x);
  14618                float x2 = (float) (x+1);
  14619                float x3 = xb;
  14620                float y3 = y_bottom;
  14621 
  14622                /*  x = e->x + e->dx * (y-y_top) */
  14623                /*  (y-y_top) = (x - e->x) / e->dx */
  14624                /*  y = (x - e->x) / e->dx + y_top */
  14625                float y1 = (x - x0) / dx + y_top;
  14626                float y2 = (x+1 - x0) / dx + y_top;
  14627 
  14628                if (x0 < x1 && x3 > x2) {         /*  three segments descending down-right */
  14629                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
  14630                   stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
  14631                   stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  14632                } else if (x3 < x1 && x0 > x2) {  /*  three segments descending down-left */
  14633                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
  14634                   stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
  14635                   stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
  14636                } else if (x0 < x1 && x3 > x1) {  /*  two segments across x, down-right */
  14637                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
  14638                   stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
  14639                } else if (x3 < x1 && x0 > x1) {  /*  two segments across x, down-left */
  14640                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
  14641                   stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
  14642                } else if (x0 < x2 && x3 > x2) {  /*  two segments across x+1, down-right */
  14643                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
  14644                   stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  14645                } else if (x3 < x2 && x0 > x2) {  /*  two segments across x+1, down-left */
  14646                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
  14647                   stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  14648                } else {  /*  one segment */
  14649                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
  14650                }
  14651             }
  14652          }
  14653       }
  14654       e = e->next;
  14655    }
  14656 }
  14657 
  14658 /*  directly AA rasterize edges w/o supersampling */
  14659 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
  14660 {
  14661    stbtt__hheap hh = { 0, 0, 0 };
  14662    stbtt__active_edge *active = NULL;
  14663    int y,j=0, i;
  14664    float scanline_data[129], *scanline, *scanline2;
  14665 
  14666    STBTT__NOTUSED(vsubsample);
  14667 
  14668    if (result->w > 64)
  14669       scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
  14670    else
  14671       scanline = scanline_data;
  14672 
  14673    scanline2 = scanline + result->w;
  14674 
  14675    y = off_y;
  14676    e[n].y0 = (float) (off_y + result->h) + 1;
  14677 
  14678    while (j < result->h) {
  14679       /*  find center of pixel for this scanline */
  14680       float scan_y_top    = y + 0.0f;
  14681       float scan_y_bottom = y + 1.0f;
  14682       stbtt__active_edge **step = &active;
  14683 
  14684       STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
  14685       STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
  14686 
  14687       /*  update all active edges; */
  14688       /*  remove all active edges that terminate before the top of this scanline */
  14689       while (*step) {
  14690          stbtt__active_edge * z = *step;
  14691          if (z->ey <= scan_y_top) {
  14692             *step = z->next; /*  delete from list */
  14693             STBTT_assert(z->direction);
  14694             z->direction = 0;
  14695             stbtt__hheap_free(&hh, z);
  14696          } else {
  14697             step = &((*step)->next); /*  advance through list */
  14698          }
  14699       }
  14700 
  14701       /*  insert all edges that start before the bottom of this scanline */
  14702       while (e->y0 <= scan_y_bottom) {
  14703          if (e->y0 != e->y1) {
  14704             stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
  14705             if (z != NULL) {
  14706                if (j == 0 && off_y != 0) {
  14707                   if (z->ey < scan_y_top) {
  14708                      /*  this can happen due to subpixel positioning and some kind of fp rounding error i think */
  14709                      z->ey = scan_y_top;
  14710                   }
  14711                }
  14712                STBTT_assert(z->ey >= scan_y_top); /*  if we get really unlucky a tiny bit of an edge can be out of bounds */
  14713                /*  insert at front */
  14714                z->next = active;
  14715                active = z;
  14716             }
  14717          }
  14718          ++e;
  14719       }
  14720 
  14721       /*  now process all active edges */
  14722       if (active)
  14723          stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
  14724 
  14725       {
  14726          float sum = 0;
  14727          for (i=0; i < result->w; ++i) {
  14728             float k;
  14729             int m;
  14730             sum += scanline2[i];
  14731             k = scanline[i] + sum;
  14732             k = (float) STBTT_fabs(k)*255 + 0.5f;
  14733             m = (int) k;
  14734             if (m > 255) m = 255;
  14735             result->pixels[j*result->stride + i] = (unsigned char) m;
  14736          }
  14737       }
  14738       /*  advance all the edges */
  14739       step = &active;
  14740       while (*step) {
  14741          stbtt__active_edge *z = *step;
  14742          z->fx += z->fdx; /*  advance to position for current scanline */
  14743          step = &((*step)->next); /*  advance through list */
  14744       }
  14745 
  14746       ++y;
  14747       ++j;
  14748    }
  14749 
  14750    stbtt__hheap_cleanup(&hh, userdata);
  14751 
  14752    if (scanline != scanline_data)
  14753       STBTT_free(scanline, userdata);
  14754 }
  14755 #else
  14756 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
  14757 #endif
  14758 
  14759 #define STBTT__COMPARE(a,b)  ((a)->y0 < (b)->y0)
  14760 
  14761 static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
  14762 {
  14763    int i,j;
  14764    for (i=1; i < n; ++i) {
  14765       stbtt__edge t = p[i], *a = &t;
  14766       j = i;
  14767       while (j > 0) {
  14768          stbtt__edge *b = &p[j-1];
  14769          int c = STBTT__COMPARE(a,b);
  14770          if (!c) break;
  14771          p[j] = p[j-1];
  14772          --j;
  14773       }
  14774       if (i != j)
  14775          p[j] = t;
  14776    }
  14777 }
  14778 
  14779 static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
  14780 {
  14781    /* threshold for transitioning to insertion sort */
  14782    while (n > 12) {
  14783       stbtt__edge t;
  14784       int c01,c12,c,m,i,j;
  14785 
  14786       /* compute median of three */
  14787       m = n >> 1;
  14788       c01 = STBTT__COMPARE(&p[0],&p[m]);
  14789       c12 = STBTT__COMPARE(&p[m],&p[n-1]);
  14790       /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
  14791       if (c01 != c12) {
  14792          /* otherwise, we'll need to swap something else to middle */
  14793          int z;
  14794          c = STBTT__COMPARE(&p[0],&p[n-1]);
  14795          /* 0>mid && mid<n:  0>n => n; 0<n => 0 */
  14796          /* 0<mid && mid>n:  0>n => 0; 0<n => n */
  14797          z = (c == c12) ? 0 : n-1;
  14798          t = p[z];
  14799          p[z] = p[m];
  14800          p[m] = t;
  14801       }
  14802       /* now p[m] is the median-of-three */
  14803       /* swap it to the beginning so it won't move around */
  14804       t = p[0];
  14805       p[0] = p[m];
  14806       p[m] = t;
  14807 
  14808       /* partition loop */
  14809       i=1;
  14810       j=n-1;
  14811       for(;;) {
  14812          /* handling of equality is crucial here */
  14813          /* for sentinels & efficiency with duplicates */
  14814          for (;;++i) {
  14815             if (!STBTT__COMPARE(&p[i], &p[0])) break;
  14816          }
  14817          for (;;--j) {
  14818             if (!STBTT__COMPARE(&p[0], &p[j])) break;
  14819          }
  14820          /* make sure we haven't crossed */
  14821          if (i >= j) break;
  14822          t = p[i];
  14823          p[i] = p[j];
  14824          p[j] = t;
  14825 
  14826          ++i;
  14827          --j;
  14828       }
  14829       /* recurse on smaller side, iterate on larger */
  14830       if (j < (n-i)) {
  14831          stbtt__sort_edges_quicksort(p,j);
  14832          p = p+i;
  14833          n = n-i;
  14834       } else {
  14835          stbtt__sort_edges_quicksort(p+i, n-i);
  14836          n = j;
  14837       }
  14838    }
  14839 }
  14840 
  14841 static void stbtt__sort_edges(stbtt__edge *p, int n)
  14842 {
  14843    stbtt__sort_edges_quicksort(p, n);
  14844    stbtt__sort_edges_ins_sort(p, n);
  14845 }
  14846 
  14847 typedef struct
  14848 {
  14849    float x,y;
  14850 } stbtt__point;
  14851 
  14852 static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
  14853 {
  14854    float y_scale_inv = invert ? -scale_y : scale_y;
  14855    stbtt__edge *e;
  14856    int n,i,j,k,m;
  14857 #if STBTT_RASTERIZER_VERSION == 1
  14858    int vsubsample = result->h < 8 ? 15 : 5;
  14859 #elif STBTT_RASTERIZER_VERSION == 2
  14860    int vsubsample = 1;
  14861 #else
  14862    #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
  14863 #endif
  14864    /*  vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
  14865 
  14866    /*  now we have to blow out the windings into explicit edge lists */
  14867    n = 0;
  14868    for (i=0; i < windings; ++i)
  14869       n += wcount[i];
  14870 
  14871    e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); /*  add an extra one as a sentinel */
  14872    if (e == 0) return;
  14873    n = 0;
  14874 
  14875    m=0;
  14876    for (i=0; i < windings; ++i) {
  14877       stbtt__point *p = pts + m;
  14878       m += wcount[i];
  14879       j = wcount[i]-1;
  14880       for (k=0; k < wcount[i]; j=k++) {
  14881          int a=k,b=j;
  14882          /*  skip the edge if horizontal */
  14883          if (p[j].y == p[k].y)
  14884             continue;
  14885          /*  add edge from j to k to the list */
  14886          e[n].invert = 0;
  14887          if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
  14888             e[n].invert = 1;
  14889             a=j,b=k;
  14890          }
  14891          e[n].x0 = p[a].x * scale_x + shift_x;
  14892          e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
  14893          e[n].x1 = p[b].x * scale_x + shift_x;
  14894          e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
  14895          ++n;
  14896       }
  14897    }
  14898 
  14899    /*  now sort the edges by their highest point (should snap to integer, and then by x) */
  14900    /* STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */
  14901    stbtt__sort_edges(e, n);
  14902 
  14903    /*  now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
  14904    stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
  14905 
  14906    STBTT_free(e, userdata);
  14907 }
  14908 
  14909 static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
  14910 {
  14911    if (!points) return; /*  during first pass, it's unallocated */
  14912    points[n].x = x;
  14913    points[n].y = y;
  14914 }
  14915 
  14916 /*  tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching */
  14917 static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
  14918 {
  14919    /*  midpoint */
  14920    float mx = (x0 + 2*x1 + x2)/4;
  14921    float my = (y0 + 2*y1 + y2)/4;
  14922    /*  versus directly drawn line */
  14923    float dx = (x0+x2)/2 - mx;
  14924    float dy = (y0+y2)/2 - my;
  14925    if (n > 16) /*  65536 segments on one curve better be enough! */
  14926       return 1;
  14927    if (dx*dx+dy*dy > objspace_flatness_squared) { /*  half-pixel error allowed... need to be smaller if AA */
  14928       stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
  14929       stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
  14930    } else {
  14931       stbtt__add_point(points, *num_points,x2,y2);
  14932       *num_points = *num_points+1;
  14933    }
  14934    return 1;
  14935 }
  14936 
  14937 static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
  14938 {
  14939    /*  @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough */
  14940    float dx0 = x1-x0;
  14941    float dy0 = y1-y0;
  14942    float dx1 = x2-x1;
  14943    float dy1 = y2-y1;
  14944    float dx2 = x3-x2;
  14945    float dy2 = y3-y2;
  14946    float dx = x3-x0;
  14947    float dy = y3-y0;
  14948    float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
  14949    float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
  14950    float flatness_squared = longlen*longlen-shortlen*shortlen;
  14951 
  14952    if (n > 16) /*  65536 segments on one curve better be enough! */
  14953       return;
  14954 
  14955    if (flatness_squared > objspace_flatness_squared) {
  14956       float x01 = (x0+x1)/2;
  14957       float y01 = (y0+y1)/2;
  14958       float x12 = (x1+x2)/2;
  14959       float y12 = (y1+y2)/2;
  14960       float x23 = (x2+x3)/2;
  14961       float y23 = (y2+y3)/2;
  14962 
  14963       float xa = (x01+x12)/2;
  14964       float ya = (y01+y12)/2;
  14965       float xb = (x12+x23)/2;
  14966       float yb = (y12+y23)/2;
  14967 
  14968       float mx = (xa+xb)/2;
  14969       float my = (ya+yb)/2;
  14970 
  14971       stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
  14972       stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
  14973    } else {
  14974       stbtt__add_point(points, *num_points,x3,y3);
  14975       *num_points = *num_points+1;
  14976    }
  14977 }
  14978 
  14979 /*  returns number of contours */
  14980 static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
  14981 {
  14982    stbtt__point *points=0;
  14983    int num_points=0;
  14984 
  14985    float objspace_flatness_squared = objspace_flatness * objspace_flatness;
  14986    int i,n=0,start=0, pass;
  14987 
  14988    /*  count how many "moves" there are to get the contour count */
  14989    for (i=0; i < num_verts; ++i)
  14990       if (vertices[i].type == STBTT_vmove)
  14991          ++n;
  14992 
  14993    *num_contours = n;
  14994    if (n == 0) return 0;
  14995 
  14996    *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
  14997 
  14998    if (*contour_lengths == 0) {
  14999       *num_contours = 0;
  15000       return 0;
  15001    }
  15002 
  15003    /*  make two passes through the points so we don't need to realloc */
  15004    for (pass=0; pass < 2; ++pass) {
  15005       float x=0,y=0;
  15006       if (pass == 1) {
  15007          points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
  15008          if (points == NULL) goto error;
  15009       }
  15010       num_points = 0;
  15011       n= -1;
  15012       for (i=0; i < num_verts; ++i) {
  15013          switch (vertices[i].type) {
  15014             case STBTT_vmove:
  15015                /*  start the next contour */
  15016                if (n >= 0)
  15017                   (*contour_lengths)[n] = num_points - start;
  15018                ++n;
  15019                start = num_points;
  15020 
  15021                x = vertices[i].x, y = vertices[i].y;
  15022                stbtt__add_point(points, num_points++, x,y);
  15023                break;
  15024             case STBTT_vline:
  15025                x = vertices[i].x, y = vertices[i].y;
  15026                stbtt__add_point(points, num_points++, x, y);
  15027                break;
  15028             case STBTT_vcurve:
  15029                stbtt__tesselate_curve(points, &num_points, x,y,
  15030                                         vertices[i].cx, vertices[i].cy,
  15031                                         vertices[i].x,  vertices[i].y,
  15032                                         objspace_flatness_squared, 0);
  15033                x = vertices[i].x, y = vertices[i].y;
  15034                break;
  15035             case STBTT_vcubic:
  15036                stbtt__tesselate_cubic(points, &num_points, x,y,
  15037                                         vertices[i].cx, vertices[i].cy,
  15038                                         vertices[i].cx1, vertices[i].cy1,
  15039                                         vertices[i].x,  vertices[i].y,
  15040                                         objspace_flatness_squared, 0);
  15041                x = vertices[i].x, y = vertices[i].y;
  15042                break;
  15043          }
  15044       }
  15045       (*contour_lengths)[n] = num_points - start;
  15046    }
  15047 
  15048    return points;
  15049 error:
  15050    STBTT_free(points, userdata);
  15051    STBTT_free(*contour_lengths, userdata);
  15052    *contour_lengths = 0;
  15053    *num_contours = 0;
  15054    return NULL;
  15055 }
  15056 
  15057 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
  15058 {
  15059    float scale            = scale_x > scale_y ? scale_y : scale_x;
  15060    int winding_count      = 0;
  15061    int *winding_lengths   = NULL;
  15062    stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
  15063    if (windings) {
  15064       stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
  15065       STBTT_free(winding_lengths, userdata);
  15066       STBTT_free(windings, userdata);
  15067    }
  15068 }
  15069 
  15070 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
  15071 {
  15072    STBTT_free(bitmap, userdata);
  15073 }
  15074 
  15075 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
  15076 {
  15077    int ix0,iy0,ix1,iy1;
  15078    stbtt__bitmap gbm;
  15079    stbtt_vertex *vertices;
  15080    int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
  15081 
  15082    if (scale_x == 0) scale_x = scale_y;
  15083    if (scale_y == 0) {
  15084       if (scale_x == 0) {
  15085          STBTT_free(vertices, info->userdata);
  15086          return NULL;
  15087       }
  15088       scale_y = scale_x;
  15089    }
  15090 
  15091    stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
  15092 
  15093    /*  now we get the size */
  15094    gbm.w = (ix1 - ix0);
  15095    gbm.h = (iy1 - iy0);
  15096    gbm.pixels = NULL; /*  in case we error */
  15097 
  15098    if (width ) *width  = gbm.w;
  15099    if (height) *height = gbm.h;
  15100    if (xoff  ) *xoff   = ix0;
  15101    if (yoff  ) *yoff   = iy0;
  15102 
  15103    if (gbm.w && gbm.h) {
  15104       gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
  15105       if (gbm.pixels) {
  15106          gbm.stride = gbm.w;
  15107 
  15108          stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
  15109       }
  15110    }
  15111    STBTT_free(vertices, info->userdata);
  15112    return gbm.pixels;
  15113 }
  15114 
  15115 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
  15116 {
  15117    return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
  15118 }
  15119 
  15120 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
  15121 {
  15122    int ix0,iy0;
  15123    stbtt_vertex *vertices;
  15124    int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
  15125    stbtt__bitmap gbm;
  15126 
  15127    stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
  15128    gbm.pixels = output;
  15129    gbm.w = out_w;
  15130    gbm.h = out_h;
  15131    gbm.stride = out_stride;
  15132 
  15133    if (gbm.w && gbm.h)
  15134       stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
  15135 
  15136    STBTT_free(vertices, info->userdata);
  15137 }
  15138 
  15139 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
  15140 {
  15141    stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
  15142 }
  15143 
  15144 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
  15145 {
  15146    return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
  15147 }
  15148 
  15149 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
  15150 {
  15151    stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
  15152 }
  15153 
  15154 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
  15155 {
  15156    stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
  15157 }
  15158 
  15159 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
  15160 {
  15161    return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
  15162 }
  15163 
  15164 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
  15165 {
  15166    stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
  15167 }
  15168 
  15169 /* //////////////////////////////////////////////////////////////////////////// */
  15170 /*  */
  15171 /*  bitmap baking */
  15172 /*  */
  15173 /*  This is SUPER-CRAPPY packing to keep source code small */
  15174 
  15175 static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset,  /*  font location (use offset=0 for plain .ttf) */
  15176                                 float pixel_height,                     /*  height of font in pixels */
  15177                                 unsigned char *pixels, int pw, int ph,  /*  bitmap to be filled in */
  15178                                 int first_char, int num_chars,          /*  characters to bake */
  15179                                 stbtt_bakedchar *chardata)
  15180 {
  15181    float scale;
  15182    int x,y,bottom_y, i;
  15183    stbtt_fontinfo f;
  15184    f.userdata = NULL;
  15185    if (!stbtt_InitFont(&f, data, offset))
  15186       return -1;
  15187    STBTT_memset(pixels, 0, pw*ph); /*  background of 0 around pixels */
  15188    x=y=1;
  15189    bottom_y = 1;
  15190 
  15191    scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
  15192 
  15193    for (i=0; i < num_chars; ++i) {
  15194       int advance, lsb, x0,y0,x1,y1,gw,gh;
  15195       int g = stbtt_FindGlyphIndex(&f, first_char + i);
  15196       stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
  15197       stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
  15198       gw = x1-x0;
  15199       gh = y1-y0;
  15200       if (x + gw + 1 >= pw)
  15201          y = bottom_y, x = 1; /*  advance to next row */
  15202       if (y + gh + 1 >= ph) /*  check if it fits vertically AFTER potentially moving to next row */
  15203          return -i;
  15204       STBTT_assert(x+gw < pw);
  15205       STBTT_assert(y+gh < ph);
  15206       stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
  15207       chardata[i].x0 = (stbtt_int16) x;
  15208       chardata[i].y0 = (stbtt_int16) y;
  15209       chardata[i].x1 = (stbtt_int16) (x + gw);
  15210       chardata[i].y1 = (stbtt_int16) (y + gh);
  15211       chardata[i].xadvance = scale * advance;
  15212       chardata[i].xoff     = (float) x0;
  15213       chardata[i].yoff     = (float) y0;
  15214       x = x + gw + 1;
  15215       if (y+gh+1 > bottom_y)
  15216          bottom_y = y+gh+1;
  15217    }
  15218    return bottom_y;
  15219 }
  15220 
  15221 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
  15222 {
  15223    float d3d_bias = opengl_fillrule ? 0 : -0.5f;
  15224    float ipw = 1.0f / pw, iph = 1.0f / ph;
  15225    const stbtt_bakedchar *b = chardata + char_index;
  15226    int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
  15227    int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
  15228 
  15229    q->x0 = round_x + d3d_bias;
  15230    q->y0 = round_y + d3d_bias;
  15231    q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
  15232    q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
  15233 
  15234    q->s0 = b->x0 * ipw;
  15235    q->t0 = b->y0 * iph;
  15236    q->s1 = b->x1 * ipw;
  15237    q->t1 = b->y1 * iph;
  15238 
  15239    *xpos += b->xadvance;
  15240 }
  15241 
  15242 /* //////////////////////////////////////////////////////////////////////////// */
  15243 /*  */
  15244 /*  rectangle packing replacement routines if you don't have stb_rect_pack.h */
  15245 /*  */
  15246 
  15247 #ifndef STB_RECT_PACK_VERSION
  15248 
  15249 typedef int stbrp_coord;
  15250 
  15251 /* ////////////////////////////////////////////////////////////////////////////////// */
  15252 /*                                                                                 // */
  15253 /*                                                                                 // */
  15254 /*  COMPILER WARNING ?!?!?                                                         // */
  15255 /*                                                                                 // */
  15256 /*                                                                                 // */
  15257 /*  if you get a compile warning due to these symbols being defined more than      // */
  15258 /*  once, move #include "stb_rect_pack.h" before #include "stb_truetype.h"         // */
  15259 /*                                                                                 // */
  15260 /* ////////////////////////////////////////////////////////////////////////////////// */
  15261 
  15262 typedef struct
  15263 {
  15264    int width,height;
  15265    int x,y,bottom_y;
  15266 } stbrp_context;
  15267 
  15268 typedef struct
  15269 {
  15270    unsigned char x;
  15271 } stbrp_node;
  15272 
  15273 struct stbrp_rect
  15274 {
  15275    stbrp_coord x,y;
  15276    int id,w,h,was_packed;
  15277 };
  15278 
  15279 static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
  15280 {
  15281    con->width  = pw;
  15282    con->height = ph;
  15283    con->x = 0;
  15284    con->y = 0;
  15285    con->bottom_y = 0;
  15286    STBTT__NOTUSED(nodes);
  15287    STBTT__NOTUSED(num_nodes);
  15288 }
  15289 
  15290 static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
  15291 {
  15292    int i;
  15293    for (i=0; i < num_rects; ++i) {
  15294       if (con->x + rects[i].w > con->width) {
  15295          con->x = 0;
  15296          con->y = con->bottom_y;
  15297       }
  15298       if (con->y + rects[i].h > con->height)
  15299          break;
  15300       rects[i].x = con->x;
  15301       rects[i].y = con->y;
  15302       rects[i].was_packed = 1;
  15303       con->x += rects[i].w;
  15304       if (con->y + rects[i].h > con->bottom_y)
  15305          con->bottom_y = con->y + rects[i].h;
  15306    }
  15307    for (   ; i < num_rects; ++i)
  15308       rects[i].was_packed = 0;
  15309 }
  15310 #endif
  15311 
  15312 /* //////////////////////////////////////////////////////////////////////////// */
  15313 /*  */
  15314 /*  bitmap baking */
  15315 /*  */
  15316 /*  This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If */
  15317 /*  stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. */
  15318 
  15319 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
  15320 {
  15321    stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context)            ,alloc_context);
  15322    int            num_nodes = pw - padding;
  15323    stbrp_node    *nodes   = (stbrp_node    *) STBTT_malloc(sizeof(*nodes  ) * num_nodes,alloc_context);
  15324 
  15325    if (context == NULL || nodes == NULL) {
  15326       if (context != NULL) STBTT_free(context, alloc_context);
  15327       if (nodes   != NULL) STBTT_free(nodes  , alloc_context);
  15328       return 0;
  15329    }
  15330 
  15331    spc->user_allocator_context = alloc_context;
  15332    spc->width = pw;
  15333    spc->height = ph;
  15334    spc->pixels = pixels;
  15335    spc->pack_info = context;
  15336    spc->nodes = nodes;
  15337    spc->padding = padding;
  15338    spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
  15339    spc->h_oversample = 1;
  15340    spc->v_oversample = 1;
  15341    spc->skip_missing = 0;
  15342 
  15343    stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
  15344 
  15345    if (pixels)
  15346       STBTT_memset(pixels, 0, pw*ph); /*  background of 0 around pixels */
  15347 
  15348    return 1;
  15349 }
  15350 
  15351 STBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc)
  15352 {
  15353    STBTT_free(spc->nodes    , spc->user_allocator_context);
  15354    STBTT_free(spc->pack_info, spc->user_allocator_context);
  15355 }
  15356 
  15357 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
  15358 {
  15359    STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
  15360    STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
  15361    if (h_oversample <= STBTT_MAX_OVERSAMPLE)
  15362       spc->h_oversample = h_oversample;
  15363    if (v_oversample <= STBTT_MAX_OVERSAMPLE)
  15364       spc->v_oversample = v_oversample;
  15365 }
  15366 
  15367 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
  15368 {
  15369    spc->skip_missing = skip;
  15370 }
  15371 
  15372 #define STBTT__OVER_MASK  (STBTT_MAX_OVERSAMPLE-1)
  15373 
  15374 static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
  15375 {
  15376    unsigned char buffer[STBTT_MAX_OVERSAMPLE];
  15377    int safe_w = w - kernel_width;
  15378    int j;
  15379    STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); /*  suppress bogus warning from VS2013 -analyze */
  15380    for (j=0; j < h; ++j) {
  15381       int i;
  15382       unsigned int total;
  15383       STBTT_memset(buffer, 0, kernel_width);
  15384 
  15385       total = 0;
  15386 
  15387       /*  make kernel_width a constant in common cases so compiler can optimize out the divide */
  15388       switch (kernel_width) {
  15389          case 2:
  15390             for (i=0; i <= safe_w; ++i) {
  15391                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  15392                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  15393                pixels[i] = (unsigned char) (total / 2);
  15394             }
  15395             break;
  15396          case 3:
  15397             for (i=0; i <= safe_w; ++i) {
  15398                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  15399                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  15400                pixels[i] = (unsigned char) (total / 3);
  15401             }
  15402             break;
  15403          case 4:
  15404             for (i=0; i <= safe_w; ++i) {
  15405                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  15406                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  15407                pixels[i] = (unsigned char) (total / 4);
  15408             }
  15409             break;
  15410          case 5:
  15411             for (i=0; i <= safe_w; ++i) {
  15412                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  15413                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  15414                pixels[i] = (unsigned char) (total / 5);
  15415             }
  15416             break;
  15417          default:
  15418             for (i=0; i <= safe_w; ++i) {
  15419                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  15420                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  15421                pixels[i] = (unsigned char) (total / kernel_width);
  15422             }
  15423             break;
  15424       }
  15425 
  15426       for (; i < w; ++i) {
  15427          STBTT_assert(pixels[i] == 0);
  15428          total -= buffer[i & STBTT__OVER_MASK];
  15429          pixels[i] = (unsigned char) (total / kernel_width);
  15430       }
  15431 
  15432       pixels += stride_in_bytes;
  15433    }
  15434 }
  15435 
  15436 static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
  15437 {
  15438    unsigned char buffer[STBTT_MAX_OVERSAMPLE];
  15439    int safe_h = h - kernel_width;
  15440    int j;
  15441    STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); /*  suppress bogus warning from VS2013 -analyze */
  15442    for (j=0; j < w; ++j) {
  15443       int i;
  15444       unsigned int total;
  15445       STBTT_memset(buffer, 0, kernel_width);
  15446 
  15447       total = 0;
  15448 
  15449       /*  make kernel_width a constant in common cases so compiler can optimize out the divide */
  15450       switch (kernel_width) {
  15451          case 2:
  15452             for (i=0; i <= safe_h; ++i) {
  15453                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  15454                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  15455                pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
  15456             }
  15457             break;
  15458          case 3:
  15459             for (i=0; i <= safe_h; ++i) {
  15460                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  15461                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  15462                pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
  15463             }
  15464             break;
  15465          case 4:
  15466             for (i=0; i <= safe_h; ++i) {
  15467                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  15468                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  15469                pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
  15470             }
  15471             break;
  15472          case 5:
  15473             for (i=0; i <= safe_h; ++i) {
  15474                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  15475                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  15476                pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
  15477             }
  15478             break;
  15479          default:
  15480             for (i=0; i <= safe_h; ++i) {
  15481                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  15482                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  15483                pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
  15484             }
  15485             break;
  15486       }
  15487 
  15488       for (; i < h; ++i) {
  15489          STBTT_assert(pixels[i*stride_in_bytes] == 0);
  15490          total -= buffer[i & STBTT__OVER_MASK];
  15491          pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
  15492       }
  15493 
  15494       pixels += 1;
  15495    }
  15496 }
  15497 
  15498 static float stbtt__oversample_shift(int oversample)
  15499 {
  15500    if (!oversample)
  15501       return 0.0f;
  15502 
  15503    /*  The prefilter is a box filter of width "oversample", */
  15504    /*  which shifts phase by (oversample - 1)/2 pixels in */
  15505    /*  oversampled space. We want to shift in the opposite */
  15506    /*  direction to counter this. */
  15507    return (float)-(oversample - 1) / (2.0f * (float)oversample);
  15508 }
  15509 
  15510 /*  rects array must be big enough to accommodate all characters in the given ranges */
  15511 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
  15512 {
  15513    int i,j,k;
  15514    int missing_glyph_added = 0;
  15515 
  15516    k=0;
  15517    for (i=0; i < num_ranges; ++i) {
  15518       float fh = ranges[i].font_size;
  15519       float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
  15520       ranges[i].h_oversample = (unsigned char) spc->h_oversample;
  15521       ranges[i].v_oversample = (unsigned char) spc->v_oversample;
  15522       for (j=0; j < ranges[i].num_chars; ++j) {
  15523          int x0,y0,x1,y1;
  15524          int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
  15525          int glyph = stbtt_FindGlyphIndex(info, codepoint);
  15526          if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
  15527             rects[k].w = rects[k].h = 0;
  15528          } else {
  15529             stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
  15530                                             scale * spc->h_oversample,
  15531                                             scale * spc->v_oversample,
  15532                                             0,0,
  15533                                             &x0,&y0,&x1,&y1);
  15534             rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
  15535             rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
  15536             if (glyph == 0)
  15537                missing_glyph_added = 1;
  15538          }
  15539          ++k;
  15540       }
  15541    }
  15542 
  15543    return k;
  15544 }
  15545 
  15546 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
  15547 {
  15548    stbtt_MakeGlyphBitmapSubpixel(info,
  15549                                  output,
  15550                                  out_w - (prefilter_x - 1),
  15551                                  out_h - (prefilter_y - 1),
  15552                                  out_stride,
  15553                                  scale_x,
  15554                                  scale_y,
  15555                                  shift_x,
  15556                                  shift_y,
  15557                                  glyph);
  15558 
  15559    if (prefilter_x > 1)
  15560       stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
  15561 
  15562    if (prefilter_y > 1)
  15563       stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
  15564 
  15565    *sub_x = stbtt__oversample_shift(prefilter_x);
  15566    *sub_y = stbtt__oversample_shift(prefilter_y);
  15567 }
  15568 
  15569 /*  rects array must be big enough to accommodate all characters in the given ranges */
  15570 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
  15571 {
  15572    int i,j,k, missing_glyph = -1, return_value = 1;
  15573 
  15574    /*  save current values */
  15575    int old_h_over = spc->h_oversample;
  15576    int old_v_over = spc->v_oversample;
  15577 
  15578    k = 0;
  15579    for (i=0; i < num_ranges; ++i) {
  15580       float fh = ranges[i].font_size;
  15581       float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
  15582       float recip_h,recip_v,sub_x,sub_y;
  15583       spc->h_oversample = ranges[i].h_oversample;
  15584       spc->v_oversample = ranges[i].v_oversample;
  15585       recip_h = 1.0f / spc->h_oversample;
  15586       recip_v = 1.0f / spc->v_oversample;
  15587       sub_x = stbtt__oversample_shift(spc->h_oversample);
  15588       sub_y = stbtt__oversample_shift(spc->v_oversample);
  15589       for (j=0; j < ranges[i].num_chars; ++j) {
  15590          stbrp_rect *r = &rects[k];
  15591          if (r->was_packed && r->w != 0 && r->h != 0) {
  15592             stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
  15593             int advance, lsb, x0,y0,x1,y1;
  15594             int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
  15595             int glyph = stbtt_FindGlyphIndex(info, codepoint);
  15596             stbrp_coord pad = (stbrp_coord) spc->padding;
  15597 
  15598             /*  pad on left and top */
  15599             r->x += pad;
  15600             r->y += pad;
  15601             r->w -= pad;
  15602             r->h -= pad;
  15603             stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
  15604             stbtt_GetGlyphBitmapBox(info, glyph,
  15605                                     scale * spc->h_oversample,
  15606                                     scale * spc->v_oversample,
  15607                                     &x0,&y0,&x1,&y1);
  15608             stbtt_MakeGlyphBitmapSubpixel(info,
  15609                                           spc->pixels + r->x + r->y*spc->stride_in_bytes,
  15610                                           r->w - spc->h_oversample+1,
  15611                                           r->h - spc->v_oversample+1,
  15612                                           spc->stride_in_bytes,
  15613                                           scale * spc->h_oversample,
  15614                                           scale * spc->v_oversample,
  15615                                           0,0,
  15616                                           glyph);
  15617 
  15618             if (spc->h_oversample > 1)
  15619                stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
  15620                                   r->w, r->h, spc->stride_in_bytes,
  15621                                   spc->h_oversample);
  15622 
  15623             if (spc->v_oversample > 1)
  15624                stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
  15625                                   r->w, r->h, spc->stride_in_bytes,
  15626                                   spc->v_oversample);
  15627 
  15628             bc->x0       = (stbtt_int16)  r->x;
  15629             bc->y0       = (stbtt_int16)  r->y;
  15630             bc->x1       = (stbtt_int16) (r->x + r->w);
  15631             bc->y1       = (stbtt_int16) (r->y + r->h);
  15632             bc->xadvance =                scale * advance;
  15633             bc->xoff     =       (float)  x0 * recip_h + sub_x;
  15634             bc->yoff     =       (float)  y0 * recip_v + sub_y;
  15635             bc->xoff2    =                (x0 + r->w) * recip_h + sub_x;
  15636             bc->yoff2    =                (y0 + r->h) * recip_v + sub_y;
  15637 
  15638             if (glyph == 0)
  15639                missing_glyph = j;
  15640          } else if (spc->skip_missing) {
  15641             return_value = 0;
  15642          } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
  15643             ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
  15644          } else {
  15645             return_value = 0; /*  if any fail, report failure */
  15646          }
  15647 
  15648          ++k;
  15649       }
  15650    }
  15651 
  15652    /*  restore original values */
  15653    spc->h_oversample = old_h_over;
  15654    spc->v_oversample = old_v_over;
  15655 
  15656    return return_value;
  15657 }
  15658 
  15659 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
  15660 {
  15661    stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
  15662 }
  15663 
  15664 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
  15665 {
  15666    stbtt_fontinfo info;
  15667    int i,j,n, return_value = 1;
  15668    /* stbrp_context *context = (stbrp_context *) spc->pack_info; */
  15669    stbrp_rect    *rects;
  15670 
  15671    /*  flag all characters as NOT packed */
  15672    for (i=0; i < num_ranges; ++i)
  15673       for (j=0; j < ranges[i].num_chars; ++j)
  15674          ranges[i].chardata_for_range[j].x0 =
  15675          ranges[i].chardata_for_range[j].y0 =
  15676          ranges[i].chardata_for_range[j].x1 =
  15677          ranges[i].chardata_for_range[j].y1 = 0;
  15678 
  15679    n = 0;
  15680    for (i=0; i < num_ranges; ++i)
  15681       n += ranges[i].num_chars;
  15682 
  15683    rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
  15684    if (rects == NULL)
  15685       return 0;
  15686 
  15687    info.userdata = spc->user_allocator_context;
  15688    stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
  15689 
  15690    n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
  15691 
  15692    stbtt_PackFontRangesPackRects(spc, rects, n);
  15693 
  15694    return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
  15695 
  15696    STBTT_free(rects, spc->user_allocator_context);
  15697    return return_value;
  15698 }
  15699 
  15700 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
  15701             int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
  15702 {
  15703    stbtt_pack_range range;
  15704    range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
  15705    range.array_of_unicode_codepoints = NULL;
  15706    range.num_chars                   = num_chars_in_range;
  15707    range.chardata_for_range          = chardata_for_range;
  15708    range.font_size                   = font_size;
  15709    return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
  15710 }
  15711 
  15712 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
  15713 {
  15714    int i_ascent, i_descent, i_lineGap;
  15715    float scale;
  15716    stbtt_fontinfo info;
  15717    stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
  15718    scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
  15719    stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
  15720    *ascent  = (float) i_ascent  * scale;
  15721    *descent = (float) i_descent * scale;
  15722    *lineGap = (float) i_lineGap * scale;
  15723 }
  15724 
  15725 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
  15726 {
  15727    float ipw = 1.0f / pw, iph = 1.0f / ph;
  15728    const stbtt_packedchar *b = chardata + char_index;
  15729 
  15730    if (align_to_integer) {
  15731       float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
  15732       float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
  15733       q->x0 = x;
  15734       q->y0 = y;
  15735       q->x1 = x + b->xoff2 - b->xoff;
  15736       q->y1 = y + b->yoff2 - b->yoff;
  15737    } else {
  15738       q->x0 = *xpos + b->xoff;
  15739       q->y0 = *ypos + b->yoff;
  15740       q->x1 = *xpos + b->xoff2;
  15741       q->y1 = *ypos + b->yoff2;
  15742    }
  15743 
  15744    q->s0 = b->x0 * ipw;
  15745    q->t0 = b->y0 * iph;
  15746    q->s1 = b->x1 * ipw;
  15747    q->t1 = b->y1 * iph;
  15748 
  15749    *xpos += b->xadvance;
  15750 }
  15751 
  15752 /* //////////////////////////////////////////////////////////////////////////// */
  15753 /*  */
  15754 /*  sdf computation */
  15755 /*  */
  15756 
  15757 #define STBTT_min(a,b)  ((a) < (b) ? (a) : (b))
  15758 #define STBTT_max(a,b)  ((a) < (b) ? (b) : (a))
  15759 
  15760 static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
  15761 {
  15762    float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
  15763    float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
  15764    float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
  15765    float roperp = orig[1]*ray[0] - orig[0]*ray[1];
  15766 
  15767    float a = q0perp - 2*q1perp + q2perp;
  15768    float b = q1perp - q0perp;
  15769    float c = q0perp - roperp;
  15770 
  15771    float s0 = 0., s1 = 0.;
  15772    int num_s = 0;
  15773 
  15774    if (a != 0.0) {
  15775       float discr = b*b - a*c;
  15776       if (discr > 0.0) {
  15777          float rcpna = -1 / a;
  15778          float d = (float) STBTT_sqrt(discr);
  15779          s0 = (b+d) * rcpna;
  15780          s1 = (b-d) * rcpna;
  15781          if (s0 >= 0.0 && s0 <= 1.0)
  15782             num_s = 1;
  15783          if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
  15784             if (num_s == 0) s0 = s1;
  15785             ++num_s;
  15786          }
  15787       }
  15788    } else {
  15789       /*  2*b*s + c = 0 */
  15790       /*  s = -c / (2*b) */
  15791       s0 = c / (-2 * b);
  15792       if (s0 >= 0.0 && s0 <= 1.0)
  15793          num_s = 1;
  15794    }
  15795 
  15796    if (num_s == 0)
  15797       return 0;
  15798    else {
  15799       float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
  15800       float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
  15801 
  15802       float q0d =   q0[0]*rayn_x +   q0[1]*rayn_y;
  15803       float q1d =   q1[0]*rayn_x +   q1[1]*rayn_y;
  15804       float q2d =   q2[0]*rayn_x +   q2[1]*rayn_y;
  15805       float rod = orig[0]*rayn_x + orig[1]*rayn_y;
  15806 
  15807       float q10d = q1d - q0d;
  15808       float q20d = q2d - q0d;
  15809       float q0rd = q0d - rod;
  15810 
  15811       hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
  15812       hits[0][1] = a*s0+b;
  15813 
  15814       if (num_s > 1) {
  15815          hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
  15816          hits[1][1] = a*s1+b;
  15817          return 2;
  15818       } else {
  15819          return 1;
  15820       }
  15821    }
  15822 }
  15823 
  15824 static int equal(float *a, float *b)
  15825 {
  15826    return (a[0] == b[0] && a[1] == b[1]);
  15827 }
  15828 
  15829 static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
  15830 {
  15831    int i;
  15832    float orig[2], ray[2] = { 1, 0 };
  15833    float y_frac;
  15834    int winding = 0;
  15835 
  15836    /*  make sure y never passes through a vertex of the shape */
  15837    y_frac = (float) STBTT_fmod(y, 1.0f);
  15838    if (y_frac < 0.01f)
  15839       y += 0.01f;
  15840    else if (y_frac > 0.99f)
  15841       y -= 0.01f;
  15842 
  15843    orig[0] = x;
  15844    orig[1] = y;
  15845 
  15846    /*  test a ray from (-infinity,y) to (x,y) */
  15847    for (i=0; i < nverts; ++i) {
  15848       if (verts[i].type == STBTT_vline) {
  15849          int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
  15850          int x1 = (int) verts[i  ].x, y1 = (int) verts[i  ].y;
  15851          if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
  15852             float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
  15853             if (x_inter < x)
  15854                winding += (y0 < y1) ? 1 : -1;
  15855          }
  15856       }
  15857       if (verts[i].type == STBTT_vcurve) {
  15858          int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
  15859          int x1 = (int) verts[i  ].cx, y1 = (int) verts[i  ].cy;
  15860          int x2 = (int) verts[i  ].x , y2 = (int) verts[i  ].y ;
  15861          int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
  15862          int by = STBTT_max(y0,STBTT_max(y1,y2));
  15863          if (y > ay && y < by && x > ax) {
  15864             float q0[2],q1[2],q2[2];
  15865             float hits[2][2];
  15866             q0[0] = (float)x0;
  15867             q0[1] = (float)y0;
  15868             q1[0] = (float)x1;
  15869             q1[1] = (float)y1;
  15870             q2[0] = (float)x2;
  15871             q2[1] = (float)y2;
  15872             if (equal(q0,q1) || equal(q1,q2)) {
  15873                x0 = (int)verts[i-1].x;
  15874                y0 = (int)verts[i-1].y;
  15875                x1 = (int)verts[i  ].x;
  15876                y1 = (int)verts[i  ].y;
  15877                if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
  15878                   float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
  15879                   if (x_inter < x)
  15880                      winding += (y0 < y1) ? 1 : -1;
  15881                }
  15882             } else {
  15883                int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
  15884                if (num_hits >= 1)
  15885                   if (hits[0][0] < 0)
  15886                      winding += (hits[0][1] < 0 ? -1 : 1);
  15887                if (num_hits >= 2)
  15888                   if (hits[1][0] < 0)
  15889                      winding += (hits[1][1] < 0 ? -1 : 1);
  15890             }
  15891          }
  15892       }
  15893    }
  15894    return winding;
  15895 }
  15896 
  15897 static float stbtt__cuberoot( float x )
  15898 {
  15899    if (x<0)
  15900       return -(float) STBTT_pow(-x,1.0f/3.0f);
  15901    else
  15902       return  (float) STBTT_pow( x,1.0f/3.0f);
  15903 }
  15904 
  15905 /*  x^3 + a*x^2 + b*x + c = 0 */
  15906 static int stbtt__solve_cubic(float a, float b, float c, float* r)
  15907 {
  15908    float s = -a / 3;
  15909    float p = b - a*a / 3;
  15910    float q = a * (2*a*a - 9*b) / 27 + c;
  15911    float p3 = p*p*p;
  15912    float d = q*q + 4*p3 / 27;
  15913    if (d >= 0) {
  15914       float z = (float) STBTT_sqrt(d);
  15915       float u = (-q + z) / 2;
  15916       float v = (-q - z) / 2;
  15917       u = stbtt__cuberoot(u);
  15918       v = stbtt__cuberoot(v);
  15919       r[0] = s + u + v;
  15920       return 1;
  15921    } else {
  15922       float u = (float) STBTT_sqrt(-p/3);
  15923       float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; /*  p3 must be negative, since d is negative */
  15924       float m = (float) STBTT_cos(v);
  15925       float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
  15926       r[0] = s + u * 2 * m;
  15927       r[1] = s - u * (m + n);
  15928       r[2] = s - u * (m - n);
  15929 
  15930       /* STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f);  // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? */
  15931       /* STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); */
  15932       /* STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); */
  15933       return 3;
  15934    }
  15935 }
  15936 
  15937 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
  15938 {
  15939    float scale_x = scale, scale_y = scale;
  15940    int ix0,iy0,ix1,iy1;
  15941    int w,h;
  15942    unsigned char *data;
  15943 
  15944    if (scale == 0) return NULL;
  15945 
  15946    stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
  15947 
  15948    /*  if empty, return NULL */
  15949    if (ix0 == ix1 || iy0 == iy1)
  15950       return NULL;
  15951 
  15952    ix0 -= padding;
  15953    iy0 -= padding;
  15954    ix1 += padding;
  15955    iy1 += padding;
  15956 
  15957    w = (ix1 - ix0);
  15958    h = (iy1 - iy0);
  15959 
  15960    if (width ) *width  = w;
  15961    if (height) *height = h;
  15962    if (xoff  ) *xoff   = ix0;
  15963    if (yoff  ) *yoff   = iy0;
  15964 
  15965    /*  invert for y-downwards bitmaps */
  15966    scale_y = -scale_y;
  15967 
  15968    {
  15969       int x,y,i,j;
  15970       float *precompute;
  15971       stbtt_vertex *verts;
  15972       int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
  15973       data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
  15974       precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
  15975 
  15976       for (i=0,j=num_verts-1; i < num_verts; j=i++) {
  15977          if (verts[i].type == STBTT_vline) {
  15978             float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
  15979             float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
  15980             float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
  15981             precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
  15982          } else if (verts[i].type == STBTT_vcurve) {
  15983             float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
  15984             float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
  15985             float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
  15986             float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
  15987             float len2 = bx*bx + by*by;
  15988             if (len2 != 0.0f)
  15989                precompute[i] = 1.0f / (bx*bx + by*by);
  15990             else
  15991                precompute[i] = 0.0f;
  15992          } else
  15993             precompute[i] = 0.0f;
  15994       }
  15995 
  15996       for (y=iy0; y < iy1; ++y) {
  15997          for (x=ix0; x < ix1; ++x) {
  15998             float val;
  15999             float min_dist = 999999.0f;
  16000             float sx = (float) x + 0.5f;
  16001             float sy = (float) y + 0.5f;
  16002             float x_gspace = (sx / scale_x);
  16003             float y_gspace = (sy / scale_y);
  16004 
  16005             int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); /*  @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path */
  16006 
  16007             for (i=0; i < num_verts; ++i) {
  16008                float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
  16009 
  16010                if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
  16011                   float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
  16012 
  16013                   float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
  16014                   if (dist2 < min_dist*min_dist)
  16015                      min_dist = (float) STBTT_sqrt(dist2);
  16016 
  16017                   /*  coarse culling against bbox */
  16018                   /* if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && */
  16019                   /*     sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) */
  16020                   dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
  16021                   STBTT_assert(i != 0);
  16022                   if (dist < min_dist) {
  16023                      /*  check position along line */
  16024                      /*  x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) */
  16025                      /*  minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) */
  16026                      float dx = x1-x0, dy = y1-y0;
  16027                      float px = x0-sx, py = y0-sy;
  16028                      /*  minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy */
  16029                      /*  derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve */
  16030                      float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
  16031                      if (t >= 0.0f && t <= 1.0f)
  16032                         min_dist = dist;
  16033                   }
  16034                } else if (verts[i].type == STBTT_vcurve) {
  16035                   float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
  16036                   float x1 = verts[i  ].cx*scale_x, y1 = verts[i  ].cy*scale_y;
  16037                   float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
  16038                   float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
  16039                   float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
  16040                   float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
  16041                   /*  coarse culling against bbox to avoid computing cubic unnecessarily */
  16042                   if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
  16043                      int num=0;
  16044                      float ax = x1-x0, ay = y1-y0;
  16045                      float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
  16046                      float mx = x0 - sx, my = y0 - sy;
  16047                      float res[3] = {0.f,0.f,0.f};
  16048                      float px,py,t,it,dist2;
  16049                      float a_inv = precompute[i];
  16050                      if (a_inv == 0.0) { /*  if a_inv is 0, it's 2nd degree so use quadratic formula */
  16051                         float a = 3*(ax*bx + ay*by);
  16052                         float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
  16053                         float c = mx*ax+my*ay;
  16054                         if (a == 0.0) { /*  if a is 0, it's linear */
  16055                            if (b != 0.0) {
  16056                               res[num++] = -c/b;
  16057                            }
  16058                         } else {
  16059                            float discriminant = b*b - 4*a*c;
  16060                            if (discriminant < 0)
  16061                               num = 0;
  16062                            else {
  16063                               float root = (float) STBTT_sqrt(discriminant);
  16064                               res[0] = (-b - root)/(2*a);
  16065                               res[1] = (-b + root)/(2*a);
  16066                               num = 2; /*  don't bother distinguishing 1-solution case, as code below will still work */
  16067                            }
  16068                         }
  16069                      } else {
  16070                         float b = 3*(ax*bx + ay*by) * a_inv; /*  could precompute this as it doesn't depend on sample point */
  16071                         float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
  16072                         float d = (mx*ax+my*ay) * a_inv;
  16073                         num = stbtt__solve_cubic(b, c, d, res);
  16074                      }
  16075                      dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
  16076                      if (dist2 < min_dist*min_dist)
  16077                         min_dist = (float) STBTT_sqrt(dist2);
  16078 
  16079                      if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
  16080                         t = res[0], it = 1.0f - t;
  16081                         px = it*it*x0 + 2*t*it*x1 + t*t*x2;
  16082                         py = it*it*y0 + 2*t*it*y1 + t*t*y2;
  16083                         dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
  16084                         if (dist2 < min_dist * min_dist)
  16085                            min_dist = (float) STBTT_sqrt(dist2);
  16086                      }
  16087                      if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
  16088                         t = res[1], it = 1.0f - t;
  16089                         px = it*it*x0 + 2*t*it*x1 + t*t*x2;
  16090                         py = it*it*y0 + 2*t*it*y1 + t*t*y2;
  16091                         dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
  16092                         if (dist2 < min_dist * min_dist)
  16093                            min_dist = (float) STBTT_sqrt(dist2);
  16094                      }
  16095                      if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
  16096                         t = res[2], it = 1.0f - t;
  16097                         px = it*it*x0 + 2*t*it*x1 + t*t*x2;
  16098                         py = it*it*y0 + 2*t*it*y1 + t*t*y2;
  16099                         dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
  16100                         if (dist2 < min_dist * min_dist)
  16101                            min_dist = (float) STBTT_sqrt(dist2);
  16102                      }
  16103                   }
  16104                }
  16105             }
  16106             if (winding == 0)
  16107                min_dist = -min_dist;  /*  if outside the shape, value is negative */
  16108             val = onedge_value + pixel_dist_scale * min_dist;
  16109             if (val < 0)
  16110                val = 0;
  16111             else if (val > 255)
  16112                val = 255;
  16113             data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
  16114          }
  16115       }
  16116       STBTT_free(precompute, info->userdata);
  16117       STBTT_free(verts, info->userdata);
  16118    }
  16119    return data;
  16120 }
  16121 
  16122 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
  16123 {
  16124    return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
  16125 }
  16126 
  16127 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
  16128 {
  16129    STBTT_free(bitmap, userdata);
  16130 }
  16131 
  16132 /* //////////////////////////////////////////////////////////////////////////// */
  16133 /*  */
  16134 /*  font name matching -- recommended not to use this */
  16135 /*  */
  16136 
  16137 /*  check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string */
  16138 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
  16139 {
  16140    stbtt_int32 i=0;
  16141 
  16142    /*  convert utf16 to utf8 and compare the results while converting */
  16143    while (len2) {
  16144       stbtt_uint16 ch = s2[0]*256 + s2[1];
  16145       if (ch < 0x80) {
  16146          if (i >= len1) return -1;
  16147          if (s1[i++] != ch) return -1;
  16148       } else if (ch < 0x800) {
  16149          if (i+1 >= len1) return -1;
  16150          if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
  16151          if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
  16152       } else if (ch >= 0xd800 && ch < 0xdc00) {
  16153          stbtt_uint32 c;
  16154          stbtt_uint16 ch2 = s2[2]*256 + s2[3];
  16155          if (i+3 >= len1) return -1;
  16156          c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
  16157          if (s1[i++] != 0xf0 + (c >> 18)) return -1;
  16158          if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
  16159          if (s1[i++] != 0x80 + ((c >>  6) & 0x3f)) return -1;
  16160          if (s1[i++] != 0x80 + ((c      ) & 0x3f)) return -1;
  16161          s2 += 2; /*  plus another 2 below */
  16162          len2 -= 2;
  16163       } else if (ch >= 0xdc00 && ch < 0xe000) {
  16164          return -1;
  16165       } else {
  16166          if (i+2 >= len1) return -1;
  16167          if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
  16168          if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
  16169          if (s1[i++] != 0x80 + ((ch     ) & 0x3f)) return -1;
  16170       }
  16171       s2 += 2;
  16172       len2 -= 2;
  16173    }
  16174    return i;
  16175 }
  16176 
  16177 static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
  16178 {
  16179    return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
  16180 }
  16181 
  16182 /*  returns results in whatever encoding you request... but note that 2-byte encodings */
  16183 /*  will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare */
  16184 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
  16185 {
  16186    stbtt_int32 i,count,stringOffset;
  16187    stbtt_uint8 *fc = font->data;
  16188    stbtt_uint32 offset = font->fontstart;
  16189    stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
  16190    if (!nm) return NULL;
  16191 
  16192    count = ttUSHORT(fc+nm+2);
  16193    stringOffset = nm + ttUSHORT(fc+nm+4);
  16194    for (i=0; i < count; ++i) {
  16195       stbtt_uint32 loc = nm + 6 + 12 * i;
  16196       if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
  16197           && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
  16198          *length = ttUSHORT(fc+loc+8);
  16199          return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
  16200       }
  16201    }
  16202    return NULL;
  16203 }
  16204 
  16205 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
  16206 {
  16207    stbtt_int32 i;
  16208    stbtt_int32 count = ttUSHORT(fc+nm+2);
  16209    stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
  16210 
  16211    for (i=0; i < count; ++i) {
  16212       stbtt_uint32 loc = nm + 6 + 12 * i;
  16213       stbtt_int32 id = ttUSHORT(fc+loc+6);
  16214       if (id == target_id) {
  16215          /*  find the encoding */
  16216          stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
  16217 
  16218          /*  is this a Unicode encoding? */
  16219          if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
  16220             stbtt_int32 slen = ttUSHORT(fc+loc+8);
  16221             stbtt_int32 off = ttUSHORT(fc+loc+10);
  16222 
  16223             /*  check if there's a prefix match */
  16224             stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
  16225             if (matchlen >= 0) {
  16226                /*  check for target_id+1 immediately following, with same encoding & language */
  16227                if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
  16228                   slen = ttUSHORT(fc+loc+12+8);
  16229                   off = ttUSHORT(fc+loc+12+10);
  16230                   if (slen == 0) {
  16231                      if (matchlen == nlen)
  16232                         return 1;
  16233                   } else if (matchlen < nlen && name[matchlen] == ' ') {
  16234                      ++matchlen;
  16235                      if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
  16236                         return 1;
  16237                   }
  16238                } else {
  16239                   /*  if nothing immediately following */
  16240                   if (matchlen == nlen)
  16241                      return 1;
  16242                }
  16243             }
  16244          }
  16245 
  16246          /*  @TODO handle other encodings */
  16247       }
  16248    }
  16249    return 0;
  16250 }
  16251 
  16252 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
  16253 {
  16254    stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
  16255    stbtt_uint32 nm,hd;
  16256    if (!stbtt__isfont(fc+offset)) return 0;
  16257 
  16258    /*  check italics/bold/underline flags in macStyle... */
  16259    if (flags) {
  16260       hd = stbtt__find_table(fc, offset, "head");
  16261       if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
  16262    }
  16263 
  16264    nm = stbtt__find_table(fc, offset, "name");
  16265    if (!nm) return 0;
  16266 
  16267    if (flags) {
  16268       /*  if we checked the macStyle flags, then just check the family and ignore the subfamily */
  16269       if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))  return 1;
  16270       if (stbtt__matchpair(fc, nm, name, nlen,  1, -1))  return 1;
  16271       if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;
  16272    } else {
  16273       if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))  return 1;
  16274       if (stbtt__matchpair(fc, nm, name, nlen,  1,  2))  return 1;
  16275       if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;
  16276    }
  16277 
  16278    return 0;
  16279 }
  16280 
  16281 static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
  16282 {
  16283    stbtt_int32 i;
  16284    for (i=0;;++i) {
  16285       stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
  16286       if (off < 0) return off;
  16287       if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
  16288          return off;
  16289    }
  16290 }
  16291 
  16292 #if defined(__GNUC__) || defined(__clang__)
  16293 #pragma GCC diagnostic push
  16294 #pragma GCC diagnostic ignored "-Wcast-qual"
  16295 #endif
  16296 
  16297 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
  16298                                 float pixel_height, unsigned char *pixels, int pw, int ph,
  16299                                 int first_char, int num_chars, stbtt_bakedchar *chardata)
  16300 {
  16301    return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
  16302 }
  16303 
  16304 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
  16305 {
  16306    return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
  16307 }
  16308 
  16309 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
  16310 {
  16311    return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
  16312 }
  16313 
  16314 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
  16315 {
  16316    return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
  16317 }
  16318 
  16319 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
  16320 {
  16321    return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
  16322 }
  16323 
  16324 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
  16325 {
  16326    return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
  16327 }
  16328 
  16329 #if defined(__GNUC__) || defined(__clang__)
  16330 #pragma GCC diagnostic pop
  16331 #endif
  16332 
  16333 #endif /*  STB_TRUETYPE_IMPLEMENTATION */
  16334 
  16335 
  16336 /*  FULL VERSION HISTORY */
  16337 /*  */
  16338 /*    1.25 (2021-07-11) many fixes */
  16339 /*    1.24 (2020-02-05) fix warning */
  16340 /*    1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) */
  16341 /*    1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined */
  16342 /*    1.21 (2019-02-25) fix warning */
  16343 /*    1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() */
  16344 /*    1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod */
  16345 /*    1.18 (2018-01-29) add missing function */
  16346 /*    1.17 (2017-07-23) make more arguments const; doc fix */
  16347 /*    1.16 (2017-07-12) SDF support */
  16348 /*    1.15 (2017-03-03) make more arguments const */
  16349 /*    1.14 (2017-01-16) num-fonts-in-TTC function */
  16350 /*    1.13 (2017-01-02) support OpenType fonts, certain Apple fonts */
  16351 /*    1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual */
  16352 /*    1.11 (2016-04-02) fix unused-variable warning */
  16353 /*    1.10 (2016-04-02) allow user-defined fabs() replacement */
  16354 /*                      fix memory leak if fontsize=0.0 */
  16355 /*                      fix warning from duplicate typedef */
  16356 /*    1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges */
  16357 /*    1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges */
  16358 /*    1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; */
  16359 /*                      allow PackFontRanges to pack and render in separate phases; */
  16360 /*                      fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); */
  16361 /*                      fixed an assert() bug in the new rasterizer */
  16362 /*                      replace assert() with STBTT_assert() in new rasterizer */
  16363 /*    1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) */
  16364 /*                      also more precise AA rasterizer, except if shapes overlap */
  16365 /*                      remove need for STBTT_sort */
  16366 /*    1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC */
  16367 /*    1.04 (2015-04-15) typo in example */
  16368 /*    1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes */
  16369 /*    1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ */
  16370 /*    1.01 (2014-12-08) fix subpixel position when oversampling to exactly match */
  16371 /*                         non-oversampled; STBTT_POINT_SIZE for packed case only */
  16372 /*    1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling */
  16373 /*    0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) */
  16374 /*    0.9  (2014-08-07) support certain mac/iOS fonts without an MS platformID */
  16375 /*    0.8b (2014-07-07) fix a warning */
  16376 /*    0.8  (2014-05-25) fix a few more warnings */
  16377 /*    0.7  (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back */
  16378 /*    0.6c (2012-07-24) improve documentation */
  16379 /*    0.6b (2012-07-20) fix a few more warnings */
  16380 /*    0.6  (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, */
  16381 /*                         stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty */
  16382 /*    0.5  (2011-12-09) bugfixes: */
  16383 /*                         subpixel glyph renderer computed wrong bounding box */
  16384 /*                         first vertex of shape can be off-curve (FreeSans) */
  16385 /*    0.4b (2011-12-03) fixed an error in the font baking example */
  16386 /*    0.4  (2011-12-01) kerning, subpixel rendering (tor) */
  16387 /*                     bugfixes for: */
  16388 /*                         codepoint-to-glyph conversion using table fmt=12 */
  16389 /*                         codepoint-to-glyph conversion using table fmt=4 */
  16390 /*                         stbtt_GetBakedQuad with non-square texture (Zer) */
  16391 /*                     updated Hello World! sample to use kerning and subpixel */
  16392 /*                     fixed some warnings */
  16393 /*    0.3  (2009-06-24) cmap fmt=12, compound shapes (MM) */
  16394 /*                     userdata, malloc-from-userdata, non-zero fill (stb) */
  16395 /*    0.2  (2009-03-11) Fix unsigned/signed char warnings */
  16396 /*    0.1  (2009-03-09) First public release */
  16397 /*  */
  16398 
  16399 /*
  16400 ------------------------------------------------------------------------------
  16401 This software is available under 2 licenses -- choose whichever you prefer.
  16402 ------------------------------------------------------------------------------
  16403 ALTERNATIVE A - MIT License
  16404 Copyright (c) 2017 Sean Barrett
  16405 Permission is hereby granted, free of charge, to any person obtaining a copy of
  16406 this software and associated documentation files (the "Software"), to deal in
  16407 the Software without restriction, including without limitation the rights to
  16408 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  16409 of the Software, and to permit persons to whom the Software is furnished to do
  16410 so, subject to the following conditions:
  16411 The above copyright notice and this permission notice shall be included in all
  16412 copies or substantial portions of the Software.
  16413 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16414 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16415 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16416 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16417 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16418 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  16419 SOFTWARE.
  16420 ------------------------------------------------------------------------------
  16421 ALTERNATIVE B - Public Domain (www.unlicense.org)
  16422 This is free and unencumbered software released into the public domain.
  16423 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
  16424 software, either in source code form or as a compiled binary, for any purpose,
  16425 commercial or non-commercial, and by any means.
  16426 In jurisdictions that recognize copyright laws, the author or authors of this
  16427 software dedicate any and all copyright interest in the software to the public
  16428 domain. We make this dedication for the benefit of the public at large and to
  16429 the detriment of our heirs and successors. We intend this dedication to be an
  16430 overt act of relinquishment in perpetuity of all present and future rights to
  16431 this software under copyright law.
  16432 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16433 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16434 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16435 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  16436 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  16437 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  16438 ------------------------------------------------------------------------------
  16439 */
  16440 
  16441 
  16442 
  16443 
  16444 #ifdef NK_INCLUDE_FONT_BAKING
  16445 /* -------------------------------------------------------------
  16446  *
  16447  *                          RECT PACK
  16448  *
  16449  * --------------------------------------------------------------*/
  16450 
  16451 
  16452 
  16453 /*
  16454  * ==============================================================
  16455  *
  16456  *                          TRUETYPE
  16457  *
  16458  * ===============================================================
  16459  */
  16460 #define STBTT_MAX_OVERSAMPLE   8
  16461 
  16462 
  16463 /* -------------------------------------------------------------
  16464  *
  16465  *                          FONT BAKING
  16466  *
  16467  * --------------------------------------------------------------*/
  16468 struct nk_font_bake_data {
  16469     struct stbtt_fontinfo info;
  16470     struct stbrp_rect *rects;
  16471     stbtt_pack_range *ranges;
  16472     nk_rune range_count;
  16473 };
  16474 
  16475 struct nk_font_baker {
  16476     struct nk_allocator alloc;
  16477     struct stbtt_pack_context spc;
  16478     struct nk_font_bake_data *build;
  16479     stbtt_packedchar *packed_chars;
  16480     struct stbrp_rect *rects;
  16481     stbtt_pack_range *ranges;
  16482 };
  16483 
  16484 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct stbrp_rect);
  16485 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(stbtt_pack_range);
  16486 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(stbtt_packedchar);
  16487 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
  16488 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
  16489 
  16490 NK_INTERN int
  16491 nk_range_count(const nk_rune *range)
  16492 {
  16493     const nk_rune *iter = range;
  16494     NK_ASSERT(range);
  16495     if (!range) return 0;
  16496     while (*(iter++) != 0);
  16497     return (iter == range) ? 0 : (int)((iter - range)/2);
  16498 }
  16499 NK_INTERN int
  16500 nk_range_glyph_count(const nk_rune *range, int count)
  16501 {
  16502     int i = 0;
  16503     int total_glyphs = 0;
  16504     for (i = 0; i < count; ++i) {
  16505         int diff;
  16506         nk_rune f = range[(i*2)+0];
  16507         nk_rune t = range[(i*2)+1];
  16508         NK_ASSERT(t >= f);
  16509         diff = (int)((t - f) + 1);
  16510         total_glyphs += diff;
  16511     }
  16512     return total_glyphs;
  16513 }
  16514 NK_API const nk_rune*
  16515 nk_font_default_glyph_ranges(void)
  16516 {
  16517     NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
  16518     return ranges;
  16519 }
  16520 NK_API const nk_rune*
  16521 nk_font_chinese_glyph_ranges(void)
  16522 {
  16523     NK_STORAGE const nk_rune ranges[] = {
  16524         0x0020, 0x00FF,
  16525         0x3000, 0x30FF,
  16526         0x31F0, 0x31FF,
  16527         0xFF00, 0xFFEF,
  16528         0x4E00, 0x9FAF,
  16529         0
  16530     };
  16531     return ranges;
  16532 }
  16533 NK_API const nk_rune*
  16534 nk_font_cyrillic_glyph_ranges(void)
  16535 {
  16536     NK_STORAGE const nk_rune ranges[] = {
  16537         0x0020, 0x00FF,
  16538         0x0400, 0x052F,
  16539         0x2DE0, 0x2DFF,
  16540         0xA640, 0xA69F,
  16541         0
  16542     };
  16543     return ranges;
  16544 }
  16545 NK_API const nk_rune*
  16546 nk_font_korean_glyph_ranges(void)
  16547 {
  16548     NK_STORAGE const nk_rune ranges[] = {
  16549         0x0020, 0x00FF,
  16550         0x3131, 0x3163,
  16551         0xAC00, 0xD79D,
  16552         0
  16553     };
  16554     return ranges;
  16555 }
  16556 NK_INTERN void
  16557 nk_font_baker_memory(nk_size *temp, int *glyph_count,
  16558     struct nk_font_config *config_list, int count)
  16559 {
  16560     int range_count = 0;
  16561     int total_range_count = 0;
  16562     struct nk_font_config *iter, *i;
  16563 
  16564     NK_ASSERT(config_list);
  16565     NK_ASSERT(glyph_count);
  16566     if (!config_list) {
  16567         *temp = 0;
  16568         *glyph_count = 0;
  16569         return;
  16570     }
  16571     *glyph_count = 0;
  16572     for (iter = config_list; iter; iter = iter->next) {
  16573         i = iter;
  16574         do {if (!i->range) iter->range = nk_font_default_glyph_ranges();
  16575             range_count = nk_range_count(i->range);
  16576             total_range_count += range_count;
  16577             *glyph_count += nk_range_glyph_count(i->range, range_count);
  16578         } while ((i = i->n) != iter);
  16579     }
  16580     *temp = (nk_size)*glyph_count * sizeof(struct stbrp_rect);
  16581     *temp += (nk_size)total_range_count * sizeof(stbtt_pack_range);
  16582     *temp += (nk_size)*glyph_count * sizeof(stbtt_packedchar);
  16583     *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
  16584     *temp += sizeof(struct nk_font_baker);
  16585     *temp += nk_rect_align + nk_range_align + nk_char_align;
  16586     *temp += nk_build_align + nk_baker_align;
  16587 }
  16588 NK_INTERN struct nk_font_baker*
  16589 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
  16590 {
  16591     struct nk_font_baker *baker;
  16592     if (!memory) return 0;
  16593     /* setup baker inside a memory block  */
  16594     baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
  16595     baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
  16596     baker->packed_chars = (stbtt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
  16597     baker->rects = (struct stbrp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
  16598     baker->ranges = (stbtt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
  16599     baker->alloc = *alloc;
  16600     return baker;
  16601 }
  16602 NK_INTERN int
  16603 nk_font_bake_pack(struct nk_font_baker *baker,
  16604     nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
  16605     const struct nk_font_config *config_list, int count,
  16606     struct nk_allocator *alloc)
  16607 {
  16608     NK_STORAGE const nk_size max_height = 1024 * 32;
  16609     const struct nk_font_config *config_iter, *it;
  16610     int total_glyph_count = 0;
  16611     int total_range_count = 0;
  16612     int range_count = 0;
  16613     int i = 0;
  16614 
  16615     NK_ASSERT(image_memory);
  16616     NK_ASSERT(width);
  16617     NK_ASSERT(height);
  16618     NK_ASSERT(config_list);
  16619     NK_ASSERT(count);
  16620     NK_ASSERT(alloc);
  16621 
  16622     if (!image_memory || !width || !height || !config_list || !count) return nk_false;
  16623     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
  16624         it = config_iter;
  16625         do {range_count = nk_range_count(it->range);
  16626             total_range_count += range_count;
  16627             total_glyph_count += nk_range_glyph_count(it->range, range_count);
  16628         } while ((it = it->n) != config_iter);
  16629     }
  16630     /* setup font baker from temporary memory */
  16631     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
  16632         it = config_iter;
  16633         do {
  16634             struct stbtt_fontinfo *font_info = &baker->build[i++].info;
  16635             font_info->userdata = alloc;
  16636 
  16637             if (!stbtt_InitFont(font_info, (const unsigned char*)it->ttf_blob, stbtt_GetFontOffsetForIndex((const unsigned char*)it->ttf_blob, 0)))
  16638                 return nk_false;
  16639         } while ((it = it->n) != config_iter);
  16640     }
  16641     *height = 0;
  16642     *width = (total_glyph_count > 1000) ? 1024 : 512;
  16643     stbtt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
  16644     {
  16645         int input_i = 0;
  16646         int range_n = 0;
  16647         int rect_n = 0;
  16648         int char_n = 0;
  16649 
  16650         if (custom) {
  16651             /* pack custom user data first so it will be in the upper left corner*/
  16652             struct stbrp_rect custom_space;
  16653             nk_zero(&custom_space, sizeof(custom_space));
  16654             custom_space.w = (stbrp_coord)(custom->w);
  16655             custom_space.h = (stbrp_coord)(custom->h);
  16656 
  16657             stbtt_PackSetOversampling(&baker->spc, 1, 1);
  16658             stbrp_pack_rects((struct stbrp_context*)baker->spc.pack_info, &custom_space, 1);
  16659             *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
  16660 
  16661             custom->x = (short)custom_space.x;
  16662             custom->y = (short)custom_space.y;
  16663             custom->w = (short)custom_space.w;
  16664             custom->h = (short)custom_space.h;
  16665         }
  16666 
  16667         /* first font pass: pack all glyphs */
  16668         for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
  16669             config_iter = config_iter->next) {
  16670             it = config_iter;
  16671             do {int n = 0;
  16672                 int glyph_count;
  16673                 const nk_rune *in_range;
  16674                 const struct nk_font_config *cfg = it;
  16675                 struct nk_font_bake_data *tmp = &baker->build[input_i++];
  16676 
  16677                 /* count glyphs + ranges in current font */
  16678                 glyph_count = 0; range_count = 0;
  16679                 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
  16680                     glyph_count += (int)(in_range[1] - in_range[0]) + 1;
  16681                     range_count++;
  16682                 }
  16683 
  16684                 /* setup ranges  */
  16685                 tmp->ranges = baker->ranges + range_n;
  16686                 tmp->range_count = (nk_rune)range_count;
  16687                 range_n += range_count;
  16688                 for (i = 0; i < range_count; ++i) {
  16689                     in_range = &cfg->range[i * 2];
  16690                     tmp->ranges[i].font_size = cfg->size;
  16691                     tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
  16692                     tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
  16693                     tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
  16694                     char_n += tmp->ranges[i].num_chars;
  16695                 }
  16696 
  16697                 /* pack */
  16698                 tmp->rects = baker->rects + rect_n;
  16699                 rect_n += glyph_count;
  16700                 stbtt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
  16701                 n = stbtt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
  16702                     tmp->ranges, (int)tmp->range_count, tmp->rects);
  16703                 stbrp_pack_rects((struct stbrp_context*)baker->spc.pack_info, tmp->rects, (int)n);
  16704 
  16705                 /* texture height */
  16706                 for (i = 0; i < n; ++i) {
  16707                     if (tmp->rects[i].was_packed)
  16708                         *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
  16709                 }
  16710             } while ((it = it->n) != config_iter);
  16711         }
  16712         NK_ASSERT(rect_n == total_glyph_count);
  16713         NK_ASSERT(char_n == total_glyph_count);
  16714         NK_ASSERT(range_n == total_range_count);
  16715     }
  16716     *height = (int)nk_round_up_pow2((nk_uint)*height);
  16717     *image_memory = (nk_size)(*width) * (nk_size)(*height);
  16718     return nk_true;
  16719 }
  16720 NK_INTERN void
  16721 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
  16722     struct nk_font_glyph *glyphs, int glyphs_count,
  16723     const struct nk_font_config *config_list, int font_count)
  16724 {
  16725     int input_i = 0;
  16726     nk_rune glyph_n = 0;
  16727     const struct nk_font_config *config_iter;
  16728     const struct nk_font_config *it;
  16729 
  16730     NK_ASSERT(image_memory);
  16731     NK_ASSERT(width);
  16732     NK_ASSERT(height);
  16733     NK_ASSERT(config_list);
  16734     NK_ASSERT(baker);
  16735     NK_ASSERT(font_count);
  16736     NK_ASSERT(glyphs_count);
  16737     if (!image_memory || !width || !height || !config_list ||
  16738         !font_count || !glyphs || !glyphs_count)
  16739         return;
  16740 
  16741     /* second font pass: render glyphs */
  16742     nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
  16743     baker->spc.pixels = (unsigned char*)image_memory;
  16744     baker->spc.height = (int)height;
  16745     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
  16746         config_iter = config_iter->next) {
  16747         it = config_iter;
  16748         do {const struct nk_font_config *cfg = it;
  16749             struct nk_font_bake_data *tmp = &baker->build[input_i++];
  16750             stbtt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
  16751             stbtt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges, (int)tmp->range_count, tmp->rects);
  16752         } while ((it = it->n) != config_iter);
  16753     } stbtt_PackEnd(&baker->spc);
  16754 
  16755     /* third pass: setup font and glyphs */
  16756     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
  16757         config_iter = config_iter->next) {
  16758         it = config_iter;
  16759         do {nk_size i = 0;
  16760             int char_idx = 0;
  16761             nk_rune glyph_count = 0;
  16762             const struct nk_font_config *cfg = it;
  16763             struct nk_font_bake_data *tmp = &baker->build[input_i++];
  16764             struct nk_baked_font *dst_font = cfg->font;
  16765 
  16766             float font_scale = stbtt_ScaleForPixelHeight(&tmp->info, cfg->size);
  16767             int unscaled_ascent, unscaled_descent, unscaled_line_gap;
  16768             stbtt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
  16769                                     &unscaled_line_gap);
  16770 
  16771             /* fill baked font */
  16772             if (!cfg->merge_mode) {
  16773                 dst_font->ranges = cfg->range;
  16774                 dst_font->height = cfg->size;
  16775                 dst_font->ascent = ((float)unscaled_ascent * font_scale);
  16776                 dst_font->descent = ((float)unscaled_descent * font_scale);
  16777                 dst_font->glyph_offset = glyph_n;
  16778                 /*
  16779                     Need to zero this, or it will carry over from a previous
  16780                     bake, and cause a segfault when accessing glyphs[].
  16781                 */
  16782                 dst_font->glyph_count = 0;
  16783             }
  16784 
  16785             /* fill own baked font glyph array */
  16786             for (i = 0; i < tmp->range_count; ++i) {
  16787                 stbtt_pack_range *range = &tmp->ranges[i];
  16788                 for (char_idx = 0; char_idx < range->num_chars; char_idx++)
  16789                 {
  16790                     nk_rune codepoint = 0;
  16791                     float dummy_x = 0, dummy_y = 0;
  16792                     stbtt_aligned_quad q;
  16793                     struct nk_font_glyph *glyph;
  16794 
  16795                     /* query glyph bounds from stb_truetype */
  16796                     const stbtt_packedchar *pc = &range->chardata_for_range[char_idx];
  16797                     codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
  16798                     stbtt_GetPackedQuad(range->chardata_for_range, (int)width,
  16799                         (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
  16800 
  16801                     /* fill own glyph type with data */
  16802                     glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count];
  16803                     glyph->codepoint = codepoint;
  16804                     glyph->x0 = q.x0; glyph->y0 = q.y0;
  16805                     glyph->x1 = q.x1; glyph->y1 = q.y1;
  16806                     glyph->y0 += (dst_font->ascent + 0.5f);
  16807                     glyph->y1 += (dst_font->ascent + 0.5f);
  16808                     glyph->w = glyph->x1 - glyph->x0 + 0.5f;
  16809                     glyph->h = glyph->y1 - glyph->y0;
  16810 
  16811                     if (cfg->coord_type == NK_COORD_PIXEL) {
  16812                         glyph->u0 = q.s0 * (float)width;
  16813                         glyph->v0 = q.t0 * (float)height;
  16814                         glyph->u1 = q.s1 * (float)width;
  16815                         glyph->v1 = q.t1 * (float)height;
  16816                     } else {
  16817                         glyph->u0 = q.s0;
  16818                         glyph->v0 = q.t0;
  16819                         glyph->u1 = q.s1;
  16820                         glyph->v1 = q.t1;
  16821                     }
  16822                     glyph->xadvance = (pc->xadvance + cfg->spacing.x);
  16823                     if (cfg->pixel_snap)
  16824                         glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
  16825                     glyph_count++;
  16826                 }
  16827             }
  16828             dst_font->glyph_count += glyph_count;
  16829             glyph_n += glyph_count;
  16830         } while ((it = it->n) != config_iter);
  16831     }
  16832 }
  16833 NK_INTERN void
  16834 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
  16835     struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
  16836     int tex_height, char white, char black)
  16837 {
  16838     nk_byte *pixels;
  16839     int y = 0;
  16840     int x = 0;
  16841     int n = 0;
  16842 
  16843     NK_ASSERT(img_memory);
  16844     NK_ASSERT(img_width);
  16845     NK_ASSERT(img_height);
  16846     NK_ASSERT(texture_data_mask);
  16847     NK_UNUSED(tex_height);
  16848     if (!img_memory || !img_width || !img_height || !texture_data_mask)
  16849         return;
  16850 
  16851     pixels = (nk_byte*)img_memory;
  16852     for (y = 0, n = 0; y < tex_height; ++y) {
  16853         for (x = 0; x < tex_width; ++x, ++n) {
  16854             const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
  16855             const int off1 = off0 + 1 + tex_width;
  16856             pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
  16857             pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
  16858         }
  16859     }
  16860 }
  16861 NK_INTERN void
  16862 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
  16863     const void *in_memory)
  16864 {
  16865     int n = 0;
  16866     nk_rune *dst;
  16867     const nk_byte *src;
  16868 
  16869     NK_ASSERT(out_memory);
  16870     NK_ASSERT(in_memory);
  16871     NK_ASSERT(img_width);
  16872     NK_ASSERT(img_height);
  16873     if (!out_memory || !in_memory || !img_height || !img_width) return;
  16874 
  16875     dst = (nk_rune*)out_memory;
  16876     src = (const nk_byte*)in_memory;
  16877     for (n = (int)(img_width * img_height); n > 0; n--)
  16878         *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
  16879 }
  16880 
  16881 /* -------------------------------------------------------------
  16882  *
  16883  *                          FONT
  16884  *
  16885  * --------------------------------------------------------------*/
  16886 NK_INTERN float
  16887 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
  16888 {
  16889     nk_rune unicode;
  16890     int text_len  = 0;
  16891     float text_width = 0;
  16892     int glyph_len = 0;
  16893     float scale = 0;
  16894 
  16895     struct nk_font *font = (struct nk_font*)handle.ptr;
  16896     NK_ASSERT(font);
  16897     NK_ASSERT(font->glyphs);
  16898     if (!font || !text || !len)
  16899         return 0;
  16900 
  16901     scale = height/font->info.height;
  16902     glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
  16903     if (!glyph_len) return 0;
  16904     while (text_len <= (int)len && glyph_len) {
  16905         const struct nk_font_glyph *g;
  16906         if (unicode == NK_UTF_INVALID) break;
  16907 
  16908         /* query currently drawn glyph information */
  16909         g = nk_font_find_glyph(font, unicode);
  16910         text_width += g->xadvance * scale;
  16911 
  16912         /* offset next glyph */
  16913         glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
  16914         text_len += glyph_len;
  16915     }
  16916     return text_width;
  16917 }
  16918 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  16919 NK_INTERN void
  16920 nk_font_query_font_glyph(nk_handle handle, float height,
  16921     struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
  16922 {
  16923     float scale;
  16924     const struct nk_font_glyph *g;
  16925     struct nk_font *font;
  16926 
  16927     NK_ASSERT(glyph);
  16928     NK_UNUSED(next_codepoint);
  16929 
  16930     font = (struct nk_font*)handle.ptr;
  16931     NK_ASSERT(font);
  16932     NK_ASSERT(font->glyphs);
  16933     if (!font || !glyph)
  16934         return;
  16935 
  16936     scale = height/font->info.height;
  16937     g = nk_font_find_glyph(font, codepoint);
  16938     glyph->width = (g->x1 - g->x0) * scale;
  16939     glyph->height = (g->y1 - g->y0) * scale;
  16940     glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
  16941     glyph->xadvance = (g->xadvance * scale);
  16942     glyph->uv[0] = nk_vec2(g->u0, g->v0);
  16943     glyph->uv[1] = nk_vec2(g->u1, g->v1);
  16944 }
  16945 #endif
  16946 NK_API const struct nk_font_glyph*
  16947 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
  16948 {
  16949     int i = 0;
  16950     int count;
  16951     int total_glyphs = 0;
  16952     const struct nk_font_glyph *glyph = 0;
  16953     const struct nk_font_config *iter = 0;
  16954 
  16955     NK_ASSERT(font);
  16956     NK_ASSERT(font->glyphs);
  16957     NK_ASSERT(font->info.ranges);
  16958     if (!font || !font->glyphs) return 0;
  16959 
  16960     glyph = font->fallback;
  16961     iter = font->config;
  16962     do {count = nk_range_count(iter->range);
  16963         for (i = 0; i < count; ++i) {
  16964             nk_rune f = iter->range[(i*2)+0];
  16965             nk_rune t = iter->range[(i*2)+1];
  16966             int diff = (int)((t - f) + 1);
  16967             if (unicode >= f && unicode <= t)
  16968                 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
  16969             total_glyphs += diff;
  16970         }
  16971     } while ((iter = iter->n) != font->config);
  16972     return glyph;
  16973 }
  16974 NK_INTERN void
  16975 nk_font_init(struct nk_font *font, float pixel_height,
  16976     nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
  16977     const struct nk_baked_font *baked_font, nk_handle atlas)
  16978 {
  16979     struct nk_baked_font baked;
  16980     NK_ASSERT(font);
  16981     NK_ASSERT(glyphs);
  16982     NK_ASSERT(baked_font);
  16983     if (!font || !glyphs || !baked_font)
  16984         return;
  16985 
  16986     baked = *baked_font;
  16987     font->fallback = 0;
  16988     font->info = baked;
  16989     font->scale = (float)pixel_height / (float)font->info.height;
  16990     font->glyphs = &glyphs[baked_font->glyph_offset];
  16991     font->texture = atlas;
  16992     font->fallback_codepoint = fallback_codepoint;
  16993     font->fallback = nk_font_find_glyph(font, fallback_codepoint);
  16994 
  16995     font->handle.height = font->info.height * font->scale;
  16996     font->handle.width = nk_font_text_width;
  16997     font->handle.userdata.ptr = font;
  16998 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  16999     font->handle.query = nk_font_query_font_glyph;
  17000     font->handle.texture = font->texture;
  17001 #endif
  17002 }
  17003 
  17004 /* ---------------------------------------------------------------------------
  17005  *
  17006  *                          DEFAULT FONT
  17007  *
  17008  * ProggyClean.ttf
  17009  * Copyright (c) 2004, 2005 Tristan Grimmer
  17010  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
  17011  * Download and more information at http://upperbounds.net
  17012  *-----------------------------------------------------------------------------*/
  17013 #ifdef __clang__
  17014 #pragma clang diagnostic push
  17015 #pragma clang diagnostic ignored "-Woverlength-strings"
  17016 #elif defined(__GNUC__) || defined(__GNUG__)
  17017 #pragma GCC diagnostic push
  17018 #pragma GCC diagnostic ignored "-Woverlength-strings"
  17019 #endif
  17020 
  17021 #ifdef NK_INCLUDE_DEFAULT_FONT
  17022 
  17023 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
  17024     "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
  17025     "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
  17026     "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
  17027     "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
  17028     "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
  17029     "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
  17030     "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
  17031     "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
  17032     "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
  17033     "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
  17034     "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
  17035     "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
  17036     "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
  17037     "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
  17038     "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
  17039     "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
  17040     "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
  17041     "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
  17042     "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
  17043     "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
  17044     "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
  17045     "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
  17046     "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
  17047     "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
  17048     "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
  17049     "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
  17050     "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
  17051     "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
  17052     "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
  17053     "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
  17054     ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
  17055     "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
  17056     "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
  17057     "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
  17058     "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
  17059     "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
  17060     "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
  17061     ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
  17062     "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
  17063     "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
  17064     "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
  17065     "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
  17066     "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
  17067     "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
  17068     "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
  17069     "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
  17070     ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
  17071     "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
  17072     "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
  17073     ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
  17074     "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
  17075     "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
  17076     "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
  17077     ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
  17078     "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
  17079     "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
  17080     "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
  17081     "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
  17082     "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
  17083     "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
  17084     "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
  17085     "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
  17086     "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
  17087     "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
  17088     "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
  17089     "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
  17090     "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
  17091     "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
  17092     ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
  17093     "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
  17094     "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
  17095     "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
  17096     "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
  17097     "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
  17098     "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
  17099     "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
  17100     "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
  17101     ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
  17102     "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
  17103     "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
  17104     "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
  17105     "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
  17106     "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
  17107     "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
  17108     "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
  17109     "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
  17110 
  17111 #endif /* NK_INCLUDE_DEFAULT_FONT */
  17112 
  17113 #define NK_CURSOR_DATA_W 90
  17114 #define NK_CURSOR_DATA_H 27
  17115 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
  17116 {
  17117     "..-         -XXXXXXX-    X    -           X           -XXXXXXX          -          XXXXXXX"
  17118     "..-         -X.....X-   X.X   -          X.X          -X.....X          -          X.....X"
  17119     "---         -XXX.XXX-  X...X  -         X...X         -X....X           -           X....X"
  17120     "X           -  X.X  - X.....X -        X.....X        -X...X            -            X...X"
  17121     "XX          -  X.X  -X.......X-       X.......X       -X..X.X           -           X.X..X"
  17122     "X.X         -  X.X  -XXXX.XXXX-       XXXX.XXXX       -X.X X.X          -          X.X X.X"
  17123     "X..X        -  X.X  -   X.X   -          X.X          -XX   X.X         -         X.X   XX"
  17124     "X...X       -  X.X  -   X.X   -    XX    X.X    XX    -      X.X        -        X.X      "
  17125     "X....X      -  X.X  -   X.X   -   X.X    X.X    X.X   -       X.X       -       X.X       "
  17126     "X.....X     -  X.X  -   X.X   -  X..X    X.X    X..X  -        X.X      -      X.X        "
  17127     "X......X    -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -         X.X   XX-XX   X.X         "
  17128     "X.......X   -  X.X  -   X.X   -X.....................X-          X.X X.X-X.X X.X          "
  17129     "X........X  -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -           X.X..X-X..X.X           "
  17130     "X.........X -XXX.XXX-   X.X   -  X..X    X.X    X..X  -            X...X-X...X            "
  17131     "X..........X-X.....X-   X.X   -   X.X    X.X    X.X   -           X....X-X....X           "
  17132     "X......XXXXX-XXXXXXX-   X.X   -    XX    X.X    XX    -          X.....X-X.....X          "
  17133     "X...X..X    ---------   X.X   -          X.X          -          XXXXXXX-XXXXXXX          "
  17134     "X..X X..X   -       -XXXX.XXXX-       XXXX.XXXX       ------------------------------------"
  17135     "X.X  X..X   -       -X.......X-       X.......X       -    XX           XX    -           "
  17136     "XX    X..X  -       - X.....X -        X.....X        -   X.X           X.X   -           "
  17137     "      X..X          -  X...X  -         X...X         -  X..X           X..X  -           "
  17138     "       XX           -   X.X   -          X.X          - X...XXXXXXXXXXXXX...X -           "
  17139     "------------        -    X    -           X           -X.....................X-           "
  17140     "                    ----------------------------------- X...XXXXXXXXXXXXX...X -           "
  17141     "                                                      -  X..X           X..X  -           "
  17142     "                                                      -   X.X           X.X   -           "
  17143     "                                                      -    XX           XX    -           "
  17144 };
  17145 
  17146 #ifdef __clang__
  17147 #pragma clang diagnostic pop
  17148 #elif defined(__GNUC__) || defined(__GNUG__)
  17149 #pragma GCC diagnostic pop
  17150 #endif
  17151 
  17152 NK_GLOBAL unsigned char *nk__barrier;
  17153 NK_GLOBAL unsigned char *nk__barrier2;
  17154 NK_GLOBAL unsigned char *nk__barrier3;
  17155 NK_GLOBAL unsigned char *nk__barrier4;
  17156 NK_GLOBAL unsigned char *nk__dout;
  17157 
  17158 NK_INTERN unsigned int
  17159 nk_decompress_length(unsigned char *input)
  17160 {
  17161     return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
  17162 }
  17163 NK_INTERN void
  17164 nk__match(unsigned char *data, unsigned int length)
  17165 {
  17166     /* INVERSE of memmove... write each byte before copying the next...*/
  17167     NK_ASSERT (nk__dout + length <= nk__barrier);
  17168     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
  17169     if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
  17170     while (length--) *nk__dout++ = *data++;
  17171 }
  17172 NK_INTERN void
  17173 nk__lit(unsigned char *data, unsigned int length)
  17174 {
  17175     NK_ASSERT (nk__dout + length <= nk__barrier);
  17176     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
  17177     if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
  17178     NK_MEMCPY(nk__dout, data, length);
  17179     nk__dout += length;
  17180 }
  17181 NK_INTERN unsigned char*
  17182 nk_decompress_token(unsigned char *i)
  17183 {
  17184     #define nk__in2(x)   ((i[x] << 8) + i[(x)+1])
  17185     #define nk__in3(x)   ((i[x] << 16) + nk__in2((x)+1))
  17186     #define nk__in4(x)   ((i[x] << 24) + nk__in3((x)+1))
  17187 
  17188     if (*i >= 0x20) { /* use fewer if's for cases that expand small */
  17189         if (*i >= 0x80)       nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
  17190         else if (*i >= 0x40)  nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
  17191         else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
  17192     } else { /* more ifs for cases that expand large, since overhead is amortized */
  17193         if (*i >= 0x18)       nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
  17194         else if (*i >= 0x10)  nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
  17195         else if (*i >= 0x08)  nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
  17196         else if (*i == 0x07)  nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
  17197         else if (*i == 0x06)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
  17198         else if (*i == 0x04)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
  17199     }
  17200     return i;
  17201 }
  17202 NK_INTERN unsigned int
  17203 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
  17204 {
  17205     const unsigned long ADLER_MOD = 65521;
  17206     unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
  17207     unsigned long blocklen, i;
  17208 
  17209     blocklen = buflen % 5552;
  17210     while (buflen) {
  17211         for (i=0; i + 7 < blocklen; i += 8) {
  17212             s1 += buffer[0]; s2 += s1;
  17213             s1 += buffer[1]; s2 += s1;
  17214             s1 += buffer[2]; s2 += s1;
  17215             s1 += buffer[3]; s2 += s1;
  17216             s1 += buffer[4]; s2 += s1;
  17217             s1 += buffer[5]; s2 += s1;
  17218             s1 += buffer[6]; s2 += s1;
  17219             s1 += buffer[7]; s2 += s1;
  17220             buffer += 8;
  17221         }
  17222         for (; i < blocklen; ++i) {
  17223             s1 += *buffer++; s2 += s1;
  17224         }
  17225 
  17226         s1 %= ADLER_MOD; s2 %= ADLER_MOD;
  17227         buflen -= (unsigned int)blocklen;
  17228         blocklen = 5552;
  17229     }
  17230     return (unsigned int)(s2 << 16) + (unsigned int)s1;
  17231 }
  17232 NK_INTERN unsigned int
  17233 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
  17234 {
  17235     unsigned int olen;
  17236     if (nk__in4(0) != 0x57bC0000) return 0;
  17237     if (nk__in4(4) != 0)          return 0; /* error! stream is > 4GB */
  17238     olen = nk_decompress_length(i);
  17239     nk__barrier2 = i;
  17240     nk__barrier3 = i+length;
  17241     nk__barrier = output + olen;
  17242     nk__barrier4 = output;
  17243     i += 16;
  17244 
  17245     nk__dout = output;
  17246     for (;;) {
  17247         unsigned char *old_i = i;
  17248         i = nk_decompress_token(i);
  17249         if (i == old_i) {
  17250             if (*i == 0x05 && i[1] == 0xfa) {
  17251                 NK_ASSERT(nk__dout == output + olen);
  17252                 if (nk__dout != output + olen) return 0;
  17253                 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
  17254                     return 0;
  17255                 return olen;
  17256             } else {
  17257                 NK_ASSERT(0); /* NOTREACHED */
  17258                 return 0;
  17259             }
  17260         }
  17261         NK_ASSERT(nk__dout <= output + olen);
  17262         if (nk__dout > output + olen)
  17263             return 0;
  17264     }
  17265 }
  17266 NK_INTERN unsigned int
  17267 nk_decode_85_byte(char c)
  17268 {
  17269     return (unsigned int)((c >= '\\') ? c-36 : c-35);
  17270 }
  17271 NK_INTERN void
  17272 nk_decode_85(unsigned char* dst, const unsigned char* src)
  17273 {
  17274     while (*src)
  17275     {
  17276         unsigned int tmp =
  17277             nk_decode_85_byte((char)src[0]) +
  17278             85 * (nk_decode_85_byte((char)src[1]) +
  17279             85 * (nk_decode_85_byte((char)src[2]) +
  17280             85 * (nk_decode_85_byte((char)src[3]) +
  17281             85 * nk_decode_85_byte((char)src[4]))));
  17282 
  17283         /* we can't assume little-endianess. */
  17284         dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
  17285         dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
  17286         dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
  17287         dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
  17288 
  17289         src += 5;
  17290         dst += 4;
  17291     }
  17292 }
  17293 
  17294 /* -------------------------------------------------------------
  17295  *
  17296  *                          FONT ATLAS
  17297  *
  17298  * --------------------------------------------------------------*/
  17299 NK_API struct nk_font_config
  17300 nk_font_config(float pixel_height)
  17301 {
  17302     struct nk_font_config cfg;
  17303     nk_zero_struct(cfg);
  17304     cfg.ttf_blob = 0;
  17305     cfg.ttf_size = 0;
  17306     cfg.ttf_data_owned_by_atlas = 0;
  17307     cfg.size = pixel_height;
  17308     cfg.oversample_h = 3;
  17309     cfg.oversample_v = 1;
  17310     cfg.pixel_snap = 0;
  17311     cfg.coord_type = NK_COORD_UV;
  17312     cfg.spacing = nk_vec2(0,0);
  17313     cfg.range = nk_font_default_glyph_ranges();
  17314     cfg.merge_mode = 0;
  17315     cfg.fallback_glyph = '?';
  17316     cfg.font = 0;
  17317     cfg.n = 0;
  17318     return cfg;
  17319 }
  17320 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
  17321 NK_API void
  17322 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
  17323 {
  17324     NK_ASSERT(atlas);
  17325     if (!atlas) return;
  17326     nk_zero_struct(*atlas);
  17327     atlas->temporary.userdata.ptr = 0;
  17328     atlas->temporary.alloc = nk_malloc;
  17329     atlas->temporary.free = nk_mfree;
  17330     atlas->permanent.userdata.ptr = 0;
  17331     atlas->permanent.alloc = nk_malloc;
  17332     atlas->permanent.free = nk_mfree;
  17333 }
  17334 #endif
  17335 NK_API void
  17336 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
  17337 {
  17338     NK_ASSERT(atlas);
  17339     NK_ASSERT(alloc);
  17340     if (!atlas || !alloc) return;
  17341     nk_zero_struct(*atlas);
  17342     atlas->permanent = *alloc;
  17343     atlas->temporary = *alloc;
  17344 }
  17345 NK_API void
  17346 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
  17347     struct nk_allocator *permanent, struct nk_allocator *temporary)
  17348 {
  17349     NK_ASSERT(atlas);
  17350     NK_ASSERT(permanent);
  17351     NK_ASSERT(temporary);
  17352     if (!atlas || !permanent || !temporary) return;
  17353     nk_zero_struct(*atlas);
  17354     atlas->permanent = *permanent;
  17355     atlas->temporary = *temporary;
  17356 }
  17357 NK_API void
  17358 nk_font_atlas_begin(struct nk_font_atlas *atlas)
  17359 {
  17360     NK_ASSERT(atlas);
  17361     NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
  17362     NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
  17363     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
  17364         !atlas->temporary.alloc || !atlas->temporary.free) return;
  17365     if (atlas->glyphs) {
  17366         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
  17367         atlas->glyphs = 0;
  17368     }
  17369     if (atlas->pixel) {
  17370         atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
  17371         atlas->pixel = 0;
  17372     }
  17373 }
  17374 NK_API struct nk_font*
  17375 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
  17376 {
  17377     struct nk_font *font = 0;
  17378     struct nk_font_config *cfg;
  17379 
  17380     NK_ASSERT(atlas);
  17381     NK_ASSERT(atlas->permanent.alloc);
  17382     NK_ASSERT(atlas->permanent.free);
  17383     NK_ASSERT(atlas->temporary.alloc);
  17384     NK_ASSERT(atlas->temporary.free);
  17385 
  17386     NK_ASSERT(config);
  17387     NK_ASSERT(config->ttf_blob);
  17388     NK_ASSERT(config->ttf_size);
  17389     NK_ASSERT(config->size > 0.0f);
  17390 
  17391     if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
  17392         !atlas->permanent.alloc || !atlas->permanent.free ||
  17393         !atlas->temporary.alloc || !atlas->temporary.free)
  17394         return 0;
  17395 
  17396     /* allocate font config  */
  17397     cfg = (struct nk_font_config*)
  17398         atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
  17399     NK_MEMCPY(cfg, config, sizeof(*config));
  17400     cfg->n = cfg;
  17401     cfg->p = cfg;
  17402 
  17403     if (!config->merge_mode) {
  17404         /* insert font config into list */
  17405         if (!atlas->config) {
  17406             atlas->config = cfg;
  17407             cfg->next = 0;
  17408         } else {
  17409             struct nk_font_config *i = atlas->config;
  17410             while (i->next) i = i->next;
  17411             i->next = cfg;
  17412             cfg->next = 0;
  17413         }
  17414         /* allocate new font */
  17415         font = (struct nk_font*)
  17416             atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
  17417         NK_ASSERT(font);
  17418         nk_zero(font, sizeof(*font));
  17419         if (!font) return 0;
  17420         font->config = cfg;
  17421 
  17422         /* insert font into list */
  17423         if (!atlas->fonts) {
  17424             atlas->fonts = font;
  17425             font->next = 0;
  17426         } else {
  17427             struct nk_font *i = atlas->fonts;
  17428             while (i->next) i = i->next;
  17429             i->next = font;
  17430             font->next = 0;
  17431         }
  17432         cfg->font = &font->info;
  17433     } else {
  17434         /* extend previously added font */
  17435         struct nk_font *f = 0;
  17436         struct nk_font_config *c = 0;
  17437         NK_ASSERT(atlas->font_num);
  17438         f = atlas->fonts;
  17439         c = f->config;
  17440         cfg->font = &f->info;
  17441 
  17442         cfg->n = c;
  17443         cfg->p = c->p;
  17444         c->p->n = cfg;
  17445         c->p = cfg;
  17446     }
  17447     /* create own copy of .TTF font blob */
  17448     if (!config->ttf_data_owned_by_atlas) {
  17449         cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
  17450         NK_ASSERT(cfg->ttf_blob);
  17451         if (!cfg->ttf_blob) {
  17452             atlas->font_num++;
  17453             return 0;
  17454         }
  17455         NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
  17456         cfg->ttf_data_owned_by_atlas = 1;
  17457     }
  17458     atlas->font_num++;
  17459     return font;
  17460 }
  17461 NK_API struct nk_font*
  17462 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
  17463     nk_size size, float height, const struct nk_font_config *config)
  17464 {
  17465     struct nk_font_config cfg;
  17466     NK_ASSERT(memory);
  17467     NK_ASSERT(size);
  17468 
  17469     NK_ASSERT(atlas);
  17470     NK_ASSERT(atlas->temporary.alloc);
  17471     NK_ASSERT(atlas->temporary.free);
  17472     NK_ASSERT(atlas->permanent.alloc);
  17473     NK_ASSERT(atlas->permanent.free);
  17474     if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
  17475         !atlas->permanent.alloc || !atlas->permanent.free)
  17476         return 0;
  17477 
  17478     cfg = (config) ? *config: nk_font_config(height);
  17479     cfg.ttf_blob = memory;
  17480     cfg.ttf_size = size;
  17481     cfg.size = height;
  17482     cfg.ttf_data_owned_by_atlas = 0;
  17483     return nk_font_atlas_add(atlas, &cfg);
  17484 }
  17485 #ifdef NK_INCLUDE_STANDARD_IO
  17486 NK_API struct nk_font*
  17487 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
  17488     float height, const struct nk_font_config *config)
  17489 {
  17490     nk_size size;
  17491     char *memory;
  17492     struct nk_font_config cfg;
  17493 
  17494     NK_ASSERT(atlas);
  17495     NK_ASSERT(atlas->temporary.alloc);
  17496     NK_ASSERT(atlas->temporary.free);
  17497     NK_ASSERT(atlas->permanent.alloc);
  17498     NK_ASSERT(atlas->permanent.free);
  17499 
  17500     if (!atlas || !file_path) return 0;
  17501     memory = nk_file_load(file_path, &size, &atlas->permanent);
  17502     if (!memory) return 0;
  17503 
  17504     cfg = (config) ? *config: nk_font_config(height);
  17505     cfg.ttf_blob = memory;
  17506     cfg.ttf_size = size;
  17507     cfg.size = height;
  17508     cfg.ttf_data_owned_by_atlas = 1;
  17509     return nk_font_atlas_add(atlas, &cfg);
  17510 }
  17511 #endif
  17512 NK_API struct nk_font*
  17513 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
  17514     void *compressed_data, nk_size compressed_size, float height,
  17515     const struct nk_font_config *config)
  17516 {
  17517     unsigned int decompressed_size;
  17518     void *decompressed_data;
  17519     struct nk_font_config cfg;
  17520 
  17521     NK_ASSERT(atlas);
  17522     NK_ASSERT(atlas->temporary.alloc);
  17523     NK_ASSERT(atlas->temporary.free);
  17524     NK_ASSERT(atlas->permanent.alloc);
  17525     NK_ASSERT(atlas->permanent.free);
  17526 
  17527     NK_ASSERT(compressed_data);
  17528     NK_ASSERT(compressed_size);
  17529     if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
  17530         !atlas->permanent.alloc || !atlas->permanent.free)
  17531         return 0;
  17532 
  17533     decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
  17534     decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
  17535     NK_ASSERT(decompressed_data);
  17536     if (!decompressed_data) return 0;
  17537     nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
  17538         (unsigned int)compressed_size);
  17539 
  17540     cfg = (config) ? *config: nk_font_config(height);
  17541     cfg.ttf_blob = decompressed_data;
  17542     cfg.ttf_size = decompressed_size;
  17543     cfg.size = height;
  17544     cfg.ttf_data_owned_by_atlas = 1;
  17545     return nk_font_atlas_add(atlas, &cfg);
  17546 }
  17547 NK_API struct nk_font*
  17548 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
  17549     const char *data_base85, float height, const struct nk_font_config *config)
  17550 {
  17551     int compressed_size;
  17552     void *compressed_data;
  17553     struct nk_font *font;
  17554 
  17555     NK_ASSERT(atlas);
  17556     NK_ASSERT(atlas->temporary.alloc);
  17557     NK_ASSERT(atlas->temporary.free);
  17558     NK_ASSERT(atlas->permanent.alloc);
  17559     NK_ASSERT(atlas->permanent.free);
  17560 
  17561     NK_ASSERT(data_base85);
  17562     if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
  17563         !atlas->permanent.alloc || !atlas->permanent.free)
  17564         return 0;
  17565 
  17566     compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
  17567     compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
  17568     NK_ASSERT(compressed_data);
  17569     if (!compressed_data) return 0;
  17570     nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
  17571     font = nk_font_atlas_add_compressed(atlas, compressed_data,
  17572                     (nk_size)compressed_size, height, config);
  17573     atlas->temporary.free(atlas->temporary.userdata, compressed_data);
  17574     return font;
  17575 }
  17576 
  17577 #ifdef NK_INCLUDE_DEFAULT_FONT
  17578 NK_API struct nk_font*
  17579 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
  17580     float pixel_height, const struct nk_font_config *config)
  17581 {
  17582     NK_ASSERT(atlas);
  17583     NK_ASSERT(atlas->temporary.alloc);
  17584     NK_ASSERT(atlas->temporary.free);
  17585     NK_ASSERT(atlas->permanent.alloc);
  17586     NK_ASSERT(atlas->permanent.free);
  17587     return nk_font_atlas_add_compressed_base85(atlas,
  17588         nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
  17589 }
  17590 #endif
  17591 NK_API const void*
  17592 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
  17593     enum nk_font_atlas_format fmt)
  17594 {
  17595     int i = 0;
  17596     void *tmp = 0;
  17597     nk_size tmp_size, img_size;
  17598     struct nk_font *font_iter;
  17599     struct nk_font_baker *baker;
  17600 
  17601     NK_ASSERT(atlas);
  17602     NK_ASSERT(atlas->temporary.alloc);
  17603     NK_ASSERT(atlas->temporary.free);
  17604     NK_ASSERT(atlas->permanent.alloc);
  17605     NK_ASSERT(atlas->permanent.free);
  17606 
  17607     NK_ASSERT(width);
  17608     NK_ASSERT(height);
  17609     if (!atlas || !width || !height ||
  17610         !atlas->temporary.alloc || !atlas->temporary.free ||
  17611         !atlas->permanent.alloc || !atlas->permanent.free)
  17612         return 0;
  17613 
  17614 #ifdef NK_INCLUDE_DEFAULT_FONT
  17615     /* no font added so just use default font */
  17616     if (!atlas->font_num)
  17617         atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
  17618 #endif
  17619     NK_ASSERT(atlas->font_num);
  17620     if (!atlas->font_num) return 0;
  17621 
  17622     /* allocate temporary baker memory required for the baking process */
  17623     nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
  17624     tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
  17625     NK_ASSERT(tmp);
  17626     if (!tmp) goto failed;
  17627     NK_MEMSET(tmp,0,tmp_size);
  17628 
  17629     /* allocate glyph memory for all fonts */
  17630     baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
  17631     atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
  17632         atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
  17633     NK_ASSERT(atlas->glyphs);
  17634     if (!atlas->glyphs)
  17635         goto failed;
  17636 
  17637     /* pack all glyphs into a tight fit space */
  17638     atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
  17639     atlas->custom.h = NK_CURSOR_DATA_H + 1;
  17640     if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
  17641         atlas->config, atlas->font_num, &atlas->temporary))
  17642         goto failed;
  17643 
  17644     /* allocate memory for the baked image font atlas */
  17645     atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
  17646     NK_ASSERT(atlas->pixel);
  17647     if (!atlas->pixel)
  17648         goto failed;
  17649 
  17650     /* bake glyphs and custom white pixel into image */
  17651     nk_font_bake(baker, atlas->pixel, *width, *height,
  17652         atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
  17653     nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
  17654             nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
  17655 
  17656     if (fmt == NK_FONT_ATLAS_RGBA32) {
  17657         /* convert alpha8 image into rgba32 image */
  17658         void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
  17659                             (nk_size)(*width * *height * 4));
  17660         NK_ASSERT(img_rgba);
  17661         if (!img_rgba) goto failed;
  17662         nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
  17663         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
  17664         atlas->pixel = img_rgba;
  17665     }
  17666     atlas->tex_width = *width;
  17667     atlas->tex_height = *height;
  17668 
  17669     /* initialize each font */
  17670     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
  17671         struct nk_font *font = font_iter;
  17672         struct nk_font_config *config = font->config;
  17673         nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
  17674             config->font, nk_handle_ptr(0));
  17675     }
  17676 
  17677     /* initialize each cursor */
  17678     {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
  17679         /* Pos      Size        Offset */
  17680         {{ 0, 3},   {12,19},    { 0, 0}},
  17681         {{13, 0},   { 7,16},    { 4, 8}},
  17682         {{31, 0},   {23,23},    {11,11}},
  17683         {{21, 0},   { 9, 23},   { 5,11}},
  17684         {{55,18},   {23, 9},    {11, 5}},
  17685         {{73, 0},   {17,17},    { 9, 9}},
  17686         {{55, 0},   {17,17},    { 9, 9}}
  17687     };
  17688     for (i = 0; i < NK_CURSOR_COUNT; ++i) {
  17689         struct nk_cursor *cursor = &atlas->cursors[i];
  17690         cursor->img.w = (unsigned short)*width;
  17691         cursor->img.h = (unsigned short)*height;
  17692         cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
  17693         cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
  17694         cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
  17695         cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
  17696         cursor->size = nk_cursor_data[i][1];
  17697         cursor->offset = nk_cursor_data[i][2];
  17698     }}
  17699     /* free temporary memory */
  17700     atlas->temporary.free(atlas->temporary.userdata, tmp);
  17701     return atlas->pixel;
  17702 
  17703 failed:
  17704     /* error so cleanup all memory */
  17705     if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
  17706     if (atlas->glyphs) {
  17707         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
  17708         atlas->glyphs = 0;
  17709     }
  17710     if (atlas->pixel) {
  17711         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
  17712         atlas->pixel = 0;
  17713     }
  17714     return 0;
  17715 }
  17716 NK_API void
  17717 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
  17718     struct nk_draw_null_texture *tex_null)
  17719 {
  17720     int i = 0;
  17721     struct nk_font *font_iter;
  17722     NK_ASSERT(atlas);
  17723     if (!atlas) {
  17724         if (!tex_null) return;
  17725         tex_null->texture = texture;
  17726         tex_null->uv = nk_vec2(0.5f,0.5f);
  17727     }
  17728     if (tex_null) {
  17729         tex_null->texture = texture;
  17730         tex_null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
  17731         tex_null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
  17732     }
  17733     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
  17734         font_iter->texture = texture;
  17735 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  17736         font_iter->handle.texture = texture;
  17737 #endif
  17738     }
  17739     for (i = 0; i < NK_CURSOR_COUNT; ++i)
  17740         atlas->cursors[i].img.handle = texture;
  17741 
  17742     atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
  17743     atlas->pixel = 0;
  17744     atlas->tex_width = 0;
  17745     atlas->tex_height = 0;
  17746     atlas->custom.x = 0;
  17747     atlas->custom.y = 0;
  17748     atlas->custom.w = 0;
  17749     atlas->custom.h = 0;
  17750 }
  17751 NK_API void
  17752 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
  17753 {
  17754     NK_ASSERT(atlas);
  17755     NK_ASSERT(atlas->temporary.alloc);
  17756     NK_ASSERT(atlas->temporary.free);
  17757     NK_ASSERT(atlas->permanent.alloc);
  17758     NK_ASSERT(atlas->permanent.free);
  17759     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
  17760     if (atlas->config) {
  17761         struct nk_font_config *iter;
  17762         for (iter = atlas->config; iter; iter = iter->next) {
  17763             struct nk_font_config *i;
  17764             for (i = iter->n; i != iter; i = i->n) {
  17765                 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
  17766                 i->ttf_blob = 0;
  17767             }
  17768             atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
  17769             iter->ttf_blob = 0;
  17770         }
  17771     }
  17772 }
  17773 NK_API void
  17774 nk_font_atlas_clear(struct nk_font_atlas *atlas)
  17775 {
  17776     NK_ASSERT(atlas);
  17777     NK_ASSERT(atlas->temporary.alloc);
  17778     NK_ASSERT(atlas->temporary.free);
  17779     NK_ASSERT(atlas->permanent.alloc);
  17780     NK_ASSERT(atlas->permanent.free);
  17781     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
  17782 
  17783     if (atlas->config) {
  17784         struct nk_font_config *iter, *next;
  17785         for (iter = atlas->config; iter; iter = next) {
  17786             struct nk_font_config *i, *n;
  17787             for (i = iter->n; i != iter; i = n) {
  17788                 n = i->n;
  17789                 if (i->ttf_blob)
  17790                     atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
  17791                 atlas->permanent.free(atlas->permanent.userdata, i);
  17792             }
  17793             next = iter->next;
  17794             if (i->ttf_blob)
  17795                 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
  17796             atlas->permanent.free(atlas->permanent.userdata, iter);
  17797         }
  17798         atlas->config = 0;
  17799     }
  17800     if (atlas->fonts) {
  17801         struct nk_font *iter, *next;
  17802         for (iter = atlas->fonts; iter; iter = next) {
  17803             next = iter->next;
  17804             atlas->permanent.free(atlas->permanent.userdata, iter);
  17805         }
  17806         atlas->fonts = 0;
  17807     }
  17808     if (atlas->glyphs)
  17809         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
  17810     nk_zero_struct(*atlas);
  17811 }
  17812 #endif
  17813 
  17814 
  17815 
  17816 
  17817 
  17818 /* ===============================================================
  17819  *
  17820  *                          INPUT
  17821  *
  17822  * ===============================================================*/
  17823 NK_API void
  17824 nk_input_begin(struct nk_context *ctx)
  17825 {
  17826     int i;
  17827     struct nk_input *in;
  17828     NK_ASSERT(ctx);
  17829     if (!ctx) return;
  17830     in = &ctx->input;
  17831     for (i = 0; i < NK_BUTTON_MAX; ++i)
  17832         in->mouse.buttons[i].clicked = 0;
  17833 
  17834     in->keyboard.text_len = 0;
  17835     in->mouse.scroll_delta = nk_vec2(0,0);
  17836     in->mouse.prev.x = in->mouse.pos.x;
  17837     in->mouse.prev.y = in->mouse.pos.y;
  17838     in->mouse.delta.x = 0;
  17839     in->mouse.delta.y = 0;
  17840     for (i = 0; i < NK_KEY_MAX; i++)
  17841         in->keyboard.keys[i].clicked = 0;
  17842 }
  17843 NK_API void
  17844 nk_input_end(struct nk_context *ctx)
  17845 {
  17846     struct nk_input *in;
  17847     NK_ASSERT(ctx);
  17848     if (!ctx) return;
  17849     in = &ctx->input;
  17850     if (in->mouse.grab)
  17851         in->mouse.grab = 0;
  17852     if (in->mouse.ungrab) {
  17853         in->mouse.grabbed = 0;
  17854         in->mouse.ungrab = 0;
  17855         in->mouse.grab = 0;
  17856     }
  17857 }
  17858 NK_API void
  17859 nk_input_motion(struct nk_context *ctx, int x, int y)
  17860 {
  17861     struct nk_input *in;
  17862     NK_ASSERT(ctx);
  17863     if (!ctx) return;
  17864     in = &ctx->input;
  17865     in->mouse.pos.x = (float)x;
  17866     in->mouse.pos.y = (float)y;
  17867     in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
  17868     in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
  17869 }
  17870 NK_API void
  17871 nk_input_key(struct nk_context *ctx, enum nk_keys key, nk_bool down)
  17872 {
  17873     struct nk_input *in;
  17874     NK_ASSERT(ctx);
  17875     if (!ctx) return;
  17876     in = &ctx->input;
  17877 #ifdef NK_KEYSTATE_BASED_INPUT
  17878     if (in->keyboard.keys[key].down != down)
  17879         in->keyboard.keys[key].clicked++;
  17880 #else
  17881     in->keyboard.keys[key].clicked++;
  17882 #endif
  17883     in->keyboard.keys[key].down = down;
  17884 }
  17885 NK_API void
  17886 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, nk_bool down)
  17887 {
  17888     struct nk_mouse_button *btn;
  17889     struct nk_input *in;
  17890     NK_ASSERT(ctx);
  17891     if (!ctx) return;
  17892     in = &ctx->input;
  17893     if (in->mouse.buttons[id].down == down) return;
  17894 
  17895     btn = &in->mouse.buttons[id];
  17896     btn->clicked_pos.x = (float)x;
  17897     btn->clicked_pos.y = (float)y;
  17898     btn->down = down;
  17899     btn->clicked++;
  17900 
  17901     /* Fix Click-Drag for touch events. */
  17902     in->mouse.delta.x = 0;
  17903     in->mouse.delta.y = 0;
  17904 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
  17905     if (down == 1 && id == NK_BUTTON_LEFT)
  17906     {
  17907         in->mouse.down_pos.x = btn->clicked_pos.x;
  17908         in->mouse.down_pos.y = btn->clicked_pos.y;
  17909     }
  17910 #endif
  17911 }
  17912 NK_API void
  17913 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
  17914 {
  17915     NK_ASSERT(ctx);
  17916     if (!ctx) return;
  17917     ctx->input.mouse.scroll_delta.x += val.x;
  17918     ctx->input.mouse.scroll_delta.y += val.y;
  17919 }
  17920 NK_API void
  17921 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
  17922 {
  17923     int len = 0;
  17924     nk_rune unicode;
  17925     struct nk_input *in;
  17926 
  17927     NK_ASSERT(ctx);
  17928     if (!ctx) return;
  17929     in = &ctx->input;
  17930 
  17931     len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
  17932     if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
  17933         nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
  17934             NK_INPUT_MAX - in->keyboard.text_len);
  17935         in->keyboard.text_len += len;
  17936     }
  17937 }
  17938 NK_API void
  17939 nk_input_char(struct nk_context *ctx, char c)
  17940 {
  17941     nk_glyph glyph;
  17942     NK_ASSERT(ctx);
  17943     if (!ctx) return;
  17944     glyph[0] = c;
  17945     nk_input_glyph(ctx, glyph);
  17946 }
  17947 NK_API void
  17948 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
  17949 {
  17950     nk_glyph rune;
  17951     NK_ASSERT(ctx);
  17952     if (!ctx) return;
  17953     nk_utf_encode(unicode, rune, NK_UTF_SIZE);
  17954     nk_input_glyph(ctx, rune);
  17955 }
  17956 NK_API nk_bool
  17957 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
  17958 {
  17959     const struct nk_mouse_button *btn;
  17960     if (!i) return nk_false;
  17961     btn = &i->mouse.buttons[id];
  17962     return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
  17963 }
  17964 NK_API nk_bool
  17965 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
  17966     struct nk_rect b)
  17967 {
  17968     const struct nk_mouse_button *btn;
  17969     if (!i) return nk_false;
  17970     btn = &i->mouse.buttons[id];
  17971     if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
  17972         return nk_false;
  17973     return nk_true;
  17974 }
  17975 NK_API nk_bool
  17976 nk_input_has_mouse_click_in_button_rect(const struct nk_input *i, enum nk_buttons id,
  17977     struct nk_rect b)
  17978 {
  17979     const struct nk_mouse_button *btn;
  17980     if (!i) return nk_false;
  17981     btn = &i->mouse.buttons[id];
  17982 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
  17983     if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)
  17984         || !NK_INBOX(i->mouse.down_pos.x,i->mouse.down_pos.y,b.x,b.y,b.w,b.h))
  17985 #else
  17986     if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
  17987 #endif
  17988         return nk_false;
  17989     return nk_true;
  17990 }
  17991 NK_API nk_bool
  17992 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
  17993     struct nk_rect b, nk_bool down)
  17994 {
  17995     const struct nk_mouse_button *btn;
  17996     if (!i) return nk_false;
  17997     btn = &i->mouse.buttons[id];
  17998     return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
  17999 }
  18000 NK_API nk_bool
  18001 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
  18002     struct nk_rect b)
  18003 {
  18004     const struct nk_mouse_button *btn;
  18005     if (!i) return nk_false;
  18006     btn = &i->mouse.buttons[id];
  18007     return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
  18008             btn->clicked) ? nk_true : nk_false;
  18009 }
  18010 NK_API nk_bool
  18011 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
  18012     struct nk_rect b, nk_bool down)
  18013 {
  18014     const struct nk_mouse_button *btn;
  18015     if (!i) return nk_false;
  18016     btn = &i->mouse.buttons[id];
  18017     return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
  18018             btn->clicked) ? nk_true : nk_false;
  18019 }
  18020 NK_API nk_bool
  18021 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
  18022 {
  18023     int i, down = 0;
  18024     for (i = 0; i < NK_BUTTON_MAX; ++i)
  18025         down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
  18026     return down;
  18027 }
  18028 NK_API nk_bool
  18029 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
  18030 {
  18031     if (!i) return nk_false;
  18032     return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
  18033 }
  18034 NK_API nk_bool
  18035 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
  18036 {
  18037     if (!i) return nk_false;
  18038     return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
  18039 }
  18040 NK_API nk_bool
  18041 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
  18042 {
  18043     if (!i) return nk_false;
  18044     if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
  18045     return nk_input_is_mouse_click_in_rect(i, id, rect);
  18046 }
  18047 NK_API nk_bool
  18048 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
  18049 {
  18050     if (!i) return nk_false;
  18051     return i->mouse.buttons[id].down;
  18052 }
  18053 NK_API nk_bool
  18054 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
  18055 {
  18056     const struct nk_mouse_button *b;
  18057     if (!i) return nk_false;
  18058     b = &i->mouse.buttons[id];
  18059     if (b->down && b->clicked)
  18060         return nk_true;
  18061     return nk_false;
  18062 }
  18063 NK_API nk_bool
  18064 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
  18065 {
  18066     if (!i) return nk_false;
  18067     return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
  18068 }
  18069 NK_API nk_bool
  18070 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
  18071 {
  18072     const struct nk_key *k;
  18073     if (!i) return nk_false;
  18074     k = &i->keyboard.keys[key];
  18075     if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
  18076         return nk_true;
  18077     return nk_false;
  18078 }
  18079 NK_API nk_bool
  18080 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
  18081 {
  18082     const struct nk_key *k;
  18083     if (!i) return nk_false;
  18084     k = &i->keyboard.keys[key];
  18085     if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
  18086         return nk_true;
  18087     return nk_false;
  18088 }
  18089 NK_API nk_bool
  18090 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
  18091 {
  18092     const struct nk_key *k;
  18093     if (!i) return nk_false;
  18094     k = &i->keyboard.keys[key];
  18095     if (k->down) return nk_true;
  18096     return nk_false;
  18097 }
  18098 
  18099 
  18100 
  18101 
  18102 
  18103 /* ===============================================================
  18104  *
  18105  *                              STYLE
  18106  *
  18107  * ===============================================================*/
  18108 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
  18109 #define NK_COLOR_MAP(NK_COLOR)\
  18110     NK_COLOR(NK_COLOR_TEXT,                     175,175,175,255) \
  18111     NK_COLOR(NK_COLOR_WINDOW,                   45, 45, 45, 255) \
  18112     NK_COLOR(NK_COLOR_HEADER,                   40, 40, 40, 255) \
  18113     NK_COLOR(NK_COLOR_BORDER,                   65, 65, 65, 255) \
  18114     NK_COLOR(NK_COLOR_BUTTON,                   50, 50, 50, 255) \
  18115     NK_COLOR(NK_COLOR_BUTTON_HOVER,             40, 40, 40, 255) \
  18116     NK_COLOR(NK_COLOR_BUTTON_ACTIVE,            35, 35, 35, 255) \
  18117     NK_COLOR(NK_COLOR_TOGGLE,                   100,100,100,255) \
  18118     NK_COLOR(NK_COLOR_TOGGLE_HOVER,             120,120,120,255) \
  18119     NK_COLOR(NK_COLOR_TOGGLE_CURSOR,            45, 45, 45, 255) \
  18120     NK_COLOR(NK_COLOR_SELECT,                   45, 45, 45, 255) \
  18121     NK_COLOR(NK_COLOR_SELECT_ACTIVE,            35, 35, 35,255) \
  18122     NK_COLOR(NK_COLOR_SLIDER,                   38, 38, 38, 255) \
  18123     NK_COLOR(NK_COLOR_SLIDER_CURSOR,            100,100,100,255) \
  18124     NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER,      120,120,120,255) \
  18125     NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE,     150,150,150,255) \
  18126     NK_COLOR(NK_COLOR_PROPERTY,                 38, 38, 38, 255) \
  18127     NK_COLOR(NK_COLOR_EDIT,                     38, 38, 38, 255)  \
  18128     NK_COLOR(NK_COLOR_EDIT_CURSOR,              175,175,175,255) \
  18129     NK_COLOR(NK_COLOR_COMBO,                    45, 45, 45, 255) \
  18130     NK_COLOR(NK_COLOR_CHART,                    120,120,120,255) \
  18131     NK_COLOR(NK_COLOR_CHART_COLOR,              45, 45, 45, 255) \
  18132     NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,    255, 0,  0, 255) \
  18133     NK_COLOR(NK_COLOR_SCROLLBAR,                40, 40, 40, 255) \
  18134     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR,         100,100,100,255) \
  18135     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,   120,120,120,255) \
  18136     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,  150,150,150,255) \
  18137     NK_COLOR(NK_COLOR_TAB_HEADER,               40, 40, 40,255)
  18138 
  18139 NK_GLOBAL const struct nk_color
  18140 nk_default_color_style[NK_COLOR_COUNT] = {
  18141 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
  18142     NK_COLOR_MAP(NK_COLOR)
  18143 #undef NK_COLOR
  18144 };
  18145 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
  18146 #define NK_COLOR(a,b,c,d,e) #a,
  18147     NK_COLOR_MAP(NK_COLOR)
  18148 #undef NK_COLOR
  18149 };
  18150 
  18151 NK_API const char*
  18152 nk_style_get_color_by_name(enum nk_style_colors c)
  18153 {
  18154     return nk_color_names[c];
  18155 }
  18156 NK_API struct nk_style_item
  18157 nk_style_item_color(struct nk_color col)
  18158 {
  18159     struct nk_style_item i;
  18160     i.type = NK_STYLE_ITEM_COLOR;
  18161     i.data.color = col;
  18162     return i;
  18163 }
  18164 NK_API struct nk_style_item
  18165 nk_style_item_image(struct nk_image img)
  18166 {
  18167     struct nk_style_item i;
  18168     i.type = NK_STYLE_ITEM_IMAGE;
  18169     i.data.image = img;
  18170     return i;
  18171 }
  18172 NK_API struct nk_style_item
  18173 nk_style_item_nine_slice(struct nk_nine_slice slice)
  18174 {
  18175     struct nk_style_item i;
  18176     i.type = NK_STYLE_ITEM_NINE_SLICE;
  18177     i.data.slice = slice;
  18178     return i;
  18179 }
  18180 NK_API struct nk_style_item
  18181 nk_style_item_hide(void)
  18182 {
  18183     struct nk_style_item i;
  18184     i.type = NK_STYLE_ITEM_COLOR;
  18185     i.data.color = nk_rgba(0,0,0,0);
  18186     return i;
  18187 }
  18188 NK_API void
  18189 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
  18190 {
  18191     struct nk_style *style;
  18192     struct nk_style_text *text;
  18193     struct nk_style_button *button;
  18194     struct nk_style_toggle *toggle;
  18195     struct nk_style_selectable *select;
  18196     struct nk_style_slider *slider;
  18197     struct nk_style_progress *prog;
  18198     struct nk_style_scrollbar *scroll;
  18199     struct nk_style_edit *edit;
  18200     struct nk_style_property *property;
  18201     struct nk_style_combo *combo;
  18202     struct nk_style_chart *chart;
  18203     struct nk_style_tab *tab;
  18204     struct nk_style_window *win;
  18205 
  18206     NK_ASSERT(ctx);
  18207     if (!ctx) return;
  18208     style = &ctx->style;
  18209     table = (!table) ? nk_default_color_style: table;
  18210 
  18211     /* default text */
  18212     text = &style->text;
  18213     text->color = table[NK_COLOR_TEXT];
  18214     text->padding = nk_vec2(0,0);
  18215 
  18216     /* default button */
  18217     button = &style->button;
  18218     nk_zero_struct(*button);
  18219     button->normal          = nk_style_item_color(table[NK_COLOR_BUTTON]);
  18220     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
  18221     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
  18222     button->border_color    = table[NK_COLOR_BORDER];
  18223     button->text_background = table[NK_COLOR_BUTTON];
  18224     button->text_normal     = table[NK_COLOR_TEXT];
  18225     button->text_hover      = table[NK_COLOR_TEXT];
  18226     button->text_active     = table[NK_COLOR_TEXT];
  18227     button->padding         = nk_vec2(2.0f,2.0f);
  18228     button->image_padding   = nk_vec2(0.0f,0.0f);
  18229     button->touch_padding   = nk_vec2(0.0f, 0.0f);
  18230     button->userdata        = nk_handle_ptr(0);
  18231     button->text_alignment  = NK_TEXT_CENTERED;
  18232     button->border          = 1.0f;
  18233     button->rounding        = 4.0f;
  18234     button->draw_begin      = 0;
  18235     button->draw_end        = 0;
  18236 
  18237     /* contextual button */
  18238     button = &style->contextual_button;
  18239     nk_zero_struct(*button);
  18240     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  18241     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
  18242     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
  18243     button->border_color    = table[NK_COLOR_WINDOW];
  18244     button->text_background = table[NK_COLOR_WINDOW];
  18245     button->text_normal     = table[NK_COLOR_TEXT];
  18246     button->text_hover      = table[NK_COLOR_TEXT];
  18247     button->text_active     = table[NK_COLOR_TEXT];
  18248     button->padding         = nk_vec2(2.0f,2.0f);
  18249     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18250     button->userdata        = nk_handle_ptr(0);
  18251     button->text_alignment  = NK_TEXT_CENTERED;
  18252     button->border          = 0.0f;
  18253     button->rounding        = 0.0f;
  18254     button->draw_begin      = 0;
  18255     button->draw_end        = 0;
  18256 
  18257     /* menu button */
  18258     button = &style->menu_button;
  18259     nk_zero_struct(*button);
  18260     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  18261     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
  18262     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  18263     button->border_color    = table[NK_COLOR_WINDOW];
  18264     button->text_background = table[NK_COLOR_WINDOW];
  18265     button->text_normal     = table[NK_COLOR_TEXT];
  18266     button->text_hover      = table[NK_COLOR_TEXT];
  18267     button->text_active     = table[NK_COLOR_TEXT];
  18268     button->padding         = nk_vec2(2.0f,2.0f);
  18269     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18270     button->userdata        = nk_handle_ptr(0);
  18271     button->text_alignment  = NK_TEXT_CENTERED;
  18272     button->border          = 0.0f;
  18273     button->rounding        = 1.0f;
  18274     button->draw_begin      = 0;
  18275     button->draw_end        = 0;
  18276 
  18277     /* checkbox toggle */
  18278     toggle = &style->checkbox;
  18279     nk_zero_struct(*toggle);
  18280     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
  18281     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
  18282     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
  18283     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
  18284     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
  18285     toggle->userdata        = nk_handle_ptr(0);
  18286     toggle->text_background = table[NK_COLOR_WINDOW];
  18287     toggle->text_normal     = table[NK_COLOR_TEXT];
  18288     toggle->text_hover      = table[NK_COLOR_TEXT];
  18289     toggle->text_active     = table[NK_COLOR_TEXT];
  18290     toggle->padding         = nk_vec2(2.0f, 2.0f);
  18291     toggle->touch_padding   = nk_vec2(0,0);
  18292     toggle->border_color    = nk_rgba(0,0,0,0);
  18293     toggle->border          = 0.0f;
  18294     toggle->spacing         = 4;
  18295 
  18296     /* option toggle */
  18297     toggle = &style->option;
  18298     nk_zero_struct(*toggle);
  18299     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
  18300     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
  18301     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
  18302     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
  18303     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
  18304     toggle->userdata        = nk_handle_ptr(0);
  18305     toggle->text_background = table[NK_COLOR_WINDOW];
  18306     toggle->text_normal     = table[NK_COLOR_TEXT];
  18307     toggle->text_hover      = table[NK_COLOR_TEXT];
  18308     toggle->text_active     = table[NK_COLOR_TEXT];
  18309     toggle->padding         = nk_vec2(3.0f, 3.0f);
  18310     toggle->touch_padding   = nk_vec2(0,0);
  18311     toggle->border_color    = nk_rgba(0,0,0,0);
  18312     toggle->border          = 0.0f;
  18313     toggle->spacing         = 4;
  18314 
  18315     /* selectable */
  18316     select = &style->selectable;
  18317     nk_zero_struct(*select);
  18318     select->normal          = nk_style_item_color(table[NK_COLOR_SELECT]);
  18319     select->hover           = nk_style_item_color(table[NK_COLOR_SELECT]);
  18320     select->pressed         = nk_style_item_color(table[NK_COLOR_SELECT]);
  18321     select->normal_active   = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
  18322     select->hover_active    = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
  18323     select->pressed_active  = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
  18324     select->text_normal     = table[NK_COLOR_TEXT];
  18325     select->text_hover      = table[NK_COLOR_TEXT];
  18326     select->text_pressed    = table[NK_COLOR_TEXT];
  18327     select->text_normal_active  = table[NK_COLOR_TEXT];
  18328     select->text_hover_active   = table[NK_COLOR_TEXT];
  18329     select->text_pressed_active = table[NK_COLOR_TEXT];
  18330     select->padding         = nk_vec2(2.0f,2.0f);
  18331     select->image_padding   = nk_vec2(2.0f,2.0f);
  18332     select->touch_padding   = nk_vec2(0,0);
  18333     select->userdata        = nk_handle_ptr(0);
  18334     select->rounding        = 0.0f;
  18335     select->draw_begin      = 0;
  18336     select->draw_end        = 0;
  18337 
  18338     /* slider */
  18339     slider = &style->slider;
  18340     nk_zero_struct(*slider);
  18341     slider->normal          = nk_style_item_hide();
  18342     slider->hover           = nk_style_item_hide();
  18343     slider->active          = nk_style_item_hide();
  18344     slider->bar_normal      = table[NK_COLOR_SLIDER];
  18345     slider->bar_hover       = table[NK_COLOR_SLIDER];
  18346     slider->bar_active      = table[NK_COLOR_SLIDER];
  18347     slider->bar_filled      = table[NK_COLOR_SLIDER_CURSOR];
  18348     slider->cursor_normal   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
  18349     slider->cursor_hover    = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
  18350     slider->cursor_active   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
  18351     slider->inc_symbol      = NK_SYMBOL_TRIANGLE_RIGHT;
  18352     slider->dec_symbol      = NK_SYMBOL_TRIANGLE_LEFT;
  18353     slider->cursor_size     = nk_vec2(16,16);
  18354     slider->padding         = nk_vec2(2,2);
  18355     slider->spacing         = nk_vec2(2,2);
  18356     slider->userdata        = nk_handle_ptr(0);
  18357     slider->show_buttons    = nk_false;
  18358     slider->bar_height      = 8;
  18359     slider->rounding        = 0;
  18360     slider->draw_begin      = 0;
  18361     slider->draw_end        = 0;
  18362 
  18363     /* slider buttons */
  18364     button = &style->slider.inc_button;
  18365     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
  18366     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
  18367     button->active          = nk_style_item_color(nk_rgb(44,44,44));
  18368     button->border_color    = nk_rgb(65,65,65);
  18369     button->text_background = nk_rgb(40,40,40);
  18370     button->text_normal     = nk_rgb(175,175,175);
  18371     button->text_hover      = nk_rgb(175,175,175);
  18372     button->text_active     = nk_rgb(175,175,175);
  18373     button->padding         = nk_vec2(8.0f,8.0f);
  18374     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18375     button->userdata        = nk_handle_ptr(0);
  18376     button->text_alignment  = NK_TEXT_CENTERED;
  18377     button->border          = 1.0f;
  18378     button->rounding        = 0.0f;
  18379     button->draw_begin      = 0;
  18380     button->draw_end        = 0;
  18381     style->slider.dec_button = style->slider.inc_button;
  18382 
  18383     /* progressbar */
  18384     prog = &style->progress;
  18385     nk_zero_struct(*prog);
  18386     prog->normal            = nk_style_item_color(table[NK_COLOR_SLIDER]);
  18387     prog->hover             = nk_style_item_color(table[NK_COLOR_SLIDER]);
  18388     prog->active            = nk_style_item_color(table[NK_COLOR_SLIDER]);
  18389     prog->cursor_normal     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
  18390     prog->cursor_hover      = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
  18391     prog->cursor_active     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
  18392     prog->border_color      = nk_rgba(0,0,0,0);
  18393     prog->cursor_border_color = nk_rgba(0,0,0,0);
  18394     prog->userdata          = nk_handle_ptr(0);
  18395     prog->padding           = nk_vec2(4,4);
  18396     prog->rounding          = 0;
  18397     prog->border            = 0;
  18398     prog->cursor_rounding   = 0;
  18399     prog->cursor_border     = 0;
  18400     prog->draw_begin        = 0;
  18401     prog->draw_end          = 0;
  18402 
  18403     /* scrollbars */
  18404     scroll = &style->scrollh;
  18405     nk_zero_struct(*scroll);
  18406     scroll->normal          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
  18407     scroll->hover           = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
  18408     scroll->active          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
  18409     scroll->cursor_normal   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]);
  18410     scroll->cursor_hover    = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]);
  18411     scroll->cursor_active   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]);
  18412     scroll->dec_symbol      = NK_SYMBOL_CIRCLE_SOLID;
  18413     scroll->inc_symbol      = NK_SYMBOL_CIRCLE_SOLID;
  18414     scroll->userdata        = nk_handle_ptr(0);
  18415     scroll->border_color    = table[NK_COLOR_SCROLLBAR];
  18416     scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
  18417     scroll->padding         = nk_vec2(0,0);
  18418     scroll->show_buttons    = nk_false;
  18419     scroll->border          = 0;
  18420     scroll->rounding        = 0;
  18421     scroll->border_cursor   = 0;
  18422     scroll->rounding_cursor = 0;
  18423     scroll->draw_begin      = 0;
  18424     scroll->draw_end        = 0;
  18425     style->scrollv = style->scrollh;
  18426 
  18427     /* scrollbars buttons */
  18428     button = &style->scrollh.inc_button;
  18429     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
  18430     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
  18431     button->active          = nk_style_item_color(nk_rgb(44,44,44));
  18432     button->border_color    = nk_rgb(65,65,65);
  18433     button->text_background = nk_rgb(40,40,40);
  18434     button->text_normal     = nk_rgb(175,175,175);
  18435     button->text_hover      = nk_rgb(175,175,175);
  18436     button->text_active     = nk_rgb(175,175,175);
  18437     button->padding         = nk_vec2(4.0f,4.0f);
  18438     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18439     button->userdata        = nk_handle_ptr(0);
  18440     button->text_alignment  = NK_TEXT_CENTERED;
  18441     button->border          = 1.0f;
  18442     button->rounding        = 0.0f;
  18443     button->draw_begin      = 0;
  18444     button->draw_end        = 0;
  18445     style->scrollh.dec_button = style->scrollh.inc_button;
  18446     style->scrollv.inc_button = style->scrollh.inc_button;
  18447     style->scrollv.dec_button = style->scrollh.inc_button;
  18448 
  18449     /* edit */
  18450     edit = &style->edit;
  18451     nk_zero_struct(*edit);
  18452     edit->normal            = nk_style_item_color(table[NK_COLOR_EDIT]);
  18453     edit->hover             = nk_style_item_color(table[NK_COLOR_EDIT]);
  18454     edit->active            = nk_style_item_color(table[NK_COLOR_EDIT]);
  18455     edit->cursor_normal     = table[NK_COLOR_TEXT];
  18456     edit->cursor_hover      = table[NK_COLOR_TEXT];
  18457     edit->cursor_text_normal= table[NK_COLOR_EDIT];
  18458     edit->cursor_text_hover = table[NK_COLOR_EDIT];
  18459     edit->border_color      = table[NK_COLOR_BORDER];
  18460     edit->text_normal       = table[NK_COLOR_TEXT];
  18461     edit->text_hover        = table[NK_COLOR_TEXT];
  18462     edit->text_active       = table[NK_COLOR_TEXT];
  18463     edit->selected_normal   = table[NK_COLOR_TEXT];
  18464     edit->selected_hover    = table[NK_COLOR_TEXT];
  18465     edit->selected_text_normal  = table[NK_COLOR_EDIT];
  18466     edit->selected_text_hover   = table[NK_COLOR_EDIT];
  18467     edit->scrollbar_size    = nk_vec2(10,10);
  18468     edit->scrollbar         = style->scrollv;
  18469     edit->padding           = nk_vec2(4,4);
  18470     edit->row_padding       = 2;
  18471     edit->cursor_size       = 4;
  18472     edit->border            = 1;
  18473     edit->rounding          = 0;
  18474 
  18475     /* property */
  18476     property = &style->property;
  18477     nk_zero_struct(*property);
  18478     property->normal        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18479     property->hover         = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18480     property->active        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18481     property->border_color  = table[NK_COLOR_BORDER];
  18482     property->label_normal  = table[NK_COLOR_TEXT];
  18483     property->label_hover   = table[NK_COLOR_TEXT];
  18484     property->label_active  = table[NK_COLOR_TEXT];
  18485     property->sym_left      = NK_SYMBOL_TRIANGLE_LEFT;
  18486     property->sym_right     = NK_SYMBOL_TRIANGLE_RIGHT;
  18487     property->userdata      = nk_handle_ptr(0);
  18488     property->padding       = nk_vec2(4,4);
  18489     property->border        = 1;
  18490     property->rounding      = 10;
  18491     property->draw_begin    = 0;
  18492     property->draw_end      = 0;
  18493 
  18494     /* property buttons */
  18495     button = &style->property.dec_button;
  18496     nk_zero_struct(*button);
  18497     button->normal          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18498     button->hover           = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18499     button->active          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18500     button->border_color    = nk_rgba(0,0,0,0);
  18501     button->text_background = table[NK_COLOR_PROPERTY];
  18502     button->text_normal     = table[NK_COLOR_TEXT];
  18503     button->text_hover      = table[NK_COLOR_TEXT];
  18504     button->text_active     = table[NK_COLOR_TEXT];
  18505     button->padding         = nk_vec2(0.0f,0.0f);
  18506     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18507     button->userdata        = nk_handle_ptr(0);
  18508     button->text_alignment  = NK_TEXT_CENTERED;
  18509     button->border          = 0.0f;
  18510     button->rounding        = 0.0f;
  18511     button->draw_begin      = 0;
  18512     button->draw_end        = 0;
  18513     style->property.inc_button = style->property.dec_button;
  18514 
  18515     /* property edit */
  18516     edit = &style->property.edit;
  18517     nk_zero_struct(*edit);
  18518     edit->normal            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18519     edit->hover             = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18520     edit->active            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  18521     edit->border_color      = nk_rgba(0,0,0,0);
  18522     edit->cursor_normal     = table[NK_COLOR_TEXT];
  18523     edit->cursor_hover      = table[NK_COLOR_TEXT];
  18524     edit->cursor_text_normal= table[NK_COLOR_EDIT];
  18525     edit->cursor_text_hover = table[NK_COLOR_EDIT];
  18526     edit->text_normal       = table[NK_COLOR_TEXT];
  18527     edit->text_hover        = table[NK_COLOR_TEXT];
  18528     edit->text_active       = table[NK_COLOR_TEXT];
  18529     edit->selected_normal   = table[NK_COLOR_TEXT];
  18530     edit->selected_hover    = table[NK_COLOR_TEXT];
  18531     edit->selected_text_normal  = table[NK_COLOR_EDIT];
  18532     edit->selected_text_hover   = table[NK_COLOR_EDIT];
  18533     edit->padding           = nk_vec2(0,0);
  18534     edit->cursor_size       = 8;
  18535     edit->border            = 0;
  18536     edit->rounding          = 0;
  18537 
  18538     /* chart */
  18539     chart = &style->chart;
  18540     nk_zero_struct(*chart);
  18541     chart->background       = nk_style_item_color(table[NK_COLOR_CHART]);
  18542     chart->border_color     = table[NK_COLOR_BORDER];
  18543     chart->selected_color   = table[NK_COLOR_CHART_COLOR_HIGHLIGHT];
  18544     chart->color            = table[NK_COLOR_CHART_COLOR];
  18545     chart->padding          = nk_vec2(4,4);
  18546     chart->border           = 0;
  18547     chart->rounding         = 0;
  18548 
  18549     /* combo */
  18550     combo = &style->combo;
  18551     combo->normal           = nk_style_item_color(table[NK_COLOR_COMBO]);
  18552     combo->hover            = nk_style_item_color(table[NK_COLOR_COMBO]);
  18553     combo->active           = nk_style_item_color(table[NK_COLOR_COMBO]);
  18554     combo->border_color     = table[NK_COLOR_BORDER];
  18555     combo->label_normal     = table[NK_COLOR_TEXT];
  18556     combo->label_hover      = table[NK_COLOR_TEXT];
  18557     combo->label_active     = table[NK_COLOR_TEXT];
  18558     combo->sym_normal       = NK_SYMBOL_TRIANGLE_DOWN;
  18559     combo->sym_hover        = NK_SYMBOL_TRIANGLE_DOWN;
  18560     combo->sym_active       = NK_SYMBOL_TRIANGLE_DOWN;
  18561     combo->content_padding  = nk_vec2(4,4);
  18562     combo->button_padding   = nk_vec2(0,4);
  18563     combo->spacing          = nk_vec2(4,0);
  18564     combo->border           = 1;
  18565     combo->rounding         = 0;
  18566 
  18567     /* combo button */
  18568     button = &style->combo.button;
  18569     nk_zero_struct(*button);
  18570     button->normal          = nk_style_item_color(table[NK_COLOR_COMBO]);
  18571     button->hover           = nk_style_item_color(table[NK_COLOR_COMBO]);
  18572     button->active          = nk_style_item_color(table[NK_COLOR_COMBO]);
  18573     button->border_color    = nk_rgba(0,0,0,0);
  18574     button->text_background = table[NK_COLOR_COMBO];
  18575     button->text_normal     = table[NK_COLOR_TEXT];
  18576     button->text_hover      = table[NK_COLOR_TEXT];
  18577     button->text_active     = table[NK_COLOR_TEXT];
  18578     button->padding         = nk_vec2(2.0f,2.0f);
  18579     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18580     button->userdata        = nk_handle_ptr(0);
  18581     button->text_alignment  = NK_TEXT_CENTERED;
  18582     button->border          = 0.0f;
  18583     button->rounding        = 0.0f;
  18584     button->draw_begin      = 0;
  18585     button->draw_end        = 0;
  18586 
  18587     /* tab */
  18588     tab = &style->tab;
  18589     tab->background         = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
  18590     tab->border_color       = table[NK_COLOR_BORDER];
  18591     tab->text               = table[NK_COLOR_TEXT];
  18592     tab->sym_minimize       = NK_SYMBOL_TRIANGLE_RIGHT;
  18593     tab->sym_maximize       = NK_SYMBOL_TRIANGLE_DOWN;
  18594     tab->padding            = nk_vec2(4,4);
  18595     tab->spacing            = nk_vec2(4,4);
  18596     tab->indent             = 10.0f;
  18597     tab->border             = 1;
  18598     tab->rounding           = 0;
  18599 
  18600     /* tab button */
  18601     button = &style->tab.tab_minimize_button;
  18602     nk_zero_struct(*button);
  18603     button->normal          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
  18604     button->hover           = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
  18605     button->active          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
  18606     button->border_color    = nk_rgba(0,0,0,0);
  18607     button->text_background = table[NK_COLOR_TAB_HEADER];
  18608     button->text_normal     = table[NK_COLOR_TEXT];
  18609     button->text_hover      = table[NK_COLOR_TEXT];
  18610     button->text_active     = table[NK_COLOR_TEXT];
  18611     button->padding         = nk_vec2(2.0f,2.0f);
  18612     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18613     button->userdata        = nk_handle_ptr(0);
  18614     button->text_alignment  = NK_TEXT_CENTERED;
  18615     button->border          = 0.0f;
  18616     button->rounding        = 0.0f;
  18617     button->draw_begin      = 0;
  18618     button->draw_end        = 0;
  18619     style->tab.tab_maximize_button =*button;
  18620 
  18621     /* node button */
  18622     button = &style->tab.node_minimize_button;
  18623     nk_zero_struct(*button);
  18624     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  18625     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
  18626     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  18627     button->border_color    = nk_rgba(0,0,0,0);
  18628     button->text_background = table[NK_COLOR_TAB_HEADER];
  18629     button->text_normal     = table[NK_COLOR_TEXT];
  18630     button->text_hover      = table[NK_COLOR_TEXT];
  18631     button->text_active     = table[NK_COLOR_TEXT];
  18632     button->padding         = nk_vec2(2.0f,2.0f);
  18633     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18634     button->userdata        = nk_handle_ptr(0);
  18635     button->text_alignment  = NK_TEXT_CENTERED;
  18636     button->border          = 0.0f;
  18637     button->rounding        = 0.0f;
  18638     button->draw_begin      = 0;
  18639     button->draw_end        = 0;
  18640     style->tab.node_maximize_button =*button;
  18641 
  18642     /* window header */
  18643     win = &style->window;
  18644     win->header.align = NK_HEADER_RIGHT;
  18645     win->header.close_symbol = NK_SYMBOL_X;
  18646     win->header.minimize_symbol = NK_SYMBOL_MINUS;
  18647     win->header.maximize_symbol = NK_SYMBOL_PLUS;
  18648     win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]);
  18649     win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]);
  18650     win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]);
  18651     win->header.label_normal = table[NK_COLOR_TEXT];
  18652     win->header.label_hover = table[NK_COLOR_TEXT];
  18653     win->header.label_active = table[NK_COLOR_TEXT];
  18654     win->header.label_padding = nk_vec2(4,4);
  18655     win->header.padding = nk_vec2(4,4);
  18656     win->header.spacing = nk_vec2(0,0);
  18657 
  18658     /* window header close button */
  18659     button = &style->window.header.close_button;
  18660     nk_zero_struct(*button);
  18661     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
  18662     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
  18663     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
  18664     button->border_color    = nk_rgba(0,0,0,0);
  18665     button->text_background = table[NK_COLOR_HEADER];
  18666     button->text_normal     = table[NK_COLOR_TEXT];
  18667     button->text_hover      = table[NK_COLOR_TEXT];
  18668     button->text_active     = table[NK_COLOR_TEXT];
  18669     button->padding         = nk_vec2(0.0f,0.0f);
  18670     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18671     button->userdata        = nk_handle_ptr(0);
  18672     button->text_alignment  = NK_TEXT_CENTERED;
  18673     button->border          = 0.0f;
  18674     button->rounding        = 0.0f;
  18675     button->draw_begin      = 0;
  18676     button->draw_end        = 0;
  18677 
  18678     /* window header minimize button */
  18679     button = &style->window.header.minimize_button;
  18680     nk_zero_struct(*button);
  18681     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
  18682     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
  18683     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
  18684     button->border_color    = nk_rgba(0,0,0,0);
  18685     button->text_background = table[NK_COLOR_HEADER];
  18686     button->text_normal     = table[NK_COLOR_TEXT];
  18687     button->text_hover      = table[NK_COLOR_TEXT];
  18688     button->text_active     = table[NK_COLOR_TEXT];
  18689     button->padding         = nk_vec2(0.0f,0.0f);
  18690     button->touch_padding   = nk_vec2(0.0f,0.0f);
  18691     button->userdata        = nk_handle_ptr(0);
  18692     button->text_alignment  = NK_TEXT_CENTERED;
  18693     button->border          = 0.0f;
  18694     button->rounding        = 0.0f;
  18695     button->draw_begin      = 0;
  18696     button->draw_end        = 0;
  18697 
  18698     /* window */
  18699     win->background = table[NK_COLOR_WINDOW];
  18700     win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]);
  18701     win->border_color = table[NK_COLOR_BORDER];
  18702     win->popup_border_color = table[NK_COLOR_BORDER];
  18703     win->combo_border_color = table[NK_COLOR_BORDER];
  18704     win->contextual_border_color = table[NK_COLOR_BORDER];
  18705     win->menu_border_color = table[NK_COLOR_BORDER];
  18706     win->group_border_color = table[NK_COLOR_BORDER];
  18707     win->tooltip_border_color = table[NK_COLOR_BORDER];
  18708     win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
  18709 
  18710     win->rounding = 0.0f;
  18711     win->spacing = nk_vec2(4,4);
  18712     win->scrollbar_size = nk_vec2(10,10);
  18713     win->min_size = nk_vec2(64,64);
  18714 
  18715     win->combo_border = 1.0f;
  18716     win->contextual_border = 1.0f;
  18717     win->menu_border = 1.0f;
  18718     win->group_border = 1.0f;
  18719     win->tooltip_border = 1.0f;
  18720     win->popup_border = 1.0f;
  18721     win->border = 2.0f;
  18722     win->min_row_height_padding = 8;
  18723 
  18724     win->padding = nk_vec2(4,4);
  18725     win->group_padding = nk_vec2(4,4);
  18726     win->popup_padding = nk_vec2(4,4);
  18727     win->combo_padding = nk_vec2(4,4);
  18728     win->contextual_padding = nk_vec2(4,4);
  18729     win->menu_padding = nk_vec2(4,4);
  18730     win->tooltip_padding = nk_vec2(4,4);
  18731 }
  18732 NK_API void
  18733 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
  18734 {
  18735     struct nk_style *style;
  18736     NK_ASSERT(ctx);
  18737 
  18738     if (!ctx) return;
  18739     style = &ctx->style;
  18740     style->font = font;
  18741     ctx->stacks.fonts.head = 0;
  18742     if (ctx->current)
  18743         nk_layout_reset_min_row_height(ctx);
  18744 }
  18745 NK_API nk_bool
  18746 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
  18747 {
  18748     struct nk_config_stack_user_font *font_stack;
  18749     struct nk_config_stack_user_font_element *element;
  18750 
  18751     NK_ASSERT(ctx);
  18752     if (!ctx) return 0;
  18753 
  18754     font_stack = &ctx->stacks.fonts;
  18755     NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
  18756     if (font_stack->head >= (int)NK_LEN(font_stack->elements))
  18757         return 0;
  18758 
  18759     element = &font_stack->elements[font_stack->head++];
  18760     element->address = &ctx->style.font;
  18761     element->old_value = ctx->style.font;
  18762     ctx->style.font = font;
  18763     return 1;
  18764 }
  18765 NK_API nk_bool
  18766 nk_style_pop_font(struct nk_context *ctx)
  18767 {
  18768     struct nk_config_stack_user_font *font_stack;
  18769     struct nk_config_stack_user_font_element *element;
  18770 
  18771     NK_ASSERT(ctx);
  18772     if (!ctx) return 0;
  18773 
  18774     font_stack = &ctx->stacks.fonts;
  18775     NK_ASSERT(font_stack->head > 0);
  18776     if (font_stack->head < 1)
  18777         return 0;
  18778 
  18779     element = &font_stack->elements[--font_stack->head];
  18780     *element->address = element->old_value;
  18781     return 1;
  18782 }
  18783 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
  18784 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
  18785 {\
  18786     struct nk_config_stack_##type * type_stack;\
  18787     struct nk_config_stack_##type##_element *element;\
  18788     NK_ASSERT(ctx);\
  18789     if (!ctx) return 0;\
  18790     type_stack = &ctx->stacks.stack;\
  18791     NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
  18792     if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
  18793         return 0;\
  18794     element = &type_stack->elements[type_stack->head++];\
  18795     element->address = address;\
  18796     element->old_value = *address;\
  18797     *address = value;\
  18798     return 1;\
  18799 }
  18800 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
  18801 nk_style_pop_##type(struct nk_context *ctx)\
  18802 {\
  18803     struct nk_config_stack_##type *type_stack;\
  18804     struct nk_config_stack_##type##_element *element;\
  18805     NK_ASSERT(ctx);\
  18806     if (!ctx) return 0;\
  18807     type_stack = &ctx->stacks.stack;\
  18808     NK_ASSERT(type_stack->head > 0);\
  18809     if (type_stack->head < 1)\
  18810         return 0;\
  18811     element = &type_stack->elements[--type_stack->head];\
  18812     *element->address = element->old_value;\
  18813     return 1;\
  18814 }
  18815 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
  18816 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
  18817 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
  18818 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
  18819 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
  18820 
  18821 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
  18822 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(float,floats)
  18823 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
  18824 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(flags,flags)
  18825 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(color,colors)
  18826 
  18827 NK_API nk_bool
  18828 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
  18829 {
  18830     struct nk_style *style;
  18831     NK_ASSERT(ctx);
  18832     if (!ctx) return 0;
  18833     style = &ctx->style;
  18834     if (style->cursors[c]) {
  18835         style->cursor_active = style->cursors[c];
  18836         return 1;
  18837     }
  18838     return 0;
  18839 }
  18840 NK_API void
  18841 nk_style_show_cursor(struct nk_context *ctx)
  18842 {
  18843     ctx->style.cursor_visible = nk_true;
  18844 }
  18845 NK_API void
  18846 nk_style_hide_cursor(struct nk_context *ctx)
  18847 {
  18848     ctx->style.cursor_visible = nk_false;
  18849 }
  18850 NK_API void
  18851 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
  18852     const struct nk_cursor *c)
  18853 {
  18854     struct nk_style *style;
  18855     NK_ASSERT(ctx);
  18856     if (!ctx) return;
  18857     style = &ctx->style;
  18858     style->cursors[cursor] = c;
  18859 }
  18860 NK_API void
  18861 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors)
  18862 {
  18863     int i = 0;
  18864     struct nk_style *style;
  18865     NK_ASSERT(ctx);
  18866     if (!ctx) return;
  18867     style = &ctx->style;
  18868     for (i = 0; i < NK_CURSOR_COUNT; ++i)
  18869         style->cursors[i] = &cursors[i];
  18870     style->cursor_visible = nk_true;
  18871 }
  18872 
  18873 
  18874 
  18875 
  18876 
  18877 /* ==============================================================
  18878  *
  18879  *                          CONTEXT
  18880  *
  18881  * ===============================================================*/
  18882 NK_INTERN void
  18883 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
  18884 {
  18885     NK_ASSERT(ctx);
  18886     if (!ctx) return;
  18887     nk_zero_struct(*ctx);
  18888     nk_style_default(ctx);
  18889     ctx->seq = 1;
  18890     if (font) ctx->style.font = font;
  18891 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  18892     nk_draw_list_init(&ctx->draw_list);
  18893 #endif
  18894 }
  18895 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
  18896 NK_API nk_bool
  18897 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
  18898 {
  18899     struct nk_allocator alloc;
  18900     alloc.userdata.ptr = 0;
  18901     alloc.alloc = nk_malloc;
  18902     alloc.free = nk_mfree;
  18903     return nk_init(ctx, &alloc, font);
  18904 }
  18905 #endif
  18906 NK_API nk_bool
  18907 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
  18908     const struct nk_user_font *font)
  18909 {
  18910     NK_ASSERT(memory);
  18911     if (!memory) return 0;
  18912     nk_setup(ctx, font);
  18913     nk_buffer_init_fixed(&ctx->memory, memory, size);
  18914     ctx->use_pool = nk_false;
  18915     return 1;
  18916 }
  18917 NK_API nk_bool
  18918 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
  18919     struct nk_buffer *pool, const struct nk_user_font *font)
  18920 {
  18921     NK_ASSERT(cmds);
  18922     NK_ASSERT(pool);
  18923     if (!cmds || !pool) return 0;
  18924 
  18925     nk_setup(ctx, font);
  18926     ctx->memory = *cmds;
  18927     if (pool->type == NK_BUFFER_FIXED) {
  18928         /* take memory from buffer and alloc fixed pool */
  18929         nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
  18930     } else {
  18931         /* create dynamic pool from buffer allocator */
  18932         struct nk_allocator *alloc = &pool->pool;
  18933         nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
  18934     }
  18935     ctx->use_pool = nk_true;
  18936     return 1;
  18937 }
  18938 NK_API nk_bool
  18939 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
  18940     const struct nk_user_font *font)
  18941 {
  18942     NK_ASSERT(alloc);
  18943     if (!alloc) return 0;
  18944     nk_setup(ctx, font);
  18945     nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
  18946     nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
  18947     ctx->use_pool = nk_true;
  18948     return 1;
  18949 }
  18950 #ifdef NK_INCLUDE_COMMAND_USERDATA
  18951 NK_API void
  18952 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
  18953 {
  18954     if (!ctx) return;
  18955     ctx->userdata = handle;
  18956     if (ctx->current)
  18957         ctx->current->buffer.userdata = handle;
  18958 }
  18959 #endif
  18960 NK_API void
  18961 nk_free(struct nk_context *ctx)
  18962 {
  18963     NK_ASSERT(ctx);
  18964     if (!ctx) return;
  18965     nk_buffer_free(&ctx->memory);
  18966     if (ctx->use_pool)
  18967         nk_pool_free(&ctx->pool);
  18968 
  18969     nk_zero(&ctx->input, sizeof(ctx->input));
  18970     nk_zero(&ctx->style, sizeof(ctx->style));
  18971     nk_zero(&ctx->memory, sizeof(ctx->memory));
  18972 
  18973     ctx->seq = 0;
  18974     ctx->build = 0;
  18975     ctx->begin = 0;
  18976     ctx->end = 0;
  18977     ctx->active = 0;
  18978     ctx->current = 0;
  18979     ctx->freelist = 0;
  18980     ctx->count = 0;
  18981 }
  18982 NK_API void
  18983 nk_clear(struct nk_context *ctx)
  18984 {
  18985     struct nk_window *iter;
  18986     struct nk_window *next;
  18987     NK_ASSERT(ctx);
  18988 
  18989     if (!ctx) return;
  18990     if (ctx->use_pool)
  18991         nk_buffer_clear(&ctx->memory);
  18992     else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
  18993 
  18994     ctx->build = 0;
  18995     ctx->memory.calls = 0;
  18996     ctx->last_widget_state = 0;
  18997     ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
  18998     NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
  18999 
  19000     /* garbage collector */
  19001     iter = ctx->begin;
  19002     while (iter) {
  19003         /* make sure valid minimized windows do not get removed */
  19004         if ((iter->flags & NK_WINDOW_MINIMIZED) &&
  19005             !(iter->flags & NK_WINDOW_CLOSED) &&
  19006             iter->seq == ctx->seq) {
  19007             iter = iter->next;
  19008             continue;
  19009         }
  19010         /* remove hotness from hidden or closed windows*/
  19011         if (((iter->flags & NK_WINDOW_HIDDEN) ||
  19012             (iter->flags & NK_WINDOW_CLOSED)) &&
  19013             iter == ctx->active) {
  19014             ctx->active = iter->prev;
  19015             ctx->end = iter->prev;
  19016             if (!ctx->end)
  19017                 ctx->begin = 0;
  19018             if (ctx->active)
  19019                 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
  19020         }
  19021         /* free unused popup windows */
  19022         if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
  19023             nk_free_window(ctx, iter->popup.win);
  19024             iter->popup.win = 0;
  19025         }
  19026         /* remove unused window state tables */
  19027         {struct nk_table *n, *it = iter->tables;
  19028         while (it) {
  19029             n = it->next;
  19030             if (it->seq != ctx->seq) {
  19031                 nk_remove_table(iter, it);
  19032                 nk_zero(it, sizeof(union nk_page_data));
  19033                 nk_free_table(ctx, it);
  19034                 if (it == iter->tables)
  19035                     iter->tables = n;
  19036             } it = n;
  19037         }}
  19038         /* window itself is not used anymore so free */
  19039         if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
  19040             next = iter->next;
  19041             nk_remove_window(ctx, iter);
  19042             nk_free_window(ctx, iter);
  19043             iter = next;
  19044         } else iter = iter->next;
  19045     }
  19046     ctx->seq++;
  19047 }
  19048 NK_LIB void
  19049 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
  19050 {
  19051     NK_ASSERT(ctx);
  19052     NK_ASSERT(buffer);
  19053     if (!ctx || !buffer) return;
  19054     buffer->begin = ctx->memory.allocated;
  19055     buffer->end = buffer->begin;
  19056     buffer->last = buffer->begin;
  19057     buffer->clip = nk_null_rect;
  19058 }
  19059 NK_LIB void
  19060 nk_start(struct nk_context *ctx, struct nk_window *win)
  19061 {
  19062     NK_ASSERT(ctx);
  19063     NK_ASSERT(win);
  19064     nk_start_buffer(ctx, &win->buffer);
  19065 }
  19066 NK_LIB void
  19067 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
  19068 {
  19069     struct nk_popup_buffer *buf;
  19070     NK_ASSERT(ctx);
  19071     NK_ASSERT(win);
  19072     if (!ctx || !win) return;
  19073 
  19074     /* save buffer fill state for popup */
  19075     buf = &win->popup.buf;
  19076     buf->begin = win->buffer.end;
  19077     buf->end = win->buffer.end;
  19078     buf->parent = win->buffer.last;
  19079     buf->last = buf->begin;
  19080     buf->active = nk_true;
  19081 }
  19082 NK_LIB void
  19083 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
  19084 {
  19085     struct nk_popup_buffer *buf;
  19086     NK_ASSERT(ctx);
  19087     NK_ASSERT(win);
  19088     if (!ctx || !win) return;
  19089 
  19090     buf = &win->popup.buf;
  19091     buf->last = win->buffer.last;
  19092     buf->end = win->buffer.end;
  19093 }
  19094 NK_LIB void
  19095 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
  19096 {
  19097     NK_ASSERT(ctx);
  19098     NK_ASSERT(buffer);
  19099     if (!ctx || !buffer) return;
  19100     buffer->end = ctx->memory.allocated;
  19101 }
  19102 NK_LIB void
  19103 nk_finish(struct nk_context *ctx, struct nk_window *win)
  19104 {
  19105     struct nk_popup_buffer *buf;
  19106     struct nk_command *parent_last;
  19107     void *memory;
  19108 
  19109     NK_ASSERT(ctx);
  19110     NK_ASSERT(win);
  19111     if (!ctx || !win) return;
  19112     nk_finish_buffer(ctx, &win->buffer);
  19113     if (!win->popup.buf.active) return;
  19114 
  19115     buf = &win->popup.buf;
  19116     memory = ctx->memory.memory.ptr;
  19117     parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
  19118     parent_last->next = buf->end;
  19119 }
  19120 NK_LIB void
  19121 nk_build(struct nk_context *ctx)
  19122 {
  19123     struct nk_window *it = 0;
  19124     struct nk_command *cmd = 0;
  19125     nk_byte *buffer = 0;
  19126 
  19127     /* draw cursor overlay */
  19128     if (!ctx->style.cursor_active)
  19129         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
  19130     if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
  19131         struct nk_rect mouse_bounds;
  19132         const struct nk_cursor *cursor = ctx->style.cursor_active;
  19133         nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
  19134         nk_start_buffer(ctx, &ctx->overlay);
  19135 
  19136         mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
  19137         mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
  19138         mouse_bounds.w = cursor->size.x;
  19139         mouse_bounds.h = cursor->size.y;
  19140 
  19141         nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
  19142         nk_finish_buffer(ctx, &ctx->overlay);
  19143     }
  19144     /* build one big draw command list out of all window buffers */
  19145     it = ctx->begin;
  19146     buffer = (nk_byte*)ctx->memory.memory.ptr;
  19147     while (it != 0) {
  19148         struct nk_window *next = it->next;
  19149         if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
  19150             it->seq != ctx->seq)
  19151             goto cont;
  19152 
  19153         cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
  19154         while (next && ((next->buffer.last == next->buffer.begin) ||
  19155             (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
  19156             next = next->next; /* skip empty command buffers */
  19157 
  19158         if (next) cmd->next = next->buffer.begin;
  19159         cont: it = next;
  19160     }
  19161     /* append all popup draw commands into lists */
  19162     it = ctx->begin;
  19163     while (it != 0) {
  19164         struct nk_window *next = it->next;
  19165         struct nk_popup_buffer *buf;
  19166         if (!it->popup.buf.active)
  19167             goto skip;
  19168 
  19169         buf = &it->popup.buf;
  19170         cmd->next = buf->begin;
  19171         cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
  19172         buf->active = nk_false;
  19173         skip: it = next;
  19174     }
  19175     if (cmd) {
  19176         /* append overlay commands */
  19177         if (ctx->overlay.end != ctx->overlay.begin)
  19178             cmd->next = ctx->overlay.begin;
  19179         else cmd->next = ctx->memory.allocated;
  19180     }
  19181 }
  19182 NK_API const struct nk_command*
  19183 nk__begin(struct nk_context *ctx)
  19184 {
  19185     struct nk_window *iter;
  19186     nk_byte *buffer;
  19187     NK_ASSERT(ctx);
  19188     if (!ctx) return 0;
  19189     if (!ctx->count) return 0;
  19190 
  19191     buffer = (nk_byte*)ctx->memory.memory.ptr;
  19192     if (!ctx->build) {
  19193         nk_build(ctx);
  19194         ctx->build = nk_true;
  19195     }
  19196     iter = ctx->begin;
  19197     while (iter && ((iter->buffer.begin == iter->buffer.end) ||
  19198         (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
  19199         iter = iter->next;
  19200     if (!iter) return 0;
  19201     return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
  19202 }
  19203 
  19204 NK_API const struct nk_command*
  19205 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
  19206 {
  19207     nk_byte *buffer;
  19208     const struct nk_command *next;
  19209     NK_ASSERT(ctx);
  19210     if (!ctx || !cmd || !ctx->count) return 0;
  19211     if (cmd->next >= ctx->memory.allocated) return 0;
  19212     buffer = (nk_byte*)ctx->memory.memory.ptr;
  19213     next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
  19214     return next;
  19215 }
  19216 
  19217 
  19218 
  19219 
  19220 
  19221 
  19222 /* ===============================================================
  19223  *
  19224  *                              POOL
  19225  *
  19226  * ===============================================================*/
  19227 NK_LIB void
  19228 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
  19229     unsigned int capacity)
  19230 {
  19231     NK_ASSERT(capacity >= 1);
  19232     nk_zero(pool, sizeof(*pool));
  19233     pool->alloc = *alloc;
  19234     pool->capacity = capacity;
  19235     pool->type = NK_BUFFER_DYNAMIC;
  19236     pool->pages = 0;
  19237 }
  19238 NK_LIB void
  19239 nk_pool_free(struct nk_pool *pool)
  19240 {
  19241     struct nk_page *iter;
  19242     if (!pool) return;
  19243     iter = pool->pages;
  19244     if (pool->type == NK_BUFFER_FIXED) return;
  19245     while (iter) {
  19246         struct nk_page *next = iter->next;
  19247         pool->alloc.free(pool->alloc.userdata, iter);
  19248         iter = next;
  19249     }
  19250 }
  19251 NK_LIB void
  19252 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
  19253 {
  19254     nk_zero(pool, sizeof(*pool));
  19255     NK_ASSERT(size >= sizeof(struct nk_page));
  19256     if (size < sizeof(struct nk_page)) return;
  19257     /* first nk_page_element is embedded in nk_page, additional elements follow in adjacent space */
  19258     pool->capacity = (unsigned)(1 + (size - sizeof(struct nk_page)) / sizeof(struct nk_page_element));
  19259     pool->pages = (struct nk_page*)memory;
  19260     pool->type = NK_BUFFER_FIXED;
  19261     pool->size = size;
  19262 }
  19263 NK_LIB struct nk_page_element*
  19264 nk_pool_alloc(struct nk_pool *pool)
  19265 {
  19266     if (!pool->pages || pool->pages->size >= pool->capacity) {
  19267         /* allocate new page */
  19268         struct nk_page *page;
  19269         if (pool->type == NK_BUFFER_FIXED) {
  19270             NK_ASSERT(pool->pages);
  19271             if (!pool->pages) return 0;
  19272             NK_ASSERT(pool->pages->size < pool->capacity);
  19273             return 0;
  19274         } else {
  19275             nk_size size = sizeof(struct nk_page);
  19276             size += (pool->capacity - 1) * sizeof(struct nk_page_element);
  19277             page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
  19278             page->next = pool->pages;
  19279             pool->pages = page;
  19280             page->size = 0;
  19281         }
  19282     } return &pool->pages->win[pool->pages->size++];
  19283 }
  19284 
  19285 
  19286 
  19287 
  19288 
  19289 /* ===============================================================
  19290  *
  19291  *                          PAGE ELEMENT
  19292  *
  19293  * ===============================================================*/
  19294 NK_LIB struct nk_page_element*
  19295 nk_create_page_element(struct nk_context *ctx)
  19296 {
  19297     struct nk_page_element *elem;
  19298     if (ctx->freelist) {
  19299         /* unlink page element from free list */
  19300         elem = ctx->freelist;
  19301         ctx->freelist = elem->next;
  19302     } else if (ctx->use_pool) {
  19303         /* allocate page element from memory pool */
  19304         elem = nk_pool_alloc(&ctx->pool);
  19305         NK_ASSERT(elem);
  19306         if (!elem) return 0;
  19307     } else {
  19308         /* allocate new page element from back of fixed size memory buffer */
  19309         NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
  19310         NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
  19311         elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
  19312         NK_ASSERT(elem);
  19313         if (!elem) return 0;
  19314     }
  19315     nk_zero_struct(*elem);
  19316     elem->next = 0;
  19317     elem->prev = 0;
  19318     return elem;
  19319 }
  19320 NK_LIB void
  19321 nk_link_page_element_into_freelist(struct nk_context *ctx,
  19322     struct nk_page_element *elem)
  19323 {
  19324     /* link table into freelist */
  19325     if (!ctx->freelist) {
  19326         ctx->freelist = elem;
  19327     } else {
  19328         elem->next = ctx->freelist;
  19329         ctx->freelist = elem;
  19330     }
  19331 }
  19332 NK_LIB void
  19333 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
  19334 {
  19335     /* we have a pool so just add to free list */
  19336     if (ctx->use_pool) {
  19337         nk_link_page_element_into_freelist(ctx, elem);
  19338         return;
  19339     }
  19340     /* if possible remove last element from back of fixed memory buffer */
  19341     {void *elem_end = (void*)(elem + 1);
  19342     void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
  19343     if (elem_end == buffer_end)
  19344         ctx->memory.size -= sizeof(struct nk_page_element);
  19345     else nk_link_page_element_into_freelist(ctx, elem);}
  19346 }
  19347 
  19348 
  19349 
  19350 
  19351 
  19352 /* ===============================================================
  19353  *
  19354  *                              TABLE
  19355  *
  19356  * ===============================================================*/
  19357 NK_LIB struct nk_table*
  19358 nk_create_table(struct nk_context *ctx)
  19359 {
  19360     struct nk_page_element *elem;
  19361     elem = nk_create_page_element(ctx);
  19362     if (!elem) return 0;
  19363     nk_zero_struct(*elem);
  19364     return &elem->data.tbl;
  19365 }
  19366 NK_LIB void
  19367 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
  19368 {
  19369     union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
  19370     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
  19371     nk_free_page_element(ctx, pe);
  19372 }
  19373 NK_LIB void
  19374 nk_push_table(struct nk_window *win, struct nk_table *tbl)
  19375 {
  19376     if (!win->tables) {
  19377         win->tables = tbl;
  19378         tbl->next = 0;
  19379         tbl->prev = 0;
  19380         tbl->size = 0;
  19381         win->table_count = 1;
  19382         return;
  19383     }
  19384     win->tables->prev = tbl;
  19385     tbl->next = win->tables;
  19386     tbl->prev = 0;
  19387     tbl->size = 0;
  19388     win->tables = tbl;
  19389     win->table_count++;
  19390 }
  19391 NK_LIB void
  19392 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
  19393 {
  19394     if (win->tables == tbl)
  19395         win->tables = tbl->next;
  19396     if (tbl->next)
  19397         tbl->next->prev = tbl->prev;
  19398     if (tbl->prev)
  19399         tbl->prev->next = tbl->next;
  19400     tbl->next = 0;
  19401     tbl->prev = 0;
  19402 }
  19403 NK_LIB nk_uint*
  19404 nk_add_value(struct nk_context *ctx, struct nk_window *win,
  19405             nk_hash name, nk_uint value)
  19406 {
  19407     NK_ASSERT(ctx);
  19408     NK_ASSERT(win);
  19409     if (!win || !ctx) return 0;
  19410     if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
  19411         struct nk_table *tbl = nk_create_table(ctx);
  19412         NK_ASSERT(tbl);
  19413         if (!tbl) return 0;
  19414         nk_push_table(win, tbl);
  19415     }
  19416     win->tables->seq = win->seq;
  19417     win->tables->keys[win->tables->size] = name;
  19418     win->tables->values[win->tables->size] = value;
  19419     return &win->tables->values[win->tables->size++];
  19420 }
  19421 NK_LIB nk_uint*
  19422 nk_find_value(struct nk_window *win, nk_hash name)
  19423 {
  19424     struct nk_table *iter = win->tables;
  19425     while (iter) {
  19426         unsigned int i = 0;
  19427         unsigned int size = iter->size;
  19428         for (i = 0; i < size; ++i) {
  19429             if (iter->keys[i] == name) {
  19430                 iter->seq = win->seq;
  19431                 return &iter->values[i];
  19432             }
  19433         } size = NK_VALUE_PAGE_CAPACITY;
  19434         iter = iter->next;
  19435     }
  19436     return 0;
  19437 }
  19438 
  19439 
  19440 
  19441 
  19442 
  19443 /* ===============================================================
  19444  *
  19445  *                              PANEL
  19446  *
  19447  * ===============================================================*/
  19448 NK_LIB void*
  19449 nk_create_panel(struct nk_context *ctx)
  19450 {
  19451     struct nk_page_element *elem;
  19452     elem = nk_create_page_element(ctx);
  19453     if (!elem) return 0;
  19454     nk_zero_struct(*elem);
  19455     return &elem->data.pan;
  19456 }
  19457 NK_LIB void
  19458 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
  19459 {
  19460     union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
  19461     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
  19462     nk_free_page_element(ctx, pe);
  19463 }
  19464 NK_LIB nk_bool
  19465 nk_panel_has_header(nk_flags flags, const char *title)
  19466 {
  19467     nk_bool active = 0;
  19468     active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
  19469     active = active || (flags & NK_WINDOW_TITLE);
  19470     active = active && !(flags & NK_WINDOW_HIDDEN) && title;
  19471     return active;
  19472 }
  19473 NK_LIB struct nk_vec2
  19474 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
  19475 {
  19476     switch (type) {
  19477     default:
  19478     case NK_PANEL_WINDOW: return style->window.padding;
  19479     case NK_PANEL_GROUP: return style->window.group_padding;
  19480     case NK_PANEL_POPUP: return style->window.popup_padding;
  19481     case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
  19482     case NK_PANEL_COMBO: return style->window.combo_padding;
  19483     case NK_PANEL_MENU: return style->window.menu_padding;
  19484     case NK_PANEL_TOOLTIP: return style->window.menu_padding;}
  19485 }
  19486 NK_LIB float
  19487 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
  19488     enum nk_panel_type type)
  19489 {
  19490     if (flags & NK_WINDOW_BORDER) {
  19491         switch (type) {
  19492         default:
  19493         case NK_PANEL_WINDOW: return style->window.border;
  19494         case NK_PANEL_GROUP: return style->window.group_border;
  19495         case NK_PANEL_POPUP: return style->window.popup_border;
  19496         case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
  19497         case NK_PANEL_COMBO: return style->window.combo_border;
  19498         case NK_PANEL_MENU: return style->window.menu_border;
  19499         case NK_PANEL_TOOLTIP: return style->window.menu_border;
  19500     }} else return 0;
  19501 }
  19502 NK_LIB struct nk_color
  19503 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
  19504 {
  19505     switch (type) {
  19506     default:
  19507     case NK_PANEL_WINDOW: return style->window.border_color;
  19508     case NK_PANEL_GROUP: return style->window.group_border_color;
  19509     case NK_PANEL_POPUP: return style->window.popup_border_color;
  19510     case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
  19511     case NK_PANEL_COMBO: return style->window.combo_border_color;
  19512     case NK_PANEL_MENU: return style->window.menu_border_color;
  19513     case NK_PANEL_TOOLTIP: return style->window.menu_border_color;}
  19514 }
  19515 NK_LIB nk_bool
  19516 nk_panel_is_sub(enum nk_panel_type type)
  19517 {
  19518     return (type & NK_PANEL_SET_SUB)?1:0;
  19519 }
  19520 NK_LIB nk_bool
  19521 nk_panel_is_nonblock(enum nk_panel_type type)
  19522 {
  19523     return (type & NK_PANEL_SET_NONBLOCK)?1:0;
  19524 }
  19525 NK_LIB nk_bool
  19526 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
  19527 {
  19528     struct nk_input *in;
  19529     struct nk_window *win;
  19530     struct nk_panel *layout;
  19531     struct nk_command_buffer *out;
  19532     const struct nk_style *style;
  19533     const struct nk_user_font *font;
  19534 
  19535     struct nk_vec2 scrollbar_size;
  19536     struct nk_vec2 panel_padding;
  19537 
  19538     NK_ASSERT(ctx);
  19539     NK_ASSERT(ctx->current);
  19540     NK_ASSERT(ctx->current->layout);
  19541     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
  19542     nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
  19543     if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
  19544         nk_zero(ctx->current->layout, sizeof(struct nk_panel));
  19545         ctx->current->layout->type = panel_type;
  19546         return 0;
  19547     }
  19548     /* pull state into local stack */
  19549     style = &ctx->style;
  19550     font = style->font;
  19551     win = ctx->current;
  19552     layout = win->layout;
  19553     out = &win->buffer;
  19554     in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
  19555 #ifdef NK_INCLUDE_COMMAND_USERDATA
  19556     win->buffer.userdata = ctx->userdata;
  19557 #endif
  19558     /* pull style configuration into local stack */
  19559     scrollbar_size = style->window.scrollbar_size;
  19560     panel_padding = nk_panel_get_padding(style, panel_type);
  19561 
  19562     /* window movement */
  19563     if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
  19564         nk_bool left_mouse_down;
  19565         unsigned int left_mouse_clicked;
  19566         int left_mouse_click_in_cursor;
  19567 
  19568         /* calculate draggable window space */
  19569         struct nk_rect header;
  19570         header.x = win->bounds.x;
  19571         header.y = win->bounds.y;
  19572         header.w = win->bounds.w;
  19573         if (nk_panel_has_header(win->flags, title)) {
  19574             header.h = font->height + 2.0f * style->window.header.padding.y;
  19575             header.h += 2.0f * style->window.header.label_padding.y;
  19576         } else header.h = panel_padding.y;
  19577 
  19578         /* window movement by dragging */
  19579         left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
  19580         left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked;
  19581         left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
  19582             NK_BUTTON_LEFT, header, nk_true);
  19583         if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
  19584             win->bounds.x = win->bounds.x + in->mouse.delta.x;
  19585             win->bounds.y = win->bounds.y + in->mouse.delta.y;
  19586             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
  19587             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
  19588             ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
  19589         }
  19590     }
  19591 
  19592     /* setup panel */
  19593     layout->type = panel_type;
  19594     layout->flags = win->flags;
  19595     layout->bounds = win->bounds;
  19596     layout->bounds.x += panel_padding.x;
  19597     layout->bounds.w -= 2*panel_padding.x;
  19598     if (win->flags & NK_WINDOW_BORDER) {
  19599         layout->border = nk_panel_get_border(style, win->flags, panel_type);
  19600         layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
  19601     } else layout->border = 0;
  19602     layout->at_y = layout->bounds.y;
  19603     layout->at_x = layout->bounds.x;
  19604     layout->max_x = 0;
  19605     layout->header_height = 0;
  19606     layout->footer_height = 0;
  19607     nk_layout_reset_min_row_height(ctx);
  19608     layout->row.index = 0;
  19609     layout->row.columns = 0;
  19610     layout->row.ratio = 0;
  19611     layout->row.item_width = 0;
  19612     layout->row.tree_depth = 0;
  19613     layout->row.height = panel_padding.y;
  19614     layout->has_scrolling = nk_true;
  19615     if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
  19616         layout->bounds.w -= scrollbar_size.x;
  19617     if (!nk_panel_is_nonblock(panel_type)) {
  19618         layout->footer_height = 0;
  19619         if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
  19620             layout->footer_height = scrollbar_size.y;
  19621         layout->bounds.h -= layout->footer_height;
  19622     }
  19623 
  19624     /* panel header */
  19625     if (nk_panel_has_header(win->flags, title))
  19626     {
  19627         struct nk_text text;
  19628         struct nk_rect header;
  19629         const struct nk_style_item *background = 0;
  19630 
  19631         /* calculate header bounds */
  19632         header.x = win->bounds.x;
  19633         header.y = win->bounds.y;
  19634         header.w = win->bounds.w;
  19635         header.h = font->height + 2.0f * style->window.header.padding.y;
  19636         header.h += (2.0f * style->window.header.label_padding.y);
  19637 
  19638         /* shrink panel by header */
  19639         layout->header_height = header.h;
  19640         layout->bounds.y += header.h;
  19641         layout->bounds.h -= header.h;
  19642         layout->at_y += header.h;
  19643 
  19644         /* select correct header background and text color */
  19645         if (ctx->active == win) {
  19646             background = &style->window.header.active;
  19647             text.text = style->window.header.label_active;
  19648         } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
  19649             background = &style->window.header.hover;
  19650             text.text = style->window.header.label_hover;
  19651         } else {
  19652             background = &style->window.header.normal;
  19653             text.text = style->window.header.label_normal;
  19654         }
  19655 
  19656         /* draw header background */
  19657         header.h += 1.0f;
  19658 
  19659         switch(background->type) {
  19660             case NK_STYLE_ITEM_IMAGE:
  19661                 text.background = nk_rgba(0,0,0,0);
  19662                 nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  19663                 break;
  19664             case NK_STYLE_ITEM_NINE_SLICE:
  19665                 text.background = nk_rgba(0, 0, 0, 0);
  19666                 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
  19667                 break;
  19668             case NK_STYLE_ITEM_COLOR:
  19669                 text.background = background->data.color;
  19670                 nk_fill_rect(out, header, 0, background->data.color);
  19671                 break;
  19672         }
  19673 
  19674         /* window close button */
  19675         {struct nk_rect button;
  19676         button.y = header.y + style->window.header.padding.y;
  19677         button.h = header.h - 2 * style->window.header.padding.y;
  19678         button.w = button.h;
  19679         if (win->flags & NK_WINDOW_CLOSABLE) {
  19680             nk_flags ws = 0;
  19681             if (style->window.header.align == NK_HEADER_RIGHT) {
  19682                 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
  19683                 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
  19684             } else {
  19685                 button.x = header.x + style->window.header.padding.x;
  19686                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
  19687             }
  19688 
  19689             if (nk_do_button_symbol(&ws, &win->buffer, button,
  19690                 style->window.header.close_symbol, NK_BUTTON_DEFAULT,
  19691                 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
  19692             {
  19693                 layout->flags |= NK_WINDOW_HIDDEN;
  19694                 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
  19695             }
  19696         }
  19697 
  19698         /* window minimize button */
  19699         if (win->flags & NK_WINDOW_MINIMIZABLE) {
  19700             nk_flags ws = 0;
  19701             if (style->window.header.align == NK_HEADER_RIGHT) {
  19702                 button.x = (header.w + header.x) - button.w;
  19703                 if (!(win->flags & NK_WINDOW_CLOSABLE)) {
  19704                     button.x -= style->window.header.padding.x;
  19705                     header.w -= style->window.header.padding.x;
  19706                 }
  19707                 header.w -= button.w + style->window.header.spacing.x;
  19708             } else {
  19709                 button.x = header.x;
  19710                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
  19711             }
  19712             if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
  19713                 style->window.header.maximize_symbol: style->window.header.minimize_symbol,
  19714                 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
  19715                 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
  19716                     layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
  19717                     layout->flags | NK_WINDOW_MINIMIZED;
  19718         }}
  19719 
  19720         {/* window header title */
  19721         int text_len = nk_strlen(title);
  19722         struct nk_rect label = {0,0,0,0};
  19723         float t = font->width(font->userdata, font->height, title, text_len);
  19724         text.padding = nk_vec2(0,0);
  19725 
  19726         label.x = header.x + style->window.header.padding.x;
  19727         label.x += style->window.header.label_padding.x;
  19728         label.y = header.y + style->window.header.label_padding.y;
  19729         label.h = font->height + 2 * style->window.header.label_padding.y;
  19730         label.w = t + 2 * style->window.header.spacing.x;
  19731         label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
  19732         nk_widget_text(out, label, (const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
  19733     }
  19734 
  19735     /* draw window background */
  19736     if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
  19737         struct nk_rect body;
  19738         body.x = win->bounds.x;
  19739         body.w = win->bounds.w;
  19740         body.y = (win->bounds.y + layout->header_height);
  19741         body.h = (win->bounds.h - layout->header_height);
  19742 
  19743         switch(style->window.fixed_background.type) {
  19744             case NK_STYLE_ITEM_IMAGE:
  19745                 nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
  19746                 break;
  19747             case NK_STYLE_ITEM_NINE_SLICE:
  19748                 nk_draw_nine_slice(out, body, &style->window.fixed_background.data.slice, nk_white);
  19749                 break;
  19750             case NK_STYLE_ITEM_COLOR:
  19751                 nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
  19752                 break;
  19753         }
  19754     }
  19755 
  19756     /* set clipping rectangle */
  19757     {struct nk_rect clip;
  19758     layout->clip = layout->bounds;
  19759     nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
  19760         layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
  19761     nk_push_scissor(out, clip);
  19762     layout->clip = clip;}
  19763     return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
  19764 }
  19765 NK_LIB void
  19766 nk_panel_end(struct nk_context *ctx)
  19767 {
  19768     struct nk_input *in;
  19769     struct nk_window *window;
  19770     struct nk_panel *layout;
  19771     const struct nk_style *style;
  19772     struct nk_command_buffer *out;
  19773 
  19774     struct nk_vec2 scrollbar_size;
  19775     struct nk_vec2 panel_padding;
  19776 
  19777     NK_ASSERT(ctx);
  19778     NK_ASSERT(ctx->current);
  19779     NK_ASSERT(ctx->current->layout);
  19780     if (!ctx || !ctx->current || !ctx->current->layout)
  19781         return;
  19782 
  19783     window = ctx->current;
  19784     layout = window->layout;
  19785     style = &ctx->style;
  19786     out = &window->buffer;
  19787     in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
  19788     if (!nk_panel_is_sub(layout->type))
  19789         nk_push_scissor(out, nk_null_rect);
  19790 
  19791     /* cache configuration data */
  19792     scrollbar_size = style->window.scrollbar_size;
  19793     panel_padding = nk_panel_get_padding(style, layout->type);
  19794 
  19795     /* update the current cursor Y-position to point over the last added widget */
  19796     layout->at_y += layout->row.height;
  19797 
  19798     /* dynamic panels */
  19799     if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
  19800     {
  19801         /* update panel height to fit dynamic growth */
  19802         struct nk_rect empty_space;
  19803         if (layout->at_y < (layout->bounds.y + layout->bounds.h))
  19804             layout->bounds.h = layout->at_y - layout->bounds.y;
  19805 
  19806         /* fill top empty space */
  19807         empty_space.x = window->bounds.x;
  19808         empty_space.y = layout->bounds.y;
  19809         empty_space.h = panel_padding.y;
  19810         empty_space.w = window->bounds.w;
  19811         nk_fill_rect(out, empty_space, 0, style->window.background);
  19812 
  19813         /* fill left empty space */
  19814         empty_space.x = window->bounds.x;
  19815         empty_space.y = layout->bounds.y;
  19816         empty_space.w = panel_padding.x + layout->border;
  19817         empty_space.h = layout->bounds.h;
  19818         nk_fill_rect(out, empty_space, 0, style->window.background);
  19819 
  19820         /* fill right empty space */
  19821         empty_space.x = layout->bounds.x + layout->bounds.w;
  19822         empty_space.y = layout->bounds.y;
  19823         empty_space.w = panel_padding.x + layout->border;
  19824         empty_space.h = layout->bounds.h;
  19825         if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
  19826             empty_space.w += scrollbar_size.x;
  19827         nk_fill_rect(out, empty_space, 0, style->window.background);
  19828 
  19829         /* fill bottom empty space */
  19830         if (layout->footer_height > 0) {
  19831             empty_space.x = window->bounds.x;
  19832             empty_space.y = layout->bounds.y + layout->bounds.h;
  19833             empty_space.w = window->bounds.w;
  19834             empty_space.h = layout->footer_height;
  19835             nk_fill_rect(out, empty_space, 0, style->window.background);
  19836         }
  19837     }
  19838 
  19839     /* scrollbars */
  19840     if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
  19841         !(layout->flags & NK_WINDOW_MINIMIZED) &&
  19842         window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
  19843     {
  19844         struct nk_rect scroll;
  19845         int scroll_has_scrolling;
  19846         float scroll_target;
  19847         float scroll_offset;
  19848         float scroll_step;
  19849         float scroll_inc;
  19850 
  19851         /* mouse wheel scrolling */
  19852         if (nk_panel_is_sub(layout->type))
  19853         {
  19854             /* sub-window mouse wheel scrolling */
  19855             struct nk_window *root_window = window;
  19856             struct nk_panel *root_panel = window->layout;
  19857             while (root_panel->parent)
  19858                 root_panel = root_panel->parent;
  19859             while (root_window->parent)
  19860                 root_window = root_window->parent;
  19861 
  19862             /* only allow scrolling if parent window is active */
  19863             scroll_has_scrolling = 0;
  19864             if ((root_window == ctx->active) && layout->has_scrolling) {
  19865                 /* and panel is being hovered and inside clip rect*/
  19866                 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
  19867                     NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
  19868                         root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
  19869                 {
  19870                     /* deactivate all parent scrolling */
  19871                     root_panel = window->layout;
  19872                     while (root_panel->parent) {
  19873                         root_panel->has_scrolling = nk_false;
  19874                         root_panel = root_panel->parent;
  19875                     }
  19876                     root_panel->has_scrolling = nk_false;
  19877                     scroll_has_scrolling = nk_true;
  19878                 }
  19879             }
  19880         } else if (!nk_panel_is_sub(layout->type)) {
  19881             /* window mouse wheel scrolling */
  19882             scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
  19883             if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
  19884                 window->scrolled = nk_true;
  19885             else window->scrolled = nk_false;
  19886         } else scroll_has_scrolling = nk_false;
  19887 
  19888         {
  19889             /* vertical scrollbar */
  19890             nk_flags state = 0;
  19891             scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
  19892             scroll.y = layout->bounds.y;
  19893             scroll.w = scrollbar_size.x;
  19894             scroll.h = layout->bounds.h;
  19895 
  19896             scroll_offset = (float)*layout->offset_y;
  19897             scroll_step = scroll.h * 0.10f;
  19898             scroll_inc = scroll.h * 0.01f;
  19899             scroll_target = (float)(int)(layout->at_y - scroll.y);
  19900             scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
  19901                 scroll_offset, scroll_target, scroll_step, scroll_inc,
  19902                 &ctx->style.scrollv, in, style->font);
  19903             *layout->offset_y = (nk_uint)scroll_offset;
  19904             if (in && scroll_has_scrolling)
  19905                 in->mouse.scroll_delta.y = 0;
  19906         }
  19907         {
  19908             /* horizontal scrollbar */
  19909             nk_flags state = 0;
  19910             scroll.x = layout->bounds.x;
  19911             scroll.y = layout->bounds.y + layout->bounds.h;
  19912             scroll.w = layout->bounds.w;
  19913             scroll.h = scrollbar_size.y;
  19914 
  19915             scroll_offset = (float)*layout->offset_x;
  19916             scroll_target = (float)(int)(layout->max_x - scroll.x);
  19917             scroll_step = layout->max_x * 0.05f;
  19918             scroll_inc = layout->max_x * 0.005f;
  19919             scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
  19920                 scroll_offset, scroll_target, scroll_step, scroll_inc,
  19921                 &ctx->style.scrollh, in, style->font);
  19922             *layout->offset_x = (nk_uint)scroll_offset;
  19923         }
  19924     }
  19925 
  19926     /* hide scroll if no user input */
  19927     if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
  19928         int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
  19929         int is_window_hovered = nk_window_is_hovered(ctx);
  19930         int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
  19931         if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
  19932             window->scrollbar_hiding_timer += ctx->delta_time_seconds;
  19933         else window->scrollbar_hiding_timer = 0;
  19934     } else window->scrollbar_hiding_timer = 0;
  19935 
  19936     /* window border */
  19937     if (layout->flags & NK_WINDOW_BORDER)
  19938     {
  19939         struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
  19940         const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED)
  19941             ? (style->window.border + window->bounds.y + layout->header_height)
  19942             : ((layout->flags & NK_WINDOW_DYNAMIC)
  19943                 ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
  19944                 : (window->bounds.y + window->bounds.h));
  19945         struct nk_rect b = window->bounds;
  19946         b.h = padding_y - window->bounds.y;
  19947         nk_stroke_rect(out, b, 0, layout->border, border_color);
  19948     }
  19949 
  19950     /* scaler */
  19951     if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
  19952     {
  19953         /* calculate scaler bounds */
  19954         struct nk_rect scaler;
  19955         scaler.w = scrollbar_size.x;
  19956         scaler.h = scrollbar_size.y;
  19957         scaler.y = layout->bounds.y + layout->bounds.h;
  19958         if (layout->flags & NK_WINDOW_SCALE_LEFT)
  19959             scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
  19960         else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
  19961         if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
  19962             scaler.x -= scaler.w;
  19963 
  19964         /* draw scaler */
  19965         {const struct nk_style_item *item = &style->window.scaler;
  19966         if (item->type == NK_STYLE_ITEM_IMAGE)
  19967             nk_draw_image(out, scaler, &item->data.image, nk_white);
  19968         else {
  19969             if (layout->flags & NK_WINDOW_SCALE_LEFT) {
  19970                 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
  19971                     scaler.y + scaler.h, scaler.x + scaler.w,
  19972                     scaler.y + scaler.h, item->data.color);
  19973             } else {
  19974                 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
  19975                     scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
  19976             }
  19977         }}
  19978 
  19979         /* do window scaling */
  19980         if (!(window->flags & NK_WINDOW_ROM)) {
  19981             struct nk_vec2 window_size = style->window.min_size;
  19982             int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
  19983             int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
  19984                     NK_BUTTON_LEFT, scaler, nk_true);
  19985 
  19986             if (left_mouse_down && left_mouse_click_in_scaler) {
  19987                 float delta_x = in->mouse.delta.x;
  19988                 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
  19989                     delta_x = -delta_x;
  19990                     window->bounds.x += in->mouse.delta.x;
  19991                 }
  19992                 /* dragging in x-direction  */
  19993                 if (window->bounds.w + delta_x >= window_size.x) {
  19994                     if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
  19995                         window->bounds.w = window->bounds.w + delta_x;
  19996                         scaler.x += in->mouse.delta.x;
  19997                     }
  19998                 }
  19999                 /* dragging in y-direction (only possible if static window) */
  20000                 if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
  20001                     if (window_size.y < window->bounds.h + in->mouse.delta.y) {
  20002                         if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
  20003                             window->bounds.h = window->bounds.h + in->mouse.delta.y;
  20004                             scaler.y += in->mouse.delta.y;
  20005                         }
  20006                     }
  20007                 }
  20008                 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
  20009                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
  20010                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
  20011             }
  20012         }
  20013     }
  20014     if (!nk_panel_is_sub(layout->type)) {
  20015         /* window is hidden so clear command buffer  */
  20016         if (layout->flags & NK_WINDOW_HIDDEN)
  20017             nk_command_buffer_reset(&window->buffer);
  20018         /* window is visible and not tab */
  20019         else nk_finish(ctx, window);
  20020     }
  20021 
  20022     /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
  20023     if (layout->flags & NK_WINDOW_REMOVE_ROM) {
  20024         layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
  20025         layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
  20026     }
  20027     window->flags = layout->flags;
  20028 
  20029     /* property garbage collector */
  20030     if (window->property.active && window->property.old != window->property.seq &&
  20031         window->property.active == window->property.prev) {
  20032         nk_zero(&window->property, sizeof(window->property));
  20033     } else {
  20034         window->property.old = window->property.seq;
  20035         window->property.prev = window->property.active;
  20036         window->property.seq = 0;
  20037     }
  20038     /* edit garbage collector */
  20039     if (window->edit.active && window->edit.old != window->edit.seq &&
  20040        window->edit.active == window->edit.prev) {
  20041         nk_zero(&window->edit, sizeof(window->edit));
  20042     } else {
  20043         window->edit.old = window->edit.seq;
  20044         window->edit.prev = window->edit.active;
  20045         window->edit.seq = 0;
  20046     }
  20047     /* contextual garbage collector */
  20048     if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
  20049         window->popup.con_count = 0;
  20050         window->popup.con_old = 0;
  20051         window->popup.active_con = 0;
  20052     } else {
  20053         window->popup.con_old = window->popup.con_count;
  20054         window->popup.con_count = 0;
  20055     }
  20056     window->popup.combo_count = 0;
  20057     /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
  20058     NK_ASSERT(!layout->row.tree_depth);
  20059 }
  20060 
  20061 
  20062 
  20063 
  20064 
  20065 /* ===============================================================
  20066  *
  20067  *                              WINDOW
  20068  *
  20069  * ===============================================================*/
  20070 NK_LIB void*
  20071 nk_create_window(struct nk_context *ctx)
  20072 {
  20073     struct nk_page_element *elem;
  20074     elem = nk_create_page_element(ctx);
  20075     if (!elem) return 0;
  20076     elem->data.win.seq = ctx->seq;
  20077     return &elem->data.win;
  20078 }
  20079 NK_LIB void
  20080 nk_free_window(struct nk_context *ctx, struct nk_window *win)
  20081 {
  20082     /* unlink windows from list */
  20083     struct nk_table *it = win->tables;
  20084     if (win->popup.win) {
  20085         nk_free_window(ctx, win->popup.win);
  20086         win->popup.win = 0;
  20087     }
  20088     win->next = 0;
  20089     win->prev = 0;
  20090 
  20091     while (it) {
  20092         /*free window state tables */
  20093         struct nk_table *n = it->next;
  20094         nk_remove_table(win, it);
  20095         nk_free_table(ctx, it);
  20096         if (it == win->tables)
  20097             win->tables = n;
  20098         it = n;
  20099     }
  20100 
  20101     /* link windows into freelist */
  20102     {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
  20103     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
  20104     nk_free_page_element(ctx, pe);}
  20105 }
  20106 NK_LIB struct nk_window*
  20107 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
  20108 {
  20109     struct nk_window *iter;
  20110     iter = ctx->begin;
  20111     while (iter) {
  20112         NK_ASSERT(iter != iter->next);
  20113         if (iter->name == hash) {
  20114             int max_len = nk_strlen(iter->name_string);
  20115             if (!nk_stricmpn(iter->name_string, name, max_len))
  20116                 return iter;
  20117         }
  20118         iter = iter->next;
  20119     }
  20120     return 0;
  20121 }
  20122 NK_LIB void
  20123 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
  20124     enum nk_window_insert_location loc)
  20125 {
  20126     const struct nk_window *iter;
  20127     NK_ASSERT(ctx);
  20128     NK_ASSERT(win);
  20129     if (!win || !ctx) return;
  20130 
  20131     iter = ctx->begin;
  20132     while (iter) {
  20133         NK_ASSERT(iter != iter->next);
  20134         NK_ASSERT(iter != win);
  20135         if (iter == win) return;
  20136         iter = iter->next;
  20137     }
  20138 
  20139     if (!ctx->begin) {
  20140         win->next = 0;
  20141         win->prev = 0;
  20142         ctx->begin = win;
  20143         ctx->end = win;
  20144         ctx->count = 1;
  20145         return;
  20146     }
  20147     if (loc == NK_INSERT_BACK) {
  20148         struct nk_window *end;
  20149         end = ctx->end;
  20150         end->flags |= NK_WINDOW_ROM;
  20151         end->next = win;
  20152         win->prev = ctx->end;
  20153         win->next = 0;
  20154         ctx->end = win;
  20155         ctx->active = ctx->end;
  20156         ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
  20157     } else {
  20158         /*ctx->end->flags |= NK_WINDOW_ROM;*/
  20159         ctx->begin->prev = win;
  20160         win->next = ctx->begin;
  20161         win->prev = 0;
  20162         ctx->begin = win;
  20163         ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
  20164     }
  20165     ctx->count++;
  20166 }
  20167 NK_LIB void
  20168 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
  20169 {
  20170     if (win == ctx->begin || win == ctx->end) {
  20171         if (win == ctx->begin) {
  20172             ctx->begin = win->next;
  20173             if (win->next)
  20174                 win->next->prev = 0;
  20175         }
  20176         if (win == ctx->end) {
  20177             ctx->end = win->prev;
  20178             if (win->prev)
  20179                 win->prev->next = 0;
  20180         }
  20181     } else {
  20182         if (win->next)
  20183             win->next->prev = win->prev;
  20184         if (win->prev)
  20185             win->prev->next = win->next;
  20186     }
  20187     if (win == ctx->active || !ctx->active) {
  20188         ctx->active = ctx->end;
  20189         if (ctx->end)
  20190             ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
  20191     }
  20192     win->next = 0;
  20193     win->prev = 0;
  20194     ctx->count--;
  20195 }
  20196 NK_API nk_bool
  20197 nk_begin(struct nk_context *ctx, const char *title,
  20198     struct nk_rect bounds, nk_flags flags)
  20199 {
  20200     return nk_begin_titled(ctx, title, title, bounds, flags);
  20201 }
  20202 NK_API nk_bool
  20203 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
  20204     struct nk_rect bounds, nk_flags flags)
  20205 {
  20206     struct nk_window *win;
  20207     struct nk_style *style;
  20208     nk_hash name_hash;
  20209     int name_len;
  20210     int ret = 0;
  20211 
  20212     NK_ASSERT(ctx);
  20213     NK_ASSERT(name);
  20214     NK_ASSERT(title);
  20215     NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
  20216     NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
  20217     if (!ctx || ctx->current || !title || !name)
  20218         return 0;
  20219 
  20220     /* find or create window */
  20221     style = &ctx->style;
  20222     name_len = (int)nk_strlen(name);
  20223     name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE);
  20224     win = nk_find_window(ctx, name_hash, name);
  20225     if (!win) {
  20226         /* create new window */
  20227         nk_size name_length = (nk_size)name_len;
  20228         win = (struct nk_window*)nk_create_window(ctx);
  20229         NK_ASSERT(win);
  20230         if (!win) return 0;
  20231 
  20232         if (flags & NK_WINDOW_BACKGROUND)
  20233             nk_insert_window(ctx, win, NK_INSERT_FRONT);
  20234         else nk_insert_window(ctx, win, NK_INSERT_BACK);
  20235         nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
  20236 
  20237         win->flags = flags;
  20238         win->bounds = bounds;
  20239         win->name = name_hash;
  20240         name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
  20241         NK_MEMCPY(win->name_string, name, name_length);
  20242         win->name_string[name_length] = 0;
  20243         win->popup.win = 0;
  20244         if (!ctx->active)
  20245             ctx->active = win;
  20246     } else {
  20247         /* update window */
  20248         win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
  20249         win->flags |= flags;
  20250         if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
  20251             win->bounds = bounds;
  20252         /* If this assert triggers you either:
  20253          *
  20254          * I.) Have more than one window with the same name or
  20255          * II.) You forgot to actually draw the window.
  20256          *      More specific you did not call `nk_clear` (nk_clear will be
  20257          *      automatically called for you if you are using one of the
  20258          *      provided demo backends). */
  20259         NK_ASSERT(win->seq != ctx->seq);
  20260         win->seq = ctx->seq;
  20261         if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
  20262             ctx->active = win;
  20263             ctx->end = win;
  20264         }
  20265     }
  20266     if (win->flags & NK_WINDOW_HIDDEN) {
  20267         ctx->current = win;
  20268         win->layout = 0;
  20269         return 0;
  20270     } else nk_start(ctx, win);
  20271 
  20272     /* window overlapping */
  20273     if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
  20274     {
  20275         int inpanel, ishovered;
  20276         struct nk_window *iter = win;
  20277         float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
  20278             (2.0f * style->window.header.label_padding.y);
  20279         struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
  20280             win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
  20281 
  20282         /* activate window if hovered and no other window is overlapping this window */
  20283         inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
  20284         inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
  20285         ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
  20286         if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
  20287             iter = win->next;
  20288             while (iter) {
  20289                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
  20290                     iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
  20291                 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
  20292                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
  20293                     (!(iter->flags & NK_WINDOW_HIDDEN)))
  20294                     break;
  20295 
  20296                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
  20297                     NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
  20298                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
  20299                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
  20300                     break;
  20301                 iter = iter->next;
  20302             }
  20303         }
  20304 
  20305         /* activate window if clicked */
  20306         if (iter && inpanel && (win != ctx->end)) {
  20307             iter = win->next;
  20308             while (iter) {
  20309                 /* try to find a panel with higher priority in the same position */
  20310                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
  20311                 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
  20312                 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
  20313                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
  20314                     !(iter->flags & NK_WINDOW_HIDDEN))
  20315                     break;
  20316                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
  20317                     NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
  20318                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
  20319                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
  20320                     break;
  20321                 iter = iter->next;
  20322             }
  20323         }
  20324         if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
  20325             win->flags |= (nk_flags)NK_WINDOW_ROM;
  20326             iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
  20327             ctx->active = iter;
  20328             if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
  20329                 /* current window is active in that position so transfer to top
  20330                  * at the highest priority in stack */
  20331                 nk_remove_window(ctx, iter);
  20332                 nk_insert_window(ctx, iter, NK_INSERT_BACK);
  20333             }
  20334         } else {
  20335             if (!iter && ctx->end != win) {
  20336                 if (!(win->flags & NK_WINDOW_BACKGROUND)) {
  20337                     /* current window is active in that position so transfer to top
  20338                      * at the highest priority in stack */
  20339                     nk_remove_window(ctx, win);
  20340                     nk_insert_window(ctx, win, NK_INSERT_BACK);
  20341                 }
  20342                 win->flags &= ~(nk_flags)NK_WINDOW_ROM;
  20343                 ctx->active = win;
  20344             }
  20345             if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
  20346                 win->flags |= NK_WINDOW_ROM;
  20347         }
  20348     }
  20349     win->layout = (struct nk_panel*)nk_create_panel(ctx);
  20350     ctx->current = win;
  20351     ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
  20352     win->layout->offset_x = &win->scrollbar.x;
  20353     win->layout->offset_y = &win->scrollbar.y;
  20354     return ret;
  20355 }
  20356 NK_API void
  20357 nk_end(struct nk_context *ctx)
  20358 {
  20359     struct nk_panel *layout;
  20360     NK_ASSERT(ctx);
  20361     NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
  20362     if (!ctx || !ctx->current)
  20363         return;
  20364 
  20365     layout = ctx->current->layout;
  20366     if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
  20367         ctx->current = 0;
  20368         return;
  20369     }
  20370     nk_panel_end(ctx);
  20371     nk_free_panel(ctx, ctx->current->layout);
  20372     ctx->current = 0;
  20373 }
  20374 NK_API struct nk_rect
  20375 nk_window_get_bounds(const struct nk_context *ctx)
  20376 {
  20377     NK_ASSERT(ctx);
  20378     NK_ASSERT(ctx->current);
  20379     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
  20380     return ctx->current->bounds;
  20381 }
  20382 NK_API struct nk_vec2
  20383 nk_window_get_position(const struct nk_context *ctx)
  20384 {
  20385     NK_ASSERT(ctx);
  20386     NK_ASSERT(ctx->current);
  20387     if (!ctx || !ctx->current) return nk_vec2(0,0);
  20388     return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
  20389 }
  20390 NK_API struct nk_vec2
  20391 nk_window_get_size(const struct nk_context *ctx)
  20392 {
  20393     NK_ASSERT(ctx);
  20394     NK_ASSERT(ctx->current);
  20395     if (!ctx || !ctx->current) return nk_vec2(0,0);
  20396     return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
  20397 }
  20398 NK_API float
  20399 nk_window_get_width(const struct nk_context *ctx)
  20400 {
  20401     NK_ASSERT(ctx);
  20402     NK_ASSERT(ctx->current);
  20403     if (!ctx || !ctx->current) return 0;
  20404     return ctx->current->bounds.w;
  20405 }
  20406 NK_API float
  20407 nk_window_get_height(const struct nk_context *ctx)
  20408 {
  20409     NK_ASSERT(ctx);
  20410     NK_ASSERT(ctx->current);
  20411     if (!ctx || !ctx->current) return 0;
  20412     return ctx->current->bounds.h;
  20413 }
  20414 NK_API struct nk_rect
  20415 nk_window_get_content_region(struct nk_context *ctx)
  20416 {
  20417     NK_ASSERT(ctx);
  20418     NK_ASSERT(ctx->current);
  20419     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
  20420     return ctx->current->layout->clip;
  20421 }
  20422 NK_API struct nk_vec2
  20423 nk_window_get_content_region_min(struct nk_context *ctx)
  20424 {
  20425     NK_ASSERT(ctx);
  20426     NK_ASSERT(ctx->current);
  20427     NK_ASSERT(ctx->current->layout);
  20428     if (!ctx || !ctx->current) return nk_vec2(0,0);
  20429     return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
  20430 }
  20431 NK_API struct nk_vec2
  20432 nk_window_get_content_region_max(struct nk_context *ctx)
  20433 {
  20434     NK_ASSERT(ctx);
  20435     NK_ASSERT(ctx->current);
  20436     NK_ASSERT(ctx->current->layout);
  20437     if (!ctx || !ctx->current) return nk_vec2(0,0);
  20438     return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
  20439         ctx->current->layout->clip.y + ctx->current->layout->clip.h);
  20440 }
  20441 NK_API struct nk_vec2
  20442 nk_window_get_content_region_size(struct nk_context *ctx)
  20443 {
  20444     NK_ASSERT(ctx);
  20445     NK_ASSERT(ctx->current);
  20446     NK_ASSERT(ctx->current->layout);
  20447     if (!ctx || !ctx->current) return nk_vec2(0,0);
  20448     return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
  20449 }
  20450 NK_API struct nk_command_buffer*
  20451 nk_window_get_canvas(struct nk_context *ctx)
  20452 {
  20453     NK_ASSERT(ctx);
  20454     NK_ASSERT(ctx->current);
  20455     NK_ASSERT(ctx->current->layout);
  20456     if (!ctx || !ctx->current) return 0;
  20457     return &ctx->current->buffer;
  20458 }
  20459 NK_API struct nk_panel*
  20460 nk_window_get_panel(struct nk_context *ctx)
  20461 {
  20462     NK_ASSERT(ctx);
  20463     NK_ASSERT(ctx->current);
  20464     if (!ctx || !ctx->current) return 0;
  20465     return ctx->current->layout;
  20466 }
  20467 NK_API void
  20468 nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
  20469 {
  20470     struct nk_window *win;
  20471     NK_ASSERT(ctx);
  20472     NK_ASSERT(ctx->current);
  20473     if (!ctx || !ctx->current)
  20474         return ;
  20475     win = ctx->current;
  20476     if (offset_x)
  20477       *offset_x = win->scrollbar.x;
  20478     if (offset_y)
  20479       *offset_y = win->scrollbar.y;
  20480 }
  20481 NK_API nk_bool
  20482 nk_window_has_focus(const struct nk_context *ctx)
  20483 {
  20484     NK_ASSERT(ctx);
  20485     NK_ASSERT(ctx->current);
  20486     NK_ASSERT(ctx->current->layout);
  20487     if (!ctx || !ctx->current) return 0;
  20488     return ctx->current == ctx->active;
  20489 }
  20490 NK_API nk_bool
  20491 nk_window_is_hovered(struct nk_context *ctx)
  20492 {
  20493     NK_ASSERT(ctx);
  20494     NK_ASSERT(ctx->current);
  20495     if (!ctx || !ctx->current || (ctx->current->flags & NK_WINDOW_HIDDEN))
  20496         return 0;
  20497     else {
  20498         struct nk_rect actual_bounds = ctx->current->bounds;
  20499         if (ctx->begin->flags & NK_WINDOW_MINIMIZED) {
  20500             actual_bounds.h = ctx->current->layout->header_height;
  20501         }
  20502         return nk_input_is_mouse_hovering_rect(&ctx->input, actual_bounds);
  20503     }
  20504 }
  20505 NK_API nk_bool
  20506 nk_window_is_any_hovered(struct nk_context *ctx)
  20507 {
  20508     struct nk_window *iter;
  20509     NK_ASSERT(ctx);
  20510     if (!ctx) return 0;
  20511     iter = ctx->begin;
  20512     while (iter) {
  20513         /* check if window is being hovered */
  20514         if(!(iter->flags & NK_WINDOW_HIDDEN)) {
  20515             /* check if window popup is being hovered */
  20516             if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
  20517                 return 1;
  20518 
  20519             if (iter->flags & NK_WINDOW_MINIMIZED) {
  20520                 struct nk_rect header = iter->bounds;
  20521                 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
  20522                 if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
  20523                     return 1;
  20524             } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
  20525                 return 1;
  20526             }
  20527         }
  20528         iter = iter->next;
  20529     }
  20530     return 0;
  20531 }
  20532 NK_API nk_bool
  20533 nk_item_is_any_active(struct nk_context *ctx)
  20534 {
  20535     int any_hovered = nk_window_is_any_hovered(ctx);
  20536     int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
  20537     return any_hovered || any_active;
  20538 }
  20539 NK_API nk_bool
  20540 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
  20541 {
  20542     int title_len;
  20543     nk_hash title_hash;
  20544     struct nk_window *win;
  20545     NK_ASSERT(ctx);
  20546     if (!ctx) return 0;
  20547 
  20548     title_len = (int)nk_strlen(name);
  20549     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  20550     win = nk_find_window(ctx, title_hash, name);
  20551     if (!win) return 0;
  20552     return win->flags & NK_WINDOW_MINIMIZED;
  20553 }
  20554 NK_API nk_bool
  20555 nk_window_is_closed(struct nk_context *ctx, const char *name)
  20556 {
  20557     int title_len;
  20558     nk_hash title_hash;
  20559     struct nk_window *win;
  20560     NK_ASSERT(ctx);
  20561     if (!ctx) return 1;
  20562 
  20563     title_len = (int)nk_strlen(name);
  20564     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  20565     win = nk_find_window(ctx, title_hash, name);
  20566     if (!win) return 1;
  20567     return (win->flags & NK_WINDOW_CLOSED);
  20568 }
  20569 NK_API nk_bool
  20570 nk_window_is_hidden(struct nk_context *ctx, const char *name)
  20571 {
  20572     int title_len;
  20573     nk_hash title_hash;
  20574     struct nk_window *win;
  20575     NK_ASSERT(ctx);
  20576     if (!ctx) return 1;
  20577 
  20578     title_len = (int)nk_strlen(name);
  20579     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  20580     win = nk_find_window(ctx, title_hash, name);
  20581     if (!win) return 1;
  20582     return (win->flags & NK_WINDOW_HIDDEN);
  20583 }
  20584 NK_API nk_bool
  20585 nk_window_is_active(struct nk_context *ctx, const char *name)
  20586 {
  20587     int title_len;
  20588     nk_hash title_hash;
  20589     struct nk_window *win;
  20590     NK_ASSERT(ctx);
  20591     if (!ctx) return 0;
  20592 
  20593     title_len = (int)nk_strlen(name);
  20594     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  20595     win = nk_find_window(ctx, title_hash, name);
  20596     if (!win) return 0;
  20597     return win == ctx->active;
  20598 }
  20599 NK_API struct nk_window*
  20600 nk_window_find(struct nk_context *ctx, const char *name)
  20601 {
  20602     int title_len;
  20603     nk_hash title_hash;
  20604     title_len = (int)nk_strlen(name);
  20605     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  20606     return nk_find_window(ctx, title_hash, name);
  20607 }
  20608 NK_API void
  20609 nk_window_close(struct nk_context *ctx, const char *name)
  20610 {
  20611     struct nk_window *win;
  20612     NK_ASSERT(ctx);
  20613     if (!ctx) return;
  20614     win = nk_window_find(ctx, name);
  20615     if (!win) return;
  20616     NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
  20617     if (ctx->current == win) return;
  20618     win->flags |= NK_WINDOW_HIDDEN;
  20619     win->flags |= NK_WINDOW_CLOSED;
  20620 }
  20621 NK_API void
  20622 nk_window_set_bounds(struct nk_context *ctx,
  20623     const char *name, struct nk_rect bounds)
  20624 {
  20625     struct nk_window *win;
  20626     NK_ASSERT(ctx);
  20627     if (!ctx) return;
  20628     win = nk_window_find(ctx, name);
  20629     if (!win) return;
  20630     NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
  20631     win->bounds = bounds;
  20632 }
  20633 NK_API void
  20634 nk_window_set_position(struct nk_context *ctx,
  20635     const char *name, struct nk_vec2 pos)
  20636 {
  20637     struct nk_window *win = nk_window_find(ctx, name);
  20638     if (!win) return;
  20639     win->bounds.x = pos.x;
  20640     win->bounds.y = pos.y;
  20641 }
  20642 NK_API void
  20643 nk_window_set_size(struct nk_context *ctx,
  20644     const char *name, struct nk_vec2 size)
  20645 {
  20646     struct nk_window *win = nk_window_find(ctx, name);
  20647     if (!win) return;
  20648     win->bounds.w = size.x;
  20649     win->bounds.h = size.y;
  20650 }
  20651 NK_API void
  20652 nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
  20653 {
  20654     struct nk_window *win;
  20655     NK_ASSERT(ctx);
  20656     NK_ASSERT(ctx->current);
  20657     if (!ctx || !ctx->current)
  20658         return;
  20659     win = ctx->current;
  20660     win->scrollbar.x = offset_x;
  20661     win->scrollbar.y = offset_y;
  20662 }
  20663 NK_API void
  20664 nk_window_collapse(struct nk_context *ctx, const char *name,
  20665                     enum nk_collapse_states c)
  20666 {
  20667     int title_len;
  20668     nk_hash title_hash;
  20669     struct nk_window *win;
  20670     NK_ASSERT(ctx);
  20671     if (!ctx) return;
  20672 
  20673     title_len = (int)nk_strlen(name);
  20674     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  20675     win = nk_find_window(ctx, title_hash, name);
  20676     if (!win) return;
  20677     if (c == NK_MINIMIZED)
  20678         win->flags |= NK_WINDOW_MINIMIZED;
  20679     else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
  20680 }
  20681 NK_API void
  20682 nk_window_collapse_if(struct nk_context *ctx, const char *name,
  20683     enum nk_collapse_states c, int cond)
  20684 {
  20685     NK_ASSERT(ctx);
  20686     if (!ctx || !cond) return;
  20687     nk_window_collapse(ctx, name, c);
  20688 }
  20689 NK_API void
  20690 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
  20691 {
  20692     int title_len;
  20693     nk_hash title_hash;
  20694     struct nk_window *win;
  20695     NK_ASSERT(ctx);
  20696     if (!ctx) return;
  20697 
  20698     title_len = (int)nk_strlen(name);
  20699     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  20700     win = nk_find_window(ctx, title_hash, name);
  20701     if (!win) return;
  20702     if (s == NK_HIDDEN) {
  20703         win->flags |= NK_WINDOW_HIDDEN;
  20704     } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
  20705 }
  20706 NK_API void
  20707 nk_window_show_if(struct nk_context *ctx, const char *name,
  20708     enum nk_show_states s, int cond)
  20709 {
  20710     NK_ASSERT(ctx);
  20711     if (!ctx || !cond) return;
  20712     nk_window_show(ctx, name, s);
  20713 }
  20714 
  20715 NK_API void
  20716 nk_window_set_focus(struct nk_context *ctx, const char *name)
  20717 {
  20718     int title_len;
  20719     nk_hash title_hash;
  20720     struct nk_window *win;
  20721     NK_ASSERT(ctx);
  20722     if (!ctx) return;
  20723 
  20724     title_len = (int)nk_strlen(name);
  20725     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  20726     win = nk_find_window(ctx, title_hash, name);
  20727     if (win && ctx->end != win) {
  20728         nk_remove_window(ctx, win);
  20729         nk_insert_window(ctx, win, NK_INSERT_BACK);
  20730     }
  20731     ctx->active = win;
  20732 }
  20733 
  20734 
  20735 
  20736 
  20737 /* ===============================================================
  20738  *
  20739  *                              POPUP
  20740  *
  20741  * ===============================================================*/
  20742 NK_API nk_bool
  20743 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
  20744     const char *title, nk_flags flags, struct nk_rect rect)
  20745 {
  20746     struct nk_window *popup;
  20747     struct nk_window *win;
  20748     struct nk_panel *panel;
  20749 
  20750     int title_len;
  20751     nk_hash title_hash;
  20752     nk_size allocated;
  20753 
  20754     NK_ASSERT(ctx);
  20755     NK_ASSERT(title);
  20756     NK_ASSERT(ctx->current);
  20757     NK_ASSERT(ctx->current->layout);
  20758     if (!ctx || !ctx->current || !ctx->current->layout)
  20759         return 0;
  20760 
  20761     win = ctx->current;
  20762     panel = win->layout;
  20763     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
  20764     (void)panel;
  20765     title_len = (int)nk_strlen(title);
  20766     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
  20767 
  20768     popup = win->popup.win;
  20769     if (!popup) {
  20770         popup = (struct nk_window*)nk_create_window(ctx);
  20771         popup->parent = win;
  20772         win->popup.win = popup;
  20773         win->popup.active = 0;
  20774         win->popup.type = NK_PANEL_POPUP;
  20775     }
  20776 
  20777     /* make sure we have correct popup */
  20778     if (win->popup.name != title_hash) {
  20779         if (!win->popup.active) {
  20780             nk_zero(popup, sizeof(*popup));
  20781             win->popup.name = title_hash;
  20782             win->popup.active = 1;
  20783             win->popup.type = NK_PANEL_POPUP;
  20784         } else return 0;
  20785     }
  20786 
  20787     /* popup position is local to window */
  20788     ctx->current = popup;
  20789     rect.x += win->layout->clip.x;
  20790     rect.y += win->layout->clip.y;
  20791 
  20792     /* setup popup data */
  20793     popup->parent = win;
  20794     popup->bounds = rect;
  20795     popup->seq = ctx->seq;
  20796     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
  20797     popup->flags = flags;
  20798     popup->flags |= NK_WINDOW_BORDER;
  20799     if (type == NK_POPUP_DYNAMIC)
  20800         popup->flags |= NK_WINDOW_DYNAMIC;
  20801 
  20802     popup->buffer = win->buffer;
  20803     nk_start_popup(ctx, win);
  20804     allocated = ctx->memory.allocated;
  20805     nk_push_scissor(&popup->buffer, nk_null_rect);
  20806 
  20807     if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
  20808         /* popup is running therefore invalidate parent panels */
  20809         struct nk_panel *root;
  20810         root = win->layout;
  20811         while (root) {
  20812             root->flags |= NK_WINDOW_ROM;
  20813             root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
  20814             root = root->parent;
  20815         }
  20816         win->popup.active = 1;
  20817         popup->layout->offset_x = &popup->scrollbar.x;
  20818         popup->layout->offset_y = &popup->scrollbar.y;
  20819         popup->layout->parent = win->layout;
  20820         return 1;
  20821     } else {
  20822         /* popup was closed/is invalid so cleanup */
  20823         struct nk_panel *root;
  20824         root = win->layout;
  20825         while (root) {
  20826             root->flags |= NK_WINDOW_REMOVE_ROM;
  20827             root = root->parent;
  20828         }
  20829         win->popup.buf.active = 0;
  20830         win->popup.active = 0;
  20831         ctx->memory.allocated = allocated;
  20832         ctx->current = win;
  20833         nk_free_panel(ctx, popup->layout);
  20834         popup->layout = 0;
  20835         return 0;
  20836     }
  20837 }
  20838 NK_LIB nk_bool
  20839 nk_nonblock_begin(struct nk_context *ctx,
  20840     nk_flags flags, struct nk_rect body, struct nk_rect header,
  20841     enum nk_panel_type panel_type)
  20842 {
  20843     struct nk_window *popup;
  20844     struct nk_window *win;
  20845     struct nk_panel *panel;
  20846     int is_active = nk_true;
  20847 
  20848     NK_ASSERT(ctx);
  20849     NK_ASSERT(ctx->current);
  20850     NK_ASSERT(ctx->current->layout);
  20851     if (!ctx || !ctx->current || !ctx->current->layout)
  20852         return 0;
  20853 
  20854     /* popups cannot have popups */
  20855     win = ctx->current;
  20856     panel = win->layout;
  20857     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
  20858     (void)panel;
  20859     popup = win->popup.win;
  20860     if (!popup) {
  20861         /* create window for nonblocking popup */
  20862         popup = (struct nk_window*)nk_create_window(ctx);
  20863         popup->parent = win;
  20864         win->popup.win = popup;
  20865         win->popup.type = panel_type;
  20866         nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
  20867     } else {
  20868         /* close the popup if user pressed outside or in the header */
  20869         int pressed, in_body, in_header;
  20870 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
  20871         pressed = nk_input_is_mouse_released(&ctx->input, NK_BUTTON_LEFT);
  20872 #else
  20873         pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
  20874 #endif
  20875         in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
  20876         in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
  20877         if (pressed && (!in_body || in_header))
  20878             is_active = nk_false;
  20879     }
  20880     win->popup.header = header;
  20881 
  20882     if (!is_active) {
  20883         /* remove read only mode from all parent panels */
  20884         struct nk_panel *root = win->layout;
  20885         while (root) {
  20886             root->flags |= NK_WINDOW_REMOVE_ROM;
  20887             root = root->parent;
  20888         }
  20889         return is_active;
  20890     }
  20891     popup->bounds = body;
  20892     popup->parent = win;
  20893     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
  20894     popup->flags = flags;
  20895     popup->flags |= NK_WINDOW_BORDER;
  20896     popup->flags |= NK_WINDOW_DYNAMIC;
  20897     popup->seq = ctx->seq;
  20898     win->popup.active = 1;
  20899     NK_ASSERT(popup->layout);
  20900 
  20901     nk_start_popup(ctx, win);
  20902     popup->buffer = win->buffer;
  20903     nk_push_scissor(&popup->buffer, nk_null_rect);
  20904     ctx->current = popup;
  20905 
  20906     nk_panel_begin(ctx, 0, panel_type);
  20907     win->buffer = popup->buffer;
  20908     popup->layout->parent = win->layout;
  20909     popup->layout->offset_x = &popup->scrollbar.x;
  20910     popup->layout->offset_y = &popup->scrollbar.y;
  20911 
  20912     /* set read only mode to all parent panels */
  20913     {struct nk_panel *root;
  20914     root = win->layout;
  20915     while (root) {
  20916         root->flags |= NK_WINDOW_ROM;
  20917         root = root->parent;
  20918     }}
  20919     return is_active;
  20920 }
  20921 NK_API void
  20922 nk_popup_close(struct nk_context *ctx)
  20923 {
  20924     struct nk_window *popup;
  20925     NK_ASSERT(ctx);
  20926     if (!ctx || !ctx->current) return;
  20927 
  20928     popup = ctx->current;
  20929     NK_ASSERT(popup->parent);
  20930     NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
  20931     popup->flags |= NK_WINDOW_HIDDEN;
  20932 }
  20933 NK_API void
  20934 nk_popup_end(struct nk_context *ctx)
  20935 {
  20936     struct nk_window *win;
  20937     struct nk_window *popup;
  20938 
  20939     NK_ASSERT(ctx);
  20940     NK_ASSERT(ctx->current);
  20941     NK_ASSERT(ctx->current->layout);
  20942     if (!ctx || !ctx->current || !ctx->current->layout)
  20943         return;
  20944 
  20945     popup = ctx->current;
  20946     if (!popup->parent) return;
  20947     win = popup->parent;
  20948     if (popup->flags & NK_WINDOW_HIDDEN) {
  20949         struct nk_panel *root;
  20950         root = win->layout;
  20951         while (root) {
  20952             root->flags |= NK_WINDOW_REMOVE_ROM;
  20953             root = root->parent;
  20954         }
  20955         win->popup.active = 0;
  20956     }
  20957     nk_push_scissor(&popup->buffer, nk_null_rect);
  20958     nk_end(ctx);
  20959 
  20960     win->buffer = popup->buffer;
  20961     nk_finish_popup(ctx, win);
  20962     ctx->current = win;
  20963     nk_push_scissor(&win->buffer, win->layout->clip);
  20964 }
  20965 NK_API void
  20966 nk_popup_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
  20967 {
  20968     struct nk_window *popup;
  20969 
  20970     NK_ASSERT(ctx);
  20971     NK_ASSERT(ctx->current);
  20972     NK_ASSERT(ctx->current->layout);
  20973     if (!ctx || !ctx->current || !ctx->current->layout)
  20974         return;
  20975 
  20976     popup = ctx->current;
  20977     if (offset_x)
  20978       *offset_x = popup->scrollbar.x;
  20979     if (offset_y)
  20980       *offset_y = popup->scrollbar.y;
  20981 }
  20982 NK_API void
  20983 nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
  20984 {
  20985     struct nk_window *popup;
  20986 
  20987     NK_ASSERT(ctx);
  20988     NK_ASSERT(ctx->current);
  20989     NK_ASSERT(ctx->current->layout);
  20990     if (!ctx || !ctx->current || !ctx->current->layout)
  20991         return;
  20992 
  20993     popup = ctx->current;
  20994     popup->scrollbar.x = offset_x;
  20995     popup->scrollbar.y = offset_y;
  20996 }
  20997 
  20998 
  20999 
  21000 
  21001 /* ==============================================================
  21002  *
  21003  *                          CONTEXTUAL
  21004  *
  21005  * ===============================================================*/
  21006 NK_API nk_bool
  21007 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
  21008     struct nk_rect trigger_bounds)
  21009 {
  21010     struct nk_window *win;
  21011     struct nk_window *popup;
  21012     struct nk_rect body;
  21013 
  21014     NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0};
  21015     int is_clicked = 0;
  21016     int is_open = 0;
  21017     int ret = 0;
  21018 
  21019     NK_ASSERT(ctx);
  21020     NK_ASSERT(ctx->current);
  21021     NK_ASSERT(ctx->current->layout);
  21022     if (!ctx || !ctx->current || !ctx->current->layout)
  21023         return 0;
  21024 
  21025     win = ctx->current;
  21026     ++win->popup.con_count;
  21027     if (ctx->current != ctx->active)
  21028         return 0;
  21029 
  21030     /* check if currently active contextual is active */
  21031     popup = win->popup.win;
  21032     is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
  21033     is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
  21034     if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
  21035         return 0;
  21036     if (!is_open && win->popup.active_con)
  21037         win->popup.active_con = 0;
  21038     if ((!is_open && !is_clicked))
  21039         return 0;
  21040 
  21041     /* calculate contextual position on click */
  21042     win->popup.active_con = win->popup.con_count;
  21043     if (is_clicked) {
  21044         body.x = ctx->input.mouse.pos.x;
  21045         body.y = ctx->input.mouse.pos.y;
  21046     } else {
  21047         body.x = popup->bounds.x;
  21048         body.y = popup->bounds.y;
  21049     }
  21050     body.w = size.x;
  21051     body.h = size.y;
  21052 
  21053     /* start nonblocking contextual popup */
  21054     ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
  21055             null_rect, NK_PANEL_CONTEXTUAL);
  21056     if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
  21057     else {
  21058         win->popup.active_con = 0;
  21059         win->popup.type = NK_PANEL_NONE;
  21060         if (win->popup.win)
  21061             win->popup.win->flags = 0;
  21062     }
  21063     return ret;
  21064 }
  21065 NK_API nk_bool
  21066 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
  21067     nk_flags alignment)
  21068 {
  21069     struct nk_window *win;
  21070     const struct nk_input *in;
  21071     const struct nk_style *style;
  21072 
  21073     struct nk_rect bounds;
  21074     enum nk_widget_layout_states state;
  21075 
  21076     NK_ASSERT(ctx);
  21077     NK_ASSERT(ctx->current);
  21078     NK_ASSERT(ctx->current->layout);
  21079     if (!ctx || !ctx->current || !ctx->current->layout)
  21080         return 0;
  21081 
  21082     win = ctx->current;
  21083     style = &ctx->style;
  21084     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
  21085     if (!state) return nk_false;
  21086 
  21087     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21088     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
  21089         text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
  21090         nk_contextual_close(ctx);
  21091         return nk_true;
  21092     }
  21093     return nk_false;
  21094 }
  21095 NK_API nk_bool
  21096 nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
  21097 {
  21098     return nk_contextual_item_text(ctx, label, nk_strlen(label), align);
  21099 }
  21100 NK_API nk_bool
  21101 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
  21102     const char *text, int len, nk_flags align)
  21103 {
  21104     struct nk_window *win;
  21105     const struct nk_input *in;
  21106     const struct nk_style *style;
  21107 
  21108     struct nk_rect bounds;
  21109     enum nk_widget_layout_states state;
  21110 
  21111     NK_ASSERT(ctx);
  21112     NK_ASSERT(ctx->current);
  21113     NK_ASSERT(ctx->current->layout);
  21114     if (!ctx || !ctx->current || !ctx->current->layout)
  21115         return 0;
  21116 
  21117     win = ctx->current;
  21118     style = &ctx->style;
  21119     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
  21120     if (!state) return nk_false;
  21121 
  21122     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21123     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
  21124         img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
  21125         nk_contextual_close(ctx);
  21126         return nk_true;
  21127     }
  21128     return nk_false;
  21129 }
  21130 NK_API nk_bool
  21131 nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
  21132     const char *label, nk_flags align)
  21133 {
  21134     return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);
  21135 }
  21136 NK_API nk_bool
  21137 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
  21138     const char *text, int len, nk_flags align)
  21139 {
  21140     struct nk_window *win;
  21141     const struct nk_input *in;
  21142     const struct nk_style *style;
  21143 
  21144     struct nk_rect bounds;
  21145     enum nk_widget_layout_states state;
  21146 
  21147     NK_ASSERT(ctx);
  21148     NK_ASSERT(ctx->current);
  21149     NK_ASSERT(ctx->current->layout);
  21150     if (!ctx || !ctx->current || !ctx->current->layout)
  21151         return 0;
  21152 
  21153     win = ctx->current;
  21154     style = &ctx->style;
  21155     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
  21156     if (!state) return nk_false;
  21157 
  21158     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21159     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
  21160         symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
  21161         nk_contextual_close(ctx);
  21162         return nk_true;
  21163     }
  21164     return nk_false;
  21165 }
  21166 NK_API nk_bool
  21167 nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
  21168     const char *text, nk_flags align)
  21169 {
  21170     return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);
  21171 }
  21172 NK_API void
  21173 nk_contextual_close(struct nk_context *ctx)
  21174 {
  21175     NK_ASSERT(ctx);
  21176     NK_ASSERT(ctx->current);
  21177     NK_ASSERT(ctx->current->layout);
  21178     if (!ctx || !ctx->current || !ctx->current->layout) return;
  21179     nk_popup_close(ctx);
  21180 }
  21181 NK_API void
  21182 nk_contextual_end(struct nk_context *ctx)
  21183 {
  21184     struct nk_window *popup;
  21185     struct nk_panel *panel;
  21186     NK_ASSERT(ctx);
  21187     NK_ASSERT(ctx->current);
  21188     if (!ctx || !ctx->current) return;
  21189 
  21190     popup = ctx->current;
  21191     panel = popup->layout;
  21192     NK_ASSERT(popup->parent);
  21193     NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
  21194     if (panel->flags & NK_WINDOW_DYNAMIC) {
  21195         /* Close behavior
  21196         This is a bit of a hack solution since we do not know before we end our popup
  21197         how big it will be. We therefore do not directly know when a
  21198         click outside the non-blocking popup must close it at that direct frame.
  21199         Instead it will be closed in the next frame.*/
  21200         struct nk_rect body = {0,0,0,0};
  21201         if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
  21202             struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
  21203             body = panel->bounds;
  21204             body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
  21205             body.h = (panel->bounds.y + panel->bounds.h) - body.y;
  21206         }
  21207         {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
  21208         int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
  21209         if (pressed && in_body)
  21210             popup->flags |= NK_WINDOW_HIDDEN;
  21211         }
  21212     }
  21213     if (popup->flags & NK_WINDOW_HIDDEN)
  21214         popup->seq = 0;
  21215     nk_popup_end(ctx);
  21216     return;
  21217 }
  21218 
  21219 
  21220 
  21221 
  21222 
  21223 /* ===============================================================
  21224  *
  21225  *                              MENU
  21226  *
  21227  * ===============================================================*/
  21228 NK_API void
  21229 nk_menubar_begin(struct nk_context *ctx)
  21230 {
  21231     struct nk_panel *layout;
  21232     NK_ASSERT(ctx);
  21233     NK_ASSERT(ctx->current);
  21234     NK_ASSERT(ctx->current->layout);
  21235     if (!ctx || !ctx->current || !ctx->current->layout)
  21236         return;
  21237 
  21238     layout = ctx->current->layout;
  21239     NK_ASSERT(layout->at_y == layout->bounds.y);
  21240     /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
  21241     If you want a menubar the first nuklear function after `nk_begin` has to be a
  21242     `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
  21243     widgets (also supports multiple rows).
  21244     Example:
  21245         if (nk_begin(...)) {
  21246             nk_menubar_begin(...);
  21247                 nk_layout_xxxx(...);
  21248                 nk_button(...);
  21249                 nk_layout_xxxx(...);
  21250                 nk_button(...);
  21251             nk_menubar_end(...);
  21252         }
  21253         nk_end(...);
  21254     */
  21255     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
  21256         return;
  21257 
  21258     layout->menu.x = layout->at_x;
  21259     layout->menu.y = layout->at_y + layout->row.height;
  21260     layout->menu.w = layout->bounds.w;
  21261     layout->menu.offset.x = *layout->offset_x;
  21262     layout->menu.offset.y = *layout->offset_y;
  21263     *layout->offset_y = 0;
  21264 }
  21265 NK_API void
  21266 nk_menubar_end(struct nk_context *ctx)
  21267 {
  21268     struct nk_window *win;
  21269     struct nk_panel *layout;
  21270     struct nk_command_buffer *out;
  21271 
  21272     NK_ASSERT(ctx);
  21273     NK_ASSERT(ctx->current);
  21274     NK_ASSERT(ctx->current->layout);
  21275     if (!ctx || !ctx->current || !ctx->current->layout)
  21276         return;
  21277 
  21278     win = ctx->current;
  21279     out = &win->buffer;
  21280     layout = win->layout;
  21281     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
  21282         return;
  21283 
  21284     layout->menu.h  = layout->at_y - layout->menu.y;
  21285     layout->menu.h += layout->row.height + ctx->style.window.spacing.y;
  21286 
  21287     layout->bounds.y += layout->menu.h;
  21288     layout->bounds.h -= layout->menu.h;
  21289 
  21290     *layout->offset_x = layout->menu.offset.x;
  21291     *layout->offset_y = layout->menu.offset.y;
  21292     layout->at_y      = layout->bounds.y - layout->row.height;
  21293 
  21294     layout->clip.y = layout->bounds.y;
  21295     layout->clip.h = layout->bounds.h;
  21296     nk_push_scissor(out, layout->clip);
  21297 }
  21298 NK_INTERN int
  21299 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
  21300     const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
  21301 {
  21302     int is_open = 0;
  21303     int is_active = 0;
  21304     struct nk_rect body;
  21305     struct nk_window *popup;
  21306     nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
  21307 
  21308     NK_ASSERT(ctx);
  21309     NK_ASSERT(ctx->current);
  21310     NK_ASSERT(ctx->current->layout);
  21311     if (!ctx || !ctx->current || !ctx->current->layout)
  21312         return 0;
  21313 
  21314     body.x = header.x;
  21315     body.w = size.x;
  21316     body.y = header.y + header.h;
  21317     body.h = size.y;
  21318 
  21319     popup = win->popup.win;
  21320     is_open = popup ? nk_true : nk_false;
  21321     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
  21322     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
  21323         (!is_open && !is_active && !is_clicked)) return 0;
  21324     if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
  21325         return 0;
  21326 
  21327     win->popup.type = NK_PANEL_MENU;
  21328     win->popup.name = hash;
  21329     return 1;
  21330 }
  21331 NK_API nk_bool
  21332 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
  21333     nk_flags align, struct nk_vec2 size)
  21334 {
  21335     struct nk_window *win;
  21336     const struct nk_input *in;
  21337     struct nk_rect header;
  21338     int is_clicked = nk_false;
  21339     nk_flags state;
  21340 
  21341     NK_ASSERT(ctx);
  21342     NK_ASSERT(ctx->current);
  21343     NK_ASSERT(ctx->current->layout);
  21344     if (!ctx || !ctx->current || !ctx->current->layout)
  21345         return 0;
  21346 
  21347     win = ctx->current;
  21348     state = nk_widget(&header, ctx);
  21349     if (!state) return 0;
  21350     in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21351     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
  21352         title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
  21353         is_clicked = nk_true;
  21354     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  21355 }
  21356 NK_API nk_bool nk_menu_begin_label(struct nk_context *ctx,
  21357     const char *text, nk_flags align, struct nk_vec2 size)
  21358 {
  21359     return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);
  21360 }
  21361 NK_API nk_bool
  21362 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
  21363     struct nk_vec2 size)
  21364 {
  21365     struct nk_window *win;
  21366     struct nk_rect header;
  21367     const struct nk_input *in;
  21368     int is_clicked = nk_false;
  21369     nk_flags state;
  21370 
  21371     NK_ASSERT(ctx);
  21372     NK_ASSERT(ctx->current);
  21373     NK_ASSERT(ctx->current->layout);
  21374     if (!ctx || !ctx->current || !ctx->current->layout)
  21375         return 0;
  21376 
  21377     win = ctx->current;
  21378     state = nk_widget(&header, ctx);
  21379     if (!state) return 0;
  21380     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21381     if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
  21382         img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
  21383         is_clicked = nk_true;
  21384     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
  21385 }
  21386 NK_API nk_bool
  21387 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
  21388     enum nk_symbol_type sym, struct nk_vec2 size)
  21389 {
  21390     struct nk_window *win;
  21391     const struct nk_input *in;
  21392     struct nk_rect header;
  21393     int is_clicked = nk_false;
  21394     nk_flags state;
  21395 
  21396     NK_ASSERT(ctx);
  21397     NK_ASSERT(ctx->current);
  21398     NK_ASSERT(ctx->current->layout);
  21399     if (!ctx || !ctx->current || !ctx->current->layout)
  21400         return 0;
  21401 
  21402     win = ctx->current;
  21403     state = nk_widget(&header, ctx);
  21404     if (!state) return 0;
  21405     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21406     if (nk_do_button_symbol(&ctx->last_widget_state,  &win->buffer, header,
  21407         sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
  21408         is_clicked = nk_true;
  21409     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
  21410 }
  21411 NK_API nk_bool
  21412 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
  21413     nk_flags align, struct nk_image img, struct nk_vec2 size)
  21414 {
  21415     struct nk_window *win;
  21416     struct nk_rect header;
  21417     const struct nk_input *in;
  21418     int is_clicked = nk_false;
  21419     nk_flags state;
  21420 
  21421     NK_ASSERT(ctx);
  21422     NK_ASSERT(ctx->current);
  21423     NK_ASSERT(ctx->current->layout);
  21424     if (!ctx || !ctx->current || !ctx->current->layout)
  21425         return 0;
  21426 
  21427     win = ctx->current;
  21428     state = nk_widget(&header, ctx);
  21429     if (!state) return 0;
  21430     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21431     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
  21432         header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
  21433         ctx->style.font, in))
  21434         is_clicked = nk_true;
  21435     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  21436 }
  21437 NK_API nk_bool
  21438 nk_menu_begin_image_label(struct nk_context *ctx,
  21439     const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
  21440 {
  21441     return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);
  21442 }
  21443 NK_API nk_bool
  21444 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
  21445     nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
  21446 {
  21447     struct nk_window *win;
  21448     struct nk_rect header;
  21449     const struct nk_input *in;
  21450     int is_clicked = nk_false;
  21451     nk_flags state;
  21452 
  21453     NK_ASSERT(ctx);
  21454     NK_ASSERT(ctx->current);
  21455     NK_ASSERT(ctx->current->layout);
  21456     if (!ctx || !ctx->current || !ctx->current->layout)
  21457         return 0;
  21458 
  21459     win = ctx->current;
  21460     state = nk_widget(&header, ctx);
  21461     if (!state) return 0;
  21462 
  21463     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21464     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
  21465         header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
  21466         ctx->style.font, in)) is_clicked = nk_true;
  21467     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  21468 }
  21469 NK_API nk_bool
  21470 nk_menu_begin_symbol_label(struct nk_context *ctx,
  21471     const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
  21472 {
  21473     return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);
  21474 }
  21475 NK_API nk_bool
  21476 nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
  21477 {
  21478     return nk_contextual_item_text(ctx, title, len, align);
  21479 }
  21480 NK_API nk_bool
  21481 nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
  21482 {
  21483     return nk_contextual_item_label(ctx, label, align);
  21484 }
  21485 NK_API nk_bool
  21486 nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
  21487     const char *label, nk_flags align)
  21488 {
  21489     return nk_contextual_item_image_label(ctx, img, label, align);
  21490 }
  21491 NK_API nk_bool
  21492 nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
  21493     const char *text, int len, nk_flags align)
  21494 {
  21495     return nk_contextual_item_image_text(ctx, img, text, len, align);
  21496 }
  21497 NK_API nk_bool nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  21498     const char *text, int len, nk_flags align)
  21499 {
  21500     return nk_contextual_item_symbol_text(ctx, sym, text, len, align);
  21501 }
  21502 NK_API nk_bool nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  21503     const char *label, nk_flags align)
  21504 {
  21505     return nk_contextual_item_symbol_label(ctx, sym, label, align);
  21506 }
  21507 NK_API void nk_menu_close(struct nk_context *ctx)
  21508 {
  21509     nk_contextual_close(ctx);
  21510 }
  21511 NK_API void
  21512 nk_menu_end(struct nk_context *ctx)
  21513 {
  21514     nk_contextual_end(ctx);
  21515 }
  21516 
  21517 
  21518 
  21519 
  21520 
  21521 /* ===============================================================
  21522  *
  21523  *                          LAYOUT
  21524  *
  21525  * ===============================================================*/
  21526 NK_API void
  21527 nk_layout_set_min_row_height(struct nk_context *ctx, float height)
  21528 {
  21529     struct nk_window *win;
  21530     struct nk_panel *layout;
  21531 
  21532     NK_ASSERT(ctx);
  21533     NK_ASSERT(ctx->current);
  21534     NK_ASSERT(ctx->current->layout);
  21535     if (!ctx || !ctx->current || !ctx->current->layout)
  21536         return;
  21537 
  21538     win = ctx->current;
  21539     layout = win->layout;
  21540     layout->row.min_height = height;
  21541 }
  21542 NK_API void
  21543 nk_layout_reset_min_row_height(struct nk_context *ctx)
  21544 {
  21545     struct nk_window *win;
  21546     struct nk_panel *layout;
  21547 
  21548     NK_ASSERT(ctx);
  21549     NK_ASSERT(ctx->current);
  21550     NK_ASSERT(ctx->current->layout);
  21551     if (!ctx || !ctx->current || !ctx->current->layout)
  21552         return;
  21553 
  21554     win = ctx->current;
  21555     layout = win->layout;
  21556     layout->row.min_height = ctx->style.font->height;
  21557     layout->row.min_height += ctx->style.text.padding.y*2;
  21558     layout->row.min_height += ctx->style.window.min_row_height_padding*2;
  21559 }
  21560 NK_LIB float
  21561 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
  21562     float total_space, int columns)
  21563 {
  21564     float panel_spacing;
  21565     float panel_space;
  21566 
  21567     struct nk_vec2 spacing;
  21568 
  21569     NK_UNUSED(type);
  21570 
  21571     spacing = style->window.spacing;
  21572 
  21573     /* calculate the usable panel space */
  21574     panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
  21575     panel_space  = total_space - panel_spacing;
  21576     return panel_space;
  21577 }
  21578 NK_LIB void
  21579 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
  21580     float height, int cols)
  21581 {
  21582     struct nk_panel *layout;
  21583     const struct nk_style *style;
  21584     struct nk_command_buffer *out;
  21585 
  21586     struct nk_vec2 item_spacing;
  21587     struct nk_color color;
  21588 
  21589     NK_ASSERT(ctx);
  21590     NK_ASSERT(ctx->current);
  21591     NK_ASSERT(ctx->current->layout);
  21592     if (!ctx || !ctx->current || !ctx->current->layout)
  21593         return;
  21594 
  21595     /* prefetch some configuration data */
  21596     layout = win->layout;
  21597     style = &ctx->style;
  21598     out = &win->buffer;
  21599     color = style->window.background;
  21600     item_spacing = style->window.spacing;
  21601 
  21602     /*  if one of these triggers you forgot to add an `if` condition around either
  21603         a window, group, popup, combobox or contextual menu `begin` and `end` block.
  21604         Example:
  21605             if (nk_begin(...) {...} nk_end(...); or
  21606             if (nk_group_begin(...) { nk_group_end(...);} */
  21607     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
  21608     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
  21609     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
  21610 
  21611     /* update the current row and set the current row layout */
  21612     layout->row.index = 0;
  21613     layout->at_y += layout->row.height;
  21614     layout->row.columns = cols;
  21615     if (height == 0.0f)
  21616         layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
  21617     else layout->row.height = height + item_spacing.y;
  21618 
  21619     layout->row.item_offset = 0;
  21620     if (layout->flags & NK_WINDOW_DYNAMIC) {
  21621         /* draw background for dynamic panels */
  21622         struct nk_rect background;
  21623         background.x = win->bounds.x;
  21624         background.w = win->bounds.w;
  21625         background.y = layout->at_y - 1.0f;
  21626         background.h = layout->row.height + 1.0f;
  21627         nk_fill_rect(out, background, 0, color);
  21628     }
  21629 }
  21630 NK_LIB void
  21631 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
  21632     float height, int cols, int width)
  21633 {
  21634     /* update the current row and set the current row layout */
  21635     struct nk_window *win;
  21636     NK_ASSERT(ctx);
  21637     NK_ASSERT(ctx->current);
  21638     NK_ASSERT(ctx->current->layout);
  21639     if (!ctx || !ctx->current || !ctx->current->layout)
  21640         return;
  21641 
  21642     win = ctx->current;
  21643     nk_panel_layout(ctx, win, height, cols);
  21644     if (fmt == NK_DYNAMIC)
  21645         win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED;
  21646     else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
  21647 
  21648     win->layout->row.ratio = 0;
  21649     win->layout->row.filled = 0;
  21650     win->layout->row.item_offset = 0;
  21651     win->layout->row.item_width = (float)width;
  21652 }
  21653 NK_API float
  21654 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
  21655 {
  21656     struct nk_window *win;
  21657     NK_ASSERT(ctx);
  21658     NK_ASSERT(pixel_width);
  21659     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
  21660     win = ctx->current;
  21661     return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
  21662 }
  21663 NK_API void
  21664 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
  21665 {
  21666     nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
  21667 }
  21668 NK_API void
  21669 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
  21670 {
  21671     nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
  21672 }
  21673 NK_API void
  21674 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
  21675     float row_height, int cols)
  21676 {
  21677     struct nk_window *win;
  21678     struct nk_panel *layout;
  21679 
  21680     NK_ASSERT(ctx);
  21681     NK_ASSERT(ctx->current);
  21682     NK_ASSERT(ctx->current->layout);
  21683     if (!ctx || !ctx->current || !ctx->current->layout)
  21684         return;
  21685 
  21686     win = ctx->current;
  21687     layout = win->layout;
  21688     nk_panel_layout(ctx, win, row_height, cols);
  21689     if (fmt == NK_DYNAMIC)
  21690         layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
  21691     else layout->row.type = NK_LAYOUT_STATIC_ROW;
  21692 
  21693     layout->row.ratio = 0;
  21694     layout->row.filled = 0;
  21695     layout->row.item_width = 0;
  21696     layout->row.item_offset = 0;
  21697     layout->row.columns = cols;
  21698 }
  21699 NK_API void
  21700 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
  21701 {
  21702     struct nk_window *win;
  21703     struct nk_panel *layout;
  21704 
  21705     NK_ASSERT(ctx);
  21706     NK_ASSERT(ctx->current);
  21707     NK_ASSERT(ctx->current->layout);
  21708     if (!ctx || !ctx->current || !ctx->current->layout)
  21709         return;
  21710 
  21711     win = ctx->current;
  21712     layout = win->layout;
  21713     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
  21714     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
  21715         return;
  21716 
  21717     if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
  21718         float ratio = ratio_or_width;
  21719         if ((ratio + layout->row.filled) > 1.0f) return;
  21720         if (ratio > 0.0f)
  21721             layout->row.item_width = NK_SATURATE(ratio);
  21722         else layout->row.item_width = 1.0f - layout->row.filled;
  21723     } else layout->row.item_width = ratio_or_width;
  21724 }
  21725 NK_API void
  21726 nk_layout_row_end(struct nk_context *ctx)
  21727 {
  21728     struct nk_window *win;
  21729     struct nk_panel *layout;
  21730 
  21731     NK_ASSERT(ctx);
  21732     NK_ASSERT(ctx->current);
  21733     NK_ASSERT(ctx->current->layout);
  21734     if (!ctx || !ctx->current || !ctx->current->layout)
  21735         return;
  21736 
  21737     win = ctx->current;
  21738     layout = win->layout;
  21739     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
  21740     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
  21741         return;
  21742     layout->row.item_width = 0;
  21743     layout->row.item_offset = 0;
  21744 }
  21745 NK_API void
  21746 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
  21747     float height, int cols, const float *ratio)
  21748 {
  21749     int i;
  21750     int n_undef = 0;
  21751     struct nk_window *win;
  21752     struct nk_panel *layout;
  21753 
  21754     NK_ASSERT(ctx);
  21755     NK_ASSERT(ctx->current);
  21756     NK_ASSERT(ctx->current->layout);
  21757     if (!ctx || !ctx->current || !ctx->current->layout)
  21758         return;
  21759 
  21760     win = ctx->current;
  21761     layout = win->layout;
  21762     nk_panel_layout(ctx, win, height, cols);
  21763     if (fmt == NK_DYNAMIC) {
  21764         /* calculate width of undefined widget ratios */
  21765         float r = 0;
  21766         layout->row.ratio = ratio;
  21767         for (i = 0; i < cols; ++i) {
  21768             if (ratio[i] < 0.0f)
  21769                 n_undef++;
  21770             else r += ratio[i];
  21771         }
  21772         r = NK_SATURATE(1.0f - r);
  21773         layout->row.type = NK_LAYOUT_DYNAMIC;
  21774         layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
  21775     } else {
  21776         layout->row.ratio = ratio;
  21777         layout->row.type = NK_LAYOUT_STATIC;
  21778         layout->row.item_width = 0;
  21779         layout->row.item_offset = 0;
  21780     }
  21781     layout->row.item_offset = 0;
  21782     layout->row.filled = 0;
  21783 }
  21784 NK_API void
  21785 nk_layout_row_template_begin(struct nk_context *ctx, float height)
  21786 {
  21787     struct nk_window *win;
  21788     struct nk_panel *layout;
  21789 
  21790     NK_ASSERT(ctx);
  21791     NK_ASSERT(ctx->current);
  21792     NK_ASSERT(ctx->current->layout);
  21793     if (!ctx || !ctx->current || !ctx->current->layout)
  21794         return;
  21795 
  21796     win = ctx->current;
  21797     layout = win->layout;
  21798     nk_panel_layout(ctx, win, height, 1);
  21799     layout->row.type = NK_LAYOUT_TEMPLATE;
  21800     layout->row.columns = 0;
  21801     layout->row.ratio = 0;
  21802     layout->row.item_width = 0;
  21803     layout->row.item_height = 0;
  21804     layout->row.item_offset = 0;
  21805     layout->row.filled = 0;
  21806     layout->row.item.x = 0;
  21807     layout->row.item.y = 0;
  21808     layout->row.item.w = 0;
  21809     layout->row.item.h = 0;
  21810 }
  21811 NK_API void
  21812 nk_layout_row_template_push_dynamic(struct nk_context *ctx)
  21813 {
  21814     struct nk_window *win;
  21815     struct nk_panel *layout;
  21816 
  21817     NK_ASSERT(ctx);
  21818     NK_ASSERT(ctx->current);
  21819     NK_ASSERT(ctx->current->layout);
  21820     if (!ctx || !ctx->current || !ctx->current->layout)
  21821         return;
  21822 
  21823     win = ctx->current;
  21824     layout = win->layout;
  21825     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
  21826     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
  21827     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
  21828     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
  21829     layout->row.templates[layout->row.columns++] = -1.0f;
  21830 }
  21831 NK_API void
  21832 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
  21833 {
  21834     struct nk_window *win;
  21835     struct nk_panel *layout;
  21836 
  21837     NK_ASSERT(ctx);
  21838     NK_ASSERT(ctx->current);
  21839     NK_ASSERT(ctx->current->layout);
  21840     if (!ctx || !ctx->current || !ctx->current->layout)
  21841         return;
  21842 
  21843     win = ctx->current;
  21844     layout = win->layout;
  21845     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
  21846     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
  21847     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
  21848     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
  21849     layout->row.templates[layout->row.columns++] = -min_width;
  21850 }
  21851 NK_API void
  21852 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
  21853 {
  21854     struct nk_window *win;
  21855     struct nk_panel *layout;
  21856 
  21857     NK_ASSERT(ctx);
  21858     NK_ASSERT(ctx->current);
  21859     NK_ASSERT(ctx->current->layout);
  21860     if (!ctx || !ctx->current || !ctx->current->layout)
  21861         return;
  21862 
  21863     win = ctx->current;
  21864     layout = win->layout;
  21865     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
  21866     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
  21867     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
  21868     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
  21869     layout->row.templates[layout->row.columns++] = width;
  21870 }
  21871 NK_API void
  21872 nk_layout_row_template_end(struct nk_context *ctx)
  21873 {
  21874     struct nk_window *win;
  21875     struct nk_panel *layout;
  21876 
  21877     int i = 0;
  21878     int variable_count = 0;
  21879     int min_variable_count = 0;
  21880     float min_fixed_width = 0.0f;
  21881     float total_fixed_width = 0.0f;
  21882     float max_variable_width = 0.0f;
  21883 
  21884     NK_ASSERT(ctx);
  21885     NK_ASSERT(ctx->current);
  21886     NK_ASSERT(ctx->current->layout);
  21887     if (!ctx || !ctx->current || !ctx->current->layout)
  21888         return;
  21889 
  21890     win = ctx->current;
  21891     layout = win->layout;
  21892     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
  21893     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
  21894     for (i = 0; i < layout->row.columns; ++i) {
  21895         float width = layout->row.templates[i];
  21896         if (width >= 0.0f) {
  21897             total_fixed_width += width;
  21898             min_fixed_width += width;
  21899         } else if (width < -1.0f) {
  21900             width = -width;
  21901             total_fixed_width += width;
  21902             max_variable_width = NK_MAX(max_variable_width, width);
  21903             variable_count++;
  21904         } else {
  21905             min_variable_count++;
  21906             variable_count++;
  21907         }
  21908     }
  21909     if (variable_count) {
  21910         float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
  21911                             layout->bounds.w, layout->row.columns);
  21912         float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
  21913         int enough_space = var_width >= max_variable_width;
  21914         if (!enough_space)
  21915             var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
  21916         for (i = 0; i < layout->row.columns; ++i) {
  21917             float *width = &layout->row.templates[i];
  21918             *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
  21919         }
  21920     }
  21921 }
  21922 NK_API void
  21923 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
  21924     float height, int widget_count)
  21925 {
  21926     struct nk_window *win;
  21927     struct nk_panel *layout;
  21928 
  21929     NK_ASSERT(ctx);
  21930     NK_ASSERT(ctx->current);
  21931     NK_ASSERT(ctx->current->layout);
  21932     if (!ctx || !ctx->current || !ctx->current->layout)
  21933         return;
  21934 
  21935     win = ctx->current;
  21936     layout = win->layout;
  21937     nk_panel_layout(ctx, win, height, widget_count);
  21938     if (fmt == NK_STATIC)
  21939         layout->row.type = NK_LAYOUT_STATIC_FREE;
  21940     else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
  21941 
  21942     layout->row.ratio = 0;
  21943     layout->row.filled = 0;
  21944     layout->row.item_width = 0;
  21945     layout->row.item_offset = 0;
  21946 }
  21947 NK_API void
  21948 nk_layout_space_end(struct nk_context *ctx)
  21949 {
  21950     struct nk_window *win;
  21951     struct nk_panel *layout;
  21952 
  21953     NK_ASSERT(ctx);
  21954     NK_ASSERT(ctx->current);
  21955     NK_ASSERT(ctx->current->layout);
  21956     if (!ctx || !ctx->current || !ctx->current->layout)
  21957         return;
  21958 
  21959     win = ctx->current;
  21960     layout = win->layout;
  21961     layout->row.item_width = 0;
  21962     layout->row.item_height = 0;
  21963     layout->row.item_offset = 0;
  21964     nk_zero(&layout->row.item, sizeof(layout->row.item));
  21965 }
  21966 NK_API void
  21967 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
  21968 {
  21969     struct nk_window *win;
  21970     struct nk_panel *layout;
  21971 
  21972     NK_ASSERT(ctx);
  21973     NK_ASSERT(ctx->current);
  21974     NK_ASSERT(ctx->current->layout);
  21975     if (!ctx || !ctx->current || !ctx->current->layout)
  21976         return;
  21977 
  21978     win = ctx->current;
  21979     layout = win->layout;
  21980     layout->row.item = rect;
  21981 }
  21982 NK_API struct nk_rect
  21983 nk_layout_space_bounds(struct nk_context *ctx)
  21984 {
  21985     struct nk_rect ret;
  21986     struct nk_window *win;
  21987     struct nk_panel *layout;
  21988 
  21989     NK_ASSERT(ctx);
  21990     NK_ASSERT(ctx->current);
  21991     NK_ASSERT(ctx->current->layout);
  21992     win = ctx->current;
  21993     layout = win->layout;
  21994 
  21995     ret.x = layout->clip.x;
  21996     ret.y = layout->clip.y;
  21997     ret.w = layout->clip.w;
  21998     ret.h = layout->row.height;
  21999     return ret;
  22000 }
  22001 NK_API struct nk_rect
  22002 nk_layout_widget_bounds(struct nk_context *ctx)
  22003 {
  22004     struct nk_rect ret;
  22005     struct nk_window *win;
  22006     struct nk_panel *layout;
  22007 
  22008     NK_ASSERT(ctx);
  22009     NK_ASSERT(ctx->current);
  22010     NK_ASSERT(ctx->current->layout);
  22011     win = ctx->current;
  22012     layout = win->layout;
  22013 
  22014     ret.x = layout->at_x;
  22015     ret.y = layout->at_y;
  22016     ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
  22017     ret.h = layout->row.height;
  22018     return ret;
  22019 }
  22020 NK_API struct nk_vec2
  22021 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
  22022 {
  22023     struct nk_window *win;
  22024     struct nk_panel *layout;
  22025 
  22026     NK_ASSERT(ctx);
  22027     NK_ASSERT(ctx->current);
  22028     NK_ASSERT(ctx->current->layout);
  22029     win = ctx->current;
  22030     layout = win->layout;
  22031 
  22032     ret.x += layout->at_x - (float)*layout->offset_x;
  22033     ret.y += layout->at_y - (float)*layout->offset_y;
  22034     return ret;
  22035 }
  22036 NK_API struct nk_vec2
  22037 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
  22038 {
  22039     struct nk_window *win;
  22040     struct nk_panel *layout;
  22041 
  22042     NK_ASSERT(ctx);
  22043     NK_ASSERT(ctx->current);
  22044     NK_ASSERT(ctx->current->layout);
  22045     win = ctx->current;
  22046     layout = win->layout;
  22047 
  22048     ret.x += -layout->at_x + (float)*layout->offset_x;
  22049     ret.y += -layout->at_y + (float)*layout->offset_y;
  22050     return ret;
  22051 }
  22052 NK_API struct nk_rect
  22053 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret)
  22054 {
  22055     struct nk_window *win;
  22056     struct nk_panel *layout;
  22057 
  22058     NK_ASSERT(ctx);
  22059     NK_ASSERT(ctx->current);
  22060     NK_ASSERT(ctx->current->layout);
  22061     win = ctx->current;
  22062     layout = win->layout;
  22063 
  22064     ret.x += layout->at_x - (float)*layout->offset_x;
  22065     ret.y += layout->at_y - (float)*layout->offset_y;
  22066     return ret;
  22067 }
  22068 NK_API struct nk_rect
  22069 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret)
  22070 {
  22071     struct nk_window *win;
  22072     struct nk_panel *layout;
  22073 
  22074     NK_ASSERT(ctx);
  22075     NK_ASSERT(ctx->current);
  22076     NK_ASSERT(ctx->current->layout);
  22077     win = ctx->current;
  22078     layout = win->layout;
  22079 
  22080     ret.x += -layout->at_x + (float)*layout->offset_x;
  22081     ret.y += -layout->at_y + (float)*layout->offset_y;
  22082     return ret;
  22083 }
  22084 NK_LIB void
  22085 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
  22086 {
  22087     struct nk_panel *layout = win->layout;
  22088     struct nk_vec2 spacing = ctx->style.window.spacing;
  22089     const float row_height = layout->row.height - spacing.y;
  22090     nk_panel_layout(ctx, win, row_height, layout->row.columns);
  22091 }
  22092 NK_LIB void
  22093 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
  22094     struct nk_window *win, int modify)
  22095 {
  22096     struct nk_panel *layout;
  22097     const struct nk_style *style;
  22098 
  22099     struct nk_vec2 spacing;
  22100 
  22101     float item_offset = 0;
  22102     float item_width = 0;
  22103     float item_spacing = 0;
  22104     float panel_space = 0;
  22105 
  22106     NK_ASSERT(ctx);
  22107     NK_ASSERT(ctx->current);
  22108     NK_ASSERT(ctx->current->layout);
  22109     if (!ctx || !ctx->current || !ctx->current->layout)
  22110         return;
  22111 
  22112     win = ctx->current;
  22113     layout = win->layout;
  22114     style = &ctx->style;
  22115     NK_ASSERT(bounds);
  22116 
  22117     spacing = style->window.spacing;
  22118     panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
  22119                                             layout->bounds.w, layout->row.columns);
  22120 
  22121     #define NK_FRAC(x) (x - (float)(int)x) /* will be used to remove fookin gaps */
  22122     /* calculate the width of one item inside the current layout space */
  22123     switch (layout->row.type) {
  22124     case NK_LAYOUT_DYNAMIC_FIXED: {
  22125         /* scaling fixed size widgets item width */
  22126         float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns;
  22127         item_offset = (float)layout->row.index * w;
  22128         item_width = w + NK_FRAC(item_offset);
  22129         item_spacing = (float)layout->row.index * spacing.x;
  22130     } break;
  22131     case NK_LAYOUT_DYNAMIC_ROW: {
  22132         /* scaling single ratio widget width */
  22133         float w = layout->row.item_width * panel_space;
  22134         item_offset = layout->row.item_offset;
  22135         item_width = w + NK_FRAC(item_offset);
  22136         item_spacing = 0;
  22137 
  22138         if (modify) {
  22139             layout->row.item_offset += w + spacing.x;
  22140             layout->row.filled += layout->row.item_width;
  22141             layout->row.index = 0;
  22142         }
  22143     } break;
  22144     case NK_LAYOUT_DYNAMIC_FREE: {
  22145         /* panel width depended free widget placing */
  22146         bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
  22147         bounds->x -= (float)*layout->offset_x;
  22148         bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
  22149         bounds->y -= (float)*layout->offset_y;
  22150         bounds->w = layout->bounds.w  * layout->row.item.w + NK_FRAC(bounds->x);
  22151         bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y);
  22152         return;
  22153     }
  22154     case NK_LAYOUT_DYNAMIC: {
  22155         /* scaling arrays of panel width ratios for every widget */
  22156         float ratio, w;
  22157         NK_ASSERT(layout->row.ratio);
  22158         ratio = (layout->row.ratio[layout->row.index] < 0) ?
  22159             layout->row.item_width : layout->row.ratio[layout->row.index];
  22160 
  22161         w = (ratio * panel_space);
  22162         item_spacing = (float)layout->row.index * spacing.x;
  22163         item_offset = layout->row.item_offset;
  22164         item_width = w + NK_FRAC(item_offset);
  22165 
  22166         if (modify) {
  22167             layout->row.item_offset += w;
  22168             layout->row.filled += ratio;
  22169         }
  22170     } break;
  22171     case NK_LAYOUT_STATIC_FIXED: {
  22172         /* non-scaling fixed widgets item width */
  22173         item_width = layout->row.item_width;
  22174         item_offset = (float)layout->row.index * item_width;
  22175         item_spacing = (float)layout->row.index * spacing.x;
  22176     } break;
  22177     case NK_LAYOUT_STATIC_ROW: {
  22178         /* scaling single ratio widget width */
  22179         item_width = layout->row.item_width;
  22180         item_offset = layout->row.item_offset;
  22181         item_spacing = (float)layout->row.index * spacing.x;
  22182         if (modify) layout->row.item_offset += item_width;
  22183     } break;
  22184     case NK_LAYOUT_STATIC_FREE: {
  22185         /* free widget placing */
  22186         bounds->x = layout->at_x + layout->row.item.x;
  22187         bounds->w = layout->row.item.w;
  22188         if (((bounds->x + bounds->w) > layout->max_x) && modify)
  22189             layout->max_x = (bounds->x + bounds->w);
  22190         bounds->x -= (float)*layout->offset_x;
  22191         bounds->y = layout->at_y + layout->row.item.y;
  22192         bounds->y -= (float)*layout->offset_y;
  22193         bounds->h = layout->row.item.h;
  22194         return;
  22195     }
  22196     case NK_LAYOUT_STATIC: {
  22197         /* non-scaling array of panel pixel width for every widget */
  22198         item_spacing = (float)layout->row.index * spacing.x;
  22199         item_width = layout->row.ratio[layout->row.index];
  22200         item_offset = layout->row.item_offset;
  22201         if (modify) layout->row.item_offset += item_width;
  22202     } break;
  22203     case NK_LAYOUT_TEMPLATE: {
  22204         /* stretchy row layout with combined dynamic/static widget width*/
  22205         float w;
  22206         NK_ASSERT(layout->row.index < layout->row.columns);
  22207         NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
  22208         w = layout->row.templates[layout->row.index];
  22209         item_offset = layout->row.item_offset;
  22210         item_width = w + NK_FRAC(item_offset);
  22211         item_spacing = (float)layout->row.index * spacing.x;
  22212         if (modify) layout->row.item_offset += w;
  22213     } break;
  22214     #undef NK_FRAC
  22215     default: NK_ASSERT(0); break;
  22216     };
  22217 
  22218     /* set the bounds of the newly allocated widget */
  22219     bounds->w = item_width;
  22220     bounds->h = layout->row.height - spacing.y;
  22221     bounds->y = layout->at_y - (float)*layout->offset_y;
  22222     bounds->x = layout->at_x + item_offset + item_spacing;
  22223     if (((bounds->x + bounds->w) > layout->max_x) && modify)
  22224         layout->max_x = bounds->x + bounds->w;
  22225     bounds->x -= (float)*layout->offset_x;
  22226 }
  22227 NK_LIB void
  22228 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
  22229 {
  22230     struct nk_window *win;
  22231     struct nk_panel *layout;
  22232 
  22233     NK_ASSERT(ctx);
  22234     NK_ASSERT(ctx->current);
  22235     NK_ASSERT(ctx->current->layout);
  22236     if (!ctx || !ctx->current || !ctx->current->layout)
  22237         return;
  22238 
  22239     /* check if the end of the row has been hit and begin new row if so */
  22240     win = ctx->current;
  22241     layout = win->layout;
  22242     if (layout->row.index >= layout->row.columns)
  22243         nk_panel_alloc_row(ctx, win);
  22244 
  22245     /* calculate widget position and size */
  22246     nk_layout_widget_space(bounds, ctx, win, nk_true);
  22247     layout->row.index++;
  22248 }
  22249 NK_LIB void
  22250 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
  22251 {
  22252     float y;
  22253     int index;
  22254     struct nk_window *win;
  22255     struct nk_panel *layout;
  22256 
  22257     NK_ASSERT(ctx);
  22258     NK_ASSERT(ctx->current);
  22259     NK_ASSERT(ctx->current->layout);
  22260     if (!ctx || !ctx->current || !ctx->current->layout) {
  22261         *bounds = nk_rect(0,0,0,0);
  22262         return;
  22263     }
  22264 
  22265     win = ctx->current;
  22266     layout = win->layout;
  22267     y = layout->at_y;
  22268     index = layout->row.index;
  22269     if (layout->row.index >= layout->row.columns) {
  22270         layout->at_y += layout->row.height;
  22271         layout->row.index = 0;
  22272     }
  22273     nk_layout_widget_space(bounds, ctx, win, nk_false);
  22274     if (!layout->row.index) {
  22275         bounds->x -= layout->row.item_offset;
  22276     }
  22277     layout->at_y = y;
  22278     layout->row.index = index;
  22279 }
  22280 NK_API void
  22281 nk_spacer(struct nk_context *ctx )
  22282 {
  22283     struct nk_rect dummy_rect = { 0, 0, 0, 0 };
  22284     nk_panel_alloc_space( &dummy_rect, ctx );
  22285 }
  22286 
  22287 
  22288 
  22289 
  22290 /* ===============================================================
  22291  *
  22292  *                              TREE
  22293  *
  22294  * ===============================================================*/
  22295 NK_INTERN int
  22296 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
  22297     struct nk_image *img, const char *title, enum nk_collapse_states *state)
  22298 {
  22299     struct nk_window *win;
  22300     struct nk_panel *layout;
  22301     const struct nk_style *style;
  22302     struct nk_command_buffer *out;
  22303     const struct nk_input *in;
  22304     const struct nk_style_button *button;
  22305     enum nk_symbol_type symbol;
  22306     float row_height;
  22307 
  22308     struct nk_vec2 item_spacing;
  22309     struct nk_rect header = {0,0,0,0};
  22310     struct nk_rect sym = {0,0,0,0};
  22311     struct nk_text text;
  22312 
  22313     nk_flags ws = 0;
  22314     enum nk_widget_layout_states widget_state;
  22315 
  22316     NK_ASSERT(ctx);
  22317     NK_ASSERT(ctx->current);
  22318     NK_ASSERT(ctx->current->layout);
  22319     if (!ctx || !ctx->current || !ctx->current->layout)
  22320         return 0;
  22321 
  22322     /* cache some data */
  22323     win = ctx->current;
  22324     layout = win->layout;
  22325     out = &win->buffer;
  22326     style = &ctx->style;
  22327     item_spacing = style->window.spacing;
  22328 
  22329     /* calculate header bounds and draw background */
  22330     row_height = style->font->height + 2 * style->tab.padding.y;
  22331     nk_layout_set_min_row_height(ctx, row_height);
  22332     nk_layout_row_dynamic(ctx, row_height, 1);
  22333     nk_layout_reset_min_row_height(ctx);
  22334 
  22335     widget_state = nk_widget(&header, ctx);
  22336     if (type == NK_TREE_TAB) {
  22337         const struct nk_style_item *background = &style->tab.background;
  22338 
  22339         switch(background->type) {
  22340             case NK_STYLE_ITEM_IMAGE:
  22341                 nk_draw_image(out, header, &background->data.image, nk_white);
  22342                 break;
  22343             case NK_STYLE_ITEM_NINE_SLICE:
  22344                 nk_draw_nine_slice(out, header, &background->data.slice, nk_white);
  22345                 break;
  22346             case NK_STYLE_ITEM_COLOR:
  22347                 nk_fill_rect(out, header, 0, style->tab.border_color);
  22348                 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
  22349                     style->tab.rounding, background->data.color);
  22350                 break;
  22351         }
  22352     } else text.background = style->window.background;
  22353 
  22354     /* update node state */
  22355     in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
  22356     in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
  22357     if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
  22358         *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
  22359 
  22360     /* select correct button style */
  22361     if (*state == NK_MAXIMIZED) {
  22362         symbol = style->tab.sym_maximize;
  22363         if (type == NK_TREE_TAB)
  22364             button = &style->tab.tab_maximize_button;
  22365         else button = &style->tab.node_maximize_button;
  22366     } else {
  22367         symbol = style->tab.sym_minimize;
  22368         if (type == NK_TREE_TAB)
  22369             button = &style->tab.tab_minimize_button;
  22370         else button = &style->tab.node_minimize_button;
  22371     }
  22372 
  22373     {/* draw triangle button */
  22374     sym.w = sym.h = style->font->height;
  22375     sym.y = header.y + style->tab.padding.y;
  22376     sym.x = header.x + style->tab.padding.x;
  22377     nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
  22378         button, 0, style->font);
  22379 
  22380     if (img) {
  22381         /* draw optional image icon */
  22382         sym.x = sym.x + sym.w + 4 * item_spacing.x;
  22383         nk_draw_image(&win->buffer, sym, img, nk_white);
  22384         sym.w = style->font->height + style->tab.spacing.x;}
  22385     }
  22386 
  22387     {/* draw label */
  22388     struct nk_rect label;
  22389     header.w = NK_MAX(header.w, sym.w + item_spacing.x);
  22390     label.x = sym.x + sym.w + item_spacing.x;
  22391     label.y = sym.y;
  22392     label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
  22393     label.h = style->font->height;
  22394     text.text = style->tab.text;
  22395     text.padding = nk_vec2(0,0);
  22396     nk_widget_text(out, label, title, nk_strlen(title), &text,
  22397         NK_TEXT_LEFT, style->font);}
  22398 
  22399     /* increase x-axis cursor widget position pointer */
  22400     if (*state == NK_MAXIMIZED) {
  22401         layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
  22402         layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
  22403         layout->bounds.w -= (style->tab.indent + style->window.padding.x);
  22404         layout->row.tree_depth++;
  22405         return nk_true;
  22406     } else return nk_false;
  22407 }
  22408 NK_INTERN int
  22409 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
  22410     struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
  22411     const char *hash, int len, int line)
  22412 {
  22413     struct nk_window *win = ctx->current;
  22414     int title_len = 0;
  22415     nk_hash tree_hash = 0;
  22416     nk_uint *state = 0;
  22417 
  22418     /* retrieve tree state from internal widget state tables */
  22419     if (!hash) {
  22420         title_len = (int)nk_strlen(title);
  22421         tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
  22422     } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
  22423     state = nk_find_value(win, tree_hash);
  22424     if (!state) {
  22425         state = nk_add_value(ctx, win, tree_hash, 0);
  22426         *state = initial_state;
  22427     }
  22428     return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
  22429 }
  22430 NK_API nk_bool
  22431 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
  22432     const char *title, enum nk_collapse_states *state)
  22433 {
  22434     return nk_tree_state_base(ctx, type, 0, title, state);
  22435 }
  22436 NK_API nk_bool
  22437 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
  22438     struct nk_image img, const char *title, enum nk_collapse_states *state)
  22439 {
  22440     return nk_tree_state_base(ctx, type, &img, title, state);
  22441 }
  22442 NK_API void
  22443 nk_tree_state_pop(struct nk_context *ctx)
  22444 {
  22445     struct nk_window *win = 0;
  22446     struct nk_panel *layout = 0;
  22447 
  22448     NK_ASSERT(ctx);
  22449     NK_ASSERT(ctx->current);
  22450     NK_ASSERT(ctx->current->layout);
  22451     if (!ctx || !ctx->current || !ctx->current->layout)
  22452         return;
  22453 
  22454     win = ctx->current;
  22455     layout = win->layout;
  22456     layout->at_x -= ctx->style.tab.indent + (float)*layout->offset_x;
  22457     layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
  22458     NK_ASSERT(layout->row.tree_depth);
  22459     layout->row.tree_depth--;
  22460 }
  22461 NK_API nk_bool
  22462 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
  22463     const char *title, enum nk_collapse_states initial_state,
  22464     const char *hash, int len, int line)
  22465 {
  22466     return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);
  22467 }
  22468 NK_API nk_bool
  22469 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
  22470     struct nk_image img, const char *title, enum nk_collapse_states initial_state,
  22471     const char *hash, int len,int seed)
  22472 {
  22473     return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);
  22474 }
  22475 NK_API void
  22476 nk_tree_pop(struct nk_context *ctx)
  22477 {
  22478     nk_tree_state_pop(ctx);
  22479 }
  22480 NK_INTERN int
  22481 nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type,
  22482     struct nk_image *img, const char *title, int title_len,
  22483     enum nk_collapse_states *state, nk_bool *selected)
  22484 {
  22485     struct nk_window *win;
  22486     struct nk_panel *layout;
  22487     const struct nk_style *style;
  22488     struct nk_command_buffer *out;
  22489     const struct nk_input *in;
  22490     const struct nk_style_button *button;
  22491     enum nk_symbol_type symbol;
  22492     float row_height;
  22493     struct nk_vec2 padding;
  22494 
  22495     int text_len;
  22496     float text_width;
  22497 
  22498     struct nk_vec2 item_spacing;
  22499     struct nk_rect header = {0,0,0,0};
  22500     struct nk_rect sym = {0,0,0,0};
  22501 
  22502     nk_flags ws = 0;
  22503     enum nk_widget_layout_states widget_state;
  22504 
  22505     NK_ASSERT(ctx);
  22506     NK_ASSERT(ctx->current);
  22507     NK_ASSERT(ctx->current->layout);
  22508     if (!ctx || !ctx->current || !ctx->current->layout)
  22509         return 0;
  22510 
  22511     /* cache some data */
  22512     win = ctx->current;
  22513     layout = win->layout;
  22514     out = &win->buffer;
  22515     style = &ctx->style;
  22516     item_spacing = style->window.spacing;
  22517     padding = style->selectable.padding;
  22518 
  22519     /* calculate header bounds and draw background */
  22520     row_height = style->font->height + 2 * style->tab.padding.y;
  22521     nk_layout_set_min_row_height(ctx, row_height);
  22522     nk_layout_row_dynamic(ctx, row_height, 1);
  22523     nk_layout_reset_min_row_height(ctx);
  22524 
  22525     widget_state = nk_widget(&header, ctx);
  22526     if (type == NK_TREE_TAB) {
  22527         const struct nk_style_item *background = &style->tab.background;
  22528 
  22529         switch (background->type) {
  22530             case NK_STYLE_ITEM_IMAGE:
  22531                 nk_draw_image(out, header, &background->data.image, nk_white);
  22532                 break;
  22533             case NK_STYLE_ITEM_NINE_SLICE:
  22534                 nk_draw_nine_slice(out, header, &background->data.slice, nk_white);
  22535                 break;
  22536             case NK_STYLE_ITEM_COLOR:
  22537                 nk_fill_rect(out, header, 0, style->tab.border_color);
  22538                 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
  22539                     style->tab.rounding, background->data.color);
  22540                 break;
  22541         }
  22542     }
  22543 
  22544     in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
  22545     in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
  22546 
  22547     /* select correct button style */
  22548     if (*state == NK_MAXIMIZED) {
  22549         symbol = style->tab.sym_maximize;
  22550         if (type == NK_TREE_TAB)
  22551             button = &style->tab.tab_maximize_button;
  22552         else button = &style->tab.node_maximize_button;
  22553     } else {
  22554         symbol = style->tab.sym_minimize;
  22555         if (type == NK_TREE_TAB)
  22556             button = &style->tab.tab_minimize_button;
  22557         else button = &style->tab.node_minimize_button;
  22558     }
  22559     {/* draw triangle button */
  22560     sym.w = sym.h = style->font->height;
  22561     sym.y = header.y + style->tab.padding.y;
  22562     sym.x = header.x + style->tab.padding.x;
  22563     if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font))
  22564         *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;}
  22565 
  22566     /* draw label */
  22567     {nk_flags dummy = 0;
  22568     struct nk_rect label;
  22569     /* calculate size of the text and tooltip */
  22570     text_len = nk_strlen(title);
  22571     text_width = style->font->width(style->font->userdata, style->font->height, title, text_len);
  22572     text_width += (4 * padding.x);
  22573 
  22574     header.w = NK_MAX(header.w, sym.w + item_spacing.x);
  22575     label.x = sym.x + sym.w + item_spacing.x;
  22576     label.y = sym.y;
  22577     label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width);
  22578     label.h = style->font->height;
  22579 
  22580     if (img) {
  22581         nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
  22582             selected, img, &style->selectable, in, style->font);
  22583     } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
  22584             selected, &style->selectable, in, style->font);
  22585     }
  22586     /* increase x-axis cursor widget position pointer */
  22587     if (*state == NK_MAXIMIZED) {
  22588         layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
  22589         layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
  22590         layout->bounds.w -= (style->tab.indent + style->window.padding.x);
  22591         layout->row.tree_depth++;
  22592         return nk_true;
  22593     } else return nk_false;
  22594 }
  22595 NK_INTERN int
  22596 nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type,
  22597     struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
  22598     nk_bool *selected, const char *hash, int len, int line)
  22599 {
  22600     struct nk_window *win = ctx->current;
  22601     int title_len = 0;
  22602     nk_hash tree_hash = 0;
  22603     nk_uint *state = 0;
  22604 
  22605     /* retrieve tree state from internal widget state tables */
  22606     if (!hash) {
  22607         title_len = (int)nk_strlen(title);
  22608         tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
  22609     } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
  22610     state = nk_find_value(win, tree_hash);
  22611     if (!state) {
  22612         state = nk_add_value(ctx, win, tree_hash, 0);
  22613         *state = initial_state;
  22614     } return nk_tree_element_image_push_hashed_base(ctx, type, img, title,
  22615         nk_strlen(title), (enum nk_collapse_states*)state, selected);
  22616 }
  22617 NK_API nk_bool
  22618 nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
  22619     const char *title, enum nk_collapse_states initial_state,
  22620     nk_bool *selected, const char *hash, int len, int seed)
  22621 {
  22622     return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed);
  22623 }
  22624 NK_API nk_bool
  22625 nk_tree_element_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
  22626     struct nk_image img, const char *title, enum nk_collapse_states initial_state,
  22627     nk_bool *selected, const char *hash, int len,int seed)
  22628 {
  22629     return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed);
  22630 }
  22631 NK_API void
  22632 nk_tree_element_pop(struct nk_context *ctx)
  22633 {
  22634     nk_tree_state_pop(ctx);
  22635 }
  22636 
  22637 
  22638 
  22639 
  22640 
  22641 /* ===============================================================
  22642  *
  22643  *                          GROUP
  22644  *
  22645  * ===============================================================*/
  22646 NK_API nk_bool
  22647 nk_group_scrolled_offset_begin(struct nk_context *ctx,
  22648     nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
  22649 {
  22650     struct nk_rect bounds;
  22651     struct nk_window panel;
  22652     struct nk_window *win;
  22653 
  22654     win = ctx->current;
  22655     nk_panel_alloc_space(&bounds, ctx);
  22656     {const struct nk_rect *c = &win->layout->clip;
  22657     if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
  22658         !(flags & NK_WINDOW_MOVABLE)) {
  22659         return 0;
  22660     }}
  22661     if (win->flags & NK_WINDOW_ROM)
  22662         flags |= NK_WINDOW_ROM;
  22663 
  22664     /* initialize a fake window to create the panel from */
  22665     nk_zero(&panel, sizeof(panel));
  22666     panel.bounds = bounds;
  22667     panel.flags = flags;
  22668     panel.scrollbar.x = *x_offset;
  22669     panel.scrollbar.y = *y_offset;
  22670     panel.buffer = win->buffer;
  22671     panel.layout = (struct nk_panel*)nk_create_panel(ctx);
  22672     ctx->current = &panel;
  22673     nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
  22674 
  22675     win->buffer = panel.buffer;
  22676     win->buffer.clip = panel.layout->clip;
  22677     panel.layout->offset_x = x_offset;
  22678     panel.layout->offset_y = y_offset;
  22679     panel.layout->parent = win->layout;
  22680     win->layout = panel.layout;
  22681 
  22682     ctx->current = win;
  22683     if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
  22684         (panel.layout->flags & NK_WINDOW_MINIMIZED))
  22685     {
  22686         nk_flags f = panel.layout->flags;
  22687         nk_group_scrolled_end(ctx);
  22688         if (f & NK_WINDOW_CLOSED)
  22689             return NK_WINDOW_CLOSED;
  22690         if (f & NK_WINDOW_MINIMIZED)
  22691             return NK_WINDOW_MINIMIZED;
  22692     }
  22693     return 1;
  22694 }
  22695 NK_API void
  22696 nk_group_scrolled_end(struct nk_context *ctx)
  22697 {
  22698     struct nk_window *win;
  22699     struct nk_panel *parent;
  22700     struct nk_panel *g;
  22701 
  22702     struct nk_rect clip;
  22703     struct nk_window pan;
  22704     struct nk_vec2 panel_padding;
  22705 
  22706     NK_ASSERT(ctx);
  22707     NK_ASSERT(ctx->current);
  22708     if (!ctx || !ctx->current)
  22709         return;
  22710 
  22711     /* make sure nk_group_begin was called correctly */
  22712     NK_ASSERT(ctx->current);
  22713     win = ctx->current;
  22714     NK_ASSERT(win->layout);
  22715     g = win->layout;
  22716     NK_ASSERT(g->parent);
  22717     parent = g->parent;
  22718 
  22719     /* dummy window */
  22720     nk_zero_struct(pan);
  22721     panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
  22722     pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
  22723     pan.bounds.x = g->bounds.x - panel_padding.x;
  22724     pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
  22725     pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
  22726     if (g->flags & NK_WINDOW_BORDER) {
  22727         pan.bounds.x -= g->border;
  22728         pan.bounds.y -= g->border;
  22729         pan.bounds.w += 2*g->border;
  22730         pan.bounds.h += 2*g->border;
  22731     }
  22732     if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
  22733         pan.bounds.w += ctx->style.window.scrollbar_size.x;
  22734         pan.bounds.h += ctx->style.window.scrollbar_size.y;
  22735     }
  22736     pan.scrollbar.x = *g->offset_x;
  22737     pan.scrollbar.y = *g->offset_y;
  22738     pan.flags = g->flags;
  22739     pan.buffer = win->buffer;
  22740     pan.layout = g;
  22741     pan.parent = win;
  22742     ctx->current = &pan;
  22743 
  22744     /* make sure group has correct clipping rectangle */
  22745     nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
  22746         pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
  22747     nk_push_scissor(&pan.buffer, clip);
  22748     nk_end(ctx);
  22749 
  22750     win->buffer = pan.buffer;
  22751     nk_push_scissor(&win->buffer, parent->clip);
  22752     ctx->current = win;
  22753     win->layout = parent;
  22754     g->bounds = pan.bounds;
  22755     return;
  22756 }
  22757 NK_API nk_bool
  22758 nk_group_scrolled_begin(struct nk_context *ctx,
  22759     struct nk_scroll *scroll, const char *title, nk_flags flags)
  22760 {
  22761     return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);
  22762 }
  22763 NK_API nk_bool
  22764 nk_group_begin_titled(struct nk_context *ctx, const char *id,
  22765     const char *title, nk_flags flags)
  22766 {
  22767     int id_len;
  22768     nk_hash id_hash;
  22769     struct nk_window *win;
  22770     nk_uint *x_offset;
  22771     nk_uint *y_offset;
  22772 
  22773     NK_ASSERT(ctx);
  22774     NK_ASSERT(id);
  22775     NK_ASSERT(ctx->current);
  22776     NK_ASSERT(ctx->current->layout);
  22777     if (!ctx || !ctx->current || !ctx->current->layout || !id)
  22778         return 0;
  22779 
  22780     /* find persistent group scrollbar value */
  22781     win = ctx->current;
  22782     id_len = (int)nk_strlen(id);
  22783     id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
  22784     x_offset = nk_find_value(win, id_hash);
  22785     if (!x_offset) {
  22786         x_offset = nk_add_value(ctx, win, id_hash, 0);
  22787         y_offset = nk_add_value(ctx, win, id_hash+1, 0);
  22788 
  22789         NK_ASSERT(x_offset);
  22790         NK_ASSERT(y_offset);
  22791         if (!x_offset || !y_offset) return 0;
  22792         *x_offset = *y_offset = 0;
  22793     } else y_offset = nk_find_value(win, id_hash+1);
  22794     return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
  22795 }
  22796 NK_API nk_bool
  22797 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
  22798 {
  22799     return nk_group_begin_titled(ctx, title, title, flags);
  22800 }
  22801 NK_API void
  22802 nk_group_end(struct nk_context *ctx)
  22803 {
  22804     nk_group_scrolled_end(ctx);
  22805 }
  22806 NK_API void
  22807 nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset)
  22808 {
  22809     int id_len;
  22810     nk_hash id_hash;
  22811     struct nk_window *win;
  22812     nk_uint *x_offset_ptr;
  22813     nk_uint *y_offset_ptr;
  22814 
  22815     NK_ASSERT(ctx);
  22816     NK_ASSERT(id);
  22817     NK_ASSERT(ctx->current);
  22818     NK_ASSERT(ctx->current->layout);
  22819     if (!ctx || !ctx->current || !ctx->current->layout || !id)
  22820         return;
  22821 
  22822     /* find persistent group scrollbar value */
  22823     win = ctx->current;
  22824     id_len = (int)nk_strlen(id);
  22825     id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
  22826     x_offset_ptr = nk_find_value(win, id_hash);
  22827     if (!x_offset_ptr) {
  22828         x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
  22829         y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
  22830 
  22831         NK_ASSERT(x_offset_ptr);
  22832         NK_ASSERT(y_offset_ptr);
  22833         if (!x_offset_ptr || !y_offset_ptr) return;
  22834         *x_offset_ptr = *y_offset_ptr = 0;
  22835     } else y_offset_ptr = nk_find_value(win, id_hash+1);
  22836     if (x_offset)
  22837       *x_offset = *x_offset_ptr;
  22838     if (y_offset)
  22839       *y_offset = *y_offset_ptr;
  22840 }
  22841 NK_API void
  22842 nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset)
  22843 {
  22844     int id_len;
  22845     nk_hash id_hash;
  22846     struct nk_window *win;
  22847     nk_uint *x_offset_ptr;
  22848     nk_uint *y_offset_ptr;
  22849 
  22850     NK_ASSERT(ctx);
  22851     NK_ASSERT(id);
  22852     NK_ASSERT(ctx->current);
  22853     NK_ASSERT(ctx->current->layout);
  22854     if (!ctx || !ctx->current || !ctx->current->layout || !id)
  22855         return;
  22856 
  22857     /* find persistent group scrollbar value */
  22858     win = ctx->current;
  22859     id_len = (int)nk_strlen(id);
  22860     id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
  22861     x_offset_ptr = nk_find_value(win, id_hash);
  22862     if (!x_offset_ptr) {
  22863         x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
  22864         y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
  22865 
  22866         NK_ASSERT(x_offset_ptr);
  22867         NK_ASSERT(y_offset_ptr);
  22868         if (!x_offset_ptr || !y_offset_ptr) return;
  22869         *x_offset_ptr = *y_offset_ptr = 0;
  22870     } else y_offset_ptr = nk_find_value(win, id_hash+1);
  22871     *x_offset_ptr = x_offset;
  22872     *y_offset_ptr = y_offset;
  22873 }
  22874 
  22875 
  22876 
  22877 
  22878 /* ===============================================================
  22879  *
  22880  *                          LIST VIEW
  22881  *
  22882  * ===============================================================*/
  22883 NK_API nk_bool
  22884 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
  22885     const char *title, nk_flags flags, int row_height, int row_count)
  22886 {
  22887     int title_len;
  22888     nk_hash title_hash;
  22889     nk_uint *x_offset;
  22890     nk_uint *y_offset;
  22891 
  22892     int result;
  22893     struct nk_window *win;
  22894     struct nk_panel *layout;
  22895     const struct nk_style *style;
  22896     struct nk_vec2 item_spacing;
  22897 
  22898     NK_ASSERT(ctx);
  22899     NK_ASSERT(view);
  22900     NK_ASSERT(title);
  22901     if (!ctx || !view || !title) return 0;
  22902 
  22903     win = ctx->current;
  22904     style = &ctx->style;
  22905     item_spacing = style->window.spacing;
  22906     row_height += NK_MAX(0, (int)item_spacing.y);
  22907 
  22908     /* find persistent list view scrollbar offset */
  22909     title_len = (int)nk_strlen(title);
  22910     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
  22911     x_offset = nk_find_value(win, title_hash);
  22912     if (!x_offset) {
  22913         x_offset = nk_add_value(ctx, win, title_hash, 0);
  22914         y_offset = nk_add_value(ctx, win, title_hash+1, 0);
  22915 
  22916         NK_ASSERT(x_offset);
  22917         NK_ASSERT(y_offset);
  22918         if (!x_offset || !y_offset) return 0;
  22919         *x_offset = *y_offset = 0;
  22920     } else y_offset = nk_find_value(win, title_hash+1);
  22921     view->scroll_value = *y_offset;
  22922     view->scroll_pointer = y_offset;
  22923 
  22924     *y_offset = 0;
  22925     result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
  22926     win = ctx->current;
  22927     layout = win->layout;
  22928 
  22929     view->total_height = row_height * NK_MAX(row_count,1);
  22930     view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
  22931     view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0);
  22932     view->count = NK_MIN(view->count, row_count - view->begin);
  22933     view->end = view->begin + view->count;
  22934     view->ctx = ctx;
  22935     return result;
  22936 }
  22937 NK_API void
  22938 nk_list_view_end(struct nk_list_view *view)
  22939 {
  22940     struct nk_context *ctx;
  22941     struct nk_window *win;
  22942     struct nk_panel *layout;
  22943 
  22944     NK_ASSERT(view);
  22945     NK_ASSERT(view->ctx);
  22946     NK_ASSERT(view->scroll_pointer);
  22947     if (!view || !view->ctx) return;
  22948 
  22949     ctx = view->ctx;
  22950     win = ctx->current;
  22951     layout = win->layout;
  22952     layout->at_y = layout->bounds.y + (float)view->total_height;
  22953     *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
  22954     nk_group_end(view->ctx);
  22955 }
  22956 
  22957 
  22958 
  22959 
  22960 
  22961 /* ===============================================================
  22962  *
  22963  *                              WIDGET
  22964  *
  22965  * ===============================================================*/
  22966 NK_API struct nk_rect
  22967 nk_widget_bounds(struct nk_context *ctx)
  22968 {
  22969     struct nk_rect bounds;
  22970     NK_ASSERT(ctx);
  22971     NK_ASSERT(ctx->current);
  22972     if (!ctx || !ctx->current)
  22973         return nk_rect(0,0,0,0);
  22974     nk_layout_peek(&bounds, ctx);
  22975     return bounds;
  22976 }
  22977 NK_API struct nk_vec2
  22978 nk_widget_position(struct nk_context *ctx)
  22979 {
  22980     struct nk_rect bounds;
  22981     NK_ASSERT(ctx);
  22982     NK_ASSERT(ctx->current);
  22983     if (!ctx || !ctx->current)
  22984         return nk_vec2(0,0);
  22985 
  22986     nk_layout_peek(&bounds, ctx);
  22987     return nk_vec2(bounds.x, bounds.y);
  22988 }
  22989 NK_API struct nk_vec2
  22990 nk_widget_size(struct nk_context *ctx)
  22991 {
  22992     struct nk_rect bounds;
  22993     NK_ASSERT(ctx);
  22994     NK_ASSERT(ctx->current);
  22995     if (!ctx || !ctx->current)
  22996         return nk_vec2(0,0);
  22997 
  22998     nk_layout_peek(&bounds, ctx);
  22999     return nk_vec2(bounds.w, bounds.h);
  23000 }
  23001 NK_API float
  23002 nk_widget_width(struct nk_context *ctx)
  23003 {
  23004     struct nk_rect bounds;
  23005     NK_ASSERT(ctx);
  23006     NK_ASSERT(ctx->current);
  23007     if (!ctx || !ctx->current)
  23008         return 0;
  23009 
  23010     nk_layout_peek(&bounds, ctx);
  23011     return bounds.w;
  23012 }
  23013 NK_API float
  23014 nk_widget_height(struct nk_context *ctx)
  23015 {
  23016     struct nk_rect bounds;
  23017     NK_ASSERT(ctx);
  23018     NK_ASSERT(ctx->current);
  23019     if (!ctx || !ctx->current)
  23020         return 0;
  23021 
  23022     nk_layout_peek(&bounds, ctx);
  23023     return bounds.h;
  23024 }
  23025 NK_API nk_bool
  23026 nk_widget_is_hovered(struct nk_context *ctx)
  23027 {
  23028     struct nk_rect c, v;
  23029     struct nk_rect bounds;
  23030     NK_ASSERT(ctx);
  23031     NK_ASSERT(ctx->current);
  23032     if (!ctx || !ctx->current || ctx->active != ctx->current)
  23033         return 0;
  23034 
  23035     c = ctx->current->layout->clip;
  23036     c.x = (float)((int)c.x);
  23037     c.y = (float)((int)c.y);
  23038     c.w = (float)((int)c.w);
  23039     c.h = (float)((int)c.h);
  23040 
  23041     nk_layout_peek(&bounds, ctx);
  23042     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
  23043     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
  23044         return 0;
  23045     return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
  23046 }
  23047 NK_API nk_bool
  23048 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
  23049 {
  23050     struct nk_rect c, v;
  23051     struct nk_rect bounds;
  23052     NK_ASSERT(ctx);
  23053     NK_ASSERT(ctx->current);
  23054     if (!ctx || !ctx->current || ctx->active != ctx->current)
  23055         return 0;
  23056 
  23057     c = ctx->current->layout->clip;
  23058     c.x = (float)((int)c.x);
  23059     c.y = (float)((int)c.y);
  23060     c.w = (float)((int)c.w);
  23061     c.h = (float)((int)c.h);
  23062 
  23063     nk_layout_peek(&bounds, ctx);
  23064     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
  23065     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
  23066         return 0;
  23067     return nk_input_mouse_clicked(&ctx->input, btn, bounds);
  23068 }
  23069 NK_API nk_bool
  23070 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, nk_bool down)
  23071 {
  23072     struct nk_rect c, v;
  23073     struct nk_rect bounds;
  23074     NK_ASSERT(ctx);
  23075     NK_ASSERT(ctx->current);
  23076     if (!ctx || !ctx->current || ctx->active != ctx->current)
  23077         return 0;
  23078 
  23079     c = ctx->current->layout->clip;
  23080     c.x = (float)((int)c.x);
  23081     c.y = (float)((int)c.y);
  23082     c.w = (float)((int)c.w);
  23083     c.h = (float)((int)c.h);
  23084 
  23085     nk_layout_peek(&bounds, ctx);
  23086     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
  23087     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
  23088         return 0;
  23089     return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
  23090 }
  23091 NK_API enum nk_widget_layout_states
  23092 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
  23093 {
  23094     struct nk_rect c, v;
  23095     struct nk_window *win;
  23096     struct nk_panel *layout;
  23097     const struct nk_input *in;
  23098 
  23099     NK_ASSERT(ctx);
  23100     NK_ASSERT(ctx->current);
  23101     NK_ASSERT(ctx->current->layout);
  23102     if (!ctx || !ctx->current || !ctx->current->layout)
  23103         return NK_WIDGET_INVALID;
  23104 
  23105     /* allocate space and check if the widget needs to be updated and drawn */
  23106     nk_panel_alloc_space(bounds, ctx);
  23107     win = ctx->current;
  23108     layout = win->layout;
  23109     in = &ctx->input;
  23110     c = layout->clip;
  23111 
  23112     /*  if one of these triggers you forgot to add an `if` condition around either
  23113         a window, group, popup, combobox or contextual menu `begin` and `end` block.
  23114         Example:
  23115             if (nk_begin(...) {...} nk_end(...); or
  23116             if (nk_group_begin(...) { nk_group_end(...);} */
  23117     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
  23118     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
  23119     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
  23120 
  23121     /* need to convert to int here to remove floating point errors */
  23122     bounds->x = (float)((int)bounds->x);
  23123     bounds->y = (float)((int)bounds->y);
  23124     bounds->w = (float)((int)bounds->w);
  23125     bounds->h = (float)((int)bounds->h);
  23126 
  23127     c.x = (float)((int)c.x);
  23128     c.y = (float)((int)c.y);
  23129     c.w = (float)((int)c.w);
  23130     c.h = (float)((int)c.h);
  23131 
  23132     nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
  23133     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
  23134         return NK_WIDGET_INVALID;
  23135     if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
  23136         return NK_WIDGET_ROM;
  23137     return NK_WIDGET_VALID;
  23138 }
  23139 NK_API enum nk_widget_layout_states
  23140 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
  23141     struct nk_vec2 item_padding)
  23142 {
  23143     /* update the bounds to stand without padding  */
  23144     enum nk_widget_layout_states state;
  23145     NK_UNUSED(item_padding);
  23146 
  23147     NK_ASSERT(ctx);
  23148     NK_ASSERT(ctx->current);
  23149     NK_ASSERT(ctx->current->layout);
  23150     if (!ctx || !ctx->current || !ctx->current->layout)
  23151         return NK_WIDGET_INVALID;
  23152 
  23153     state = nk_widget(bounds, ctx);
  23154     return state;
  23155 }
  23156 NK_API void
  23157 nk_spacing(struct nk_context *ctx, int cols)
  23158 {
  23159     struct nk_window *win;
  23160     struct nk_panel *layout;
  23161     struct nk_rect none;
  23162     int i, index, rows;
  23163 
  23164     NK_ASSERT(ctx);
  23165     NK_ASSERT(ctx->current);
  23166     NK_ASSERT(ctx->current->layout);
  23167     if (!ctx || !ctx->current || !ctx->current->layout)
  23168         return;
  23169 
  23170     /* spacing over row boundaries */
  23171     win = ctx->current;
  23172     layout = win->layout;
  23173     index = (layout->row.index + cols) % layout->row.columns;
  23174     rows = (layout->row.index + cols) / layout->row.columns;
  23175     if (rows) {
  23176         for (i = 0; i < rows; ++i)
  23177             nk_panel_alloc_row(ctx, win);
  23178         cols = index;
  23179     }
  23180     /* non table layout need to allocate space */
  23181     if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
  23182         layout->row.type != NK_LAYOUT_STATIC_FIXED) {
  23183         for (i = 0; i < cols; ++i)
  23184             nk_panel_alloc_space(&none, ctx);
  23185     } layout->row.index = index;
  23186 }
  23187 
  23188 
  23189 
  23190 
  23191 
  23192 /* ===============================================================
  23193  *
  23194  *                              TEXT
  23195  *
  23196  * ===============================================================*/
  23197 NK_LIB void
  23198 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
  23199     const char *string, int len, const struct nk_text *t,
  23200     nk_flags a, const struct nk_user_font *f)
  23201 {
  23202     struct nk_rect label;
  23203     float text_width;
  23204 
  23205     NK_ASSERT(o);
  23206     NK_ASSERT(t);
  23207     if (!o || !t) return;
  23208 
  23209     b.h = NK_MAX(b.h, 2 * t->padding.y);
  23210     label.x = 0; label.w = 0;
  23211     label.y = b.y + t->padding.y;
  23212     label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
  23213 
  23214     text_width = f->width(f->userdata, f->height, (const char*)string, len);
  23215     text_width += (2.0f * t->padding.x);
  23216 
  23217     /* align in x-axis */
  23218     if (a & NK_TEXT_ALIGN_LEFT) {
  23219         label.x = b.x + t->padding.x;
  23220         label.w = NK_MAX(0, b.w - 2 * t->padding.x);
  23221     } else if (a & NK_TEXT_ALIGN_CENTERED) {
  23222         label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
  23223         label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
  23224         label.x = NK_MAX(b.x + t->padding.x, label.x);
  23225         label.w = NK_MIN(b.x + b.w, label.x + label.w);
  23226         if (label.w >= label.x) label.w -= label.x;
  23227     } else if (a & NK_TEXT_ALIGN_RIGHT) {
  23228         label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
  23229         label.w = (float)text_width + 2 * t->padding.x;
  23230     } else return;
  23231 
  23232     /* align in y-axis */
  23233     if (a & NK_TEXT_ALIGN_MIDDLE) {
  23234         label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
  23235         label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
  23236     } else if (a & NK_TEXT_ALIGN_BOTTOM) {
  23237         label.y = b.y + b.h - f->height;
  23238         label.h = f->height;
  23239     }
  23240     nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text);
  23241 }
  23242 NK_LIB void
  23243 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
  23244     const char *string, int len, const struct nk_text *t,
  23245     const struct nk_user_font *f)
  23246 {
  23247     float width;
  23248     int glyphs = 0;
  23249     int fitting = 0;
  23250     int done = 0;
  23251     struct nk_rect line;
  23252     struct nk_text text;
  23253     NK_INTERN nk_rune seperator[] = {' '};
  23254 
  23255     NK_ASSERT(o);
  23256     NK_ASSERT(t);
  23257     if (!o || !t) return;
  23258 
  23259     text.padding = nk_vec2(0,0);
  23260     text.background = t->background;
  23261     text.text = t->text;
  23262 
  23263     b.w = NK_MAX(b.w, 2 * t->padding.x);
  23264     b.h = NK_MAX(b.h, 2 * t->padding.y);
  23265     b.h = b.h - 2 * t->padding.y;
  23266 
  23267     line.x = b.x + t->padding.x;
  23268     line.y = b.y + t->padding.y;
  23269     line.w = b.w - 2 * t->padding.x;
  23270     line.h = 2 * t->padding.y + f->height;
  23271 
  23272     fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
  23273     while (done < len) {
  23274         if (!fitting || line.y + line.h >= (b.y + b.h)) break;
  23275         nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
  23276         done += fitting;
  23277         line.y += f->height + 2 * t->padding.y;
  23278         fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
  23279     }
  23280 }
  23281 NK_API void
  23282 nk_text_colored(struct nk_context *ctx, const char *str, int len,
  23283     nk_flags alignment, struct nk_color color)
  23284 {
  23285     struct nk_window *win;
  23286     const struct nk_style *style;
  23287 
  23288     struct nk_vec2 item_padding;
  23289     struct nk_rect bounds;
  23290     struct nk_text text;
  23291 
  23292     NK_ASSERT(ctx);
  23293     NK_ASSERT(ctx->current);
  23294     NK_ASSERT(ctx->current->layout);
  23295     if (!ctx || !ctx->current || !ctx->current->layout) return;
  23296 
  23297     win = ctx->current;
  23298     style = &ctx->style;
  23299     nk_panel_alloc_space(&bounds, ctx);
  23300     item_padding = style->text.padding;
  23301 
  23302     text.padding.x = item_padding.x;
  23303     text.padding.y = item_padding.y;
  23304     text.background = style->window.background;
  23305     text.text = color;
  23306     nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
  23307 }
  23308 NK_API void
  23309 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
  23310     int len, struct nk_color color)
  23311 {
  23312     struct nk_window *win;
  23313     const struct nk_style *style;
  23314 
  23315     struct nk_vec2 item_padding;
  23316     struct nk_rect bounds;
  23317     struct nk_text text;
  23318 
  23319     NK_ASSERT(ctx);
  23320     NK_ASSERT(ctx->current);
  23321     NK_ASSERT(ctx->current->layout);
  23322     if (!ctx || !ctx->current || !ctx->current->layout) return;
  23323 
  23324     win = ctx->current;
  23325     style = &ctx->style;
  23326     nk_panel_alloc_space(&bounds, ctx);
  23327     item_padding = style->text.padding;
  23328 
  23329     text.padding.x = item_padding.x;
  23330     text.padding.y = item_padding.y;
  23331     text.background = style->window.background;
  23332     text.text = color;
  23333     nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
  23334 }
  23335 #ifdef NK_INCLUDE_STANDARD_VARARGS
  23336 NK_API void
  23337 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
  23338     struct nk_color color, const char *fmt, ...)
  23339 {
  23340     va_list args;
  23341     va_start(args, fmt);
  23342     nk_labelfv_colored(ctx, flags, color, fmt, args);
  23343     va_end(args);
  23344 }
  23345 NK_API void
  23346 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
  23347     const char *fmt, ...)
  23348 {
  23349     va_list args;
  23350     va_start(args, fmt);
  23351     nk_labelfv_colored_wrap(ctx, color, fmt, args);
  23352     va_end(args);
  23353 }
  23354 NK_API void
  23355 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
  23356 {
  23357     va_list args;
  23358     va_start(args, fmt);
  23359     nk_labelfv(ctx, flags, fmt, args);
  23360     va_end(args);
  23361 }
  23362 NK_API void
  23363 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
  23364 {
  23365     va_list args;
  23366     va_start(args, fmt);
  23367     nk_labelfv_wrap(ctx, fmt, args);
  23368     va_end(args);
  23369 }
  23370 NK_API void
  23371 nk_labelfv_colored(struct nk_context *ctx, nk_flags flags,
  23372     struct nk_color color, const char *fmt, va_list args)
  23373 {
  23374     char buf[256];
  23375     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  23376     nk_label_colored(ctx, buf, flags, color);
  23377 }
  23378 
  23379 NK_API void
  23380 nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color,
  23381     const char *fmt, va_list args)
  23382 {
  23383     char buf[256];
  23384     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  23385     nk_label_colored_wrap(ctx, buf, color);
  23386 }
  23387 
  23388 NK_API void
  23389 nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args)
  23390 {
  23391     char buf[256];
  23392     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  23393     nk_label(ctx, buf, flags);
  23394 }
  23395 
  23396 NK_API void
  23397 nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args)
  23398 {
  23399     char buf[256];
  23400     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  23401     nk_label_wrap(ctx, buf);
  23402 }
  23403 
  23404 NK_API void
  23405 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
  23406 {
  23407     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));
  23408 }
  23409 NK_API void
  23410 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
  23411 {
  23412     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);
  23413 }
  23414 NK_API void
  23415 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
  23416 {
  23417     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);
  23418 }
  23419 NK_API void
  23420 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
  23421 {
  23422     double double_value = (double)value;
  23423     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
  23424 }
  23425 NK_API void
  23426 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
  23427 {
  23428     nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);
  23429 }
  23430 NK_API void
  23431 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
  23432 {
  23433     double c[4]; nk_color_dv(c, color);
  23434     nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
  23435         p, c[0], c[1], c[2], c[3]);
  23436 }
  23437 NK_API void
  23438 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
  23439 {
  23440     char hex[16];
  23441     nk_color_hex_rgba(hex, color);
  23442     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
  23443 }
  23444 #endif
  23445 NK_API void
  23446 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
  23447 {
  23448     NK_ASSERT(ctx);
  23449     if (!ctx) return;
  23450     nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
  23451 }
  23452 NK_API void
  23453 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
  23454 {
  23455     NK_ASSERT(ctx);
  23456     if (!ctx) return;
  23457     nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
  23458 }
  23459 NK_API void
  23460 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
  23461 {
  23462     nk_text(ctx, str, nk_strlen(str), alignment);
  23463 }
  23464 NK_API void
  23465 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
  23466     struct nk_color color)
  23467 {
  23468     nk_text_colored(ctx, str, nk_strlen(str), align, color);
  23469 }
  23470 NK_API void
  23471 nk_label_wrap(struct nk_context *ctx, const char *str)
  23472 {
  23473     nk_text_wrap(ctx, str, nk_strlen(str));
  23474 }
  23475 NK_API void
  23476 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
  23477 {
  23478     nk_text_wrap_colored(ctx, str, nk_strlen(str), color);
  23479 }
  23480 
  23481 
  23482 
  23483 
  23484 
  23485 /* ===============================================================
  23486  *
  23487  *                          IMAGE
  23488  *
  23489  * ===============================================================*/
  23490 NK_API nk_handle
  23491 nk_handle_ptr(void *ptr)
  23492 {
  23493     nk_handle handle = {0};
  23494     handle.ptr = ptr;
  23495     return handle;
  23496 }
  23497 NK_API nk_handle
  23498 nk_handle_id(int id)
  23499 {
  23500     nk_handle handle;
  23501     nk_zero_struct(handle);
  23502     handle.id = id;
  23503     return handle;
  23504 }
  23505 NK_API struct nk_image
  23506 nk_subimage_ptr(void *ptr, nk_ushort w, nk_ushort h, struct nk_rect r)
  23507 {
  23508     struct nk_image s;
  23509     nk_zero(&s, sizeof(s));
  23510     s.handle.ptr = ptr;
  23511     s.w = w; s.h = h;
  23512     s.region[0] = (nk_ushort)r.x;
  23513     s.region[1] = (nk_ushort)r.y;
  23514     s.region[2] = (nk_ushort)r.w;
  23515     s.region[3] = (nk_ushort)r.h;
  23516     return s;
  23517 }
  23518 NK_API struct nk_image
  23519 nk_subimage_id(int id, nk_ushort w, nk_ushort h, struct nk_rect r)
  23520 {
  23521     struct nk_image s;
  23522     nk_zero(&s, sizeof(s));
  23523     s.handle.id = id;
  23524     s.w = w; s.h = h;
  23525     s.region[0] = (nk_ushort)r.x;
  23526     s.region[1] = (nk_ushort)r.y;
  23527     s.region[2] = (nk_ushort)r.w;
  23528     s.region[3] = (nk_ushort)r.h;
  23529     return s;
  23530 }
  23531 NK_API struct nk_image
  23532 nk_subimage_handle(nk_handle handle, nk_ushort w, nk_ushort h, struct nk_rect r)
  23533 {
  23534     struct nk_image s;
  23535     nk_zero(&s, sizeof(s));
  23536     s.handle = handle;
  23537     s.w = w; s.h = h;
  23538     s.region[0] = (nk_ushort)r.x;
  23539     s.region[1] = (nk_ushort)r.y;
  23540     s.region[2] = (nk_ushort)r.w;
  23541     s.region[3] = (nk_ushort)r.h;
  23542     return s;
  23543 }
  23544 NK_API struct nk_image
  23545 nk_image_handle(nk_handle handle)
  23546 {
  23547     struct nk_image s;
  23548     nk_zero(&s, sizeof(s));
  23549     s.handle = handle;
  23550     s.w = 0; s.h = 0;
  23551     s.region[0] = 0;
  23552     s.region[1] = 0;
  23553     s.region[2] = 0;
  23554     s.region[3] = 0;
  23555     return s;
  23556 }
  23557 NK_API struct nk_image
  23558 nk_image_ptr(void *ptr)
  23559 {
  23560     struct nk_image s;
  23561     nk_zero(&s, sizeof(s));
  23562     NK_ASSERT(ptr);
  23563     s.handle.ptr = ptr;
  23564     s.w = 0; s.h = 0;
  23565     s.region[0] = 0;
  23566     s.region[1] = 0;
  23567     s.region[2] = 0;
  23568     s.region[3] = 0;
  23569     return s;
  23570 }
  23571 NK_API struct nk_image
  23572 nk_image_id(int id)
  23573 {
  23574     struct nk_image s;
  23575     nk_zero(&s, sizeof(s));
  23576     s.handle.id = id;
  23577     s.w = 0; s.h = 0;
  23578     s.region[0] = 0;
  23579     s.region[1] = 0;
  23580     s.region[2] = 0;
  23581     s.region[3] = 0;
  23582     return s;
  23583 }
  23584 NK_API nk_bool
  23585 nk_image_is_subimage(const struct nk_image* img)
  23586 {
  23587     NK_ASSERT(img);
  23588     return !(img->w == 0 && img->h == 0);
  23589 }
  23590 NK_API void
  23591 nk_image(struct nk_context *ctx, struct nk_image img)
  23592 {
  23593     struct nk_window *win;
  23594     struct nk_rect bounds;
  23595 
  23596     NK_ASSERT(ctx);
  23597     NK_ASSERT(ctx->current);
  23598     NK_ASSERT(ctx->current->layout);
  23599     if (!ctx || !ctx->current || !ctx->current->layout) return;
  23600 
  23601     win = ctx->current;
  23602     if (!nk_widget(&bounds, ctx)) return;
  23603     nk_draw_image(&win->buffer, bounds, &img, nk_white);
  23604 }
  23605 NK_API void
  23606 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col)
  23607 {
  23608     struct nk_window *win;
  23609     struct nk_rect bounds;
  23610 
  23611     NK_ASSERT(ctx);
  23612     NK_ASSERT(ctx->current);
  23613     NK_ASSERT(ctx->current->layout);
  23614     if (!ctx || !ctx->current || !ctx->current->layout) return;
  23615 
  23616     win = ctx->current;
  23617     if (!nk_widget(&bounds, ctx)) return;
  23618     nk_draw_image(&win->buffer, bounds, &img, col);
  23619 }
  23620 
  23621 
  23622 
  23623 
  23624 
  23625 /* ===============================================================
  23626  *
  23627  *                          9-SLICE
  23628  *
  23629  * ===============================================================*/
  23630 NK_API struct nk_nine_slice
  23631 nk_sub9slice_ptr(void *ptr, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
  23632 {
  23633     struct nk_nine_slice s;
  23634     struct nk_image *i = &s.img;
  23635     nk_zero(&s, sizeof(s));
  23636     i->handle.ptr = ptr;
  23637     i->w = w; i->h = h;
  23638     i->region[0] = (nk_ushort)rgn.x;
  23639     i->region[1] = (nk_ushort)rgn.y;
  23640     i->region[2] = (nk_ushort)rgn.w;
  23641     i->region[3] = (nk_ushort)rgn.h;
  23642     s.l = l; s.t = t; s.r = r; s.b = b;
  23643     return s;
  23644 }
  23645 NK_API struct nk_nine_slice
  23646 nk_sub9slice_id(int id, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
  23647 {
  23648     struct nk_nine_slice s;
  23649     struct nk_image *i = &s.img;
  23650     nk_zero(&s, sizeof(s));
  23651     i->handle.id = id;
  23652     i->w = w; i->h = h;
  23653     i->region[0] = (nk_ushort)rgn.x;
  23654     i->region[1] = (nk_ushort)rgn.y;
  23655     i->region[2] = (nk_ushort)rgn.w;
  23656     i->region[3] = (nk_ushort)rgn.h;
  23657     s.l = l; s.t = t; s.r = r; s.b = b;
  23658     return s;
  23659 }
  23660 NK_API struct nk_nine_slice
  23661 nk_sub9slice_handle(nk_handle handle, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
  23662 {
  23663     struct nk_nine_slice s;
  23664     struct nk_image *i = &s.img;
  23665     nk_zero(&s, sizeof(s));
  23666     i->handle = handle;
  23667     i->w = w; i->h = h;
  23668     i->region[0] = (nk_ushort)rgn.x;
  23669     i->region[1] = (nk_ushort)rgn.y;
  23670     i->region[2] = (nk_ushort)rgn.w;
  23671     i->region[3] = (nk_ushort)rgn.h;
  23672     s.l = l; s.t = t; s.r = r; s.b = b;
  23673     return s;
  23674 }
  23675 NK_API struct nk_nine_slice
  23676 nk_nine_slice_handle(nk_handle handle, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
  23677 {
  23678     struct nk_nine_slice s;
  23679     struct nk_image *i = &s.img;
  23680     nk_zero(&s, sizeof(s));
  23681     i->handle = handle;
  23682     i->w = 0; i->h = 0;
  23683     i->region[0] = 0;
  23684     i->region[1] = 0;
  23685     i->region[2] = 0;
  23686     i->region[3] = 0;
  23687     s.l = l; s.t = t; s.r = r; s.b = b;
  23688     return s;
  23689 }
  23690 NK_API struct nk_nine_slice
  23691 nk_nine_slice_ptr(void *ptr, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
  23692 {
  23693     struct nk_nine_slice s;
  23694     struct nk_image *i = &s.img;
  23695     nk_zero(&s, sizeof(s));
  23696     NK_ASSERT(ptr);
  23697     i->handle.ptr = ptr;
  23698     i->w = 0; i->h = 0;
  23699     i->region[0] = 0;
  23700     i->region[1] = 0;
  23701     i->region[2] = 0;
  23702     i->region[3] = 0;
  23703     s.l = l; s.t = t; s.r = r; s.b = b;
  23704     return s;
  23705 }
  23706 NK_API struct nk_nine_slice
  23707 nk_nine_slice_id(int id, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
  23708 {
  23709     struct nk_nine_slice s;
  23710     struct nk_image *i = &s.img;
  23711     nk_zero(&s, sizeof(s));
  23712     i->handle.id = id;
  23713     i->w = 0; i->h = 0;
  23714     i->region[0] = 0;
  23715     i->region[1] = 0;
  23716     i->region[2] = 0;
  23717     i->region[3] = 0;
  23718     s.l = l; s.t = t; s.r = r; s.b = b;
  23719     return s;
  23720 }
  23721 NK_API int
  23722 nk_nine_slice_is_sub9slice(const struct nk_nine_slice* slice)
  23723 {
  23724     NK_ASSERT(slice);
  23725     return !(slice->img.w == 0 && slice->img.h == 0);
  23726 }
  23727 
  23728 
  23729 
  23730 
  23731 
  23732 /* ==============================================================
  23733  *
  23734  *                          BUTTON
  23735  *
  23736  * ===============================================================*/
  23737 NK_LIB void
  23738 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
  23739     struct nk_rect content, struct nk_color background, struct nk_color foreground,
  23740     float border_width, const struct nk_user_font *font)
  23741 {
  23742     switch (type) {
  23743     case NK_SYMBOL_X:
  23744     case NK_SYMBOL_UNDERSCORE:
  23745     case NK_SYMBOL_PLUS:
  23746     case NK_SYMBOL_MINUS: {
  23747         /* single character text symbol */
  23748         const char *X = (type == NK_SYMBOL_X) ? "x":
  23749             (type == NK_SYMBOL_UNDERSCORE) ? "_":
  23750             (type == NK_SYMBOL_PLUS) ? "+": "-";
  23751         struct nk_text text;
  23752         text.padding = nk_vec2(0,0);
  23753         text.background = background;
  23754         text.text = foreground;
  23755         nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
  23756     } break;
  23757     case NK_SYMBOL_CIRCLE_SOLID:
  23758     case NK_SYMBOL_CIRCLE_OUTLINE:
  23759     case NK_SYMBOL_RECT_SOLID:
  23760     case NK_SYMBOL_RECT_OUTLINE: {
  23761         /* simple empty/filled shapes */
  23762         if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
  23763             nk_fill_rect(out, content,  0, foreground);
  23764             if (type == NK_SYMBOL_RECT_OUTLINE)
  23765                 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
  23766         } else {
  23767             nk_fill_circle(out, content, foreground);
  23768             if (type == NK_SYMBOL_CIRCLE_OUTLINE)
  23769                 nk_fill_circle(out, nk_shrink_rect(content, 1), background);
  23770         }
  23771     } break;
  23772     case NK_SYMBOL_TRIANGLE_UP:
  23773     case NK_SYMBOL_TRIANGLE_DOWN:
  23774     case NK_SYMBOL_TRIANGLE_LEFT:
  23775     case NK_SYMBOL_TRIANGLE_RIGHT: {
  23776         enum nk_heading heading;
  23777         struct nk_vec2 points[3];
  23778         heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
  23779             (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
  23780             (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
  23781         nk_triangle_from_direction(points, content, 0, 0, heading);
  23782         nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
  23783             points[2].x, points[2].y, foreground);
  23784     } break;
  23785     default:
  23786     case NK_SYMBOL_NONE:
  23787     case NK_SYMBOL_MAX: break;
  23788     }
  23789 }
  23790 NK_LIB nk_bool
  23791 nk_button_behavior(nk_flags *state, struct nk_rect r,
  23792     const struct nk_input *i, enum nk_button_behavior behavior)
  23793 {
  23794     int ret = 0;
  23795     nk_widget_state_reset(state);
  23796     if (!i) return 0;
  23797     if (nk_input_is_mouse_hovering_rect(i, r)) {
  23798         *state = NK_WIDGET_STATE_HOVERED;
  23799         if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT))
  23800             *state = NK_WIDGET_STATE_ACTIVE;
  23801         if (nk_input_has_mouse_click_in_button_rect(i, NK_BUTTON_LEFT, r)) {
  23802             ret = (behavior != NK_BUTTON_DEFAULT) ?
  23803                 nk_input_is_mouse_down(i, NK_BUTTON_LEFT):
  23804 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
  23805                 nk_input_is_mouse_released(i, NK_BUTTON_LEFT);
  23806 #else
  23807                 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT);
  23808 #endif
  23809         }
  23810     }
  23811     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r))
  23812         *state |= NK_WIDGET_STATE_ENTERED;
  23813     else if (nk_input_is_mouse_prev_hovering_rect(i, r))
  23814         *state |= NK_WIDGET_STATE_LEFT;
  23815     return ret;
  23816 }
  23817 NK_LIB const struct nk_style_item*
  23818 nk_draw_button(struct nk_command_buffer *out,
  23819     const struct nk_rect *bounds, nk_flags state,
  23820     const struct nk_style_button *style)
  23821 {
  23822     const struct nk_style_item *background;
  23823     if (state & NK_WIDGET_STATE_HOVER)
  23824         background = &style->hover;
  23825     else if (state & NK_WIDGET_STATE_ACTIVED)
  23826         background = &style->active;
  23827     else background = &style->normal;
  23828 
  23829     switch(background->type) {
  23830         case NK_STYLE_ITEM_IMAGE:
  23831             nk_draw_image(out, *bounds, &background->data.image, nk_white);
  23832             break;
  23833         case NK_STYLE_ITEM_NINE_SLICE:
  23834             nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white);
  23835             break;
  23836         case NK_STYLE_ITEM_COLOR:
  23837             nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  23838             nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
  23839             break;
  23840     }
  23841     return background;
  23842 }
  23843 NK_LIB nk_bool
  23844 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
  23845     const struct nk_style_button *style, const struct nk_input *in,
  23846     enum nk_button_behavior behavior, struct nk_rect *content)
  23847 {
  23848     struct nk_rect bounds;
  23849     NK_ASSERT(style);
  23850     NK_ASSERT(state);
  23851     NK_ASSERT(out);
  23852     if (!out || !style)
  23853         return nk_false;
  23854 
  23855     /* calculate button content space */
  23856     content->x = r.x + style->padding.x + style->border + style->rounding;
  23857     content->y = r.y + style->padding.y + style->border + style->rounding;
  23858     content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
  23859     content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
  23860 
  23861     /* execute button behavior */
  23862     bounds.x = r.x - style->touch_padding.x;
  23863     bounds.y = r.y - style->touch_padding.y;
  23864     bounds.w = r.w + 2 * style->touch_padding.x;
  23865     bounds.h = r.h + 2 * style->touch_padding.y;
  23866     return nk_button_behavior(state, bounds, in, behavior);
  23867 }
  23868 NK_LIB void
  23869 nk_draw_button_text(struct nk_command_buffer *out,
  23870     const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
  23871     const struct nk_style_button *style, const char *txt, int len,
  23872     nk_flags text_alignment, const struct nk_user_font *font)
  23873 {
  23874     struct nk_text text;
  23875     const struct nk_style_item *background;
  23876     background = nk_draw_button(out, bounds, state, style);
  23877 
  23878     /* select correct colors/images */
  23879     if (background->type == NK_STYLE_ITEM_COLOR)
  23880         text.background = background->data.color;
  23881     else text.background = style->text_background;
  23882     if (state & NK_WIDGET_STATE_HOVER)
  23883         text.text = style->text_hover;
  23884     else if (state & NK_WIDGET_STATE_ACTIVED)
  23885         text.text = style->text_active;
  23886     else text.text = style->text_normal;
  23887 
  23888     text.padding = nk_vec2(0,0);
  23889     nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
  23890 }
  23891 NK_LIB nk_bool
  23892 nk_do_button_text(nk_flags *state,
  23893     struct nk_command_buffer *out, struct nk_rect bounds,
  23894     const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
  23895     const struct nk_style_button *style, const struct nk_input *in,
  23896     const struct nk_user_font *font)
  23897 {
  23898     struct nk_rect content;
  23899     int ret = nk_false;
  23900 
  23901     NK_ASSERT(state);
  23902     NK_ASSERT(style);
  23903     NK_ASSERT(out);
  23904     NK_ASSERT(string);
  23905     NK_ASSERT(font);
  23906     if (!out || !style || !font || !string)
  23907         return nk_false;
  23908 
  23909     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
  23910     if (style->draw_begin) style->draw_begin(out, style->userdata);
  23911     nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
  23912     if (style->draw_end) style->draw_end(out, style->userdata);
  23913     return ret;
  23914 }
  23915 NK_LIB void
  23916 nk_draw_button_symbol(struct nk_command_buffer *out,
  23917     const struct nk_rect *bounds, const struct nk_rect *content,
  23918     nk_flags state, const struct nk_style_button *style,
  23919     enum nk_symbol_type type, const struct nk_user_font *font)
  23920 {
  23921     struct nk_color sym, bg;
  23922     const struct nk_style_item *background;
  23923 
  23924     /* select correct colors/images */
  23925     background = nk_draw_button(out, bounds, state, style);
  23926     if (background->type == NK_STYLE_ITEM_COLOR)
  23927         bg = background->data.color;
  23928     else bg = style->text_background;
  23929 
  23930     if (state & NK_WIDGET_STATE_HOVER)
  23931         sym = style->text_hover;
  23932     else if (state & NK_WIDGET_STATE_ACTIVED)
  23933         sym = style->text_active;
  23934     else sym = style->text_normal;
  23935     nk_draw_symbol(out, type, *content, bg, sym, 1, font);
  23936 }
  23937 NK_LIB nk_bool
  23938 nk_do_button_symbol(nk_flags *state,
  23939     struct nk_command_buffer *out, struct nk_rect bounds,
  23940     enum nk_symbol_type symbol, enum nk_button_behavior behavior,
  23941     const struct nk_style_button *style, const struct nk_input *in,
  23942     const struct nk_user_font *font)
  23943 {
  23944     int ret;
  23945     struct nk_rect content;
  23946 
  23947     NK_ASSERT(state);
  23948     NK_ASSERT(style);
  23949     NK_ASSERT(font);
  23950     NK_ASSERT(out);
  23951     if (!out || !style || !font || !state)
  23952         return nk_false;
  23953 
  23954     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
  23955     if (style->draw_begin) style->draw_begin(out, style->userdata);
  23956     nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
  23957     if (style->draw_end) style->draw_end(out, style->userdata);
  23958     return ret;
  23959 }
  23960 NK_LIB void
  23961 nk_draw_button_image(struct nk_command_buffer *out,
  23962     const struct nk_rect *bounds, const struct nk_rect *content,
  23963     nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
  23964 {
  23965     nk_draw_button(out, bounds, state, style);
  23966     nk_draw_image(out, *content, img, nk_white);
  23967 }
  23968 NK_LIB nk_bool
  23969 nk_do_button_image(nk_flags *state,
  23970     struct nk_command_buffer *out, struct nk_rect bounds,
  23971     struct nk_image img, enum nk_button_behavior b,
  23972     const struct nk_style_button *style, const struct nk_input *in)
  23973 {
  23974     int ret;
  23975     struct nk_rect content;
  23976 
  23977     NK_ASSERT(state);
  23978     NK_ASSERT(style);
  23979     NK_ASSERT(out);
  23980     if (!out || !style || !state)
  23981         return nk_false;
  23982 
  23983     ret = nk_do_button(state, out, bounds, style, in, b, &content);
  23984     content.x += style->image_padding.x;
  23985     content.y += style->image_padding.y;
  23986     content.w -= 2 * style->image_padding.x;
  23987     content.h -= 2 * style->image_padding.y;
  23988 
  23989     if (style->draw_begin) style->draw_begin(out, style->userdata);
  23990     nk_draw_button_image(out, &bounds, &content, *state, style, &img);
  23991     if (style->draw_end) style->draw_end(out, style->userdata);
  23992     return ret;
  23993 }
  23994 NK_LIB void
  23995 nk_draw_button_text_symbol(struct nk_command_buffer *out,
  23996     const struct nk_rect *bounds, const struct nk_rect *label,
  23997     const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
  23998     const char *str, int len, enum nk_symbol_type type,
  23999     const struct nk_user_font *font)
  24000 {
  24001     struct nk_color sym;
  24002     struct nk_text text;
  24003     const struct nk_style_item *background;
  24004 
  24005     /* select correct background colors/images */
  24006     background = nk_draw_button(out, bounds, state, style);
  24007     if (background->type == NK_STYLE_ITEM_COLOR)
  24008         text.background = background->data.color;
  24009     else text.background = style->text_background;
  24010 
  24011     /* select correct text colors */
  24012     if (state & NK_WIDGET_STATE_HOVER) {
  24013         sym = style->text_hover;
  24014         text.text = style->text_hover;
  24015     } else if (state & NK_WIDGET_STATE_ACTIVED) {
  24016         sym = style->text_active;
  24017         text.text = style->text_active;
  24018     } else {
  24019         sym = style->text_normal;
  24020         text.text = style->text_normal;
  24021     }
  24022 
  24023     text.padding = nk_vec2(0,0);
  24024     nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
  24025     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
  24026 }
  24027 NK_LIB nk_bool
  24028 nk_do_button_text_symbol(nk_flags *state,
  24029     struct nk_command_buffer *out, struct nk_rect bounds,
  24030     enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
  24031     enum nk_button_behavior behavior, const struct nk_style_button *style,
  24032     const struct nk_user_font *font, const struct nk_input *in)
  24033 {
  24034     int ret;
  24035     struct nk_rect tri = {0,0,0,0};
  24036     struct nk_rect content;
  24037 
  24038     NK_ASSERT(style);
  24039     NK_ASSERT(out);
  24040     NK_ASSERT(font);
  24041     if (!out || !style || !font)
  24042         return nk_false;
  24043 
  24044     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
  24045     tri.y = content.y + (content.h/2) - font->height/2;
  24046     tri.w = font->height; tri.h = font->height;
  24047     if (align & NK_TEXT_ALIGN_LEFT) {
  24048         tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
  24049         tri.x = NK_MAX(tri.x, 0);
  24050     } else tri.x = content.x + 2 * style->padding.x;
  24051 
  24052     /* draw button */
  24053     if (style->draw_begin) style->draw_begin(out, style->userdata);
  24054     nk_draw_button_text_symbol(out, &bounds, &content, &tri,
  24055         *state, style, str, len, symbol, font);
  24056     if (style->draw_end) style->draw_end(out, style->userdata);
  24057     return ret;
  24058 }
  24059 NK_LIB void
  24060 nk_draw_button_text_image(struct nk_command_buffer *out,
  24061     const struct nk_rect *bounds, const struct nk_rect *label,
  24062     const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
  24063     const char *str, int len, const struct nk_user_font *font,
  24064     const struct nk_image *img)
  24065 {
  24066     struct nk_text text;
  24067     const struct nk_style_item *background;
  24068     background = nk_draw_button(out, bounds, state, style);
  24069 
  24070     /* select correct colors */
  24071     if (background->type == NK_STYLE_ITEM_COLOR)
  24072         text.background = background->data.color;
  24073     else text.background = style->text_background;
  24074     if (state & NK_WIDGET_STATE_HOVER)
  24075         text.text = style->text_hover;
  24076     else if (state & NK_WIDGET_STATE_ACTIVED)
  24077         text.text = style->text_active;
  24078     else text.text = style->text_normal;
  24079 
  24080     text.padding = nk_vec2(0,0);
  24081     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
  24082     nk_draw_image(out, *image, img, nk_white);
  24083 }
  24084 NK_LIB nk_bool
  24085 nk_do_button_text_image(nk_flags *state,
  24086     struct nk_command_buffer *out, struct nk_rect bounds,
  24087     struct nk_image img, const char* str, int len, nk_flags align,
  24088     enum nk_button_behavior behavior, const struct nk_style_button *style,
  24089     const struct nk_user_font *font, const struct nk_input *in)
  24090 {
  24091     int ret;
  24092     struct nk_rect icon;
  24093     struct nk_rect content;
  24094 
  24095     NK_ASSERT(style);
  24096     NK_ASSERT(state);
  24097     NK_ASSERT(font);
  24098     NK_ASSERT(out);
  24099     if (!out || !font || !style || !str)
  24100         return nk_false;
  24101 
  24102     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
  24103     icon.y = bounds.y + style->padding.y;
  24104     icon.w = icon.h = bounds.h - 2 * style->padding.y;
  24105     if (align & NK_TEXT_ALIGN_LEFT) {
  24106         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
  24107         icon.x = NK_MAX(icon.x, 0);
  24108     } else icon.x = bounds.x + 2 * style->padding.x;
  24109 
  24110     icon.x += style->image_padding.x;
  24111     icon.y += style->image_padding.y;
  24112     icon.w -= 2 * style->image_padding.x;
  24113     icon.h -= 2 * style->image_padding.y;
  24114 
  24115     if (style->draw_begin) style->draw_begin(out, style->userdata);
  24116     nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
  24117     if (style->draw_end) style->draw_end(out, style->userdata);
  24118     return ret;
  24119 }
  24120 NK_API void
  24121 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
  24122 {
  24123     NK_ASSERT(ctx);
  24124     if (!ctx) return;
  24125     ctx->button_behavior = behavior;
  24126 }
  24127 NK_API nk_bool
  24128 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
  24129 {
  24130     struct nk_config_stack_button_behavior *button_stack;
  24131     struct nk_config_stack_button_behavior_element *element;
  24132 
  24133     NK_ASSERT(ctx);
  24134     if (!ctx) return 0;
  24135 
  24136     button_stack = &ctx->stacks.button_behaviors;
  24137     NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
  24138     if (button_stack->head >= (int)NK_LEN(button_stack->elements))
  24139         return 0;
  24140 
  24141     element = &button_stack->elements[button_stack->head++];
  24142     element->address = &ctx->button_behavior;
  24143     element->old_value = ctx->button_behavior;
  24144     ctx->button_behavior = behavior;
  24145     return 1;
  24146 }
  24147 NK_API nk_bool
  24148 nk_button_pop_behavior(struct nk_context *ctx)
  24149 {
  24150     struct nk_config_stack_button_behavior *button_stack;
  24151     struct nk_config_stack_button_behavior_element *element;
  24152 
  24153     NK_ASSERT(ctx);
  24154     if (!ctx) return 0;
  24155 
  24156     button_stack = &ctx->stacks.button_behaviors;
  24157     NK_ASSERT(button_stack->head > 0);
  24158     if (button_stack->head < 1)
  24159         return 0;
  24160 
  24161     element = &button_stack->elements[--button_stack->head];
  24162     *element->address = element->old_value;
  24163     return 1;
  24164 }
  24165 NK_API nk_bool
  24166 nk_button_text_styled(struct nk_context *ctx,
  24167     const struct nk_style_button *style, const char *title, int len)
  24168 {
  24169     struct nk_window *win;
  24170     struct nk_panel *layout;
  24171     const struct nk_input *in;
  24172 
  24173     struct nk_rect bounds;
  24174     enum nk_widget_layout_states state;
  24175 
  24176     NK_ASSERT(ctx);
  24177     NK_ASSERT(style);
  24178     NK_ASSERT(ctx->current);
  24179     NK_ASSERT(ctx->current->layout);
  24180     if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
  24181 
  24182     win = ctx->current;
  24183     layout = win->layout;
  24184     state = nk_widget(&bounds, ctx);
  24185 
  24186     if (!state) return 0;
  24187     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24188     return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
  24189                     title, len, style->text_alignment, ctx->button_behavior,
  24190                     style, in, ctx->style.font);
  24191 }
  24192 NK_API nk_bool
  24193 nk_button_text(struct nk_context *ctx, const char *title, int len)
  24194 {
  24195     NK_ASSERT(ctx);
  24196     if (!ctx) return 0;
  24197     return nk_button_text_styled(ctx, &ctx->style.button, title, len);
  24198 }
  24199 NK_API nk_bool nk_button_label_styled(struct nk_context *ctx,
  24200     const struct nk_style_button *style, const char *title)
  24201 {
  24202     return nk_button_text_styled(ctx, style, title, nk_strlen(title));
  24203 }
  24204 NK_API nk_bool nk_button_label(struct nk_context *ctx, const char *title)
  24205 {
  24206     return nk_button_text(ctx, title, nk_strlen(title));
  24207 }
  24208 NK_API nk_bool
  24209 nk_button_color(struct nk_context *ctx, struct nk_color color)
  24210 {
  24211     struct nk_window *win;
  24212     struct nk_panel *layout;
  24213     const struct nk_input *in;
  24214     struct nk_style_button button;
  24215 
  24216     int ret = 0;
  24217     struct nk_rect bounds;
  24218     struct nk_rect content;
  24219     enum nk_widget_layout_states state;
  24220 
  24221     NK_ASSERT(ctx);
  24222     NK_ASSERT(ctx->current);
  24223     NK_ASSERT(ctx->current->layout);
  24224     if (!ctx || !ctx->current || !ctx->current->layout)
  24225         return 0;
  24226 
  24227     win = ctx->current;
  24228     layout = win->layout;
  24229 
  24230     state = nk_widget(&bounds, ctx);
  24231     if (!state) return 0;
  24232     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24233 
  24234     button = ctx->style.button;
  24235     button.normal = nk_style_item_color(color);
  24236     button.hover = nk_style_item_color(color);
  24237     button.active = nk_style_item_color(color);
  24238     ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
  24239                 &button, in, ctx->button_behavior, &content);
  24240     nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
  24241     return ret;
  24242 }
  24243 NK_API nk_bool
  24244 nk_button_symbol_styled(struct nk_context *ctx,
  24245     const struct nk_style_button *style, enum nk_symbol_type symbol)
  24246 {
  24247     struct nk_window *win;
  24248     struct nk_panel *layout;
  24249     const struct nk_input *in;
  24250 
  24251     struct nk_rect bounds;
  24252     enum nk_widget_layout_states state;
  24253 
  24254     NK_ASSERT(ctx);
  24255     NK_ASSERT(ctx->current);
  24256     NK_ASSERT(ctx->current->layout);
  24257     if (!ctx || !ctx->current || !ctx->current->layout)
  24258         return 0;
  24259 
  24260     win = ctx->current;
  24261     layout = win->layout;
  24262     state = nk_widget(&bounds, ctx);
  24263     if (!state) return 0;
  24264     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24265     return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
  24266             symbol, ctx->button_behavior, style, in, ctx->style.font);
  24267 }
  24268 NK_API nk_bool
  24269 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
  24270 {
  24271     NK_ASSERT(ctx);
  24272     if (!ctx) return 0;
  24273     return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
  24274 }
  24275 NK_API nk_bool
  24276 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
  24277     struct nk_image img)
  24278 {
  24279     struct nk_window *win;
  24280     struct nk_panel *layout;
  24281     const struct nk_input *in;
  24282 
  24283     struct nk_rect bounds;
  24284     enum nk_widget_layout_states state;
  24285 
  24286     NK_ASSERT(ctx);
  24287     NK_ASSERT(ctx->current);
  24288     NK_ASSERT(ctx->current->layout);
  24289     if (!ctx || !ctx->current || !ctx->current->layout)
  24290         return 0;
  24291 
  24292     win = ctx->current;
  24293     layout = win->layout;
  24294 
  24295     state = nk_widget(&bounds, ctx);
  24296     if (!state) return 0;
  24297     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24298     return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
  24299                 img, ctx->button_behavior, style, in);
  24300 }
  24301 NK_API nk_bool
  24302 nk_button_image(struct nk_context *ctx, struct nk_image img)
  24303 {
  24304     NK_ASSERT(ctx);
  24305     if (!ctx) return 0;
  24306     return nk_button_image_styled(ctx, &ctx->style.button, img);
  24307 }
  24308 NK_API nk_bool
  24309 nk_button_symbol_text_styled(struct nk_context *ctx,
  24310     const struct nk_style_button *style, enum nk_symbol_type symbol,
  24311     const char *text, int len, nk_flags align)
  24312 {
  24313     struct nk_window *win;
  24314     struct nk_panel *layout;
  24315     const struct nk_input *in;
  24316 
  24317     struct nk_rect bounds;
  24318     enum nk_widget_layout_states state;
  24319 
  24320     NK_ASSERT(ctx);
  24321     NK_ASSERT(ctx->current);
  24322     NK_ASSERT(ctx->current->layout);
  24323     if (!ctx || !ctx->current || !ctx->current->layout)
  24324         return 0;
  24325 
  24326     win = ctx->current;
  24327     layout = win->layout;
  24328 
  24329     state = nk_widget(&bounds, ctx);
  24330     if (!state) return 0;
  24331     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24332     return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
  24333                 symbol, text, len, align, ctx->button_behavior,
  24334                 style, ctx->style.font, in);
  24335 }
  24336 NK_API nk_bool
  24337 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
  24338     const char* text, int len, nk_flags align)
  24339 {
  24340     NK_ASSERT(ctx);
  24341     if (!ctx) return 0;
  24342     return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
  24343 }
  24344 NK_API nk_bool nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
  24345     const char *label, nk_flags align)
  24346 {
  24347     return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);
  24348 }
  24349 NK_API nk_bool nk_button_symbol_label_styled(struct nk_context *ctx,
  24350     const struct nk_style_button *style, enum nk_symbol_type symbol,
  24351     const char *title, nk_flags align)
  24352 {
  24353     return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);
  24354 }
  24355 NK_API nk_bool
  24356 nk_button_image_text_styled(struct nk_context *ctx,
  24357     const struct nk_style_button *style, struct nk_image img, const char *text,
  24358     int len, nk_flags align)
  24359 {
  24360     struct nk_window *win;
  24361     struct nk_panel *layout;
  24362     const struct nk_input *in;
  24363 
  24364     struct nk_rect bounds;
  24365     enum nk_widget_layout_states state;
  24366 
  24367     NK_ASSERT(ctx);
  24368     NK_ASSERT(ctx->current);
  24369     NK_ASSERT(ctx->current->layout);
  24370     if (!ctx || !ctx->current || !ctx->current->layout)
  24371         return 0;
  24372 
  24373     win = ctx->current;
  24374     layout = win->layout;
  24375 
  24376     state = nk_widget(&bounds, ctx);
  24377     if (!state) return 0;
  24378     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24379     return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
  24380             bounds, img, text, len, align, ctx->button_behavior,
  24381             style, ctx->style.font, in);
  24382 }
  24383 NK_API nk_bool
  24384 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
  24385     const char *text, int len, nk_flags align)
  24386 {
  24387     return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);
  24388 }
  24389 NK_API nk_bool nk_button_image_label(struct nk_context *ctx, struct nk_image img,
  24390     const char *label, nk_flags align)
  24391 {
  24392     return nk_button_image_text(ctx, img, label, nk_strlen(label), align);
  24393 }
  24394 NK_API nk_bool nk_button_image_label_styled(struct nk_context *ctx,
  24395     const struct nk_style_button *style, struct nk_image img,
  24396     const char *label, nk_flags text_alignment)
  24397 {
  24398     return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);
  24399 }
  24400 
  24401 
  24402 
  24403 
  24404 
  24405 /* ===============================================================
  24406  *
  24407  *                              TOGGLE
  24408  *
  24409  * ===============================================================*/
  24410 NK_LIB nk_bool
  24411 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
  24412     nk_flags *state, nk_bool active)
  24413 {
  24414     nk_widget_state_reset(state);
  24415     if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
  24416         *state = NK_WIDGET_STATE_ACTIVE;
  24417         active = !active;
  24418     }
  24419     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
  24420         *state |= NK_WIDGET_STATE_ENTERED;
  24421     else if (nk_input_is_mouse_prev_hovering_rect(in, select))
  24422         *state |= NK_WIDGET_STATE_LEFT;
  24423     return active;
  24424 }
  24425 NK_LIB void
  24426 nk_draw_checkbox(struct nk_command_buffer *out,
  24427     nk_flags state, const struct nk_style_toggle *style, nk_bool active,
  24428     const struct nk_rect *label, const struct nk_rect *selector,
  24429     const struct nk_rect *cursors, const char *string, int len,
  24430     const struct nk_user_font *font)
  24431 {
  24432     const struct nk_style_item *background;
  24433     const struct nk_style_item *cursor;
  24434     struct nk_text text;
  24435 
  24436     /* select correct colors/images */
  24437     if (state & NK_WIDGET_STATE_HOVER) {
  24438         background = &style->hover;
  24439         cursor = &style->cursor_hover;
  24440         text.text = style->text_hover;
  24441     } else if (state & NK_WIDGET_STATE_ACTIVED) {
  24442         background = &style->hover;
  24443         cursor = &style->cursor_hover;
  24444         text.text = style->text_active;
  24445     } else {
  24446         background = &style->normal;
  24447         cursor = &style->cursor_normal;
  24448         text.text = style->text_normal;
  24449     }
  24450 
  24451     /* draw background and cursor */
  24452     if (background->type == NK_STYLE_ITEM_COLOR) {
  24453         nk_fill_rect(out, *selector, 0, style->border_color);
  24454         nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
  24455     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
  24456     if (active) {
  24457         if (cursor->type == NK_STYLE_ITEM_IMAGE)
  24458             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
  24459         else nk_fill_rect(out, *cursors, 0, cursor->data.color);
  24460     }
  24461 
  24462     text.padding.x = 0;
  24463     text.padding.y = 0;
  24464     text.background = style->text_background;
  24465     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
  24466 }
  24467 NK_LIB void
  24468 nk_draw_option(struct nk_command_buffer *out,
  24469     nk_flags state, const struct nk_style_toggle *style, nk_bool active,
  24470     const struct nk_rect *label, const struct nk_rect *selector,
  24471     const struct nk_rect *cursors, const char *string, int len,
  24472     const struct nk_user_font *font)
  24473 {
  24474     const struct nk_style_item *background;
  24475     const struct nk_style_item *cursor;
  24476     struct nk_text text;
  24477 
  24478     /* select correct colors/images */
  24479     if (state & NK_WIDGET_STATE_HOVER) {
  24480         background = &style->hover;
  24481         cursor = &style->cursor_hover;
  24482         text.text = style->text_hover;
  24483     } else if (state & NK_WIDGET_STATE_ACTIVED) {
  24484         background = &style->hover;
  24485         cursor = &style->cursor_hover;
  24486         text.text = style->text_active;
  24487     } else {
  24488         background = &style->normal;
  24489         cursor = &style->cursor_normal;
  24490         text.text = style->text_normal;
  24491     }
  24492 
  24493     /* draw background and cursor */
  24494     if (background->type == NK_STYLE_ITEM_COLOR) {
  24495         nk_fill_circle(out, *selector, style->border_color);
  24496         nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
  24497     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
  24498     if (active) {
  24499         if (cursor->type == NK_STYLE_ITEM_IMAGE)
  24500             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
  24501         else nk_fill_circle(out, *cursors, cursor->data.color);
  24502     }
  24503 
  24504     text.padding.x = 0;
  24505     text.padding.y = 0;
  24506     text.background = style->text_background;
  24507     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
  24508 }
  24509 NK_LIB nk_bool
  24510 nk_do_toggle(nk_flags *state,
  24511     struct nk_command_buffer *out, struct nk_rect r,
  24512     nk_bool *active, const char *str, int len, enum nk_toggle_type type,
  24513     const struct nk_style_toggle *style, const struct nk_input *in,
  24514     const struct nk_user_font *font)
  24515 {
  24516     int was_active;
  24517     struct nk_rect bounds;
  24518     struct nk_rect select;
  24519     struct nk_rect cursor;
  24520     struct nk_rect label;
  24521 
  24522     NK_ASSERT(style);
  24523     NK_ASSERT(out);
  24524     NK_ASSERT(font);
  24525     if (!out || !style || !font || !active)
  24526         return 0;
  24527 
  24528     r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
  24529     r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
  24530 
  24531     /* add additional touch padding for touch screen devices */
  24532     bounds.x = r.x - style->touch_padding.x;
  24533     bounds.y = r.y - style->touch_padding.y;
  24534     bounds.w = r.w + 2 * style->touch_padding.x;
  24535     bounds.h = r.h + 2 * style->touch_padding.y;
  24536 
  24537     /* calculate the selector space */
  24538     select.w = font->height;
  24539     select.h = select.w;
  24540     select.y = r.y + r.h/2.0f - select.h/2.0f;
  24541     select.x = r.x;
  24542 
  24543     /* calculate the bounds of the cursor inside the selector */
  24544     cursor.x = select.x + style->padding.x + style->border;
  24545     cursor.y = select.y + style->padding.y + style->border;
  24546     cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
  24547     cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
  24548 
  24549     /* label behind the selector */
  24550     label.x = select.x + select.w + style->spacing;
  24551     label.y = select.y;
  24552     label.w = NK_MAX(r.x + r.w, label.x) - label.x;
  24553     label.h = select.w;
  24554 
  24555     /* update selector */
  24556     was_active = *active;
  24557     *active = nk_toggle_behavior(in, bounds, state, *active);
  24558 
  24559     /* draw selector */
  24560     if (style->draw_begin)
  24561         style->draw_begin(out, style->userdata);
  24562     if (type == NK_TOGGLE_CHECK) {
  24563         nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
  24564     } else {
  24565         nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
  24566     }
  24567     if (style->draw_end)
  24568         style->draw_end(out, style->userdata);
  24569     return (was_active != *active);
  24570 }
  24571 /*----------------------------------------------------------------
  24572  *
  24573  *                          CHECKBOX
  24574  *
  24575  * --------------------------------------------------------------*/
  24576 NK_API nk_bool
  24577 nk_check_text(struct nk_context *ctx, const char *text, int len, nk_bool active)
  24578 {
  24579     struct nk_window *win;
  24580     struct nk_panel *layout;
  24581     const struct nk_input *in;
  24582     const struct nk_style *style;
  24583 
  24584     struct nk_rect bounds;
  24585     enum nk_widget_layout_states state;
  24586 
  24587     NK_ASSERT(ctx);
  24588     NK_ASSERT(ctx->current);
  24589     NK_ASSERT(ctx->current->layout);
  24590     if (!ctx || !ctx->current || !ctx->current->layout)
  24591         return active;
  24592 
  24593     win = ctx->current;
  24594     style = &ctx->style;
  24595     layout = win->layout;
  24596 
  24597     state = nk_widget(&bounds, ctx);
  24598     if (!state) return active;
  24599     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24600     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
  24601         text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
  24602     return active;
  24603 }
  24604 NK_API unsigned int
  24605 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
  24606     unsigned int flags, unsigned int value)
  24607 {
  24608     int old_active;
  24609     NK_ASSERT(ctx);
  24610     NK_ASSERT(text);
  24611     if (!ctx || !text) return flags;
  24612     old_active = (int)((flags & value) & value);
  24613     if (nk_check_text(ctx, text, len, old_active))
  24614         flags |= value;
  24615     else flags &= ~value;
  24616     return flags;
  24617 }
  24618 NK_API nk_bool
  24619 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, nk_bool *active)
  24620 {
  24621     int old_val;
  24622     NK_ASSERT(ctx);
  24623     NK_ASSERT(text);
  24624     NK_ASSERT(active);
  24625     if (!ctx || !text || !active) return 0;
  24626     old_val = *active;
  24627     *active = nk_check_text(ctx, text, len, *active);
  24628     return old_val != *active;
  24629 }
  24630 NK_API nk_bool
  24631 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
  24632     unsigned int *flags, unsigned int value)
  24633 {
  24634     nk_bool active;
  24635     NK_ASSERT(ctx);
  24636     NK_ASSERT(text);
  24637     NK_ASSERT(flags);
  24638     if (!ctx || !text || !flags) return 0;
  24639 
  24640     active = (int)((*flags & value) & value);
  24641     if (nk_checkbox_text(ctx, text, len, &active)) {
  24642         if (active) *flags |= value;
  24643         else *flags &= ~value;
  24644         return 1;
  24645     }
  24646     return 0;
  24647 }
  24648 NK_API nk_bool nk_check_label(struct nk_context *ctx, const char *label, nk_bool active)
  24649 {
  24650     return nk_check_text(ctx, label, nk_strlen(label), active);
  24651 }
  24652 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
  24653     unsigned int flags, unsigned int value)
  24654 {
  24655     return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);
  24656 }
  24657 NK_API nk_bool nk_checkbox_label(struct nk_context *ctx, const char *label, nk_bool *active)
  24658 {
  24659     return nk_checkbox_text(ctx, label, nk_strlen(label), active);
  24660 }
  24661 NK_API nk_bool nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
  24662     unsigned int *flags, unsigned int value)
  24663 {
  24664     return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);
  24665 }
  24666 /*----------------------------------------------------------------
  24667  *
  24668  *                          OPTION
  24669  *
  24670  * --------------------------------------------------------------*/
  24671 NK_API nk_bool
  24672 nk_option_text(struct nk_context *ctx, const char *text, int len, nk_bool is_active)
  24673 {
  24674     struct nk_window *win;
  24675     struct nk_panel *layout;
  24676     const struct nk_input *in;
  24677     const struct nk_style *style;
  24678 
  24679     struct nk_rect bounds;
  24680     enum nk_widget_layout_states state;
  24681 
  24682     NK_ASSERT(ctx);
  24683     NK_ASSERT(ctx->current);
  24684     NK_ASSERT(ctx->current->layout);
  24685     if (!ctx || !ctx->current || !ctx->current->layout)
  24686         return is_active;
  24687 
  24688     win = ctx->current;
  24689     style = &ctx->style;
  24690     layout = win->layout;
  24691 
  24692     state = nk_widget(&bounds, ctx);
  24693     if (!state) return (int)state;
  24694     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24695     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
  24696         text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
  24697     return is_active;
  24698 }
  24699 NK_API nk_bool
  24700 nk_radio_text(struct nk_context *ctx, const char *text, int len, nk_bool *active)
  24701 {
  24702     int old_value;
  24703     NK_ASSERT(ctx);
  24704     NK_ASSERT(text);
  24705     NK_ASSERT(active);
  24706     if (!ctx || !text || !active) return 0;
  24707     old_value = *active;
  24708     *active = nk_option_text(ctx, text, len, old_value);
  24709     return old_value != *active;
  24710 }
  24711 NK_API nk_bool
  24712 nk_option_label(struct nk_context *ctx, const char *label, nk_bool active)
  24713 {
  24714     return nk_option_text(ctx, label, nk_strlen(label), active);
  24715 }
  24716 NK_API nk_bool
  24717 nk_radio_label(struct nk_context *ctx, const char *label, nk_bool *active)
  24718 {
  24719     return nk_radio_text(ctx, label, nk_strlen(label), active);
  24720 }
  24721 
  24722 
  24723 
  24724 
  24725 
  24726 /* ===============================================================
  24727  *
  24728  *                              SELECTABLE
  24729  *
  24730  * ===============================================================*/
  24731 NK_LIB void
  24732 nk_draw_selectable(struct nk_command_buffer *out,
  24733     nk_flags state, const struct nk_style_selectable *style, nk_bool active,
  24734     const struct nk_rect *bounds,
  24735     const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym,
  24736     const char *string, int len, nk_flags align, const struct nk_user_font *font)
  24737 {
  24738     const struct nk_style_item *background;
  24739     struct nk_text text;
  24740     text.padding = style->padding;
  24741 
  24742     /* select correct colors/images */
  24743     if (!active) {
  24744         if (state & NK_WIDGET_STATE_ACTIVED) {
  24745             background = &style->pressed;
  24746             text.text = style->text_pressed;
  24747         } else if (state & NK_WIDGET_STATE_HOVER) {
  24748             background = &style->hover;
  24749             text.text = style->text_hover;
  24750         } else {
  24751             background = &style->normal;
  24752             text.text = style->text_normal;
  24753         }
  24754     } else {
  24755         if (state & NK_WIDGET_STATE_ACTIVED) {
  24756             background = &style->pressed_active;
  24757             text.text = style->text_pressed_active;
  24758         } else if (state & NK_WIDGET_STATE_HOVER) {
  24759             background = &style->hover_active;
  24760             text.text = style->text_hover_active;
  24761         } else {
  24762             background = &style->normal_active;
  24763             text.text = style->text_normal_active;
  24764         }
  24765     }
  24766     /* draw selectable background and text */
  24767     switch (background->type) {
  24768         case NK_STYLE_ITEM_IMAGE:
  24769             text.background = nk_rgba(0, 0, 0, 0);
  24770             nk_draw_image(out, *bounds, &background->data.image, nk_white);
  24771             break;
  24772         case NK_STYLE_ITEM_NINE_SLICE:
  24773             text.background = nk_rgba(0, 0, 0, 0);
  24774             nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white);
  24775             break;
  24776         case NK_STYLE_ITEM_COLOR:
  24777             text.background = background->data.color;
  24778             nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  24779             break;
  24780     }
  24781     if (icon) {
  24782         if (img) nk_draw_image(out, *icon, img, nk_white);
  24783         else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font);
  24784     }
  24785     nk_widget_text(out, *bounds, string, len, &text, align, font);
  24786 }
  24787 NK_LIB nk_bool
  24788 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
  24789     struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value,
  24790     const struct nk_style_selectable *style, const struct nk_input *in,
  24791     const struct nk_user_font *font)
  24792 {
  24793     int old_value;
  24794     struct nk_rect touch;
  24795 
  24796     NK_ASSERT(state);
  24797     NK_ASSERT(out);
  24798     NK_ASSERT(str);
  24799     NK_ASSERT(len);
  24800     NK_ASSERT(value);
  24801     NK_ASSERT(style);
  24802     NK_ASSERT(font);
  24803 
  24804     if (!state || !out || !str || !len || !value || !style || !font) return 0;
  24805     old_value = *value;
  24806 
  24807     /* remove padding */
  24808     touch.x = bounds.x - style->touch_padding.x;
  24809     touch.y = bounds.y - style->touch_padding.y;
  24810     touch.w = bounds.w + style->touch_padding.x * 2;
  24811     touch.h = bounds.h + style->touch_padding.y * 2;
  24812 
  24813     /* update button */
  24814     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
  24815         *value = !(*value);
  24816 
  24817     /* draw selectable */
  24818     if (style->draw_begin) style->draw_begin(out, style->userdata);
  24819     nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font);
  24820     if (style->draw_end) style->draw_end(out, style->userdata);
  24821     return old_value != *value;
  24822 }
  24823 NK_LIB nk_bool
  24824 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
  24825     struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value,
  24826     const struct nk_image *img, const struct nk_style_selectable *style,
  24827     const struct nk_input *in, const struct nk_user_font *font)
  24828 {
  24829     nk_bool old_value;
  24830     struct nk_rect touch;
  24831     struct nk_rect icon;
  24832 
  24833     NK_ASSERT(state);
  24834     NK_ASSERT(out);
  24835     NK_ASSERT(str);
  24836     NK_ASSERT(len);
  24837     NK_ASSERT(value);
  24838     NK_ASSERT(style);
  24839     NK_ASSERT(font);
  24840 
  24841     if (!state || !out || !str || !len || !value || !style || !font) return 0;
  24842     old_value = *value;
  24843 
  24844     /* toggle behavior */
  24845     touch.x = bounds.x - style->touch_padding.x;
  24846     touch.y = bounds.y - style->touch_padding.y;
  24847     touch.w = bounds.w + style->touch_padding.x * 2;
  24848     touch.h = bounds.h + style->touch_padding.y * 2;
  24849     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
  24850         *value = !(*value);
  24851 
  24852     icon.y = bounds.y + style->padding.y;
  24853     icon.w = icon.h = bounds.h - 2 * style->padding.y;
  24854     if (align & NK_TEXT_ALIGN_LEFT) {
  24855         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
  24856         icon.x = NK_MAX(icon.x, 0);
  24857     } else icon.x = bounds.x + 2 * style->padding.x;
  24858 
  24859     icon.x += style->image_padding.x;
  24860     icon.y += style->image_padding.y;
  24861     icon.w -= 2 * style->image_padding.x;
  24862     icon.h -= 2 * style->image_padding.y;
  24863 
  24864     /* draw selectable */
  24865     if (style->draw_begin) style->draw_begin(out, style->userdata);
  24866     nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font);
  24867     if (style->draw_end) style->draw_end(out, style->userdata);
  24868     return old_value != *value;
  24869 }
  24870 NK_LIB nk_bool
  24871 nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out,
  24872     struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value,
  24873     enum nk_symbol_type sym, const struct nk_style_selectable *style,
  24874     const struct nk_input *in, const struct nk_user_font *font)
  24875 {
  24876     int old_value;
  24877     struct nk_rect touch;
  24878     struct nk_rect icon;
  24879 
  24880     NK_ASSERT(state);
  24881     NK_ASSERT(out);
  24882     NK_ASSERT(str);
  24883     NK_ASSERT(len);
  24884     NK_ASSERT(value);
  24885     NK_ASSERT(style);
  24886     NK_ASSERT(font);
  24887 
  24888     if (!state || !out || !str || !len || !value || !style || !font) return 0;
  24889     old_value = *value;
  24890 
  24891     /* toggle behavior */
  24892     touch.x = bounds.x - style->touch_padding.x;
  24893     touch.y = bounds.y - style->touch_padding.y;
  24894     touch.w = bounds.w + style->touch_padding.x * 2;
  24895     touch.h = bounds.h + style->touch_padding.y * 2;
  24896     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
  24897         *value = !(*value);
  24898 
  24899     icon.y = bounds.y + style->padding.y;
  24900     icon.w = icon.h = bounds.h - 2 * style->padding.y;
  24901     if (align & NK_TEXT_ALIGN_LEFT) {
  24902         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
  24903         icon.x = NK_MAX(icon.x, 0);
  24904     } else icon.x = bounds.x + 2 * style->padding.x;
  24905 
  24906     icon.x += style->image_padding.x;
  24907     icon.y += style->image_padding.y;
  24908     icon.w -= 2 * style->image_padding.x;
  24909     icon.h -= 2 * style->image_padding.y;
  24910 
  24911     /* draw selectable */
  24912     if (style->draw_begin) style->draw_begin(out, style->userdata);
  24913     nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font);
  24914     if (style->draw_end) style->draw_end(out, style->userdata);
  24915     return old_value != *value;
  24916 }
  24917 
  24918 NK_API nk_bool
  24919 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
  24920     nk_flags align, nk_bool *value)
  24921 {
  24922     struct nk_window *win;
  24923     struct nk_panel *layout;
  24924     const struct nk_input *in;
  24925     const struct nk_style *style;
  24926 
  24927     enum nk_widget_layout_states state;
  24928     struct nk_rect bounds;
  24929 
  24930     NK_ASSERT(ctx);
  24931     NK_ASSERT(value);
  24932     NK_ASSERT(ctx->current);
  24933     NK_ASSERT(ctx->current->layout);
  24934     if (!ctx || !ctx->current || !ctx->current->layout || !value)
  24935         return 0;
  24936 
  24937     win = ctx->current;
  24938     layout = win->layout;
  24939     style = &ctx->style;
  24940 
  24941     state = nk_widget(&bounds, ctx);
  24942     if (!state) return 0;
  24943     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24944     return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
  24945                 str, len, align, value, &style->selectable, in, style->font);
  24946 }
  24947 NK_API nk_bool
  24948 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
  24949     const char *str, int len, nk_flags align, nk_bool *value)
  24950 {
  24951     struct nk_window *win;
  24952     struct nk_panel *layout;
  24953     const struct nk_input *in;
  24954     const struct nk_style *style;
  24955 
  24956     enum nk_widget_layout_states state;
  24957     struct nk_rect bounds;
  24958 
  24959     NK_ASSERT(ctx);
  24960     NK_ASSERT(value);
  24961     NK_ASSERT(ctx->current);
  24962     NK_ASSERT(ctx->current->layout);
  24963     if (!ctx || !ctx->current || !ctx->current->layout || !value)
  24964         return 0;
  24965 
  24966     win = ctx->current;
  24967     layout = win->layout;
  24968     style = &ctx->style;
  24969 
  24970     state = nk_widget(&bounds, ctx);
  24971     if (!state) return 0;
  24972     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24973     return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
  24974                 str, len, align, value, &img, &style->selectable, in, style->font);
  24975 }
  24976 NK_API nk_bool
  24977 nk_selectable_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  24978     const char *str, int len, nk_flags align, nk_bool *value)
  24979 {
  24980     struct nk_window *win;
  24981     struct nk_panel *layout;
  24982     const struct nk_input *in;
  24983     const struct nk_style *style;
  24984 
  24985     enum nk_widget_layout_states state;
  24986     struct nk_rect bounds;
  24987 
  24988     NK_ASSERT(ctx);
  24989     NK_ASSERT(value);
  24990     NK_ASSERT(ctx->current);
  24991     NK_ASSERT(ctx->current->layout);
  24992     if (!ctx || !ctx->current || !ctx->current->layout || !value)
  24993         return 0;
  24994 
  24995     win = ctx->current;
  24996     layout = win->layout;
  24997     style = &ctx->style;
  24998 
  24999     state = nk_widget(&bounds, ctx);
  25000     if (!state) return 0;
  25001     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  25002     return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds,
  25003                 str, len, align, value, sym, &style->selectable, in, style->font);
  25004 }
  25005 NK_API nk_bool
  25006 nk_selectable_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  25007     const char *title, nk_flags align, nk_bool *value)
  25008 {
  25009     return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
  25010 }
  25011 NK_API nk_bool nk_select_text(struct nk_context *ctx, const char *str, int len,
  25012     nk_flags align, nk_bool value)
  25013 {
  25014     nk_selectable_text(ctx, str, len, align, &value);return value;
  25015 }
  25016 NK_API nk_bool nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, nk_bool *value)
  25017 {
  25018     return nk_selectable_text(ctx, str, nk_strlen(str), align, value);
  25019 }
  25020 NK_API nk_bool nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
  25021     const char *str, nk_flags align, nk_bool *value)
  25022 {
  25023     return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);
  25024 }
  25025 NK_API nk_bool nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, nk_bool value)
  25026 {
  25027     nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;
  25028 }
  25029 NK_API nk_bool nk_select_image_label(struct nk_context *ctx, struct nk_image img,
  25030     const char *str, nk_flags align, nk_bool value)
  25031 {
  25032     nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;
  25033 }
  25034 NK_API nk_bool nk_select_image_text(struct nk_context *ctx, struct nk_image img,
  25035     const char *str, int len, nk_flags align, nk_bool value)
  25036 {
  25037     nk_selectable_image_text(ctx, img, str, len, align, &value);return value;
  25038 }
  25039 NK_API nk_bool
  25040 nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  25041     const char *title, int title_len, nk_flags align, nk_bool value)
  25042 {
  25043     nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value;
  25044 }
  25045 NK_API nk_bool
  25046 nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  25047     const char *title, nk_flags align, nk_bool value)
  25048 {
  25049     return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
  25050 }
  25051 
  25052 
  25053 
  25054 
  25055 
  25056 /* ===============================================================
  25057  *
  25058  *                              SLIDER
  25059  *
  25060  * ===============================================================*/
  25061 NK_LIB float
  25062 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
  25063     struct nk_rect *visual_cursor, struct nk_input *in,
  25064     struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
  25065     float slider_step, float slider_steps)
  25066 {
  25067     int left_mouse_down;
  25068     int left_mouse_click_in_cursor;
  25069 
  25070     /* check if visual cursor is being dragged */
  25071     nk_widget_state_reset(state);
  25072     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
  25073     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
  25074             NK_BUTTON_LEFT, *visual_cursor, nk_true);
  25075 
  25076     if (left_mouse_down && left_mouse_click_in_cursor) {
  25077         float ratio = 0;
  25078         const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
  25079         const float pxstep = bounds.w / slider_steps;
  25080 
  25081         /* only update value if the next slider step is reached */
  25082         *state = NK_WIDGET_STATE_ACTIVE;
  25083         if (NK_ABS(d) >= pxstep) {
  25084             const float steps = (float)((int)(NK_ABS(d) / pxstep));
  25085             slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
  25086             slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
  25087             ratio = (slider_value - slider_min)/slider_step;
  25088             logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
  25089             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
  25090         }
  25091     }
  25092 
  25093     /* slider widget state */
  25094     if (nk_input_is_mouse_hovering_rect(in, bounds))
  25095         *state = NK_WIDGET_STATE_HOVERED;
  25096     if (*state & NK_WIDGET_STATE_HOVER &&
  25097         !nk_input_is_mouse_prev_hovering_rect(in, bounds))
  25098         *state |= NK_WIDGET_STATE_ENTERED;
  25099     else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
  25100         *state |= NK_WIDGET_STATE_LEFT;
  25101     return slider_value;
  25102 }
  25103 NK_LIB void
  25104 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
  25105     const struct nk_style_slider *style, const struct nk_rect *bounds,
  25106     const struct nk_rect *visual_cursor, float min, float value, float max)
  25107 {
  25108     struct nk_rect fill;
  25109     struct nk_rect bar;
  25110     const struct nk_style_item *background;
  25111 
  25112     /* select correct slider images/colors */
  25113     struct nk_color bar_color;
  25114     const struct nk_style_item *cursor;
  25115 
  25116     NK_UNUSED(min);
  25117     NK_UNUSED(max);
  25118     NK_UNUSED(value);
  25119 
  25120     if (state & NK_WIDGET_STATE_ACTIVED) {
  25121         background = &style->active;
  25122         bar_color = style->bar_active;
  25123         cursor = &style->cursor_active;
  25124     } else if (state & NK_WIDGET_STATE_HOVER) {
  25125         background = &style->hover;
  25126         bar_color = style->bar_hover;
  25127         cursor = &style->cursor_hover;
  25128     } else {
  25129         background = &style->normal;
  25130         bar_color = style->bar_normal;
  25131         cursor = &style->cursor_normal;
  25132     }
  25133     /* calculate slider background bar */
  25134     bar.x = bounds->x;
  25135     bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
  25136     bar.w = bounds->w;
  25137     bar.h = bounds->h/6;
  25138 
  25139     /* filled background bar style */
  25140     fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
  25141     fill.x = bar.x;
  25142     fill.y = bar.y;
  25143     fill.h = bar.h;
  25144 
  25145     /* draw background */
  25146     switch(background->type) {
  25147         case NK_STYLE_ITEM_IMAGE:
  25148             nk_draw_image(out, *bounds, &background->data.image, nk_white);
  25149             break;
  25150         case NK_STYLE_ITEM_NINE_SLICE:
  25151             nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white);
  25152             break;
  25153         case NK_STYLE_ITEM_COLOR:
  25154             nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  25155             nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
  25156             break;
  25157     }
  25158 
  25159     /* draw slider bar */
  25160     nk_fill_rect(out, bar, style->rounding, bar_color);
  25161     nk_fill_rect(out, fill, style->rounding, style->bar_filled);
  25162 
  25163     /* draw cursor */
  25164     if (cursor->type == NK_STYLE_ITEM_IMAGE)
  25165         nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
  25166     else
  25167         nk_fill_circle(out, *visual_cursor, cursor->data.color);
  25168 }
  25169 NK_LIB float
  25170 nk_do_slider(nk_flags *state,
  25171     struct nk_command_buffer *out, struct nk_rect bounds,
  25172     float min, float val, float max, float step,
  25173     const struct nk_style_slider *style, struct nk_input *in,
  25174     const struct nk_user_font *font)
  25175 {
  25176     float slider_range;
  25177     float slider_min;
  25178     float slider_max;
  25179     float slider_value;
  25180     float slider_steps;
  25181     float cursor_offset;
  25182 
  25183     struct nk_rect visual_cursor;
  25184     struct nk_rect logical_cursor;
  25185 
  25186     NK_ASSERT(style);
  25187     NK_ASSERT(out);
  25188     if (!out || !style)
  25189         return 0;
  25190 
  25191     /* remove padding from slider bounds */
  25192     bounds.x = bounds.x + style->padding.x;
  25193     bounds.y = bounds.y + style->padding.y;
  25194     bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
  25195     bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
  25196     bounds.w -= 2 * style->padding.x;
  25197     bounds.h -= 2 * style->padding.y;
  25198 
  25199     /* optional buttons */
  25200     if (style->show_buttons) {
  25201         nk_flags ws;
  25202         struct nk_rect button;
  25203         button.y = bounds.y;
  25204         button.w = bounds.h;
  25205         button.h = bounds.h;
  25206 
  25207         /* decrement button */
  25208         button.x = bounds.x;
  25209         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
  25210             &style->dec_button, in, font))
  25211             val -= step;
  25212 
  25213         /* increment button */
  25214         button.x = (bounds.x + bounds.w) - button.w;
  25215         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
  25216             &style->inc_button, in, font))
  25217             val += step;
  25218 
  25219         bounds.x = bounds.x + button.w + style->spacing.x;
  25220         bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
  25221     }
  25222 
  25223     /* remove one cursor size to support visual cursor */
  25224     bounds.x += style->cursor_size.x*0.5f;
  25225     bounds.w -= style->cursor_size.x;
  25226 
  25227     /* make sure the provided values are correct */
  25228     slider_max = NK_MAX(min, max);
  25229     slider_min = NK_MIN(min, max);
  25230     slider_value = NK_CLAMP(slider_min, val, slider_max);
  25231     slider_range = slider_max - slider_min;
  25232     slider_steps = slider_range / step;
  25233     cursor_offset = (slider_value - slider_min) / step;
  25234 
  25235     /* calculate cursor
  25236     Basically you have two cursors. One for visual representation and interaction
  25237     and one for updating the actual cursor value. */
  25238     logical_cursor.h = bounds.h;
  25239     logical_cursor.w = bounds.w / slider_steps;
  25240     logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
  25241     logical_cursor.y = bounds.y;
  25242 
  25243     visual_cursor.h = style->cursor_size.y;
  25244     visual_cursor.w = style->cursor_size.x;
  25245     visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
  25246     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
  25247 
  25248     slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
  25249         in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
  25250     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
  25251 
  25252     /* draw slider */
  25253     if (style->draw_begin) style->draw_begin(out, style->userdata);
  25254     nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
  25255     if (style->draw_end) style->draw_end(out, style->userdata);
  25256     return slider_value;
  25257 }
  25258 NK_API nk_bool
  25259 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
  25260     float value_step)
  25261 {
  25262     struct nk_window *win;
  25263     struct nk_panel *layout;
  25264     struct nk_input *in;
  25265     const struct nk_style *style;
  25266 
  25267     int ret = 0;
  25268     float old_value;
  25269     struct nk_rect bounds;
  25270     enum nk_widget_layout_states state;
  25271 
  25272     NK_ASSERT(ctx);
  25273     NK_ASSERT(ctx->current);
  25274     NK_ASSERT(ctx->current->layout);
  25275     NK_ASSERT(value);
  25276     if (!ctx || !ctx->current || !ctx->current->layout || !value)
  25277         return ret;
  25278 
  25279     win = ctx->current;
  25280     style = &ctx->style;
  25281     layout = win->layout;
  25282 
  25283     state = nk_widget(&bounds, ctx);
  25284     if (!state) return ret;
  25285     in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  25286 
  25287     old_value = *value;
  25288     *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
  25289                 old_value, max_value, value_step, &style->slider, in, style->font);
  25290     return (old_value > *value || old_value < *value);
  25291 }
  25292 NK_API float
  25293 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
  25294 {
  25295     nk_slider_float(ctx, min, &val, max, step); return val;
  25296 }
  25297 NK_API int
  25298 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
  25299 {
  25300     float value = (float)val;
  25301     nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
  25302     return (int)value;
  25303 }
  25304 NK_API nk_bool
  25305 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
  25306 {
  25307     int ret;
  25308     float value = (float)*val;
  25309     ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
  25310     *val =  (int)value;
  25311     return ret;
  25312 }
  25313 
  25314 
  25315 
  25316 
  25317 
  25318 /* ===============================================================
  25319  *
  25320  *                          PROGRESS
  25321  *
  25322  * ===============================================================*/
  25323 NK_LIB nk_size
  25324 nk_progress_behavior(nk_flags *state, struct nk_input *in,
  25325     struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, nk_bool modifiable)
  25326 {
  25327     int left_mouse_down = 0;
  25328     int left_mouse_click_in_cursor = 0;
  25329 
  25330     nk_widget_state_reset(state);
  25331     if (!in || !modifiable) return value;
  25332     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
  25333     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
  25334             NK_BUTTON_LEFT, cursor, nk_true);
  25335     if (nk_input_is_mouse_hovering_rect(in, r))
  25336         *state = NK_WIDGET_STATE_HOVERED;
  25337 
  25338     if (in && left_mouse_down && left_mouse_click_in_cursor) {
  25339         if (left_mouse_down && left_mouse_click_in_cursor) {
  25340             float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w;
  25341             value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max);
  25342             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f;
  25343             *state |= NK_WIDGET_STATE_ACTIVE;
  25344         }
  25345     }
  25346     /* set progressbar widget state */
  25347     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
  25348         *state |= NK_WIDGET_STATE_ENTERED;
  25349     else if (nk_input_is_mouse_prev_hovering_rect(in, r))
  25350         *state |= NK_WIDGET_STATE_LEFT;
  25351     return value;
  25352 }
  25353 NK_LIB void
  25354 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
  25355     const struct nk_style_progress *style, const struct nk_rect *bounds,
  25356     const struct nk_rect *scursor, nk_size value, nk_size max)
  25357 {
  25358     const struct nk_style_item *background;
  25359     const struct nk_style_item *cursor;
  25360 
  25361     NK_UNUSED(max);
  25362     NK_UNUSED(value);
  25363 
  25364     /* select correct colors/images to draw */
  25365     if (state & NK_WIDGET_STATE_ACTIVED) {
  25366         background = &style->active;
  25367         cursor = &style->cursor_active;
  25368     } else if (state & NK_WIDGET_STATE_HOVER){
  25369         background = &style->hover;
  25370         cursor = &style->cursor_hover;
  25371     } else {
  25372         background = &style->normal;
  25373         cursor = &style->cursor_normal;
  25374     }
  25375 
  25376     /* draw background */
  25377     switch(background->type) {
  25378         case NK_STYLE_ITEM_IMAGE:
  25379             nk_draw_image(out, *bounds, &background->data.image, nk_white);
  25380             break;
  25381         case NK_STYLE_ITEM_NINE_SLICE:
  25382             nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white);
  25383             break;
  25384         case NK_STYLE_ITEM_COLOR:
  25385             nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  25386             nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
  25387             break;
  25388     }
  25389 
  25390     /* draw cursor */
  25391     switch(cursor->type) {
  25392         case NK_STYLE_ITEM_IMAGE:
  25393             nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
  25394             break;
  25395         case NK_STYLE_ITEM_NINE_SLICE:
  25396             nk_draw_nine_slice(out, *scursor, &cursor->data.slice, nk_white);
  25397             break;
  25398         case NK_STYLE_ITEM_COLOR:
  25399             nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
  25400             nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
  25401             break;
  25402     }
  25403 }
  25404 NK_LIB nk_size
  25405 nk_do_progress(nk_flags *state,
  25406     struct nk_command_buffer *out, struct nk_rect bounds,
  25407     nk_size value, nk_size max, nk_bool modifiable,
  25408     const struct nk_style_progress *style, struct nk_input *in)
  25409 {
  25410     float prog_scale;
  25411     nk_size prog_value;
  25412     struct nk_rect cursor;
  25413 
  25414     NK_ASSERT(style);
  25415     NK_ASSERT(out);
  25416     if (!out || !style) return 0;
  25417 
  25418     /* calculate progressbar cursor */
  25419     cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
  25420     cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
  25421     cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
  25422     prog_scale = (float)value / (float)max;
  25423 
  25424     /* update progressbar */
  25425     prog_value = NK_MIN(value, max);
  25426     prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable);
  25427     cursor.w = cursor.w * prog_scale;
  25428 
  25429     /* draw progressbar */
  25430     if (style->draw_begin) style->draw_begin(out, style->userdata);
  25431     nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
  25432     if (style->draw_end) style->draw_end(out, style->userdata);
  25433     return prog_value;
  25434 }
  25435 NK_API nk_bool
  25436 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, nk_bool is_modifyable)
  25437 {
  25438     struct nk_window *win;
  25439     struct nk_panel *layout;
  25440     const struct nk_style *style;
  25441     struct nk_input *in;
  25442 
  25443     struct nk_rect bounds;
  25444     enum nk_widget_layout_states state;
  25445     nk_size old_value;
  25446 
  25447     NK_ASSERT(ctx);
  25448     NK_ASSERT(cur);
  25449     NK_ASSERT(ctx->current);
  25450     NK_ASSERT(ctx->current->layout);
  25451     if (!ctx || !ctx->current || !ctx->current->layout || !cur)
  25452         return 0;
  25453 
  25454     win = ctx->current;
  25455     style = &ctx->style;
  25456     layout = win->layout;
  25457     state = nk_widget(&bounds, ctx);
  25458     if (!state) return 0;
  25459 
  25460     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  25461     old_value = *cur;
  25462     *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
  25463             *cur, max, is_modifyable, &style->progress, in);
  25464     return (*cur != old_value);
  25465 }
  25466 NK_API nk_size
  25467 nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, nk_bool modifyable)
  25468 {
  25469     nk_progress(ctx, &cur, max, modifyable);
  25470     return cur;
  25471 }
  25472 
  25473 
  25474 
  25475 
  25476 
  25477 /* ===============================================================
  25478  *
  25479  *                              SCROLLBAR
  25480  *
  25481  * ===============================================================*/
  25482 NK_LIB float
  25483 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
  25484     int has_scrolling, const struct nk_rect *scroll,
  25485     const struct nk_rect *cursor, const struct nk_rect *empty0,
  25486     const struct nk_rect *empty1, float scroll_offset,
  25487     float target, float scroll_step, enum nk_orientation o)
  25488 {
  25489     nk_flags ws = 0;
  25490     int left_mouse_down;
  25491     unsigned int left_mouse_clicked;
  25492     int left_mouse_click_in_cursor;
  25493     float scroll_delta;
  25494 
  25495     nk_widget_state_reset(state);
  25496     if (!in) return scroll_offset;
  25497 
  25498     left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
  25499     left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked;
  25500     left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
  25501         NK_BUTTON_LEFT, *cursor, nk_true);
  25502     if (nk_input_is_mouse_hovering_rect(in, *scroll))
  25503         *state = NK_WIDGET_STATE_HOVERED;
  25504 
  25505     scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
  25506     if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
  25507         /* update cursor by mouse dragging */
  25508         float pixel, delta;
  25509         *state = NK_WIDGET_STATE_ACTIVE;
  25510         if (o == NK_VERTICAL) {
  25511             float cursor_y;
  25512             pixel = in->mouse.delta.y;
  25513             delta = (pixel / scroll->h) * target;
  25514             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
  25515             cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
  25516             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
  25517         } else {
  25518             float cursor_x;
  25519             pixel = in->mouse.delta.x;
  25520             delta = (pixel / scroll->w) * target;
  25521             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
  25522             cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
  25523             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
  25524         }
  25525     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
  25526             nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
  25527         /* scroll page up by click on empty space or shortcut */
  25528         if (o == NK_VERTICAL)
  25529             scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
  25530         else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
  25531     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
  25532         nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
  25533         /* scroll page down by click on empty space or shortcut */
  25534         if (o == NK_VERTICAL)
  25535             scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
  25536         else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
  25537     } else if (has_scrolling) {
  25538         if ((scroll_delta < 0 || (scroll_delta > 0))) {
  25539             /* update cursor by mouse scrolling */
  25540             scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
  25541             if (o == NK_VERTICAL)
  25542                 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
  25543             else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
  25544         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
  25545             /* update cursor to the beginning  */
  25546             if (o == NK_VERTICAL) scroll_offset = 0;
  25547         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
  25548             /* update cursor to the end */
  25549             if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
  25550         }
  25551     }
  25552     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
  25553         *state |= NK_WIDGET_STATE_ENTERED;
  25554     else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
  25555         *state |= NK_WIDGET_STATE_LEFT;
  25556     return scroll_offset;
  25557 }
  25558 NK_LIB void
  25559 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
  25560     const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
  25561     const struct nk_rect *scroll)
  25562 {
  25563     const struct nk_style_item *background;
  25564     const struct nk_style_item *cursor;
  25565 
  25566     /* select correct colors/images to draw */
  25567     if (state & NK_WIDGET_STATE_ACTIVED) {
  25568         background = &style->active;
  25569         cursor = &style->cursor_active;
  25570     } else if (state & NK_WIDGET_STATE_HOVER) {
  25571         background = &style->hover;
  25572         cursor = &style->cursor_hover;
  25573     } else {
  25574         background = &style->normal;
  25575         cursor = &style->cursor_normal;
  25576     }
  25577 
  25578     /* draw background */
  25579     switch (background->type) {
  25580         case NK_STYLE_ITEM_IMAGE:
  25581             nk_draw_image(out, *bounds, &background->data.image, nk_white);
  25582             break;
  25583         case NK_STYLE_ITEM_NINE_SLICE:
  25584             nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white);
  25585             break;
  25586         case NK_STYLE_ITEM_COLOR:
  25587             nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  25588             nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
  25589             break;
  25590     }
  25591 
  25592     /* draw cursor */
  25593     switch (cursor->type) {
  25594         case NK_STYLE_ITEM_IMAGE:
  25595             nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
  25596             break;
  25597         case NK_STYLE_ITEM_NINE_SLICE:
  25598             nk_draw_nine_slice(out, *scroll, &cursor->data.slice, nk_white);
  25599             break;
  25600         case NK_STYLE_ITEM_COLOR:
  25601             nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
  25602             nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
  25603             break;
  25604     }
  25605 }
  25606 NK_LIB float
  25607 nk_do_scrollbarv(nk_flags *state,
  25608     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
  25609     float offset, float target, float step, float button_pixel_inc,
  25610     const struct nk_style_scrollbar *style, struct nk_input *in,
  25611     const struct nk_user_font *font)
  25612 {
  25613     struct nk_rect empty_north;
  25614     struct nk_rect empty_south;
  25615     struct nk_rect cursor;
  25616 
  25617     float scroll_step;
  25618     float scroll_offset;
  25619     float scroll_off;
  25620     float scroll_ratio;
  25621 
  25622     NK_ASSERT(out);
  25623     NK_ASSERT(style);
  25624     NK_ASSERT(state);
  25625     if (!out || !style) return 0;
  25626 
  25627     scroll.w = NK_MAX(scroll.w, 1);
  25628     scroll.h = NK_MAX(scroll.h, 0);
  25629     if (target <= scroll.h) return 0;
  25630 
  25631     /* optional scrollbar buttons */
  25632     if (style->show_buttons) {
  25633         nk_flags ws;
  25634         float scroll_h;
  25635         struct nk_rect button;
  25636 
  25637         button.x = scroll.x;
  25638         button.w = scroll.w;
  25639         button.h = scroll.w;
  25640 
  25641         scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
  25642         scroll_step = NK_MIN(step, button_pixel_inc);
  25643 
  25644         /* decrement button */
  25645         button.y = scroll.y;
  25646         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
  25647             NK_BUTTON_REPEATER, &style->dec_button, in, font))
  25648             offset = offset - scroll_step;
  25649 
  25650         /* increment button */
  25651         button.y = scroll.y + scroll.h - button.h;
  25652         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
  25653             NK_BUTTON_REPEATER, &style->inc_button, in, font))
  25654             offset = offset + scroll_step;
  25655 
  25656         scroll.y = scroll.y + button.h;
  25657         scroll.h = scroll_h;
  25658     }
  25659 
  25660     /* calculate scrollbar constants */
  25661     scroll_step = NK_MIN(step, scroll.h);
  25662     scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
  25663     scroll_ratio = scroll.h / target;
  25664     scroll_off = scroll_offset / target;
  25665 
  25666     /* calculate scrollbar cursor bounds */
  25667     cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
  25668     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
  25669     cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
  25670     cursor.x = scroll.x + style->border + style->padding.x;
  25671 
  25672     /* calculate empty space around cursor */
  25673     empty_north.x = scroll.x;
  25674     empty_north.y = scroll.y;
  25675     empty_north.w = scroll.w;
  25676     empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
  25677 
  25678     empty_south.x = scroll.x;
  25679     empty_south.y = cursor.y + cursor.h;
  25680     empty_south.w = scroll.w;
  25681     empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
  25682 
  25683     /* update scrollbar */
  25684     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
  25685         &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
  25686     scroll_off = scroll_offset / target;
  25687     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
  25688 
  25689     /* draw scrollbar */
  25690     if (style->draw_begin) style->draw_begin(out, style->userdata);
  25691     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
  25692     if (style->draw_end) style->draw_end(out, style->userdata);
  25693     return scroll_offset;
  25694 }
  25695 NK_LIB float
  25696 nk_do_scrollbarh(nk_flags *state,
  25697     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
  25698     float offset, float target, float step, float button_pixel_inc,
  25699     const struct nk_style_scrollbar *style, struct nk_input *in,
  25700     const struct nk_user_font *font)
  25701 {
  25702     struct nk_rect cursor;
  25703     struct nk_rect empty_west;
  25704     struct nk_rect empty_east;
  25705 
  25706     float scroll_step;
  25707     float scroll_offset;
  25708     float scroll_off;
  25709     float scroll_ratio;
  25710 
  25711     NK_ASSERT(out);
  25712     NK_ASSERT(style);
  25713     if (!out || !style) return 0;
  25714 
  25715     /* scrollbar background */
  25716     scroll.h = NK_MAX(scroll.h, 1);
  25717     scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
  25718     if (target <= scroll.w) return 0;
  25719 
  25720     /* optional scrollbar buttons */
  25721     if (style->show_buttons) {
  25722         nk_flags ws;
  25723         float scroll_w;
  25724         struct nk_rect button;
  25725         button.y = scroll.y;
  25726         button.w = scroll.h;
  25727         button.h = scroll.h;
  25728 
  25729         scroll_w = scroll.w - 2 * button.w;
  25730         scroll_step = NK_MIN(step, button_pixel_inc);
  25731 
  25732         /* decrement button */
  25733         button.x = scroll.x;
  25734         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
  25735             NK_BUTTON_REPEATER, &style->dec_button, in, font))
  25736             offset = offset - scroll_step;
  25737 
  25738         /* increment button */
  25739         button.x = scroll.x + scroll.w - button.w;
  25740         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
  25741             NK_BUTTON_REPEATER, &style->inc_button, in, font))
  25742             offset = offset + scroll_step;
  25743 
  25744         scroll.x = scroll.x + button.w;
  25745         scroll.w = scroll_w;
  25746     }
  25747 
  25748     /* calculate scrollbar constants */
  25749     scroll_step = NK_MIN(step, scroll.w);
  25750     scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
  25751     scroll_ratio = scroll.w / target;
  25752     scroll_off = scroll_offset / target;
  25753 
  25754     /* calculate cursor bounds */
  25755     cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
  25756     cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
  25757     cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
  25758     cursor.y = scroll.y + style->border + style->padding.y;
  25759 
  25760     /* calculate empty space around cursor */
  25761     empty_west.x = scroll.x;
  25762     empty_west.y = scroll.y;
  25763     empty_west.w = cursor.x - scroll.x;
  25764     empty_west.h = scroll.h;
  25765 
  25766     empty_east.x = cursor.x + cursor.w;
  25767     empty_east.y = scroll.y;
  25768     empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
  25769     empty_east.h = scroll.h;
  25770 
  25771     /* update scrollbar */
  25772     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
  25773         &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
  25774     scroll_off = scroll_offset / target;
  25775     cursor.x = scroll.x + (scroll_off * scroll.w);
  25776 
  25777     /* draw scrollbar */
  25778     if (style->draw_begin) style->draw_begin(out, style->userdata);
  25779     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
  25780     if (style->draw_end) style->draw_end(out, style->userdata);
  25781     return scroll_offset;
  25782 }
  25783 
  25784 
  25785 
  25786 
  25787 
  25788 /* ===============================================================
  25789  *
  25790  *                          TEXT EDITOR
  25791  *
  25792  * ===============================================================*/
  25793 /* stb_textedit.h - v1.8  - public domain - Sean Barrett */
  25794 struct nk_text_find {
  25795    float x,y;    /* position of n'th character */
  25796    float height; /* height of line */
  25797    int first_char, length; /* first char of row, and length */
  25798    int prev_first;  /*_ first char of previous row */
  25799 };
  25800 
  25801 struct nk_text_edit_row {
  25802    float x0,x1;
  25803    /* starting x location, end x location (allows for align=right, etc) */
  25804    float baseline_y_delta;
  25805    /* position of baseline relative to previous row's baseline*/
  25806    float ymin,ymax;
  25807    /* height of row above and below baseline */
  25808    int num_chars;
  25809 };
  25810 
  25811 /* forward declarations */
  25812 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
  25813 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
  25814 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
  25815 #define NK_TEXT_HAS_SELECTION(s)   ((s)->select_start != (s)->select_end)
  25816 
  25817 NK_INTERN float
  25818 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
  25819     const struct nk_user_font *font)
  25820 {
  25821     int len = 0;
  25822     nk_rune unicode = 0;
  25823     const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
  25824     return font->width(font->userdata, font->height, str, len);
  25825 }
  25826 NK_INTERN void
  25827 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
  25828     int line_start_id, float row_height, const struct nk_user_font *font)
  25829 {
  25830     int l;
  25831     int glyphs = 0;
  25832     nk_rune unicode;
  25833     const char *remaining;
  25834     int len = nk_str_len_char(&edit->string);
  25835     const char *end = nk_str_get_const(&edit->string) + len;
  25836     const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
  25837     const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
  25838         text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
  25839 
  25840     r->x0 = 0.0f;
  25841     r->x1 = size.x;
  25842     r->baseline_y_delta = size.y;
  25843     r->ymin = 0.0f;
  25844     r->ymax = size.y;
  25845     r->num_chars = glyphs;
  25846 }
  25847 NK_INTERN int
  25848 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
  25849     const struct nk_user_font *font, float row_height)
  25850 {
  25851     struct nk_text_edit_row r;
  25852     int n = edit->string.len;
  25853     float base_y = 0, prev_x;
  25854     int i=0, k;
  25855 
  25856     r.x0 = r.x1 = 0;
  25857     r.ymin = r.ymax = 0;
  25858     r.num_chars = 0;
  25859 
  25860     /* search rows to find one that straddles 'y' */
  25861     while (i < n) {
  25862         nk_textedit_layout_row(&r, edit, i, row_height, font);
  25863         if (r.num_chars <= 0)
  25864             return n;
  25865 
  25866         if (i==0 && y < base_y + r.ymin)
  25867             return 0;
  25868 
  25869         if (y < base_y + r.ymax)
  25870             break;
  25871 
  25872         i += r.num_chars;
  25873         base_y += r.baseline_y_delta;
  25874     }
  25875 
  25876     /* below all text, return 'after' last character */
  25877     if (i >= n)
  25878         return n;
  25879 
  25880     /* check if it's before the beginning of the line */
  25881     if (x < r.x0)
  25882         return i;
  25883 
  25884     /* check if it's before the end of the line */
  25885     if (x < r.x1) {
  25886         /* search characters in row for one that straddles 'x' */
  25887         k = i;
  25888         prev_x = r.x0;
  25889         for (i=0; i < r.num_chars; ++i) {
  25890             float w = nk_textedit_get_width(edit, k, i, font);
  25891             if (x < prev_x+w) {
  25892                 if (x < prev_x+w/2)
  25893                     return k+i;
  25894                 else return k+i+1;
  25895             }
  25896             prev_x += w;
  25897         }
  25898         /* shouldn't happen, but if it does, fall through to end-of-line case */
  25899     }
  25900 
  25901     /* if the last character is a newline, return that.
  25902      * otherwise return 'after' the last character */
  25903     if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
  25904         return i+r.num_chars-1;
  25905     else return i+r.num_chars;
  25906 }
  25907 NK_LIB void
  25908 nk_textedit_click(struct nk_text_edit *state, float x, float y,
  25909     const struct nk_user_font *font, float row_height)
  25910 {
  25911     /* API click: on mouse down, move the cursor to the clicked location,
  25912      * and reset the selection */
  25913     state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
  25914     state->select_start = state->cursor;
  25915     state->select_end = state->cursor;
  25916     state->has_preferred_x = 0;
  25917 }
  25918 NK_LIB void
  25919 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
  25920     const struct nk_user_font *font, float row_height)
  25921 {
  25922     /* API drag: on mouse drag, move the cursor and selection endpoint
  25923      * to the clicked location */
  25924     int p = nk_textedit_locate_coord(state, x, y, font, row_height);
  25925     if (state->select_start == state->select_end)
  25926         state->select_start = state->cursor;
  25927     state->cursor = state->select_end = p;
  25928 }
  25929 NK_INTERN void
  25930 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
  25931     int n, int single_line, const struct nk_user_font *font, float row_height)
  25932 {
  25933     /* find the x/y location of a character, and remember info about the previous
  25934      * row in case we get a move-up event (for page up, we'll have to rescan) */
  25935     struct nk_text_edit_row r;
  25936     int prev_start = 0;
  25937     int z = state->string.len;
  25938     int i=0, first;
  25939 
  25940     nk_zero_struct(r);
  25941     if (n == z) {
  25942         /* if it's at the end, then find the last line -- simpler than trying to
  25943         explicitly handle this case in the regular code */
  25944         nk_textedit_layout_row(&r, state, 0, row_height, font);
  25945         if (single_line) {
  25946             find->first_char = 0;
  25947             find->length = z;
  25948         } else {
  25949             while (i < z) {
  25950                 prev_start = i;
  25951                 i += r.num_chars;
  25952                 nk_textedit_layout_row(&r, state, i, row_height, font);
  25953             }
  25954 
  25955             find->first_char = i;
  25956             find->length = r.num_chars;
  25957         }
  25958         find->x = r.x1;
  25959         find->y = r.ymin;
  25960         find->height = r.ymax - r.ymin;
  25961         find->prev_first = prev_start;
  25962         return;
  25963     }
  25964 
  25965     /* search rows to find the one that straddles character n */
  25966     find->y = 0;
  25967 
  25968     for(;;) {
  25969         nk_textedit_layout_row(&r, state, i, row_height, font);
  25970         if (n < i + r.num_chars) break;
  25971         prev_start = i;
  25972         i += r.num_chars;
  25973         find->y += r.baseline_y_delta;
  25974     }
  25975 
  25976     find->first_char = first = i;
  25977     find->length = r.num_chars;
  25978     find->height = r.ymax - r.ymin;
  25979     find->prev_first = prev_start;
  25980 
  25981     /* now scan to find xpos */
  25982     find->x = r.x0;
  25983     for (i=0; first+i < n; ++i)
  25984         find->x += nk_textedit_get_width(state, first, i, font);
  25985 }
  25986 NK_INTERN void
  25987 nk_textedit_clamp(struct nk_text_edit *state)
  25988 {
  25989     /* make the selection/cursor state valid if client altered the string */
  25990     int n = state->string.len;
  25991     if (NK_TEXT_HAS_SELECTION(state)) {
  25992         if (state->select_start > n) state->select_start = n;
  25993         if (state->select_end   > n) state->select_end = n;
  25994         /* if clamping forced them to be equal, move the cursor to match */
  25995         if (state->select_start == state->select_end)
  25996             state->cursor = state->select_start;
  25997     }
  25998     if (state->cursor > n) state->cursor = n;
  25999 }
  26000 NK_API void
  26001 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
  26002 {
  26003     /* delete characters while updating undo */
  26004     nk_textedit_makeundo_delete(state, where, len);
  26005     nk_str_delete_runes(&state->string, where, len);
  26006     state->has_preferred_x = 0;
  26007 }
  26008 NK_API void
  26009 nk_textedit_delete_selection(struct nk_text_edit *state)
  26010 {
  26011     /* delete the section */
  26012     nk_textedit_clamp(state);
  26013     if (NK_TEXT_HAS_SELECTION(state)) {
  26014         if (state->select_start < state->select_end) {
  26015             nk_textedit_delete(state, state->select_start,
  26016                 state->select_end - state->select_start);
  26017             state->select_end = state->cursor = state->select_start;
  26018         } else {
  26019             nk_textedit_delete(state, state->select_end,
  26020                 state->select_start - state->select_end);
  26021             state->select_start = state->cursor = state->select_end;
  26022         }
  26023         state->has_preferred_x = 0;
  26024     }
  26025 }
  26026 NK_INTERN void
  26027 nk_textedit_sortselection(struct nk_text_edit *state)
  26028 {
  26029     /* canonicalize the selection so start <= end */
  26030     if (state->select_end < state->select_start) {
  26031         int temp = state->select_end;
  26032         state->select_end = state->select_start;
  26033         state->select_start = temp;
  26034     }
  26035 }
  26036 NK_INTERN void
  26037 nk_textedit_move_to_first(struct nk_text_edit *state)
  26038 {
  26039     /* move cursor to first character of selection */
  26040     if (NK_TEXT_HAS_SELECTION(state)) {
  26041         nk_textedit_sortselection(state);
  26042         state->cursor = state->select_start;
  26043         state->select_end = state->select_start;
  26044         state->has_preferred_x = 0;
  26045     }
  26046 }
  26047 NK_INTERN void
  26048 nk_textedit_move_to_last(struct nk_text_edit *state)
  26049 {
  26050     /* move cursor to last character of selection */
  26051     if (NK_TEXT_HAS_SELECTION(state)) {
  26052         nk_textedit_sortselection(state);
  26053         nk_textedit_clamp(state);
  26054         state->cursor = state->select_end;
  26055         state->select_start = state->select_end;
  26056         state->has_preferred_x = 0;
  26057     }
  26058 }
  26059 NK_INTERN int
  26060 nk_is_word_boundary( struct nk_text_edit *state, int idx)
  26061 {
  26062     int len;
  26063     nk_rune c;
  26064     if (idx <= 0) return 1;
  26065     if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
  26066     return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
  26067             c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
  26068             c == '|');
  26069 }
  26070 NK_INTERN int
  26071 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
  26072 {
  26073    int c = state->cursor - 1;
  26074    while( c >= 0 && !nk_is_word_boundary(state, c))
  26075       --c;
  26076 
  26077    if( c < 0 )
  26078       c = 0;
  26079 
  26080    return c;
  26081 }
  26082 NK_INTERN int
  26083 nk_textedit_move_to_word_next(struct nk_text_edit *state)
  26084 {
  26085    const int len = state->string.len;
  26086    int c = state->cursor+1;
  26087    while( c < len && !nk_is_word_boundary(state, c))
  26088       ++c;
  26089 
  26090    if( c > len )
  26091       c = len;
  26092 
  26093    return c;
  26094 }
  26095 NK_INTERN void
  26096 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
  26097 {
  26098     /* update selection and cursor to match each other */
  26099     if (!NK_TEXT_HAS_SELECTION(state))
  26100         state->select_start = state->select_end = state->cursor;
  26101     else state->cursor = state->select_end;
  26102 }
  26103 NK_API nk_bool
  26104 nk_textedit_cut(struct nk_text_edit *state)
  26105 {
  26106     /* API cut: delete selection */
  26107     if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  26108         return 0;
  26109     if (NK_TEXT_HAS_SELECTION(state)) {
  26110         nk_textedit_delete_selection(state); /* implicitly clamps */
  26111         state->has_preferred_x = 0;
  26112         return 1;
  26113     }
  26114    return 0;
  26115 }
  26116 NK_API nk_bool
  26117 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
  26118 {
  26119     /* API paste: replace existing selection with passed-in text */
  26120     int glyphs;
  26121     const char *text = (const char *) ctext;
  26122     if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
  26123 
  26124     /* if there's a selection, the paste should delete it */
  26125     nk_textedit_clamp(state);
  26126     nk_textedit_delete_selection(state);
  26127 
  26128     /* try to insert the characters */
  26129     glyphs = nk_utf_len(ctext, len);
  26130     if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
  26131         nk_textedit_makeundo_insert(state, state->cursor, glyphs);
  26132         state->cursor += len;
  26133         state->has_preferred_x = 0;
  26134         return 1;
  26135     }
  26136     /* remove the undo since we didn't actually insert the characters */
  26137     if (state->undo.undo_point)
  26138         --state->undo.undo_point;
  26139     return 0;
  26140 }
  26141 NK_API void
  26142 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
  26143 {
  26144     nk_rune unicode;
  26145     int glyph_len;
  26146     int text_len = 0;
  26147 
  26148     NK_ASSERT(state);
  26149     NK_ASSERT(text);
  26150     if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
  26151 
  26152     glyph_len = nk_utf_decode(text, &unicode, total_len);
  26153     while ((text_len < total_len) && glyph_len)
  26154     {
  26155         /* don't insert a backward delete, just process the event */
  26156         if (unicode == 127) goto next;
  26157         /* can't add newline in single-line mode */
  26158         if (unicode == '\n' && state->single_line) goto next;
  26159         /* filter incoming text */
  26160         if (state->filter && !state->filter(state, unicode)) goto next;
  26161 
  26162         if (!NK_TEXT_HAS_SELECTION(state) &&
  26163             state->cursor < state->string.len)
  26164         {
  26165             if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
  26166                 nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
  26167                 nk_str_delete_runes(&state->string, state->cursor, 1);
  26168             }
  26169             if (nk_str_insert_text_utf8(&state->string, state->cursor,
  26170                                         text+text_len, 1))
  26171             {
  26172                 ++state->cursor;
  26173                 state->has_preferred_x = 0;
  26174             }
  26175         } else {
  26176             nk_textedit_delete_selection(state); /* implicitly clamps */
  26177             if (nk_str_insert_text_utf8(&state->string, state->cursor,
  26178                                         text+text_len, 1))
  26179             {
  26180                 nk_textedit_makeundo_insert(state, state->cursor, 1);
  26181                 state->cursor = NK_MIN(state->cursor + 1, state->string.len);
  26182                 state->has_preferred_x = 0;
  26183             }
  26184         }
  26185         next:
  26186         text_len += glyph_len;
  26187         glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
  26188     }
  26189 }
  26190 NK_LIB void
  26191 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
  26192     const struct nk_user_font *font, float row_height)
  26193 {
  26194 retry:
  26195     switch (key)
  26196     {
  26197     case NK_KEY_NONE:
  26198     case NK_KEY_CTRL:
  26199     case NK_KEY_ENTER:
  26200     case NK_KEY_SHIFT:
  26201     case NK_KEY_TAB:
  26202     case NK_KEY_COPY:
  26203     case NK_KEY_CUT:
  26204     case NK_KEY_PASTE:
  26205     case NK_KEY_MAX:
  26206     default: break;
  26207     case NK_KEY_TEXT_UNDO:
  26208          nk_textedit_undo(state);
  26209          state->has_preferred_x = 0;
  26210          break;
  26211 
  26212     case NK_KEY_TEXT_REDO:
  26213         nk_textedit_redo(state);
  26214         state->has_preferred_x = 0;
  26215         break;
  26216 
  26217     case NK_KEY_TEXT_SELECT_ALL:
  26218         nk_textedit_select_all(state);
  26219         state->has_preferred_x = 0;
  26220         break;
  26221 
  26222     case NK_KEY_TEXT_INSERT_MODE:
  26223         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  26224             state->mode = NK_TEXT_EDIT_MODE_INSERT;
  26225         break;
  26226     case NK_KEY_TEXT_REPLACE_MODE:
  26227         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  26228             state->mode = NK_TEXT_EDIT_MODE_REPLACE;
  26229         break;
  26230     case NK_KEY_TEXT_RESET_MODE:
  26231         if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
  26232             state->mode == NK_TEXT_EDIT_MODE_REPLACE)
  26233             state->mode = NK_TEXT_EDIT_MODE_VIEW;
  26234         break;
  26235 
  26236     case NK_KEY_LEFT:
  26237         if (shift_mod) {
  26238             nk_textedit_clamp(state);
  26239             nk_textedit_prep_selection_at_cursor(state);
  26240             /* move selection left */
  26241             if (state->select_end > 0)
  26242                 --state->select_end;
  26243             state->cursor = state->select_end;
  26244             state->has_preferred_x = 0;
  26245         } else {
  26246             /* if currently there's a selection,
  26247              * move cursor to start of selection */
  26248             if (NK_TEXT_HAS_SELECTION(state))
  26249                 nk_textedit_move_to_first(state);
  26250             else if (state->cursor > 0)
  26251                --state->cursor;
  26252             state->has_preferred_x = 0;
  26253         } break;
  26254 
  26255     case NK_KEY_RIGHT:
  26256         if (shift_mod) {
  26257             nk_textedit_prep_selection_at_cursor(state);
  26258             /* move selection right */
  26259             ++state->select_end;
  26260             nk_textedit_clamp(state);
  26261             state->cursor = state->select_end;
  26262             state->has_preferred_x = 0;
  26263         } else {
  26264             /* if currently there's a selection,
  26265              * move cursor to end of selection */
  26266             if (NK_TEXT_HAS_SELECTION(state))
  26267                 nk_textedit_move_to_last(state);
  26268             else ++state->cursor;
  26269             nk_textedit_clamp(state);
  26270             state->has_preferred_x = 0;
  26271         } break;
  26272 
  26273     case NK_KEY_TEXT_WORD_LEFT:
  26274         if (shift_mod) {
  26275             if( !NK_TEXT_HAS_SELECTION( state ) )
  26276             nk_textedit_prep_selection_at_cursor(state);
  26277             state->cursor = nk_textedit_move_to_word_previous(state);
  26278             state->select_end = state->cursor;
  26279             nk_textedit_clamp(state );
  26280         } else {
  26281             if (NK_TEXT_HAS_SELECTION(state))
  26282                 nk_textedit_move_to_first(state);
  26283             else {
  26284                 state->cursor = nk_textedit_move_to_word_previous(state);
  26285                 nk_textedit_clamp(state );
  26286             }
  26287         } break;
  26288 
  26289     case NK_KEY_TEXT_WORD_RIGHT:
  26290         if (shift_mod) {
  26291             if( !NK_TEXT_HAS_SELECTION( state ) )
  26292                 nk_textedit_prep_selection_at_cursor(state);
  26293             state->cursor = nk_textedit_move_to_word_next(state);
  26294             state->select_end = state->cursor;
  26295             nk_textedit_clamp(state);
  26296         } else {
  26297             if (NK_TEXT_HAS_SELECTION(state))
  26298                 nk_textedit_move_to_last(state);
  26299             else {
  26300                 state->cursor = nk_textedit_move_to_word_next(state);
  26301                 nk_textedit_clamp(state );
  26302             }
  26303         } break;
  26304 
  26305     case NK_KEY_DOWN: {
  26306         struct nk_text_find find;
  26307         struct nk_text_edit_row row;
  26308         int i, sel = shift_mod;
  26309 
  26310         if (state->single_line) {
  26311             /* on windows, up&down in single-line behave like left&right */
  26312             key = NK_KEY_RIGHT;
  26313             goto retry;
  26314         }
  26315 
  26316         if (sel)
  26317             nk_textedit_prep_selection_at_cursor(state);
  26318         else if (NK_TEXT_HAS_SELECTION(state))
  26319             nk_textedit_move_to_last(state);
  26320 
  26321         /* compute current position of cursor point */
  26322         nk_textedit_clamp(state);
  26323         nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  26324             font, row_height);
  26325 
  26326         /* now find character position down a row */
  26327         if (find.length)
  26328         {
  26329             float x;
  26330             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
  26331             int start = find.first_char + find.length;
  26332 
  26333             state->cursor = start;
  26334             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
  26335             x = row.x0;
  26336 
  26337             for (i=0; i < row.num_chars && x < row.x1; ++i) {
  26338                 float dx = nk_textedit_get_width(state, start, i, font);
  26339                 x += dx;
  26340                 if (x > goal_x)
  26341                     break;
  26342                 ++state->cursor;
  26343             }
  26344             nk_textedit_clamp(state);
  26345 
  26346             state->has_preferred_x = 1;
  26347             state->preferred_x = goal_x;
  26348             if (sel)
  26349                 state->select_end = state->cursor;
  26350         }
  26351     } break;
  26352 
  26353     case NK_KEY_UP: {
  26354         struct nk_text_find find;
  26355         struct nk_text_edit_row row;
  26356         int i, sel = shift_mod;
  26357 
  26358         if (state->single_line) {
  26359             /* on windows, up&down become left&right */
  26360             key = NK_KEY_LEFT;
  26361             goto retry;
  26362         }
  26363 
  26364         if (sel)
  26365             nk_textedit_prep_selection_at_cursor(state);
  26366         else if (NK_TEXT_HAS_SELECTION(state))
  26367             nk_textedit_move_to_first(state);
  26368 
  26369          /* compute current position of cursor point */
  26370          nk_textedit_clamp(state);
  26371          nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  26372                 font, row_height);
  26373 
  26374          /* can only go up if there's a previous row */
  26375          if (find.prev_first != find.first_char) {
  26376             /* now find character position up a row */
  26377             float x;
  26378             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
  26379 
  26380             state->cursor = find.prev_first;
  26381             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
  26382             x = row.x0;
  26383 
  26384             for (i=0; i < row.num_chars && x < row.x1; ++i) {
  26385                 float dx = nk_textedit_get_width(state, find.prev_first, i, font);
  26386                 x += dx;
  26387                 if (x > goal_x)
  26388                     break;
  26389                 ++state->cursor;
  26390             }
  26391             nk_textedit_clamp(state);
  26392 
  26393             state->has_preferred_x = 1;
  26394             state->preferred_x = goal_x;
  26395             if (sel) state->select_end = state->cursor;
  26396          }
  26397       } break;
  26398 
  26399     case NK_KEY_DEL:
  26400         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  26401             break;
  26402         if (NK_TEXT_HAS_SELECTION(state))
  26403             nk_textedit_delete_selection(state);
  26404         else {
  26405             int n = state->string.len;
  26406             if (state->cursor < n)
  26407                 nk_textedit_delete(state, state->cursor, 1);
  26408          }
  26409          state->has_preferred_x = 0;
  26410          break;
  26411 
  26412     case NK_KEY_BACKSPACE:
  26413         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  26414             break;
  26415         if (NK_TEXT_HAS_SELECTION(state))
  26416             nk_textedit_delete_selection(state);
  26417         else {
  26418             nk_textedit_clamp(state);
  26419             if (state->cursor > 0) {
  26420                 nk_textedit_delete(state, state->cursor-1, 1);
  26421                 --state->cursor;
  26422             }
  26423          }
  26424          state->has_preferred_x = 0;
  26425          break;
  26426 
  26427     case NK_KEY_TEXT_START:
  26428          if (shift_mod) {
  26429             nk_textedit_prep_selection_at_cursor(state);
  26430             state->cursor = state->select_end = 0;
  26431             state->has_preferred_x = 0;
  26432          } else {
  26433             state->cursor = state->select_start = state->select_end = 0;
  26434             state->has_preferred_x = 0;
  26435          }
  26436          break;
  26437 
  26438     case NK_KEY_TEXT_END:
  26439          if (shift_mod) {
  26440             nk_textedit_prep_selection_at_cursor(state);
  26441             state->cursor = state->select_end = state->string.len;
  26442             state->has_preferred_x = 0;
  26443          } else {
  26444             state->cursor = state->string.len;
  26445             state->select_start = state->select_end = 0;
  26446             state->has_preferred_x = 0;
  26447          }
  26448          break;
  26449 
  26450     case NK_KEY_TEXT_LINE_START: {
  26451         if (shift_mod) {
  26452             struct nk_text_find find;
  26453            nk_textedit_clamp(state);
  26454             nk_textedit_prep_selection_at_cursor(state);
  26455             if (state->string.len && state->cursor == state->string.len)
  26456                 --state->cursor;
  26457             nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
  26458                 font, row_height);
  26459             state->cursor = state->select_end = find.first_char;
  26460             state->has_preferred_x = 0;
  26461         } else {
  26462             struct nk_text_find find;
  26463             if (state->string.len && state->cursor == state->string.len)
  26464                 --state->cursor;
  26465             nk_textedit_clamp(state);
  26466             nk_textedit_move_to_first(state);
  26467             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  26468                 font, row_height);
  26469             state->cursor = find.first_char;
  26470             state->has_preferred_x = 0;
  26471         }
  26472       } break;
  26473 
  26474     case NK_KEY_TEXT_LINE_END: {
  26475         if (shift_mod) {
  26476             struct nk_text_find find;
  26477             nk_textedit_clamp(state);
  26478             nk_textedit_prep_selection_at_cursor(state);
  26479             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  26480                 font, row_height);
  26481             state->has_preferred_x = 0;
  26482             state->cursor = find.first_char + find.length;
  26483             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
  26484                 --state->cursor;
  26485             state->select_end = state->cursor;
  26486         } else {
  26487             struct nk_text_find find;
  26488             nk_textedit_clamp(state);
  26489             nk_textedit_move_to_first(state);
  26490             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  26491                 font, row_height);
  26492 
  26493             state->has_preferred_x = 0;
  26494             state->cursor = find.first_char + find.length;
  26495             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
  26496                 --state->cursor;
  26497         }} break;
  26498     }
  26499 }
  26500 NK_INTERN void
  26501 nk_textedit_flush_redo(struct nk_text_undo_state *state)
  26502 {
  26503     state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
  26504     state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
  26505 }
  26506 NK_INTERN void
  26507 nk_textedit_discard_undo(struct nk_text_undo_state *state)
  26508 {
  26509     /* discard the oldest entry in the undo list */
  26510     if (state->undo_point > 0) {
  26511         /* if the 0th undo state has characters, clean those up */
  26512         if (state->undo_rec[0].char_storage >= 0) {
  26513             int n = state->undo_rec[0].insert_length, i;
  26514             /* delete n characters from all other records */
  26515             state->undo_char_point = (short)(state->undo_char_point - n);
  26516             NK_MEMCPY(state->undo_char, state->undo_char + n,
  26517                 (nk_size)state->undo_char_point*sizeof(nk_rune));
  26518             for (i=0; i < state->undo_point; ++i) {
  26519                 if (state->undo_rec[i].char_storage >= 0)
  26520                 state->undo_rec[i].char_storage = (short)
  26521                     (state->undo_rec[i].char_storage - n);
  26522             }
  26523         }
  26524         --state->undo_point;
  26525         NK_MEMCPY(state->undo_rec, state->undo_rec+1,
  26526             (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
  26527     }
  26528 }
  26529 NK_INTERN void
  26530 nk_textedit_discard_redo(struct nk_text_undo_state *state)
  26531 {
  26532 /*  discard the oldest entry in the redo list--it's bad if this
  26533     ever happens, but because undo & redo have to store the actual
  26534     characters in different cases, the redo character buffer can
  26535     fill up even though the undo buffer didn't */
  26536     nk_size num;
  26537     int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
  26538     if (state->redo_point <= k) {
  26539         /* if the k'th undo state has characters, clean those up */
  26540         if (state->undo_rec[k].char_storage >= 0) {
  26541             int n = state->undo_rec[k].insert_length, i;
  26542             /* delete n characters from all other records */
  26543             state->redo_char_point = (short)(state->redo_char_point + n);
  26544             num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point);
  26545             NK_MEMCPY(state->undo_char + state->redo_char_point,
  26546                 state->undo_char + state->redo_char_point-n, num * sizeof(char));
  26547             for (i = state->redo_point; i < k; ++i) {
  26548                 if (state->undo_rec[i].char_storage >= 0) {
  26549                     state->undo_rec[i].char_storage = (short)
  26550                         (state->undo_rec[i].char_storage + n);
  26551                 }
  26552             }
  26553         }
  26554         ++state->redo_point;
  26555         num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
  26556         if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
  26557             state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
  26558     }
  26559 }
  26560 NK_INTERN struct nk_text_undo_record*
  26561 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
  26562 {
  26563     /* any time we create a new undo record, we discard redo*/
  26564     nk_textedit_flush_redo(state);
  26565 
  26566     /* if we have no free records, we have to make room,
  26567      * by sliding the existing records down */
  26568     if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
  26569         nk_textedit_discard_undo(state);
  26570 
  26571     /* if the characters to store won't possibly fit in the buffer,
  26572      * we can't undo */
  26573     if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
  26574         state->undo_point = 0;
  26575         state->undo_char_point = 0;
  26576         return 0;
  26577     }
  26578 
  26579     /* if we don't have enough free characters in the buffer,
  26580      * we have to make room */
  26581     while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
  26582         nk_textedit_discard_undo(state);
  26583     return &state->undo_rec[state->undo_point++];
  26584 }
  26585 NK_INTERN nk_rune*
  26586 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
  26587     int insert_len, int delete_len)
  26588 {
  26589     struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
  26590     if (r == 0)
  26591         return 0;
  26592 
  26593     r->where = pos;
  26594     r->insert_length = (short) insert_len;
  26595     r->delete_length = (short) delete_len;
  26596 
  26597     if (insert_len == 0) {
  26598         r->char_storage = -1;
  26599         return 0;
  26600     } else {
  26601         r->char_storage = state->undo_char_point;
  26602         state->undo_char_point = (short)(state->undo_char_point +  insert_len);
  26603         return &state->undo_char[r->char_storage];
  26604     }
  26605 }
  26606 NK_API void
  26607 nk_textedit_undo(struct nk_text_edit *state)
  26608 {
  26609     struct nk_text_undo_state *s = &state->undo;
  26610     struct nk_text_undo_record u, *r;
  26611     if (s->undo_point == 0)
  26612         return;
  26613 
  26614     /* we need to do two things: apply the undo record, and create a redo record */
  26615     u = s->undo_rec[s->undo_point-1];
  26616     r = &s->undo_rec[s->redo_point-1];
  26617     r->char_storage = -1;
  26618 
  26619     r->insert_length = u.delete_length;
  26620     r->delete_length = u.insert_length;
  26621     r->where = u.where;
  26622 
  26623     if (u.delete_length)
  26624     {
  26625        /*   if the undo record says to delete characters, then the redo record will
  26626             need to re-insert the characters that get deleted, so we need to store
  26627             them.
  26628             there are three cases:
  26629                 - there's enough room to store the characters
  26630                 - characters stored for *redoing* don't leave room for redo
  26631                 - characters stored for *undoing* don't leave room for redo
  26632             if the last is true, we have to bail */
  26633         if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
  26634             /* the undo records take up too much character space; there's no space
  26635             * to store the redo characters */
  26636             r->insert_length = 0;
  26637         } else {
  26638             int i;
  26639             /* there's definitely room to store the characters eventually */
  26640             while (s->undo_char_point + u.delete_length > s->redo_char_point) {
  26641                 /* there's currently not enough room, so discard a redo record */
  26642                 nk_textedit_discard_redo(s);
  26643                 /* should never happen: */
  26644                 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
  26645                     return;
  26646             }
  26647 
  26648             r = &s->undo_rec[s->redo_point-1];
  26649             r->char_storage = (short)(s->redo_char_point - u.delete_length);
  26650             s->redo_char_point = (short)(s->redo_char_point -  u.delete_length);
  26651 
  26652             /* now save the characters */
  26653             for (i=0; i < u.delete_length; ++i)
  26654                 s->undo_char[r->char_storage + i] =
  26655                     nk_str_rune_at(&state->string, u.where + i);
  26656         }
  26657         /* now we can carry out the deletion */
  26658         nk_str_delete_runes(&state->string, u.where, u.delete_length);
  26659     }
  26660 
  26661     /* check type of recorded action: */
  26662     if (u.insert_length) {
  26663         /* easy case: was a deletion, so we need to insert n characters */
  26664         nk_str_insert_text_runes(&state->string, u.where,
  26665             &s->undo_char[u.char_storage], u.insert_length);
  26666         s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
  26667     }
  26668     state->cursor = (short)(u.where + u.insert_length);
  26669 
  26670     s->undo_point--;
  26671     s->redo_point--;
  26672 }
  26673 NK_API void
  26674 nk_textedit_redo(struct nk_text_edit *state)
  26675 {
  26676     struct nk_text_undo_state *s = &state->undo;
  26677     struct nk_text_undo_record *u, r;
  26678     if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
  26679         return;
  26680 
  26681     /* we need to do two things: apply the redo record, and create an undo record */
  26682     u = &s->undo_rec[s->undo_point];
  26683     r = s->undo_rec[s->redo_point];
  26684 
  26685     /* we KNOW there must be room for the undo record, because the redo record
  26686     was derived from an undo record */
  26687     u->delete_length = r.insert_length;
  26688     u->insert_length = r.delete_length;
  26689     u->where = r.where;
  26690     u->char_storage = -1;
  26691 
  26692     if (r.delete_length) {
  26693         /* the redo record requires us to delete characters, so the undo record
  26694         needs to store the characters */
  26695         if (s->undo_char_point + u->insert_length > s->redo_char_point) {
  26696             u->insert_length = 0;
  26697             u->delete_length = 0;
  26698         } else {
  26699             int i;
  26700             u->char_storage = s->undo_char_point;
  26701             s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
  26702 
  26703             /* now save the characters */
  26704             for (i=0; i < u->insert_length; ++i) {
  26705                 s->undo_char[u->char_storage + i] =
  26706                     nk_str_rune_at(&state->string, u->where + i);
  26707             }
  26708         }
  26709         nk_str_delete_runes(&state->string, r.where, r.delete_length);
  26710     }
  26711 
  26712     if (r.insert_length) {
  26713         /* easy case: need to insert n characters */
  26714         nk_str_insert_text_runes(&state->string, r.where,
  26715             &s->undo_char[r.char_storage], r.insert_length);
  26716     }
  26717     state->cursor = r.where + r.insert_length;
  26718 
  26719     s->undo_point++;
  26720     s->redo_point++;
  26721 }
  26722 NK_INTERN void
  26723 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
  26724 {
  26725     nk_textedit_createundo(&state->undo, where, 0, length);
  26726 }
  26727 NK_INTERN void
  26728 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
  26729 {
  26730     int i;
  26731     nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
  26732     if (p) {
  26733         for (i=0; i < length; ++i)
  26734             p[i] = nk_str_rune_at(&state->string, where+i);
  26735     }
  26736 }
  26737 NK_INTERN void
  26738 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
  26739     int old_length, int new_length)
  26740 {
  26741     int i;
  26742     nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
  26743     if (p) {
  26744         for (i=0; i < old_length; ++i)
  26745             p[i] = nk_str_rune_at(&state->string, where+i);
  26746     }
  26747 }
  26748 NK_LIB void
  26749 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
  26750     nk_plugin_filter filter)
  26751 {
  26752     /* reset the state to default */
  26753    state->undo.undo_point = 0;
  26754    state->undo.undo_char_point = 0;
  26755    state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
  26756    state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
  26757    state->select_end = state->select_start = 0;
  26758    state->cursor = 0;
  26759    state->has_preferred_x = 0;
  26760    state->preferred_x = 0;
  26761    state->cursor_at_end_of_line = 0;
  26762    state->initialized = 1;
  26763    state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
  26764    state->mode = NK_TEXT_EDIT_MODE_VIEW;
  26765    state->filter = filter;
  26766    state->scrollbar = nk_vec2(0,0);
  26767 }
  26768 NK_API void
  26769 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
  26770 {
  26771     NK_ASSERT(state);
  26772     NK_ASSERT(memory);
  26773     if (!state || !memory || !size) return;
  26774     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
  26775     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
  26776     nk_str_init_fixed(&state->string, memory, size);
  26777 }
  26778 NK_API void
  26779 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
  26780 {
  26781     NK_ASSERT(state);
  26782     NK_ASSERT(alloc);
  26783     if (!state || !alloc) return;
  26784     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
  26785     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
  26786     nk_str_init(&state->string, alloc, size);
  26787 }
  26788 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
  26789 NK_API void
  26790 nk_textedit_init_default(struct nk_text_edit *state)
  26791 {
  26792     NK_ASSERT(state);
  26793     if (!state) return;
  26794     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
  26795     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
  26796     nk_str_init_default(&state->string);
  26797 }
  26798 #endif
  26799 NK_API void
  26800 nk_textedit_select_all(struct nk_text_edit *state)
  26801 {
  26802     NK_ASSERT(state);
  26803     state->select_start = 0;
  26804     state->select_end = state->string.len;
  26805 }
  26806 NK_API void
  26807 nk_textedit_free(struct nk_text_edit *state)
  26808 {
  26809     NK_ASSERT(state);
  26810     if (!state) return;
  26811     nk_str_free(&state->string);
  26812 }
  26813 
  26814 
  26815 
  26816 
  26817 
  26818 /* ===============================================================
  26819  *
  26820  *                          FILTER
  26821  *
  26822  * ===============================================================*/
  26823 NK_API nk_bool
  26824 nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
  26825 {
  26826     NK_UNUSED(unicode);
  26827     NK_UNUSED(box);
  26828     return nk_true;
  26829 }
  26830 NK_API nk_bool
  26831 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
  26832 {
  26833     NK_UNUSED(box);
  26834     if (unicode > 128) return nk_false;
  26835     else return nk_true;
  26836 }
  26837 NK_API nk_bool
  26838 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
  26839 {
  26840     NK_UNUSED(box);
  26841     if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
  26842         return nk_false;
  26843     else return nk_true;
  26844 }
  26845 NK_API nk_bool
  26846 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
  26847 {
  26848     NK_UNUSED(box);
  26849     if ((unicode < '0' || unicode > '9') && unicode != '-')
  26850         return nk_false;
  26851     else return nk_true;
  26852 }
  26853 NK_API nk_bool
  26854 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
  26855 {
  26856     NK_UNUSED(box);
  26857     if ((unicode < '0' || unicode > '9') &&
  26858         (unicode < 'a' || unicode > 'f') &&
  26859         (unicode < 'A' || unicode > 'F'))
  26860         return nk_false;
  26861     else return nk_true;
  26862 }
  26863 NK_API nk_bool
  26864 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
  26865 {
  26866     NK_UNUSED(box);
  26867     if (unicode < '0' || unicode > '7')
  26868         return nk_false;
  26869     else return nk_true;
  26870 }
  26871 NK_API nk_bool
  26872 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
  26873 {
  26874     NK_UNUSED(box);
  26875     if (unicode != '0' && unicode != '1')
  26876         return nk_false;
  26877     else return nk_true;
  26878 }
  26879 
  26880 /* ===============================================================
  26881  *
  26882  *                          EDIT
  26883  *
  26884  * ===============================================================*/
  26885 NK_LIB void
  26886 nk_edit_draw_text(struct nk_command_buffer *out,
  26887     const struct nk_style_edit *style, float pos_x, float pos_y,
  26888     float x_offset, const char *text, int byte_len, float row_height,
  26889     const struct nk_user_font *font, struct nk_color background,
  26890     struct nk_color foreground, nk_bool is_selected)
  26891 {
  26892     NK_ASSERT(out);
  26893     NK_ASSERT(font);
  26894     NK_ASSERT(style);
  26895     if (!text || !byte_len || !out || !style) return;
  26896 
  26897     {int glyph_len = 0;
  26898     nk_rune unicode = 0;
  26899     int text_len = 0;
  26900     float line_width = 0;
  26901     float glyph_width;
  26902     const char *line = text;
  26903     float line_offset = 0;
  26904     int line_count = 0;
  26905 
  26906     struct nk_text txt;
  26907     txt.padding = nk_vec2(0,0);
  26908     txt.background = background;
  26909     txt.text = foreground;
  26910 
  26911     glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
  26912     if (!glyph_len) return;
  26913     while ((text_len < byte_len) && glyph_len)
  26914     {
  26915         if (unicode == '\n') {
  26916             /* new line separator so draw previous line */
  26917             struct nk_rect label;
  26918             label.y = pos_y + line_offset;
  26919             label.h = row_height;
  26920             label.w = line_width;
  26921             label.x = pos_x;
  26922             if (!line_count)
  26923                 label.x += x_offset;
  26924 
  26925             if (is_selected) /* selection needs to draw different background color */
  26926                 nk_fill_rect(out, label, 0, background);
  26927             nk_widget_text(out, label, line, (int)((text + text_len) - line),
  26928                 &txt, NK_TEXT_CENTERED, font);
  26929 
  26930             text_len++;
  26931             line_count++;
  26932             line_width = 0;
  26933             line = text + text_len;
  26934             line_offset += row_height;
  26935             glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
  26936             continue;
  26937         }
  26938         if (unicode == '\r') {
  26939             text_len++;
  26940             glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
  26941             continue;
  26942         }
  26943         glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
  26944         line_width += (float)glyph_width;
  26945         text_len += glyph_len;
  26946         glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
  26947         continue;
  26948     }
  26949     if (line_width > 0) {
  26950         /* draw last line */
  26951         struct nk_rect label;
  26952         label.y = pos_y + line_offset;
  26953         label.h = row_height;
  26954         label.w = line_width;
  26955         label.x = pos_x;
  26956         if (!line_count)
  26957             label.x += x_offset;
  26958 
  26959         if (is_selected)
  26960             nk_fill_rect(out, label, 0, background);
  26961         nk_widget_text(out, label, line, (int)((text + text_len) - line),
  26962             &txt, NK_TEXT_LEFT, font);
  26963     }}
  26964 }
  26965 NK_LIB nk_flags
  26966 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
  26967     struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
  26968     struct nk_text_edit *edit, const struct nk_style_edit *style,
  26969     struct nk_input *in, const struct nk_user_font *font)
  26970 {
  26971     struct nk_rect area;
  26972     nk_flags ret = 0;
  26973     float row_height;
  26974     char prev_state = 0;
  26975     char is_hovered = 0;
  26976     char select_all = 0;
  26977     char cursor_follow = 0;
  26978     struct nk_rect old_clip;
  26979     struct nk_rect clip;
  26980 
  26981     NK_ASSERT(state);
  26982     NK_ASSERT(out);
  26983     NK_ASSERT(style);
  26984     if (!state || !out || !style)
  26985         return ret;
  26986 
  26987     /* visible text area calculation */
  26988     area.x = bounds.x + style->padding.x + style->border;
  26989     area.y = bounds.y + style->padding.y + style->border;
  26990     area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
  26991     area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
  26992     if (flags & NK_EDIT_MULTILINE)
  26993         area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
  26994     row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
  26995 
  26996     /* calculate clipping rectangle */
  26997     old_clip = out->clip;
  26998     nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
  26999 
  27000     /* update edit state */
  27001     prev_state = (char)edit->active;
  27002     is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
  27003     if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) {
  27004         edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
  27005                                 bounds.x, bounds.y, bounds.w, bounds.h);
  27006     }
  27007 
  27008     /* (de)activate text editor */
  27009     if (!prev_state && edit->active) {
  27010         const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
  27011             NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE;
  27012         /* keep scroll position when re-activating edit widget */
  27013         struct nk_vec2 oldscrollbar = edit->scrollbar;
  27014         nk_textedit_clear_state(edit, type, filter);
  27015         edit->scrollbar = oldscrollbar;
  27016         if (flags & NK_EDIT_AUTO_SELECT)
  27017             select_all = nk_true;
  27018         if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
  27019             edit->cursor = edit->string.len;
  27020             in = 0;
  27021         }
  27022     } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
  27023     if (flags & NK_EDIT_READ_ONLY)
  27024         edit->mode = NK_TEXT_EDIT_MODE_VIEW;
  27025     else if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
  27026         edit->mode = NK_TEXT_EDIT_MODE_INSERT;
  27027 
  27028     ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
  27029     if (prev_state != edit->active)
  27030         ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
  27031 
  27032     /* handle user input */
  27033     if (edit->active && in)
  27034     {
  27035         int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
  27036         const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
  27037         const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
  27038 
  27039         /* mouse click handler */
  27040         is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
  27041         if (select_all) {
  27042             nk_textedit_select_all(edit);
  27043         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
  27044             in->mouse.buttons[NK_BUTTON_LEFT].clicked) {
  27045             nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
  27046         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
  27047             (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
  27048             nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
  27049             cursor_follow = nk_true;
  27050         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
  27051             in->mouse.buttons[NK_BUTTON_RIGHT].down) {
  27052             nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
  27053             nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
  27054             cursor_follow = nk_true;
  27055         }
  27056 
  27057         {int i; /* keyboard input */
  27058         int old_mode = edit->mode;
  27059         for (i = 0; i < NK_KEY_MAX; ++i) {
  27060             if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
  27061             if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
  27062                 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
  27063                 cursor_follow = nk_true;
  27064             }
  27065         }
  27066         if (old_mode != edit->mode) {
  27067             in->keyboard.text_len = 0;
  27068         }}
  27069 
  27070         /* text input */
  27071         edit->filter = filter;
  27072         if (in->keyboard.text_len) {
  27073             nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
  27074             cursor_follow = nk_true;
  27075             in->keyboard.text_len = 0;
  27076         }
  27077 
  27078         /* enter key handler */
  27079         if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) {
  27080             cursor_follow = nk_true;
  27081             if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
  27082                 nk_textedit_text(edit, "\n", 1);
  27083             else if (flags & NK_EDIT_SIG_ENTER)
  27084                 ret |= NK_EDIT_COMMITED;
  27085             else nk_textedit_text(edit, "\n", 1);
  27086         }
  27087 
  27088         /* cut & copy handler */
  27089         {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
  27090         int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
  27091         if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
  27092         {
  27093             int glyph_len;
  27094             nk_rune unicode;
  27095             const char *text;
  27096             int b = edit->select_start;
  27097             int e = edit->select_end;
  27098 
  27099             int begin = NK_MIN(b, e);
  27100             int end = NK_MAX(b, e);
  27101             text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
  27102             if (edit->clip.copy)
  27103                 edit->clip.copy(edit->clip.userdata, text, end - begin);
  27104             if (cut && !(flags & NK_EDIT_READ_ONLY)){
  27105                 nk_textedit_cut(edit);
  27106                 cursor_follow = nk_true;
  27107             }
  27108         }}
  27109 
  27110         /* paste handler */
  27111         {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
  27112         if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
  27113             edit->clip.paste(edit->clip.userdata, edit);
  27114             cursor_follow = nk_true;
  27115         }}
  27116 
  27117         /* tab handler */
  27118         {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
  27119         if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
  27120             nk_textedit_text(edit, "    ", 4);
  27121             cursor_follow = nk_true;
  27122         }}
  27123     }
  27124 
  27125     /* set widget state */
  27126     if (edit->active)
  27127         *state = NK_WIDGET_STATE_ACTIVE;
  27128     else nk_widget_state_reset(state);
  27129 
  27130     if (is_hovered)
  27131         *state |= NK_WIDGET_STATE_HOVERED;
  27132 
  27133     /* DRAW EDIT */
  27134     {const char *text = nk_str_get_const(&edit->string);
  27135     int len = nk_str_len_char(&edit->string);
  27136 
  27137     {/* select background colors/images  */
  27138     const struct nk_style_item *background;
  27139     if (*state & NK_WIDGET_STATE_ACTIVED)
  27140         background = &style->active;
  27141     else if (*state & NK_WIDGET_STATE_HOVER)
  27142         background = &style->hover;
  27143     else background = &style->normal;
  27144 
  27145     /* draw background frame */
  27146     switch(background->type) {
  27147         case NK_STYLE_ITEM_IMAGE:
  27148             nk_draw_image(out, bounds, &background->data.image, nk_white);
  27149             break;
  27150         case NK_STYLE_ITEM_NINE_SLICE:
  27151             nk_draw_nine_slice(out, bounds, &background->data.slice, nk_white);
  27152             break;
  27153         case NK_STYLE_ITEM_COLOR:
  27154             nk_fill_rect(out, bounds, style->rounding, background->data.color);
  27155             nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
  27156             break;
  27157     }}
  27158 
  27159 
  27160     area.w = NK_MAX(0, area.w - style->cursor_size);
  27161     if (edit->active)
  27162     {
  27163         int total_lines = 1;
  27164         struct nk_vec2 text_size = nk_vec2(0,0);
  27165 
  27166         /* text pointer positions */
  27167         const char *cursor_ptr = 0;
  27168         const char *select_begin_ptr = 0;
  27169         const char *select_end_ptr = 0;
  27170 
  27171         /* 2D pixel positions */
  27172         struct nk_vec2 cursor_pos = nk_vec2(0,0);
  27173         struct nk_vec2 selection_offset_start = nk_vec2(0,0);
  27174         struct nk_vec2 selection_offset_end = nk_vec2(0,0);
  27175 
  27176         int selection_begin = NK_MIN(edit->select_start, edit->select_end);
  27177         int selection_end = NK_MAX(edit->select_start, edit->select_end);
  27178 
  27179         /* calculate total line count + total space + cursor/selection position */
  27180         float line_width = 0.0f;
  27181         if (text && len)
  27182         {
  27183             /* utf8 encoding */
  27184             float glyph_width;
  27185             int glyph_len = 0;
  27186             nk_rune unicode = 0;
  27187             int text_len = 0;
  27188             int glyphs = 0;
  27189             int row_begin = 0;
  27190 
  27191             glyph_len = nk_utf_decode(text, &unicode, len);
  27192             glyph_width = font->width(font->userdata, font->height, text, glyph_len);
  27193             line_width = 0;
  27194 
  27195             /* iterate all lines */
  27196             while ((text_len < len) && glyph_len)
  27197             {
  27198                 /* set cursor 2D position and line */
  27199                 if (!cursor_ptr && glyphs == edit->cursor)
  27200                 {
  27201                     int glyph_offset;
  27202                     struct nk_vec2 out_offset;
  27203                     struct nk_vec2 row_size;
  27204                     const char *remaining;
  27205 
  27206                     /* calculate 2d position */
  27207                     cursor_pos.y = (float)(total_lines-1) * row_height;
  27208                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
  27209                                 text_len-row_begin, row_height, &remaining,
  27210                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
  27211                     cursor_pos.x = row_size.x;
  27212                     cursor_ptr = text + text_len;
  27213                 }
  27214 
  27215                 /* set start selection 2D position and line */
  27216                 if (!select_begin_ptr && edit->select_start != edit->select_end &&
  27217                     glyphs == selection_begin)
  27218                 {
  27219                     int glyph_offset;
  27220                     struct nk_vec2 out_offset;
  27221                     struct nk_vec2 row_size;
  27222                     const char *remaining;
  27223 
  27224                     /* calculate 2d position */
  27225                     selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
  27226                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
  27227                                 text_len-row_begin, row_height, &remaining,
  27228                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
  27229                     selection_offset_start.x = row_size.x;
  27230                     select_begin_ptr = text + text_len;
  27231                 }
  27232 
  27233                 /* set end selection 2D position and line */
  27234                 if (!select_end_ptr && edit->select_start != edit->select_end &&
  27235                     glyphs == selection_end)
  27236                 {
  27237                     int glyph_offset;
  27238                     struct nk_vec2 out_offset;
  27239                     struct nk_vec2 row_size;
  27240                     const char *remaining;
  27241 
  27242                     /* calculate 2d position */
  27243                     selection_offset_end.y = (float)(total_lines-1) * row_height;
  27244                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
  27245                                 text_len-row_begin, row_height, &remaining,
  27246                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
  27247                     selection_offset_end.x = row_size.x;
  27248                     select_end_ptr = text + text_len;
  27249                 }
  27250                 if (unicode == '\n') {
  27251                     text_size.x = NK_MAX(text_size.x, line_width);
  27252                     total_lines++;
  27253                     line_width = 0;
  27254                     text_len++;
  27255                     glyphs++;
  27256                     row_begin = text_len;
  27257                     glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
  27258                     glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
  27259                     continue;
  27260                 }
  27261 
  27262                 glyphs++;
  27263                 text_len += glyph_len;
  27264                 line_width += (float)glyph_width;
  27265 
  27266                 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
  27267                 glyph_width = font->width(font->userdata, font->height,
  27268                     text+text_len, glyph_len);
  27269                 continue;
  27270             }
  27271             text_size.y = (float)total_lines * row_height;
  27272 
  27273             /* handle case when cursor is at end of text buffer */
  27274             if (!cursor_ptr && edit->cursor == edit->string.len) {
  27275                 cursor_pos.x = line_width;
  27276                 cursor_pos.y = text_size.y - row_height;
  27277             }
  27278         }
  27279         {
  27280             /* scrollbar */
  27281             if (cursor_follow)
  27282             {
  27283                 /* update scrollbar to follow cursor */
  27284                 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
  27285                     /* horizontal scroll */
  27286                     const float scroll_increment = area.w * 0.25f;
  27287                     if (cursor_pos.x < edit->scrollbar.x)
  27288                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
  27289                     if (cursor_pos.x >= edit->scrollbar.x + area.w)
  27290                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - area.w + scroll_increment);
  27291                 } else edit->scrollbar.x = 0;
  27292 
  27293                 if (flags & NK_EDIT_MULTILINE) {
  27294                     /* vertical scroll */
  27295                     if (cursor_pos.y < edit->scrollbar.y)
  27296                         edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
  27297                     if (cursor_pos.y >= edit->scrollbar.y + row_height)
  27298                         edit->scrollbar.y = edit->scrollbar.y + row_height;
  27299                 } else edit->scrollbar.y = 0;
  27300             }
  27301 
  27302             /* scrollbar widget */
  27303             if (flags & NK_EDIT_MULTILINE)
  27304             {
  27305                 nk_flags ws;
  27306                 struct nk_rect scroll;
  27307                 float scroll_target;
  27308                 float scroll_offset;
  27309                 float scroll_step;
  27310                 float scroll_inc;
  27311 
  27312                 scroll = area;
  27313                 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
  27314                 scroll.w = style->scrollbar_size.x;
  27315 
  27316                 scroll_offset = edit->scrollbar.y;
  27317                 scroll_step = scroll.h * 0.10f;
  27318                 scroll_inc = scroll.h * 0.01f;
  27319                 scroll_target = text_size.y;
  27320                 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
  27321                         scroll_offset, scroll_target, scroll_step, scroll_inc,
  27322                         &style->scrollbar, in, font);
  27323             }
  27324         }
  27325 
  27326         /* draw text */
  27327         {struct nk_color background_color;
  27328         struct nk_color text_color;
  27329         struct nk_color sel_background_color;
  27330         struct nk_color sel_text_color;
  27331         struct nk_color cursor_color;
  27332         struct nk_color cursor_text_color;
  27333         const struct nk_style_item *background;
  27334         nk_push_scissor(out, clip);
  27335 
  27336         /* select correct colors to draw */
  27337         if (*state & NK_WIDGET_STATE_ACTIVED) {
  27338             background = &style->active;
  27339             text_color = style->text_active;
  27340             sel_text_color = style->selected_text_hover;
  27341             sel_background_color = style->selected_hover;
  27342             cursor_color = style->cursor_hover;
  27343             cursor_text_color = style->cursor_text_hover;
  27344         } else if (*state & NK_WIDGET_STATE_HOVER) {
  27345             background = &style->hover;
  27346             text_color = style->text_hover;
  27347             sel_text_color = style->selected_text_hover;
  27348             sel_background_color = style->selected_hover;
  27349             cursor_text_color = style->cursor_text_hover;
  27350             cursor_color = style->cursor_hover;
  27351         } else {
  27352             background = &style->normal;
  27353             text_color = style->text_normal;
  27354             sel_text_color = style->selected_text_normal;
  27355             sel_background_color = style->selected_normal;
  27356             cursor_color = style->cursor_normal;
  27357             cursor_text_color = style->cursor_text_normal;
  27358         }
  27359         if (background->type == NK_STYLE_ITEM_IMAGE)
  27360             background_color = nk_rgba(0,0,0,0);
  27361         else
  27362             background_color = background->data.color;
  27363 
  27364 
  27365         if (edit->select_start == edit->select_end) {
  27366             /* no selection so just draw the complete text */
  27367             const char *begin = nk_str_get_const(&edit->string);
  27368             int l = nk_str_len_char(&edit->string);
  27369             nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
  27370                 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
  27371                 background_color, text_color, nk_false);
  27372         } else {
  27373             /* edit has selection so draw 1-3 text chunks */
  27374             if (edit->select_start != edit->select_end && selection_begin > 0){
  27375                 /* draw unselected text before selection */
  27376                 const char *begin = nk_str_get_const(&edit->string);
  27377                 NK_ASSERT(select_begin_ptr);
  27378                 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
  27379                     area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
  27380                     row_height, font, background_color, text_color, nk_false);
  27381             }
  27382             if (edit->select_start != edit->select_end) {
  27383                 /* draw selected text */
  27384                 NK_ASSERT(select_begin_ptr);
  27385                 if (!select_end_ptr) {
  27386                     const char *begin = nk_str_get_const(&edit->string);
  27387                     select_end_ptr = begin + nk_str_len_char(&edit->string);
  27388                 }
  27389                 nk_edit_draw_text(out, style,
  27390                     area.x - edit->scrollbar.x,
  27391                     area.y + selection_offset_start.y - edit->scrollbar.y,
  27392                     selection_offset_start.x,
  27393                     select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
  27394                     row_height, font, sel_background_color, sel_text_color, nk_true);
  27395             }
  27396             if ((edit->select_start != edit->select_end &&
  27397                 selection_end < edit->string.len))
  27398             {
  27399                 /* draw unselected text after selected text */
  27400                 const char *begin = select_end_ptr;
  27401                 const char *end = nk_str_get_const(&edit->string) +
  27402                                     nk_str_len_char(&edit->string);
  27403                 NK_ASSERT(select_end_ptr);
  27404                 nk_edit_draw_text(out, style,
  27405                     area.x - edit->scrollbar.x,
  27406                     area.y + selection_offset_end.y - edit->scrollbar.y,
  27407                     selection_offset_end.x,
  27408                     begin, (int)(end - begin), row_height, font,
  27409                     background_color, text_color, nk_true);
  27410             }
  27411         }
  27412 
  27413         /* cursor */
  27414         if (edit->select_start == edit->select_end)
  27415         {
  27416             if (edit->cursor >= nk_str_len(&edit->string) ||
  27417                 (cursor_ptr && *cursor_ptr == '\n')) {
  27418                 /* draw cursor at end of line */
  27419                 struct nk_rect cursor;
  27420                 cursor.w = style->cursor_size;
  27421                 cursor.h = font->height;
  27422                 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
  27423                 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
  27424                 cursor.y -= edit->scrollbar.y;
  27425                 nk_fill_rect(out, cursor, 0, cursor_color);
  27426             } else {
  27427                 /* draw cursor inside text */
  27428                 int glyph_len;
  27429                 struct nk_rect label;
  27430                 struct nk_text txt;
  27431 
  27432                 nk_rune unicode;
  27433                 NK_ASSERT(cursor_ptr);
  27434                 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
  27435 
  27436                 label.x = area.x + cursor_pos.x - edit->scrollbar.x;
  27437                 label.y = area.y + cursor_pos.y - edit->scrollbar.y;
  27438                 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
  27439                 label.h = row_height;
  27440 
  27441                 txt.padding = nk_vec2(0,0);
  27442                 txt.background = cursor_color;;
  27443                 txt.text = cursor_text_color;
  27444                 nk_fill_rect(out, label, 0, cursor_color);
  27445                 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
  27446             }
  27447         }}
  27448     } else {
  27449         /* not active so just draw text */
  27450         int l = nk_str_len_char(&edit->string);
  27451         const char *begin = nk_str_get_const(&edit->string);
  27452 
  27453         const struct nk_style_item *background;
  27454         struct nk_color background_color;
  27455         struct nk_color text_color;
  27456         nk_push_scissor(out, clip);
  27457         if (*state & NK_WIDGET_STATE_ACTIVED) {
  27458             background = &style->active;
  27459             text_color = style->text_active;
  27460         } else if (*state & NK_WIDGET_STATE_HOVER) {
  27461             background = &style->hover;
  27462             text_color = style->text_hover;
  27463         } else {
  27464             background = &style->normal;
  27465             text_color = style->text_normal;
  27466         }
  27467         if (background->type == NK_STYLE_ITEM_IMAGE)
  27468             background_color = nk_rgba(0,0,0,0);
  27469         else
  27470             background_color = background->data.color;
  27471         nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
  27472             area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
  27473             background_color, text_color, nk_false);
  27474     }
  27475     nk_push_scissor(out, old_clip);}
  27476     return ret;
  27477 }
  27478 NK_API void
  27479 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
  27480 {
  27481     nk_hash hash;
  27482     struct nk_window *win;
  27483 
  27484     NK_ASSERT(ctx);
  27485     NK_ASSERT(ctx->current);
  27486     if (!ctx || !ctx->current) return;
  27487 
  27488     win = ctx->current;
  27489     hash = win->edit.seq;
  27490     win->edit.active = nk_true;
  27491     win->edit.name = hash;
  27492     if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
  27493         win->edit.mode = NK_TEXT_EDIT_MODE_INSERT;
  27494 }
  27495 NK_API void
  27496 nk_edit_unfocus(struct nk_context *ctx)
  27497 {
  27498     struct nk_window *win;
  27499     NK_ASSERT(ctx);
  27500     NK_ASSERT(ctx->current);
  27501     if (!ctx || !ctx->current) return;
  27502 
  27503     win = ctx->current;
  27504     win->edit.active = nk_false;
  27505     win->edit.name = 0;
  27506 }
  27507 NK_API nk_flags
  27508 nk_edit_string(struct nk_context *ctx, nk_flags flags,
  27509     char *memory, int *len, int max, nk_plugin_filter filter)
  27510 {
  27511     nk_hash hash;
  27512     nk_flags state;
  27513     struct nk_text_edit *edit;
  27514     struct nk_window *win;
  27515 
  27516     NK_ASSERT(ctx);
  27517     NK_ASSERT(memory);
  27518     NK_ASSERT(len);
  27519     if (!ctx || !memory || !len)
  27520         return 0;
  27521 
  27522     filter = (!filter) ? nk_filter_default: filter;
  27523     win = ctx->current;
  27524     hash = win->edit.seq;
  27525     edit = &ctx->text_edit;
  27526     nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
  27527         NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter);
  27528 
  27529     if (win->edit.active && hash == win->edit.name) {
  27530         if (flags & NK_EDIT_NO_CURSOR)
  27531             edit->cursor = nk_utf_len(memory, *len);
  27532         else edit->cursor = win->edit.cursor;
  27533         if (!(flags & NK_EDIT_SELECTABLE)) {
  27534             edit->select_start = win->edit.cursor;
  27535             edit->select_end = win->edit.cursor;
  27536         } else {
  27537             edit->select_start = win->edit.sel_start;
  27538             edit->select_end = win->edit.sel_end;
  27539         }
  27540         edit->mode = win->edit.mode;
  27541         edit->scrollbar.x = (float)win->edit.scrollbar.x;
  27542         edit->scrollbar.y = (float)win->edit.scrollbar.y;
  27543         edit->active = nk_true;
  27544     } else edit->active = nk_false;
  27545 
  27546     max = NK_MAX(1, max);
  27547     *len = NK_MIN(*len, max-1);
  27548     nk_str_init_fixed(&edit->string, memory, (nk_size)max);
  27549     edit->string.buffer.allocated = (nk_size)*len;
  27550     edit->string.len = nk_utf_len(memory, *len);
  27551     state = nk_edit_buffer(ctx, flags, edit, filter);
  27552     *len = (int)edit->string.buffer.allocated;
  27553 
  27554     if (edit->active) {
  27555         win->edit.cursor = edit->cursor;
  27556         win->edit.sel_start = edit->select_start;
  27557         win->edit.sel_end = edit->select_end;
  27558         win->edit.mode = edit->mode;
  27559         win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x;
  27560         win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y;
  27561     } return state;
  27562 }
  27563 NK_API nk_flags
  27564 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
  27565     struct nk_text_edit *edit, nk_plugin_filter filter)
  27566 {
  27567     struct nk_window *win;
  27568     struct nk_style *style;
  27569     struct nk_input *in;
  27570 
  27571     enum nk_widget_layout_states state;
  27572     struct nk_rect bounds;
  27573 
  27574     nk_flags ret_flags = 0;
  27575     unsigned char prev_state;
  27576     nk_hash hash;
  27577 
  27578     /* make sure correct values */
  27579     NK_ASSERT(ctx);
  27580     NK_ASSERT(edit);
  27581     NK_ASSERT(ctx->current);
  27582     NK_ASSERT(ctx->current->layout);
  27583     if (!ctx || !ctx->current || !ctx->current->layout)
  27584         return 0;
  27585 
  27586     win = ctx->current;
  27587     style = &ctx->style;
  27588     state = nk_widget(&bounds, ctx);
  27589     if (!state) return state;
  27590     in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  27591 
  27592     /* check if edit is currently hot item */
  27593     hash = win->edit.seq++;
  27594     if (win->edit.active && hash == win->edit.name) {
  27595         if (flags & NK_EDIT_NO_CURSOR)
  27596             edit->cursor = edit->string.len;
  27597         if (!(flags & NK_EDIT_SELECTABLE)) {
  27598             edit->select_start = edit->cursor;
  27599             edit->select_end = edit->cursor;
  27600         }
  27601         if (flags & NK_EDIT_CLIPBOARD)
  27602             edit->clip = ctx->clip;
  27603         edit->active = (unsigned char)win->edit.active;
  27604     } else edit->active = nk_false;
  27605     edit->mode = win->edit.mode;
  27606 
  27607     filter = (!filter) ? nk_filter_default: filter;
  27608     prev_state = (unsigned char)edit->active;
  27609     in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
  27610     ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
  27611                     filter, edit, &style->edit, in, style->font);
  27612 
  27613     if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  27614         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT];
  27615     if (edit->active && prev_state != edit->active) {
  27616         /* current edit is now hot */
  27617         win->edit.active = nk_true;
  27618         win->edit.name = hash;
  27619     } else if (prev_state && !edit->active) {
  27620         /* current edit is now cold */
  27621         win->edit.active = nk_false;
  27622     } return ret_flags;
  27623 }
  27624 NK_API nk_flags
  27625 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
  27626     char *buffer, int max, nk_plugin_filter filter)
  27627 {
  27628     nk_flags result;
  27629     int len = nk_strlen(buffer);
  27630     result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
  27631     buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
  27632     return result;
  27633 }
  27634 
  27635 
  27636 
  27637 
  27638 
  27639 /* ===============================================================
  27640  *
  27641  *                              PROPERTY
  27642  *
  27643  * ===============================================================*/
  27644 NK_LIB void
  27645 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
  27646     struct nk_rect drag, struct nk_property_variant *variant,
  27647     float inc_per_pixel)
  27648 {
  27649     int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
  27650     int left_mouse_click_in_cursor = in &&
  27651         nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true);
  27652 
  27653     nk_widget_state_reset(state);
  27654     if (nk_input_is_mouse_hovering_rect(in, drag))
  27655         *state = NK_WIDGET_STATE_HOVERED;
  27656 
  27657     if (left_mouse_down && left_mouse_click_in_cursor) {
  27658         float delta, pixels;
  27659         pixels = in->mouse.delta.x;
  27660         delta = pixels * inc_per_pixel;
  27661         switch (variant->kind) {
  27662         default: break;
  27663         case NK_PROPERTY_INT:
  27664             variant->value.i = variant->value.i + (int)delta;
  27665             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
  27666             break;
  27667         case NK_PROPERTY_FLOAT:
  27668             variant->value.f = variant->value.f + (float)delta;
  27669             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
  27670             break;
  27671         case NK_PROPERTY_DOUBLE:
  27672             variant->value.d = variant->value.d + (double)delta;
  27673             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
  27674             break;
  27675         }
  27676         *state = NK_WIDGET_STATE_ACTIVE;
  27677     }
  27678     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
  27679         *state |= NK_WIDGET_STATE_ENTERED;
  27680     else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
  27681         *state |= NK_WIDGET_STATE_LEFT;
  27682 }
  27683 NK_LIB void
  27684 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
  27685     struct nk_rect property,  struct nk_rect label, struct nk_rect edit,
  27686     struct nk_rect empty, int *state, struct nk_property_variant *variant,
  27687     float inc_per_pixel)
  27688 {
  27689     nk_widget_state_reset(ws);
  27690     if (in && *state == NK_PROPERTY_DEFAULT) {
  27691         if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
  27692             *state = NK_PROPERTY_EDIT;
  27693         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true))
  27694             *state = NK_PROPERTY_DRAG;
  27695         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true))
  27696             *state = NK_PROPERTY_DRAG;
  27697     }
  27698     if (*state == NK_PROPERTY_DRAG) {
  27699         nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
  27700         if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
  27701     }
  27702 }
  27703 NK_LIB void
  27704 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
  27705     const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
  27706     const char *name, int len, const struct nk_user_font *font)
  27707 {
  27708     struct nk_text text;
  27709     const struct nk_style_item *background;
  27710 
  27711     /* select correct background and text color */
  27712     if (state & NK_WIDGET_STATE_ACTIVED) {
  27713         background = &style->active;
  27714         text.text = style->label_active;
  27715     } else if (state & NK_WIDGET_STATE_HOVER) {
  27716         background = &style->hover;
  27717         text.text = style->label_hover;
  27718     } else {
  27719         background = &style->normal;
  27720         text.text = style->label_normal;
  27721     }
  27722 
  27723     /* draw background */
  27724     switch(background->type) {
  27725         case NK_STYLE_ITEM_IMAGE:
  27726             text.background = nk_rgba(0, 0, 0, 0);
  27727             nk_draw_image(out, *bounds, &background->data.image, nk_white);
  27728             break;
  27729         case NK_STYLE_ITEM_NINE_SLICE:
  27730             text.background = nk_rgba(0, 0, 0, 0);
  27731             nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white);
  27732             break;
  27733         case NK_STYLE_ITEM_COLOR:
  27734             text.background = background->data.color;
  27735             nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  27736             nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
  27737             break;
  27738     }
  27739 
  27740     /* draw label */
  27741     text.padding = nk_vec2(0,0);
  27742     nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
  27743 }
  27744 NK_LIB void
  27745 nk_do_property(nk_flags *ws,
  27746     struct nk_command_buffer *out, struct nk_rect property,
  27747     const char *name, struct nk_property_variant *variant,
  27748     float inc_per_pixel, char *buffer, int *len,
  27749     int *state, int *cursor, int *select_begin, int *select_end,
  27750     const struct nk_style_property *style,
  27751     enum nk_property_filter filter, struct nk_input *in,
  27752     const struct nk_user_font *font, struct nk_text_edit *text_edit,
  27753     enum nk_button_behavior behavior)
  27754 {
  27755     const nk_plugin_filter filters[] = {
  27756         nk_filter_decimal,
  27757         nk_filter_float
  27758     };
  27759     nk_bool active, old;
  27760     int num_len = 0, name_len;
  27761     char string[NK_MAX_NUMBER_BUFFER];
  27762     float size;
  27763 
  27764     char *dst = 0;
  27765     int *length;
  27766 
  27767     struct nk_rect left;
  27768     struct nk_rect right;
  27769     struct nk_rect label;
  27770     struct nk_rect edit;
  27771     struct nk_rect empty;
  27772 
  27773     /* left decrement button */
  27774     left.h = font->height/2;
  27775     left.w = left.h;
  27776     left.x = property.x + style->border + style->padding.x;
  27777     left.y = property.y + style->border + property.h/2.0f - left.h/2;
  27778 
  27779     /* text label */
  27780     name_len = nk_strlen(name);
  27781     size = font->width(font->userdata, font->height, name, name_len);
  27782     label.x = left.x + left.w + style->padding.x;
  27783     label.w = (float)size + 2 * style->padding.x;
  27784     label.y = property.y + style->border + style->padding.y;
  27785     label.h = property.h - (2 * style->border + 2 * style->padding.y);
  27786 
  27787     /* right increment button */
  27788     right.y = left.y;
  27789     right.w = left.w;
  27790     right.h = left.h;
  27791     right.x = property.x + property.w - (right.w + style->padding.x);
  27792 
  27793     /* edit */
  27794     if (*state == NK_PROPERTY_EDIT) {
  27795         size = font->width(font->userdata, font->height, buffer, *len);
  27796         size += style->edit.cursor_size;
  27797         length = len;
  27798         dst = buffer;
  27799     } else {
  27800         switch (variant->kind) {
  27801         default: break;
  27802         case NK_PROPERTY_INT:
  27803             nk_itoa(string, variant->value.i);
  27804             num_len = nk_strlen(string);
  27805             break;
  27806         case NK_PROPERTY_FLOAT:
  27807             NK_DTOA(string, (double)variant->value.f);
  27808             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
  27809             break;
  27810         case NK_PROPERTY_DOUBLE:
  27811             NK_DTOA(string, variant->value.d);
  27812             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
  27813             break;
  27814         }
  27815         size = font->width(font->userdata, font->height, string, num_len);
  27816         dst = string;
  27817         length = &num_len;
  27818     }
  27819 
  27820     edit.w =  (float)size + 2 * style->padding.x;
  27821     edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
  27822     edit.x = right.x - (edit.w + style->padding.x);
  27823     edit.y = property.y + style->border;
  27824     edit.h = property.h - (2 * style->border);
  27825 
  27826     /* empty left space activator */
  27827     empty.w = edit.x - (label.x + label.w);
  27828     empty.x = label.x + label.w;
  27829     empty.y = property.y;
  27830     empty.h = property.h;
  27831 
  27832     /* update property */
  27833     old = (*state == NK_PROPERTY_EDIT);
  27834     nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
  27835 
  27836     /* draw property */
  27837     if (style->draw_begin) style->draw_begin(out, style->userdata);
  27838     nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
  27839     if (style->draw_end) style->draw_end(out, style->userdata);
  27840 
  27841     /* execute right button  */
  27842     if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
  27843         switch (variant->kind) {
  27844         default: break;
  27845         case NK_PROPERTY_INT:
  27846             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
  27847         case NK_PROPERTY_FLOAT:
  27848             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
  27849         case NK_PROPERTY_DOUBLE:
  27850             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
  27851         }
  27852     }
  27853     /* execute left button  */
  27854     if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
  27855         switch (variant->kind) {
  27856         default: break;
  27857         case NK_PROPERTY_INT:
  27858             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
  27859         case NK_PROPERTY_FLOAT:
  27860             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
  27861         case NK_PROPERTY_DOUBLE:
  27862             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
  27863         }
  27864     }
  27865     if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
  27866         /* property has been activated so setup buffer */
  27867         NK_MEMCPY(buffer, dst, (nk_size)*length);
  27868         *cursor = nk_utf_len(buffer, *length);
  27869         *len = *length;
  27870         length = len;
  27871         dst = buffer;
  27872         active = 0;
  27873     } else active = (*state == NK_PROPERTY_EDIT);
  27874 
  27875     /* execute and run text edit field */
  27876     nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
  27877     text_edit->active = (unsigned char)active;
  27878     text_edit->string.len = *length;
  27879     text_edit->cursor = NK_CLAMP(0, *cursor, *length);
  27880     text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
  27881     text_edit->select_end = NK_CLAMP(0,*select_end, *length);
  27882     text_edit->string.buffer.allocated = (nk_size)*length;
  27883     text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER;
  27884     text_edit->string.buffer.memory.ptr = dst;
  27885     text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
  27886     text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
  27887     nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
  27888         filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
  27889 
  27890     *length = text_edit->string.len;
  27891     *cursor = text_edit->cursor;
  27892     *select_begin = text_edit->select_start;
  27893     *select_end = text_edit->select_end;
  27894     if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
  27895         text_edit->active = nk_false;
  27896 
  27897     if (active && !text_edit->active) {
  27898         /* property is now not active so convert edit text to value*/
  27899         *state = NK_PROPERTY_DEFAULT;
  27900         buffer[*len] = '\0';
  27901         switch (variant->kind) {
  27902         default: break;
  27903         case NK_PROPERTY_INT:
  27904             variant->value.i = nk_strtoi(buffer, 0);
  27905             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
  27906             break;
  27907         case NK_PROPERTY_FLOAT:
  27908             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
  27909             variant->value.f = nk_strtof(buffer, 0);
  27910             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
  27911             break;
  27912         case NK_PROPERTY_DOUBLE:
  27913             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
  27914             variant->value.d = nk_strtod(buffer, 0);
  27915             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
  27916             break;
  27917         }
  27918     }
  27919 }
  27920 NK_LIB struct nk_property_variant
  27921 nk_property_variant_int(int value, int min_value, int max_value, int step)
  27922 {
  27923     struct nk_property_variant result;
  27924     result.kind = NK_PROPERTY_INT;
  27925     result.value.i = value;
  27926     result.min_value.i = min_value;
  27927     result.max_value.i = max_value;
  27928     result.step.i = step;
  27929     return result;
  27930 }
  27931 NK_LIB struct nk_property_variant
  27932 nk_property_variant_float(float value, float min_value, float max_value, float step)
  27933 {
  27934     struct nk_property_variant result;
  27935     result.kind = NK_PROPERTY_FLOAT;
  27936     result.value.f = value;
  27937     result.min_value.f = min_value;
  27938     result.max_value.f = max_value;
  27939     result.step.f = step;
  27940     return result;
  27941 }
  27942 NK_LIB struct nk_property_variant
  27943 nk_property_variant_double(double value, double min_value, double max_value,
  27944     double step)
  27945 {
  27946     struct nk_property_variant result;
  27947     result.kind = NK_PROPERTY_DOUBLE;
  27948     result.value.d = value;
  27949     result.min_value.d = min_value;
  27950     result.max_value.d = max_value;
  27951     result.step.d = step;
  27952     return result;
  27953 }
  27954 NK_LIB void
  27955 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
  27956     float inc_per_pixel, const enum nk_property_filter filter)
  27957 {
  27958     struct nk_window *win;
  27959     struct nk_panel *layout;
  27960     struct nk_input *in;
  27961     const struct nk_style *style;
  27962 
  27963     struct nk_rect bounds;
  27964     enum nk_widget_layout_states s;
  27965 
  27966     int *state = 0;
  27967     nk_hash hash = 0;
  27968     char *buffer = 0;
  27969     int *len = 0;
  27970     int *cursor = 0;
  27971     int *select_begin = 0;
  27972     int *select_end = 0;
  27973     int old_state;
  27974 
  27975     char dummy_buffer[NK_MAX_NUMBER_BUFFER];
  27976     int dummy_state = NK_PROPERTY_DEFAULT;
  27977     int dummy_length = 0;
  27978     int dummy_cursor = 0;
  27979     int dummy_select_begin = 0;
  27980     int dummy_select_end = 0;
  27981 
  27982     NK_ASSERT(ctx);
  27983     NK_ASSERT(ctx->current);
  27984     NK_ASSERT(ctx->current->layout);
  27985     if (!ctx || !ctx->current || !ctx->current->layout)
  27986         return;
  27987 
  27988     win = ctx->current;
  27989     layout = win->layout;
  27990     style = &ctx->style;
  27991     s = nk_widget(&bounds, ctx);
  27992     if (!s) return;
  27993 
  27994     /* calculate hash from name */
  27995     if (name[0] == '#') {
  27996         hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
  27997         name++; /* special number hash */
  27998     } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
  27999 
  28000     /* check if property is currently hot item */
  28001     if (win->property.active && hash == win->property.name) {
  28002         buffer = win->property.buffer;
  28003         len = &win->property.length;
  28004         cursor = &win->property.cursor;
  28005         state = &win->property.state;
  28006         select_begin = &win->property.select_start;
  28007         select_end = &win->property.select_end;
  28008     } else {
  28009         buffer = dummy_buffer;
  28010         len = &dummy_length;
  28011         cursor = &dummy_cursor;
  28012         state = &dummy_state;
  28013         select_begin =  &dummy_select_begin;
  28014         select_end = &dummy_select_end;
  28015     }
  28016 
  28017     /* execute property widget */
  28018     old_state = *state;
  28019     ctx->text_edit.clip = ctx->clip;
  28020     in = ((s == NK_WIDGET_ROM && !win->property.active) ||
  28021         layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  28022     nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
  28023         variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
  28024         select_end, &style->property, filter, in, style->font, &ctx->text_edit,
  28025         ctx->button_behavior);
  28026 
  28027     if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
  28028         /* current property is now hot */
  28029         win->property.active = 1;
  28030         NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
  28031         win->property.length = *len;
  28032         win->property.cursor = *cursor;
  28033         win->property.state = *state;
  28034         win->property.name = hash;
  28035         win->property.select_start = *select_begin;
  28036         win->property.select_end = *select_end;
  28037         if (*state == NK_PROPERTY_DRAG) {
  28038             ctx->input.mouse.grab = nk_true;
  28039             ctx->input.mouse.grabbed = nk_true;
  28040         }
  28041     }
  28042     /* check if previously active property is now inactive */
  28043     if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
  28044         if (old_state == NK_PROPERTY_DRAG) {
  28045             ctx->input.mouse.grab = nk_false;
  28046             ctx->input.mouse.grabbed = nk_false;
  28047             ctx->input.mouse.ungrab = nk_true;
  28048         }
  28049         win->property.select_start = 0;
  28050         win->property.select_end = 0;
  28051         win->property.active = 0;
  28052     }
  28053 }
  28054 NK_API void
  28055 nk_property_int(struct nk_context *ctx, const char *name,
  28056     int min, int *val, int max, int step, float inc_per_pixel)
  28057 {
  28058     struct nk_property_variant variant;
  28059     NK_ASSERT(ctx);
  28060     NK_ASSERT(name);
  28061     NK_ASSERT(val);
  28062 
  28063     if (!ctx || !ctx->current || !name || !val) return;
  28064     variant = nk_property_variant_int(*val, min, max, step);
  28065     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
  28066     *val = variant.value.i;
  28067 }
  28068 NK_API void
  28069 nk_property_float(struct nk_context *ctx, const char *name,
  28070     float min, float *val, float max, float step, float inc_per_pixel)
  28071 {
  28072     struct nk_property_variant variant;
  28073     NK_ASSERT(ctx);
  28074     NK_ASSERT(name);
  28075     NK_ASSERT(val);
  28076 
  28077     if (!ctx || !ctx->current || !name || !val) return;
  28078     variant = nk_property_variant_float(*val, min, max, step);
  28079     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
  28080     *val = variant.value.f;
  28081 }
  28082 NK_API void
  28083 nk_property_double(struct nk_context *ctx, const char *name,
  28084     double min, double *val, double max, double step, float inc_per_pixel)
  28085 {
  28086     struct nk_property_variant variant;
  28087     NK_ASSERT(ctx);
  28088     NK_ASSERT(name);
  28089     NK_ASSERT(val);
  28090 
  28091     if (!ctx || !ctx->current || !name || !val) return;
  28092     variant = nk_property_variant_double(*val, min, max, step);
  28093     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
  28094     *val = variant.value.d;
  28095 }
  28096 NK_API int
  28097 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
  28098     int max, int step, float inc_per_pixel)
  28099 {
  28100     struct nk_property_variant variant;
  28101     NK_ASSERT(ctx);
  28102     NK_ASSERT(name);
  28103 
  28104     if (!ctx || !ctx->current || !name) return val;
  28105     variant = nk_property_variant_int(val, min, max, step);
  28106     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
  28107     val = variant.value.i;
  28108     return val;
  28109 }
  28110 NK_API float
  28111 nk_propertyf(struct nk_context *ctx, const char *name, float min,
  28112     float val, float max, float step, float inc_per_pixel)
  28113 {
  28114     struct nk_property_variant variant;
  28115     NK_ASSERT(ctx);
  28116     NK_ASSERT(name);
  28117 
  28118     if (!ctx || !ctx->current || !name) return val;
  28119     variant = nk_property_variant_float(val, min, max, step);
  28120     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
  28121     val = variant.value.f;
  28122     return val;
  28123 }
  28124 NK_API double
  28125 nk_propertyd(struct nk_context *ctx, const char *name, double min,
  28126     double val, double max, double step, float inc_per_pixel)
  28127 {
  28128     struct nk_property_variant variant;
  28129     NK_ASSERT(ctx);
  28130     NK_ASSERT(name);
  28131 
  28132     if (!ctx || !ctx->current || !name) return val;
  28133     variant = nk_property_variant_double(val, min, max, step);
  28134     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
  28135     val = variant.value.d;
  28136     return val;
  28137 }
  28138 
  28139 
  28140 
  28141 
  28142 
  28143 /* ==============================================================
  28144  *
  28145  *                          CHART
  28146  *
  28147  * ===============================================================*/
  28148 NK_API nk_bool
  28149 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
  28150     struct nk_color color, struct nk_color highlight,
  28151     int count, float min_value, float max_value)
  28152 {
  28153     struct nk_window *win;
  28154     struct nk_chart *chart;
  28155     const struct nk_style *config;
  28156     const struct nk_style_chart *style;
  28157 
  28158     const struct nk_style_item *background;
  28159     struct nk_rect bounds = {0, 0, 0, 0};
  28160 
  28161     NK_ASSERT(ctx);
  28162     NK_ASSERT(ctx->current);
  28163     NK_ASSERT(ctx->current->layout);
  28164 
  28165     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
  28166     if (!nk_widget(&bounds, ctx)) {
  28167         chart = &ctx->current->layout->chart;
  28168         nk_zero(chart, sizeof(*chart));
  28169         return 0;
  28170     }
  28171 
  28172     win = ctx->current;
  28173     config = &ctx->style;
  28174     chart = &win->layout->chart;
  28175     style = &config->chart;
  28176 
  28177     /* setup basic generic chart  */
  28178     nk_zero(chart, sizeof(*chart));
  28179     chart->x = bounds.x + style->padding.x;
  28180     chart->y = bounds.y + style->padding.y;
  28181     chart->w = bounds.w - 2 * style->padding.x;
  28182     chart->h = bounds.h - 2 * style->padding.y;
  28183     chart->w = NK_MAX(chart->w, 2 * style->padding.x);
  28184     chart->h = NK_MAX(chart->h, 2 * style->padding.y);
  28185 
  28186     /* add first slot into chart */
  28187     {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
  28188     slot->type = type;
  28189     slot->count = count;
  28190     slot->color = color;
  28191     slot->highlight = highlight;
  28192     slot->min = NK_MIN(min_value, max_value);
  28193     slot->max = NK_MAX(min_value, max_value);
  28194     slot->range = slot->max - slot->min;}
  28195 
  28196     /* draw chart background */
  28197     background = &style->background;
  28198 
  28199     switch(background->type) {
  28200         case NK_STYLE_ITEM_IMAGE:
  28201             nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
  28202             break;
  28203         case NK_STYLE_ITEM_NINE_SLICE:
  28204             nk_draw_nine_slice(&win->buffer, bounds, &background->data.slice, nk_white);
  28205             break;
  28206         case NK_STYLE_ITEM_COLOR:
  28207             nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
  28208             nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
  28209                 style->rounding, style->background.data.color);
  28210             break;
  28211     }
  28212     return 1;
  28213 }
  28214 NK_API nk_bool
  28215 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
  28216     int count, float min_value, float max_value)
  28217 {
  28218     return nk_chart_begin_colored(ctx, type, ctx->style.chart.color,
  28219                 ctx->style.chart.selected_color, count, min_value, max_value);
  28220 }
  28221 NK_API void
  28222 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
  28223     struct nk_color color, struct nk_color highlight,
  28224     int count, float min_value, float max_value)
  28225 {
  28226     NK_ASSERT(ctx);
  28227     NK_ASSERT(ctx->current);
  28228     NK_ASSERT(ctx->current->layout);
  28229     NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
  28230     if (!ctx || !ctx->current || !ctx->current->layout) return;
  28231     if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
  28232 
  28233     /* add another slot into the graph */
  28234     {struct nk_chart *chart = &ctx->current->layout->chart;
  28235     struct nk_chart_slot *slot = &chart->slots[chart->slot++];
  28236     slot->type = type;
  28237     slot->count = count;
  28238     slot->color = color;
  28239     slot->highlight = highlight;
  28240     slot->min = NK_MIN(min_value, max_value);
  28241     slot->max = NK_MAX(min_value, max_value);
  28242     slot->range = slot->max - slot->min;}
  28243 }
  28244 NK_API void
  28245 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
  28246     int count, float min_value, float max_value)
  28247 {
  28248     nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color,
  28249         ctx->style.chart.selected_color, count, min_value, max_value);
  28250 }
  28251 NK_INTERN nk_flags
  28252 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
  28253     struct nk_chart *g, float value, int slot)
  28254 {
  28255     struct nk_panel *layout = win->layout;
  28256     const struct nk_input *i = &ctx->input;
  28257     struct nk_command_buffer *out = &win->buffer;
  28258 
  28259     nk_flags ret = 0;
  28260     struct nk_vec2 cur;
  28261     struct nk_rect bounds;
  28262     struct nk_color color;
  28263     float step;
  28264     float range;
  28265     float ratio;
  28266 
  28267     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
  28268     step = g->w / (float)g->slots[slot].count;
  28269     range = g->slots[slot].max - g->slots[slot].min;
  28270     ratio = (value - g->slots[slot].min) / range;
  28271 
  28272     if (g->slots[slot].index == 0) {
  28273         /* first data point does not have a connection */
  28274         g->slots[slot].last.x = g->x;
  28275         g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
  28276 
  28277         bounds.x = g->slots[slot].last.x - 2;
  28278         bounds.y = g->slots[slot].last.y - 2;
  28279         bounds.w = bounds.h = 4;
  28280 
  28281         color = g->slots[slot].color;
  28282         if (!(layout->flags & NK_WINDOW_ROM) &&
  28283             NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
  28284             ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
  28285             ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
  28286                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
  28287             color = g->slots[slot].highlight;
  28288         }
  28289         nk_fill_rect(out, bounds, 0, color);
  28290         g->slots[slot].index += 1;
  28291         return ret;
  28292     }
  28293 
  28294     /* draw a line between the last data point and the new one */
  28295     color = g->slots[slot].color;
  28296     cur.x = g->x + (float)(step * (float)g->slots[slot].index);
  28297     cur.y = (g->y + g->h) - (ratio * (float)g->h);
  28298     nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
  28299 
  28300     bounds.x = cur.x - 3;
  28301     bounds.y = cur.y - 3;
  28302     bounds.w = bounds.h = 6;
  28303 
  28304     /* user selection of current data point */
  28305     if (!(layout->flags & NK_WINDOW_ROM)) {
  28306         if (nk_input_is_mouse_hovering_rect(i, bounds)) {
  28307             ret = NK_CHART_HOVERING;
  28308             ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
  28309                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
  28310             color = g->slots[slot].highlight;
  28311         }
  28312     }
  28313     nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
  28314 
  28315     /* save current data point position */
  28316     g->slots[slot].last.x = cur.x;
  28317     g->slots[slot].last.y = cur.y;
  28318     g->slots[slot].index  += 1;
  28319     return ret;
  28320 }
  28321 NK_INTERN nk_flags
  28322 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
  28323     struct nk_chart *chart, float value, int slot)
  28324 {
  28325     struct nk_command_buffer *out = &win->buffer;
  28326     const struct nk_input *in = &ctx->input;
  28327     struct nk_panel *layout = win->layout;
  28328 
  28329     float ratio;
  28330     nk_flags ret = 0;
  28331     struct nk_color color;
  28332     struct nk_rect item = {0,0,0,0};
  28333 
  28334     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
  28335     if (chart->slots[slot].index  >= chart->slots[slot].count)
  28336         return nk_false;
  28337     if (chart->slots[slot].count) {
  28338         float padding = (float)(chart->slots[slot].count-1);
  28339         item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
  28340     }
  28341 
  28342     /* calculate bounds of current bar chart entry */
  28343     color = chart->slots[slot].color;;
  28344     item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
  28345     if (value >= 0) {
  28346         ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
  28347         item.y = (chart->y + chart->h) - chart->h * ratio;
  28348     } else {
  28349         ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
  28350         item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
  28351     }
  28352     item.x = chart->x + ((float)chart->slots[slot].index * item.w);
  28353     item.x = item.x + ((float)chart->slots[slot].index);
  28354 
  28355     /* user chart bar selection */
  28356     if (!(layout->flags & NK_WINDOW_ROM) &&
  28357         NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
  28358         ret = NK_CHART_HOVERING;
  28359         ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
  28360                 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
  28361         color = chart->slots[slot].highlight;
  28362     }
  28363     nk_fill_rect(out, item, 0, color);
  28364     chart->slots[slot].index += 1;
  28365     return ret;
  28366 }
  28367 NK_API nk_flags
  28368 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
  28369 {
  28370     nk_flags flags;
  28371     struct nk_window *win;
  28372 
  28373     NK_ASSERT(ctx);
  28374     NK_ASSERT(ctx->current);
  28375     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
  28376     NK_ASSERT(slot < ctx->current->layout->chart.slot);
  28377     if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
  28378     if (slot >= ctx->current->layout->chart.slot) return nk_false;
  28379 
  28380     win = ctx->current;
  28381     if (win->layout->chart.slot < slot) return nk_false;
  28382     switch (win->layout->chart.slots[slot].type) {
  28383     case NK_CHART_LINES:
  28384         flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
  28385     case NK_CHART_COLUMN:
  28386         flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
  28387     default:
  28388     case NK_CHART_MAX:
  28389         flags = 0;
  28390     }
  28391     return flags;
  28392 }
  28393 NK_API nk_flags
  28394 nk_chart_push(struct nk_context *ctx, float value)
  28395 {
  28396     return nk_chart_push_slot(ctx, value, 0);
  28397 }
  28398 NK_API void
  28399 nk_chart_end(struct nk_context *ctx)
  28400 {
  28401     struct nk_window *win;
  28402     struct nk_chart *chart;
  28403 
  28404     NK_ASSERT(ctx);
  28405     NK_ASSERT(ctx->current);
  28406     if (!ctx || !ctx->current)
  28407         return;
  28408 
  28409     win = ctx->current;
  28410     chart = &win->layout->chart;
  28411     NK_MEMSET(chart, 0, sizeof(*chart));
  28412     return;
  28413 }
  28414 NK_API void
  28415 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
  28416     int count, int offset)
  28417 {
  28418     int i = 0;
  28419     float min_value;
  28420     float max_value;
  28421 
  28422     NK_ASSERT(ctx);
  28423     NK_ASSERT(values);
  28424     if (!ctx || !values || !count) return;
  28425 
  28426     min_value = values[offset];
  28427     max_value = values[offset];
  28428     for (i = 0; i < count; ++i) {
  28429         min_value = NK_MIN(values[i + offset], min_value);
  28430         max_value = NK_MAX(values[i + offset], max_value);
  28431     }
  28432 
  28433     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
  28434         for (i = 0; i < count; ++i)
  28435             nk_chart_push(ctx, values[i + offset]);
  28436         nk_chart_end(ctx);
  28437     }
  28438 }
  28439 NK_API void
  28440 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
  28441     float(*value_getter)(void* user, int index), int count, int offset)
  28442 {
  28443     int i = 0;
  28444     float min_value;
  28445     float max_value;
  28446 
  28447     NK_ASSERT(ctx);
  28448     NK_ASSERT(value_getter);
  28449     if (!ctx || !value_getter || !count) return;
  28450 
  28451     max_value = min_value = value_getter(userdata, offset);
  28452     for (i = 0; i < count; ++i) {
  28453         float value = value_getter(userdata, i + offset);
  28454         min_value = NK_MIN(value, min_value);
  28455         max_value = NK_MAX(value, max_value);
  28456     }
  28457 
  28458     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
  28459         for (i = 0; i < count; ++i)
  28460             nk_chart_push(ctx, value_getter(userdata, i + offset));
  28461         nk_chart_end(ctx);
  28462     }
  28463 }
  28464 
  28465 
  28466 
  28467 
  28468 
  28469 /* ==============================================================
  28470  *
  28471  *                          COLOR PICKER
  28472  *
  28473  * ===============================================================*/
  28474 NK_LIB nk_bool
  28475 nk_color_picker_behavior(nk_flags *state,
  28476     const struct nk_rect *bounds, const struct nk_rect *matrix,
  28477     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
  28478     struct nk_colorf *color, const struct nk_input *in)
  28479 {
  28480     float hsva[4];
  28481     nk_bool value_changed = 0;
  28482     nk_bool hsv_changed = 0;
  28483 
  28484     NK_ASSERT(state);
  28485     NK_ASSERT(matrix);
  28486     NK_ASSERT(hue_bar);
  28487     NK_ASSERT(color);
  28488 
  28489     /* color matrix */
  28490     nk_colorf_hsva_fv(hsva, *color);
  28491     if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
  28492         hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
  28493         hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
  28494         value_changed = hsv_changed = 1;
  28495     }
  28496     /* hue bar */
  28497     if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
  28498         hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
  28499         value_changed = hsv_changed = 1;
  28500     }
  28501     /* alpha bar */
  28502     if (alpha_bar) {
  28503         if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
  28504             hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
  28505             value_changed = 1;
  28506         }
  28507     }
  28508     nk_widget_state_reset(state);
  28509     if (hsv_changed) {
  28510         *color = nk_hsva_colorfv(hsva);
  28511         *state = NK_WIDGET_STATE_ACTIVE;
  28512     }
  28513     if (value_changed) {
  28514         color->a = hsva[3];
  28515         *state = NK_WIDGET_STATE_ACTIVE;
  28516     }
  28517     /* set color picker widget state */
  28518     if (nk_input_is_mouse_hovering_rect(in, *bounds))
  28519         *state = NK_WIDGET_STATE_HOVERED;
  28520     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
  28521         *state |= NK_WIDGET_STATE_ENTERED;
  28522     else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
  28523         *state |= NK_WIDGET_STATE_LEFT;
  28524     return value_changed;
  28525 }
  28526 NK_LIB void
  28527 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
  28528     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
  28529     struct nk_colorf col)
  28530 {
  28531     NK_STORAGE const struct nk_color black = {0,0,0,255};
  28532     NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
  28533     NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
  28534 
  28535     const float crosshair_size = 7.0f;
  28536     struct nk_color temp;
  28537     float hsva[4];
  28538     float line_y;
  28539     int i;
  28540 
  28541     NK_ASSERT(o);
  28542     NK_ASSERT(matrix);
  28543     NK_ASSERT(hue_bar);
  28544 
  28545     /* draw hue bar */
  28546     nk_colorf_hsva_fv(hsva, col);
  28547     for (i = 0; i < 6; ++i) {
  28548         NK_GLOBAL const struct nk_color hue_colors[] = {
  28549             {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255},
  28550             {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}
  28551         };
  28552         nk_fill_rect_multi_color(o,
  28553             nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
  28554                 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
  28555                 hue_colors[i+1], hue_colors[i+1]);
  28556     }
  28557     line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
  28558     nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
  28559         line_y, 1, nk_rgb(255,255,255));
  28560 
  28561     /* draw alpha bar */
  28562     if (alpha_bar) {
  28563         float alpha = NK_SATURATE(col.a);
  28564         line_y = (float)(int)(alpha_bar->y +  (1.0f - alpha) * matrix->h + 0.5f);
  28565 
  28566         nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
  28567         nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
  28568             line_y, 1, nk_rgb(255,255,255));
  28569     }
  28570 
  28571     /* draw color matrix */
  28572     temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
  28573     nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
  28574     nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
  28575 
  28576     /* draw cross-hair */
  28577     {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
  28578     p.x = (float)(int)(matrix->x + S * matrix->w);
  28579     p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
  28580     nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
  28581     nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
  28582     nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
  28583     nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
  28584 }
  28585 NK_LIB nk_bool
  28586 nk_do_color_picker(nk_flags *state,
  28587     struct nk_command_buffer *out, struct nk_colorf *col,
  28588     enum nk_color_format fmt, struct nk_rect bounds,
  28589     struct nk_vec2 padding, const struct nk_input *in,
  28590     const struct nk_user_font *font)
  28591 {
  28592     int ret = 0;
  28593     struct nk_rect matrix;
  28594     struct nk_rect hue_bar;
  28595     struct nk_rect alpha_bar;
  28596     float bar_w;
  28597 
  28598     NK_ASSERT(out);
  28599     NK_ASSERT(col);
  28600     NK_ASSERT(state);
  28601     NK_ASSERT(font);
  28602     if (!out || !col || !state || !font)
  28603         return ret;
  28604 
  28605     bar_w = font->height;
  28606     bounds.x += padding.x;
  28607     bounds.y += padding.x;
  28608     bounds.w -= 2 * padding.x;
  28609     bounds.h -= 2 * padding.y;
  28610 
  28611     matrix.x = bounds.x;
  28612     matrix.y = bounds.y;
  28613     matrix.h = bounds.h;
  28614     matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
  28615 
  28616     hue_bar.w = bar_w;
  28617     hue_bar.y = bounds.y;
  28618     hue_bar.h = matrix.h;
  28619     hue_bar.x = matrix.x + matrix.w + padding.x;
  28620 
  28621     alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
  28622     alpha_bar.y = bounds.y;
  28623     alpha_bar.w = bar_w;
  28624     alpha_bar.h = matrix.h;
  28625 
  28626     ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
  28627         (fmt == NK_RGBA) ? &alpha_bar:0, col, in);
  28628     nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col);
  28629     return ret;
  28630 }
  28631 NK_API nk_bool
  28632 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color,
  28633     enum nk_color_format fmt)
  28634 {
  28635     struct nk_window *win;
  28636     struct nk_panel *layout;
  28637     const struct nk_style *config;
  28638     const struct nk_input *in;
  28639 
  28640     enum nk_widget_layout_states state;
  28641     struct nk_rect bounds;
  28642 
  28643     NK_ASSERT(ctx);
  28644     NK_ASSERT(color);
  28645     NK_ASSERT(ctx->current);
  28646     NK_ASSERT(ctx->current->layout);
  28647     if (!ctx || !ctx->current || !ctx->current->layout || !color)
  28648         return 0;
  28649 
  28650     win = ctx->current;
  28651     config = &ctx->style;
  28652     layout = win->layout;
  28653     state = nk_widget(&bounds, ctx);
  28654     if (!state) return 0;
  28655     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  28656     return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
  28657                 nk_vec2(0,0), in, config->font);
  28658 }
  28659 NK_API struct nk_colorf
  28660 nk_color_picker(struct nk_context *ctx, struct nk_colorf color,
  28661     enum nk_color_format fmt)
  28662 {
  28663     nk_color_pick(ctx, &color, fmt);
  28664     return color;
  28665 }
  28666 
  28667 
  28668 
  28669 
  28670 
  28671 /* ==============================================================
  28672  *
  28673  *                          COMBO
  28674  *
  28675  * ===============================================================*/
  28676 NK_INTERN nk_bool
  28677 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
  28678     struct nk_vec2 size, nk_bool is_clicked, struct nk_rect header)
  28679 {
  28680     struct nk_window *popup;
  28681     int is_open = 0;
  28682     int is_active = 0;
  28683     struct nk_rect body;
  28684     nk_hash hash;
  28685 
  28686     NK_ASSERT(ctx);
  28687     NK_ASSERT(ctx->current);
  28688     NK_ASSERT(ctx->current->layout);
  28689     if (!ctx || !ctx->current || !ctx->current->layout)
  28690         return 0;
  28691 
  28692     popup = win->popup.win;
  28693     body.x = header.x;
  28694     body.w = size.x;
  28695     body.y = header.y + header.h-ctx->style.window.combo_border;
  28696     body.h = size.y;
  28697 
  28698     hash = win->popup.combo_count++;
  28699     is_open = (popup) ? nk_true:nk_false;
  28700     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
  28701     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
  28702         (!is_open && !is_active && !is_clicked)) return 0;
  28703     if (!nk_nonblock_begin(ctx, 0, body,
  28704         (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
  28705 
  28706     win->popup.type = NK_PANEL_COMBO;
  28707     win->popup.name = hash;
  28708     return 1;
  28709 }
  28710 NK_API nk_bool
  28711 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
  28712     struct nk_vec2 size)
  28713 {
  28714     const struct nk_input *in;
  28715     struct nk_window *win;
  28716     struct nk_style *style;
  28717 
  28718     enum nk_widget_layout_states s;
  28719     int is_clicked = nk_false;
  28720     struct nk_rect header;
  28721     const struct nk_style_item *background;
  28722     struct nk_text text;
  28723 
  28724     NK_ASSERT(ctx);
  28725     NK_ASSERT(selected);
  28726     NK_ASSERT(ctx->current);
  28727     NK_ASSERT(ctx->current->layout);
  28728     if (!ctx || !ctx->current || !ctx->current->layout || !selected)
  28729         return 0;
  28730 
  28731     win = ctx->current;
  28732     style = &ctx->style;
  28733     s = nk_widget(&header, ctx);
  28734     if (s == NK_WIDGET_INVALID)
  28735         return 0;
  28736 
  28737     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  28738     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  28739         is_clicked = nk_true;
  28740 
  28741     /* draw combo box header background and border */
  28742     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
  28743         background = &style->combo.active;
  28744         text.text = style->combo.label_active;
  28745     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
  28746         background = &style->combo.hover;
  28747         text.text = style->combo.label_hover;
  28748     } else {
  28749         background = &style->combo.normal;
  28750         text.text = style->combo.label_normal;
  28751     }
  28752 
  28753     switch(background->type) {
  28754         case NK_STYLE_ITEM_IMAGE:
  28755             text.background = nk_rgba(0, 0, 0, 0);
  28756             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  28757             break;
  28758         case NK_STYLE_ITEM_NINE_SLICE:
  28759             text.background = nk_rgba(0, 0, 0, 0);
  28760             nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
  28761             break;
  28762         case NK_STYLE_ITEM_COLOR:
  28763             text.background = background->data.color;
  28764             nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  28765             nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  28766             break;
  28767     }
  28768     {
  28769         /* print currently selected text item */
  28770         struct nk_rect label;
  28771         struct nk_rect button;
  28772         struct nk_rect content;
  28773         int draw_button_symbol;
  28774 
  28775         enum nk_symbol_type sym;
  28776         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  28777             sym = style->combo.sym_hover;
  28778         else if (is_clicked)
  28779             sym = style->combo.sym_active;
  28780         else
  28781             sym = style->combo.sym_normal;
  28782 
  28783         /* represents whether or not the combo's button symbol should be drawn */
  28784         draw_button_symbol = sym != NK_SYMBOL_NONE;
  28785 
  28786         /* calculate button */
  28787         button.w = header.h - 2 * style->combo.button_padding.y;
  28788         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
  28789         button.y = header.y + style->combo.button_padding.y;
  28790         button.h = button.w;
  28791 
  28792         content.x = button.x + style->combo.button.padding.x;
  28793         content.y = button.y + style->combo.button.padding.y;
  28794         content.w = button.w - 2 * style->combo.button.padding.x;
  28795         content.h = button.h - 2 * style->combo.button.padding.y;
  28796 
  28797         /* draw selected label */
  28798         text.padding = nk_vec2(0,0);
  28799         label.x = header.x + style->combo.content_padding.x;
  28800         label.y = header.y + style->combo.content_padding.y;
  28801         label.h = header.h - 2 * style->combo.content_padding.y;
  28802         if (draw_button_symbol)
  28803             label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;
  28804         else
  28805             label.w = header.w - 2 * style->combo.content_padding.x;
  28806         nk_widget_text(&win->buffer, label, selected, len, &text,
  28807             NK_TEXT_LEFT, ctx->style.font);
  28808 
  28809         /* draw open/close button */
  28810         if (draw_button_symbol)
  28811             nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
  28812                 &ctx->style.combo.button, sym, style->font);
  28813     }
  28814     return nk_combo_begin(ctx, win, size, is_clicked, header);
  28815 }
  28816 NK_API nk_bool
  28817 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
  28818 {
  28819     return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);
  28820 }
  28821 NK_API nk_bool
  28822 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
  28823 {
  28824     struct nk_window *win;
  28825     struct nk_style *style;
  28826     const struct nk_input *in;
  28827 
  28828     struct nk_rect header;
  28829     int is_clicked = nk_false;
  28830     enum nk_widget_layout_states s;
  28831     const struct nk_style_item *background;
  28832 
  28833     NK_ASSERT(ctx);
  28834     NK_ASSERT(ctx->current);
  28835     NK_ASSERT(ctx->current->layout);
  28836     if (!ctx || !ctx->current || !ctx->current->layout)
  28837         return 0;
  28838 
  28839     win = ctx->current;
  28840     style = &ctx->style;
  28841     s = nk_widget(&header, ctx);
  28842     if (s == NK_WIDGET_INVALID)
  28843         return 0;
  28844 
  28845     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  28846     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  28847         is_clicked = nk_true;
  28848 
  28849     /* draw combo box header background and border */
  28850     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
  28851         background = &style->combo.active;
  28852     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  28853         background = &style->combo.hover;
  28854     else background = &style->combo.normal;
  28855 
  28856     switch(background->type) {
  28857         case NK_STYLE_ITEM_IMAGE:
  28858             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  28859             break;
  28860         case NK_STYLE_ITEM_NINE_SLICE:
  28861             nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
  28862             break;
  28863         case NK_STYLE_ITEM_COLOR:
  28864             nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  28865             nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  28866             break;
  28867     }
  28868     {
  28869         struct nk_rect content;
  28870         struct nk_rect button;
  28871         struct nk_rect bounds;
  28872         int draw_button_symbol;
  28873 
  28874         enum nk_symbol_type sym;
  28875         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  28876             sym = style->combo.sym_hover;
  28877         else if (is_clicked)
  28878             sym = style->combo.sym_active;
  28879         else sym = style->combo.sym_normal;
  28880 
  28881         /* represents whether or not the combo's button symbol should be drawn */
  28882         draw_button_symbol = sym != NK_SYMBOL_NONE;
  28883 
  28884         /* calculate button */
  28885         button.w = header.h - 2 * style->combo.button_padding.y;
  28886         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
  28887         button.y = header.y + style->combo.button_padding.y;
  28888         button.h = button.w;
  28889 
  28890         content.x = button.x + style->combo.button.padding.x;
  28891         content.y = button.y + style->combo.button.padding.y;
  28892         content.w = button.w - 2 * style->combo.button.padding.x;
  28893         content.h = button.h - 2 * style->combo.button.padding.y;
  28894 
  28895         /* draw color */
  28896         bounds.h = header.h - 4 * style->combo.content_padding.y;
  28897         bounds.y = header.y + 2 * style->combo.content_padding.y;
  28898         bounds.x = header.x + 2 * style->combo.content_padding.x;
  28899         if (draw_button_symbol)
  28900             bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
  28901         else
  28902             bounds.w = header.w - 4 * style->combo.content_padding.x;
  28903         nk_fill_rect(&win->buffer, bounds, 0, color);
  28904 
  28905         /* draw open/close button */
  28906         if (draw_button_symbol)
  28907             nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
  28908                 &ctx->style.combo.button, sym, style->font);
  28909     }
  28910     return nk_combo_begin(ctx, win, size, is_clicked, header);
  28911 }
  28912 NK_API nk_bool
  28913 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
  28914 {
  28915     struct nk_window *win;
  28916     struct nk_style *style;
  28917     const struct nk_input *in;
  28918 
  28919     struct nk_rect header;
  28920     int is_clicked = nk_false;
  28921     enum nk_widget_layout_states s;
  28922     const struct nk_style_item *background;
  28923     struct nk_color sym_background;
  28924     struct nk_color symbol_color;
  28925 
  28926     NK_ASSERT(ctx);
  28927     NK_ASSERT(ctx->current);
  28928     NK_ASSERT(ctx->current->layout);
  28929     if (!ctx || !ctx->current || !ctx->current->layout)
  28930         return 0;
  28931 
  28932     win = ctx->current;
  28933     style = &ctx->style;
  28934     s = nk_widget(&header, ctx);
  28935     if (s == NK_WIDGET_INVALID)
  28936         return 0;
  28937 
  28938     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  28939     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  28940         is_clicked = nk_true;
  28941 
  28942     /* draw combo box header background and border */
  28943     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
  28944         background = &style->combo.active;
  28945         symbol_color = style->combo.symbol_active;
  28946     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
  28947         background = &style->combo.hover;
  28948         symbol_color = style->combo.symbol_hover;
  28949     } else {
  28950         background = &style->combo.normal;
  28951         symbol_color = style->combo.symbol_hover;
  28952     }
  28953 
  28954     switch(background->type) {
  28955         case NK_STYLE_ITEM_IMAGE:
  28956             sym_background = nk_rgba(0, 0, 0, 0);
  28957             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  28958             break;
  28959         case NK_STYLE_ITEM_NINE_SLICE:
  28960             sym_background = nk_rgba(0, 0, 0, 0);
  28961             nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
  28962             break;
  28963         case NK_STYLE_ITEM_COLOR:
  28964             sym_background = background->data.color;
  28965             nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  28966             nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  28967             break;
  28968     }
  28969     {
  28970         struct nk_rect bounds = {0,0,0,0};
  28971         struct nk_rect content;
  28972         struct nk_rect button;
  28973 
  28974         enum nk_symbol_type sym;
  28975         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  28976             sym = style->combo.sym_hover;
  28977         else if (is_clicked)
  28978             sym = style->combo.sym_active;
  28979         else sym = style->combo.sym_normal;
  28980 
  28981         /* calculate button */
  28982         button.w = header.h - 2 * style->combo.button_padding.y;
  28983         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
  28984         button.y = header.y + style->combo.button_padding.y;
  28985         button.h = button.w;
  28986 
  28987         content.x = button.x + style->combo.button.padding.x;
  28988         content.y = button.y + style->combo.button.padding.y;
  28989         content.w = button.w - 2 * style->combo.button.padding.x;
  28990         content.h = button.h - 2 * style->combo.button.padding.y;
  28991 
  28992         /* draw symbol */
  28993         bounds.h = header.h - 2 * style->combo.content_padding.y;
  28994         bounds.y = header.y + style->combo.content_padding.y;
  28995         bounds.x = header.x + style->combo.content_padding.x;
  28996         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
  28997         nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
  28998             1.0f, style->font);
  28999 
  29000         /* draw open/close button */
  29001         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
  29002             &ctx->style.combo.button, sym, style->font);
  29003     }
  29004     return nk_combo_begin(ctx, win, size, is_clicked, header);
  29005 }
  29006 NK_API nk_bool
  29007 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
  29008     enum nk_symbol_type symbol, struct nk_vec2 size)
  29009 {
  29010     struct nk_window *win;
  29011     struct nk_style *style;
  29012     struct nk_input *in;
  29013 
  29014     struct nk_rect header;
  29015     int is_clicked = nk_false;
  29016     enum nk_widget_layout_states s;
  29017     const struct nk_style_item *background;
  29018     struct nk_color symbol_color;
  29019     struct nk_text text;
  29020 
  29021     NK_ASSERT(ctx);
  29022     NK_ASSERT(ctx->current);
  29023     NK_ASSERT(ctx->current->layout);
  29024     if (!ctx || !ctx->current || !ctx->current->layout)
  29025         return 0;
  29026 
  29027     win = ctx->current;
  29028     style = &ctx->style;
  29029     s = nk_widget(&header, ctx);
  29030     if (!s) return 0;
  29031 
  29032     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  29033     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  29034         is_clicked = nk_true;
  29035 
  29036     /* draw combo box header background and border */
  29037     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
  29038         background = &style->combo.active;
  29039         symbol_color = style->combo.symbol_active;
  29040         text.text = style->combo.label_active;
  29041     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
  29042         background = &style->combo.hover;
  29043         symbol_color = style->combo.symbol_hover;
  29044         text.text = style->combo.label_hover;
  29045     } else {
  29046         background = &style->combo.normal;
  29047         symbol_color = style->combo.symbol_normal;
  29048         text.text = style->combo.label_normal;
  29049     }
  29050 
  29051     switch(background->type) {
  29052         case NK_STYLE_ITEM_IMAGE:
  29053             text.background = nk_rgba(0, 0, 0, 0);
  29054             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  29055             break;
  29056         case NK_STYLE_ITEM_NINE_SLICE:
  29057             text.background = nk_rgba(0, 0, 0, 0);
  29058             nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
  29059             break;
  29060         case NK_STYLE_ITEM_COLOR:
  29061             text.background = background->data.color;
  29062             nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  29063             nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  29064             break;
  29065     }
  29066     {
  29067         struct nk_rect content;
  29068         struct nk_rect button;
  29069         struct nk_rect label;
  29070         struct nk_rect image;
  29071 
  29072         enum nk_symbol_type sym;
  29073         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  29074             sym = style->combo.sym_hover;
  29075         else if (is_clicked)
  29076             sym = style->combo.sym_active;
  29077         else sym = style->combo.sym_normal;
  29078 
  29079         /* calculate button */
  29080         button.w = header.h - 2 * style->combo.button_padding.y;
  29081         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
  29082         button.y = header.y + style->combo.button_padding.y;
  29083         button.h = button.w;
  29084 
  29085         content.x = button.x + style->combo.button.padding.x;
  29086         content.y = button.y + style->combo.button.padding.y;
  29087         content.w = button.w - 2 * style->combo.button.padding.x;
  29088         content.h = button.h - 2 * style->combo.button.padding.y;
  29089         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
  29090             &ctx->style.combo.button, sym, style->font);
  29091 
  29092         /* draw symbol */
  29093         image.x = header.x + style->combo.content_padding.x;
  29094         image.y = header.y + style->combo.content_padding.y;
  29095         image.h = header.h - 2 * style->combo.content_padding.y;
  29096         image.w = image.h;
  29097         nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
  29098             1.0f, style->font);
  29099 
  29100         /* draw label */
  29101         text.padding = nk_vec2(0,0);
  29102         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
  29103         label.y = header.y + style->combo.content_padding.y;
  29104         label.w = (button.x - style->combo.content_padding.x) - label.x;
  29105         label.h = header.h - 2 * style->combo.content_padding.y;
  29106         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
  29107     }
  29108     return nk_combo_begin(ctx, win, size, is_clicked, header);
  29109 }
  29110 NK_API nk_bool
  29111 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
  29112 {
  29113     struct nk_window *win;
  29114     struct nk_style *style;
  29115     const struct nk_input *in;
  29116 
  29117     struct nk_rect header;
  29118     int is_clicked = nk_false;
  29119     enum nk_widget_layout_states s;
  29120     const struct nk_style_item *background;
  29121 
  29122     NK_ASSERT(ctx);
  29123     NK_ASSERT(ctx->current);
  29124     NK_ASSERT(ctx->current->layout);
  29125     if (!ctx || !ctx->current || !ctx->current->layout)
  29126         return 0;
  29127 
  29128     win = ctx->current;
  29129     style = &ctx->style;
  29130     s = nk_widget(&header, ctx);
  29131     if (s == NK_WIDGET_INVALID)
  29132         return 0;
  29133 
  29134     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  29135     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  29136         is_clicked = nk_true;
  29137 
  29138     /* draw combo box header background and border */
  29139     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
  29140         background = &style->combo.active;
  29141     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  29142         background = &style->combo.hover;
  29143     else background = &style->combo.normal;
  29144 
  29145     switch (background->type) {
  29146         case NK_STYLE_ITEM_IMAGE:
  29147             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  29148             break;
  29149         case NK_STYLE_ITEM_NINE_SLICE:
  29150             nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
  29151             break;
  29152         case NK_STYLE_ITEM_COLOR:
  29153             nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  29154             nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  29155             break;
  29156     }
  29157     {
  29158         struct nk_rect bounds = {0,0,0,0};
  29159         struct nk_rect content;
  29160         struct nk_rect button;
  29161         int draw_button_symbol;
  29162 
  29163         enum nk_symbol_type sym;
  29164         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  29165             sym = style->combo.sym_hover;
  29166         else if (is_clicked)
  29167             sym = style->combo.sym_active;
  29168         else sym = style->combo.sym_normal;
  29169 
  29170         /* represents whether or not the combo's button symbol should be drawn */
  29171         draw_button_symbol = sym != NK_SYMBOL_NONE;
  29172 
  29173         /* calculate button */
  29174         button.w = header.h - 2 * style->combo.button_padding.y;
  29175         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
  29176         button.y = header.y + style->combo.button_padding.y;
  29177         button.h = button.w;
  29178 
  29179         content.x = button.x + style->combo.button.padding.x;
  29180         content.y = button.y + style->combo.button.padding.y;
  29181         content.w = button.w - 2 * style->combo.button.padding.x;
  29182         content.h = button.h - 2 * style->combo.button.padding.y;
  29183 
  29184         /* draw image */
  29185         bounds.h = header.h - 2 * style->combo.content_padding.y;
  29186         bounds.y = header.y + style->combo.content_padding.y;
  29187         bounds.x = header.x + style->combo.content_padding.x;
  29188         if (draw_button_symbol)
  29189             bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
  29190         else
  29191             bounds.w = header.w - 2 * style->combo.content_padding.x;
  29192         nk_draw_image(&win->buffer, bounds, &img, nk_white);
  29193 
  29194         /* draw open/close button */
  29195         if (draw_button_symbol)
  29196             nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
  29197                 &ctx->style.combo.button, sym, style->font);
  29198     }
  29199     return nk_combo_begin(ctx, win, size, is_clicked, header);
  29200 }
  29201 NK_API nk_bool
  29202 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
  29203     struct nk_image img, struct nk_vec2 size)
  29204 {
  29205     struct nk_window *win;
  29206     struct nk_style *style;
  29207     struct nk_input *in;
  29208 
  29209     struct nk_rect header;
  29210     int is_clicked = nk_false;
  29211     enum nk_widget_layout_states s;
  29212     const struct nk_style_item *background;
  29213     struct nk_text text;
  29214 
  29215     NK_ASSERT(ctx);
  29216     NK_ASSERT(ctx->current);
  29217     NK_ASSERT(ctx->current->layout);
  29218     if (!ctx || !ctx->current || !ctx->current->layout)
  29219         return 0;
  29220 
  29221     win = ctx->current;
  29222     style = &ctx->style;
  29223     s = nk_widget(&header, ctx);
  29224     if (!s) return 0;
  29225 
  29226     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  29227     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  29228         is_clicked = nk_true;
  29229 
  29230     /* draw combo box header background and border */
  29231     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
  29232         background = &style->combo.active;
  29233         text.text = style->combo.label_active;
  29234     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
  29235         background = &style->combo.hover;
  29236         text.text = style->combo.label_hover;
  29237     } else {
  29238         background = &style->combo.normal;
  29239         text.text = style->combo.label_normal;
  29240     }
  29241 
  29242     switch(background->type) {
  29243         case NK_STYLE_ITEM_IMAGE:
  29244             text.background = nk_rgba(0, 0, 0, 0);
  29245             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  29246             break;
  29247         case NK_STYLE_ITEM_NINE_SLICE:
  29248             text.background = nk_rgba(0, 0, 0, 0);
  29249             nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
  29250             break;
  29251         case NK_STYLE_ITEM_COLOR:
  29252             text.background = background->data.color;
  29253             nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  29254             nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  29255             break;
  29256     }
  29257     {
  29258         struct nk_rect content;
  29259         struct nk_rect button;
  29260         struct nk_rect label;
  29261         struct nk_rect image;
  29262         int draw_button_symbol;
  29263 
  29264         enum nk_symbol_type sym;
  29265         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  29266             sym = style->combo.sym_hover;
  29267         else if (is_clicked)
  29268             sym = style->combo.sym_active;
  29269         else sym = style->combo.sym_normal;
  29270 
  29271         /* represents whether or not the combo's button symbol should be drawn */
  29272         draw_button_symbol = sym != NK_SYMBOL_NONE;
  29273 
  29274         /* calculate button */
  29275         button.w = header.h - 2 * style->combo.button_padding.y;
  29276         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
  29277         button.y = header.y + style->combo.button_padding.y;
  29278         button.h = button.w;
  29279 
  29280         content.x = button.x + style->combo.button.padding.x;
  29281         content.y = button.y + style->combo.button.padding.y;
  29282         content.w = button.w - 2 * style->combo.button.padding.x;
  29283         content.h = button.h - 2 * style->combo.button.padding.y;
  29284         if (draw_button_symbol)
  29285             nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
  29286                 &ctx->style.combo.button, sym, style->font);
  29287 
  29288         /* draw image */
  29289         image.x = header.x + style->combo.content_padding.x;
  29290         image.y = header.y + style->combo.content_padding.y;
  29291         image.h = header.h - 2 * style->combo.content_padding.y;
  29292         image.w = image.h;
  29293         nk_draw_image(&win->buffer, image, &img, nk_white);
  29294 
  29295         /* draw label */
  29296         text.padding = nk_vec2(0,0);
  29297         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
  29298         label.y = header.y + style->combo.content_padding.y;
  29299         label.h = header.h - 2 * style->combo.content_padding.y;
  29300         if (draw_button_symbol)
  29301             label.w = (button.x - style->combo.content_padding.x) - label.x;
  29302         else
  29303             label.w = (header.x + header.w - style->combo.content_padding.x) - label.x;
  29304         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
  29305     }
  29306     return nk_combo_begin(ctx, win, size, is_clicked, header);
  29307 }
  29308 NK_API nk_bool
  29309 nk_combo_begin_symbol_label(struct nk_context *ctx,
  29310     const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
  29311 {
  29312     return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);
  29313 }
  29314 NK_API nk_bool
  29315 nk_combo_begin_image_label(struct nk_context *ctx,
  29316     const char *selected, struct nk_image img, struct nk_vec2 size)
  29317 {
  29318     return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);
  29319 }
  29320 NK_API nk_bool
  29321 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
  29322 {
  29323     return nk_contextual_item_text(ctx, text, len, align);
  29324 }
  29325 NK_API nk_bool
  29326 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
  29327 {
  29328     return nk_contextual_item_label(ctx, label, align);
  29329 }
  29330 NK_API nk_bool
  29331 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
  29332     int len, nk_flags alignment)
  29333 {
  29334     return nk_contextual_item_image_text(ctx, img, text, len, alignment);
  29335 }
  29336 NK_API nk_bool
  29337 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
  29338     const char *text, nk_flags alignment)
  29339 {
  29340     return nk_contextual_item_image_label(ctx, img, text, alignment);
  29341 }
  29342 NK_API nk_bool
  29343 nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  29344     const char *text, int len, nk_flags alignment)
  29345 {
  29346     return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);
  29347 }
  29348 NK_API nk_bool
  29349 nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  29350     const char *label, nk_flags alignment)
  29351 {
  29352     return nk_contextual_item_symbol_label(ctx, sym, label, alignment);
  29353 }
  29354 NK_API void nk_combo_end(struct nk_context *ctx)
  29355 {
  29356     nk_contextual_end(ctx);
  29357 }
  29358 NK_API void nk_combo_close(struct nk_context *ctx)
  29359 {
  29360     nk_contextual_close(ctx);
  29361 }
  29362 NK_API int
  29363 nk_combo(struct nk_context *ctx, const char **items, int count,
  29364     int selected, int item_height, struct nk_vec2 size)
  29365 {
  29366     int i = 0;
  29367     int max_height;
  29368     struct nk_vec2 item_spacing;
  29369     struct nk_vec2 window_padding;
  29370 
  29371     NK_ASSERT(ctx);
  29372     NK_ASSERT(items);
  29373     NK_ASSERT(ctx->current);
  29374     if (!ctx || !items ||!count)
  29375         return selected;
  29376 
  29377     item_spacing = ctx->style.window.spacing;
  29378     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
  29379     max_height = count * item_height + count * (int)item_spacing.y;
  29380     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
  29381     size.y = NK_MIN(size.y, (float)max_height);
  29382     if (nk_combo_begin_label(ctx, items[selected], size)) {
  29383         nk_layout_row_dynamic(ctx, (float)item_height, 1);
  29384         for (i = 0; i < count; ++i) {
  29385             if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
  29386                 selected = i;
  29387         }
  29388         nk_combo_end(ctx);
  29389     }
  29390     return selected;
  29391 }
  29392 NK_API int
  29393 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
  29394     int separator, int selected, int count, int item_height, struct nk_vec2 size)
  29395 {
  29396     int i;
  29397     int max_height;
  29398     struct nk_vec2 item_spacing;
  29399     struct nk_vec2 window_padding;
  29400     const char *current_item;
  29401     const char *iter;
  29402     int length = 0;
  29403 
  29404     NK_ASSERT(ctx);
  29405     NK_ASSERT(items_separated_by_separator);
  29406     if (!ctx || !items_separated_by_separator)
  29407         return selected;
  29408 
  29409     /* calculate popup window */
  29410     item_spacing = ctx->style.window.spacing;
  29411     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
  29412     max_height = count * item_height + count * (int)item_spacing.y;
  29413     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
  29414     size.y = NK_MIN(size.y, (float)max_height);
  29415 
  29416     /* find selected item */
  29417     current_item = items_separated_by_separator;
  29418     for (i = 0; i < count; ++i) {
  29419         iter = current_item;
  29420         while (*iter && *iter != separator) iter++;
  29421         length = (int)(iter - current_item);
  29422         if (i == selected) break;
  29423         current_item = iter + 1;
  29424     }
  29425 
  29426     if (nk_combo_begin_text(ctx, current_item, length, size)) {
  29427         current_item = items_separated_by_separator;
  29428         nk_layout_row_dynamic(ctx, (float)item_height, 1);
  29429         for (i = 0; i < count; ++i) {
  29430             iter = current_item;
  29431             while (*iter && *iter != separator) iter++;
  29432             length = (int)(iter - current_item);
  29433             if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
  29434                 selected = i;
  29435             current_item = current_item + length + 1;
  29436         }
  29437         nk_combo_end(ctx);
  29438     }
  29439     return selected;
  29440 }
  29441 NK_API int
  29442 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
  29443     int selected, int count, int item_height, struct nk_vec2 size)
  29444 {
  29445     return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);
  29446 }
  29447 NK_API int
  29448 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
  29449     void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
  29450 {
  29451     int i;
  29452     int max_height;
  29453     struct nk_vec2 item_spacing;
  29454     struct nk_vec2 window_padding;
  29455     const char *item;
  29456 
  29457     NK_ASSERT(ctx);
  29458     NK_ASSERT(item_getter);
  29459     if (!ctx || !item_getter)
  29460         return selected;
  29461 
  29462     /* calculate popup window */
  29463     item_spacing = ctx->style.window.spacing;
  29464     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
  29465     max_height = count * item_height + count * (int)item_spacing.y;
  29466     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
  29467     size.y = NK_MIN(size.y, (float)max_height);
  29468 
  29469     item_getter(userdata, selected, &item);
  29470     if (nk_combo_begin_label(ctx, item, size)) {
  29471         nk_layout_row_dynamic(ctx, (float)item_height, 1);
  29472         for (i = 0; i < count; ++i) {
  29473             item_getter(userdata, i, &item);
  29474             if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
  29475                 selected = i;
  29476         }
  29477         nk_combo_end(ctx);
  29478     } return selected;
  29479 }
  29480 NK_API void
  29481 nk_combobox(struct nk_context *ctx, const char **items, int count,
  29482     int *selected, int item_height, struct nk_vec2 size)
  29483 {
  29484     *selected = nk_combo(ctx, items, count, *selected, item_height, size);
  29485 }
  29486 NK_API void
  29487 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
  29488     int *selected, int count, int item_height, struct nk_vec2 size)
  29489 {
  29490     *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);
  29491 }
  29492 NK_API void
  29493 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
  29494     int separator, int *selected, int count, int item_height, struct nk_vec2 size)
  29495 {
  29496     *selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
  29497                                     *selected, count, item_height, size);
  29498 }
  29499 NK_API void
  29500 nk_combobox_callback(struct nk_context *ctx,
  29501     void(*item_getter)(void* data, int id, const char **out_text),
  29502     void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
  29503 {
  29504     *selected = nk_combo_callback(ctx, item_getter, userdata,  *selected, count, item_height, size);
  29505 }
  29506 
  29507 
  29508 
  29509 
  29510 
  29511 /* ===============================================================
  29512  *
  29513  *                              TOOLTIP
  29514  *
  29515  * ===============================================================*/
  29516 NK_API nk_bool
  29517 nk_tooltip_begin(struct nk_context *ctx, float width)
  29518 {
  29519     int x,y,w,h;
  29520     struct nk_window *win;
  29521     const struct nk_input *in;
  29522     struct nk_rect bounds;
  29523     int ret;
  29524 
  29525     NK_ASSERT(ctx);
  29526     NK_ASSERT(ctx->current);
  29527     NK_ASSERT(ctx->current->layout);
  29528     if (!ctx || !ctx->current || !ctx->current->layout)
  29529         return 0;
  29530 
  29531     /* make sure that no nonblocking popup is currently active */
  29532     win = ctx->current;
  29533     in = &ctx->input;
  29534     if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
  29535         return 0;
  29536 
  29537     w = nk_iceilf(width);
  29538     h = nk_iceilf(nk_null_rect.h);
  29539     x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x;
  29540     y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y;
  29541 
  29542     bounds.x = (float)x;
  29543     bounds.y = (float)y;
  29544     bounds.w = (float)w;
  29545     bounds.h = (float)h;
  29546 
  29547     ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
  29548         "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
  29549     if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
  29550     win->popup.type = NK_PANEL_TOOLTIP;
  29551     ctx->current->layout->type = NK_PANEL_TOOLTIP;
  29552     return ret;
  29553 }
  29554 
  29555 NK_API void
  29556 nk_tooltip_end(struct nk_context *ctx)
  29557 {
  29558     NK_ASSERT(ctx);
  29559     NK_ASSERT(ctx->current);
  29560     if (!ctx || !ctx->current) return;
  29561     ctx->current->seq--;
  29562     nk_popup_close(ctx);
  29563     nk_popup_end(ctx);
  29564 }
  29565 NK_API void
  29566 nk_tooltip(struct nk_context *ctx, const char *text)
  29567 {
  29568     const struct nk_style *style;
  29569     struct nk_vec2 padding;
  29570 
  29571     int text_len;
  29572     float text_width;
  29573     float text_height;
  29574 
  29575     NK_ASSERT(ctx);
  29576     NK_ASSERT(ctx->current);
  29577     NK_ASSERT(ctx->current->layout);
  29578     NK_ASSERT(text);
  29579     if (!ctx || !ctx->current || !ctx->current->layout || !text)
  29580         return;
  29581 
  29582     /* fetch configuration data */
  29583     style = &ctx->style;
  29584     padding = style->window.padding;
  29585 
  29586     /* calculate size of the text and tooltip */
  29587     text_len = nk_strlen(text);
  29588     text_width = style->font->width(style->font->userdata,
  29589                     style->font->height, text, text_len);
  29590     text_width += (4 * padding.x);
  29591     text_height = (style->font->height + 2 * padding.y);
  29592 
  29593     /* execute tooltip and fill with text */
  29594     if (nk_tooltip_begin(ctx, (float)text_width)) {
  29595         nk_layout_row_dynamic(ctx, (float)text_height, 1);
  29596         nk_text(ctx, text, text_len, NK_TEXT_LEFT);
  29597         nk_tooltip_end(ctx);
  29598     }
  29599 }
  29600 #ifdef NK_INCLUDE_STANDARD_VARARGS
  29601 NK_API void
  29602 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...)
  29603 {
  29604     va_list args;
  29605     va_start(args, fmt);
  29606     nk_tooltipfv(ctx, fmt, args);
  29607     va_end(args);
  29608 }
  29609 NK_API void
  29610 nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
  29611 {
  29612     char buf[256];
  29613     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  29614     nk_tooltip(ctx, buf);
  29615 }
  29616 #endif
  29617 
  29618 
  29619 
  29620 #endif /* NK_IMPLEMENTATION */
  29621 
  29622 /*
  29623 /// ## License
  29624 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
  29625 ///    ------------------------------------------------------------------------------
  29626 ///    This software is available under 2 licenses -- choose whichever you prefer.
  29627 ///    ------------------------------------------------------------------------------
  29628 ///    ALTERNATIVE A - MIT License
  29629 ///    Copyright (c) 2016-2018 Micha Mettke
  29630 ///    Permission is hereby granted, free of charge, to any person obtaining a copy of
  29631 ///    this software and associated documentation files (the "Software"), to deal in
  29632 ///    the Software without restriction, including without limitation the rights to
  29633 ///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  29634 ///    of the Software, and to permit persons to whom the Software is furnished to do
  29635 ///    so, subject to the following conditions:
  29636 ///    The above copyright notice and this permission notice shall be included in all
  29637 ///    copies or substantial portions of the Software.
  29638 ///    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29639 ///    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29640 ///    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  29641 ///    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  29642 ///    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  29643 ///    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  29644 ///    SOFTWARE.
  29645 ///    ------------------------------------------------------------------------------
  29646 ///    ALTERNATIVE B - Public Domain (www.unlicense.org)
  29647 ///    This is free and unencumbered software released into the public domain.
  29648 ///    Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
  29649 ///    software, either in source code form or as a compiled binary, for any purpose,
  29650 ///    commercial or non-commercial, and by any means.
  29651 ///    In jurisdictions that recognize copyright laws, the author or authors of this
  29652 ///    software dedicate any and all copyright interest in the software to the public
  29653 ///    domain. We make this dedication for the benefit of the public at large and to
  29654 ///    the detriment of our heirs and successors. We intend this dedication to be an
  29655 ///    overt act of relinquishment in perpetuity of all present and future rights to
  29656 ///    this software under copyright law.
  29657 ///    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29658 ///    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29659 ///    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  29660 ///    AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29661 ///    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29662 ///    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29663 ///    ------------------------------------------------------------------------------
  29664 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  29665 
  29666 /// ## Changelog
  29667 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
  29668 /// [date] ([x.y.z]) - [description]
  29669 /// - [date]: date on which the change has been pushed
  29670 /// - [x.y.z]: Version string, represented in Semantic Versioning format
  29671 ///   - [x]: Major version with API and library breaking changes
  29672 ///   - [y]: Minor version with non-breaking API and library changes
  29673 ///   - [z]: Patch version with no direct changes to the API
  29674 ///
  29675 /// - 2022/12/23 (4.10.6) - Fix incorrect glyph index in nk_font_bake()
  29676 /// - 2022/12/17 (4.10.5) - Fix nk_font_bake_pack() using TTC font offset incorrectly
  29677 /// - 2022/10/24 (4.10.4) - Fix nk_str_{append,insert}_str_utf8 always returning 0
  29678 /// - 2022/09/03 (4.10.3) - Renamed the `null` texture variable to `tex_null`
  29679 /// - 2022/08/01 (4.10.2) - Fix Apple Silicon with incorrect NK_SITE_TYPE and NK_POINTER_TYPE
  29680 /// - 2022/08/01 (4.10.1) - Fix cursor jumping back to beginning of text when typing more than
  29681 ///                         nk_edit_xxx limit
  29682 /// - 2022/05/27 (4.10.0) - Add nk_input_has_mouse_click_in_button_rect() to fix window move bug
  29683 /// - 2022/04/18 (4.9.7)  - Change button behavior when NK_BUTTON_TRIGGER_ON_RELEASE is defined to
  29684 ///                         only trigger when the mouse position was inside the same button on down
  29685 /// - 2022/02/03 (4.9.6)  - Allow overriding the NK_INV_SQRT function, similar to NK_SIN and NK_COS
  29686 /// - 2021/12/22 (4.9.5)  - Revert layout bounds not accounting for padding due to regressions
  29687 /// - 2021/12/22 (4.9.4)  - Fix checking hovering when window is minimized
  29688 /// - 2021/12/22 (4.09.3) - Fix layout bounds not accounting for padding
  29689 /// - 2021/12/19 (4.09.2) - Update to stb_rect_pack.h v1.01 and stb_truetype.h v1.26
  29690 /// - 2021/12/16 (4.09.1) - Fix the majority of GCC warnings
  29691 /// - 2021/10/16 (4.09.0) - Added nk_spacer() widget
  29692 /// - 2021/09/22 (4.08.6) - Fix "may be used uninitialized" warnings in nk_widget
  29693 /// - 2021/09/22 (4.08.5) - GCC __builtin_offsetof only exists in version 4 and later
  29694 /// - 2021/09/15 (4.08.4) - Fix "'num_len' may be used uninitialized" in nk_do_property
  29695 /// - 2021/09/15 (4.08.3) - Fix "Templates cannot be declared to have 'C' Linkage"
  29696 /// - 2021/09/08 (4.08.2) - Fix warnings in C89 builds
  29697 /// - 2021/09/08 (4.08.1) - Use compiler builtins for NK_OFFSETOF when possible
  29698 /// - 2021/08/17 (4.08.0) - Implemented 9-slice scaling support for widget styles
  29699 /// - 2021/08/16 (4.07.5) - Replace usage of memset in nk_font_atlas_bake with NK_MEMSET
  29700 /// - 2021/08/15 (4.07.4) - Fix conversion and sign conversion warnings
  29701 /// - 2021/08/08 (4.07.3) - Fix crash when baking merged fonts
  29702 /// - 2021/08/08 (4.07.2) - Fix Multiline Edit wrong offset
  29703 /// - 2021/03/17 (4.07.1) - Fix warning about unused parameter
  29704 /// - 2021/03/17 (4.07.0) - Fix nk_property hover bug
  29705 /// - 2021/03/15 (4.06.4) - Change nk_propertyi back to int
  29706 /// - 2021/03/15 (4.06.3) - Update documentation for functions that now return nk_bool
  29707 /// - 2020/12/19 (4.06.2) - Fix additional C++ style comments which are not allowed in ISO C90.
  29708 /// - 2020/10/11 (4.06.1) - Fix C++ style comments which are not allowed in ISO C90.
  29709 /// - 2020/10/07 (4.06.0) - Fix nk_combo return type wrongly changed to nk_bool
  29710 /// - 2020/09/05 (4.05.0) - Use the nk_font_atlas allocator for stb_truetype memory management.
  29711 /// - 2020/09/04 (4.04.1) - Replace every boolean int by nk_bool
  29712 /// - 2020/09/04 (4.04.0) - Add nk_bool with NK_INCLUDE_STANDARD_BOOL
  29713 /// - 2020/06/13 (4.03.1) - Fix nk_pool allocation sizes.
  29714 /// - 2020/06/04 (4.03.0) - Made nk_combo header symbols optional.
  29715 /// - 2020/05/27 (4.02.5) - Fix nk_do_edit: Keep scroll position when re-activating edit widget.
  29716 /// - 2020/05/09 (4.02.4) - Fix nk_menubar height calculation bug
  29717 /// - 2020/05/08 (4.02.3) - Fix missing stdarg.h with NK_INCLUDE_STANDARD_VARARGS
  29718 /// - 2020/04/30 (4.02.2) - Fix nk_edit border drawing bug
  29719 /// - 2020/04/09 (4.02.1) - Removed unused nk_sqrt function to fix compiler warnings
  29720 ///                       - Fixed compiler warnings if you bring your own methods for
  29721 ///                        nk_cos/nk_sin/nk_strtod/nk_memset/nk_memcopy/nk_dtoa
  29722 /// - 2020/04/06 (4.01.10) - Fix bug: Do not use pool before checking for NULL
  29723 /// - 2020/03/22 (4.01.9) - Fix bug where layout state wasn't restored correctly after
  29724 ///                        popping a tree.
  29725 /// - 2020/03/11 (4.01.8) - Fix bug where padding is subtracted from widget
  29726 /// - 2020/03/06 (4.01.7) - Fix bug where width padding was applied twice
  29727 /// - 2020/02/06 (4.01.6) - Update stb_truetype.h and stb_rect_pack.h and separate them
  29728 /// - 2019/12/10 (4.01.5) - Fix off-by-one error in NK_INTERSECT
  29729 /// - 2019/10/09 (4.01.4) - Fix bug for autoscrolling in nk_do_edit
  29730 /// - 2019/09/20 (4.01.3) - Fixed a bug wherein combobox cannot be closed by clicking the header
  29731 ///                        when NK_BUTTON_TRIGGER_ON_RELEASE is defined.
  29732 /// - 2019/09/10 (4.01.2) - Fixed the nk_cos function, which deviated significantly.
  29733 /// - 2019/09/08 (4.01.1) - Fixed a bug wherein re-baking of fonts caused a segmentation
  29734 ///                        fault due to dst_font->glyph_count not being zeroed on subsequent
  29735 ///                        bakes of the same set of fonts.
  29736 /// - 2019/06/23 (4.01.0) - Added nk_***_get_scroll and nk_***_set_scroll for groups, windows, and popups.
  29737 /// - 2019/06/12 (4.00.3) - Fix panel background drawing bug.
  29738 /// - 2018/10/31 (4.00.2) - Added NK_KEYSTATE_BASED_INPUT to "fix" state based backends
  29739 ///                        like GLFW without breaking key repeat behavior on event based.
  29740 /// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame.
  29741 /// - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to
  29742 ///                        clear provided buffers. So make sure to either free
  29743 ///                        or clear each passed buffer after calling nk_convert.
  29744 /// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior.
  29745 /// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process.
  29746 /// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype.
  29747 /// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug.
  29748 /// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separated group identifier and title.
  29749 /// - 2018/01/07 (3.00.1) - Started to change documentation style.
  29750 /// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken
  29751 ///                        because of conversions between float and byte color representation.
  29752 ///                        Color pickers now use floating point values to represent
  29753 ///                        HSV values. To get back the old behavior I added some additional
  29754 ///                        color conversion functions to cast between nk_color and
  29755 ///                        nk_colorf.
  29756 /// - 2017/12/23 (2.00.7) - Fixed small warning.
  29757 /// - 2017/12/23 (2.00.7) - Fixed `nk_edit_buffer` behavior if activated to allow input.
  29758 /// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior.
  29759 /// - 2017/12/04 (2.00.6) - Added formatted string tooltip widget.
  29760 /// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag `NK_WINDOW_NO_INPUT`.
  29761 /// - 2017/11/15 (2.00.4) - Fixed font merging.
  29762 /// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions.
  29763 /// - 2017/09/14 (2.00.2) - Fixed `nk_edit_buffer` and `nk_edit_focus` behavior.
  29764 /// - 2017/09/14 (2.00.1) - Fixed window closing behavior.
  29765 /// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifying window position and size functions now
  29766 ///                        require the name of the window and must happen outside the window
  29767 ///                        building process (between function call nk_begin and nk_end).
  29768 /// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last.
  29769 /// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows.
  29770 /// - 2017/08/27 (1.40.7) - Fixed window background flag.
  29771 /// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked
  29772 ///                        query for widgets.
  29773 /// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked
  29774 ///                        and filled rectangles.
  29775 /// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in
  29776 ///                        process of being destroyed.
  29777 /// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in
  29778 ///                        window instead of directly in table.
  29779 /// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro.
  29780 /// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero.
  29781 /// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only
  29782 ///                        comes in effect if you pass in zero was row height argument.
  29783 /// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change
  29784 ///                        how layouting works. From now there will be an internal minimum
  29785 ///                        row height derived from font height. If you need a row smaller than
  29786 ///                        that you can directly set it by `nk_layout_set_min_row_height` and
  29787 ///                        reset the value back by calling `nk_layout_reset_min_row_height.
  29788 /// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix.
  29789 /// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a `nk_layout_xxx` function.
  29790 /// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer.
  29791 /// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped.
  29792 /// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundaries.
  29793 /// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space.
  29794 /// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size.
  29795 /// - 2017/05/06 (1.38.0) - Added platform double-click support.
  29796 /// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends.
  29797 /// - 2017/04/20 (1.37.0) - Extended properties with selection and clipboard support.
  29798 /// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing.
  29799 /// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error.
  29800 /// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags.
  29801 /// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption.
  29802 /// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows.
  29803 /// - 2017/03/25 (1.35.1) - Fixed windows closing behavior.
  29804 /// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377.
  29805 /// - 2017/03/18 (1.34.3) - Fixed long window header titles.
  29806 /// - 2017/03/04 (1.34.2) - Fixed text edit filtering.
  29807 /// - 2017/03/04 (1.34.1) - Fixed group closable flag.
  29808 /// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support.
  29809 /// - 2017/01/24 (1.33.0) - Added programmatic way to remove edit focus.
  29810 /// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows.
  29811 /// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows.
  29812 /// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing.
  29813 /// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner.
  29814 /// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both
  29815 ///                        dynamic and static widgets.
  29816 /// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit.
  29817 /// - 2016/12/31 (1.29.2) - Fixed closing window bug of minimized windows.
  29818 /// - 2016/12/03 (1.29.1) - Fixed wrapped text with no seperator and C89 error.
  29819 /// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters.
  29820 /// - 2016/11/22 (1.28.6) - Fixed window minimized closing bug.
  29821 /// - 2016/11/19 (1.28.5) - Fixed abstract combo box closing behavior.
  29822 /// - 2016/11/19 (1.28.4) - Fixed tooltip flickering.
  29823 /// - 2016/11/19 (1.28.3) - Fixed memory leak caused by popup repeated closing.
  29824 /// - 2016/11/18 (1.28.2) - Fixed memory leak caused by popup panel allocation.
  29825 /// - 2016/11/10 (1.28.1) - Fixed some warnings and C++ error.
  29826 /// - 2016/11/10 (1.28.0) - Added additional `nk_button` versions which allows to directly
  29827 ///                        pass in a style struct to change buttons visual.
  29828 /// - 2016/11/10 (1.27.0) - Added additional `nk_tree` versions to support external state
  29829 ///                        storage. Just like last the `nk_group` commit the main
  29830 ///                        advantage is that you optionally can minimize nuklears runtime
  29831 ///                        memory consumption or handle hash collisions.
  29832 /// - 2016/11/09 (1.26.0) - Added additional `nk_group` version to support external scrollbar
  29833 ///                        offset storage. Main advantage is that you can externalize
  29834 ///                        the memory management for the offset. It could also be helpful
  29835 ///                        if you have a hash collision in `nk_group_begin` but really
  29836 ///                        want the name. In addition I added `nk_list_view` which allows
  29837 ///                        to draw big lists inside a group without actually having to
  29838 ///                        commit the whole list to nuklear (issue #269).
  29839 /// - 2016/10/30 (1.25.1) - Fixed clipping rectangle bug inside `nk_draw_list`.
  29840 /// - 2016/10/29 (1.25.0) - Pulled `nk_panel` memory management into nuklear and out of
  29841 ///                        the hands of the user. From now on users don't have to care
  29842 ///                        about panels unless they care about some information. If you
  29843 ///                        still need the panel just call `nk_window_get_panel`.
  29844 /// - 2016/10/21 (1.24.0) - Changed widget border drawing to stroked rectangle from filled
  29845 ///                        rectangle for less overdraw and widget background transparency.
  29846 /// - 2016/10/18 (1.23.0) - Added `nk_edit_focus` for manually edit widget focus control.
  29847 /// - 2016/09/29 (1.22.7) - Fixed deduction of basic type in non `<stdint.h>` compilation.
  29848 /// - 2016/09/29 (1.22.6) - Fixed edit widget UTF-8 text cursor drawing bug.
  29849 /// - 2016/09/28 (1.22.5) - Fixed edit widget UTF-8 text appending/inserting/removing.
  29850 /// - 2016/09/28 (1.22.4) - Fixed drawing bug inside edit widgets which offset all text
  29851 ///                        text in every edit widget if one of them is scrolled.
  29852 /// - 2016/09/28 (1.22.3) - Fixed small bug in edit widgets if not active. The wrong
  29853 ///                        text length is passed. It should have been in bytes but
  29854 ///                        was passed as glyphs.
  29855 /// - 2016/09/20 (1.22.2) - Fixed color button size calculation.
  29856 /// - 2016/09/20 (1.22.1) - Fixed some `nk_vsnprintf` behavior bugs and removed `<stdio.h>`
  29857 ///                        again from `NK_INCLUDE_STANDARD_VARARGS`.
  29858 /// - 2016/09/18 (1.22.0) - C89 does not support vsnprintf only C99 and newer as well
  29859 ///                        as C++11 and newer. In addition to use vsnprintf you have
  29860 ///                        to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS`
  29861 ///                        is not enough. That behavior is now fixed. By default if
  29862 ///                        both varargs as well as stdio is selected I try to use
  29863 ///                        vsnprintf if not possible I will revert to vsprintf. If
  29864 ///                        varargs but not stdio was defined I will use my own function.
  29865 /// - 2016/09/15 (1.21.2) - Fixed panel `close` behavior for deeper panel levels.
  29866 /// - 2016/09/15 (1.21.1) - Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`.
  29867 /// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo,
  29868 ///                        and contextual which prevented closing in y-direction if
  29869 ///                        popup did not reach max height.
  29870 ///                        In addition the height parameter was changed into vec2
  29871 ///                        for width and height to have more control over the popup size.
  29872 /// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection.
  29873 /// - 2016/09/13 (1.20.2) - Fixed slider behavior hopefully for the last time. This time
  29874 ///                        all calculation are correct so no more hackery.
  29875 /// - 2016/09/13 (1.20.1) - Internal change to divide window/panel flags into panel flags and types.
  29876 ///                        Suprisinly spend years in C and still happened to confuse types
  29877 ///                        with flags. Probably something to take note.
  29878 /// - 2016/09/08 (1.20.0) - Added additional helper function to make it easier to just
  29879 ///                        take the produced buffers from `nk_convert` and unplug the
  29880 ///                        iteration process from `nk_context`. So now you can
  29881 ///                        just use the vertex,element and command buffer + two pointer
  29882 ///                        inside the command buffer retrieved by calls `nk__draw_begin`
  29883 ///                        and `nk__draw_end` and macro `nk_draw_foreach_bounded`.
  29884 /// - 2016/09/08 (1.19.0) - Added additional asserts to make sure every `nk_xxx_begin` call
  29885 ///                        for windows, popups, combobox, menu and contextual is guarded by
  29886 ///                        `if` condition and does not produce false drawing output.
  29887 /// - 2016/09/08 (1.18.0) - Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT`
  29888 ///                        to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and
  29889 ///                        `NK_SYMBOL_RECT_OUTLINE`.
  29890 /// - 2016/09/08 (1.17.0) - Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE`
  29891 ///                        to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and
  29892 ///                        `NK_SYMBOL_CIRCLE_OUTLINE`.
  29893 /// - 2016/09/08 (1.16.0) - Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES`
  29894 ///                        is not defined by supporting the biggest compiler GCC, clang and MSVC.
  29895 /// - 2016/09/07 (1.15.3) - Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error.
  29896 /// - 2016/09/04 (1.15.2) - Fixed wrong combobox height calculation.
  29897 /// - 2016/09/03 (1.15.1) - Fixed gaps inside combo boxes in OpenGL.
  29898 /// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and
  29899 ///                        instead made it user provided. The range of types to convert
  29900 ///                        to is quite limited at the moment, but I would be more than
  29901 ///                        happy to accept PRs to add additional.
  29902 /// - 2016/08/30 (1.14.2) - Removed unused variables.
  29903 /// - 2016/08/30 (1.14.1) - Fixed C++ build errors.
  29904 /// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly.
  29905 /// - 2016/08/30 (1.13.4) - Tweaked some default styling variables.
  29906 /// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would
  29907 ///                        refrain from using slider with a big number of steps.
  29908 /// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the
  29909 ///                        window was in Read Only Mode.
  29910 /// - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just
  29911 ///                        a hack for combo box and menu.
  29912 /// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since
  29913 ///                        it is bugged and causes issues in window selection.
  29914 /// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now
  29915 ///                        determined by the scrollbar size.
  29916 /// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11.0.
  29917 /// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection.
  29918 /// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code
  29919 ///                        handling panel padding and panel border.
  29920 /// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`.
  29921 /// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups.
  29922 /// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes.
  29923 /// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for
  29924 ///                        hash collisions. Currently limited to `NK_WINDOW_MAX_NAME`
  29925 ///                        which in term can be redefined if not big enough.
  29926 /// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code.
  29927 /// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released'
  29928 ///                        to account for key press and release happening in one frame.
  29929 /// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate.
  29930 /// - 2016/08/17 (1.09.6) - Removed invalid check for value zero in `nk_propertyx`.
  29931 /// - 2016/08/16 (1.09.5) - Fixed ROM mode for deeper levels of popup windows parents.
  29932 /// - 2016/08/15 (1.09.4) - Editbox are now still active if enter was pressed with flag
  29933 ///                        `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep
  29934 ///                        typing after committing.
  29935 /// - 2016/08/15 (1.09.4) - Removed redundant code.
  29936 /// - 2016/08/15 (1.09.4) - Fixed negative numbers in `nk_strtoi` and remove unused variable.
  29937 /// - 2016/08/15 (1.09.3) - Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background
  29938 ///                        window only as selected by hovering and not by clicking.
  29939 /// - 2016/08/14 (1.09.2) - Fixed a bug in font atlas which caused wrong loading
  29940 ///                        of glyphs for font with multiple ranges.
  29941 /// - 2016/08/12 (1.09.1) - Added additional function to check if window is currently
  29942 ///                        hidden and therefore not visible.
  29943 /// - 2016/08/12 (1.09.1) - nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED`
  29944 ///                        instead of the old flag `NK_WINDOW_HIDDEN`.
  29945 /// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed
  29946 ///                        the underlying implementation to not cast to float and instead
  29947 ///                        work directly on the given values.
  29948 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
  29949 ///                        floating pointer number to string conversion for additional
  29950 ///                        precision.
  29951 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
  29952 ///                        string to floating point number conversion for additional
  29953 ///                        precision.
  29954 /// - 2016/08/08 (1.07.2) - Fixed compiling error without define `NK_INCLUDE_FIXED_TYPE`.
  29955 /// - 2016/08/08 (1.07.1) - Fixed possible floating point error inside `nk_widget` leading
  29956 ///                        to wrong wiget width calculation which results in widgets falsely
  29957 ///                        becoming tagged as not inside window and cannot be accessed.
  29958 /// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and
  29959 ///                        closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown
  29960 ///                        by using `nk_window_show` and closed by either clicking the close
  29961 ///                        icon in a window or by calling `nk_window_close`. Only closed
  29962 ///                        windows get removed at the end of the frame while hidden windows
  29963 ///                        remain.
  29964 /// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to
  29965 ///                        `nk_edit_string` which takes, edits and outputs a '\0' terminated string.
  29966 /// - 2016/08/08 (1.05.4) - Fixed scrollbar auto hiding behavior.
  29967 /// - 2016/08/08 (1.05.3) - Fixed wrong panel padding selection in `nk_layout_widget_space`.
  29968 /// - 2016/08/07 (1.05.2) - Fixed old bug in dynamic immediate mode layout API, calculating
  29969 ///                        wrong item spacing and panel width.
  29970 /// - 2016/08/07 (1.05.1) - Hopefully finally fixed combobox popup drawing bug.
  29971 /// - 2016/08/07 (1.05.0) - Split varargs away from `NK_INCLUDE_STANDARD_IO` into own
  29972 ///                        define `NK_INCLUDE_STANDARD_VARARGS` to allow more fine
  29973 ///                        grained controlled over library includes.
  29974 /// - 2016/08/06 (1.04.5) - Changed memset calls to `NK_MEMSET`.
  29975 /// - 2016/08/04 (1.04.4) - Fixed fast window scaling behavior.
  29976 /// - 2016/08/04 (1.04.3) - Fixed window scaling, movement bug which appears if you
  29977 ///                        move/scale a window and another window is behind it.
  29978 ///                        If you are fast enough then the window behind gets activated
  29979 ///                        and the operation is blocked. I now require activating
  29980 ///                        by hovering only if mouse is not pressed.
  29981 /// - 2016/08/04 (1.04.2) - Fixed changing fonts.
  29982 /// - 2016/08/03 (1.04.1) - Fixed `NK_WINDOW_BACKGROUND` behavior.
  29983 /// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`.
  29984 /// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for
  29985 ///                        sub windows (combo, menu, ...).
  29986 /// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor.
  29987 /// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window
  29988 ///                        to be always in the background of the screen.
  29989 /// - 2016/08/03 (1.03.2) - Removed invalid assert macro for NK_RGB color picker.
  29990 /// - 2016/08/01 (1.03.1) - Added helper macros into header include guard.
  29991 /// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to
  29992 ///                        simplify memory management by removing the need to
  29993 ///                        allocate the pool.
  29994 /// - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled
  29995 ///                        will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT
  29996 ///                        seconds without window interaction. To make it work
  29997 ///                        you have to also set a delta time inside the `nk_context`.
  29998 /// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs.
  29999 /// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`.
  30000 /// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument.
  30001 /// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified
  30002 ///                        font atlas memory management by converting pointer
  30003 ///                        arrays for fonts and font configurations to lists.
  30004 /// - 2016/07/15 (1.00.0) - Changed button API to use context dependent button
  30005 ///                        behavior instead of passing it for every function call.
  30006 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  30007 /// ## Gallery
  30008 /// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png)
  30009 /// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png)
  30010 /// ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png)
  30011 /// ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png)
  30012 /// ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png)
  30013 /// ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png)
  30014 /// ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif)
  30015 /// ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png)
  30016 /// ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png)
  30017 ///
  30018 /// ## Credits
  30019 /// Developed by Micha Mettke and every direct or indirect github contributor. <br /><br />
  30020 ///
  30021 /// Embeds [stb_texedit](https://github.com/nothings/stb/blob/master/stb_textedit.h), [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) and [stb_rectpack](https://github.com/nothings/stb/blob/master/stb_rect_pack.h) by Sean Barret (public domain) <br />
  30022 /// Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from r-lyeh@github.com for documentation generation <br /><br />
  30023 /// Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br />
  30024 ///
  30025 /// Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and
  30026 /// giving me the inspiration for this library, Casey Muratori for handmade hero
  30027 /// and his original immediate mode graphical user interface idea and Sean
  30028 /// Barret for his amazing single header libraries which restored my faith
  30029 /// in libraries and brought me to create some of my own. Finally Apoorva Joshi
  30030 /// for his single header file packer.
  30031 */
  30032