zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

nuklear.h (980614B)


      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 ///
     52 /// ## Features
     53 /// - Absolutely no platform dependent code
     54 /// - Memory management control ranging from/to
     55 ///     - Ease of use by allocating everything from standard library
     56 ///     - Control every byte of memory inside the library
     57 /// - Font handling control ranging from/to
     58 ///     - Use your own font implementation for everything
     59 ///     - Use this libraries internal font baking and handling API
     60 /// - Drawing output control ranging from/to
     61 ///     - Simple shapes for more high level APIs which already have drawing capabilities
     62 ///     - Hardware accessible anti-aliased vertex buffer output
     63 /// - Customizable colors and properties ranging from/to
     64 ///     - Simple changes to color by filling a simple color table
     65 ///     - Complete control with ability to use skinning to decorate widgets
     66 /// - Bendable UI library with widget ranging from/to
     67 ///     - Basic widgets like buttons, checkboxes, slider, ...
     68 ///     - Advanced widget like abstract comboboxes, contextual menus,...
     69 /// - Compile time configuration to only compile what you need
     70 ///     - Subset which can be used if you do not want to link or use the standard library
     71 /// - Can be easily modified to only update on user input instead of frame updates
     72 ///
     73 /// ## Usage
     74 /// This library is self contained in one single header file and can be used either
     75 /// in header only mode or in implementation mode. The header only mode is used
     76 /// by default when included and allows including this header in other headers
     77 /// and does not contain the actual implementation. <br /><br />
     78 ///
     79 /// The implementation mode requires to define  the preprocessor macro
     80 /// NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.:
     81 ///
     82 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C
     83 ///     #define NK_IMPLEMENTATION
     84 ///     #include "nuklear.h"
     85 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     86 ///
     87 /// Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
     88 /// below in header and implementation mode if you want to use additional functionality
     89 /// or need more control over the library.
     90 ///
     91 /// !!! WARNING
     92 ///     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.
     93 ///
     94 /// ### Flags
     95 /// Flag                            | Description
     96 /// --------------------------------|------------------------------------------
     97 /// NK_PRIVATE                      | If defined declares all functions as static, so they can only be accessed inside the file that contains the implementation
     98 /// 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.
     99 /// 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.
    100 /// NK_INCLUDE_STANDARD_IO          | If defined it will include header `<stdio.h>` and provide additional functions depending on file loading.
    101 /// NK_INCLUDE_STANDARD_VARARGS     | If defined it will include header <stdio.h> and provide additional functions depending on file loading.
    102 /// 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,...
    103 /// 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.
    104 /// 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
    105 /// 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.
    106 /// 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.
    107 /// 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.
    108 ///
    109 /// !!! WARNING
    110 ///     The following flags will pull in the standard C library:
    111 ///     - NK_INCLUDE_DEFAULT_ALLOCATOR
    112 ///     - NK_INCLUDE_STANDARD_IO
    113 ///     - NK_INCLUDE_STANDARD_VARARGS
    114 ///
    115 /// !!! WARNING
    116 ///     The following flags if defined need to be defined for both header and implementation:
    117 ///     - NK_INCLUDE_FIXED_TYPES
    118 ///     - NK_INCLUDE_DEFAULT_ALLOCATOR
    119 ///     - NK_INCLUDE_STANDARD_VARARGS
    120 ///     - NK_INCLUDE_VERTEX_BUFFER_OUTPUT
    121 ///     - NK_INCLUDE_FONT_BAKING
    122 ///     - NK_INCLUDE_DEFAULT_FONT
    123 ///     - NK_INCLUDE_STANDARD_VARARGS
    124 ///     - NK_INCLUDE_COMMAND_USERDATA
    125 ///
    126 /// ### Constants
    127 /// Define                          | Description
    128 /// --------------------------------|---------------------------------------
    129 /// 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.
    130 /// NK_MAX_NUMBER_BUFFER            | Maximum buffer size for the conversion buffer between float and string Under normal circumstances this should be more than sufficient.
    131 /// 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.
    132 ///
    133 /// !!! WARNING
    134 ///     The following constants if defined need to be defined for both header and implementation:
    135 ///     - NK_MAX_NUMBER_BUFFER
    136 ///     - NK_BUFFER_DEFAULT_INITIAL_SIZE
    137 ///     - NK_INPUT_MAX
    138 ///
    139 /// ### Dependencies
    140 /// Function    | Description
    141 /// ------------|---------------------------------------------------------------
    142 /// NK_ASSERT   | If you don't define this, nuklear will use <assert.h> with assert().
    143 /// NK_MEMSET   | You can define this to 'memset' or your own memset implementation replacement. If not nuklear will use its own version.
    144 /// NK_MEMCPY   | You can define this to 'memcpy' or your own memcpy implementation replacement. If not nuklear will use its own version.
    145 /// NK_SQRT     | You can define this to 'sqrt' or your own sqrt implementation replacement. If not nuklear will use its own slow and not highly accurate version.
    146 /// NK_SIN      | You can define this to 'sinf' or your own sine implementation replacement. If not nuklear will use its own approximation implementation.
    147 /// NK_COS      | You can define this to 'cosf' or your own cosine implementation replacement. If not nuklear will use its own approximation implementation.
    148 /// 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!).
    149 /// 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!).
    150 /// 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.
    151 ///
    152 /// !!! WARNING
    153 ///     The following dependencies will pull in the standard C library if not redefined:
    154 ///     - NK_ASSERT
    155 ///
    156 /// !!! WARNING
    157 ///     The following dependencies if defined need to be defined for both header and implementation:
    158 ///     - NK_ASSERT
    159 ///
    160 /// !!! WARNING
    161 ///     The following dependencies if defined need to be defined only for the implementation part:
    162 ///     - NK_MEMSET
    163 ///     - NK_MEMCPY
    164 ///     - NK_SQRT
    165 ///     - NK_SIN
    166 ///     - NK_COS
    167 ///     - NK_STRTOD
    168 ///     - NK_DTOA
    169 ///     - NK_VSNPRINTF
    170 ///
    171 /// ## Example
    172 ///
    173 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    174 /// // init gui state
    175 /// enum {EASY, HARD};
    176 /// static int op = EASY;
    177 /// static float value = 0.6f;
    178 /// static int i =  20;
    179 /// struct nk_context ctx;
    180 ///
    181 /// nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);
    182 /// if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220),
    183 ///     NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
    184 ///     // fixed widget pixel width
    185 ///     nk_layout_row_static(&ctx, 30, 80, 1);
    186 ///     if (nk_button_label(&ctx, "button")) {
    187 ///         // event handling
    188 ///     }
    189 ///
    190 ///     // fixed widget window ratio width
    191 ///     nk_layout_row_dynamic(&ctx, 30, 2);
    192 ///     if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY;
    193 ///     if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD;
    194 ///
    195 ///     // custom widget pixel width
    196 ///     nk_layout_row_begin(&ctx, NK_STATIC, 30, 2);
    197 ///     {
    198 ///         nk_layout_row_push(&ctx, 50);
    199 ///         nk_label(&ctx, "Volume:", NK_TEXT_LEFT);
    200 ///         nk_layout_row_push(&ctx, 110);
    201 ///         nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
    202 ///     }
    203 ///     nk_layout_row_end(&ctx);
    204 /// }
    205 /// nk_end(&ctx);
    206 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    207 ///
    208 /// ![](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png)
    209 ///
    210 /// ## API
    211 ///
    212 */
    213 #ifndef NK_SINGLE_FILE
    214   #define NK_SINGLE_FILE
    215 #endif
    216 
    217 #ifndef NK_NUKLEAR_H_
    218 #define NK_NUKLEAR_H_
    219 
    220 #ifdef __cplusplus
    221 extern "C" {
    222 #endif
    223 /*
    224  * ==============================================================
    225  *
    226  *                          CONSTANTS
    227  *
    228  * ===============================================================
    229  */
    230 #define NK_UNDEFINED (-1.0f)
    231 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
    232 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
    233 #ifndef NK_INPUT_MAX
    234   #define NK_INPUT_MAX 16
    235 #endif
    236 #ifndef NK_MAX_NUMBER_BUFFER
    237   #define NK_MAX_NUMBER_BUFFER 64
    238 #endif
    239 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
    240   #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
    241 #endif
    242 /*
    243  * ==============================================================
    244  *
    245  *                          HELPER
    246  *
    247  * ===============================================================
    248  */
    249 #ifndef NK_API
    250   #ifdef NK_PRIVATE
    251     #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
    252       #define NK_API static inline
    253     #elif defined(__cplusplus)
    254       #define NK_API static inline
    255     #else
    256       #define NK_API static
    257     #endif
    258   #else
    259     #define NK_API extern
    260   #endif
    261 #endif
    262 #ifndef NK_LIB
    263   #ifdef NK_SINGLE_FILE
    264     #define NK_LIB static
    265   #else
    266     #define NK_LIB extern
    267   #endif
    268 #endif
    269 
    270 #define NK_INTERN static
    271 #define NK_STORAGE static
    272 #define NK_GLOBAL static
    273 
    274 #define NK_FLAG(x) (1 << (x))
    275 #define NK_STRINGIFY(x) #x
    276 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
    277 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
    278 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
    279 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
    280 
    281 #ifdef _MSC_VER
    282   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
    283 #else
    284   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
    285 #endif
    286 
    287 #ifndef NK_STATIC_ASSERT
    288   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
    289 #endif
    290 
    291 #ifndef NK_FILE_LINE
    292 #ifdef _MSC_VER
    293   #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
    294 #else
    295   #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
    296 #endif
    297 #endif
    298 
    299 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
    300 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
    301 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
    302 
    303 #ifdef NK_INCLUDE_STANDARD_VARARGS
    304   #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
    305     #include <sal.h>
    306     #define NK_PRINTF_FORMAT_STRING _Printf_format_string_
    307   #else
    308     #define NK_PRINTF_FORMAT_STRING
    309   #endif
    310   #if defined(__GNUC__)
    311     #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1)))
    312     #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0)))
    313   #else
    314     #define NK_PRINTF_VARARG_FUNC(fmtargnumber)
    315     #define NK_PRINTF_VALIST_FUNC(fmtargnumber)
    316   #endif
    317   #include <stdarg.h> /* valist, va_start, va_end, ... */
    318 #endif
    319 
    320 /*
    321  * ===============================================================
    322  *
    323  *                          BASIC
    324  *
    325  * ===============================================================
    326  */
    327 #ifdef NK_INCLUDE_FIXED_TYPES
    328  #include <stdint.h>
    329  #define NK_INT8 int8_t
    330  #define NK_UINT8 uint8_t
    331  #define NK_INT16 int16_t
    332  #define NK_UINT16 uint16_t
    333  #define NK_INT32 int32_t
    334  #define NK_UINT32 uint32_t
    335  #define NK_SIZE_TYPE uintptr_t
    336  #define NK_POINTER_TYPE uintptr_t
    337 #else
    338   #ifndef NK_INT8
    339     #define NK_INT8 char
    340   #endif
    341   #ifndef NK_UINT8
    342     #define NK_UINT8 unsigned char
    343   #endif
    344   #ifndef NK_INT16
    345     #define NK_INT16 signed short
    346   #endif
    347   #ifndef NK_UINT16
    348     #define NK_UINT16 unsigned short
    349   #endif
    350   #ifndef NK_INT32
    351     #if defined(_MSC_VER)
    352       #define NK_INT32 __int32
    353     #else
    354       #define NK_INT32 signed int
    355     #endif
    356   #endif
    357   #ifndef NK_UINT32
    358     #if defined(_MSC_VER)
    359       #define NK_UINT32 unsigned __int32
    360     #else
    361       #define NK_UINT32 unsigned int
    362     #endif
    363   #endif
    364   #ifndef NK_SIZE_TYPE
    365     #if defined(_WIN64) && defined(_MSC_VER)
    366       #define NK_SIZE_TYPE unsigned __int64
    367     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
    368       #define NK_SIZE_TYPE unsigned __int32
    369     #elif defined(__GNUC__) || defined(__clang__)
    370       #if defined(__x86_64__) || defined(__ppc64__)
    371         #define NK_SIZE_TYPE unsigned long
    372       #else
    373         #define NK_SIZE_TYPE unsigned int
    374       #endif
    375     #else
    376       #define NK_SIZE_TYPE unsigned long
    377     #endif
    378   #endif
    379   #ifndef NK_POINTER_TYPE
    380     #if defined(_WIN64) && defined(_MSC_VER)
    381       #define NK_POINTER_TYPE unsigned __int64
    382     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
    383       #define NK_POINTER_TYPE unsigned __int32
    384     #elif defined(__GNUC__) || defined(__clang__)
    385       #if defined(__x86_64__) || defined(__ppc64__)
    386         #define NK_POINTER_TYPE unsigned long
    387       #else
    388         #define NK_POINTER_TYPE unsigned int
    389       #endif
    390     #else
    391       #define NK_POINTER_TYPE unsigned long
    392     #endif
    393   #endif
    394 #endif
    395 
    396 typedef NK_INT8 nk_char;
    397 typedef NK_UINT8 nk_uchar;
    398 typedef NK_UINT8 nk_byte;
    399 typedef NK_INT16 nk_short;
    400 typedef NK_UINT16 nk_ushort;
    401 typedef NK_INT32 nk_int;
    402 typedef NK_UINT32 nk_uint;
    403 typedef NK_SIZE_TYPE nk_size;
    404 typedef NK_POINTER_TYPE nk_ptr;
    405 
    406 typedef nk_uint nk_hash;
    407 typedef nk_uint nk_flags;
    408 typedef nk_uint nk_rune;
    409 
    410 /* Make sure correct type size:
    411  * This will fire with a negative subscript error if the type sizes
    412  * are set incorrectly by the compiler, and compile out if not */
    413 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
    414 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
    415 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
    416 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
    417 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
    418 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
    419 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
    420 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
    421 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
    422 
    423 /* ============================================================================
    424  *
    425  *                                  API
    426  *
    427  * =========================================================================== */
    428 struct nk_buffer;
    429 struct nk_allocator;
    430 struct nk_command_buffer;
    431 struct nk_draw_command;
    432 struct nk_convert_config;
    433 struct nk_style_item;
    434 struct nk_text_edit;
    435 struct nk_draw_list;
    436 struct nk_user_font;
    437 struct nk_panel;
    438 struct nk_context;
    439 struct nk_draw_vertex_layout_element;
    440 struct nk_style_button;
    441 struct nk_style_toggle;
    442 struct nk_style_selectable;
    443 struct nk_style_slide;
    444 struct nk_style_progress;
    445 struct nk_style_scrollbar;
    446 struct nk_style_edit;
    447 struct nk_style_property;
    448 struct nk_style_chart;
    449 struct nk_style_combo;
    450 struct nk_style_tab;
    451 struct nk_style_window_header;
    452 struct nk_style_window;
    453 
    454 enum {nk_false, nk_true};
    455 struct nk_color {nk_byte r,g,b,a;};
    456 struct nk_colorf {float r,g,b,a;};
    457 struct nk_vec2 {float x,y;};
    458 struct nk_vec2i {short x, y;};
    459 struct nk_rect {float x,y,w,h;};
    460 struct nk_recti {short x,y,w,h;};
    461 typedef char nk_glyph[NK_UTF_SIZE];
    462 typedef union {void *ptr; int id;} nk_handle;
    463 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
    464 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
    465 struct nk_scroll {nk_uint x, y;};
    466 
    467 enum nk_heading         {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
    468 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
    469 enum nk_modify          {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
    470 enum nk_orientation     {NK_VERTICAL, NK_HORIZONTAL};
    471 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true};
    472 enum nk_show_states     {NK_HIDDEN = nk_false, NK_SHOWN = nk_true};
    473 enum nk_chart_type      {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX};
    474 enum nk_chart_event     {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02};
    475 enum nk_color_format    {NK_RGB, NK_RGBA};
    476 enum nk_popup_type      {NK_POPUP_STATIC, NK_POPUP_DYNAMIC};
    477 enum nk_layout_format   {NK_DYNAMIC, NK_STATIC};
    478 enum nk_tree_type       {NK_TREE_NODE, NK_TREE_TAB};
    479 
    480 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
    481 typedef void (*nk_plugin_free)(nk_handle, void *old);
    482 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
    483 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
    484 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
    485 
    486 struct nk_allocator {
    487     nk_handle userdata;
    488     nk_plugin_alloc alloc;
    489     nk_plugin_free free;
    490 };
    491 enum nk_symbol_type {
    492     NK_SYMBOL_NONE,
    493     NK_SYMBOL_X,
    494     NK_SYMBOL_UNDERSCORE,
    495     NK_SYMBOL_CIRCLE_SOLID,
    496     NK_SYMBOL_CIRCLE_OUTLINE,
    497     NK_SYMBOL_RECT_SOLID,
    498     NK_SYMBOL_RECT_OUTLINE,
    499     NK_SYMBOL_TRIANGLE_UP,
    500     NK_SYMBOL_TRIANGLE_DOWN,
    501     NK_SYMBOL_TRIANGLE_LEFT,
    502     NK_SYMBOL_TRIANGLE_RIGHT,
    503     NK_SYMBOL_PLUS,
    504     NK_SYMBOL_MINUS,
    505     NK_SYMBOL_MAX
    506 };
    507 /* =============================================================================
    508  *
    509  *                                  CONTEXT
    510  *
    511  * =============================================================================*/
    512 /*/// ### Context
    513 /// Contexts are the main entry point and the majestro of nuklear and contain all required state.
    514 /// They are used for window, memory, input, style, stack, commands and time management and need
    515 /// to be passed into all nuklear GUI specific functions.
    516 ///
    517 /// #### Usage
    518 /// To use a context it first has to be initialized which can be achieved by calling
    519 /// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
    520 /// Each takes in a font handle and a specific way of handling memory. Memory control
    521 /// hereby ranges from standard library to just specifying a fixed sized block of memory
    522 /// which nuklear has to manage itself from.
    523 ///
    524 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    525 /// struct nk_context ctx;
    526 /// nk_init_xxx(&ctx, ...);
    527 /// while (1) {
    528 ///     // [...]
    529 ///     nk_clear(&ctx);
    530 /// }
    531 /// nk_free(&ctx);
    532 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    533 ///
    534 /// #### Reference
    535 /// Function            | Description
    536 /// --------------------|-------------------------------------------------------
    537 /// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free)
    538 /// __nk_init_fixed__   | Initializes context from single fixed size memory block
    539 /// __nk_init__         | Initializes context with memory allocator callbacks for alloc and free
    540 /// __nk_init_custom__  | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
    541 /// __nk_clear__        | Called at the end of the frame to reset and prepare the context for the next frame
    542 /// __nk_free__         | Shutdown and free all memory allocated inside the context
    543 /// __nk_set_user_data__| Utility function to pass user data to draw command
    544  */
    545 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
    546 /*/// #### nk_init_default
    547 /// Initializes a `nk_context` struct with a default standard library allocator.
    548 /// Should be used if you don't want to be bothered with memory management in nuklear.
    549 ///
    550 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    551 /// int nk_init_default(struct nk_context *ctx, const struct nk_user_font *font);
    552 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    553 ///
    554 /// Parameter   | Description
    555 /// ------------|---------------------------------------------------------------
    556 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
    557 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
    558 ///
    559 /// Returns either `false(0)` on failure or `true(1)` on success.
    560 ///
    561 */
    562 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
    563 #endif
    564 /*/// #### nk_init_fixed
    565 /// Initializes a `nk_context` struct from single fixed size memory block
    566 /// Should be used if you want complete control over nuklear's memory management.
    567 /// Especially recommended for system with little memory or systems with virtual memory.
    568 /// For the later case you can just allocate for example 16MB of virtual memory
    569 /// and only the required amount of memory will actually be committed.
    570 ///
    571 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    572 /// int nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font);
    573 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    574 ///
    575 /// !!! Warning
    576 ///     make sure the passed memory block is aligned correctly for `nk_draw_commands`.
    577 ///
    578 /// Parameter   | Description
    579 /// ------------|--------------------------------------------------------------
    580 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
    581 /// __memory__  | Must point to a previously allocated memory block
    582 /// __size__    | Must contain the total size of __memory__
    583 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
    584 ///
    585 /// Returns either `false(0)` on failure or `true(1)` on success.
    586 */
    587 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
    588 /*/// #### nk_init
    589 /// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
    590 /// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
    591 /// interface to nuklear. Can be useful for cases like monitoring memory consumption.
    592 ///
    593 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    594 /// int nk_init(struct nk_context *ctx, struct nk_allocator *alloc, const struct nk_user_font *font);
    595 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    596 ///
    597 /// Parameter   | Description
    598 /// ------------|---------------------------------------------------------------
    599 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
    600 /// __alloc__   | Must point to a previously allocated memory allocator
    601 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
    602 ///
    603 /// Returns either `false(0)` on failure or `true(1)` on success.
    604 */
    605 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
    606 /*/// #### nk_init_custom
    607 /// Initializes a `nk_context` struct from two different either fixed or growing
    608 /// buffers. The first buffer is for allocating draw commands while the second buffer is
    609 /// used for allocating windows, panels and state tables.
    610 ///
    611 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    612 /// int nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font);
    613 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    614 ///
    615 /// Parameter   | Description
    616 /// ------------|---------------------------------------------------------------
    617 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
    618 /// __cmds__    | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
    619 /// __pool__    | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
    620 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
    621 ///
    622 /// Returns either `false(0)` on failure or `true(1)` on success.
    623 */
    624 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
    625 /*/// #### nk_clear
    626 /// Resets the context state at the end of the frame. This includes mostly
    627 /// garbage collector tasks like removing windows or table not called and therefore
    628 /// used anymore.
    629 ///
    630 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    631 /// void nk_clear(struct nk_context *ctx);
    632 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    633 ///
    634 /// Parameter   | Description
    635 /// ------------|-----------------------------------------------------------
    636 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    637 */
    638 NK_API void nk_clear(struct nk_context*);
    639 /*/// #### nk_free
    640 /// Frees all memory allocated by nuklear. Not needed if context was
    641 /// initialized with `nk_init_fixed`.
    642 ///
    643 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    644 /// void nk_free(struct nk_context *ctx);
    645 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    646 ///
    647 /// Parameter   | Description
    648 /// ------------|-----------------------------------------------------------
    649 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    650 */
    651 NK_API void nk_free(struct nk_context*);
    652 #ifdef NK_INCLUDE_COMMAND_USERDATA
    653 /*/// #### nk_set_user_data
    654 /// Sets the currently passed userdata passed down into each draw command.
    655 ///
    656 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    657 /// void nk_set_user_data(struct nk_context *ctx, nk_handle data);
    658 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    659 ///
    660 /// Parameter   | Description
    661 /// ------------|--------------------------------------------------------------
    662 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    663 /// __data__    | Handle with either pointer or index to be passed into every draw commands
    664 */
    665 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
    666 #endif
    667 /* =============================================================================
    668  *
    669  *                                  INPUT
    670  *
    671  * =============================================================================*/
    672 /*/// ### Input
    673 /// The input API is responsible for holding the current input state composed of
    674 /// mouse, key and text input states.
    675 /// It is worth noting that no direct OS or window handling is done in nuklear.
    676 /// Instead all input state has to be provided by platform specific code. This on one hand
    677 /// expects more work from the user and complicates usage but on the other hand
    678 /// provides simple abstraction over a big number of platforms, libraries and other
    679 /// already provided functionality.
    680 ///
    681 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    682 /// nk_input_begin(&ctx);
    683 /// while (GetEvent(&evt)) {
    684 ///     if (evt.type == MOUSE_MOVE)
    685 ///         nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
    686 ///     else if (evt.type == [...]) {
    687 ///         // [...]
    688 ///     }
    689 /// } nk_input_end(&ctx);
    690 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    691 ///
    692 /// #### Usage
    693 /// Input state needs to be provided to nuklear by first calling `nk_input_begin`
    694 /// which resets internal state like delta mouse position and button transistions.
    695 /// After `nk_input_begin` all current input state needs to be provided. This includes
    696 /// mouse motion, button and key pressed and released, text input and scrolling.
    697 /// Both event- or state-based input handling are supported by this API
    698 /// and should work without problems. Finally after all input state has been
    699 /// mirrored `nk_input_end` needs to be called to finish input process.
    700 ///
    701 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    702 /// struct nk_context ctx;
    703 /// nk_init_xxx(&ctx, ...);
    704 /// while (1) {
    705 ///     Event evt;
    706 ///     nk_input_begin(&ctx);
    707 ///     while (GetEvent(&evt)) {
    708 ///         if (evt.type == MOUSE_MOVE)
    709 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
    710 ///         else if (evt.type == [...]) {
    711 ///             // [...]
    712 ///         }
    713 ///     }
    714 ///     nk_input_end(&ctx);
    715 ///     // [...]
    716 ///     nk_clear(&ctx);
    717 /// } nk_free(&ctx);
    718 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    719 ///
    720 /// #### Reference
    721 /// Function            | Description
    722 /// --------------------|-------------------------------------------------------
    723 /// __nk_input_begin__  | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
    724 /// __nk_input_motion__ | Mirrors mouse cursor position
    725 /// __nk_input_key__    | Mirrors key state with either pressed or released
    726 /// __nk_input_button__ | Mirrors mouse button state with either pressed or released
    727 /// __nk_input_scroll__ | Mirrors mouse scroll values
    728 /// __nk_input_char__   | Adds a single ASCII text character into an internal text buffer
    729 /// __nk_input_glyph__  | Adds a single multi-byte UTF-8 character into an internal text buffer
    730 /// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer
    731 /// __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
    732 */
    733 enum nk_keys {
    734     NK_KEY_NONE,
    735     NK_KEY_SHIFT,
    736     NK_KEY_CTRL,
    737     NK_KEY_DEL,
    738     NK_KEY_ENTER,
    739     NK_KEY_TAB,
    740     NK_KEY_BACKSPACE,
    741     NK_KEY_COPY,
    742     NK_KEY_CUT,
    743     NK_KEY_PASTE,
    744     NK_KEY_UP,
    745     NK_KEY_DOWN,
    746     NK_KEY_LEFT,
    747     NK_KEY_RIGHT,
    748     /* Shortcuts: text field */
    749     NK_KEY_TEXT_INSERT_MODE,
    750     NK_KEY_TEXT_REPLACE_MODE,
    751     NK_KEY_TEXT_RESET_MODE,
    752     NK_KEY_TEXT_LINE_START,
    753     NK_KEY_TEXT_LINE_END,
    754     NK_KEY_TEXT_START,
    755     NK_KEY_TEXT_END,
    756     NK_KEY_TEXT_UNDO,
    757     NK_KEY_TEXT_REDO,
    758     NK_KEY_TEXT_SELECT_ALL,
    759     NK_KEY_TEXT_WORD_LEFT,
    760     NK_KEY_TEXT_WORD_RIGHT,
    761     /* Shortcuts: scrollbar */
    762     NK_KEY_SCROLL_START,
    763     NK_KEY_SCROLL_END,
    764     NK_KEY_SCROLL_DOWN,
    765     NK_KEY_SCROLL_UP,
    766     NK_KEY_MAX
    767 };
    768 enum nk_buttons {
    769     NK_BUTTON_LEFT,
    770     NK_BUTTON_MIDDLE,
    771     NK_BUTTON_RIGHT,
    772     NK_BUTTON_DOUBLE,
    773     NK_BUTTON_MAX
    774 };
    775 /*/// #### nk_input_begin
    776 /// Begins the input mirroring process by resetting text, scroll
    777 /// mouse, previous mouse position and movement as well as key state transitions,
    778 ///
    779 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    780 /// void nk_input_begin(struct nk_context*);
    781 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    782 ///
    783 /// Parameter   | Description
    784 /// ------------|-----------------------------------------------------------
    785 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    786 */
    787 NK_API void nk_input_begin(struct nk_context*);
    788 /*/// #### nk_input_motion
    789 /// Mirrors current mouse position to nuklear
    790 ///
    791 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    792 /// void nk_input_motion(struct nk_context *ctx, int x, int y);
    793 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    794 ///
    795 /// Parameter   | Description
    796 /// ------------|-----------------------------------------------------------
    797 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    798 /// __x__       | Must hold an integer describing the current mouse cursor x-position
    799 /// __y__       | Must hold an integer describing the current mouse cursor y-position
    800 */
    801 NK_API void nk_input_motion(struct nk_context*, int x, int y);
    802 /*/// #### nk_input_key
    803 /// Mirrors the state of a specific key to nuklear
    804 ///
    805 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    806 /// void nk_input_key(struct nk_context*, enum nk_keys key, int down);
    807 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    808 ///
    809 /// Parameter   | Description
    810 /// ------------|-----------------------------------------------------------
    811 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    812 /// __key__     | Must be any value specified in enum `nk_keys` that needs to be mirrored
    813 /// __down__    | Must be 0 for key is up and 1 for key is down
    814 */
    815 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
    816 /*/// #### nk_input_button
    817 /// Mirrors the state of a specific mouse button to nuklear
    818 ///
    819 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    820 /// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, int down);
    821 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    822 ///
    823 /// Parameter   | Description
    824 /// ------------|-----------------------------------------------------------
    825 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    826 /// __btn__     | Must be any value specified in enum `nk_buttons` that needs to be mirrored
    827 /// __x__       | Must contain an integer describing mouse cursor x-position on click up/down
    828 /// __y__       | Must contain an integer describing mouse cursor y-position on click up/down
    829 /// __down__    | Must be 0 for key is up and 1 for key is down
    830 */
    831 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
    832 /*/// #### nk_input_scroll
    833 /// Copies the last mouse scroll value to nuklear. Is generally
    834 /// a scroll value. So does not have to come from mouse and could also originate
    835 /// TODO finish this sentence
    836 ///
    837 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    838 /// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val);
    839 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    840 ///
    841 /// Parameter   | Description
    842 /// ------------|-----------------------------------------------------------
    843 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    844 /// __val__     | vector with both X- as well as Y-scroll value
    845 */
    846 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
    847 /*/// #### nk_input_char
    848 /// Copies a single ASCII character into an internal text buffer
    849 /// This is basically a helper function to quickly push ASCII characters into
    850 /// nuklear.
    851 ///
    852 /// !!! Note
    853 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
    854 ///
    855 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    856 /// void nk_input_char(struct nk_context *ctx, char c);
    857 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    858 ///
    859 /// Parameter   | Description
    860 /// ------------|-----------------------------------------------------------
    861 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    862 /// __c__       | Must be a single ASCII character preferable one that can be printed
    863 */
    864 NK_API void nk_input_char(struct nk_context*, char);
    865 /*/// #### nk_input_glyph
    866 /// Converts an encoded unicode rune into UTF-8 and copies the result into an
    867 /// internal text buffer.
    868 ///
    869 /// !!! Note
    870 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
    871 ///
    872 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    873 /// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g);
    874 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    875 ///
    876 /// Parameter   | Description
    877 /// ------------|-----------------------------------------------------------
    878 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    879 /// __g__       | UTF-32 unicode codepoint
    880 */
    881 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
    882 /*/// #### nk_input_unicode
    883 /// Converts a unicode rune into UTF-8 and copies the result
    884 /// into an internal text buffer.
    885 /// !!! Note
    886 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
    887 ///
    888 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    889 /// void nk_input_unicode(struct nk_context*, nk_rune rune);
    890 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    891 ///
    892 /// Parameter   | Description
    893 /// ------------|-----------------------------------------------------------
    894 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    895 /// __rune__    | UTF-32 unicode codepoint
    896 */
    897 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
    898 /*/// #### nk_input_end
    899 /// End the input mirroring process by resetting mouse grabbing
    900 /// state to ensure the mouse cursor is not grabbed indefinitely.
    901 ///
    902 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    903 /// void nk_input_end(struct nk_context *ctx);
    904 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    905 ///
    906 /// Parameter   | Description
    907 /// ------------|-----------------------------------------------------------
    908 /// __ctx__     | Must point to a previously initialized `nk_context` struct
    909 */
    910 NK_API void nk_input_end(struct nk_context*);
    911 /* =============================================================================
    912  *
    913  *                                  DRAWING
    914  *
    915  * =============================================================================*/
    916 /*/// ### Drawing
    917 /// This library was designed to be render backend agnostic so it does
    918 /// not draw anything to screen directly. Instead all drawn shapes, widgets
    919 /// are made of, are buffered into memory and make up a command queue.
    920 /// Each frame therefore fills the command buffer with draw commands
    921 /// that then need to be executed by the user and his own render backend.
    922 /// After that the command buffer needs to be cleared and a new frame can be
    923 /// started. It is probably important to note that the command buffer is the main
    924 /// drawing API and the optional vertex buffer API only takes this format and
    925 /// converts it into a hardware accessible format.
    926 ///
    927 /// #### Usage
    928 /// To draw all draw commands accumulated over a frame you need your own render
    929 /// backend able to draw a number of 2D primitives. This includes at least
    930 /// filled and stroked rectangles, circles, text, lines, triangles and scissors.
    931 /// As soon as this criterion is met you can iterate over each draw command
    932 /// and execute each draw command in a interpreter like fashion:
    933 ///
    934 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    935 /// const struct nk_command *cmd = 0;
    936 /// nk_foreach(cmd, &ctx) {
    937 ///     switch (cmd->type) {
    938 ///     case NK_COMMAND_LINE:
    939 ///         your_draw_line_function(...)
    940 ///         break;
    941 ///     case NK_COMMAND_RECT
    942 ///         your_draw_rect_function(...)
    943 ///         break;
    944 ///     case //...:
    945 ///         //[...]
    946 ///     }
    947 /// }
    948 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    949 ///
    950 /// In program flow context draw commands need to be executed after input has been
    951 /// gathered and the complete UI with windows and their contained widgets have
    952 /// been executed and before calling `nk_clear` which frees all previously
    953 /// allocated draw commands.
    954 ///
    955 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
    956 /// struct nk_context ctx;
    957 /// nk_init_xxx(&ctx, ...);
    958 /// while (1) {
    959 ///     Event evt;
    960 ///     nk_input_begin(&ctx);
    961 ///     while (GetEvent(&evt)) {
    962 ///         if (evt.type == MOUSE_MOVE)
    963 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
    964 ///         else if (evt.type == [...]) {
    965 ///             [...]
    966 ///         }
    967 ///     }
    968 ///     nk_input_end(&ctx);
    969 ///     //
    970 ///     // [...]
    971 ///     //
    972 ///     const struct nk_command *cmd = 0;
    973 ///     nk_foreach(cmd, &ctx) {
    974 ///     switch (cmd->type) {
    975 ///     case NK_COMMAND_LINE:
    976 ///         your_draw_line_function(...)
    977 ///         break;
    978 ///     case NK_COMMAND_RECT
    979 ///         your_draw_rect_function(...)
    980 ///         break;
    981 ///     case ...:
    982 ///         // [...]
    983 ///     }
    984 ///     nk_clear(&ctx);
    985 /// }
    986 /// nk_free(&ctx);
    987 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    988 ///
    989 /// You probably noticed that you have to draw all of the UI each frame which is
    990 /// quite wasteful. While the actual UI updating loop is quite fast rendering
    991 /// without actually needing it is not. So there are multiple things you could do.
    992 ///
    993 /// First is only update on input. This of course is only an option if your
    994 /// application only depends on the UI and does not require any outside calculations.
    995 /// If you actually only update on input make sure to update the UI two times each
    996 /// frame and call `nk_clear` directly after the first pass and only draw in
    997 /// the second pass. In addition it is recommended to also add additional timers
    998 /// to make sure the UI is not drawn more than a fixed number of frames per second.
    999 ///
   1000 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1001 /// struct nk_context ctx;
   1002 /// nk_init_xxx(&ctx, ...);
   1003 /// while (1) {
   1004 ///     // [...wait for input ]
   1005 ///     // [...do two UI passes ...]
   1006 ///     do_ui(...)
   1007 ///     nk_clear(&ctx);
   1008 ///     do_ui(...)
   1009 ///     //
   1010 ///     // draw
   1011 ///     const struct nk_command *cmd = 0;
   1012 ///     nk_foreach(cmd, &ctx) {
   1013 ///     switch (cmd->type) {
   1014 ///     case NK_COMMAND_LINE:
   1015 ///         your_draw_line_function(...)
   1016 ///         break;
   1017 ///     case NK_COMMAND_RECT
   1018 ///         your_draw_rect_function(...)
   1019 ///         break;
   1020 ///     case ...:
   1021 ///         //[...]
   1022 ///     }
   1023 ///     nk_clear(&ctx);
   1024 /// }
   1025 /// nk_free(&ctx);
   1026 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1027 ///
   1028 /// The second probably more applicable trick is to only draw if anything changed.
   1029 /// It is not really useful for applications with continuous draw loop but
   1030 /// quite useful for desktop applications. To actually get nuklear to only
   1031 /// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
   1032 /// allocate a memory buffer that will store each unique drawing output.
   1033 /// After each frame you compare the draw command memory inside the library
   1034 /// with your allocated buffer by memcmp. If memcmp detects differences
   1035 /// you have to copy the command buffer into the allocated buffer
   1036 /// and then draw like usual (this example uses fixed memory but you could
   1037 /// use dynamically allocated memory).
   1038 ///
   1039 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1040 /// //[... other defines ...]
   1041 /// #define NK_ZERO_COMMAND_MEMORY
   1042 /// #include "nuklear.h"
   1043 /// //
   1044 /// // setup context
   1045 /// struct nk_context ctx;
   1046 /// void *last = calloc(1,64*1024);
   1047 /// void *buf = calloc(1,64*1024);
   1048 /// nk_init_fixed(&ctx, buf, 64*1024);
   1049 /// //
   1050 /// // loop
   1051 /// while (1) {
   1052 ///     // [...input...]
   1053 ///     // [...ui...]
   1054 ///     void *cmds = nk_buffer_memory(&ctx.memory);
   1055 ///     if (memcmp(cmds, last, ctx.memory.allocated)) {
   1056 ///         memcpy(last,cmds,ctx.memory.allocated);
   1057 ///         const struct nk_command *cmd = 0;
   1058 ///         nk_foreach(cmd, &ctx) {
   1059 ///             switch (cmd->type) {
   1060 ///             case NK_COMMAND_LINE:
   1061 ///                 your_draw_line_function(...)
   1062 ///                 break;
   1063 ///             case NK_COMMAND_RECT
   1064 ///                 your_draw_rect_function(...)
   1065 ///                 break;
   1066 ///             case ...:
   1067 ///                 // [...]
   1068 ///             }
   1069 ///         }
   1070 ///     }
   1071 ///     nk_clear(&ctx);
   1072 /// }
   1073 /// nk_free(&ctx);
   1074 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1075 ///
   1076 /// Finally while using draw commands makes sense for higher abstracted platforms like
   1077 /// X11 and Win32 or drawing libraries it is often desirable to use graphics
   1078 /// hardware directly. Therefore it is possible to just define
   1079 /// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
   1080 /// To access the vertex output you first have to convert all draw commands into
   1081 /// vertexes by calling `nk_convert` which takes in your preferred vertex format.
   1082 /// After successfully converting all draw commands just iterate over and execute all
   1083 /// vertex draw commands:
   1084 ///
   1085 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1086 /// // fill configuration
   1087 /// struct nk_convert_config cfg = {};
   1088 /// static const struct nk_draw_vertex_layout_element vertex_layout[] = {
   1089 ///     {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
   1090 ///     {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
   1091 ///     {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
   1092 ///     {NK_VERTEX_LAYOUT_END}
   1093 /// };
   1094 /// cfg.shape_AA = NK_ANTI_ALIASING_ON;
   1095 /// cfg.line_AA = NK_ANTI_ALIASING_ON;
   1096 /// cfg.vertex_layout = vertex_layout;
   1097 /// cfg.vertex_size = sizeof(struct your_vertex);
   1098 /// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
   1099 /// cfg.circle_segment_count = 22;
   1100 /// cfg.curve_segment_count = 22;
   1101 /// cfg.arc_segment_count = 22;
   1102 /// cfg.global_alpha = 1.0f;
   1103 /// cfg.null = dev->null;
   1104 /// //
   1105 /// // setup buffers and convert
   1106 /// struct nk_buffer cmds, verts, idx;
   1107 /// nk_buffer_init_default(&cmds);
   1108 /// nk_buffer_init_default(&verts);
   1109 /// nk_buffer_init_default(&idx);
   1110 /// nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
   1111 /// //
   1112 /// // draw
   1113 /// nk_draw_foreach(cmd, &ctx, &cmds) {
   1114 /// if (!cmd->elem_count) continue;
   1115 ///     //[...]
   1116 /// }
   1117 /// nk_buffer_free(&cms);
   1118 /// nk_buffer_free(&verts);
   1119 /// nk_buffer_free(&idx);
   1120 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1121 ///
   1122 /// #### Reference
   1123 /// Function            | Description
   1124 /// --------------------|-------------------------------------------------------
   1125 /// __nk__begin__       | Returns the first draw command in the context draw command list to be drawn
   1126 /// __nk__next__        | Increments the draw command iterator to the next command inside the context draw command list
   1127 /// __nk_foreach__      | Iterates over each draw command inside the context draw command list
   1128 /// __nk_convert__      | Converts from the abstract draw commands list into a hardware accessible vertex format
   1129 /// __nk_draw_begin__   | Returns the first vertex command in the context vertex draw list to be executed
   1130 /// __nk__draw_next__   | Increments the vertex command iterator to the next command inside the context vertex command list
   1131 /// __nk__draw_end__    | Returns the end of the vertex draw list
   1132 /// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list
   1133 */
   1134 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON};
   1135 enum nk_convert_result {
   1136     NK_CONVERT_SUCCESS = 0,
   1137     NK_CONVERT_INVALID_PARAM = 1,
   1138     NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1),
   1139     NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2),
   1140     NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3)
   1141 };
   1142 struct nk_draw_null_texture {
   1143     nk_handle texture; /* texture handle to a texture with a white pixel */
   1144     struct nk_vec2 uv; /* coordinates to a white pixel in the texture  */
   1145 };
   1146 struct nk_convert_config {
   1147     float global_alpha; /* global alpha value */
   1148     enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
   1149     enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
   1150     unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
   1151     unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
   1152     unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
   1153     struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
   1154     const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
   1155     nk_size vertex_size; /* sizeof one vertex for vertex packing */
   1156     nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
   1157 };
   1158 /*/// #### nk__begin
   1159 /// Returns a draw command list iterator to iterate all draw
   1160 /// commands accumulated over one frame.
   1161 ///
   1162 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1163 /// const struct nk_command* nk__begin(struct nk_context*);
   1164 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1165 ///
   1166 /// Parameter   | Description
   1167 /// ------------|-----------------------------------------------------------
   1168 /// __ctx__     | must point to an previously initialized `nk_context` struct at the end of a frame
   1169 ///
   1170 /// Returns draw command pointer pointing to the first command inside the draw command list
   1171 */
   1172 NK_API const struct nk_command* nk__begin(struct nk_context*);
   1173 /*/// #### nk__next
   1174 /// Returns draw command pointer pointing to the next command inside the draw command list
   1175 ///
   1176 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1177 /// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
   1178 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1179 ///
   1180 /// Parameter   | Description
   1181 /// ------------|-----------------------------------------------------------
   1182 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1183 /// __cmd__     | Must point to an previously a draw command either returned by `nk__begin` or `nk__next`
   1184 ///
   1185 /// Returns draw command pointer pointing to the next command inside the draw command list
   1186 */
   1187 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
   1188 /*/// #### nk_foreach
   1189 /// Iterates over each draw command inside the context draw command list
   1190 ///
   1191 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1192 /// #define nk_foreach(c, ctx)
   1193 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1194 ///
   1195 /// Parameter   | Description
   1196 /// ------------|-----------------------------------------------------------
   1197 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1198 /// __cmd__     | Command pointer initialized to NULL
   1199 ///
   1200 /// Iterates over each draw command inside the context draw command list
   1201 */
   1202 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
   1203 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   1204 /*/// #### nk_convert
   1205 /// Converts all internal draw commands into vertex draw commands and fills
   1206 /// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format
   1207 /// as well as some other configuration values have to be configured by filling out a
   1208 /// `nk_convert_config` struct.
   1209 ///
   1210 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1211 /// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
   1212 //      struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
   1213 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1214 ///
   1215 /// Parameter   | Description
   1216 /// ------------|-----------------------------------------------------------
   1217 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1218 /// __cmds__    | Must point to a previously initialized buffer to hold converted vertex draw commands
   1219 /// __vertices__| Must point to a previously initialized buffer to hold all produced vertices
   1220 /// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices
   1221 /// __config__  | Must point to a filled out `nk_config` struct to configure the conversion process
   1222 ///
   1223 /// Returns one of enum nk_convert_result error codes
   1224 ///
   1225 /// Parameter                       | Description
   1226 /// --------------------------------|-----------------------------------------------------------
   1227 /// NK_CONVERT_SUCCESS              | Signals a successful draw command to vertex buffer conversion
   1228 /// NK_CONVERT_INVALID_PARAM        | An invalid argument was passed in the function call
   1229 /// NK_CONVERT_COMMAND_BUFFER_FULL  | The provided buffer for storing draw commands is full or failed to allocate more memory
   1230 /// NK_CONVERT_VERTEX_BUFFER_FULL   | The provided buffer for storing vertices is full or failed to allocate more memory
   1231 /// NK_CONVERT_ELEMENT_BUFFER_FULL  | The provided buffer for storing indicies is full or failed to allocate more memory
   1232 */
   1233 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*);
   1234 /*/// #### nk__draw_begin
   1235 /// Returns a draw vertex command buffer iterator to iterate over the vertex draw command buffer
   1236 ///
   1237 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1238 /// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
   1239 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1240 ///
   1241 /// Parameter   | Description
   1242 /// ------------|-----------------------------------------------------------
   1243 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1244 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
   1245 ///
   1246 /// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer
   1247 */
   1248 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
   1249 /*/// #### nk__draw_end
   1250 /// Returns the vertex draw command at the end of the vertex draw command buffer
   1251 ///
   1252 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1253 /// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf);
   1254 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1255 ///
   1256 /// Parameter   | Description
   1257 /// ------------|-----------------------------------------------------------
   1258 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1259 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
   1260 ///
   1261 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
   1262 */
   1263 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
   1264 /*/// #### nk__draw_next
   1265 /// Increments the vertex draw command buffer iterator
   1266 ///
   1267 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1268 /// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
   1269 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1270 ///
   1271 /// Parameter   | Description
   1272 /// ------------|-----------------------------------------------------------
   1273 /// __cmd__     | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
   1274 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
   1275 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1276 ///
   1277 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
   1278 */
   1279 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
   1280 /*/// #### nk_draw_foreach
   1281 /// Iterates over each vertex draw command inside a vertex draw command buffer
   1282 ///
   1283 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1284 /// #define nk_draw_foreach(cmd,ctx, b)
   1285 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1286 ///
   1287 /// Parameter   | Description
   1288 /// ------------|-----------------------------------------------------------
   1289 /// __cmd__     | `nk_draw_command`iterator set to NULL
   1290 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
   1291 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
   1292 */
   1293 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
   1294 #endif
   1295 /* =============================================================================
   1296  *
   1297  *                                  WINDOW
   1298  *
   1299  * =============================================================================
   1300 /// ### Window
   1301 /// Windows are the main persistent state used inside nuklear and are life time
   1302 /// controlled by simply "retouching" (i.e. calling) each window each frame.
   1303 /// All widgets inside nuklear can only be added inside the function pair `nk_begin_xxx`
   1304 /// and `nk_end`. Calling any widgets outside these two functions will result in an
   1305 /// assert in debug or no state change in release mode.<br /><br />
   1306 ///
   1307 /// Each window holds frame persistent state like position, size, flags, state tables,
   1308 /// and some garbage collected internal persistent widget state. Each window
   1309 /// is linked into a window stack list which determines the drawing and overlapping
   1310 /// order. The topmost window thereby is the currently active window.<br /><br />
   1311 ///
   1312 /// To change window position inside the stack occurs either automatically by
   1313 /// user input by being clicked on or programmatically by calling `nk_window_focus`.
   1314 /// Windows by default are visible unless explicitly being defined with flag
   1315 /// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
   1316 /// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
   1317 /// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.<br /><br />
   1318 ///
   1319 /// #### Usage
   1320 /// To create and keep a window you have to call one of the two `nk_begin_xxx`
   1321 /// functions to start window declarations and `nk_end` at the end. Furthermore it
   1322 /// is recommended to check the return value of `nk_begin_xxx` and only process
   1323 /// widgets inside the window if the value is not 0. Either way you have to call
   1324 /// `nk_end` at the end of window declarations. Furthermore, do not attempt to
   1325 /// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
   1326 /// in a segmentation fault.
   1327 ///
   1328 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1329 /// if (nk_begin_xxx(...) {
   1330 ///     // [... widgets ...]
   1331 /// }
   1332 /// nk_end(ctx);
   1333 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1334 ///
   1335 /// In the grand concept window and widget declarations need to occur after input
   1336 /// handling and before drawing to screen. Not doing so can result in higher
   1337 /// latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
   1338 /// is called at the end of the frame. While nuklear's default platform backends
   1339 /// already call `nk_clear` for you if you write your own backend not calling
   1340 /// `nk_clear` can cause asserts or even worse undefined behavior.
   1341 ///
   1342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1343 /// struct nk_context ctx;
   1344 /// nk_init_xxx(&ctx, ...);
   1345 /// while (1) {
   1346 ///     Event evt;
   1347 ///     nk_input_begin(&ctx);
   1348 ///     while (GetEvent(&evt)) {
   1349 ///         if (evt.type == MOUSE_MOVE)
   1350 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
   1351 ///         else if (evt.type == [...]) {
   1352 ///             nk_input_xxx(...);
   1353 ///         }
   1354 ///     }
   1355 ///     nk_input_end(&ctx);
   1356 ///
   1357 ///     if (nk_begin_xxx(...) {
   1358 ///         //[...]
   1359 ///     }
   1360 ///     nk_end(ctx);
   1361 ///
   1362 ///     const struct nk_command *cmd = 0;
   1363 ///     nk_foreach(cmd, &ctx) {
   1364 ///     case NK_COMMAND_LINE:
   1365 ///         your_draw_line_function(...)
   1366 ///         break;
   1367 ///     case NK_COMMAND_RECT
   1368 ///         your_draw_rect_function(...)
   1369 ///         break;
   1370 ///     case //...:
   1371 ///         //[...]
   1372 ///     }
   1373 ///     nk_clear(&ctx);
   1374 /// }
   1375 /// nk_free(&ctx);
   1376 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1377 ///
   1378 /// #### Reference
   1379 /// Function                            | Description
   1380 /// ------------------------------------|----------------------------------------
   1381 /// nk_begin                            | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
   1382 /// nk_begin_titled                     | Extended window start with separated title and identifier to allow multiple windows with same name but not title
   1383 /// nk_end                              | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
   1384 //
   1385 /// nk_window_find                      | Finds and returns the window with give name
   1386 /// nk_window_get_bounds                | Returns a rectangle with screen position and size of the currently processed window.
   1387 /// nk_window_get_position              | Returns the position of the currently processed window
   1388 /// nk_window_get_size                  | Returns the size with width and height of the currently processed window
   1389 /// nk_window_get_width                 | Returns the width of the currently processed window
   1390 /// nk_window_get_height                | Returns the height of the currently processed window
   1391 /// nk_window_get_panel                 | Returns the underlying panel which contains all processing state of the current window
   1392 /// nk_window_get_content_region        | Returns the position and size of the currently visible and non-clipped space inside the currently processed window
   1393 /// nk_window_get_content_region_min    | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
   1394 /// nk_window_get_content_region_max    | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
   1395 /// nk_window_get_content_region_size   | Returns the size of the currently visible and non-clipped space inside the currently processed window
   1396 /// nk_window_get_canvas                | Returns the draw command buffer. Can be used to draw custom widgets
   1397 /// nk_window_has_focus                 | Returns if the currently processed window is currently active
   1398 /// nk_window_is_collapsed              | Returns if the window with given name is currently minimized/collapsed
   1399 /// nk_window_is_closed                 | Returns if the currently processed window was closed
   1400 /// nk_window_is_hidden                 | Returns if the currently processed window was hidden
   1401 /// nk_window_is_active                 | Same as nk_window_has_focus for some reason
   1402 /// nk_window_is_hovered                | Returns if the currently processed window is currently being hovered by mouse
   1403 /// nk_window_is_any_hovered            | Return if any window currently hovered
   1404 /// nk_item_is_any_active               | Returns if any window or widgets is currently hovered or active
   1405 //
   1406 /// nk_window_set_bounds                | Updates position and size of the currently processed window
   1407 /// nk_window_set_position              | Updates position of the currently process window
   1408 /// nk_window_set_size                  | Updates the size of the currently processed window
   1409 /// nk_window_set_focus                 | Set the currently processed window as active window
   1410 //
   1411 /// nk_window_close                     | Closes the window with given window name which deletes the window at the end of the frame
   1412 /// nk_window_collapse                  | Collapses the window with given window name
   1413 /// nk_window_collapse_if               | Collapses the window with given window name if the given condition was met
   1414 /// nk_window_show                      | Hides a visible or reshows a hidden window
   1415 /// nk_window_show_if                   | Hides/shows a window depending on condition
   1416 */
   1417 /*
   1418 /// #### nk_panel_flags
   1419 /// Flag                        | Description
   1420 /// ----------------------------|----------------------------------------
   1421 /// NK_WINDOW_BORDER            | Draws a border around the window to visually separate window from the background
   1422 /// NK_WINDOW_MOVABLE           | The movable flag indicates that a window can be moved by user input or by dragging the window header
   1423 /// 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
   1424 /// NK_WINDOW_CLOSABLE          | Adds a closable icon into the header
   1425 /// NK_WINDOW_MINIMIZABLE       | Adds a minimize icon into the header
   1426 /// NK_WINDOW_NO_SCROLLBAR      | Removes the scrollbar from the window
   1427 /// NK_WINDOW_TITLE             | Forces a header at the top at the window showing the title
   1428 /// 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
   1429 /// NK_WINDOW_BACKGROUND        | Always keep window in the background
   1430 /// NK_WINDOW_SCALE_LEFT        | Puts window scaler in the left-ottom corner instead right-bottom
   1431 /// NK_WINDOW_NO_INPUT          | Prevents window of scaling, moving or getting focus
   1432 ///
   1433 /// #### nk_collapse_states
   1434 /// State           | Description
   1435 /// ----------------|-----------------------------------------------------------
   1436 /// __NK_MINIMIZED__| UI section is collased and not visibile until maximized
   1437 /// __NK_MAXIMIZED__| UI section is extended and visibile until minimized
   1438 /// <br /><br />
   1439 */
   1440 enum nk_panel_flags {
   1441     NK_WINDOW_BORDER            = NK_FLAG(0),
   1442     NK_WINDOW_MOVABLE           = NK_FLAG(1),
   1443     NK_WINDOW_SCALABLE          = NK_FLAG(2),
   1444     NK_WINDOW_CLOSABLE          = NK_FLAG(3),
   1445     NK_WINDOW_MINIMIZABLE       = NK_FLAG(4),
   1446     NK_WINDOW_NO_SCROLLBAR      = NK_FLAG(5),
   1447     NK_WINDOW_TITLE             = NK_FLAG(6),
   1448     NK_WINDOW_SCROLL_AUTO_HIDE  = NK_FLAG(7),
   1449     NK_WINDOW_BACKGROUND        = NK_FLAG(8),
   1450     NK_WINDOW_SCALE_LEFT        = NK_FLAG(9),
   1451     NK_WINDOW_NO_INPUT          = NK_FLAG(10)
   1452 };
   1453 /*/// #### nk_begin
   1454 /// Starts a new window; needs to be called every frame for every
   1455 /// window (unless hidden) or otherwise the window gets removed
   1456 ///
   1457 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1458 /// int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
   1459 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1460 ///
   1461 /// Parameter   | Description
   1462 /// ------------|-----------------------------------------------------------
   1463 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1464 /// __title__   | Window title and identifier. Needs to be persistent over frames to identify the window
   1465 /// __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
   1466 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different window behaviors
   1467 ///
   1468 /// Returns `true(1)` if the window can be filled up with widgets from this point
   1469 /// until `nk_end` or `false(0)` otherwise for example if minimized
   1470 */
   1471 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
   1472 /*/// #### nk_begin_titled
   1473 /// Extended window start with separated title and identifier to allow multiple
   1474 /// windows with same title but not name
   1475 ///
   1476 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1477 /// int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
   1478 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1479 ///
   1480 /// Parameter   | Description
   1481 /// ------------|-----------------------------------------------------------
   1482 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1483 /// __name__    | Window identifier. Needs to be persistent over frames to identify the window
   1484 /// __title__   | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
   1485 /// __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
   1486 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different window behaviors
   1487 ///
   1488 /// Returns `true(1)` if the window can be filled up with widgets from this point
   1489 /// until `nk_end` or `false(0)` otherwise for example if minimized
   1490 */
   1491 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
   1492 /*/// #### nk_end
   1493 /// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
   1494 /// All widget calls after this functions will result in asserts or no state changes
   1495 ///
   1496 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1497 /// void nk_end(struct nk_context *ctx);
   1498 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1499 ///
   1500 /// Parameter   | Description
   1501 /// ------------|-----------------------------------------------------------
   1502 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1503 */
   1504 NK_API void nk_end(struct nk_context *ctx);
   1505 /*/// #### nk_window_find
   1506 /// Finds and returns a window from passed name
   1507 ///
   1508 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1509 /// void nk_end(struct nk_context *ctx);
   1510 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1511 ///
   1512 /// Parameter   | Description
   1513 /// ------------|-----------------------------------------------------------
   1514 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1515 /// __name__    | Window identifier
   1516 ///
   1517 /// Returns a `nk_window` struct pointing to the identified window or NULL if
   1518 /// no window with the given name was found
   1519 */
   1520 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
   1521 /*/// #### nk_window_get_bounds
   1522 /// Returns a rectangle with screen position and size of the currently processed window
   1523 ///
   1524 /// !!! WARNING
   1525 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1526 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1527 /// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
   1528 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1529 ///
   1530 /// Parameter   | Description
   1531 /// ------------|-----------------------------------------------------------
   1532 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1533 ///
   1534 /// Returns a `nk_rect` struct with window upper left window position and size
   1535 */
   1536 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
   1537 /*/// #### nk_window_get_position
   1538 /// Returns the position of the currently processed window.
   1539 ///
   1540 /// !!! WARNING
   1541 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1542 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1543 /// struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
   1544 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1545 ///
   1546 /// Parameter   | Description
   1547 /// ------------|-----------------------------------------------------------
   1548 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1549 ///
   1550 /// Returns a `nk_vec2` struct with window upper left position
   1551 */
   1552 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
   1553 /*/// #### nk_window_get_size
   1554 /// Returns the size with width and height of the currently processed window.
   1555 ///
   1556 /// !!! WARNING
   1557 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1558 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1559 /// struct nk_vec2 nk_window_get_size(const struct nk_context *ctx);
   1560 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1561 ///
   1562 /// Parameter   | Description
   1563 /// ------------|-----------------------------------------------------------
   1564 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1565 ///
   1566 /// Returns a `nk_vec2` struct with window width and height
   1567 */
   1568 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*);
   1569 /*/// #### nk_window_get_width
   1570 /// Returns the width of the currently processed window.
   1571 ///
   1572 /// !!! WARNING
   1573 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1575 /// float nk_window_get_width(const struct nk_context *ctx);
   1576 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1577 ///
   1578 /// Parameter   | Description
   1579 /// ------------|-----------------------------------------------------------
   1580 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1581 ///
   1582 /// Returns the current window width
   1583 */
   1584 NK_API float nk_window_get_width(const struct nk_context*);
   1585 /*/// #### nk_window_get_height
   1586 /// Returns the height of the currently processed window.
   1587 ///
   1588 /// !!! WARNING
   1589 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1590 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1591 /// float nk_window_get_height(const struct nk_context *ctx);
   1592 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1593 ///
   1594 /// Parameter   | Description
   1595 /// ------------|-----------------------------------------------------------
   1596 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1597 ///
   1598 /// Returns the current window height
   1599 */
   1600 NK_API float nk_window_get_height(const struct nk_context*);
   1601 /*/// #### nk_window_get_panel
   1602 /// Returns the underlying panel which contains all processing state of the current window.
   1603 ///
   1604 /// !!! WARNING
   1605 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1606 /// !!! WARNING
   1607 ///     Do not keep the returned panel pointer around, it is only valid until `nk_end`
   1608 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1609 /// struct nk_panel* nk_window_get_panel(struct nk_context *ctx);
   1610 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1611 ///
   1612 /// Parameter   | Description
   1613 /// ------------|-----------------------------------------------------------
   1614 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1615 ///
   1616 /// Returns a pointer to window internal `nk_panel` state.
   1617 */
   1618 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*);
   1619 /*/// #### nk_window_get_content_region
   1620 /// Returns the position and size of the currently visible and non-clipped space
   1621 /// inside the currently processed window.
   1622 ///
   1623 /// !!! WARNING
   1624 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1625 ///
   1626 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1627 /// struct nk_rect nk_window_get_content_region(struct nk_context *ctx);
   1628 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1629 ///
   1630 /// Parameter   | Description
   1631 /// ------------|-----------------------------------------------------------
   1632 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1633 ///
   1634 /// Returns `nk_rect` struct with screen position and size (no scrollbar offset)
   1635 /// of the visible space inside the current window
   1636 */
   1637 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*);
   1638 /*/// #### nk_window_get_content_region_min
   1639 /// Returns the upper left position of the currently visible and non-clipped
   1640 /// space inside the currently processed window.
   1641 ///
   1642 /// !!! WARNING
   1643 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1644 ///
   1645 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1646 /// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx);
   1647 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1648 ///
   1649 /// Parameter   | Description
   1650 /// ------------|-----------------------------------------------------------
   1651 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1652 ///
   1653 /// returns `nk_vec2` struct with  upper left screen position (no scrollbar offset)
   1654 /// of the visible space inside the current window
   1655 */
   1656 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*);
   1657 /*/// #### nk_window_get_content_region_max
   1658 /// Returns the lower right screen position of the currently visible and
   1659 /// non-clipped space inside the currently processed window.
   1660 ///
   1661 /// !!! WARNING
   1662 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1663 ///
   1664 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1665 /// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx);
   1666 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1667 ///
   1668 /// Parameter   | Description
   1669 /// ------------|-----------------------------------------------------------
   1670 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1671 ///
   1672 /// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset)
   1673 /// of the visible space inside the current window
   1674 */
   1675 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*);
   1676 /*/// #### nk_window_get_content_region_size
   1677 /// Returns the size of the currently visible and non-clipped space inside the
   1678 /// currently processed window
   1679 ///
   1680 /// !!! WARNING
   1681 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1682 ///
   1683 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1684 /// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx);
   1685 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1686 ///
   1687 /// Parameter   | Description
   1688 /// ------------|-----------------------------------------------------------
   1689 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1690 ///
   1691 /// Returns `nk_vec2` struct with size the visible space inside the current window
   1692 */
   1693 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*);
   1694 /*/// #### nk_window_get_canvas
   1695 /// Returns the draw command buffer. Can be used to draw custom widgets
   1696 /// !!! WARNING
   1697 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1698 /// !!! WARNING
   1699 ///     Do not keep the returned command buffer pointer around it is only valid until `nk_end`
   1700 ///
   1701 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1702 /// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx);
   1703 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1704 ///
   1705 /// Parameter   | Description
   1706 /// ------------|-----------------------------------------------------------
   1707 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1708 ///
   1709 /// Returns a pointer to window internal `nk_command_buffer` struct used as
   1710 /// drawing canvas. Can be used to do custom drawing.
   1711 */
   1712 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*);
   1713 /*/// #### nk_window_has_focus
   1714 /// Returns if the currently processed window is currently active
   1715 /// !!! WARNING
   1716 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1717 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1718 /// int nk_window_has_focus(const struct nk_context *ctx);
   1719 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1720 ///
   1721 /// Parameter   | Description
   1722 /// ------------|-----------------------------------------------------------
   1723 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1724 ///
   1725 /// Returns `false(0)` if current window is not active or `true(1)` if it is
   1726 */
   1727 NK_API int nk_window_has_focus(const struct nk_context*);
   1728 /*/// #### nk_window_is_hovered
   1729 /// Return if the current window is being hovered
   1730 /// !!! WARNING
   1731 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
   1732 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1733 /// int nk_window_is_hovered(struct nk_context *ctx);
   1734 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1735 ///
   1736 /// Parameter   | Description
   1737 /// ------------|-----------------------------------------------------------
   1738 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1739 ///
   1740 /// Returns `true(1)` if current window is hovered or `false(0)` otherwise
   1741 */
   1742 NK_API int nk_window_is_hovered(struct nk_context*);
   1743 /*/// #### nk_window_is_collapsed
   1744 /// Returns if the window with given name is currently minimized/collapsed
   1745 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1746 /// int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
   1747 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1748 ///
   1749 /// Parameter   | Description
   1750 /// ------------|-----------------------------------------------------------
   1751 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1752 /// __name__    | Identifier of window you want to check if it is collapsed
   1753 ///
   1754 /// Returns `true(1)` if current window is minimized and `false(0)` if window not
   1755 /// found or is not minimized
   1756 */
   1757 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
   1758 /*/// #### nk_window_is_closed
   1759 /// Returns if the window with given name was closed by calling `nk_close`
   1760 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1761 /// int nk_window_is_closed(struct nk_context *ctx, const char *name);
   1762 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1763 ///
   1764 /// Parameter   | Description
   1765 /// ------------|-----------------------------------------------------------
   1766 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1767 /// __name__    | Identifier of window you want to check if it is closed
   1768 ///
   1769 /// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed
   1770 */
   1771 NK_API int nk_window_is_closed(struct nk_context*, const char*);
   1772 /*/// #### nk_window_is_hidden
   1773 /// Returns if the window with given name is hidden
   1774 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1775 /// int nk_window_is_hidden(struct nk_context *ctx, const char *name);
   1776 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1777 ///
   1778 /// Parameter   | Description
   1779 /// ------------|-----------------------------------------------------------
   1780 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1781 /// __name__    | Identifier of window you want to check if it is hidden
   1782 ///
   1783 /// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible
   1784 */
   1785 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
   1786 /*/// #### nk_window_is_active
   1787 /// Same as nk_window_has_focus for some reason
   1788 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1789 /// int nk_window_is_active(struct nk_context *ctx, const char *name);
   1790 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1791 ///
   1792 /// Parameter   | Description
   1793 /// ------------|-----------------------------------------------------------
   1794 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1795 /// __name__    | Identifier of window you want to check if it is active
   1796 ///
   1797 /// Returns `true(1)` if current window is active or `false(0)` window not found or not active
   1798 */
   1799 NK_API int nk_window_is_active(struct nk_context*, const char*);
   1800 /*/// #### nk_window_is_any_hovered
   1801 /// Returns if the any window is being hovered
   1802 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1803 /// int nk_window_is_any_hovered(struct nk_context*);
   1804 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1805 ///
   1806 /// Parameter   | Description
   1807 /// ------------|-----------------------------------------------------------
   1808 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1809 ///
   1810 /// Returns `true(1)` if any window is hovered or `false(0)` otherwise
   1811 */
   1812 NK_API int nk_window_is_any_hovered(struct nk_context*);
   1813 /*/// #### nk_item_is_any_active
   1814 /// Returns if the any window is being hovered or any widget is currently active.
   1815 /// Can be used to decide if input should be processed by UI or your specific input handling.
   1816 /// Example could be UI and 3D camera to move inside a 3D space.
   1817 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1818 /// int nk_item_is_any_active(struct nk_context*);
   1819 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1820 ///
   1821 /// Parameter   | Description
   1822 /// ------------|-----------------------------------------------------------
   1823 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1824 ///
   1825 /// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise
   1826 */
   1827 NK_API int nk_item_is_any_active(struct nk_context*);
   1828 /*/// #### nk_window_set_bounds
   1829 /// Updates position and size of window with passed in name
   1830 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1831 /// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
   1832 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1833 ///
   1834 /// Parameter   | Description
   1835 /// ------------|-----------------------------------------------------------
   1836 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1837 /// __name__    | Identifier of the window to modify both position and size
   1838 /// __bounds__  | Must point to a `nk_rect` struct with the new position and size
   1839 */
   1840 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
   1841 /*/// #### nk_window_set_position
   1842 /// Updates position of window with passed name
   1843 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1844 /// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
   1845 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1846 ///
   1847 /// Parameter   | Description
   1848 /// ------------|-----------------------------------------------------------
   1849 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1850 /// __name__    | Identifier of the window to modify both position
   1851 /// __pos__     | Must point to a `nk_vec2` struct with the new position
   1852 */
   1853 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
   1854 /*/// #### nk_window_set_size
   1855 /// Updates size of window with passed in name
   1856 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1857 /// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
   1858 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1859 ///
   1860 /// Parameter   | Description
   1861 /// ------------|-----------------------------------------------------------
   1862 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1863 /// __name__    | Identifier of the window to modify both window size
   1864 /// __size__    | Must point to a `nk_vec2` struct with new window size
   1865 */
   1866 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
   1867 /*/// #### nk_window_set_focus
   1868 /// Sets the window with given name as active
   1869 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1870 /// void nk_window_set_focus(struct nk_context*, const char *name);
   1871 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1872 ///
   1873 /// Parameter   | Description
   1874 /// ------------|-----------------------------------------------------------
   1875 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1876 /// __name__    | Identifier of the window to set focus on
   1877 */
   1878 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
   1879 /*/// #### nk_window_close
   1880 /// Closes a window and marks it for being freed at the end of the frame
   1881 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1882 /// void nk_window_close(struct nk_context *ctx, const char *name);
   1883 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1884 ///
   1885 /// Parameter   | Description
   1886 /// ------------|-----------------------------------------------------------
   1887 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1888 /// __name__    | Identifier of the window to close
   1889 */
   1890 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
   1891 /*/// #### nk_window_collapse
   1892 /// Updates collapse state of a window with given name
   1893 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1894 /// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
   1895 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1896 ///
   1897 /// Parameter   | Description
   1898 /// ------------|-----------------------------------------------------------
   1899 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1900 /// __name__    | Identifier of the window to close
   1901 /// __state__   | value out of nk_collapse_states section
   1902 */
   1903 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
   1904 /*/// #### nk_window_collapse_if
   1905 /// Updates collapse state of a window with given name if given condition is met
   1906 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1907 /// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
   1908 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1909 ///
   1910 /// Parameter   | Description
   1911 /// ------------|-----------------------------------------------------------
   1912 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1913 /// __name__    | Identifier of the window to either collapse or maximize
   1914 /// __state__   | value out of nk_collapse_states section the window should be put into
   1915 /// __cond__    | condition that has to be met to actually commit the collapse state change
   1916 */
   1917 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
   1918 /*/// #### nk_window_show
   1919 /// updates visibility state of a window with given name
   1920 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1921 /// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
   1922 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1923 ///
   1924 /// Parameter   | Description
   1925 /// ------------|-----------------------------------------------------------
   1926 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1927 /// __name__    | Identifier of the window to either collapse or maximize
   1928 /// __state__   | state with either visible or hidden to modify the window with
   1929 */
   1930 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
   1931 /*/// #### nk_window_show_if
   1932 /// Updates visibility state of a window with given name if a given condition is met
   1933 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1934 /// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
   1935 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1936 ///
   1937 /// Parameter   | Description
   1938 /// ------------|-----------------------------------------------------------
   1939 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   1940 /// __name__    | Identifier of the window to either hide or show
   1941 /// __state__   | state with either visible or hidden to modify the window with
   1942 /// __cond__    | condition that has to be met to actually commit the visbility state change
   1943 */
   1944 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
   1945 /* =============================================================================
   1946  *
   1947  *                                  LAYOUT
   1948  *
   1949  * =============================================================================
   1950 /// ### Layouting
   1951 /// Layouting in general describes placing widget inside a window with position and size.
   1952 /// While in this particular implementation there are five different APIs for layouting
   1953 /// each with different trade offs between control and ease of use. <br /><br />
   1954 ///
   1955 /// All layouting methods in this library are based around the concept of a row.
   1956 /// A row has a height the window content grows by and a number of columns and each
   1957 /// layouting method specifies how each widget is placed inside the row.
   1958 /// After a row has been allocated by calling a layouting functions and then
   1959 /// filled with widgets will advance an internal pointer over the allocated row. <br /><br />
   1960 ///
   1961 /// To actually define a layout you just call the appropriate layouting function
   1962 /// and each subsequent widget call will place the widget as specified. Important
   1963 /// here is that if you define more widgets then columns defined inside the layout
   1964 /// functions it will allocate the next row without you having to make another layouting <br /><br />
   1965 /// call.
   1966 ///
   1967 /// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
   1968 /// is that you have to define the row height for each. However the row height
   1969 /// often depends on the height of the font. <br /><br />
   1970 ///
   1971 /// To fix that internally nuklear uses a minimum row height that is set to the
   1972 /// height plus padding of currently active font and overwrites the row height
   1973 /// value if zero. <br /><br />
   1974 ///
   1975 /// If you manually want to change the minimum row height then
   1976 /// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to
   1977 /// reset it back to be derived from font height. <br /><br />
   1978 ///
   1979 /// Also if you change the font in nuklear it will automatically change the minimum
   1980 /// row height for you and. This means if you change the font but still want
   1981 /// a minimum row height smaller than the font you have to repush your value. <br /><br />
   1982 ///
   1983 /// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
   1984 /// layouting method in combination with a cassowary constraint solver (there are
   1985 /// some versions on github with permissive license model) to take over all control over widget
   1986 /// layouting yourself. However for quick and dirty layouting using all the other layouting
   1987 /// functions should be fine.
   1988 ///
   1989 /// #### Usage
   1990 /// 1.  __nk_layout_row_dynamic__<br /><br />
   1991 ///     The easiest layouting function is `nk_layout_row_dynamic`. It provides each
   1992 ///     widgets with same horizontal space inside the row and dynamically grows
   1993 ///     if the owning window grows in width. So the number of columns dictates
   1994 ///     the size of each widget dynamically by formula:
   1995 ///
   1996 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   1997 ///     widget_width = (window_width - padding - spacing) * (1/colum_count)
   1998 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1999 ///
   2000 ///     Just like all other layouting APIs if you define more widget than columns this
   2001 ///     library will allocate a new row and keep all layouting parameters previously
   2002 ///     defined.
   2003 ///
   2004 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2005 ///     if (nk_begin_xxx(...) {
   2006 ///         // first row with height: 30 composed of two widgets
   2007 ///         nk_layout_row_dynamic(&ctx, 30, 2);
   2008 ///         nk_widget(...);
   2009 ///         nk_widget(...);
   2010 ///         //
   2011 ///         // second row with same parameter as defined above
   2012 ///         nk_widget(...);
   2013 ///         nk_widget(...);
   2014 ///         //
   2015 ///         // third row uses 0 for height which will use auto layouting
   2016 ///         nk_layout_row_dynamic(&ctx, 0, 2);
   2017 ///         nk_widget(...);
   2018 ///         nk_widget(...);
   2019 ///     }
   2020 ///     nk_end(...);
   2021 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2022 ///
   2023 /// 2.  __nk_layout_row_static__<br /><br />
   2024 ///     Another easy layouting function is `nk_layout_row_static`. It provides each
   2025 ///     widget with same horizontal pixel width inside the row and does not grow
   2026 ///     if the owning window scales smaller or bigger.
   2027 ///
   2028 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2029 ///     if (nk_begin_xxx(...) {
   2030 ///         // first row with height: 30 composed of two widgets with width: 80
   2031 ///         nk_layout_row_static(&ctx, 30, 80, 2);
   2032 ///         nk_widget(...);
   2033 ///         nk_widget(...);
   2034 ///         //
   2035 ///         // second row with same parameter as defined above
   2036 ///         nk_widget(...);
   2037 ///         nk_widget(...);
   2038 ///         //
   2039 ///         // third row uses 0 for height which will use auto layouting
   2040 ///         nk_layout_row_static(&ctx, 0, 80, 2);
   2041 ///         nk_widget(...);
   2042 ///         nk_widget(...);
   2043 ///     }
   2044 ///     nk_end(...);
   2045 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2046 ///
   2047 /// 3.  __nk_layout_row_xxx__<br /><br />
   2048 ///     A little bit more advanced layouting API are functions `nk_layout_row_begin`,
   2049 ///     `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
   2050 ///     specify each column pixel or window ratio in a row. It supports either
   2051 ///     directly setting per column pixel width or widget window ratio but not
   2052 ///     both. Furthermore it is a immediate mode API so each value is directly
   2053 ///     pushed before calling a widget. Therefore the layout is not automatically
   2054 ///     repeating like the last two layouting functions.
   2055 ///
   2056 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2057 ///     if (nk_begin_xxx(...) {
   2058 ///         // first row with height: 25 composed of two widgets with width 60 and 40
   2059 ///         nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
   2060 ///         nk_layout_row_push(ctx, 60);
   2061 ///         nk_widget(...);
   2062 ///         nk_layout_row_push(ctx, 40);
   2063 ///         nk_widget(...);
   2064 ///         nk_layout_row_end(ctx);
   2065 ///         //
   2066 ///         // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
   2067 ///         nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
   2068 ///         nk_layout_row_push(ctx, 0.25f);
   2069 ///         nk_widget(...);
   2070 ///         nk_layout_row_push(ctx, 0.75f);
   2071 ///         nk_widget(...);
   2072 ///         nk_layout_row_end(ctx);
   2073 ///         //
   2074 ///         // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75
   2075 ///         nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
   2076 ///         nk_layout_row_push(ctx, 0.25f);
   2077 ///         nk_widget(...);
   2078 ///         nk_layout_row_push(ctx, 0.75f);
   2079 ///         nk_widget(...);
   2080 ///         nk_layout_row_end(ctx);
   2081 ///     }
   2082 ///     nk_end(...);
   2083 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2084 ///
   2085 /// 4.  __nk_layout_row__<br /><br />
   2086 ///     The array counterpart to API nk_layout_row_xxx is the single nk_layout_row
   2087 ///     functions. Instead of pushing either pixel or window ratio for every widget
   2088 ///     it allows to define it by array. The trade of for less control is that
   2089 ///     `nk_layout_row` is automatically repeating. Otherwise the behavior is the
   2090 ///     same.
   2091 ///
   2092 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2093 ///     if (nk_begin_xxx(...) {
   2094 ///         // two rows with height: 30 composed of two widgets with width 60 and 40
   2095 ///         const float size[] = {60,40};
   2096 ///         nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
   2097 ///         nk_widget(...);
   2098 ///         nk_widget(...);
   2099 ///         nk_widget(...);
   2100 ///         nk_widget(...);
   2101 ///         //
   2102 ///         // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
   2103 ///         const float ratio[] = {0.25, 0.75};
   2104 ///         nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
   2105 ///         nk_widget(...);
   2106 ///         nk_widget(...);
   2107 ///         nk_widget(...);
   2108 ///         nk_widget(...);
   2109 ///         //
   2110 ///         // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75
   2111 ///         const float ratio[] = {0.25, 0.75};
   2112 ///         nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
   2113 ///         nk_widget(...);
   2114 ///         nk_widget(...);
   2115 ///         nk_widget(...);
   2116 ///         nk_widget(...);
   2117 ///     }
   2118 ///     nk_end(...);
   2119 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2120 ///
   2121 /// 5.  __nk_layout_row_template_xxx__<br /><br />
   2122 ///     The most complex and second most flexible API is a simplified flexbox version without
   2123 ///     line wrapping and weights for dynamic widgets. It is an immediate mode API but
   2124 ///     unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
   2125 ///     before calling the templated widgets.
   2126 ///     The row template layout has three different per widget size specifier. The first
   2127 ///     one is the `nk_layout_row_template_push_static`  with fixed widget pixel width.
   2128 ///     They do not grow if the row grows and will always stay the same.
   2129 ///     The second size specifier is `nk_layout_row_template_push_variable`
   2130 ///     which defines a minimum widget size but it also can grow if more space is available
   2131 ///     not taken by other widgets.
   2132 ///     Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic`
   2133 ///     which are completely flexible and unlike variable widgets can even shrink
   2134 ///     to zero if not enough space is provided.
   2135 ///
   2136 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2137 ///     if (nk_begin_xxx(...) {
   2138 ///         // two rows with height: 30 composed of three widgets
   2139 ///         nk_layout_row_template_begin(ctx, 30);
   2140 ///         nk_layout_row_template_push_dynamic(ctx);
   2141 ///         nk_layout_row_template_push_variable(ctx, 80);
   2142 ///         nk_layout_row_template_push_static(ctx, 80);
   2143 ///         nk_layout_row_template_end(ctx);
   2144 ///         //
   2145 ///         // first row
   2146 ///         nk_widget(...); // dynamic widget can go to zero if not enough space
   2147 ///         nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
   2148 ///         nk_widget(...); // static widget with fixed 80 pixel width
   2149 ///         //
   2150 ///         // second row same layout
   2151 ///         nk_widget(...);
   2152 ///         nk_widget(...);
   2153 ///         nk_widget(...);
   2154 ///     }
   2155 ///     nk_end(...);
   2156 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2157 ///
   2158 /// 6.  __nk_layout_space_xxx__<br /><br />
   2159 ///     Finally the most flexible API directly allows you to place widgets inside the
   2160 ///     window. The space layout API is an immediate mode API which does not support
   2161 ///     row auto repeat and directly sets position and size of a widget. Position
   2162 ///     and size hereby can be either specified as ratio of allocated space or
   2163 ///     allocated space local position and pixel size. Since this API is quite
   2164 ///     powerful there are a number of utility functions to get the available space
   2165 ///     and convert between local allocated space and screen space.
   2166 ///
   2167 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2168 ///     if (nk_begin_xxx(...) {
   2169 ///         // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
   2170 ///         nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
   2171 ///         nk_layout_space_push(ctx, nk_rect(0,0,150,200));
   2172 ///         nk_widget(...);
   2173 ///         nk_layout_space_push(ctx, nk_rect(200,200,100,200));
   2174 ///         nk_widget(...);
   2175 ///         nk_layout_space_end(ctx);
   2176 ///         //
   2177 ///         // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
   2178 ///         nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
   2179 ///         nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
   2180 ///         nk_widget(...);
   2181 ///         nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
   2182 ///         nk_widget(...);
   2183 ///     }
   2184 ///     nk_end(...);
   2185 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2186 ///
   2187 /// #### Reference
   2188 /// Function                                | Description
   2189 /// ----------------------------------------|------------------------------------
   2190 /// nk_layout_set_min_row_height            | Set the currently used minimum row height to a specified value
   2191 /// nk_layout_reset_min_row_height          | Resets the currently used minimum row height to font height
   2192 /// nk_layout_widget_bounds                 | Calculates current width a static layout row can fit inside a window
   2193 /// nk_layout_ratio_from_pixel              | Utility functions to calculate window ratio from pixel size
   2194 //
   2195 /// nk_layout_row_dynamic                   | Current layout is divided into n same sized growing columns
   2196 /// nk_layout_row_static                    | Current layout is divided into n same fixed sized columns
   2197 /// nk_layout_row_begin                     | Starts a new row with given height and number of columns
   2198 /// nk_layout_row_push                      | Pushes another column with given size or window ratio
   2199 /// nk_layout_row_end                       | Finished previously started row
   2200 /// nk_layout_row                           | Specifies row columns in array as either window ratio or size
   2201 //
   2202 /// nk_layout_row_template_begin            | Begins the row template declaration
   2203 /// nk_layout_row_template_push_dynamic     | Adds a dynamic column that dynamically grows and can go to zero if not enough space
   2204 /// nk_layout_row_template_push_variable    | Adds a variable column that dynamically grows but does not shrink below specified pixel width
   2205 /// nk_layout_row_template_push_static      | Adds a static column that does not grow and will always have the same size
   2206 /// nk_layout_row_template_end              | Marks the end of the row template
   2207 //
   2208 /// nk_layout_space_begin                   | Begins a new layouting space that allows to specify each widgets position and size
   2209 /// nk_layout_space_push                    | Pushes position and size of the next widget in own coordinate space either as pixel or ratio
   2210 /// nk_layout_space_end                     | Marks the end of the layouting space
   2211 //
   2212 /// nk_layout_space_bounds                  | Callable after nk_layout_space_begin and returns total space allocated
   2213 /// nk_layout_space_to_screen               | Converts vector from nk_layout_space coordinate space into screen space
   2214 /// nk_layout_space_to_local                | Converts vector from screen space into nk_layout_space coordinates
   2215 /// nk_layout_space_rect_to_screen          | Converts rectangle from nk_layout_space coordinate space into screen space
   2216 /// nk_layout_space_rect_to_local           | Converts rectangle from screen space into nk_layout_space coordinates
   2217 */
   2218 /*/// #### nk_layout_set_min_row_height
   2219 /// Sets the currently used minimum row height.
   2220 /// !!! WARNING
   2221 ///     The passed height needs to include both your preferred row height
   2222 ///     as well as padding. No internal padding is added.
   2223 ///
   2224 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2225 /// void nk_layout_set_min_row_height(struct nk_context*, float height);
   2226 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2227 ///
   2228 /// Parameter   | Description
   2229 /// ------------|-----------------------------------------------------------
   2230 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2231 /// __height__  | New minimum row height to be used for auto generating the row height
   2232 */
   2233 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height);
   2234 /*/// #### nk_layout_reset_min_row_height
   2235 /// Reset the currently used minimum row height back to `font_height + text_padding + padding`
   2236 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2237 /// void nk_layout_reset_min_row_height(struct nk_context*);
   2238 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2239 ///
   2240 /// Parameter   | Description
   2241 /// ------------|-----------------------------------------------------------
   2242 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2243 */
   2244 NK_API void nk_layout_reset_min_row_height(struct nk_context*);
   2245 /*/// #### nk_layout_widget_bounds
   2246 /// Returns the width of the next row allocate by one of the layouting functions
   2247 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2248 /// struct nk_rect nk_layout_widget_bounds(struct nk_context*);
   2249 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2250 ///
   2251 /// Parameter   | Description
   2252 /// ------------|-----------------------------------------------------------
   2253 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2254 ///
   2255 /// Return `nk_rect` with both position and size of the next row
   2256 */
   2257 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*);
   2258 /*/// #### nk_layout_ratio_from_pixel
   2259 /// Utility functions to calculate window ratio from pixel size
   2260 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2261 /// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
   2262 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2263 ///
   2264 /// Parameter   | Description
   2265 /// ------------|-----------------------------------------------------------
   2266 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2267 /// __pixel__   | Pixel_width to convert to window ratio
   2268 ///
   2269 /// Returns `nk_rect` with both position and size of the next row
   2270 */
   2271 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
   2272 /*/// #### nk_layout_row_dynamic
   2273 /// Sets current row layout to share horizontal space
   2274 /// between @cols number of widgets evenly. Once called all subsequent widget
   2275 /// calls greater than @cols will allocate a new row with same layout.
   2276 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2277 /// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
   2278 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2279 ///
   2280 /// Parameter   | Description
   2281 /// ------------|-----------------------------------------------------------
   2282 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2283 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2284 /// __columns__ | Number of widget inside row
   2285 */
   2286 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
   2287 /*/// #### nk_layout_row_static
   2288 /// Sets current row layout to fill @cols number of widgets
   2289 /// in row with same @item_width horizontal size. Once called all subsequent widget
   2290 /// calls greater than @cols will allocate a new row with same layout.
   2291 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2292 /// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
   2293 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2294 ///
   2295 /// Parameter   | Description
   2296 /// ------------|-----------------------------------------------------------
   2297 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2298 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2299 /// __width__   | Holds pixel width of each widget in the row
   2300 /// __columns__ | Number of widget inside row
   2301 */
   2302 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
   2303 /*/// #### nk_layout_row_begin
   2304 /// Starts a new dynamic or fixed row with given height and columns.
   2305 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2306 /// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
   2307 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2308 ///
   2309 /// Parameter   | Description
   2310 /// ------------|-----------------------------------------------------------
   2311 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2312 /// __fmt__     | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
   2313 /// __height__  | holds height of each widget in row or zero for auto layouting
   2314 /// __columns__ | Number of widget inside row
   2315 */
   2316 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
   2317 /*/// #### nk_layout_row_push
   2318 /// Specifies either window ratio or width of a single column
   2319 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2320 /// void nk_layout_row_push(struct nk_context*, float value);
   2321 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2322 ///
   2323 /// Parameter   | Description
   2324 /// ------------|-----------------------------------------------------------
   2325 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2326 /// __value__   | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call
   2327 */
   2328 NK_API void nk_layout_row_push(struct nk_context*, float value);
   2329 /*/// #### nk_layout_row_end
   2330 /// Finished previously started row
   2331 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2332 /// void nk_layout_row_end(struct nk_context*);
   2333 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2334 ///
   2335 /// Parameter   | Description
   2336 /// ------------|-----------------------------------------------------------
   2337 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2338 */
   2339 NK_API void nk_layout_row_end(struct nk_context*);
   2340 /*/// #### nk_layout_row
   2341 /// Specifies row columns in array as either window ratio or size
   2342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2343 /// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
   2344 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2345 ///
   2346 /// Parameter   | Description
   2347 /// ------------|-----------------------------------------------------------
   2348 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2349 /// __fmt__     | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
   2350 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2351 /// __columns__ | Number of widget inside row
   2352 */
   2353 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
   2354 /*/// #### nk_layout_row_template_begin
   2355 /// Begins the row template declaration
   2356 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2357 /// void nk_layout_row_template_begin(struct nk_context*, float row_height);
   2358 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2359 ///
   2360 /// Parameter   | Description
   2361 /// ------------|-----------------------------------------------------------
   2362 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2363 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2364 */
   2365 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
   2366 /*/// #### nk_layout_row_template_push_dynamic
   2367 /// Adds a dynamic column that dynamically grows and can go to zero if not enough space
   2368 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2369 /// void nk_layout_row_template_push_dynamic(struct nk_context*);
   2370 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2371 ///
   2372 /// Parameter   | Description
   2373 /// ------------|-----------------------------------------------------------
   2374 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2375 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2376 */
   2377 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*);
   2378 /*/// #### nk_layout_row_template_push_variable
   2379 /// Adds a variable column that dynamically grows but does not shrink below specified pixel width
   2380 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2381 /// void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
   2382 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2383 ///
   2384 /// Parameter   | Description
   2385 /// ------------|-----------------------------------------------------------
   2386 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2387 /// __width__   | Holds the minimum pixel width the next column must always be
   2388 */
   2389 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
   2390 /*/// #### nk_layout_row_template_push_static
   2391 /// Adds a static column that does not grow and will always have the same size
   2392 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2393 /// void nk_layout_row_template_push_static(struct nk_context*, float width);
   2394 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2395 ///
   2396 /// Parameter   | Description
   2397 /// ------------|-----------------------------------------------------------
   2398 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2399 /// __width__   | Holds the absolute pixel width value the next column must be
   2400 */
   2401 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
   2402 /*/// #### nk_layout_row_template_end
   2403 /// Marks the end of the row template
   2404 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2405 /// void nk_layout_row_template_end(struct nk_context*);
   2406 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2407 ///
   2408 /// Parameter   | Description
   2409 /// ------------|-----------------------------------------------------------
   2410 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2411 */
   2412 NK_API void nk_layout_row_template_end(struct nk_context*);
   2413 /*/// #### nk_layout_space_begin
   2414 /// Begins a new layouting space that allows to specify each widgets position and size.
   2415 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2416 /// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
   2417 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2418 ///
   2419 /// Parameter   | Description
   2420 /// ------------|-----------------------------------------------------------
   2421 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
   2422 /// __fmt__     | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
   2423 /// __height__  | Holds height of each widget in row or zero for auto layouting
   2424 /// __columns__ | Number of widgets inside row
   2425 */
   2426 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
   2427 /*/// #### nk_layout_space_push
   2428 /// Pushes position and size of the next widget in own coordinate space either as pixel or ratio
   2429 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2430 /// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds);
   2431 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2432 ///
   2433 /// Parameter   | Description
   2434 /// ------------|-----------------------------------------------------------
   2435 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2436 /// __bounds__  | Position and size in laoyut space local coordinates
   2437 */
   2438 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds);
   2439 /*/// #### nk_layout_space_end
   2440 /// Marks the end of the layout space
   2441 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2442 /// void nk_layout_space_end(struct nk_context*);
   2443 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2444 ///
   2445 /// Parameter   | Description
   2446 /// ------------|-----------------------------------------------------------
   2447 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2448 */
   2449 NK_API void nk_layout_space_end(struct nk_context*);
   2450 /*/// #### nk_layout_space_bounds
   2451 /// Utility function to calculate total space allocated for `nk_layout_space`
   2452 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2453 /// struct nk_rect nk_layout_space_bounds(struct nk_context*);
   2454 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2455 ///
   2456 /// Parameter   | Description
   2457 /// ------------|-----------------------------------------------------------
   2458 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2459 ///
   2460 /// Returns `nk_rect` holding the total space allocated
   2461 */
   2462 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*);
   2463 /*/// #### nk_layout_space_to_screen
   2464 /// Converts vector from nk_layout_space coordinate space into screen space
   2465 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2466 /// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
   2467 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2468 ///
   2469 /// Parameter   | Description
   2470 /// ------------|-----------------------------------------------------------
   2471 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2472 /// __vec__     | Position to convert from layout space into screen coordinate space
   2473 ///
   2474 /// Returns transformed `nk_vec2` in screen space coordinates
   2475 */
   2476 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
   2477 /*/// #### nk_layout_space_to_local
   2478 /// Converts vector from layout space into screen space
   2479 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2480 /// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
   2481 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2482 ///
   2483 /// Parameter   | Description
   2484 /// ------------|-----------------------------------------------------------
   2485 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2486 /// __vec__     | Position to convert from screen space into layout coordinate space
   2487 ///
   2488 /// Returns transformed `nk_vec2` in layout space coordinates
   2489 */
   2490 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
   2491 /*/// #### nk_layout_space_rect_to_screen
   2492 /// Converts rectangle from screen space into layout space
   2493 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2494 /// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
   2495 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2496 ///
   2497 /// Parameter   | Description
   2498 /// ------------|-----------------------------------------------------------
   2499 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2500 /// __bounds__  | Rectangle to convert from layout space into screen space
   2501 ///
   2502 /// Returns transformed `nk_rect` in screen space coordinates
   2503 */
   2504 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
   2505 /*/// #### nk_layout_space_rect_to_local
   2506 /// Converts rectangle from layout space into screen space
   2507 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2508 /// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
   2509 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2510 ///
   2511 /// Parameter   | Description
   2512 /// ------------|-----------------------------------------------------------
   2513 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
   2514 /// __bounds__  | Rectangle to convert from layout space into screen space
   2515 ///
   2516 /// Returns transformed `nk_rect` in layout space coordinates
   2517 */
   2518 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
   2519 /* =============================================================================
   2520  *
   2521  *                                  GROUP
   2522  *
   2523  * =============================================================================
   2524 /// ### Groups
   2525 /// Groups are basically windows inside windows. They allow to subdivide space
   2526 /// in a window to layout widgets as a group. Almost all more complex widget
   2527 /// layouting requirements can be solved using groups and basic layouting
   2528 /// fuctionality. Groups just like windows are identified by an unique name and
   2529 /// internally keep track of scrollbar offsets by default. However additional
   2530 /// versions are provided to directly manage the scrollbar.
   2531 ///
   2532 /// #### Usage
   2533 /// To create a group you have to call one of the three `nk_group_begin_xxx`
   2534 /// functions to start group declarations and `nk_group_end` at the end. Furthermore it
   2535 /// is required to check the return value of `nk_group_begin_xxx` and only process
   2536 /// widgets inside the window if the value is not 0.
   2537 /// Nesting groups is possible and even encouraged since many layouting schemes
   2538 /// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end`
   2539 /// to be only called if the corosponding `nk_group_begin_xxx` call does not return 0:
   2540 ///
   2541 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2542 /// if (nk_group_begin_xxx(ctx, ...) {
   2543 ///     // [... widgets ...]
   2544 ///     nk_group_end(ctx);
   2545 /// }
   2546 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2547 ///
   2548 /// In the grand concept groups can be called after starting a window
   2549 /// with `nk_begin_xxx` and before calling `nk_end`:
   2550 ///
   2551 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2552 /// struct nk_context ctx;
   2553 /// nk_init_xxx(&ctx, ...);
   2554 /// while (1) {
   2555 ///     // Input
   2556 ///     Event evt;
   2557 ///     nk_input_begin(&ctx);
   2558 ///     while (GetEvent(&evt)) {
   2559 ///         if (evt.type == MOUSE_MOVE)
   2560 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
   2561 ///         else if (evt.type == [...]) {
   2562 ///             nk_input_xxx(...);
   2563 ///         }
   2564 ///     }
   2565 ///     nk_input_end(&ctx);
   2566 ///     //
   2567 ///     // Window
   2568 ///     if (nk_begin_xxx(...) {
   2569 ///         // [...widgets...]
   2570 ///         nk_layout_row_dynamic(...);
   2571 ///         if (nk_group_begin_xxx(ctx, ...) {
   2572 ///             //[... widgets ...]
   2573 ///             nk_group_end(ctx);
   2574 ///         }
   2575 ///     }
   2576 ///     nk_end(ctx);
   2577 ///     //
   2578 ///     // Draw
   2579 ///     const struct nk_command *cmd = 0;
   2580 ///     nk_foreach(cmd, &ctx) {
   2581 ///     switch (cmd->type) {
   2582 ///     case NK_COMMAND_LINE:
   2583 ///         your_draw_line_function(...)
   2584 ///         break;
   2585 ///     case NK_COMMAND_RECT
   2586 ///         your_draw_rect_function(...)
   2587 ///         break;
   2588 ///     case ...:
   2589 ///         // [...]
   2590 ///     }
   2591 //      nk_clear(&ctx);
   2592 /// }
   2593 /// nk_free(&ctx);
   2594 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2595 /// #### Reference
   2596 /// Function                        | Description
   2597 /// --------------------------------|-------------------------------------------
   2598 /// nk_group_begin                  | Start a new group with internal scrollbar handling
   2599 /// nk_group_begin_titled           | Start a new group with separeted name and title and internal scrollbar handling
   2600 /// nk_group_end                    | Ends a group. Should only be called if nk_group_begin returned non-zero
   2601 /// nk_group_scrolled_offset_begin  | Start a new group with manual separated handling of scrollbar x- and y-offset
   2602 /// nk_group_scrolled_begin         | Start a new group with manual scrollbar handling
   2603 /// nk_group_scrolled_end           | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero
   2604 */
   2605 /*/// #### nk_group_begin
   2606 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
   2607 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2608 /// int nk_group_begin(struct nk_context*, const char *title, nk_flags);
   2609 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2610 ///
   2611 /// Parameter   | Description
   2612 /// ------------|-----------------------------------------------------------
   2613 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2614 /// __title__   | Must be an unique identifier for this group that is also used for the group header
   2615 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different group behaviors
   2616 ///
   2617 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2618 */
   2619 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
   2620 /*/// #### nk_group_begin_titled
   2621 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
   2622 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2623 /// int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
   2624 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2625 ///
   2626 /// Parameter   | Description
   2627 /// ------------|-----------------------------------------------------------
   2628 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2629 /// __id__      | Must be an unique identifier for this group
   2630 /// __title__   | Group header title
   2631 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different group behaviors
   2632 ///
   2633 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2634 */
   2635 NK_API int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
   2636 /*/// #### nk_group_end
   2637 /// Ends a widget group
   2638 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2639 /// void nk_group_end(struct nk_context*);
   2640 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2641 ///
   2642 /// Parameter   | Description
   2643 /// ------------|-----------------------------------------------------------
   2644 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2645 */
   2646 NK_API void nk_group_end(struct nk_context*);
   2647 /*/// #### nk_group_scrolled_offset_begin
   2648 /// starts a new widget group. requires a previous layouting function to specify
   2649 /// a size. Does not keep track of scrollbar.
   2650 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2651 /// int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
   2652 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2653 ///
   2654 /// Parameter   | Description
   2655 /// ------------|-----------------------------------------------------------
   2656 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2657 /// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally.
   2658 /// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically
   2659 /// __title__   | Window unique group title used to both identify and display in the group header
   2660 /// __flags__   | Window flags from the nk_panel_flags section
   2661 ///
   2662 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2663 */
   2664 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
   2665 /*/// #### nk_group_scrolled_begin
   2666 /// Starts a new widget group. requires a previous
   2667 /// layouting function to specify a size. Does not keep track of scrollbar.
   2668 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2669 /// int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
   2670 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2671 ///
   2672 /// Parameter   | Description
   2673 /// ------------|-----------------------------------------------------------
   2674 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2675 /// __off__     | Both x- and y- scroll offset. Allows for manual scrollbar control
   2676 /// __title__   | Window unique group title used to both identify and display in the group header
   2677 /// __flags__   | Window flags from nk_panel_flags section
   2678 ///
   2679 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2680 */
   2681 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
   2682 /*/// #### nk_group_scrolled_end
   2683 /// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin.
   2684 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2685 /// void nk_group_scrolled_end(struct nk_context*);
   2686 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2687 ///
   2688 /// Parameter   | Description
   2689 /// ------------|-----------------------------------------------------------
   2690 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2691 */
   2692 NK_API void nk_group_scrolled_end(struct nk_context*);
   2693 /* =============================================================================
   2694  *
   2695  *                                  TREE
   2696  *
   2697  * ============================================================================= 
   2698 /// ### Tree
   2699 /// Trees represent two different concept. First the concept of a collapsable
   2700 /// UI section that can be either in a hidden or visibile state. They allow the UI
   2701 /// user to selectively minimize the current set of visible UI to comprehend.
   2702 /// The second concept are tree widgets for visual UI representation of trees.<br /><br />
   2703 ///
   2704 /// Trees thereby can be nested for tree representations and multiple nested
   2705 /// collapsable UI sections. All trees are started by calling of the
   2706 /// `nk_tree_xxx_push_tree` functions and ended by calling one of the
   2707 /// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label
   2708 /// and optionally an image to be displayed and the initial collapse state from
   2709 /// the nk_collapse_states section.<br /><br />
   2710 ///
   2711 /// The runtime state of the tree is either stored outside the library by the caller
   2712 /// or inside which requires a unique ID. The unique ID can either be generated
   2713 /// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`,
   2714 /// by `__FILE__` and a user provided ID generated for example by loop index with
   2715 /// function `nk_tree_push_id` or completely provided from outside by user with
   2716 /// function `nk_tree_push_hashed`.
   2717 ///
   2718 /// #### Usage
   2719 /// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx`
   2720 /// functions to start a collapsable UI section and `nk_tree_xxx_pop` to mark the
   2721 /// end.
   2722 /// Each starting function will either return `false(0)` if the tree is collapsed
   2723 /// or hidden and therefore does not need to be filled with content or `true(1)`
   2724 /// if visible and required to be filled.
   2725 ///
   2726 /// !!! Note
   2727 ///     The tree header does not require and layouting function and instead
   2728 ///     calculates a auto height based on the currently used font size
   2729 ///
   2730 /// The tree ending functions only need to be called if the tree content is
   2731 /// actually visible. So make sure the tree push function is guarded by `if`
   2732 /// and the pop call is only taken if the tree is visible.
   2733 ///
   2734 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2735 /// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) {
   2736 ///     nk_layout_row_dynamic(...);
   2737 ///     nk_widget(...);
   2738 ///     nk_tree_pop(ctx);
   2739 /// }
   2740 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2741 ///
   2742 /// #### Reference
   2743 /// Function                    | Description
   2744 /// ----------------------------|-------------------------------------------
   2745 /// nk_tree_push                | Start a collapsable UI section with internal state management
   2746 /// nk_tree_push_id             | Start a collapsable UI section with internal state management callable in a look
   2747 /// nk_tree_push_hashed         | Start a collapsable UI section with internal state management with full control over internal unique ID use to store state
   2748 /// nk_tree_image_push          | Start a collapsable UI section with image and label header
   2749 /// nk_tree_image_push_id       | Start a collapsable UI section with image and label header and internal state management callable in a look
   2750 /// nk_tree_image_push_hashed   | Start a collapsable UI section with image and label header and internal state management with full control over internal unique ID use to store state
   2751 /// nk_tree_pop                 | Ends a collapsable UI section
   2752 //
   2753 /// nk_tree_state_push          | Start a collapsable UI section with external state management
   2754 /// nk_tree_state_image_push    | Start a collapsable UI section with image and label header and external state management
   2755 /// nk_tree_state_pop           | Ends a collapsabale UI section
   2756 ///
   2757 /// #### nk_tree_type
   2758 /// Flag            | Description
   2759 /// ----------------|----------------------------------------
   2760 /// NK_TREE_NODE    | Highlighted tree header to mark a collapsable UI section
   2761 /// NK_TREE_TAB     | Non-highighted tree header closer to tree representations
   2762 */
   2763 /*/// #### nk_tree_push
   2764 /// Starts a collapsable UI section with internal state management
   2765 /// !!! WARNING
   2766 ///     To keep track of the runtime tree collapsable state this function uses
   2767 ///     defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
   2768 ///     to call this function in a loop please use `nk_tree_push_id` or
   2769 ///     `nk_tree_push_hashed` instead.
   2770 ///
   2771 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2772 /// #define nk_tree_push(ctx, type, title, state)
   2773 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2774 ///
   2775 /// Parameter   | Description
   2776 /// ------------|-----------------------------------------------------------
   2777 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2778 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2779 /// __title__   | Label printed in the tree header
   2780 /// __state__   | Initial tree state value out of nk_collapse_states
   2781 ///
   2782 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2783 */
   2784 #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__)
   2785 /*/// #### nk_tree_push_id
   2786 /// Starts a collapsable UI section with internal state management callable in a look
   2787 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2788 /// #define nk_tree_push_id(ctx, type, title, state, id)
   2789 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2790 ///
   2791 /// Parameter   | Description
   2792 /// ------------|-----------------------------------------------------------
   2793 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2794 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2795 /// __title__   | Label printed in the tree header
   2796 /// __state__   | Initial tree state value out of nk_collapse_states
   2797 /// __id__      | Loop counter index if this function is called in a loop
   2798 ///
   2799 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2800 */
   2801 #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)
   2802 /*/// #### nk_tree_push_hashed
   2803 /// Start a collapsable UI section with internal state management with full
   2804 /// control over internal unique ID used to store state
   2805 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2806 /// int 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);
   2807 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2808 ///
   2809 /// Parameter   | Description
   2810 /// ------------|-----------------------------------------------------------
   2811 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2812 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2813 /// __title__   | Label printed in the tree header
   2814 /// __state__   | Initial tree state value out of nk_collapse_states
   2815 /// __hash__    | Memory block or string to generate the ID from
   2816 /// __len__     | Size of passed memory block or string in __hash__
   2817 /// __seed__    | Seeding value if this function is called in a loop or default to `0`
   2818 ///
   2819 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2820 */
   2821 NK_API int 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);
   2822 /*/// #### nk_tree_image_push
   2823 /// Start a collapsable UI section with image and label header
   2824 /// !!! WARNING
   2825 ///     To keep track of the runtime tree collapsable state this function uses
   2826 ///     defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
   2827 ///     to call this function in a loop please use `nk_tree_image_push_id` or
   2828 ///     `nk_tree_image_push_hashed` instead.
   2829 ///
   2830 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2831 /// #define nk_tree_image_push(ctx, type, img, title, state)
   2832 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2833 //
   2834 /// Parameter   | Description
   2835 /// ------------|-----------------------------------------------------------
   2836 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2837 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2838 /// __img__     | Image to display inside the header on the left of the label
   2839 /// __title__   | Label printed in the tree header
   2840 /// __state__   | Initial tree state value out of nk_collapse_states
   2841 ///
   2842 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2843 */
   2844 #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__)
   2845 /*/// #### nk_tree_image_push_id
   2846 /// Start a collapsable UI section with image and label header and internal state
   2847 /// management callable in a look
   2848 ///
   2849 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2850 /// #define nk_tree_image_push_id(ctx, type, img, title, state, id)
   2851 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2852 ///
   2853 /// Parameter   | Description
   2854 /// ------------|-----------------------------------------------------------
   2855 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2856 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2857 /// __img__     | Image to display inside the header on the left of the label
   2858 /// __title__   | Label printed in the tree header
   2859 /// __state__   | Initial tree state value out of nk_collapse_states
   2860 /// __id__      | Loop counter index if this function is called in a loop
   2861 ///
   2862 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2863 */
   2864 #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)
   2865 /*/// #### nk_tree_image_push_hashed
   2866 /// Start a collapsable UI section with internal state management with full
   2867 /// control over internal unique ID used to store state
   2868 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2869 /// int 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);
   2870 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2871 ///
   2872 /// Parameter   | Description
   2873 /// ------------|-----------------------------------------------------------
   2874 /// __ctx__     | Must point to an previously initialized `nk_context` struct
   2875 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2876 /// __img__     | Image to display inside the header on the left of the label
   2877 /// __title__   | Label printed in the tree header
   2878 /// __state__   | Initial tree state value out of nk_collapse_states
   2879 /// __hash__    | Memory block or string to generate the ID from
   2880 /// __len__     | Size of passed memory block or string in __hash__
   2881 /// __seed__    | Seeding value if this function is called in a loop or default to `0`
   2882 ///
   2883 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2884 */
   2885 NK_API int 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);
   2886 /*/// #### nk_tree_pop
   2887 /// Ends a collapsabale UI section
   2888 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2889 /// void nk_tree_pop(struct nk_context*);
   2890 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2891 ///
   2892 /// Parameter   | Description
   2893 /// ------------|-----------------------------------------------------------
   2894 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
   2895 */
   2896 NK_API void nk_tree_pop(struct nk_context*);
   2897 /*/// #### nk_tree_state_push
   2898 /// Start a collapsable UI section with external state management
   2899 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2900 /// int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
   2901 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2902 ///
   2903 /// Parameter   | Description
   2904 /// ------------|-----------------------------------------------------------
   2905 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
   2906 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2907 /// __title__   | Label printed in the tree header
   2908 /// __state__   | Persistent state to update
   2909 ///
   2910 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2911 */
   2912 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
   2913 /*/// #### nk_tree_state_image_push
   2914 /// Start a collapsable UI section with image and label header and external state management
   2915 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2916 /// int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
   2917 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2918 ///
   2919 /// Parameter   | Description
   2920 /// ------------|-----------------------------------------------------------
   2921 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
   2922 /// __img__     | Image to display inside the header on the left of the label
   2923 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
   2924 /// __title__   | Label printed in the tree header
   2925 /// __state__   | Persistent state to update
   2926 ///
   2927 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
   2928 */
   2929 NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
   2930 /*/// #### nk_tree_state_pop
   2931 /// Ends a collapsabale UI section
   2932 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   2933 /// void nk_tree_state_pop(struct nk_context*);
   2934 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2935 ///
   2936 /// Parameter   | Description
   2937 /// ------------|-----------------------------------------------------------
   2938 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
   2939 */
   2940 NK_API void nk_tree_state_pop(struct nk_context*);
   2941 
   2942 #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__)
   2943 #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)
   2944 NK_API int nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed);
   2945 NK_API int 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, int *selected, const char *hash, int len,int seed);
   2946 NK_API void nk_tree_element_pop(struct nk_context*);
   2947 
   2948 /* =============================================================================
   2949  *
   2950  *                                  LIST VIEW
   2951  *
   2952  * ============================================================================= */
   2953 struct nk_list_view {
   2954 /* public: */
   2955     int begin, end, count;
   2956 /* private: */
   2957     int total_height;
   2958     struct nk_context *ctx;
   2959     nk_uint *scroll_pointer;
   2960     nk_uint scroll_value;
   2961 };
   2962 NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
   2963 NK_API void nk_list_view_end(struct nk_list_view*);
   2964 /* =============================================================================
   2965  *
   2966  *                                  WIDGET
   2967  *
   2968  * ============================================================================= */
   2969 enum nk_widget_layout_states {
   2970     NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
   2971     NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
   2972     NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
   2973 };
   2974 enum nk_widget_states {
   2975     NK_WIDGET_STATE_MODIFIED    = NK_FLAG(1),
   2976     NK_WIDGET_STATE_INACTIVE    = NK_FLAG(2), /* widget is neither active nor hovered */
   2977     NK_WIDGET_STATE_ENTERED     = NK_FLAG(3), /* widget has been hovered on the current frame */
   2978     NK_WIDGET_STATE_HOVER       = NK_FLAG(4), /* widget is being hovered */
   2979     NK_WIDGET_STATE_ACTIVED     = NK_FLAG(5),/* widget is currently activated */
   2980     NK_WIDGET_STATE_LEFT        = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
   2981     NK_WIDGET_STATE_HOVERED     = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */
   2982     NK_WIDGET_STATE_ACTIVE      = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */
   2983 };
   2984 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
   2985 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2);
   2986 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
   2987 NK_API struct nk_vec2 nk_widget_position(struct nk_context*);
   2988 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
   2989 NK_API float nk_widget_width(struct nk_context*);
   2990 NK_API float nk_widget_height(struct nk_context*);
   2991 NK_API int nk_widget_is_hovered(struct nk_context*);
   2992 NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons);
   2993 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
   2994 NK_API void nk_spacing(struct nk_context*, int cols);
   2995 /* =============================================================================
   2996  *
   2997  *                                  TEXT
   2998  *
   2999  * ============================================================================= */
   3000 enum nk_text_align {
   3001     NK_TEXT_ALIGN_LEFT        = 0x01,
   3002     NK_TEXT_ALIGN_CENTERED    = 0x02,
   3003     NK_TEXT_ALIGN_RIGHT       = 0x04,
   3004     NK_TEXT_ALIGN_TOP         = 0x08,
   3005     NK_TEXT_ALIGN_MIDDLE      = 0x10,
   3006     NK_TEXT_ALIGN_BOTTOM      = 0x20
   3007 };
   3008 enum nk_text_alignment {
   3009     NK_TEXT_LEFT        = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT,
   3010     NK_TEXT_CENTERED    = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED,
   3011     NK_TEXT_RIGHT       = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT
   3012 };
   3013 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
   3014 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
   3015 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
   3016 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
   3017 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
   3018 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
   3019 NK_API void nk_label_wrap(struct nk_context*, const char*);
   3020 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
   3021 NK_API void nk_image(struct nk_context*, struct nk_image);
   3022 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color);
   3023 #ifdef NK_INCLUDE_STANDARD_VARARGS
   3024 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3);
   3025 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);
   3026 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2);
   3027 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3);
   3028 NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
   3029 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);
   3030 NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
   3031 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);
   3032 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
   3033 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
   3034 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
   3035 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
   3036 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
   3037 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
   3038 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
   3039 #endif
   3040 /* =============================================================================
   3041  *
   3042  *                                  BUTTON
   3043  *
   3044  * ============================================================================= */
   3045 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
   3046 NK_API int nk_button_label(struct nk_context*, const char *title);
   3047 NK_API int nk_button_color(struct nk_context*, struct nk_color);
   3048 NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type);
   3049 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
   3050 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
   3051 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3052 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
   3053 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
   3054 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
   3055 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
   3056 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
   3057 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
   3058 NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3059 NK_API int 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);
   3060 NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
   3061 NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
   3062 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior);
   3063 NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior);
   3064 NK_API int nk_button_pop_behavior(struct nk_context*);
   3065 /* =============================================================================
   3066  *
   3067  *                                  CHECKBOX
   3068  *
   3069  * ============================================================================= */
   3070 NK_API int nk_check_label(struct nk_context*, const char*, int active);
   3071 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
   3072 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
   3073 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
   3074 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
   3075 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
   3076 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
   3077 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
   3078 /* =============================================================================
   3079  *
   3080  *                                  RADIO BUTTON
   3081  *
   3082  * ============================================================================= */
   3083 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
   3084 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
   3085 NK_API int nk_option_label(struct nk_context*, const char*, int active);
   3086 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
   3087 /* =============================================================================
   3088  *
   3089  *                                  SELECTABLE
   3090  *
   3091  * ============================================================================= */
   3092 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
   3093 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
   3094 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image,  const char*, nk_flags align, int *value);
   3095 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
   3096 NK_API int nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type,  const char*, nk_flags align, int *value);
   3097 NK_API int nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int *value);
   3098 
   3099 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
   3100 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
   3101 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
   3102 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
   3103 NK_API int nk_select_symbol_label(struct nk_context*,enum nk_symbol_type,  const char*, nk_flags align, int value);
   3104 NK_API int nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int value);
   3105 
   3106 /* =============================================================================
   3107  *
   3108  *                                  SLIDER
   3109  *
   3110  * ============================================================================= */
   3111 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
   3112 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
   3113 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
   3114 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
   3115 /* =============================================================================
   3116  *
   3117  *                                  PROGRESSBAR
   3118  *
   3119  * ============================================================================= */
   3120 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
   3121 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
   3122 
   3123 /* =============================================================================
   3124  *
   3125  *                                  COLOR PICKER
   3126  *
   3127  * ============================================================================= */
   3128 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format);
   3129 NK_API int nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format);
   3130 /* =============================================================================
   3131  *
   3132  *                                  PROPERTIES
   3133  *
   3134  * =============================================================================
   3135 /// ### Properties
   3136 /// Properties are the main value modification widgets in Nuklear. Changing a value
   3137 /// can be achieved by dragging, adding/removing incremental steps on button click
   3138 /// or by directly typing a number.
   3139 ///
   3140 /// #### Usage
   3141 /// Each property requires a unique name for identifaction that is also used for
   3142 /// displaying a label. If you want to use the same name multiple times make sure
   3143 /// add a '#' before your name. The '#' will not be shown but will generate a
   3144 /// unique ID. Each propery also takes in a minimum and maximum value. If you want
   3145 /// to make use of the complete number range of a type just use the provided
   3146 /// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for
   3147 /// `nk_property_int` and `nk_propertyi`. In additional each property takes in
   3148 /// a increment value that will be added or subtracted if either the increment
   3149 /// decrement button is clicked. Finally there is a value for increment per pixel
   3150 /// dragged that is added or subtracted from the value.
   3151 ///
   3152 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3153 /// int value = 0;
   3154 /// struct nk_context ctx;
   3155 /// nk_init_xxx(&ctx, ...);
   3156 /// while (1) {
   3157 ///     // Input
   3158 ///     Event evt;
   3159 ///     nk_input_begin(&ctx);
   3160 ///     while (GetEvent(&evt)) {
   3161 ///         if (evt.type == MOUSE_MOVE)
   3162 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
   3163 ///         else if (evt.type == [...]) {
   3164 ///             nk_input_xxx(...);
   3165 ///         }
   3166 ///     }
   3167 ///     nk_input_end(&ctx);
   3168 ///     //
   3169 ///     // Window
   3170 ///     if (nk_begin_xxx(...) {
   3171 ///         // Property
   3172 ///         nk_layout_row_dynamic(...);
   3173 ///         nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1);
   3174 ///     }
   3175 ///     nk_end(ctx);
   3176 ///     //
   3177 ///     // Draw
   3178 ///     const struct nk_command *cmd = 0;
   3179 ///     nk_foreach(cmd, &ctx) {
   3180 ///     switch (cmd->type) {
   3181 ///     case NK_COMMAND_LINE:
   3182 ///         your_draw_line_function(...)
   3183 ///         break;
   3184 ///     case NK_COMMAND_RECT
   3185 ///         your_draw_rect_function(...)
   3186 ///         break;
   3187 ///     case ...:
   3188 ///         // [...]
   3189 ///     }
   3190 //      nk_clear(&ctx);
   3191 /// }
   3192 /// nk_free(&ctx);
   3193 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3194 ///
   3195 /// #### Reference
   3196 /// Function            | Description
   3197 /// --------------------|-------------------------------------------
   3198 /// nk_property_int     | Integer property directly modifing a passed in value
   3199 /// nk_property_float   | Float property directly modifing a passed in value
   3200 /// nk_property_double  | Double property directly modifing a passed in value
   3201 /// nk_propertyi        | Integer property returning the modified int value
   3202 /// nk_propertyf        | Float property returning the modified float value
   3203 /// nk_propertyd        | Double property returning the modified double value
   3204 ///
   3205 */
   3206 /*/// #### nk_property_int
   3207 /// Integer property directly modifing a passed in value
   3208 /// !!! WARNING
   3209 ///     To generate a unique property ID using the same label make sure to insert
   3210 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3211 ///
   3212 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3213 /// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
   3214 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3215 ///
   3216 /// Parameter           | Description
   3217 /// --------------------|-----------------------------------------------------------
   3218 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3219 /// __name__            | String used both as a label as well as a unique identifier
   3220 /// __min__             | Minimum value not allowed to be underflown
   3221 /// __val__             | Integer pointer to be modified
   3222 /// __max__             | Maximum value not allowed to be overflown
   3223 /// __step__            | Increment added and subtracted on increment and decrement button
   3224 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3225 */
   3226 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
   3227 /*/// #### nk_property_float
   3228 /// Float property directly modifing a passed in value
   3229 /// !!! WARNING
   3230 ///     To generate a unique property ID using the same label make sure to insert
   3231 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3232 ///
   3233 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3234 /// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
   3235 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3236 ///
   3237 /// Parameter           | Description
   3238 /// --------------------|-----------------------------------------------------------
   3239 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3240 /// __name__            | String used both as a label as well as a unique identifier
   3241 /// __min__             | Minimum value not allowed to be underflown
   3242 /// __val__             | Float pointer to be modified
   3243 /// __max__             | Maximum value not allowed to be overflown
   3244 /// __step__            | Increment added and subtracted on increment and decrement button
   3245 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3246 */
   3247 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
   3248 /*/// #### nk_property_double
   3249 /// Double property directly modifing a passed in value
   3250 /// !!! WARNING
   3251 ///     To generate a unique property ID using the same label make sure to insert
   3252 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3253 ///
   3254 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3255 /// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel);
   3256 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3257 ///
   3258 /// Parameter           | Description
   3259 /// --------------------|-----------------------------------------------------------
   3260 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3261 /// __name__            | String used both as a label as well as a unique identifier
   3262 /// __min__             | Minimum value not allowed to be underflown
   3263 /// __val__             | Double pointer to be modified
   3264 /// __max__             | Maximum value not allowed to be overflown
   3265 /// __step__            | Increment added and subtracted on increment and decrement button
   3266 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3267 */
   3268 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
   3269 /*/// #### nk_propertyi
   3270 /// Integer property modifing a passed in value and returning the new value
   3271 /// !!! WARNING
   3272 ///     To generate a unique property ID using the same label make sure to insert
   3273 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3274 ///
   3275 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3276 /// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel);
   3277 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3278 ///
   3279 /// Parameter           | Description
   3280 /// --------------------|-----------------------------------------------------------
   3281 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3282 /// __name__            | String used both as a label as well as a unique identifier
   3283 /// __min__             | Minimum value not allowed to be underflown
   3284 /// __val__             | Current integer value to be modified and returned
   3285 /// __max__             | Maximum value not allowed to be overflown
   3286 /// __step__            | Increment added and subtracted on increment and decrement button
   3287 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3288 ///
   3289 /// Returns the new modified integer value
   3290 */
   3291 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
   3292 /*/// #### nk_propertyf
   3293 /// Float property modifing a passed in value and returning the new value
   3294 /// !!! WARNING
   3295 ///     To generate a unique property ID using the same label make sure to insert
   3296 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3297 ///
   3298 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3299 /// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel);
   3300 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3301 ///
   3302 /// Parameter           | Description
   3303 /// --------------------|-----------------------------------------------------------
   3304 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3305 /// __name__            | String used both as a label as well as a unique identifier
   3306 /// __min__             | Minimum value not allowed to be underflown
   3307 /// __val__             | Current float value to be modified and returned
   3308 /// __max__             | Maximum value not allowed to be overflown
   3309 /// __step__            | Increment added and subtracted on increment and decrement button
   3310 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3311 ///
   3312 /// Returns the new modified float value
   3313 */
   3314 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
   3315 /*/// #### nk_propertyd
   3316 /// Float property modifing a passed in value and returning the new value
   3317 /// !!! WARNING
   3318 ///     To generate a unique property ID using the same label make sure to insert
   3319 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
   3320 ///
   3321 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
   3322 /// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel);
   3323 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3324 ///
   3325 /// Parameter           | Description
   3326 /// --------------------|-----------------------------------------------------------
   3327 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
   3328 /// __name__            | String used both as a label as well as a unique identifier
   3329 /// __min__             | Minimum value not allowed to be underflown
   3330 /// __val__             | Current double value to be modified and returned
   3331 /// __max__             | Maximum value not allowed to be overflown
   3332 /// __step__            | Increment added and subtracted on increment and decrement button
   3333 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
   3334 ///
   3335 /// Returns the new modified double value
   3336 */
   3337 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
   3338 /* =============================================================================
   3339  *
   3340  *                                  TEXT EDIT
   3341  *
   3342  * ============================================================================= */
   3343 enum nk_edit_flags {
   3344     NK_EDIT_DEFAULT                 = 0,
   3345     NK_EDIT_READ_ONLY               = NK_FLAG(0),
   3346     NK_EDIT_AUTO_SELECT             = NK_FLAG(1),
   3347     NK_EDIT_SIG_ENTER               = NK_FLAG(2),
   3348     NK_EDIT_ALLOW_TAB               = NK_FLAG(3),
   3349     NK_EDIT_NO_CURSOR               = NK_FLAG(4),
   3350     NK_EDIT_SELECTABLE              = NK_FLAG(5),
   3351     NK_EDIT_CLIPBOARD               = NK_FLAG(6),
   3352     NK_EDIT_CTRL_ENTER_NEWLINE      = NK_FLAG(7),
   3353     NK_EDIT_NO_HORIZONTAL_SCROLL    = NK_FLAG(8),
   3354     NK_EDIT_ALWAYS_INSERT_MODE      = NK_FLAG(9),
   3355     NK_EDIT_MULTILINE               = NK_FLAG(10),
   3356     NK_EDIT_GOTO_END_ON_ACTIVATE    = NK_FLAG(11)
   3357 };
   3358 enum nk_edit_types {
   3359     NK_EDIT_SIMPLE  = NK_EDIT_ALWAYS_INSERT_MODE,
   3360     NK_EDIT_FIELD   = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD,
   3361     NK_EDIT_BOX     = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD,
   3362     NK_EDIT_EDITOR  = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD
   3363 };
   3364 enum nk_edit_events {
   3365     NK_EDIT_ACTIVE      = NK_FLAG(0), /* edit widget is currently being modified */
   3366     NK_EDIT_INACTIVE    = NK_FLAG(1), /* edit widget is not active and is not being modified */
   3367     NK_EDIT_ACTIVATED   = NK_FLAG(2), /* edit widget went from state inactive to state active */
   3368     NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
   3369     NK_EDIT_COMMITED    = NK_FLAG(4) /* edit widget has received an enter and lost focus */
   3370 };
   3371 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
   3372 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
   3373 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
   3374 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
   3375 NK_API void nk_edit_unfocus(struct nk_context*);
   3376 /* =============================================================================
   3377  *
   3378  *                                  CHART
   3379  *
   3380  * ============================================================================= */
   3381 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
   3382 NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
   3383 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
   3384 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);
   3385 NK_API nk_flags nk_chart_push(struct nk_context*, float);
   3386 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
   3387 NK_API void nk_chart_end(struct nk_context*);
   3388 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
   3389 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);
   3390 /* =============================================================================
   3391  *
   3392  *                                  POPUP
   3393  *
   3394  * ============================================================================= */
   3395 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
   3396 NK_API void nk_popup_close(struct nk_context*);
   3397 NK_API void nk_popup_end(struct nk_context*);
   3398 /* =============================================================================
   3399  *
   3400  *                                  COMBOBOX
   3401  *
   3402  * ============================================================================= */
   3403 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
   3404 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);
   3405 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);
   3406 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);
   3407 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
   3408 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);
   3409 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);
   3410 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);
   3411 /* =============================================================================
   3412  *
   3413  *                                  ABSTRACT COMBOBOX
   3414  *
   3415  * ============================================================================= */
   3416 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
   3417 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
   3418 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
   3419 NK_API int nk_combo_begin_symbol(struct nk_context*,  enum nk_symbol_type,  struct nk_vec2 size);
   3420 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
   3421 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
   3422 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img,  struct nk_vec2 size);
   3423 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
   3424 NK_API int nk_combo_begin_image_text(struct nk_context*,  const char *selected, int, struct nk_image, struct nk_vec2 size);
   3425 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
   3426 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
   3427 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
   3428 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
   3429 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
   3430 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3431 NK_API void nk_combo_close(struct nk_context*);
   3432 NK_API void nk_combo_end(struct nk_context*);
   3433 /* =============================================================================
   3434  *
   3435  *                                  CONTEXTUAL
   3436  *
   3437  * ============================================================================= */
   3438 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
   3439 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
   3440 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
   3441 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
   3442 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
   3443 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
   3444 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3445 NK_API void nk_contextual_close(struct nk_context*);
   3446 NK_API void nk_contextual_end(struct nk_context*);
   3447 /* =============================================================================
   3448  *
   3449  *                                  TOOLTIP
   3450  *
   3451  * ============================================================================= */
   3452 NK_API void nk_tooltip(struct nk_context*, const char*);
   3453 #ifdef NK_INCLUDE_STANDARD_VARARGS
   3454 NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2);
   3455 NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
   3456 #endif
   3457 NK_API int nk_tooltip_begin(struct nk_context*, float width);
   3458 NK_API void nk_tooltip_end(struct nk_context*);
   3459 /* =============================================================================
   3460  *
   3461  *                                  MENU
   3462  *
   3463  * ============================================================================= */
   3464 NK_API void nk_menubar_begin(struct nk_context*);
   3465 NK_API void nk_menubar_end(struct nk_context*);
   3466 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
   3467 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
   3468 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
   3469 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
   3470 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
   3471 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
   3472 NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
   3473 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
   3474 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
   3475 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
   3476 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
   3477 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
   3478 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
   3479 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
   3480 NK_API void nk_menu_close(struct nk_context*);
   3481 NK_API void nk_menu_end(struct nk_context*);
   3482 /* =============================================================================
   3483  *
   3484  *                                  STYLE
   3485  *
   3486  * ============================================================================= */
   3487 enum nk_style_colors {
   3488     NK_COLOR_TEXT,
   3489     NK_COLOR_WINDOW,
   3490     NK_COLOR_HEADER,
   3491     NK_COLOR_BORDER,
   3492     NK_COLOR_BUTTON,
   3493     NK_COLOR_BUTTON_HOVER,
   3494     NK_COLOR_BUTTON_ACTIVE,
   3495     NK_COLOR_TOGGLE,
   3496     NK_COLOR_TOGGLE_HOVER,
   3497     NK_COLOR_TOGGLE_CURSOR,
   3498     NK_COLOR_SELECT,
   3499     NK_COLOR_SELECT_ACTIVE,
   3500     NK_COLOR_SLIDER,
   3501     NK_COLOR_SLIDER_CURSOR,
   3502     NK_COLOR_SLIDER_CURSOR_HOVER,
   3503     NK_COLOR_SLIDER_CURSOR_ACTIVE,
   3504     NK_COLOR_PROPERTY,
   3505     NK_COLOR_EDIT,
   3506     NK_COLOR_EDIT_CURSOR,
   3507     NK_COLOR_COMBO,
   3508     NK_COLOR_CHART,
   3509     NK_COLOR_CHART_COLOR,
   3510     NK_COLOR_CHART_COLOR_HIGHLIGHT,
   3511     NK_COLOR_SCROLLBAR,
   3512     NK_COLOR_SCROLLBAR_CURSOR,
   3513     NK_COLOR_SCROLLBAR_CURSOR_HOVER,
   3514     NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,
   3515     NK_COLOR_TAB_HEADER,
   3516     NK_COLOR_COUNT
   3517 };
   3518 enum nk_style_cursor {
   3519     NK_CURSOR_ARROW,
   3520     NK_CURSOR_TEXT,
   3521     NK_CURSOR_MOVE,
   3522     NK_CURSOR_RESIZE_VERTICAL,
   3523     NK_CURSOR_RESIZE_HORIZONTAL,
   3524     NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT,
   3525     NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT,
   3526     NK_CURSOR_COUNT
   3527 };
   3528 NK_API void nk_style_default(struct nk_context*);
   3529 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
   3530 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
   3531 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
   3532 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors);
   3533 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
   3534 NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor);
   3535 NK_API void nk_style_show_cursor(struct nk_context*);
   3536 NK_API void nk_style_hide_cursor(struct nk_context*);
   3537 
   3538 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*);
   3539 NK_API int nk_style_push_float(struct nk_context*, float*, float);
   3540 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
   3541 NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item);
   3542 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
   3543 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
   3544 
   3545 NK_API int nk_style_pop_font(struct nk_context*);
   3546 NK_API int nk_style_pop_float(struct nk_context*);
   3547 NK_API int nk_style_pop_vec2(struct nk_context*);
   3548 NK_API int nk_style_pop_style_item(struct nk_context*);
   3549 NK_API int nk_style_pop_flags(struct nk_context*);
   3550 NK_API int nk_style_pop_color(struct nk_context*);
   3551 /* =============================================================================
   3552  *
   3553  *                                  COLOR
   3554  *
   3555  * ============================================================================= */
   3556 NK_API struct nk_color nk_rgb(int r, int g, int b);
   3557 NK_API struct nk_color nk_rgb_iv(const int *rgb);
   3558 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
   3559 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
   3560 NK_API struct nk_color nk_rgb_fv(const float *rgb);
   3561 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c);
   3562 NK_API struct nk_color nk_rgb_hex(const char *rgb);
   3563 
   3564 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
   3565 NK_API struct nk_color nk_rgba_u32(nk_uint);
   3566 NK_API struct nk_color nk_rgba_iv(const int *rgba);
   3567 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
   3568 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
   3569 NK_API struct nk_color nk_rgba_fv(const float *rgba);
   3570 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c);
   3571 NK_API struct nk_color nk_rgba_hex(const char *rgb);
   3572 
   3573 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a);
   3574 NK_API struct nk_colorf nk_hsva_colorfv(float *c);
   3575 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in);
   3576 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in);
   3577 
   3578 NK_API struct nk_color nk_hsv(int h, int s, int v);
   3579 NK_API struct nk_color nk_hsv_iv(const int *hsv);
   3580 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
   3581 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
   3582 NK_API struct nk_color nk_hsv_fv(const float *hsv);
   3583 
   3584 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
   3585 NK_API struct nk_color nk_hsva_iv(const int *hsva);
   3586 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
   3587 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
   3588 NK_API struct nk_color nk_hsva_fv(const float *hsva);
   3589 
   3590 /* color (conversion nuklear --> user) */
   3591 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
   3592 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
   3593 NK_API struct nk_colorf nk_color_cf(struct nk_color);
   3594 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
   3595 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
   3596 
   3597 NK_API nk_uint nk_color_u32(struct nk_color);
   3598 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
   3599 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
   3600 
   3601 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
   3602 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
   3603 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
   3604 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
   3605 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
   3606 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
   3607 
   3608 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
   3609 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
   3610 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
   3611 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
   3612 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
   3613 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
   3614 /* =============================================================================
   3615  *
   3616  *                                  IMAGE
   3617  *
   3618  * ============================================================================= */
   3619 NK_API nk_handle nk_handle_ptr(void*);
   3620 NK_API nk_handle nk_handle_id(int);
   3621 NK_API struct nk_image nk_image_handle(nk_handle);
   3622 NK_API struct nk_image nk_image_ptr(void*);
   3623 NK_API struct nk_image nk_image_id(int);
   3624 NK_API int nk_image_is_subimage(const struct nk_image* img);
   3625 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
   3626 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
   3627 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
   3628 /* =============================================================================
   3629  *
   3630  *                                  MATH
   3631  *
   3632  * ============================================================================= */
   3633 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
   3634 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
   3635 
   3636 NK_API struct nk_vec2 nk_vec2(float x, float y);
   3637 NK_API struct nk_vec2 nk_vec2i(int x, int y);
   3638 NK_API struct nk_vec2 nk_vec2v(const float *xy);
   3639 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
   3640 
   3641 NK_API struct nk_rect nk_get_null_rect(void);
   3642 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
   3643 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
   3644 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
   3645 NK_API struct nk_rect nk_rectv(const float *xywh);
   3646 NK_API struct nk_rect nk_rectiv(const int *xywh);
   3647 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
   3648 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
   3649 /* =============================================================================
   3650  *
   3651  *                                  STRING
   3652  *
   3653  * ============================================================================= */
   3654 NK_API int nk_strlen(const char *str);
   3655 NK_API int nk_stricmp(const char *s1, const char *s2);
   3656 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
   3657 NK_API int nk_strtoi(const char *str, const char **endptr);
   3658 NK_API float nk_strtof(const char *str, const char **endptr);
   3659 NK_API double nk_strtod(const char *str, const char **endptr);
   3660 NK_API int nk_strfilter(const char *text, const char *regexp);
   3661 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
   3662 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
   3663 /* =============================================================================
   3664  *
   3665  *                                  UTF-8
   3666  *
   3667  * ============================================================================= */
   3668 NK_API int nk_utf_decode(const char*, nk_rune*, int);
   3669 NK_API int nk_utf_encode(nk_rune, char*, int);
   3670 NK_API int nk_utf_len(const char*, int byte_len);
   3671 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
   3672 /* ===============================================================
   3673  *
   3674  *                          FONT
   3675  *
   3676  * ===============================================================*/
   3677 /*  Font handling in this library was designed to be quite customizable and lets
   3678     you decide what you want to use and what you want to provide. There are three
   3679     different ways to use the font atlas. The first two will use your font
   3680     handling scheme and only requires essential data to run nuklear. The next
   3681     slightly more advanced features is font handling with vertex buffer output.
   3682     Finally the most complex API wise is using nuklear's font baking API.
   3683 
   3684     1.) Using your own implementation without vertex buffer output
   3685     --------------------------------------------------------------
   3686     So first up the easiest way to do font handling is by just providing a
   3687     `nk_user_font` struct which only requires the height in pixel of the used
   3688     font and a callback to calculate the width of a string. This way of handling
   3689     fonts is best fitted for using the normal draw shape command API where you
   3690     do all the text drawing yourself and the library does not require any kind
   3691     of deeper knowledge about which font handling mechanism you use.
   3692     IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
   3693     over the complete life time! I know this sucks but it is currently the only
   3694     way to switch between fonts.
   3695 
   3696         float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
   3697         {
   3698             your_font_type *type = handle.ptr;
   3699             float text_width = ...;
   3700             return text_width;
   3701         }
   3702 
   3703         struct nk_user_font font;
   3704         font.userdata.ptr = &your_font_class_or_struct;
   3705         font.height = your_font_height;
   3706         font.width = your_text_width_calculation;
   3707 
   3708         struct nk_context ctx;
   3709         nk_init_default(&ctx, &font);
   3710 
   3711     2.) Using your own implementation with vertex buffer output
   3712     --------------------------------------------------------------
   3713     While the first approach works fine if you don't want to use the optional
   3714     vertex buffer output it is not enough if you do. To get font handling working
   3715     for these cases you have to provide two additional parameters inside the
   3716     `nk_user_font`. First a texture atlas handle used to draw text as subimages
   3717     of a bigger font atlas texture and a callback to query a character's glyph
   3718     information (offset, size, ...). So it is still possible to provide your own
   3719     font and use the vertex buffer output.
   3720 
   3721         float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
   3722         {
   3723             your_font_type *type = handle.ptr;
   3724             float text_width = ...;
   3725             return text_width;
   3726         }
   3727         void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
   3728         {
   3729             your_font_type *type = handle.ptr;
   3730             glyph.width = ...;
   3731             glyph.height = ...;
   3732             glyph.xadvance = ...;
   3733             glyph.uv[0].x = ...;
   3734             glyph.uv[0].y = ...;
   3735             glyph.uv[1].x = ...;
   3736             glyph.uv[1].y = ...;
   3737             glyph.offset.x = ...;
   3738             glyph.offset.y = ...;
   3739         }
   3740 
   3741         struct nk_user_font font;
   3742         font.userdata.ptr = &your_font_class_or_struct;
   3743         font.height = your_font_height;
   3744         font.width = your_text_width_calculation;
   3745         font.query = query_your_font_glyph;
   3746         font.texture.id = your_font_texture;
   3747 
   3748         struct nk_context ctx;
   3749         nk_init_default(&ctx, &font);
   3750 
   3751     3.) Nuklear font baker
   3752     ------------------------------------
   3753     The final approach if you do not have a font handling functionality or don't
   3754     want to use it in this library is by using the optional font baker.
   3755     The font baker APIs can be used to create a font plus font atlas texture
   3756     and can be used with or without the vertex buffer output.
   3757 
   3758     It still uses the `nk_user_font` struct and the two different approaches
   3759     previously stated still work. The font baker is not located inside
   3760     `nk_context` like all other systems since it can be understood as more of
   3761     an extension to nuklear and does not really depend on any `nk_context` state.
   3762 
   3763     Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
   3764     functions. If you don't care about memory just call the default version
   3765     `nk_font_atlas_init_default` which will allocate all memory from the standard library.
   3766     If you want to control memory allocation but you don't care if the allocated
   3767     memory is temporary and therefore can be freed directly after the baking process
   3768     is over or permanent you can call `nk_font_atlas_init`.
   3769 
   3770     After successfully initializing the font baker you can add Truetype(.ttf) fonts from
   3771     different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
   3772     functions. Adding font will permanently store each font, font config and ttf memory block(!)
   3773     inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
   3774     the font baker by for example adding additional fonts you can call
   3775     `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
   3776 
   3777     As soon as you added all fonts you wanted you can now start the baking process
   3778     for every selected glyph to image by calling `nk_font_atlas_bake`.
   3779     The baking process returns image memory, width and height which can be used to
   3780     either create your own image object or upload it to any graphics library.
   3781     No matter which case you finally have to call `nk_font_atlas_end` which
   3782     will free all temporary memory including the font atlas image so make sure
   3783     you created our texture beforehand. `nk_font_atlas_end` requires a handle
   3784     to your font texture or object and optionally fills a `struct nk_draw_null_texture`
   3785     which can be used for the optional vertex output. If you don't want it just
   3786     set the argument to `NULL`.
   3787 
   3788     At this point you are done and if you don't want to reuse the font atlas you
   3789     can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
   3790     memory. Finally if you don't use the font atlas and any of it's fonts anymore
   3791     you need to call `nk_font_atlas_clear` to free all memory still being used.
   3792 
   3793         struct nk_font_atlas atlas;
   3794         nk_font_atlas_init_default(&atlas);
   3795         nk_font_atlas_begin(&atlas);
   3796         nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
   3797         nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
   3798         const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
   3799         nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
   3800 
   3801         struct nk_context ctx;
   3802         nk_init_default(&ctx, &font->handle);
   3803         while (1) {
   3804 
   3805         }
   3806         nk_font_atlas_clear(&atlas);
   3807 
   3808     The font baker API is probably the most complex API inside this library and
   3809     I would suggest reading some of my examples `example/` to get a grip on how
   3810     to use the font atlas. There are a number of details I left out. For example
   3811     how to merge fonts, configure a font with `nk_font_config` to use other languages,
   3812     use another texture coordinate format and a lot more:
   3813 
   3814         struct nk_font_config cfg = nk_font_config(font_pixel_height);
   3815         cfg.merge_mode = nk_false or nk_true;
   3816         cfg.range = nk_font_korean_glyph_ranges();
   3817         cfg.coord_type = NK_COORD_PIXEL;
   3818         nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
   3819 
   3820 */
   3821 struct nk_user_font_glyph;
   3822 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
   3823 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
   3824                                     struct nk_user_font_glyph *glyph,
   3825                                     nk_rune codepoint, nk_rune next_codepoint);
   3826 
   3827 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT)
   3828 struct nk_user_font_glyph {
   3829     struct nk_vec2 uv[2];
   3830     /* texture coordinates */
   3831     struct nk_vec2 offset;
   3832     /* offset between top left and glyph */
   3833     float width, height;
   3834     /* size of the glyph  */
   3835     float xadvance;
   3836     /* offset to the next glyph */
   3837 };
   3838 #endif
   3839 
   3840 struct nk_user_font {
   3841     nk_handle userdata;
   3842     /* user provided font handle */
   3843     float height;
   3844     /* max height of the font */
   3845     nk_text_width_f width;
   3846     /* font string width in pixel callback */
   3847 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   3848     nk_query_font_glyph_f query;
   3849     /* font glyph callback to query drawing info */
   3850     nk_handle texture;
   3851     /* texture handle to the used font atlas or texture */
   3852 #endif
   3853 };
   3854 
   3855 #ifdef NK_INCLUDE_FONT_BAKING
   3856 enum nk_font_coord_type {
   3857     NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
   3858     NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
   3859 };
   3860 
   3861 struct nk_font;
   3862 struct nk_baked_font {
   3863     float height;
   3864     /* height of the font  */
   3865     float ascent, descent;
   3866     /* font glyphs ascent and descent  */
   3867     nk_rune glyph_offset;
   3868     /* glyph array offset inside the font glyph baking output array  */
   3869     nk_rune glyph_count;
   3870     /* number of glyphs of this font inside the glyph baking array output */
   3871     const nk_rune *ranges;
   3872     /* font codepoint ranges as pairs of (from/to) and 0 as last element */
   3873 };
   3874 
   3875 struct nk_font_config {
   3876     struct nk_font_config *next;
   3877     /* NOTE: only used internally */
   3878     void *ttf_blob;
   3879     /* pointer to loaded TTF file memory block.
   3880      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
   3881     nk_size ttf_size;
   3882     /* size of the loaded TTF file memory block
   3883      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
   3884 
   3885     unsigned char ttf_data_owned_by_atlas;
   3886     /* used inside font atlas: default to: 0*/
   3887     unsigned char merge_mode;
   3888     /* merges this font into the last font */
   3889     unsigned char pixel_snap;
   3890     /* align every character to pixel boundary (if true set oversample (1,1)) */
   3891     unsigned char oversample_v, oversample_h;
   3892     /* rasterize at hight quality for sub-pixel position */
   3893     unsigned char padding[3];
   3894 
   3895     float size;
   3896     /* baked pixel height of the font */
   3897     enum nk_font_coord_type coord_type;
   3898     /* texture coordinate format with either pixel or UV coordinates */
   3899     struct nk_vec2 spacing;
   3900     /* extra pixel spacing between glyphs  */
   3901     const nk_rune *range;
   3902     /* list of unicode ranges (2 values per range, zero terminated) */
   3903     struct nk_baked_font *font;
   3904     /* font to setup in the baking process: NOTE: not needed for font atlas */
   3905     nk_rune fallback_glyph;
   3906     /* fallback glyph to use if a given rune is not found */
   3907     struct nk_font_config *n;
   3908     struct nk_font_config *p;
   3909 };
   3910 
   3911 struct nk_font_glyph {
   3912     nk_rune codepoint;
   3913     float xadvance;
   3914     float x0, y0, x1, y1, w, h;
   3915     float u0, v0, u1, v1;
   3916 };
   3917 
   3918 struct nk_font {
   3919     struct nk_font *next;
   3920     struct nk_user_font handle;
   3921     struct nk_baked_font info;
   3922     float scale;
   3923     struct nk_font_glyph *glyphs;
   3924     const struct nk_font_glyph *fallback;
   3925     nk_rune fallback_codepoint;
   3926     nk_handle texture;
   3927     struct nk_font_config *config;
   3928 };
   3929 
   3930 enum nk_font_atlas_format {
   3931     NK_FONT_ATLAS_ALPHA8,
   3932     NK_FONT_ATLAS_RGBA32
   3933 };
   3934 
   3935 struct nk_font_atlas {
   3936     void *pixel;
   3937     int tex_width;
   3938     int tex_height;
   3939 
   3940     struct nk_allocator permanent;
   3941     struct nk_allocator temporary;
   3942 
   3943     struct nk_recti custom;
   3944     struct nk_cursor cursors[NK_CURSOR_COUNT];
   3945 
   3946     int glyph_count;
   3947     struct nk_font_glyph *glyphs;
   3948     struct nk_font *default_font;
   3949     struct nk_font *fonts;
   3950     struct nk_font_config *config;
   3951     int font_num;
   3952 };
   3953 
   3954 /* some language glyph codepoint ranges */
   3955 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
   3956 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
   3957 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
   3958 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
   3959 
   3960 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   3961 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
   3962 #endif
   3963 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
   3964 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
   3965 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
   3966 NK_API struct nk_font_config nk_font_config(float pixel_height);
   3967 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
   3968 #ifdef NK_INCLUDE_DEFAULT_FONT
   3969 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
   3970 #endif
   3971 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);
   3972 #ifdef NK_INCLUDE_STANDARD_IO
   3973 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*);
   3974 #endif
   3975 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*);
   3976 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);
   3977 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
   3978 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
   3979 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
   3980 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
   3981 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
   3982 
   3983 #endif
   3984 
   3985 /* ==============================================================
   3986  *
   3987  *                          MEMORY BUFFER
   3988  *
   3989  * ===============================================================*/
   3990 /*  A basic (double)-buffer with linear allocation and resetting as only
   3991     freeing policy. The buffer's main purpose is to control all memory management
   3992     inside the GUI toolkit and still leave memory control as much as possible in
   3993     the hand of the user while also making sure the library is easy to use if
   3994     not as much control is needed.
   3995     In general all memory inside this library can be provided from the user in
   3996     three different ways.
   3997 
   3998     The first way and the one providing most control is by just passing a fixed
   3999     size memory block. In this case all control lies in the hand of the user
   4000     since he can exactly control where the memory comes from and how much memory
   4001     the library should consume. Of course using the fixed size API removes the
   4002     ability to automatically resize a buffer if not enough memory is provided so
   4003     you have to take over the resizing. While being a fixed sized buffer sounds
   4004     quite limiting, it is very effective in this library since the actual memory
   4005     consumption is quite stable and has a fixed upper bound for a lot of cases.
   4006 
   4007     If you don't want to think about how much memory the library should allocate
   4008     at all time or have a very dynamic UI with unpredictable memory consumption
   4009     habits but still want control over memory allocation you can use the dynamic
   4010     allocator based API. The allocator consists of two callbacks for allocating
   4011     and freeing memory and optional userdata so you can plugin your own allocator.
   4012 
   4013     The final and easiest way can be used by defining
   4014     NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
   4015     allocation functions malloc and free and takes over complete control over
   4016     memory in this library.
   4017 */
   4018 struct nk_memory_status {
   4019     void *memory;
   4020     unsigned int type;
   4021     nk_size size;
   4022     nk_size allocated;
   4023     nk_size needed;
   4024     nk_size calls;
   4025 };
   4026 
   4027 enum nk_allocation_type {
   4028     NK_BUFFER_FIXED,
   4029     NK_BUFFER_DYNAMIC
   4030 };
   4031 
   4032 enum nk_buffer_allocation_type {
   4033     NK_BUFFER_FRONT,
   4034     NK_BUFFER_BACK,
   4035     NK_BUFFER_MAX
   4036 };
   4037 
   4038 struct nk_buffer_marker {
   4039     int active;
   4040     nk_size offset;
   4041 };
   4042 
   4043 struct nk_memory {void *ptr;nk_size size;};
   4044 struct nk_buffer {
   4045     struct nk_buffer_marker marker[NK_BUFFER_MAX];
   4046     /* buffer marker to free a buffer to a certain offset */
   4047     struct nk_allocator pool;
   4048     /* allocator callback for dynamic buffers */
   4049     enum nk_allocation_type type;
   4050     /* memory management type */
   4051     struct nk_memory memory;
   4052     /* memory and size of the current memory block */
   4053     float grow_factor;
   4054     /* growing factor for dynamic memory management */
   4055     nk_size allocated;
   4056     /* total amount of memory allocated */
   4057     nk_size needed;
   4058     /* totally consumed memory given that enough memory is present */
   4059     nk_size calls;
   4060     /* number of allocation calls */
   4061     nk_size size;
   4062     /* current size of the buffer */
   4063 };
   4064 
   4065 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   4066 NK_API void nk_buffer_init_default(struct nk_buffer*);
   4067 #endif
   4068 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
   4069 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
   4070 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
   4071 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
   4072 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
   4073 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type);
   4074 NK_API void nk_buffer_clear(struct nk_buffer*);
   4075 NK_API void nk_buffer_free(struct nk_buffer*);
   4076 NK_API void *nk_buffer_memory(struct nk_buffer*);
   4077 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
   4078 NK_API nk_size nk_buffer_total(struct nk_buffer*);
   4079 
   4080 /* ==============================================================
   4081  *
   4082  *                          STRING
   4083  *
   4084  * ===============================================================*/
   4085 /*  Basic string buffer which is only used in context with the text editor
   4086  *  to manage and manipulate dynamic or fixed size string content. This is _NOT_
   4087  *  the default string handling method. The only instance you should have any contact
   4088  *  with this API is if you interact with an `nk_text_edit` object inside one of the
   4089  *  copy and paste functions and even there only for more advanced cases. */
   4090 struct nk_str {
   4091     struct nk_buffer buffer;
   4092     int len; /* in codepoints/runes/glyphs */
   4093 };
   4094 
   4095 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   4096 NK_API void nk_str_init_default(struct nk_str*);
   4097 #endif
   4098 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
   4099 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
   4100 NK_API void nk_str_clear(struct nk_str*);
   4101 NK_API void nk_str_free(struct nk_str*);
   4102 
   4103 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
   4104 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
   4105 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
   4106 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
   4107 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
   4108 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
   4109 
   4110 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
   4111 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
   4112 
   4113 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
   4114 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
   4115 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
   4116 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
   4117 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
   4118 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
   4119 
   4120 NK_API void nk_str_remove_chars(struct nk_str*, int len);
   4121 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
   4122 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
   4123 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
   4124 
   4125 NK_API char *nk_str_at_char(struct nk_str*, int pos);
   4126 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
   4127 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
   4128 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
   4129 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
   4130 
   4131 NK_API char *nk_str_get(struct nk_str*);
   4132 NK_API const char *nk_str_get_const(const struct nk_str*);
   4133 NK_API int nk_str_len(struct nk_str*);
   4134 NK_API int nk_str_len_char(struct nk_str*);
   4135 
   4136 /*===============================================================
   4137  *
   4138  *                      TEXT EDITOR
   4139  *
   4140  * ===============================================================*/
   4141 /* Editing text in this library is handled by either `nk_edit_string` or
   4142  * `nk_edit_buffer`. But like almost everything in this library there are multiple
   4143  * ways of doing it and a balance between control and ease of use with memory
   4144  * as well as functionality controlled by flags.
   4145  *
   4146  * This library generally allows three different levels of memory control:
   4147  * First of is the most basic way of just providing a simple char array with
   4148  * string length. This method is probably the easiest way of handling simple
   4149  * user text input. Main upside is complete control over memory while the biggest
   4150  * downside in comparison with the other two approaches is missing undo/redo.
   4151  *
   4152  * For UIs that require undo/redo the second way was created. It is based on
   4153  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
   4154  * This is mainly useful if you want something more like a text editor but don't want
   4155  * to have a dynamically growing buffer.
   4156  *
   4157  * The final way is using a dynamically growing nk_text_edit struct, which
   4158  * has both a default version if you don't care where memory comes from and an
   4159  * allocator version if you do. While the text editor is quite powerful for its
   4160  * complexity I would not recommend editing gigabytes of data with it.
   4161  * It is rather designed for uses cases which make sense for a GUI library not for
   4162  * an full blown text editor.
   4163  */
   4164 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
   4165 #define NK_TEXTEDIT_UNDOSTATECOUNT     99
   4166 #endif
   4167 
   4168 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
   4169 #define NK_TEXTEDIT_UNDOCHARCOUNT      999
   4170 #endif
   4171 
   4172 struct nk_text_edit;
   4173 struct nk_clipboard {
   4174     nk_handle userdata;
   4175     nk_plugin_paste paste;
   4176     nk_plugin_copy copy;
   4177 };
   4178 
   4179 struct nk_text_undo_record {
   4180    int where;
   4181    short insert_length;
   4182    short delete_length;
   4183    short char_storage;
   4184 };
   4185 
   4186 struct nk_text_undo_state {
   4187    struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT];
   4188    nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT];
   4189    short undo_point;
   4190    short redo_point;
   4191    short undo_char_point;
   4192    short redo_char_point;
   4193 };
   4194 
   4195 enum nk_text_edit_type {
   4196     NK_TEXT_EDIT_SINGLE_LINE,
   4197     NK_TEXT_EDIT_MULTI_LINE
   4198 };
   4199 
   4200 enum nk_text_edit_mode {
   4201     NK_TEXT_EDIT_MODE_VIEW,
   4202     NK_TEXT_EDIT_MODE_INSERT,
   4203     NK_TEXT_EDIT_MODE_REPLACE
   4204 };
   4205 
   4206 struct nk_text_edit {
   4207     struct nk_clipboard clip;
   4208     struct nk_str string;
   4209     nk_plugin_filter filter;
   4210     struct nk_vec2 scrollbar;
   4211 
   4212     int cursor;
   4213     int select_start;
   4214     int select_end;
   4215     unsigned char mode;
   4216     unsigned char cursor_at_end_of_line;
   4217     unsigned char initialized;
   4218     unsigned char has_preferred_x;
   4219     unsigned char single_line;
   4220     unsigned char active;
   4221     unsigned char padding1;
   4222     float preferred_x;
   4223     struct nk_text_undo_state undo;
   4224 };
   4225 
   4226 /* filter function */
   4227 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
   4228 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
   4229 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
   4230 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
   4231 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
   4232 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
   4233 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
   4234 
   4235 /* text editor */
   4236 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   4237 NK_API void nk_textedit_init_default(struct nk_text_edit*);
   4238 #endif
   4239 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
   4240 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
   4241 NK_API void nk_textedit_free(struct nk_text_edit*);
   4242 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
   4243 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
   4244 NK_API void nk_textedit_delete_selection(struct nk_text_edit*);
   4245 NK_API void nk_textedit_select_all(struct nk_text_edit*);
   4246 NK_API int nk_textedit_cut(struct nk_text_edit*);
   4247 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
   4248 NK_API void nk_textedit_undo(struct nk_text_edit*);
   4249 NK_API void nk_textedit_redo(struct nk_text_edit*);
   4250 
   4251 /* ===============================================================
   4252  *
   4253  *                          DRAWING
   4254  *
   4255  * ===============================================================*/
   4256 /*  This library was designed to be render backend agnostic so it does
   4257     not draw anything to screen. Instead all drawn shapes, widgets
   4258     are made of, are buffered into memory and make up a command queue.
   4259     Each frame therefore fills the command buffer with draw commands
   4260     that then need to be executed by the user and his own render backend.
   4261     After that the command buffer needs to be cleared and a new frame can be
   4262     started. It is probably important to note that the command buffer is the main
   4263     drawing API and the optional vertex buffer API only takes this format and
   4264     converts it into a hardware accessible format.
   4265 
   4266     To use the command queue to draw your own widgets you can access the
   4267     command buffer of each window by calling `nk_window_get_canvas` after
   4268     previously having called `nk_begin`:
   4269 
   4270         void draw_red_rectangle_widget(struct nk_context *ctx)
   4271         {
   4272             struct nk_command_buffer *canvas;
   4273             struct nk_input *input = &ctx->input;
   4274             canvas = nk_window_get_canvas(ctx);
   4275 
   4276             struct nk_rect space;
   4277             enum nk_widget_layout_states state;
   4278             state = nk_widget(&space, ctx);
   4279             if (!state) return;
   4280 
   4281             if (state != NK_WIDGET_ROM)
   4282                 update_your_widget_by_user_input(...);
   4283             nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
   4284         }
   4285 
   4286         if (nk_begin(...)) {
   4287             nk_layout_row_dynamic(ctx, 25, 1);
   4288             draw_red_rectangle_widget(ctx);
   4289         }
   4290         nk_end(..)
   4291 
   4292     Important to know if you want to create your own widgets is the `nk_widget`
   4293     call. It allocates space on the panel reserved for this widget to be used,
   4294     but also returns the state of the widget space. If your widget is not seen and does
   4295     not have to be updated it is '0' and you can just return. If it only has
   4296     to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
   4297     update and draw your widget. The reason for separating is to only draw and
   4298     update what is actually necessary which is crucial for performance.
   4299 */
   4300 enum nk_command_type {
   4301     NK_COMMAND_NOP,
   4302     NK_COMMAND_SCISSOR,
   4303     NK_COMMAND_LINE,
   4304     NK_COMMAND_CURVE,
   4305     NK_COMMAND_RECT,
   4306     NK_COMMAND_RECT_FILLED,
   4307     NK_COMMAND_RECT_MULTI_COLOR,
   4308     NK_COMMAND_CIRCLE,
   4309     NK_COMMAND_CIRCLE_FILLED,
   4310     NK_COMMAND_ARC,
   4311     NK_COMMAND_ARC_FILLED,
   4312     NK_COMMAND_TRIANGLE,
   4313     NK_COMMAND_TRIANGLE_FILLED,
   4314     NK_COMMAND_POLYGON,
   4315     NK_COMMAND_POLYGON_FILLED,
   4316     NK_COMMAND_POLYLINE,
   4317     NK_COMMAND_TEXT,
   4318     NK_COMMAND_IMAGE,
   4319     NK_COMMAND_CUSTOM
   4320 };
   4321 
   4322 /* command base and header of every command inside the buffer */
   4323 struct nk_command {
   4324     enum nk_command_type type;
   4325     nk_size next;
   4326 #ifdef NK_INCLUDE_COMMAND_USERDATA
   4327     nk_handle userdata;
   4328 #endif
   4329 };
   4330 
   4331 struct nk_command_scissor {
   4332     struct nk_command header;
   4333     short x, y;
   4334     unsigned short w, h;
   4335 };
   4336 
   4337 struct nk_command_line {
   4338     struct nk_command header;
   4339     unsigned short line_thickness;
   4340     struct nk_vec2i begin;
   4341     struct nk_vec2i end;
   4342     struct nk_color color;
   4343 };
   4344 
   4345 struct nk_command_curve {
   4346     struct nk_command header;
   4347     unsigned short line_thickness;
   4348     struct nk_vec2i begin;
   4349     struct nk_vec2i end;
   4350     struct nk_vec2i ctrl[2];
   4351     struct nk_color color;
   4352 };
   4353 
   4354 struct nk_command_rect {
   4355     struct nk_command header;
   4356     unsigned short rounding;
   4357     unsigned short line_thickness;
   4358     short x, y;
   4359     unsigned short w, h;
   4360     struct nk_color color;
   4361 };
   4362 
   4363 struct nk_command_rect_filled {
   4364     struct nk_command header;
   4365     unsigned short rounding;
   4366     short x, y;
   4367     unsigned short w, h;
   4368     struct nk_color color;
   4369 };
   4370 
   4371 struct nk_command_rect_multi_color {
   4372     struct nk_command header;
   4373     short x, y;
   4374     unsigned short w, h;
   4375     struct nk_color left;
   4376     struct nk_color top;
   4377     struct nk_color bottom;
   4378     struct nk_color right;
   4379 };
   4380 
   4381 struct nk_command_triangle {
   4382     struct nk_command header;
   4383     unsigned short line_thickness;
   4384     struct nk_vec2i a;
   4385     struct nk_vec2i b;
   4386     struct nk_vec2i c;
   4387     struct nk_color color;
   4388 };
   4389 
   4390 struct nk_command_triangle_filled {
   4391     struct nk_command header;
   4392     struct nk_vec2i a;
   4393     struct nk_vec2i b;
   4394     struct nk_vec2i c;
   4395     struct nk_color color;
   4396 };
   4397 
   4398 struct nk_command_circle {
   4399     struct nk_command header;
   4400     short x, y;
   4401     unsigned short line_thickness;
   4402     unsigned short w, h;
   4403     struct nk_color color;
   4404 };
   4405 
   4406 struct nk_command_circle_filled {
   4407     struct nk_command header;
   4408     short x, y;
   4409     unsigned short w, h;
   4410     struct nk_color color;
   4411 };
   4412 
   4413 struct nk_command_arc {
   4414     struct nk_command header;
   4415     short cx, cy;
   4416     unsigned short r;
   4417     unsigned short line_thickness;
   4418     float a[2];
   4419     struct nk_color color;
   4420 };
   4421 
   4422 struct nk_command_arc_filled {
   4423     struct nk_command header;
   4424     short cx, cy;
   4425     unsigned short r;
   4426     float a[2];
   4427     struct nk_color color;
   4428 };
   4429 
   4430 struct nk_command_polygon {
   4431     struct nk_command header;
   4432     struct nk_color color;
   4433     unsigned short line_thickness;
   4434     unsigned short point_count;
   4435     struct nk_vec2i points[1];
   4436 };
   4437 
   4438 struct nk_command_polygon_filled {
   4439     struct nk_command header;
   4440     struct nk_color color;
   4441     unsigned short point_count;
   4442     struct nk_vec2i points[1];
   4443 };
   4444 
   4445 struct nk_command_polyline {
   4446     struct nk_command header;
   4447     struct nk_color color;
   4448     unsigned short line_thickness;
   4449     unsigned short point_count;
   4450     struct nk_vec2i points[1];
   4451 };
   4452 
   4453 struct nk_command_image {
   4454     struct nk_command header;
   4455     short x, y;
   4456     unsigned short w, h;
   4457     struct nk_image img;
   4458     struct nk_color col;
   4459 };
   4460 
   4461 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
   4462     unsigned short w, unsigned short h, nk_handle callback_data);
   4463 struct nk_command_custom {
   4464     struct nk_command header;
   4465     short x, y;
   4466     unsigned short w, h;
   4467     nk_handle callback_data;
   4468     nk_command_custom_callback callback;
   4469 };
   4470 
   4471 struct nk_command_text {
   4472     struct nk_command header;
   4473     const struct nk_user_font *font;
   4474     struct nk_color background;
   4475     struct nk_color foreground;
   4476     short x, y;
   4477     unsigned short w, h;
   4478     float height;
   4479     int length;
   4480     char string[1];
   4481 };
   4482 
   4483 enum nk_command_clipping {
   4484     NK_CLIPPING_OFF = nk_false,
   4485     NK_CLIPPING_ON = nk_true
   4486 };
   4487 
   4488 struct nk_command_buffer {
   4489     struct nk_buffer *base;
   4490     struct nk_rect clip;
   4491     int use_clipping;
   4492     nk_handle userdata;
   4493     nk_size begin, end, last;
   4494 };
   4495 
   4496 /* shape outlines */
   4497 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);
   4498 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
   4499 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
   4500 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
   4501 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);
   4502 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
   4503 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
   4504 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
   4505 
   4506 /* filled shades */
   4507 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
   4508 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);
   4509 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
   4510 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);
   4511 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);
   4512 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
   4513 
   4514 /* misc */
   4515 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
   4516 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);
   4517 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
   4518 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
   4519 
   4520 /* ===============================================================
   4521  *
   4522  *                          INPUT
   4523  *
   4524  * ===============================================================*/
   4525 struct nk_mouse_button {
   4526     int down;
   4527     unsigned int clicked;
   4528     struct nk_vec2 clicked_pos;
   4529 };
   4530 struct nk_mouse {
   4531     struct nk_mouse_button buttons[NK_BUTTON_MAX];
   4532     struct nk_vec2 pos;
   4533     struct nk_vec2 prev;
   4534     struct nk_vec2 delta;
   4535     struct nk_vec2 scroll_delta;
   4536     unsigned char grab;
   4537     unsigned char grabbed;
   4538     unsigned char ungrab;
   4539 };
   4540 
   4541 struct nk_key {
   4542     int down;
   4543     unsigned int clicked;
   4544 };
   4545 struct nk_keyboard {
   4546     struct nk_key keys[NK_KEY_MAX];
   4547     char text[NK_INPUT_MAX];
   4548     int text_len;
   4549 };
   4550 
   4551 struct nk_input {
   4552     struct nk_keyboard keyboard;
   4553     struct nk_mouse mouse;
   4554 };
   4555 
   4556 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
   4557 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
   4558 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
   4559 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
   4560 NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down);
   4561 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
   4562 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
   4563 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
   4564 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
   4565 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
   4566 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
   4567 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
   4568 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
   4569 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
   4570 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
   4571 
   4572 /* ===============================================================
   4573  *
   4574  *                          DRAW LIST
   4575  *
   4576  * ===============================================================*/
   4577 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   4578 /*  The optional vertex buffer draw list provides a 2D drawing context
   4579     with antialiasing functionality which takes basic filled or outlined shapes
   4580     or a path and outputs vertexes, elements and draw commands.
   4581     The actual draw list API is not required to be used directly while using this
   4582     library since converting the default library draw command output is done by
   4583     just calling `nk_convert` but I decided to still make this library accessible
   4584     since it can be useful.
   4585 
   4586     The draw list is based on a path buffering and polygon and polyline
   4587     rendering API which allows a lot of ways to draw 2D content to screen.
   4588     In fact it is probably more powerful than needed but allows even more crazy
   4589     things than this library provides by default.
   4590 */
   4591 typedef nk_ushort nk_draw_index;
   4592 enum nk_draw_list_stroke {
   4593     NK_STROKE_OPEN = nk_false,
   4594     /* build up path has no connection back to the beginning */
   4595     NK_STROKE_CLOSED = nk_true
   4596     /* build up path has a connection back to the beginning */
   4597 };
   4598 
   4599 enum nk_draw_vertex_layout_attribute {
   4600     NK_VERTEX_POSITION,
   4601     NK_VERTEX_COLOR,
   4602     NK_VERTEX_TEXCOORD,
   4603     NK_VERTEX_ATTRIBUTE_COUNT
   4604 };
   4605 
   4606 enum nk_draw_vertex_layout_format {
   4607     NK_FORMAT_SCHAR,
   4608     NK_FORMAT_SSHORT,
   4609     NK_FORMAT_SINT,
   4610     NK_FORMAT_UCHAR,
   4611     NK_FORMAT_USHORT,
   4612     NK_FORMAT_UINT,
   4613     NK_FORMAT_FLOAT,
   4614     NK_FORMAT_DOUBLE,
   4615 
   4616 NK_FORMAT_COLOR_BEGIN,
   4617     NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
   4618     NK_FORMAT_R16G15B16,
   4619     NK_FORMAT_R32G32B32,
   4620 
   4621     NK_FORMAT_R8G8B8A8,
   4622     NK_FORMAT_B8G8R8A8,
   4623     NK_FORMAT_R16G15B16A16,
   4624     NK_FORMAT_R32G32B32A32,
   4625     NK_FORMAT_R32G32B32A32_FLOAT,
   4626     NK_FORMAT_R32G32B32A32_DOUBLE,
   4627 
   4628     NK_FORMAT_RGB32,
   4629     NK_FORMAT_RGBA32,
   4630 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
   4631     NK_FORMAT_COUNT
   4632 };
   4633 
   4634 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
   4635 struct nk_draw_vertex_layout_element {
   4636     enum nk_draw_vertex_layout_attribute attribute;
   4637     enum nk_draw_vertex_layout_format format;
   4638     nk_size offset;
   4639 };
   4640 
   4641 struct nk_draw_command {
   4642     unsigned int elem_count;
   4643     /* number of elements in the current draw batch */
   4644     struct nk_rect clip_rect;
   4645     /* current screen clipping rectangle */
   4646     nk_handle texture;
   4647     /* current texture to set */
   4648 #ifdef NK_INCLUDE_COMMAND_USERDATA
   4649     nk_handle userdata;
   4650 #endif
   4651 };
   4652 
   4653 struct nk_draw_list {
   4654     struct nk_rect clip_rect;
   4655     struct nk_vec2 circle_vtx[12];
   4656     struct nk_convert_config config;
   4657 
   4658     struct nk_buffer *buffer;
   4659     struct nk_buffer *vertices;
   4660     struct nk_buffer *elements;
   4661 
   4662     unsigned int element_count;
   4663     unsigned int vertex_count;
   4664     unsigned int cmd_count;
   4665     nk_size cmd_offset;
   4666 
   4667     unsigned int path_count;
   4668     unsigned int path_offset;
   4669 
   4670     enum nk_anti_aliasing line_AA;
   4671     enum nk_anti_aliasing shape_AA;
   4672 
   4673 #ifdef NK_INCLUDE_COMMAND_USERDATA
   4674     nk_handle userdata;
   4675 #endif
   4676 };
   4677 
   4678 /* draw list */
   4679 NK_API void nk_draw_list_init(struct nk_draw_list*);
   4680 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);
   4681 
   4682 /* drawing */
   4683 #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))
   4684 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
   4685 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*);
   4686 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
   4687 
   4688 /* path */
   4689 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
   4690 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
   4691 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);
   4692 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);
   4693 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
   4694 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);
   4695 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
   4696 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
   4697 
   4698 /* stroke */
   4699 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);
   4700 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
   4701 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);
   4702 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);
   4703 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);
   4704 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);
   4705 
   4706 /* fill */
   4707 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
   4708 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);
   4709 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);
   4710 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);
   4711 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);
   4712 
   4713 /* misc */
   4714 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
   4715 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);
   4716 #ifdef NK_INCLUDE_COMMAND_USERDATA
   4717 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
   4718 #endif
   4719 
   4720 #endif
   4721 
   4722 /* ===============================================================
   4723  *
   4724  *                          GUI
   4725  *
   4726  * ===============================================================*/
   4727 enum nk_style_item_type {
   4728     NK_STYLE_ITEM_COLOR,
   4729     NK_STYLE_ITEM_IMAGE
   4730 };
   4731 
   4732 union nk_style_item_data {
   4733     struct nk_image image;
   4734     struct nk_color color;
   4735 };
   4736 
   4737 struct nk_style_item {
   4738     enum nk_style_item_type type;
   4739     union nk_style_item_data data;
   4740 };
   4741 
   4742 struct nk_style_text {
   4743     struct nk_color color;
   4744     struct nk_vec2 padding;
   4745 };
   4746 
   4747 struct nk_style_button {
   4748     /* background */
   4749     struct nk_style_item normal;
   4750     struct nk_style_item hover;
   4751     struct nk_style_item active;
   4752     struct nk_color border_color;
   4753 
   4754     /* text */
   4755     struct nk_color text_background;
   4756     struct nk_color text_normal;
   4757     struct nk_color text_hover;
   4758     struct nk_color text_active;
   4759     nk_flags text_alignment;
   4760 
   4761     /* properties */
   4762     float border;
   4763     float rounding;
   4764     struct nk_vec2 padding;
   4765     struct nk_vec2 image_padding;
   4766     struct nk_vec2 touch_padding;
   4767 
   4768     /* optional user callbacks */
   4769     nk_handle userdata;
   4770     void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata);
   4771     void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
   4772 };
   4773 
   4774 struct nk_style_toggle {
   4775     /* background */
   4776     struct nk_style_item normal;
   4777     struct nk_style_item hover;
   4778     struct nk_style_item active;
   4779     struct nk_color border_color;
   4780 
   4781     /* cursor */
   4782     struct nk_style_item cursor_normal;
   4783     struct nk_style_item cursor_hover;
   4784 
   4785     /* text */
   4786     struct nk_color text_normal;
   4787     struct nk_color text_hover;
   4788     struct nk_color text_active;
   4789     struct nk_color text_background;
   4790     nk_flags text_alignment;
   4791 
   4792     /* properties */
   4793     struct nk_vec2 padding;
   4794     struct nk_vec2 touch_padding;
   4795     float spacing;
   4796     float border;
   4797 
   4798     /* optional user callbacks */
   4799     nk_handle userdata;
   4800     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   4801     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   4802 };
   4803 
   4804 struct nk_style_selectable {
   4805     /* background (inactive) */
   4806     struct nk_style_item normal;
   4807     struct nk_style_item hover;
   4808     struct nk_style_item pressed;
   4809 
   4810     /* background (active) */
   4811     struct nk_style_item normal_active;
   4812     struct nk_style_item hover_active;
   4813     struct nk_style_item pressed_active;
   4814 
   4815     /* text color (inactive) */
   4816     struct nk_color text_normal;
   4817     struct nk_color text_hover;
   4818     struct nk_color text_pressed;
   4819 
   4820     /* text color (active) */
   4821     struct nk_color text_normal_active;
   4822     struct nk_color text_hover_active;
   4823     struct nk_color text_pressed_active;
   4824     struct nk_color text_background;
   4825     nk_flags text_alignment;
   4826 
   4827     /* properties */
   4828     float rounding;
   4829     struct nk_vec2 padding;
   4830     struct nk_vec2 touch_padding;
   4831     struct nk_vec2 image_padding;
   4832 
   4833     /* optional user callbacks */
   4834     nk_handle userdata;
   4835     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   4836     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   4837 };
   4838 
   4839 struct nk_style_slider {
   4840     /* background */
   4841     struct nk_style_item normal;
   4842     struct nk_style_item hover;
   4843     struct nk_style_item active;
   4844     struct nk_color border_color;
   4845 
   4846     /* background bar */
   4847     struct nk_color bar_normal;
   4848     struct nk_color bar_hover;
   4849     struct nk_color bar_active;
   4850     struct nk_color bar_filled;
   4851 
   4852     /* cursor */
   4853     struct nk_style_item cursor_normal;
   4854     struct nk_style_item cursor_hover;
   4855     struct nk_style_item cursor_active;
   4856 
   4857     /* properties */
   4858     float border;
   4859     float rounding;
   4860     float bar_height;
   4861     struct nk_vec2 padding;
   4862     struct nk_vec2 spacing;
   4863     struct nk_vec2 cursor_size;
   4864 
   4865     /* optional buttons */
   4866     int show_buttons;
   4867     struct nk_style_button inc_button;
   4868     struct nk_style_button dec_button;
   4869     enum nk_symbol_type inc_symbol;
   4870     enum nk_symbol_type dec_symbol;
   4871 
   4872     /* optional user callbacks */
   4873     nk_handle userdata;
   4874     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   4875     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   4876 };
   4877 
   4878 struct nk_style_progress {
   4879     /* background */
   4880     struct nk_style_item normal;
   4881     struct nk_style_item hover;
   4882     struct nk_style_item active;
   4883     struct nk_color border_color;
   4884 
   4885     /* cursor */
   4886     struct nk_style_item cursor_normal;
   4887     struct nk_style_item cursor_hover;
   4888     struct nk_style_item cursor_active;
   4889     struct nk_color cursor_border_color;
   4890 
   4891     /* properties */
   4892     float rounding;
   4893     float border;
   4894     float cursor_border;
   4895     float cursor_rounding;
   4896     struct nk_vec2 padding;
   4897 
   4898     /* optional user callbacks */
   4899     nk_handle userdata;
   4900     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   4901     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   4902 };
   4903 
   4904 struct nk_style_scrollbar {
   4905     /* background */
   4906     struct nk_style_item normal;
   4907     struct nk_style_item hover;
   4908     struct nk_style_item active;
   4909     struct nk_color border_color;
   4910 
   4911     /* cursor */
   4912     struct nk_style_item cursor_normal;
   4913     struct nk_style_item cursor_hover;
   4914     struct nk_style_item cursor_active;
   4915     struct nk_color cursor_border_color;
   4916 
   4917     /* properties */
   4918     float border;
   4919     float rounding;
   4920     float border_cursor;
   4921     float rounding_cursor;
   4922     struct nk_vec2 padding;
   4923 
   4924     /* optional buttons */
   4925     int show_buttons;
   4926     struct nk_style_button inc_button;
   4927     struct nk_style_button dec_button;
   4928     enum nk_symbol_type inc_symbol;
   4929     enum nk_symbol_type dec_symbol;
   4930 
   4931     /* optional user callbacks */
   4932     nk_handle userdata;
   4933     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   4934     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   4935 };
   4936 
   4937 struct nk_style_edit {
   4938     /* background */
   4939     struct nk_style_item normal;
   4940     struct nk_style_item hover;
   4941     struct nk_style_item active;
   4942     struct nk_color border_color;
   4943     struct nk_style_scrollbar scrollbar;
   4944 
   4945     /* cursor  */
   4946     struct nk_color cursor_normal;
   4947     struct nk_color cursor_hover;
   4948     struct nk_color cursor_text_normal;
   4949     struct nk_color cursor_text_hover;
   4950 
   4951     /* text (unselected) */
   4952     struct nk_color text_normal;
   4953     struct nk_color text_hover;
   4954     struct nk_color text_active;
   4955 
   4956     /* text (selected) */
   4957     struct nk_color selected_normal;
   4958     struct nk_color selected_hover;
   4959     struct nk_color selected_text_normal;
   4960     struct nk_color selected_text_hover;
   4961 
   4962     /* properties */
   4963     float border;
   4964     float rounding;
   4965     float cursor_size;
   4966     struct nk_vec2 scrollbar_size;
   4967     struct nk_vec2 padding;
   4968     float row_padding;
   4969 };
   4970 
   4971 struct nk_style_property {
   4972     /* background */
   4973     struct nk_style_item normal;
   4974     struct nk_style_item hover;
   4975     struct nk_style_item active;
   4976     struct nk_color border_color;
   4977 
   4978     /* text */
   4979     struct nk_color label_normal;
   4980     struct nk_color label_hover;
   4981     struct nk_color label_active;
   4982 
   4983     /* symbols */
   4984     enum nk_symbol_type sym_left;
   4985     enum nk_symbol_type sym_right;
   4986 
   4987     /* properties */
   4988     float border;
   4989     float rounding;
   4990     struct nk_vec2 padding;
   4991 
   4992     struct nk_style_edit edit;
   4993     struct nk_style_button inc_button;
   4994     struct nk_style_button dec_button;
   4995 
   4996     /* optional user callbacks */
   4997     nk_handle userdata;
   4998     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
   4999     void(*draw_end)(struct nk_command_buffer*, nk_handle);
   5000 };
   5001 
   5002 struct nk_style_chart {
   5003     /* colors */
   5004     struct nk_style_item background;
   5005     struct nk_color border_color;
   5006     struct nk_color selected_color;
   5007     struct nk_color color;
   5008 
   5009     /* properties */
   5010     float border;
   5011     float rounding;
   5012     struct nk_vec2 padding;
   5013 };
   5014 
   5015 struct nk_style_combo {
   5016     /* background */
   5017     struct nk_style_item normal;
   5018     struct nk_style_item hover;
   5019     struct nk_style_item active;
   5020     struct nk_color border_color;
   5021 
   5022     /* label */
   5023     struct nk_color label_normal;
   5024     struct nk_color label_hover;
   5025     struct nk_color label_active;
   5026 
   5027     /* symbol */
   5028     struct nk_color symbol_normal;
   5029     struct nk_color symbol_hover;
   5030     struct nk_color symbol_active;
   5031 
   5032     /* button */
   5033     struct nk_style_button button;
   5034     enum nk_symbol_type sym_normal;
   5035     enum nk_symbol_type sym_hover;
   5036     enum nk_symbol_type sym_active;
   5037 
   5038     /* properties */
   5039     float border;
   5040     float rounding;
   5041     struct nk_vec2 content_padding;
   5042     struct nk_vec2 button_padding;
   5043     struct nk_vec2 spacing;
   5044 };
   5045 
   5046 struct nk_style_tab {
   5047     /* background */
   5048     struct nk_style_item background;
   5049     struct nk_color border_color;
   5050     struct nk_color text;
   5051 
   5052     /* button */
   5053     struct nk_style_button tab_maximize_button;
   5054     struct nk_style_button tab_minimize_button;
   5055     struct nk_style_button node_maximize_button;
   5056     struct nk_style_button node_minimize_button;
   5057     enum nk_symbol_type sym_minimize;
   5058     enum nk_symbol_type sym_maximize;
   5059 
   5060     /* properties */
   5061     float border;
   5062     float rounding;
   5063     float indent;
   5064     struct nk_vec2 padding;
   5065     struct nk_vec2 spacing;
   5066 };
   5067 
   5068 enum nk_style_header_align {
   5069     NK_HEADER_LEFT,
   5070     NK_HEADER_RIGHT
   5071 };
   5072 struct nk_style_window_header {
   5073     /* background */
   5074     struct nk_style_item normal;
   5075     struct nk_style_item hover;
   5076     struct nk_style_item active;
   5077 
   5078     /* button */
   5079     struct nk_style_button close_button;
   5080     struct nk_style_button minimize_button;
   5081     enum nk_symbol_type close_symbol;
   5082     enum nk_symbol_type minimize_symbol;
   5083     enum nk_symbol_type maximize_symbol;
   5084 
   5085     /* title */
   5086     struct nk_color label_normal;
   5087     struct nk_color label_hover;
   5088     struct nk_color label_active;
   5089 
   5090     /* properties */
   5091     enum nk_style_header_align align;
   5092     struct nk_vec2 padding;
   5093     struct nk_vec2 label_padding;
   5094     struct nk_vec2 spacing;
   5095 };
   5096 
   5097 struct nk_style_window {
   5098     struct nk_style_window_header header;
   5099     struct nk_style_item fixed_background;
   5100     struct nk_color background;
   5101 
   5102     struct nk_color border_color;
   5103     struct nk_color popup_border_color;
   5104     struct nk_color combo_border_color;
   5105     struct nk_color contextual_border_color;
   5106     struct nk_color menu_border_color;
   5107     struct nk_color group_border_color;
   5108     struct nk_color tooltip_border_color;
   5109     struct nk_style_item scaler;
   5110 
   5111     float border;
   5112     float combo_border;
   5113     float contextual_border;
   5114     float menu_border;
   5115     float group_border;
   5116     float tooltip_border;
   5117     float popup_border;
   5118     float min_row_height_padding;
   5119 
   5120     float rounding;
   5121     struct nk_vec2 spacing;
   5122     struct nk_vec2 scrollbar_size;
   5123     struct nk_vec2 min_size;
   5124 
   5125     struct nk_vec2 padding;
   5126     struct nk_vec2 group_padding;
   5127     struct nk_vec2 popup_padding;
   5128     struct nk_vec2 combo_padding;
   5129     struct nk_vec2 contextual_padding;
   5130     struct nk_vec2 menu_padding;
   5131     struct nk_vec2 tooltip_padding;
   5132 };
   5133 
   5134 struct nk_style {
   5135     const struct nk_user_font *font;
   5136     const struct nk_cursor *cursors[NK_CURSOR_COUNT];
   5137     const struct nk_cursor *cursor_active;
   5138     struct nk_cursor *cursor_last;
   5139     int cursor_visible;
   5140 
   5141     struct nk_style_text text;
   5142     struct nk_style_button button;
   5143     struct nk_style_button contextual_button;
   5144     struct nk_style_button menu_button;
   5145     struct nk_style_toggle option;
   5146     struct nk_style_toggle checkbox;
   5147     struct nk_style_selectable selectable;
   5148     struct nk_style_slider slider;
   5149     struct nk_style_progress progress;
   5150     struct nk_style_property property;
   5151     struct nk_style_edit edit;
   5152     struct nk_style_chart chart;
   5153     struct nk_style_scrollbar scrollh;
   5154     struct nk_style_scrollbar scrollv;
   5155     struct nk_style_tab tab;
   5156     struct nk_style_combo combo;
   5157     struct nk_style_window window;
   5158 };
   5159 
   5160 NK_API struct nk_style_item nk_style_item_image(struct nk_image img);
   5161 NK_API struct nk_style_item nk_style_item_color(struct nk_color);
   5162 NK_API struct nk_style_item nk_style_item_hide(void);
   5163 
   5164 /*==============================================================
   5165  *                          PANEL
   5166  * =============================================================*/
   5167 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
   5168 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
   5169 #endif
   5170 #ifndef NK_CHART_MAX_SLOT
   5171 #define NK_CHART_MAX_SLOT 4
   5172 #endif
   5173 
   5174 enum nk_panel_type {
   5175     NK_PANEL_NONE       = 0,
   5176     NK_PANEL_WINDOW     = NK_FLAG(0),
   5177     NK_PANEL_GROUP      = NK_FLAG(1),
   5178     NK_PANEL_POPUP      = NK_FLAG(2),
   5179     NK_PANEL_CONTEXTUAL = NK_FLAG(4),
   5180     NK_PANEL_COMBO      = NK_FLAG(5),
   5181     NK_PANEL_MENU       = NK_FLAG(6),
   5182     NK_PANEL_TOOLTIP    = NK_FLAG(7)
   5183 };
   5184 enum nk_panel_set {
   5185     NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP,
   5186     NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP,
   5187     NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP
   5188 };
   5189 
   5190 struct nk_chart_slot {
   5191     enum nk_chart_type type;
   5192     struct nk_color color;
   5193     struct nk_color highlight;
   5194     float min, max, range;
   5195     int count;
   5196     struct nk_vec2 last;
   5197     int index;
   5198 };
   5199 
   5200 struct nk_chart {
   5201     int slot;
   5202     float x, y, w, h;
   5203     struct nk_chart_slot slots[NK_CHART_MAX_SLOT];
   5204 };
   5205 
   5206 enum nk_panel_row_layout_type {
   5207     NK_LAYOUT_DYNAMIC_FIXED = 0,
   5208     NK_LAYOUT_DYNAMIC_ROW,
   5209     NK_LAYOUT_DYNAMIC_FREE,
   5210     NK_LAYOUT_DYNAMIC,
   5211     NK_LAYOUT_STATIC_FIXED,
   5212     NK_LAYOUT_STATIC_ROW,
   5213     NK_LAYOUT_STATIC_FREE,
   5214     NK_LAYOUT_STATIC,
   5215     NK_LAYOUT_TEMPLATE,
   5216     NK_LAYOUT_COUNT
   5217 };
   5218 struct nk_row_layout {
   5219     enum nk_panel_row_layout_type type;
   5220     int index;
   5221     float height;
   5222     float min_height;
   5223     int columns;
   5224     const float *ratio;
   5225     float item_width;
   5226     float item_height;
   5227     float item_offset;
   5228     float filled;
   5229     struct nk_rect item;
   5230     int tree_depth;
   5231     float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS];
   5232 };
   5233 
   5234 struct nk_popup_buffer {
   5235     nk_size begin;
   5236     nk_size parent;
   5237     nk_size last;
   5238     nk_size end;
   5239     int active;
   5240 };
   5241 
   5242 struct nk_menu_state {
   5243     float x, y, w, h;
   5244     struct nk_scroll offset;
   5245 };
   5246 
   5247 struct nk_panel {
   5248     enum nk_panel_type type;
   5249     nk_flags flags;
   5250     struct nk_rect bounds;
   5251     nk_uint *offset_x;
   5252     nk_uint *offset_y;
   5253     float at_x, at_y, max_x;
   5254     float footer_height;
   5255     float header_height;
   5256     float border;
   5257     unsigned int has_scrolling;
   5258     struct nk_rect clip;
   5259     struct nk_menu_state menu;
   5260     struct nk_row_layout row;
   5261     struct nk_chart chart;
   5262     struct nk_command_buffer *buffer;
   5263     struct nk_panel *parent;
   5264 };
   5265 
   5266 /*==============================================================
   5267  *                          WINDOW
   5268  * =============================================================*/
   5269 #ifndef NK_WINDOW_MAX_NAME
   5270 #define NK_WINDOW_MAX_NAME 64
   5271 #endif
   5272 
   5273 struct nk_table;
   5274 enum nk_window_flags {
   5275     NK_WINDOW_PRIVATE       = NK_FLAG(11),
   5276     NK_WINDOW_DYNAMIC       = NK_WINDOW_PRIVATE,
   5277     /* special window type growing up in height while being filled to a certain maximum height */
   5278     NK_WINDOW_ROM           = NK_FLAG(12),
   5279     /* sets window widgets into a read only mode and does not allow input changes */
   5280     NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT,
   5281     /* prevents all interaction caused by input to either window or widgets inside */
   5282     NK_WINDOW_HIDDEN        = NK_FLAG(13),
   5283     /* Hides window and stops any window interaction and drawing */
   5284     NK_WINDOW_CLOSED        = NK_FLAG(14),
   5285     /* Directly closes and frees the window at the end of the frame */
   5286     NK_WINDOW_MINIMIZED     = NK_FLAG(15),
   5287     /* marks the window as minimized */
   5288     NK_WINDOW_REMOVE_ROM    = NK_FLAG(16)
   5289     /* Removes read only mode at the end of the window */
   5290 };
   5291 
   5292 struct nk_popup_state {
   5293     struct nk_window *win;
   5294     enum nk_panel_type type;
   5295     struct nk_popup_buffer buf;
   5296     nk_hash name;
   5297     int active;
   5298     unsigned combo_count;
   5299     unsigned con_count, con_old;
   5300     unsigned active_con;
   5301     struct nk_rect header;
   5302 };
   5303 
   5304 struct nk_edit_state {
   5305     nk_hash name;
   5306     unsigned int seq;
   5307     unsigned int old;
   5308     int active, prev;
   5309     int cursor;
   5310     int sel_start;
   5311     int sel_end;
   5312     struct nk_scroll scrollbar;
   5313     unsigned char mode;
   5314     unsigned char single_line;
   5315 };
   5316 
   5317 struct nk_property_state {
   5318     int active, prev;
   5319     char buffer[NK_MAX_NUMBER_BUFFER];
   5320     int length;
   5321     int cursor;
   5322     int select_start;
   5323     int select_end;
   5324     nk_hash name;
   5325     unsigned int seq;
   5326     unsigned int old;
   5327     int state;
   5328 };
   5329 
   5330 struct nk_window {
   5331     unsigned int seq;
   5332     nk_hash name;
   5333     char name_string[NK_WINDOW_MAX_NAME];
   5334     nk_flags flags;
   5335 
   5336     struct nk_rect bounds;
   5337     struct nk_scroll scrollbar;
   5338     struct nk_command_buffer buffer;
   5339     struct nk_panel *layout;
   5340     float scrollbar_hiding_timer;
   5341 
   5342     /* persistent widget state */
   5343     struct nk_property_state property;
   5344     struct nk_popup_state popup;
   5345     struct nk_edit_state edit;
   5346     unsigned int scrolled;
   5347 
   5348     struct nk_table *tables;
   5349     unsigned int table_count;
   5350 
   5351     /* window list hooks */
   5352     struct nk_window *next;
   5353     struct nk_window *prev;
   5354     struct nk_window *parent;
   5355 };
   5356 
   5357 /*==============================================================
   5358  *                          STACK
   5359  * =============================================================*/
   5360 /* The style modifier stack can be used to temporarily change a
   5361  * property inside `nk_style`. For example if you want a special
   5362  * red button you can temporarily push the old button color onto a stack
   5363  * draw the button with a red color and then you just pop the old color
   5364  * back from the stack:
   5365  *
   5366  *      nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
   5367  *      nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
   5368  *      nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
   5369  *      nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
   5370  *
   5371  *      nk_button(...);
   5372  *
   5373  *      nk_style_pop_style_item(ctx);
   5374  *      nk_style_pop_style_item(ctx);
   5375  *      nk_style_pop_style_item(ctx);
   5376  *      nk_style_pop_vec2(ctx);
   5377  *
   5378  * Nuklear has a stack for style_items, float properties, vector properties,
   5379  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
   5380  * which can be changed at compile time.
   5381  */
   5382 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
   5383 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
   5384 #endif
   5385 
   5386 #ifndef NK_FONT_STACK_SIZE
   5387 #define NK_FONT_STACK_SIZE 8
   5388 #endif
   5389 
   5390 #ifndef NK_STYLE_ITEM_STACK_SIZE
   5391 #define NK_STYLE_ITEM_STACK_SIZE 16
   5392 #endif
   5393 
   5394 #ifndef NK_FLOAT_STACK_SIZE
   5395 #define NK_FLOAT_STACK_SIZE 32
   5396 #endif
   5397 
   5398 #ifndef NK_VECTOR_STACK_SIZE
   5399 #define NK_VECTOR_STACK_SIZE 16
   5400 #endif
   5401 
   5402 #ifndef NK_FLAGS_STACK_SIZE
   5403 #define NK_FLAGS_STACK_SIZE 32
   5404 #endif
   5405 
   5406 #ifndef NK_COLOR_STACK_SIZE
   5407 #define NK_COLOR_STACK_SIZE 32
   5408 #endif
   5409 
   5410 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
   5411     struct nk_config_stack_##name##_element {\
   5412         prefix##_##type *address;\
   5413         prefix##_##type old_value;\
   5414     }
   5415 #define NK_CONFIG_STACK(type,size)\
   5416     struct nk_config_stack_##type {\
   5417         int head;\
   5418         struct nk_config_stack_##type##_element elements[size];\
   5419     }
   5420 
   5421 #define nk_float float
   5422 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
   5423 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
   5424 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
   5425 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags);
   5426 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
   5427 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
   5428 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
   5429 
   5430 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE);
   5431 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE);
   5432 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE);
   5433 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE);
   5434 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE);
   5435 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE);
   5436 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE);
   5437 
   5438 struct nk_configuration_stacks {
   5439     struct nk_config_stack_style_item style_items;
   5440     struct nk_config_stack_float floats;
   5441     struct nk_config_stack_vec2 vectors;
   5442     struct nk_config_stack_flags flags;
   5443     struct nk_config_stack_color colors;
   5444     struct nk_config_stack_user_font fonts;
   5445     struct nk_config_stack_button_behavior button_behaviors;
   5446 };
   5447 
   5448 /*==============================================================
   5449  *                          CONTEXT
   5450  * =============================================================*/
   5451 #define NK_VALUE_PAGE_CAPACITY \
   5452     (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
   5453 
   5454 struct nk_table {
   5455     unsigned int seq;
   5456     unsigned int size;
   5457     nk_hash keys[NK_VALUE_PAGE_CAPACITY];
   5458     nk_uint values[NK_VALUE_PAGE_CAPACITY];
   5459     struct nk_table *next, *prev;
   5460 };
   5461 
   5462 union nk_page_data {
   5463     struct nk_table tbl;
   5464     struct nk_panel pan;
   5465     struct nk_window win;
   5466 };
   5467 
   5468 struct nk_page_element {
   5469     union nk_page_data data;
   5470     struct nk_page_element *next;
   5471     struct nk_page_element *prev;
   5472 };
   5473 
   5474 struct nk_page {
   5475     unsigned int size;
   5476     struct nk_page *next;
   5477     struct nk_page_element win[1];
   5478 };
   5479 
   5480 struct nk_pool {
   5481     struct nk_allocator alloc;
   5482     enum nk_allocation_type type;
   5483     unsigned int page_count;
   5484     struct nk_page *pages;
   5485     struct nk_page_element *freelist;
   5486     unsigned capacity;
   5487     nk_size size;
   5488     nk_size cap;
   5489 };
   5490 
   5491 struct nk_context {
   5492 /* public: can be accessed freely */
   5493     struct nk_input input;
   5494     struct nk_style style;
   5495     struct nk_buffer memory;
   5496     struct nk_clipboard clip;
   5497     nk_flags last_widget_state;
   5498     enum nk_button_behavior button_behavior;
   5499     struct nk_configuration_stacks stacks;
   5500     float delta_time_seconds;
   5501 
   5502 /* private:
   5503     should only be accessed if you
   5504     know what you are doing */
   5505 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   5506     struct nk_draw_list draw_list;
   5507 #endif
   5508 #ifdef NK_INCLUDE_COMMAND_USERDATA
   5509     nk_handle userdata;
   5510 #endif
   5511     /* text editor objects are quite big because of an internal
   5512      * undo/redo stack. Therefore it does not make sense to have one for
   5513      * each window for temporary use cases, so I only provide *one* instance
   5514      * for all windows. This works because the content is cleared anyway */
   5515     struct nk_text_edit text_edit;
   5516     /* draw buffer used for overlay drawing operation like cursor */
   5517     struct nk_command_buffer overlay;
   5518 
   5519     /* windows */
   5520     int build;
   5521     int use_pool;
   5522     struct nk_pool pool;
   5523     struct nk_window *begin;
   5524     struct nk_window *end;
   5525     struct nk_window *active;
   5526     struct nk_window *current;
   5527     struct nk_page_element *freelist;
   5528     unsigned int count;
   5529     unsigned int seq;
   5530 };
   5531 
   5532 /* ==============================================================
   5533  *                          MATH
   5534  * =============================================================== */
   5535 #define NK_PI 3.141592654f
   5536 #define NK_UTF_INVALID 0xFFFD
   5537 #define NK_MAX_FLOAT_PRECISION 2
   5538 
   5539 #define NK_UNUSED(x) ((void)(x))
   5540 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
   5541 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
   5542 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
   5543 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
   5544 #define NK_INBOX(px, py, x, y, w, h)\
   5545     (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
   5546 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
   5547     (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
   5548 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
   5549     (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
   5550 
   5551 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
   5552 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
   5553 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
   5554 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
   5555 
   5556 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
   5557 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
   5558 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
   5559 
   5560 /* ==============================================================
   5561  *                          ALIGNMENT
   5562  * =============================================================== */
   5563 /* Pointer to Integer type conversion for pointer alignment */
   5564 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
   5565 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
   5566 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
   5567 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
   5568 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
   5569 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
   5570 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
   5571 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
   5572 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
   5573 #else /* generates warning but works */
   5574 # define NK_UINT_TO_PTR(x) ((void*)(x))
   5575 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
   5576 #endif
   5577 
   5578 #define NK_ALIGN_PTR(x, mask)\
   5579     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
   5580 #define NK_ALIGN_PTR_BACK(x, mask)\
   5581     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
   5582 
   5583 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
   5584 #define NK_CONTAINER_OF(ptr,type,member)\
   5585     (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
   5586 
   5587 #ifdef __cplusplus
   5588 }
   5589 #endif
   5590 
   5591 #ifdef __cplusplus
   5592 template<typename T> struct nk_alignof;
   5593 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
   5594 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
   5595 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
   5596     diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
   5597 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
   5598 #elif defined(_MSC_VER)
   5599 #define NK_ALIGNOF(t) (__alignof(t))
   5600 #else
   5601 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
   5602 #endif
   5603 
   5604 #endif /* NK_NUKLEAR_H_ */
   5605 
   5606 
   5607 #ifdef NK_IMPLEMENTATION
   5608 
   5609 #ifndef NK_INTERNAL_H
   5610 #define NK_INTERNAL_H
   5611 
   5612 #ifndef NK_POOL_DEFAULT_CAPACITY
   5613 #define NK_POOL_DEFAULT_CAPACITY 16
   5614 #endif
   5615 
   5616 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
   5617 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
   5618 #endif
   5619 
   5620 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
   5621 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
   5622 #endif
   5623 
   5624 /* standard library headers */
   5625 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   5626 #include <stdlib.h> /* malloc, free */
   5627 #endif
   5628 #ifdef NK_INCLUDE_STANDARD_IO
   5629 #include <stdio.h> /* fopen, fclose,... */
   5630 #endif
   5631 #ifndef NK_ASSERT
   5632 #include <assert.h>
   5633 #define NK_ASSERT(expr) assert(expr)
   5634 #endif
   5635 
   5636 #ifndef NK_MEMSET
   5637 #define NK_MEMSET nk_memset
   5638 #endif
   5639 #ifndef NK_MEMCPY
   5640 #define NK_MEMCPY nk_memcopy
   5641 #endif
   5642 #ifndef NK_SQRT
   5643 #define NK_SQRT nk_sqrt
   5644 #endif
   5645 #ifndef NK_SIN
   5646 #define NK_SIN nk_sin
   5647 #endif
   5648 #ifndef NK_COS
   5649 #define NK_COS nk_cos
   5650 #endif
   5651 #ifndef NK_STRTOD
   5652 #define NK_STRTOD nk_strtod
   5653 #endif
   5654 #ifndef NK_DTOA
   5655 #define NK_DTOA nk_dtoa
   5656 #endif
   5657 
   5658 #define NK_DEFAULT (-1)
   5659 
   5660 #ifndef NK_VSNPRINTF
   5661 /* If your compiler does support `vsnprintf` I would highly recommend
   5662  * defining this to vsnprintf instead since `vsprintf` is basically
   5663  * unbelievable unsafe and should *NEVER* be used. But I have to support
   5664  * it since C89 only provides this unsafe version. */
   5665   #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
   5666       (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
   5667       (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
   5668       (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
   5669        defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
   5670       #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
   5671   #else
   5672     #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
   5673   #endif
   5674 #endif
   5675 
   5676 #define NK_SCHAR_MIN (-127)
   5677 #define NK_SCHAR_MAX 127
   5678 #define NK_UCHAR_MIN 0
   5679 #define NK_UCHAR_MAX 256
   5680 #define NK_SSHORT_MIN (-32767)
   5681 #define NK_SSHORT_MAX 32767
   5682 #define NK_USHORT_MIN 0
   5683 #define NK_USHORT_MAX 65535
   5684 #define NK_SINT_MIN (-2147483647)
   5685 #define NK_SINT_MAX 2147483647
   5686 #define NK_UINT_MIN 0
   5687 #define NK_UINT_MAX 4294967295u
   5688 
   5689 /* Make sure correct type size:
   5690  * This will fire with a negative subscript error if the type sizes
   5691  * are set incorrectly by the compiler, and compile out if not */
   5692 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
   5693 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
   5694 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
   5695 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
   5696 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
   5697 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
   5698 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
   5699 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
   5700 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
   5701 
   5702 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
   5703 #define NK_FLOAT_PRECISION 0.00000000000001
   5704 
   5705 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
   5706 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
   5707 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
   5708 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
   5709 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
   5710 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
   5711 
   5712 /* widget */
   5713 #define nk_widget_state_reset(s)\
   5714     if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
   5715         (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
   5716     else (*(s)) = NK_WIDGET_STATE_INACTIVE;
   5717 
   5718 /* math */
   5719 NK_LIB float nk_inv_sqrt(float n);
   5720 NK_LIB float nk_sqrt(float x);
   5721 NK_LIB float nk_sin(float x);
   5722 NK_LIB float nk_cos(float x);
   5723 NK_LIB nk_uint nk_round_up_pow2(nk_uint v);
   5724 NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount);
   5725 NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad);
   5726 NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1);
   5727 NK_LIB double nk_pow(double x, int n);
   5728 NK_LIB int nk_ifloord(double x);
   5729 NK_LIB int nk_ifloorf(float x);
   5730 NK_LIB int nk_iceilf(float x);
   5731 NK_LIB int nk_log10(double n);
   5732 
   5733 /* util */
   5734 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
   5735 NK_LIB int nk_is_lower(int c);
   5736 NK_LIB int nk_is_upper(int c);
   5737 NK_LIB int nk_to_upper(int c);
   5738 NK_LIB int nk_to_lower(int c);
   5739 NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n);
   5740 NK_LIB void nk_memset(void *ptr, int c0, nk_size size);
   5741 NK_LIB void nk_zero(void *ptr, nk_size size);
   5742 NK_LIB char *nk_itoa(char *s, long n);
   5743 NK_LIB int nk_string_float_limit(char *string, int prec);
   5744 NK_LIB char *nk_dtoa(char *s, double n);
   5745 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);
   5746 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);
   5747 #ifdef NK_INCLUDE_STANDARD_VARARGS
   5748 NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args);
   5749 #endif
   5750 #ifdef NK_INCLUDE_STANDARD_IO
   5751 NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc);
   5752 #endif
   5753 
   5754 /* buffer */
   5755 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   5756 NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size);
   5757 NK_LIB void nk_mfree(nk_handle unused, void *ptr);
   5758 #endif
   5759 NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type);
   5760 NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align);
   5761 NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size);
   5762 
   5763 /* draw */
   5764 NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip);
   5765 NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b);
   5766 NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size);
   5767 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);
   5768 
   5769 /* buffering */
   5770 NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
   5771 NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win);
   5772 NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win);
   5773 NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*);
   5774 NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
   5775 NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w);
   5776 NK_LIB void nk_build(struct nk_context *ctx);
   5777 
   5778 /* text editor */
   5779 NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter);
   5780 NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
   5781 NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
   5782 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);
   5783 
   5784 /* window */
   5785 enum nk_window_insert_location {
   5786     NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
   5787     NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
   5788 };
   5789 NK_LIB void *nk_create_window(struct nk_context *ctx);
   5790 NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*);
   5791 NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win);
   5792 NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name);
   5793 NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc);
   5794 
   5795 /* pool */
   5796 NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity);
   5797 NK_LIB void nk_pool_free(struct nk_pool *pool);
   5798 NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size);
   5799 NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool);
   5800 
   5801 /* page-element */
   5802 NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx);
   5803 NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem);
   5804 NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem);
   5805 
   5806 /* table */
   5807 NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx);
   5808 NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
   5809 NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
   5810 NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl);
   5811 NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value);
   5812 NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name);
   5813 
   5814 /* panel */
   5815 NK_LIB void *nk_create_panel(struct nk_context *ctx);
   5816 NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan);
   5817 NK_LIB int nk_panel_has_header(nk_flags flags, const char *title);
   5818 NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type);
   5819 NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type);
   5820 NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type);
   5821 NK_LIB int nk_panel_is_sub(enum nk_panel_type type);
   5822 NK_LIB int nk_panel_is_nonblock(enum nk_panel_type type);
   5823 NK_LIB int nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type);
   5824 NK_LIB void nk_panel_end(struct nk_context *ctx);
   5825 
   5826 /* layout */
   5827 NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns);
   5828 NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols);
   5829 NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width);
   5830 NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win);
   5831 NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify);
   5832 NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx);
   5833 NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx);
   5834 
   5835 /* popup */
   5836 NK_LIB int nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type);
   5837 
   5838 /* text */
   5839 struct nk_text {
   5840     struct nk_vec2 padding;
   5841     struct nk_color background;
   5842     struct nk_color text;
   5843 };
   5844 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);
   5845 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);
   5846 
   5847 /* button */
   5848 NK_LIB int nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior);
   5849 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);
   5850 NK_LIB int 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);
   5851 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);
   5852 NK_LIB int 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);
   5853 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);
   5854 NK_LIB int 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);
   5855 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);
   5856 NK_LIB int 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);
   5857 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);
   5858 NK_LIB int 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);
   5859 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);
   5860 NK_LIB int 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);
   5861 
   5862 /* toggle */
   5863 enum nk_toggle_type {
   5864     NK_TOGGLE_CHECK,
   5865     NK_TOGGLE_OPTION
   5866 };
   5867 NK_LIB int nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, int active);
   5868 NK_LIB void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int 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);
   5869 NK_LIB void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int 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);
   5870 NK_LIB int nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, int *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);
   5871 
   5872 /* progress */
   5873 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, int modifiable);
   5874 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);
   5875 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, int modifiable, const struct nk_style_progress *style, struct nk_input *in);
   5876 
   5877 /* slider */
   5878 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);
   5879 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);
   5880 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);
   5881 
   5882 /* scrollbar */
   5883 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);
   5884 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);
   5885 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);
   5886 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);
   5887 
   5888 /* selectable */
   5889 NK_LIB void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, int 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);
   5890 NK_LIB int nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
   5891 NK_LIB int nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
   5892 
   5893 /* edit */
   5894 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, int is_selected);
   5895 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);
   5896 
   5897 /* color-picker */
   5898 NK_LIB int 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);
   5899 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);
   5900 NK_LIB int 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);
   5901 
   5902 /* property */
   5903 enum nk_property_status {
   5904     NK_PROPERTY_DEFAULT,
   5905     NK_PROPERTY_EDIT,
   5906     NK_PROPERTY_DRAG
   5907 };
   5908 enum nk_property_filter {
   5909     NK_FILTER_INT,
   5910     NK_FILTER_FLOAT
   5911 };
   5912 enum nk_property_kind {
   5913     NK_PROPERTY_INT,
   5914     NK_PROPERTY_FLOAT,
   5915     NK_PROPERTY_DOUBLE
   5916 };
   5917 union nk_property {
   5918     int i;
   5919     float f;
   5920     double d;
   5921 };
   5922 struct nk_property_variant {
   5923     enum nk_property_kind kind;
   5924     union nk_property value;
   5925     union nk_property min_value;
   5926     union nk_property max_value;
   5927     union nk_property step;
   5928 };
   5929 NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step);
   5930 NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step);
   5931 NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step);
   5932 
   5933 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);
   5934 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);
   5935 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);
   5936 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);
   5937 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);
   5938 
   5939 #endif
   5940 
   5941 
   5942 
   5943 
   5944 
   5945 /* ===============================================================
   5946  *
   5947  *                              MATH
   5948  *
   5949  * ===============================================================*/
   5950 /*  Since nuklear is supposed to work on all systems providing floating point
   5951     math without any dependencies I also had to implement my own math functions
   5952     for sqrt, sin and cos. Since the actual highly accurate implementations for
   5953     the standard library functions are quite complex and I do not need high
   5954     precision for my use cases I use approximations.
   5955 
   5956     Sqrt
   5957     ----
   5958     For square root nuklear uses the famous fast inverse square root:
   5959     https://en.wikipedia.org/wiki/Fast_inverse_square_root with
   5960     slightly tweaked magic constant. While on today's hardware it is
   5961     probably not faster it is still fast and accurate enough for
   5962     nuklear's use cases. IMPORTANT: this requires float format IEEE 754
   5963 
   5964     Sine/Cosine
   5965     -----------
   5966     All constants inside both function are generated Remez's minimax
   5967     approximations for value range 0...2*PI. The reason why I decided to
   5968     approximate exactly that range is that nuklear only needs sine and
   5969     cosine to generate circles which only requires that exact range.
   5970     In addition I used Remez instead of Taylor for additional precision:
   5971     www.lolengine.net/blog/2011/12/21/better-function-approximations.
   5972 
   5973     The tool I used to generate constants for both sine and cosine
   5974     (it can actually approximate a lot more functions) can be
   5975     found here: www.lolengine.net/wiki/oss/lolremez
   5976 */
   5977 NK_LIB float
   5978 nk_inv_sqrt(float n)
   5979 {
   5980     float x2;
   5981     const float threehalfs = 1.5f;
   5982     union {nk_uint i; float f;} conv = {0};
   5983     conv.f = n;
   5984     x2 = n * 0.5f;
   5985     conv.i = 0x5f375A84 - (conv.i >> 1);
   5986     conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
   5987     return conv.f;
   5988 }
   5989 NK_LIB float
   5990 nk_sqrt(float x)
   5991 {
   5992     return x * nk_inv_sqrt(x);
   5993 }
   5994 NK_LIB float
   5995 nk_sin(float x)
   5996 {
   5997     NK_STORAGE const float a0 = +1.91059300966915117e-31f;
   5998     NK_STORAGE const float a1 = +1.00086760103908896f;
   5999     NK_STORAGE const float a2 = -1.21276126894734565e-2f;
   6000     NK_STORAGE const float a3 = -1.38078780785773762e-1f;
   6001     NK_STORAGE const float a4 = -2.67353392911981221e-2f;
   6002     NK_STORAGE const float a5 = +2.08026600266304389e-2f;
   6003     NK_STORAGE const float a6 = -3.03996055049204407e-3f;
   6004     NK_STORAGE const float a7 = +1.38235642404333740e-4f;
   6005     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
   6006 }
   6007 NK_LIB float
   6008 nk_cos(float x)
   6009 {
   6010     NK_STORAGE const float a0 = +1.00238601909309722f;
   6011     NK_STORAGE const float a1 = -3.81919947353040024e-2f;
   6012     NK_STORAGE const float a2 = -3.94382342128062756e-1f;
   6013     NK_STORAGE const float a3 = -1.18134036025221444e-1f;
   6014     NK_STORAGE const float a4 = +1.07123798512170878e-1f;
   6015     NK_STORAGE const float a5 = -1.86637164165180873e-2f;
   6016     NK_STORAGE const float a6 = +9.90140908664079833e-4f;
   6017     NK_STORAGE const float a7 = -5.23022132118824778e-14f;
   6018     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
   6019 }
   6020 NK_LIB nk_uint
   6021 nk_round_up_pow2(nk_uint v)
   6022 {
   6023     v--;
   6024     v |= v >> 1;
   6025     v |= v >> 2;
   6026     v |= v >> 4;
   6027     v |= v >> 8;
   6028     v |= v >> 16;
   6029     v++;
   6030     return v;
   6031 }
   6032 NK_LIB double
   6033 nk_pow(double x, int n)
   6034 {
   6035     /*  check the sign of n */
   6036     double r = 1;
   6037     int plus = n >= 0;
   6038     n = (plus) ? n : -n;
   6039     while (n > 0) {
   6040         if ((n & 1) == 1)
   6041             r *= x;
   6042         n /= 2;
   6043         x *= x;
   6044     }
   6045     return plus ? r : 1.0 / r;
   6046 }
   6047 NK_LIB int
   6048 nk_ifloord(double x)
   6049 {
   6050     x = (double)((int)x - ((x < 0.0) ? 1 : 0));
   6051     return (int)x;
   6052 }
   6053 NK_LIB int
   6054 nk_ifloorf(float x)
   6055 {
   6056     x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
   6057     return (int)x;
   6058 }
   6059 NK_LIB int
   6060 nk_iceilf(float x)
   6061 {
   6062     if (x >= 0) {
   6063         int i = (int)x;
   6064         return (x > i) ? i+1: i;
   6065     } else {
   6066         int t = (int)x;
   6067         float r = x - (float)t;
   6068         return (r > 0.0f) ? t+1: t;
   6069     }
   6070 }
   6071 NK_LIB int
   6072 nk_log10(double n)
   6073 {
   6074     int neg;
   6075     int ret;
   6076     int exp = 0;
   6077 
   6078     neg = (n < 0) ? 1 : 0;
   6079     ret = (neg) ? (int)-n : (int)n;
   6080     while ((ret / 10) > 0) {
   6081         ret /= 10;
   6082         exp++;
   6083     }
   6084     if (neg) exp = -exp;
   6085     return exp;
   6086 }
   6087 NK_API struct nk_rect
   6088 nk_get_null_rect(void)
   6089 {
   6090     return nk_null_rect;
   6091 }
   6092 NK_API struct nk_rect
   6093 nk_rect(float x, float y, float w, float h)
   6094 {
   6095     struct nk_rect r;
   6096     r.x = x; r.y = y;
   6097     r.w = w; r.h = h;
   6098     return r;
   6099 }
   6100 NK_API struct nk_rect
   6101 nk_recti(int x, int y, int w, int h)
   6102 {
   6103     struct nk_rect r;
   6104     r.x = (float)x;
   6105     r.y = (float)y;
   6106     r.w = (float)w;
   6107     r.h = (float)h;
   6108     return r;
   6109 }
   6110 NK_API struct nk_rect
   6111 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
   6112 {
   6113     return nk_rect(pos.x, pos.y, size.x, size.y);
   6114 }
   6115 NK_API struct nk_rect
   6116 nk_rectv(const float *r)
   6117 {
   6118     return nk_rect(r[0], r[1], r[2], r[3]);
   6119 }
   6120 NK_API struct nk_rect
   6121 nk_rectiv(const int *r)
   6122 {
   6123     return nk_recti(r[0], r[1], r[2], r[3]);
   6124 }
   6125 NK_API struct nk_vec2
   6126 nk_rect_pos(struct nk_rect r)
   6127 {
   6128     struct nk_vec2 ret;
   6129     ret.x = r.x; ret.y = r.y;
   6130     return ret;
   6131 }
   6132 NK_API struct nk_vec2
   6133 nk_rect_size(struct nk_rect r)
   6134 {
   6135     struct nk_vec2 ret;
   6136     ret.x = r.w; ret.y = r.h;
   6137     return ret;
   6138 }
   6139 NK_LIB struct nk_rect
   6140 nk_shrink_rect(struct nk_rect r, float amount)
   6141 {
   6142     struct nk_rect res;
   6143     r.w = NK_MAX(r.w, 2 * amount);
   6144     r.h = NK_MAX(r.h, 2 * amount);
   6145     res.x = r.x + amount;
   6146     res.y = r.y + amount;
   6147     res.w = r.w - 2 * amount;
   6148     res.h = r.h - 2 * amount;
   6149     return res;
   6150 }
   6151 NK_LIB struct nk_rect
   6152 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
   6153 {
   6154     r.w = NK_MAX(r.w, 2 * pad.x);
   6155     r.h = NK_MAX(r.h, 2 * pad.y);
   6156     r.x += pad.x; r.y += pad.y;
   6157     r.w -= 2 * pad.x;
   6158     r.h -= 2 * pad.y;
   6159     return r;
   6160 }
   6161 NK_API struct nk_vec2
   6162 nk_vec2(float x, float y)
   6163 {
   6164     struct nk_vec2 ret;
   6165     ret.x = x; ret.y = y;
   6166     return ret;
   6167 }
   6168 NK_API struct nk_vec2
   6169 nk_vec2i(int x, int y)
   6170 {
   6171     struct nk_vec2 ret;
   6172     ret.x = (float)x;
   6173     ret.y = (float)y;
   6174     return ret;
   6175 }
   6176 NK_API struct nk_vec2
   6177 nk_vec2v(const float *v)
   6178 {
   6179     return nk_vec2(v[0], v[1]);
   6180 }
   6181 NK_API struct nk_vec2
   6182 nk_vec2iv(const int *v)
   6183 {
   6184     return nk_vec2i(v[0], v[1]);
   6185 }
   6186 NK_LIB void
   6187 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
   6188     float x1, float y1)
   6189 {
   6190     NK_ASSERT(a);
   6191     NK_ASSERT(clip);
   6192     clip->x = NK_MAX(a->x, x0);
   6193     clip->y = NK_MAX(a->y, y0);
   6194     clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
   6195     clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
   6196     clip->w = NK_MAX(0, clip->w);
   6197     clip->h = NK_MAX(0, clip->h);
   6198 }
   6199 
   6200 NK_API void
   6201 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
   6202     float pad_x, float pad_y, enum nk_heading direction)
   6203 {
   6204     float w_half, h_half;
   6205     NK_ASSERT(result);
   6206 
   6207     r.w = NK_MAX(2 * pad_x, r.w);
   6208     r.h = NK_MAX(2 * pad_y, r.h);
   6209     r.w = r.w - 2 * pad_x;
   6210     r.h = r.h - 2 * pad_y;
   6211 
   6212     r.x = r.x + pad_x;
   6213     r.y = r.y + pad_y;
   6214 
   6215     w_half = r.w / 2.0f;
   6216     h_half = r.h / 2.0f;
   6217 
   6218     if (direction == NK_UP) {
   6219         result[0] = nk_vec2(r.x + w_half, r.y);
   6220         result[1] = nk_vec2(r.x + r.w, r.y + r.h);
   6221         result[2] = nk_vec2(r.x, r.y + r.h);
   6222     } else if (direction == NK_RIGHT) {
   6223         result[0] = nk_vec2(r.x, r.y);
   6224         result[1] = nk_vec2(r.x + r.w, r.y + h_half);
   6225         result[2] = nk_vec2(r.x, r.y + r.h);
   6226     } else if (direction == NK_DOWN) {
   6227         result[0] = nk_vec2(r.x, r.y);
   6228         result[1] = nk_vec2(r.x + r.w, r.y);
   6229         result[2] = nk_vec2(r.x + w_half, r.y + r.h);
   6230     } else {
   6231         result[0] = nk_vec2(r.x, r.y + h_half);
   6232         result[1] = nk_vec2(r.x + r.w, r.y);
   6233         result[2] = nk_vec2(r.x + r.w, r.y + r.h);
   6234     }
   6235 }
   6236 
   6237 
   6238 
   6239 
   6240 
   6241 /* ===============================================================
   6242  *
   6243  *                              UTIL
   6244  *
   6245  * ===============================================================*/
   6246 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
   6247 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
   6248 NK_LIB int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
   6249 NK_LIB int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
   6250 NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
   6251 NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
   6252 
   6253 NK_LIB void*
   6254 nk_memcopy(void *dst0, const void *src0, nk_size length)
   6255 {
   6256     nk_ptr t;
   6257     char *dst = (char*)dst0;
   6258     const char *src = (const char*)src0;
   6259     if (length == 0 || dst == src)
   6260         goto done;
   6261 
   6262     #define nk_word int
   6263     #define nk_wsize sizeof(nk_word)
   6264     #define nk_wmask (nk_wsize-1)
   6265     #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
   6266     #define NK_TLOOP1(s) do { s; } while (--t)
   6267 
   6268     if (dst < src) {
   6269         t = (nk_ptr)src; /* only need low bits */
   6270         if ((t | (nk_ptr)dst) & nk_wmask) {
   6271             if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
   6272                 t = length;
   6273             else
   6274                 t = nk_wsize - (t & nk_wmask);
   6275             length -= t;
   6276             NK_TLOOP1(*dst++ = *src++);
   6277         }
   6278         t = length / nk_wsize;
   6279         NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
   6280             src += nk_wsize; dst += nk_wsize);
   6281         t = length & nk_wmask;
   6282         NK_TLOOP(*dst++ = *src++);
   6283     } else {
   6284         src += length;
   6285         dst += length;
   6286         t = (nk_ptr)src;
   6287         if ((t | (nk_ptr)dst) & nk_wmask) {
   6288             if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
   6289                 t = length;
   6290             else
   6291                 t &= nk_wmask;
   6292             length -= t;
   6293             NK_TLOOP1(*--dst = *--src);
   6294         }
   6295         t = length / nk_wsize;
   6296         NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
   6297             *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
   6298         t = length & nk_wmask;
   6299         NK_TLOOP(*--dst = *--src);
   6300     }
   6301     #undef nk_word
   6302     #undef nk_wsize
   6303     #undef nk_wmask
   6304     #undef NK_TLOOP
   6305     #undef NK_TLOOP1
   6306 done:
   6307     return (dst0);
   6308 }
   6309 NK_LIB void
   6310 nk_memset(void *ptr, int c0, nk_size size)
   6311 {
   6312     #define nk_word unsigned
   6313     #define nk_wsize sizeof(nk_word)
   6314     #define nk_wmask (nk_wsize - 1)
   6315     nk_byte *dst = (nk_byte*)ptr;
   6316     unsigned c = 0;
   6317     nk_size t = 0;
   6318 
   6319     if ((c = (nk_byte)c0) != 0) {
   6320         c = (c << 8) | c; /* at least 16-bits  */
   6321         if (sizeof(unsigned int) > 2)
   6322             c = (c << 16) | c; /* at least 32-bits*/
   6323     }
   6324 
   6325     /* too small of a word count */
   6326     dst = (nk_byte*)ptr;
   6327     if (size < 3 * nk_wsize) {
   6328         while (size--) *dst++ = (nk_byte)c0;
   6329         return;
   6330     }
   6331 
   6332     /* align destination */
   6333     if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
   6334         t = nk_wsize -t;
   6335         size -= t;
   6336         do {
   6337             *dst++ = (nk_byte)c0;
   6338         } while (--t != 0);
   6339     }
   6340 
   6341     /* fill word */
   6342     t = size / nk_wsize;
   6343     do {
   6344         *(nk_word*)((void*)dst) = c;
   6345         dst += nk_wsize;
   6346     } while (--t != 0);
   6347 
   6348     /* fill trailing bytes */
   6349     t = (size & nk_wmask);
   6350     if (t != 0) {
   6351         do {
   6352             *dst++ = (nk_byte)c0;
   6353         } while (--t != 0);
   6354     }
   6355 
   6356     #undef nk_word
   6357     #undef nk_wsize
   6358     #undef nk_wmask
   6359 }
   6360 NK_LIB void
   6361 nk_zero(void *ptr, nk_size size)
   6362 {
   6363     NK_ASSERT(ptr);
   6364     NK_MEMSET(ptr, 0, size);
   6365 }
   6366 NK_API int
   6367 nk_strlen(const char *str)
   6368 {
   6369     int siz = 0;
   6370     NK_ASSERT(str);
   6371     while (str && *str++ != '\0') siz++;
   6372     return siz;
   6373 }
   6374 NK_API int
   6375 nk_strtoi(const char *str, const char **endptr)
   6376 {
   6377     int neg = 1;
   6378     const char *p = str;
   6379     int value = 0;
   6380 
   6381     NK_ASSERT(str);
   6382     if (!str) return 0;
   6383 
   6384     /* skip whitespace */
   6385     while (*p == ' ') p++;
   6386     if (*p == '-') {
   6387         neg = -1;
   6388         p++;
   6389     }
   6390     while (*p && *p >= '0' && *p <= '9') {
   6391         value = value * 10 + (int) (*p - '0');
   6392         p++;
   6393     }
   6394     if (endptr)
   6395         *endptr = p;
   6396     return neg*value;
   6397 }
   6398 NK_API double
   6399 nk_strtod(const char *str, const char **endptr)
   6400 {
   6401     double m;
   6402     double neg = 1.0;
   6403     const char *p = str;
   6404     double value = 0;
   6405     double number = 0;
   6406 
   6407     NK_ASSERT(str);
   6408     if (!str) return 0;
   6409 
   6410     /* skip whitespace */
   6411     while (*p == ' ') p++;
   6412     if (*p == '-') {
   6413         neg = -1.0;
   6414         p++;
   6415     }
   6416 
   6417     while (*p && *p != '.' && *p != 'e') {
   6418         value = value * 10.0 + (double) (*p - '0');
   6419         p++;
   6420     }
   6421 
   6422     if (*p == '.') {
   6423         p++;
   6424         for(m = 0.1; *p && *p != 'e'; p++ ) {
   6425             value = value + (double) (*p - '0') * m;
   6426             m *= 0.1;
   6427         }
   6428     }
   6429     if (*p == 'e') {
   6430         int i, pow, div;
   6431         p++;
   6432         if (*p == '-') {
   6433             div = nk_true;
   6434             p++;
   6435         } else if (*p == '+') {
   6436             div = nk_false;
   6437             p++;
   6438         } else div = nk_false;
   6439 
   6440         for (pow = 0; *p; p++)
   6441             pow = pow * 10 + (int) (*p - '0');
   6442 
   6443         for (m = 1.0, i = 0; i < pow; i++)
   6444             m *= 10.0;
   6445 
   6446         if (div)
   6447             value /= m;
   6448         else value *= m;
   6449     }
   6450     number = value * neg;
   6451     if (endptr)
   6452         *endptr = p;
   6453     return number;
   6454 }
   6455 NK_API float
   6456 nk_strtof(const char *str, const char **endptr)
   6457 {
   6458     float float_value;
   6459     double double_value;
   6460     double_value = NK_STRTOD(str, endptr);
   6461     float_value = (float)double_value;
   6462     return float_value;
   6463 }
   6464 NK_API int
   6465 nk_stricmp(const char *s1, const char *s2)
   6466 {
   6467     nk_int c1,c2,d;
   6468     do {
   6469         c1 = *s1++;
   6470         c2 = *s2++;
   6471         d = c1 - c2;
   6472         while (d) {
   6473             if (c1 <= 'Z' && c1 >= 'A') {
   6474                 d += ('a' - 'A');
   6475                 if (!d) break;
   6476             }
   6477             if (c2 <= 'Z' && c2 >= 'A') {
   6478                 d -= ('a' - 'A');
   6479                 if (!d) break;
   6480             }
   6481             return ((d >= 0) << 1) - 1;
   6482         }
   6483     } while (c1);
   6484     return 0;
   6485 }
   6486 NK_API int
   6487 nk_stricmpn(const char *s1, const char *s2, int n)
   6488 {
   6489     int c1,c2,d;
   6490     NK_ASSERT(n >= 0);
   6491     do {
   6492         c1 = *s1++;
   6493         c2 = *s2++;
   6494         if (!n--) return 0;
   6495 
   6496         d = c1 - c2;
   6497         while (d) {
   6498             if (c1 <= 'Z' && c1 >= 'A') {
   6499                 d += ('a' - 'A');
   6500                 if (!d) break;
   6501             }
   6502             if (c2 <= 'Z' && c2 >= 'A') {
   6503                 d -= ('a' - 'A');
   6504                 if (!d) break;
   6505             }
   6506             return ((d >= 0) << 1) - 1;
   6507         }
   6508     } while (c1);
   6509     return 0;
   6510 }
   6511 NK_INTERN int
   6512 nk_str_match_here(const char *regexp, const char *text)
   6513 {
   6514     if (regexp[0] == '\0')
   6515         return 1;
   6516     if (regexp[1] == '*')
   6517         return nk_str_match_star(regexp[0], regexp+2, text);
   6518     if (regexp[0] == '$' && regexp[1] == '\0')
   6519         return *text == '\0';
   6520     if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
   6521         return nk_str_match_here(regexp+1, text+1);
   6522     return 0;
   6523 }
   6524 NK_INTERN int
   6525 nk_str_match_star(int c, const char *regexp, const char *text)
   6526 {
   6527     do {/* a '* matches zero or more instances */
   6528         if (nk_str_match_here(regexp, text))
   6529             return 1;
   6530     } while (*text != '\0' && (*text++ == c || c == '.'));
   6531     return 0;
   6532 }
   6533 NK_API int
   6534 nk_strfilter(const char *text, const char *regexp)
   6535 {
   6536     /*
   6537     c    matches any literal character c
   6538     .    matches any single character
   6539     ^    matches the beginning of the input string
   6540     $    matches the end of the input string
   6541     *    matches zero or more occurrences of the previous character*/
   6542     if (regexp[0] == '^')
   6543         return nk_str_match_here(regexp+1, text);
   6544     do {    /* must look even if string is empty */
   6545         if (nk_str_match_here(regexp, text))
   6546             return 1;
   6547     } while (*text++ != '\0');
   6548     return 0;
   6549 }
   6550 NK_API int
   6551 nk_strmatch_fuzzy_text(const char *str, int str_len,
   6552     const char *pattern, int *out_score)
   6553 {
   6554     /* Returns true if each character in pattern is found sequentially within str
   6555      * if found then out_score is also set. Score value has no intrinsic meaning.
   6556      * Range varies with pattern. Can only compare scores with same search pattern. */
   6557 
   6558     /* bonus for adjacent matches */
   6559     #define NK_ADJACENCY_BONUS 5
   6560     /* bonus if match occurs after a separator */
   6561     #define NK_SEPARATOR_BONUS 10
   6562     /* bonus if match is uppercase and prev is lower */
   6563     #define NK_CAMEL_BONUS 10
   6564     /* penalty applied for every letter in str before the first match */
   6565     #define NK_LEADING_LETTER_PENALTY (-3)
   6566     /* maximum penalty for leading letters */
   6567     #define NK_MAX_LEADING_LETTER_PENALTY (-9)
   6568     /* penalty for every letter that doesn't matter */
   6569     #define NK_UNMATCHED_LETTER_PENALTY (-1)
   6570 
   6571     /* loop variables */
   6572     int score = 0;
   6573     char const * pattern_iter = pattern;
   6574     int str_iter = 0;
   6575     int prev_matched = nk_false;
   6576     int prev_lower = nk_false;
   6577     /* true so if first letter match gets separator bonus*/
   6578     int prev_separator = nk_true;
   6579 
   6580     /* use "best" matched letter if multiple string letters match the pattern */
   6581     char const * best_letter = 0;
   6582     int best_letter_score = 0;
   6583 
   6584     /* loop over strings */
   6585     NK_ASSERT(str);
   6586     NK_ASSERT(pattern);
   6587     if (!str || !str_len || !pattern) return 0;
   6588     while (str_iter < str_len)
   6589     {
   6590         const char pattern_letter = *pattern_iter;
   6591         const char str_letter = str[str_iter];
   6592 
   6593         int next_match = *pattern_iter != '\0' &&
   6594             nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
   6595         int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
   6596 
   6597         int advanced = next_match && best_letter;
   6598         int pattern_repeat = best_letter && *pattern_iter != '\0';
   6599         pattern_repeat = pattern_repeat &&
   6600             nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
   6601 
   6602         if (advanced || pattern_repeat) {
   6603             score += best_letter_score;
   6604             best_letter = 0;
   6605             best_letter_score = 0;
   6606         }
   6607 
   6608         if (next_match || rematch)
   6609         {
   6610             int new_score = 0;
   6611             /* Apply penalty for each letter before the first pattern match */
   6612             if (pattern_iter == pattern) {
   6613                 int count = (int)(&str[str_iter] - str);
   6614                 int penalty = NK_LEADING_LETTER_PENALTY * count;
   6615                 if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
   6616                     penalty = NK_MAX_LEADING_LETTER_PENALTY;
   6617 
   6618                 score += penalty;
   6619             }
   6620 
   6621             /* apply bonus for consecutive bonuses */
   6622             if (prev_matched)
   6623                 new_score += NK_ADJACENCY_BONUS;
   6624 
   6625             /* apply bonus for matches after a separator */
   6626             if (prev_separator)
   6627                 new_score += NK_SEPARATOR_BONUS;
   6628 
   6629             /* apply bonus across camel case boundaries */
   6630             if (prev_lower && nk_is_upper(str_letter))
   6631                 new_score += NK_CAMEL_BONUS;
   6632 
   6633             /* update pattern iter IFF the next pattern letter was matched */
   6634             if (next_match)
   6635                 ++pattern_iter;
   6636 
   6637             /* update best letter in str which may be for a "next" letter or a rematch */
   6638             if (new_score >= best_letter_score) {
   6639                 /* apply penalty for now skipped letter */
   6640                 if (best_letter != 0)
   6641                     score += NK_UNMATCHED_LETTER_PENALTY;
   6642 
   6643                 best_letter = &str[str_iter];
   6644                 best_letter_score = new_score;
   6645             }
   6646             prev_matched = nk_true;
   6647         } else {
   6648             score += NK_UNMATCHED_LETTER_PENALTY;
   6649             prev_matched = nk_false;
   6650         }
   6651 
   6652         /* separators should be more easily defined */
   6653         prev_lower = nk_is_lower(str_letter) != 0;
   6654         prev_separator = str_letter == '_' || str_letter == ' ';
   6655 
   6656         ++str_iter;
   6657     }
   6658 
   6659     /* apply score for last match */
   6660     if (best_letter)
   6661         score += best_letter_score;
   6662 
   6663     /* did not match full pattern */
   6664     if (*pattern_iter != '\0')
   6665         return nk_false;
   6666 
   6667     if (out_score)
   6668         *out_score = score;
   6669     return nk_true;
   6670 }
   6671 NK_API int
   6672 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
   6673 {
   6674     return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);
   6675 }
   6676 NK_LIB int
   6677 nk_string_float_limit(char *string, int prec)
   6678 {
   6679     int dot = 0;
   6680     char *c = string;
   6681     while (*c) {
   6682         if (*c == '.') {
   6683             dot = 1;
   6684             c++;
   6685             continue;
   6686         }
   6687         if (dot == (prec+1)) {
   6688             *c = 0;
   6689             break;
   6690         }
   6691         if (dot > 0) dot++;
   6692         c++;
   6693     }
   6694     return (int)(c - string);
   6695 }
   6696 NK_INTERN void
   6697 nk_strrev_ascii(char *s)
   6698 {
   6699     int len = nk_strlen(s);
   6700     int end = len / 2;
   6701     int i = 0;
   6702     char t;
   6703     for (; i < end; ++i) {
   6704         t = s[i];
   6705         s[i] = s[len - 1 - i];
   6706         s[len -1 - i] = t;
   6707     }
   6708 }
   6709 NK_LIB char*
   6710 nk_itoa(char *s, long n)
   6711 {
   6712     long i = 0;
   6713     if (n == 0) {
   6714         s[i++] = '0';
   6715         s[i] = 0;
   6716         return s;
   6717     }
   6718     if (n < 0) {
   6719         s[i++] = '-';
   6720         n = -n;
   6721     }
   6722     while (n > 0) {
   6723         s[i++] = (char)('0' + (n % 10));
   6724         n /= 10;
   6725     }
   6726     s[i] = 0;
   6727     if (s[0] == '-')
   6728         ++s;
   6729 
   6730     nk_strrev_ascii(s);
   6731     return s;
   6732 }
   6733 NK_LIB char*
   6734 nk_dtoa(char *s, double n)
   6735 {
   6736     int useExp = 0;
   6737     int digit = 0, m = 0, m1 = 0;
   6738     char *c = s;
   6739     int neg = 0;
   6740 
   6741     NK_ASSERT(s);
   6742     if (!s) return 0;
   6743 
   6744     if (n == 0.0) {
   6745         s[0] = '0'; s[1] = '\0';
   6746         return s;
   6747     }
   6748 
   6749     neg = (n < 0);
   6750     if (neg) n = -n;
   6751 
   6752     /* calculate magnitude */
   6753     m = nk_log10(n);
   6754     useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
   6755     if (neg) *(c++) = '-';
   6756 
   6757     /* set up for scientific notation */
   6758     if (useExp) {
   6759         if (m < 0)
   6760            m -= 1;
   6761         n = n / (double)nk_pow(10.0, m);
   6762         m1 = m;
   6763         m = 0;
   6764     }
   6765     if (m < 1.0) {
   6766         m = 0;
   6767     }
   6768 
   6769     /* convert the number */
   6770     while (n > NK_FLOAT_PRECISION || m >= 0) {
   6771         double weight = nk_pow(10.0, m);
   6772         if (weight > 0) {
   6773             double t = (double)n / weight;
   6774             digit = nk_ifloord(t);
   6775             n -= ((double)digit * weight);
   6776             *(c++) = (char)('0' + (char)digit);
   6777         }
   6778         if (m == 0 && n > 0)
   6779             *(c++) = '.';
   6780         m--;
   6781     }
   6782 
   6783     if (useExp) {
   6784         /* convert the exponent */
   6785         int i, j;
   6786         *(c++) = 'e';
   6787         if (m1 > 0) {
   6788             *(c++) = '+';
   6789         } else {
   6790             *(c++) = '-';
   6791             m1 = -m1;
   6792         }
   6793         m = 0;
   6794         while (m1 > 0) {
   6795             *(c++) = (char)('0' + (char)(m1 % 10));
   6796             m1 /= 10;
   6797             m++;
   6798         }
   6799         c -= m;
   6800         for (i = 0, j = m-1; i<j; i++, j--) {
   6801             /* swap without temporary */
   6802             c[i] ^= c[j];
   6803             c[j] ^= c[i];
   6804             c[i] ^= c[j];
   6805         }
   6806         c += m;
   6807     }
   6808     *(c) = '\0';
   6809     return s;
   6810 }
   6811 #ifdef NK_INCLUDE_STANDARD_VARARGS
   6812 #ifndef NK_INCLUDE_STANDARD_IO
   6813 NK_INTERN int
   6814 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
   6815 {
   6816     enum nk_arg_type {
   6817         NK_ARG_TYPE_CHAR,
   6818         NK_ARG_TYPE_SHORT,
   6819         NK_ARG_TYPE_DEFAULT,
   6820         NK_ARG_TYPE_LONG
   6821     };
   6822     enum nk_arg_flags {
   6823         NK_ARG_FLAG_LEFT = 0x01,
   6824         NK_ARG_FLAG_PLUS = 0x02,
   6825         NK_ARG_FLAG_SPACE = 0x04,
   6826         NK_ARG_FLAG_NUM = 0x10,
   6827         NK_ARG_FLAG_ZERO = 0x20
   6828     };
   6829 
   6830     char number_buffer[NK_MAX_NUMBER_BUFFER];
   6831     enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
   6832     int precision = NK_DEFAULT;
   6833     int width = NK_DEFAULT;
   6834     nk_flags flag = 0;
   6835 
   6836     int len = 0;
   6837     int result = -1;
   6838     const char *iter = fmt;
   6839 
   6840     NK_ASSERT(buf);
   6841     NK_ASSERT(buf_size);
   6842     if (!buf || !buf_size || !fmt) return 0;
   6843     for (iter = fmt; *iter && len < buf_size; iter++) {
   6844         /* copy all non-format characters */
   6845         while (*iter && (*iter != '%') && (len < buf_size))
   6846             buf[len++] = *iter++;
   6847         if (!(*iter) || len >= buf_size) break;
   6848         iter++;
   6849 
   6850         /* flag arguments */
   6851         while (*iter) {
   6852             if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
   6853             else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
   6854             else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
   6855             else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
   6856             else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
   6857             else break;
   6858             iter++;
   6859         }
   6860 
   6861         /* width argument */
   6862         width = NK_DEFAULT;
   6863         if (*iter >= '1' && *iter <= '9') {
   6864             const char *end;
   6865             width = nk_strtoi(iter, &end);
   6866             if (end == iter)
   6867                 width = -1;
   6868             else iter = end;
   6869         } else if (*iter == '*') {
   6870             width = va_arg(args, int);
   6871             iter++;
   6872         }
   6873 
   6874         /* precision argument */
   6875         precision = NK_DEFAULT;
   6876         if (*iter == '.') {
   6877             iter++;
   6878             if (*iter == '*') {
   6879                 precision = va_arg(args, int);
   6880                 iter++;
   6881             } else {
   6882                 const char *end;
   6883                 precision = nk_strtoi(iter, &end);
   6884                 if (end == iter)
   6885                     precision = -1;
   6886                 else iter = end;
   6887             }
   6888         }
   6889 
   6890         /* length modifier */
   6891         if (*iter == 'h') {
   6892             if (*(iter+1) == 'h') {
   6893                 arg_type = NK_ARG_TYPE_CHAR;
   6894                 iter++;
   6895             } else arg_type = NK_ARG_TYPE_SHORT;
   6896             iter++;
   6897         } else if (*iter == 'l') {
   6898             arg_type = NK_ARG_TYPE_LONG;
   6899             iter++;
   6900         } else arg_type = NK_ARG_TYPE_DEFAULT;
   6901 
   6902         /* specifier */
   6903         if (*iter == '%') {
   6904             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
   6905             NK_ASSERT(precision == NK_DEFAULT);
   6906             NK_ASSERT(width == NK_DEFAULT);
   6907             if (len < buf_size)
   6908                 buf[len++] = '%';
   6909         } else if (*iter == 's') {
   6910             /* string  */
   6911             const char *str = va_arg(args, const char*);
   6912             NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
   6913             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
   6914             NK_ASSERT(precision == NK_DEFAULT);
   6915             NK_ASSERT(width == NK_DEFAULT);
   6916             if (str == buf) return -1;
   6917             while (str && *str && len < buf_size)
   6918                 buf[len++] = *str++;
   6919         } else if (*iter == 'n') {
   6920             /* current length callback */
   6921             signed int *n = va_arg(args, int*);
   6922             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
   6923             NK_ASSERT(precision == NK_DEFAULT);
   6924             NK_ASSERT(width == NK_DEFAULT);
   6925             if (n) *n = len;
   6926         } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
   6927             /* signed integer */
   6928             long value = 0;
   6929             const char *num_iter;
   6930             int num_len, num_print, padding;
   6931             int cur_precision = NK_MAX(precision, 1);
   6932             int cur_width = NK_MAX(width, 0);
   6933 
   6934             /* retrieve correct value type */
   6935             if (arg_type == NK_ARG_TYPE_CHAR)
   6936                 value = (signed char)va_arg(args, int);
   6937             else if (arg_type == NK_ARG_TYPE_SHORT)
   6938                 value = (signed short)va_arg(args, int);
   6939             else if (arg_type == NK_ARG_TYPE_LONG)
   6940                 value = va_arg(args, signed long);
   6941             else if (*iter == 'c')
   6942                 value = (unsigned char)va_arg(args, int);
   6943             else value = va_arg(args, signed int);
   6944 
   6945             /* convert number to string */
   6946             nk_itoa(number_buffer, value);
   6947             num_len = nk_strlen(number_buffer);
   6948             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
   6949             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
   6950                 padding = NK_MAX(padding-1, 0);
   6951 
   6952             /* fill left padding up to a total of `width` characters */
   6953             if (!(flag & NK_ARG_FLAG_LEFT)) {
   6954                 while (padding-- > 0 && (len < buf_size)) {
   6955                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
   6956                         buf[len++] = '0';
   6957                     else buf[len++] = ' ';
   6958                 }
   6959             }
   6960 
   6961             /* copy string value representation into buffer */
   6962             if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
   6963                 buf[len++] = '+';
   6964             else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
   6965                 buf[len++] = ' ';
   6966 
   6967             /* fill up to precision number of digits with '0' */
   6968             num_print = NK_MAX(cur_precision, num_len);
   6969             while (precision && (num_print > num_len) && (len < buf_size)) {
   6970                 buf[len++] = '0';
   6971                 num_print--;
   6972             }
   6973 
   6974             /* copy string value representation into buffer */
   6975             num_iter = number_buffer;
   6976             while (precision && *num_iter && len < buf_size)
   6977                 buf[len++] = *num_iter++;
   6978 
   6979             /* fill right padding up to width characters */
   6980             if (flag & NK_ARG_FLAG_LEFT) {
   6981                 while ((padding-- > 0) && (len < buf_size))
   6982                     buf[len++] = ' ';
   6983             }
   6984         } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
   6985             /* unsigned integer */
   6986             unsigned long value = 0;
   6987             int num_len = 0, num_print, padding = 0;
   6988             int cur_precision = NK_MAX(precision, 1);
   6989             int cur_width = NK_MAX(width, 0);
   6990             unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
   6991 
   6992             /* print oct/hex/dec value */
   6993             const char *upper_output_format = "0123456789ABCDEF";
   6994             const char *lower_output_format = "0123456789abcdef";
   6995             const char *output_format = (*iter == 'x') ?
   6996                 lower_output_format: upper_output_format;
   6997 
   6998             /* retrieve correct value type */
   6999             if (arg_type == NK_ARG_TYPE_CHAR)
   7000                 value = (unsigned char)va_arg(args, int);
   7001             else if (arg_type == NK_ARG_TYPE_SHORT)
   7002                 value = (unsigned short)va_arg(args, int);
   7003             else if (arg_type == NK_ARG_TYPE_LONG)
   7004                 value = va_arg(args, unsigned long);
   7005             else value = va_arg(args, unsigned int);
   7006 
   7007             do {
   7008                 /* convert decimal number into hex/oct number */
   7009                 int digit = output_format[value % base];
   7010                 if (num_len < NK_MAX_NUMBER_BUFFER)
   7011                     number_buffer[num_len++] = (char)digit;
   7012                 value /= base;
   7013             } while (value > 0);
   7014 
   7015             num_print = NK_MAX(cur_precision, num_len);
   7016             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
   7017             if (flag & NK_ARG_FLAG_NUM)
   7018                 padding = NK_MAX(padding-1, 0);
   7019 
   7020             /* fill left padding up to a total of `width` characters */
   7021             if (!(flag & NK_ARG_FLAG_LEFT)) {
   7022                 while ((padding-- > 0) && (len < buf_size)) {
   7023                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
   7024                         buf[len++] = '0';
   7025                     else buf[len++] = ' ';
   7026                 }
   7027             }
   7028 
   7029             /* fill up to precision number of digits */
   7030             if (num_print && (flag & NK_ARG_FLAG_NUM)) {
   7031                 if ((*iter == 'o') && (len < buf_size)) {
   7032                     buf[len++] = '0';
   7033                 } else if ((*iter == 'x') && ((len+1) < buf_size)) {
   7034                     buf[len++] = '0';
   7035                     buf[len++] = 'x';
   7036                 } else if ((*iter == 'X') && ((len+1) < buf_size)) {
   7037                     buf[len++] = '0';
   7038                     buf[len++] = 'X';
   7039                 }
   7040             }
   7041             while (precision && (num_print > num_len) && (len < buf_size)) {
   7042                 buf[len++] = '0';
   7043                 num_print--;
   7044             }
   7045 
   7046             /* reverse number direction */
   7047             while (num_len > 0) {
   7048                 if (precision && (len < buf_size))
   7049                     buf[len++] = number_buffer[num_len-1];
   7050                 num_len--;
   7051             }
   7052 
   7053             /* fill right padding up to width characters */
   7054             if (flag & NK_ARG_FLAG_LEFT) {
   7055                 while ((padding-- > 0) && (len < buf_size))
   7056                     buf[len++] = ' ';
   7057             }
   7058         } else if (*iter == 'f') {
   7059             /* floating point */
   7060             const char *num_iter;
   7061             int cur_precision = (precision < 0) ? 6: precision;
   7062             int prefix, cur_width = NK_MAX(width, 0);
   7063             double value = va_arg(args, double);
   7064             int num_len = 0, frac_len = 0, dot = 0;
   7065             int padding = 0;
   7066 
   7067             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
   7068             NK_DTOA(number_buffer, value);
   7069             num_len = nk_strlen(number_buffer);
   7070 
   7071             /* calculate padding */
   7072             num_iter = number_buffer;
   7073             while (*num_iter && *num_iter != '.')
   7074                 num_iter++;
   7075 
   7076             prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
   7077             padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
   7078             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
   7079                 padding = NK_MAX(padding-1, 0);
   7080 
   7081             /* fill left padding up to a total of `width` characters */
   7082             if (!(flag & NK_ARG_FLAG_LEFT)) {
   7083                 while (padding-- > 0 && (len < buf_size)) {
   7084                     if (flag & NK_ARG_FLAG_ZERO)
   7085                         buf[len++] = '0';
   7086                     else buf[len++] = ' ';
   7087                 }
   7088             }
   7089 
   7090             /* copy string value representation into buffer */
   7091             num_iter = number_buffer;
   7092             if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
   7093                 buf[len++] = '+';
   7094             else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
   7095                 buf[len++] = ' ';
   7096             while (*num_iter) {
   7097                 if (dot) frac_len++;
   7098                 if (len < buf_size)
   7099                     buf[len++] = *num_iter;
   7100                 if (*num_iter == '.') dot = 1;
   7101                 if (frac_len >= cur_precision) break;
   7102                 num_iter++;
   7103             }
   7104 
   7105             /* fill number up to precision */
   7106             while (frac_len < cur_precision) {
   7107                 if (!dot && len < buf_size) {
   7108                     buf[len++] = '.';
   7109                     dot = 1;
   7110                 }
   7111                 if (len < buf_size)
   7112                     buf[len++] = '0';
   7113                 frac_len++;
   7114             }
   7115 
   7116             /* fill right padding up to width characters */
   7117             if (flag & NK_ARG_FLAG_LEFT) {
   7118                 while ((padding-- > 0) && (len < buf_size))
   7119                     buf[len++] = ' ';
   7120             }
   7121         } else {
   7122             /* Specifier not supported: g,G,e,E,p,z */
   7123             NK_ASSERT(0 && "specifier is not supported!");
   7124             return result;
   7125         }
   7126     }
   7127     buf[(len >= buf_size)?(buf_size-1):len] = 0;
   7128     result = (len >= buf_size)?-1:len;
   7129     return result;
   7130 }
   7131 #endif
   7132 NK_LIB int
   7133 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
   7134 {
   7135     int result = -1;
   7136     NK_ASSERT(buf);
   7137     NK_ASSERT(buf_size);
   7138     if (!buf || !buf_size || !fmt) return 0;
   7139 #ifdef NK_INCLUDE_STANDARD_IO
   7140     result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
   7141     result = (result >= buf_size) ? -1: result;
   7142     buf[buf_size-1] = 0;
   7143 #else
   7144     result = nk_vsnprintf(buf, buf_size, fmt, args);
   7145 #endif
   7146     return result;
   7147 }
   7148 #endif
   7149 NK_API nk_hash
   7150 nk_murmur_hash(const void * key, int len, nk_hash seed)
   7151 {
   7152     /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
   7153     #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
   7154     union {const nk_uint *i; const nk_byte *b;} conv = {0};
   7155     const nk_byte *data = (const nk_byte*)key;
   7156     const int nblocks = len/4;
   7157     nk_uint h1 = seed;
   7158     const nk_uint c1 = 0xcc9e2d51;
   7159     const nk_uint c2 = 0x1b873593;
   7160     const nk_byte *tail;
   7161     const nk_uint *blocks;
   7162     nk_uint k1;
   7163     int i;
   7164 
   7165     /* body */
   7166     if (!key) return 0;
   7167     conv.b = (data + nblocks*4);
   7168     blocks = (const nk_uint*)conv.i;
   7169     for (i = -nblocks; i; ++i) {
   7170         k1 = blocks[i];
   7171         k1 *= c1;
   7172         k1 = NK_ROTL(k1,15);
   7173         k1 *= c2;
   7174 
   7175         h1 ^= k1;
   7176         h1 = NK_ROTL(h1,13);
   7177         h1 = h1*5+0xe6546b64;
   7178     }
   7179 
   7180     /* tail */
   7181     tail = (const nk_byte*)(data + nblocks*4);
   7182     k1 = 0;
   7183     switch (len & 3) {
   7184     case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
   7185     case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
   7186     case 1: k1 ^= tail[0];
   7187             k1 *= c1;
   7188             k1 = NK_ROTL(k1,15);
   7189             k1 *= c2;
   7190             h1 ^= k1;
   7191             break;
   7192     default: break;
   7193     }
   7194 
   7195     /* finalization */
   7196     h1 ^= (nk_uint)len;
   7197     /* fmix32 */
   7198     h1 ^= h1 >> 16;
   7199     h1 *= 0x85ebca6b;
   7200     h1 ^= h1 >> 13;
   7201     h1 *= 0xc2b2ae35;
   7202     h1 ^= h1 >> 16;
   7203 
   7204     #undef NK_ROTL
   7205     return h1;
   7206 }
   7207 #ifdef NK_INCLUDE_STANDARD_IO
   7208 NK_LIB char*
   7209 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
   7210 {
   7211     char *buf;
   7212     FILE *fd;
   7213     long ret;
   7214 
   7215     NK_ASSERT(path);
   7216     NK_ASSERT(siz);
   7217     NK_ASSERT(alloc);
   7218     if (!path || !siz || !alloc)
   7219         return 0;
   7220 
   7221     fd = fopen(path, "rb");
   7222     if (!fd) return 0;
   7223     fseek(fd, 0, SEEK_END);
   7224     ret = ftell(fd);
   7225     if (ret < 0) {
   7226         fclose(fd);
   7227         return 0;
   7228     }
   7229     *siz = (nk_size)ret;
   7230     fseek(fd, 0, SEEK_SET);
   7231     buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
   7232     NK_ASSERT(buf);
   7233     if (!buf) {
   7234         fclose(fd);
   7235         return 0;
   7236     }
   7237     *siz = (nk_size)fread(buf, 1,*siz, fd);
   7238     fclose(fd);
   7239     return buf;
   7240 }
   7241 #endif
   7242 NK_LIB int
   7243 nk_text_clamp(const struct nk_user_font *font, const char *text,
   7244     int text_len, float space, int *glyphs, float *text_width,
   7245     nk_rune *sep_list, int sep_count)
   7246 {
   7247     int i = 0;
   7248     int glyph_len = 0;
   7249     float last_width = 0;
   7250     nk_rune unicode = 0;
   7251     float width = 0;
   7252     int len = 0;
   7253     int g = 0;
   7254     float s;
   7255 
   7256     int sep_len = 0;
   7257     int sep_g = 0;
   7258     float sep_width = 0;
   7259     sep_count = NK_MAX(sep_count,0);
   7260 
   7261     glyph_len = nk_utf_decode(text, &unicode, text_len);
   7262     while (glyph_len && (width < space) && (len < text_len)) {
   7263         len += glyph_len;
   7264         s = font->width(font->userdata, font->height, text, len);
   7265         for (i = 0; i < sep_count; ++i) {
   7266             if (unicode != sep_list[i]) continue;
   7267             sep_width = last_width = width;
   7268             sep_g = g+1;
   7269             sep_len = len;
   7270             break;
   7271         }
   7272         if (i == sep_count){
   7273             last_width = sep_width = width;
   7274             sep_g = g+1;
   7275         }
   7276         width = s;
   7277         glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
   7278         g++;
   7279     }
   7280     if (len >= text_len) {
   7281         *glyphs = g;
   7282         *text_width = last_width;
   7283         return len;
   7284     } else {
   7285         *glyphs = sep_g;
   7286         *text_width = sep_width;
   7287         return (!sep_len) ? len: sep_len;
   7288     }
   7289 }
   7290 NK_LIB struct nk_vec2
   7291 nk_text_calculate_text_bounds(const struct nk_user_font *font,
   7292     const char *begin, int byte_len, float row_height, const char **remaining,
   7293     struct nk_vec2 *out_offset, int *glyphs, int op)
   7294 {
   7295     float line_height = row_height;
   7296     struct nk_vec2 text_size = nk_vec2(0,0);
   7297     float line_width = 0.0f;
   7298 
   7299     float glyph_width;
   7300     int glyph_len = 0;
   7301     nk_rune unicode = 0;
   7302     int text_len = 0;
   7303     if (!begin || byte_len <= 0 || !font)
   7304         return nk_vec2(0,row_height);
   7305 
   7306     glyph_len = nk_utf_decode(begin, &unicode, byte_len);
   7307     if (!glyph_len) return text_size;
   7308     glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
   7309 
   7310     *glyphs = 0;
   7311     while ((text_len < byte_len) && glyph_len) {
   7312         if (unicode == '\n') {
   7313             text_size.x = NK_MAX(text_size.x, line_width);
   7314             text_size.y += line_height;
   7315             line_width = 0;
   7316             *glyphs+=1;
   7317             if (op == NK_STOP_ON_NEW_LINE)
   7318                 break;
   7319 
   7320             text_len++;
   7321             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
   7322             continue;
   7323         }
   7324 
   7325         if (unicode == '\r') {
   7326             text_len++;
   7327             *glyphs+=1;
   7328             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
   7329             continue;
   7330         }
   7331 
   7332         *glyphs = *glyphs + 1;
   7333         text_len += glyph_len;
   7334         line_width += (float)glyph_width;
   7335         glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
   7336         glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
   7337         continue;
   7338     }
   7339 
   7340     if (text_size.x < line_width)
   7341         text_size.x = line_width;
   7342     if (out_offset)
   7343         *out_offset = nk_vec2(line_width, text_size.y + line_height);
   7344     if (line_width > 0 || text_size.y == 0.0f)
   7345         text_size.y += line_height;
   7346     if (remaining)
   7347         *remaining = begin+text_len;
   7348     return text_size;
   7349 }
   7350 
   7351 
   7352 
   7353 
   7354 
   7355 /* ==============================================================
   7356  *
   7357  *                          COLOR
   7358  *
   7359  * ===============================================================*/
   7360 NK_INTERN int
   7361 nk_parse_hex(const char *p, int length)
   7362 {
   7363     int i = 0;
   7364     int len = 0;
   7365     while (len < length) {
   7366         i <<= 4;
   7367         if (p[len] >= 'a' && p[len] <= 'f')
   7368             i += ((p[len] - 'a') + 10);
   7369         else if (p[len] >= 'A' && p[len] <= 'F')
   7370             i += ((p[len] - 'A') + 10);
   7371         else i += (p[len] - '0');
   7372         len++;
   7373     }
   7374     return i;
   7375 }
   7376 NK_API struct nk_color
   7377 nk_rgba(int r, int g, int b, int a)
   7378 {
   7379     struct nk_color ret;
   7380     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
   7381     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
   7382     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
   7383     ret.a = (nk_byte)NK_CLAMP(0, a, 255);
   7384     return ret;
   7385 }
   7386 NK_API struct nk_color
   7387 nk_rgb_hex(const char *rgb)
   7388 {
   7389     struct nk_color col;
   7390     const char *c = rgb;
   7391     if (*c == '#') c++;
   7392     col.r = (nk_byte)nk_parse_hex(c, 2);
   7393     col.g = (nk_byte)nk_parse_hex(c+2, 2);
   7394     col.b = (nk_byte)nk_parse_hex(c+4, 2);
   7395     col.a = 255;
   7396     return col;
   7397 }
   7398 NK_API struct nk_color
   7399 nk_rgba_hex(const char *rgb)
   7400 {
   7401     struct nk_color col;
   7402     const char *c = rgb;
   7403     if (*c == '#') c++;
   7404     col.r = (nk_byte)nk_parse_hex(c, 2);
   7405     col.g = (nk_byte)nk_parse_hex(c+2, 2);
   7406     col.b = (nk_byte)nk_parse_hex(c+4, 2);
   7407     col.a = (nk_byte)nk_parse_hex(c+6, 2);
   7408     return col;
   7409 }
   7410 NK_API void
   7411 nk_color_hex_rgba(char *output, struct nk_color col)
   7412 {
   7413     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
   7414     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
   7415     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
   7416     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
   7417     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
   7418     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
   7419     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
   7420     output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
   7421     output[7] = (char)NK_TO_HEX((col.a & 0x0F));
   7422     output[8] = '\0';
   7423     #undef NK_TO_HEX
   7424 }
   7425 NK_API void
   7426 nk_color_hex_rgb(char *output, struct nk_color col)
   7427 {
   7428     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
   7429     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
   7430     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
   7431     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
   7432     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
   7433     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
   7434     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
   7435     output[6] = '\0';
   7436     #undef NK_TO_HEX
   7437 }
   7438 NK_API struct nk_color
   7439 nk_rgba_iv(const int *c)
   7440 {
   7441     return nk_rgba(c[0], c[1], c[2], c[3]);
   7442 }
   7443 NK_API struct nk_color
   7444 nk_rgba_bv(const nk_byte *c)
   7445 {
   7446     return nk_rgba(c[0], c[1], c[2], c[3]);
   7447 }
   7448 NK_API struct nk_color
   7449 nk_rgb(int r, int g, int b)
   7450 {
   7451     struct nk_color ret;
   7452     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
   7453     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
   7454     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
   7455     ret.a = (nk_byte)255;
   7456     return ret;
   7457 }
   7458 NK_API struct nk_color
   7459 nk_rgb_iv(const int *c)
   7460 {
   7461     return nk_rgb(c[0], c[1], c[2]);
   7462 }
   7463 NK_API struct nk_color
   7464 nk_rgb_bv(const nk_byte* c)
   7465 {
   7466     return nk_rgb(c[0], c[1], c[2]);
   7467 }
   7468 NK_API struct nk_color
   7469 nk_rgba_u32(nk_uint in)
   7470 {
   7471     struct nk_color ret;
   7472     ret.r = (in & 0xFF);
   7473     ret.g = ((in >> 8) & 0xFF);
   7474     ret.b = ((in >> 16) & 0xFF);
   7475     ret.a = (nk_byte)((in >> 24) & 0xFF);
   7476     return ret;
   7477 }
   7478 NK_API struct nk_color
   7479 nk_rgba_f(float r, float g, float b, float a)
   7480 {
   7481     struct nk_color ret;
   7482     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
   7483     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
   7484     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
   7485     ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
   7486     return ret;
   7487 }
   7488 NK_API struct nk_color
   7489 nk_rgba_fv(const float *c)
   7490 {
   7491     return nk_rgba_f(c[0], c[1], c[2], c[3]);
   7492 }
   7493 NK_API struct nk_color
   7494 nk_rgba_cf(struct nk_colorf c)
   7495 {
   7496     return nk_rgba_f(c.r, c.g, c.b, c.a);
   7497 }
   7498 NK_API struct nk_color
   7499 nk_rgb_f(float r, float g, float b)
   7500 {
   7501     struct nk_color ret;
   7502     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
   7503     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
   7504     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
   7505     ret.a = 255;
   7506     return ret;
   7507 }
   7508 NK_API struct nk_color
   7509 nk_rgb_fv(const float *c)
   7510 {
   7511     return nk_rgb_f(c[0], c[1], c[2]);
   7512 }
   7513 NK_API struct nk_color
   7514 nk_rgb_cf(struct nk_colorf c)
   7515 {
   7516     return nk_rgb_f(c.r, c.g, c.b);
   7517 }
   7518 NK_API struct nk_color
   7519 nk_hsv(int h, int s, int v)
   7520 {
   7521     return nk_hsva(h, s, v, 255);
   7522 }
   7523 NK_API struct nk_color
   7524 nk_hsv_iv(const int *c)
   7525 {
   7526     return nk_hsv(c[0], c[1], c[2]);
   7527 }
   7528 NK_API struct nk_color
   7529 nk_hsv_bv(const nk_byte *c)
   7530 {
   7531     return nk_hsv(c[0], c[1], c[2]);
   7532 }
   7533 NK_API struct nk_color
   7534 nk_hsv_f(float h, float s, float v)
   7535 {
   7536     return nk_hsva_f(h, s, v, 1.0f);
   7537 }
   7538 NK_API struct nk_color
   7539 nk_hsv_fv(const float *c)
   7540 {
   7541     return nk_hsv_f(c[0], c[1], c[2]);
   7542 }
   7543 NK_API struct nk_color
   7544 nk_hsva(int h, int s, int v, int a)
   7545 {
   7546     float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
   7547     float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
   7548     float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
   7549     float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
   7550     return nk_hsva_f(hf, sf, vf, af);
   7551 }
   7552 NK_API struct nk_color
   7553 nk_hsva_iv(const int *c)
   7554 {
   7555     return nk_hsva(c[0], c[1], c[2], c[3]);
   7556 }
   7557 NK_API struct nk_color
   7558 nk_hsva_bv(const nk_byte *c)
   7559 {
   7560     return nk_hsva(c[0], c[1], c[2], c[3]);
   7561 }
   7562 NK_API struct nk_colorf
   7563 nk_hsva_colorf(float h, float s, float v, float a)
   7564 {
   7565     int i;
   7566     float p, q, t, f;
   7567     struct nk_colorf out = {0,0,0,0};
   7568     if (s <= 0.0f) {
   7569         out.r = v; out.g = v; out.b = v; out.a = a;
   7570         return out;
   7571     }
   7572     h = h / (60.0f/360.0f);
   7573     i = (int)h;
   7574     f = h - (float)i;
   7575     p = v * (1.0f - s);
   7576     q = v * (1.0f - (s * f));
   7577     t = v * (1.0f - s * (1.0f - f));
   7578 
   7579     switch (i) {
   7580     case 0: default: out.r = v; out.g = t; out.b = p; break;
   7581     case 1: out.r = q; out.g = v; out.b = p; break;
   7582     case 2: out.r = p; out.g = v; out.b = t; break;
   7583     case 3: out.r = p; out.g = q; out.b = v; break;
   7584     case 4: out.r = t; out.g = p; out.b = v; break;
   7585     case 5: out.r = v; out.g = p; out.b = q; break;}
   7586     out.a = a;
   7587     return out;
   7588 }
   7589 NK_API struct nk_colorf
   7590 nk_hsva_colorfv(float *c)
   7591 {
   7592     return nk_hsva_colorf(c[0], c[1], c[2], c[3]);
   7593 }
   7594 NK_API struct nk_color
   7595 nk_hsva_f(float h, float s, float v, float a)
   7596 {
   7597     struct nk_colorf c = nk_hsva_colorf(h, s, v, a);
   7598     return nk_rgba_f(c.r, c.g, c.b, c.a);
   7599 }
   7600 NK_API struct nk_color
   7601 nk_hsva_fv(const float *c)
   7602 {
   7603     return nk_hsva_f(c[0], c[1], c[2], c[3]);
   7604 }
   7605 NK_API nk_uint
   7606 nk_color_u32(struct nk_color in)
   7607 {
   7608     nk_uint out = (nk_uint)in.r;
   7609     out |= ((nk_uint)in.g << 8);
   7610     out |= ((nk_uint)in.b << 16);
   7611     out |= ((nk_uint)in.a << 24);
   7612     return out;
   7613 }
   7614 NK_API void
   7615 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
   7616 {
   7617     NK_STORAGE const float s = 1.0f/255.0f;
   7618     *r = (float)in.r * s;
   7619     *g = (float)in.g * s;
   7620     *b = (float)in.b * s;
   7621     *a = (float)in.a * s;
   7622 }
   7623 NK_API void
   7624 nk_color_fv(float *c, struct nk_color in)
   7625 {
   7626     nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
   7627 }
   7628 NK_API struct nk_colorf
   7629 nk_color_cf(struct nk_color in)
   7630 {
   7631     struct nk_colorf o;
   7632     nk_color_f(&o.r, &o.g, &o.b, &o.a, in);
   7633     return o;
   7634 }
   7635 NK_API void
   7636 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
   7637 {
   7638     NK_STORAGE const double s = 1.0/255.0;
   7639     *r = (double)in.r * s;
   7640     *g = (double)in.g * s;
   7641     *b = (double)in.b * s;
   7642     *a = (double)in.a * s;
   7643 }
   7644 NK_API void
   7645 nk_color_dv(double *c, struct nk_color in)
   7646 {
   7647     nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
   7648 }
   7649 NK_API void
   7650 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
   7651 {
   7652     float a;
   7653     nk_color_hsva_f(out_h, out_s, out_v, &a, in);
   7654 }
   7655 NK_API void
   7656 nk_color_hsv_fv(float *out, struct nk_color in)
   7657 {
   7658     float a;
   7659     nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
   7660 }
   7661 NK_API void
   7662 nk_colorf_hsva_f(float *out_h, float *out_s,
   7663     float *out_v, float *out_a, struct nk_colorf in)
   7664 {
   7665     float chroma;
   7666     float K = 0.0f;
   7667     if (in.g < in.b) {
   7668         const float t = in.g; in.g = in.b; in.b = t;
   7669         K = -1.f;
   7670     }
   7671     if (in.r < in.g) {
   7672         const float t = in.r; in.r = in.g; in.g = t;
   7673         K = -2.f/6.0f - K;
   7674     }
   7675     chroma = in.r - ((in.g < in.b) ? in.g: in.b);
   7676     *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f));
   7677     *out_s = chroma / (in.r + 1e-20f);
   7678     *out_v = in.r;
   7679     *out_a = in.a;
   7680 
   7681 }
   7682 NK_API void
   7683 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
   7684 {
   7685     nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in);
   7686 }
   7687 NK_API void
   7688 nk_color_hsva_f(float *out_h, float *out_s,
   7689     float *out_v, float *out_a, struct nk_color in)
   7690 {
   7691     struct nk_colorf col;
   7692     nk_color_f(&col.r,&col.g,&col.b,&col.a, in);
   7693     nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col);
   7694 }
   7695 NK_API void
   7696 nk_color_hsva_fv(float *out, struct nk_color in)
   7697 {
   7698     nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
   7699 }
   7700 NK_API void
   7701 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
   7702                 int *out_a, struct nk_color in)
   7703 {
   7704     float h,s,v,a;
   7705     nk_color_hsva_f(&h, &s, &v, &a, in);
   7706     *out_h = (nk_byte)(h * 255.0f);
   7707     *out_s = (nk_byte)(s * 255.0f);
   7708     *out_v = (nk_byte)(v * 255.0f);
   7709     *out_a = (nk_byte)(a * 255.0f);
   7710 }
   7711 NK_API void
   7712 nk_color_hsva_iv(int *out, struct nk_color in)
   7713 {
   7714     nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
   7715 }
   7716 NK_API void
   7717 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
   7718 {
   7719     int tmp[4];
   7720     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
   7721     out[0] = (nk_byte)tmp[0];
   7722     out[1] = (nk_byte)tmp[1];
   7723     out[2] = (nk_byte)tmp[2];
   7724     out[3] = (nk_byte)tmp[3];
   7725 }
   7726 NK_API void
   7727 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
   7728 {
   7729     int tmp[4];
   7730     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
   7731     *h = (nk_byte)tmp[0];
   7732     *s = (nk_byte)tmp[1];
   7733     *v = (nk_byte)tmp[2];
   7734     *a = (nk_byte)tmp[3];
   7735 }
   7736 NK_API void
   7737 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
   7738 {
   7739     int a;
   7740     nk_color_hsva_i(out_h, out_s, out_v, &a, in);
   7741 }
   7742 NK_API void
   7743 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
   7744 {
   7745     int tmp[4];
   7746     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
   7747     *out_h = (nk_byte)tmp[0];
   7748     *out_s = (nk_byte)tmp[1];
   7749     *out_v = (nk_byte)tmp[2];
   7750 }
   7751 NK_API void
   7752 nk_color_hsv_iv(int *out, struct nk_color in)
   7753 {
   7754     nk_color_hsv_i(&out[0], &out[1], &out[2], in);
   7755 }
   7756 NK_API void
   7757 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
   7758 {
   7759     int tmp[4];
   7760     nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
   7761     out[0] = (nk_byte)tmp[0];
   7762     out[1] = (nk_byte)tmp[1];
   7763     out[2] = (nk_byte)tmp[2];
   7764 }
   7765 
   7766 
   7767 
   7768 
   7769 
   7770 /* ===============================================================
   7771  *
   7772  *                              UTF-8
   7773  *
   7774  * ===============================================================*/
   7775 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
   7776 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
   7777 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
   7778 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
   7779 
   7780 NK_INTERN int
   7781 nk_utf_validate(nk_rune *u, int i)
   7782 {
   7783     NK_ASSERT(u);
   7784     if (!u) return 0;
   7785     if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
   7786          NK_BETWEEN(*u, 0xD800, 0xDFFF))
   7787             *u = NK_UTF_INVALID;
   7788     for (i = 1; *u > nk_utfmax[i]; ++i);
   7789     return i;
   7790 }
   7791 NK_INTERN nk_rune
   7792 nk_utf_decode_byte(char c, int *i)
   7793 {
   7794     NK_ASSERT(i);
   7795     if (!i) return 0;
   7796     for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
   7797         if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
   7798             return (nk_byte)(c & ~nk_utfmask[*i]);
   7799     }
   7800     return 0;
   7801 }
   7802 NK_API int
   7803 nk_utf_decode(const char *c, nk_rune *u, int clen)
   7804 {
   7805     int i, j, len, type=0;
   7806     nk_rune udecoded;
   7807 
   7808     NK_ASSERT(c);
   7809     NK_ASSERT(u);
   7810 
   7811     if (!c || !u) return 0;
   7812     if (!clen) return 0;
   7813     *u = NK_UTF_INVALID;
   7814 
   7815     udecoded = nk_utf_decode_byte(c[0], &len);
   7816     if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
   7817         return 1;
   7818 
   7819     for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
   7820         udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
   7821         if (type != 0)
   7822             return j;
   7823     }
   7824     if (j < len)
   7825         return 0;
   7826     *u = udecoded;
   7827     nk_utf_validate(u, len);
   7828     return len;
   7829 }
   7830 NK_INTERN char
   7831 nk_utf_encode_byte(nk_rune u, int i)
   7832 {
   7833     return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
   7834 }
   7835 NK_API int
   7836 nk_utf_encode(nk_rune u, char *c, int clen)
   7837 {
   7838     int len, i;
   7839     len = nk_utf_validate(&u, 0);
   7840     if (clen < len || !len || len > NK_UTF_SIZE)
   7841         return 0;
   7842 
   7843     for (i = len - 1; i != 0; --i) {
   7844         c[i] = nk_utf_encode_byte(u, 0);
   7845         u >>= 6;
   7846     }
   7847     c[0] = nk_utf_encode_byte(u, len);
   7848     return len;
   7849 }
   7850 NK_API int
   7851 nk_utf_len(const char *str, int len)
   7852 {
   7853     const char *text;
   7854     int glyphs = 0;
   7855     int text_len;
   7856     int glyph_len;
   7857     int src_len = 0;
   7858     nk_rune unicode;
   7859 
   7860     NK_ASSERT(str);
   7861     if (!str || !len) return 0;
   7862 
   7863     text = str;
   7864     text_len = len;
   7865     glyph_len = nk_utf_decode(text, &unicode, text_len);
   7866     while (glyph_len && src_len < len) {
   7867         glyphs++;
   7868         src_len = src_len + glyph_len;
   7869         glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
   7870     }
   7871     return glyphs;
   7872 }
   7873 NK_API const char*
   7874 nk_utf_at(const char *buffer, int length, int index,
   7875     nk_rune *unicode, int *len)
   7876 {
   7877     int i = 0;
   7878     int src_len = 0;
   7879     int glyph_len = 0;
   7880     const char *text;
   7881     int text_len;
   7882 
   7883     NK_ASSERT(buffer);
   7884     NK_ASSERT(unicode);
   7885     NK_ASSERT(len);
   7886 
   7887     if (!buffer || !unicode || !len) return 0;
   7888     if (index < 0) {
   7889         *unicode = NK_UTF_INVALID;
   7890         *len = 0;
   7891         return 0;
   7892     }
   7893 
   7894     text = buffer;
   7895     text_len = length;
   7896     glyph_len = nk_utf_decode(text, unicode, text_len);
   7897     while (glyph_len) {
   7898         if (i == index) {
   7899             *len = glyph_len;
   7900             break;
   7901         }
   7902 
   7903         i++;
   7904         src_len = src_len + glyph_len;
   7905         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
   7906     }
   7907     if (i != index) return 0;
   7908     return buffer + src_len;
   7909 }
   7910 
   7911 
   7912 
   7913 
   7914 
   7915 /* ==============================================================
   7916  *
   7917  *                          BUFFER
   7918  *
   7919  * ===============================================================*/
   7920 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   7921 NK_LIB void*
   7922 nk_malloc(nk_handle unused, void *old,nk_size size)
   7923 {
   7924     NK_UNUSED(unused);
   7925     NK_UNUSED(old);
   7926     return malloc(size);
   7927 }
   7928 NK_LIB void
   7929 nk_mfree(nk_handle unused, void *ptr)
   7930 {
   7931     NK_UNUSED(unused);
   7932     free(ptr);
   7933 }
   7934 NK_API void
   7935 nk_buffer_init_default(struct nk_buffer *buffer)
   7936 {
   7937     struct nk_allocator alloc;
   7938     alloc.userdata.ptr = 0;
   7939     alloc.alloc = nk_malloc;
   7940     alloc.free = nk_mfree;
   7941     nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
   7942 }
   7943 #endif
   7944 
   7945 NK_API void
   7946 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
   7947     nk_size initial_size)
   7948 {
   7949     NK_ASSERT(b);
   7950     NK_ASSERT(a);
   7951     NK_ASSERT(initial_size);
   7952     if (!b || !a || !initial_size) return;
   7953 
   7954     nk_zero(b, sizeof(*b));
   7955     b->type = NK_BUFFER_DYNAMIC;
   7956     b->memory.ptr = a->alloc(a->userdata,0, initial_size);
   7957     b->memory.size = initial_size;
   7958     b->size = initial_size;
   7959     b->grow_factor = 2.0f;
   7960     b->pool = *a;
   7961 }
   7962 NK_API void
   7963 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
   7964 {
   7965     NK_ASSERT(b);
   7966     NK_ASSERT(m);
   7967     NK_ASSERT(size);
   7968     if (!b || !m || !size) return;
   7969 
   7970     nk_zero(b, sizeof(*b));
   7971     b->type = NK_BUFFER_FIXED;
   7972     b->memory.ptr = m;
   7973     b->memory.size = size;
   7974     b->size = size;
   7975 }
   7976 NK_LIB void*
   7977 nk_buffer_align(void *unaligned,
   7978     nk_size align, nk_size *alignment,
   7979     enum nk_buffer_allocation_type type)
   7980 {
   7981     void *memory = 0;
   7982     switch (type) {
   7983     default:
   7984     case NK_BUFFER_MAX:
   7985     case NK_BUFFER_FRONT:
   7986         if (align) {
   7987             memory = NK_ALIGN_PTR(unaligned, align);
   7988             *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
   7989         } else {
   7990             memory = unaligned;
   7991             *alignment = 0;
   7992         }
   7993         break;
   7994     case NK_BUFFER_BACK:
   7995         if (align) {
   7996             memory = NK_ALIGN_PTR_BACK(unaligned, align);
   7997             *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
   7998         } else {
   7999             memory = unaligned;
   8000             *alignment = 0;
   8001         }
   8002         break;
   8003     }
   8004     return memory;
   8005 }
   8006 NK_LIB void*
   8007 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
   8008 {
   8009     void *temp;
   8010     nk_size buffer_size;
   8011 
   8012     NK_ASSERT(b);
   8013     NK_ASSERT(size);
   8014     if (!b || !size || !b->pool.alloc || !b->pool.free)
   8015         return 0;
   8016 
   8017     buffer_size = b->memory.size;
   8018     temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
   8019     NK_ASSERT(temp);
   8020     if (!temp) return 0;
   8021 
   8022     *size = capacity;
   8023     if (temp != b->memory.ptr) {
   8024         NK_MEMCPY(temp, b->memory.ptr, buffer_size);
   8025         b->pool.free(b->pool.userdata, b->memory.ptr);
   8026     }
   8027 
   8028     if (b->size == buffer_size) {
   8029         /* no back buffer so just set correct size */
   8030         b->size = capacity;
   8031         return temp;
   8032     } else {
   8033         /* copy back buffer to the end of the new buffer */
   8034         void *dst, *src;
   8035         nk_size back_size;
   8036         back_size = buffer_size - b->size;
   8037         dst = nk_ptr_add(void, temp, capacity - back_size);
   8038         src = nk_ptr_add(void, temp, b->size);
   8039         NK_MEMCPY(dst, src, back_size);
   8040         b->size = capacity - back_size;
   8041     }
   8042     return temp;
   8043 }
   8044 NK_LIB void*
   8045 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
   8046     nk_size size, nk_size align)
   8047 {
   8048     int full;
   8049     nk_size alignment;
   8050     void *unaligned;
   8051     void *memory;
   8052 
   8053     NK_ASSERT(b);
   8054     NK_ASSERT(size);
   8055     if (!b || !size) return 0;
   8056     b->needed += size;
   8057 
   8058     /* calculate total size with needed alignment + size */
   8059     if (type == NK_BUFFER_FRONT)
   8060         unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
   8061     else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
   8062     memory = nk_buffer_align(unaligned, align, &alignment, type);
   8063 
   8064     /* check if buffer has enough memory*/
   8065     if (type == NK_BUFFER_FRONT)
   8066         full = ((b->allocated + size + alignment) > b->size);
   8067     else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
   8068 
   8069     if (full) {
   8070         nk_size capacity;
   8071         if (b->type != NK_BUFFER_DYNAMIC)
   8072             return 0;
   8073         NK_ASSERT(b->pool.alloc && b->pool.free);
   8074         if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
   8075             return 0;
   8076 
   8077         /* buffer is full so allocate bigger buffer if dynamic */
   8078         capacity = (nk_size)((float)b->memory.size * b->grow_factor);
   8079         capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
   8080         b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
   8081         if (!b->memory.ptr) return 0;
   8082 
   8083         /* align newly allocated pointer */
   8084         if (type == NK_BUFFER_FRONT)
   8085             unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
   8086         else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
   8087         memory = nk_buffer_align(unaligned, align, &alignment, type);
   8088     }
   8089     if (type == NK_BUFFER_FRONT)
   8090         b->allocated += size + alignment;
   8091     else b->size -= (size + alignment);
   8092     b->needed += alignment;
   8093     b->calls++;
   8094     return memory;
   8095 }
   8096 NK_API void
   8097 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type,
   8098     const void *memory, nk_size size, nk_size align)
   8099 {
   8100     void *mem = nk_buffer_alloc(b, type, size, align);
   8101     if (!mem) return;
   8102     NK_MEMCPY(mem, memory, size);
   8103 }
   8104 NK_API void
   8105 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
   8106 {
   8107     NK_ASSERT(buffer);
   8108     if (!buffer) return;
   8109     buffer->marker[type].active = nk_true;
   8110     if (type == NK_BUFFER_BACK)
   8111         buffer->marker[type].offset = buffer->size;
   8112     else buffer->marker[type].offset = buffer->allocated;
   8113 }
   8114 NK_API void
   8115 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
   8116 {
   8117     NK_ASSERT(buffer);
   8118     if (!buffer) return;
   8119     if (type == NK_BUFFER_BACK) {
   8120         /* reset back buffer either back to marker or empty */
   8121         buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
   8122         if (buffer->marker[type].active)
   8123             buffer->size = buffer->marker[type].offset;
   8124         else buffer->size = buffer->memory.size;
   8125         buffer->marker[type].active = nk_false;
   8126     } else {
   8127         /* reset front buffer either back to back marker or empty */
   8128         buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
   8129         if (buffer->marker[type].active)
   8130             buffer->allocated = buffer->marker[type].offset;
   8131         else buffer->allocated = 0;
   8132         buffer->marker[type].active = nk_false;
   8133     }
   8134 }
   8135 NK_API void
   8136 nk_buffer_clear(struct nk_buffer *b)
   8137 {
   8138     NK_ASSERT(b);
   8139     if (!b) return;
   8140     b->allocated = 0;
   8141     b->size = b->memory.size;
   8142     b->calls = 0;
   8143     b->needed = 0;
   8144 }
   8145 NK_API void
   8146 nk_buffer_free(struct nk_buffer *b)
   8147 {
   8148     NK_ASSERT(b);
   8149     if (!b || !b->memory.ptr) return;
   8150     if (b->type == NK_BUFFER_FIXED) return;
   8151     if (!b->pool.free) return;
   8152     NK_ASSERT(b->pool.free);
   8153     b->pool.free(b->pool.userdata, b->memory.ptr);
   8154 }
   8155 NK_API void
   8156 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
   8157 {
   8158     NK_ASSERT(b);
   8159     NK_ASSERT(s);
   8160     if (!s || !b) return;
   8161     s->allocated = b->allocated;
   8162     s->size =  b->memory.size;
   8163     s->needed = b->needed;
   8164     s->memory = b->memory.ptr;
   8165     s->calls = b->calls;
   8166 }
   8167 NK_API void*
   8168 nk_buffer_memory(struct nk_buffer *buffer)
   8169 {
   8170     NK_ASSERT(buffer);
   8171     if (!buffer) return 0;
   8172     return buffer->memory.ptr;
   8173 }
   8174 NK_API const void*
   8175 nk_buffer_memory_const(const struct nk_buffer *buffer)
   8176 {
   8177     NK_ASSERT(buffer);
   8178     if (!buffer) return 0;
   8179     return buffer->memory.ptr;
   8180 }
   8181 NK_API nk_size
   8182 nk_buffer_total(struct nk_buffer *buffer)
   8183 {
   8184     NK_ASSERT(buffer);
   8185     if (!buffer) return 0;
   8186     return buffer->memory.size;
   8187 }
   8188 
   8189 
   8190 
   8191 
   8192 
   8193 /* ===============================================================
   8194  *
   8195  *                              STRING
   8196  *
   8197  * ===============================================================*/
   8198 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
   8199 NK_API void
   8200 nk_str_init_default(struct nk_str *str)
   8201 {
   8202     struct nk_allocator alloc;
   8203     alloc.userdata.ptr = 0;
   8204     alloc.alloc = nk_malloc;
   8205     alloc.free = nk_mfree;
   8206     nk_buffer_init(&str->buffer, &alloc, 32);
   8207     str->len = 0;
   8208 }
   8209 #endif
   8210 
   8211 NK_API void
   8212 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
   8213 {
   8214     nk_buffer_init(&str->buffer, alloc, size);
   8215     str->len = 0;
   8216 }
   8217 NK_API void
   8218 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
   8219 {
   8220     nk_buffer_init_fixed(&str->buffer, memory, size);
   8221     str->len = 0;
   8222 }
   8223 NK_API int
   8224 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
   8225 {
   8226     char *mem;
   8227     NK_ASSERT(s);
   8228     NK_ASSERT(str);
   8229     if (!s || !str || !len) return 0;
   8230     mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
   8231     if (!mem) return 0;
   8232     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
   8233     s->len += nk_utf_len(str, len);
   8234     return len;
   8235 }
   8236 NK_API int
   8237 nk_str_append_str_char(struct nk_str *s, const char *str)
   8238 {
   8239     return nk_str_append_text_char(s, str, nk_strlen(str));
   8240 }
   8241 NK_API int
   8242 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
   8243 {
   8244     int i = 0;
   8245     int byte_len = 0;
   8246     nk_rune unicode;
   8247     if (!str || !text || !len) return 0;
   8248     for (i = 0; i < len; ++i)
   8249         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
   8250     nk_str_append_text_char(str, text, byte_len);
   8251     return len;
   8252 }
   8253 NK_API int
   8254 nk_str_append_str_utf8(struct nk_str *str, const char *text)
   8255 {
   8256     int runes = 0;
   8257     int byte_len = 0;
   8258     int num_runes = 0;
   8259     int glyph_len = 0;
   8260     nk_rune unicode;
   8261     if (!str || !text) return 0;
   8262 
   8263     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
   8264     while (unicode != '\0' && glyph_len) {
   8265         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
   8266         byte_len += glyph_len;
   8267         num_runes++;
   8268     }
   8269     nk_str_append_text_char(str, text, byte_len);
   8270     return runes;
   8271 }
   8272 NK_API int
   8273 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
   8274 {
   8275     int i = 0;
   8276     int byte_len = 0;
   8277     nk_glyph glyph;
   8278 
   8279     NK_ASSERT(str);
   8280     if (!str || !text || !len) return 0;
   8281     for (i = 0; i < len; ++i) {
   8282         byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
   8283         if (!byte_len) break;
   8284         nk_str_append_text_char(str, glyph, byte_len);
   8285     }
   8286     return len;
   8287 }
   8288 NK_API int
   8289 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
   8290 {
   8291     int i = 0;
   8292     nk_glyph glyph;
   8293     int byte_len;
   8294     NK_ASSERT(str);
   8295     if (!str || !runes) return 0;
   8296     while (runes[i] != '\0') {
   8297         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
   8298         nk_str_append_text_char(str, glyph, byte_len);
   8299         i++;
   8300     }
   8301     return i;
   8302 }
   8303 NK_API int
   8304 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
   8305 {
   8306     int i;
   8307     void *mem;
   8308     char *src;
   8309     char *dst;
   8310 
   8311     int copylen;
   8312     NK_ASSERT(s);
   8313     NK_ASSERT(str);
   8314     NK_ASSERT(len >= 0);
   8315     if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
   8316     if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
   8317         (s->buffer.type == NK_BUFFER_FIXED)) return 0;
   8318 
   8319     copylen = (int)s->buffer.allocated - pos;
   8320     if (!copylen) {
   8321         nk_str_append_text_char(s, str, len);
   8322         return 1;
   8323     }
   8324     mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
   8325     if (!mem) return 0;
   8326 
   8327     /* memmove */
   8328     NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
   8329     NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
   8330     dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
   8331     src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
   8332     for (i = 0; i < copylen; ++i) *dst-- = *src--;
   8333     mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
   8334     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
   8335     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
   8336     return 1;
   8337 }
   8338 NK_API int
   8339 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
   8340 {
   8341     int glyph_len;
   8342     nk_rune unicode;
   8343     const char *begin;
   8344     const char *buffer;
   8345 
   8346     NK_ASSERT(str);
   8347     NK_ASSERT(cstr);
   8348     NK_ASSERT(len);
   8349     if (!str || !cstr || !len) return 0;
   8350     begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
   8351     if (!str->len)
   8352         return nk_str_append_text_char(str, cstr, len);
   8353     buffer = nk_str_get_const(str);
   8354     if (!begin) return 0;
   8355     return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
   8356 }
   8357 NK_API int
   8358 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
   8359 {
   8360     return nk_str_insert_text_utf8(str, pos, text, len);
   8361 }
   8362 NK_API int
   8363 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
   8364 {
   8365     return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
   8366 }
   8367 NK_API int
   8368 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
   8369 {
   8370     int i = 0;
   8371     int byte_len = 0;
   8372     nk_rune unicode;
   8373 
   8374     NK_ASSERT(str);
   8375     NK_ASSERT(text);
   8376     if (!str || !text || !len) return 0;
   8377     for (i = 0; i < len; ++i)
   8378         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
   8379     nk_str_insert_at_rune(str, pos, text, byte_len);
   8380     return len;
   8381 }
   8382 NK_API int
   8383 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
   8384 {
   8385     int runes = 0;
   8386     int byte_len = 0;
   8387     int num_runes = 0;
   8388     int glyph_len = 0;
   8389     nk_rune unicode;
   8390     if (!str || !text) return 0;
   8391 
   8392     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
   8393     while (unicode != '\0' && glyph_len) {
   8394         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
   8395         byte_len += glyph_len;
   8396         num_runes++;
   8397     }
   8398     nk_str_insert_at_rune(str, pos, text, byte_len);
   8399     return runes;
   8400 }
   8401 NK_API int
   8402 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
   8403 {
   8404     int i = 0;
   8405     int byte_len = 0;
   8406     nk_glyph glyph;
   8407 
   8408     NK_ASSERT(str);
   8409     if (!str || !runes || !len) return 0;
   8410     for (i = 0; i < len; ++i) {
   8411         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
   8412         if (!byte_len) break;
   8413         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
   8414     }
   8415     return len;
   8416 }
   8417 NK_API int
   8418 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
   8419 {
   8420     int i = 0;
   8421     nk_glyph glyph;
   8422     int byte_len;
   8423     NK_ASSERT(str);
   8424     if (!str || !runes) return 0;
   8425     while (runes[i] != '\0') {
   8426         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
   8427         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
   8428         i++;
   8429     }
   8430     return i;
   8431 }
   8432 NK_API void
   8433 nk_str_remove_chars(struct nk_str *s, int len)
   8434 {
   8435     NK_ASSERT(s);
   8436     NK_ASSERT(len >= 0);
   8437     if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
   8438     NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
   8439     s->buffer.allocated -= (nk_size)len;
   8440     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
   8441 }
   8442 NK_API void
   8443 nk_str_remove_runes(struct nk_str *str, int len)
   8444 {
   8445     int index;
   8446     const char *begin;
   8447     const char *end;
   8448     nk_rune unicode;
   8449 
   8450     NK_ASSERT(str);
   8451     NK_ASSERT(len >= 0);
   8452     if (!str || len < 0) return;
   8453     if (len >= str->len) {
   8454         str->len = 0;
   8455         return;
   8456     }
   8457 
   8458     index = str->len - len;
   8459     begin = nk_str_at_rune(str, index, &unicode, &len);
   8460     end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
   8461     nk_str_remove_chars(str, (int)(end-begin)+1);
   8462 }
   8463 NK_API void
   8464 nk_str_delete_chars(struct nk_str *s, int pos, int len)
   8465 {
   8466     NK_ASSERT(s);
   8467     if (!s || !len || (nk_size)pos > s->buffer.allocated ||
   8468         (nk_size)(pos + len) > s->buffer.allocated) return;
   8469 
   8470     if ((nk_size)(pos + len) < s->buffer.allocated) {
   8471         /* memmove */
   8472         char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
   8473         char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
   8474         NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
   8475         NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
   8476         s->buffer.allocated -= (nk_size)len;
   8477     } else nk_str_remove_chars(s, len);
   8478     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
   8479 }
   8480 NK_API void
   8481 nk_str_delete_runes(struct nk_str *s, int pos, int len)
   8482 {
   8483     char *temp;
   8484     nk_rune unicode;
   8485     char *begin;
   8486     char *end;
   8487     int unused;
   8488 
   8489     NK_ASSERT(s);
   8490     NK_ASSERT(s->len >= pos + len);
   8491     if (s->len < pos + len)
   8492         len = NK_CLAMP(0, (s->len - pos), s->len);
   8493     if (!len) return;
   8494 
   8495     temp = (char *)s->buffer.memory.ptr;
   8496     begin = nk_str_at_rune(s, pos, &unicode, &unused);
   8497     if (!begin) return;
   8498     s->buffer.memory.ptr = begin;
   8499     end = nk_str_at_rune(s, len, &unicode, &unused);
   8500     s->buffer.memory.ptr = temp;
   8501     if (!end) return;
   8502     nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
   8503 }
   8504 NK_API char*
   8505 nk_str_at_char(struct nk_str *s, int pos)
   8506 {
   8507     NK_ASSERT(s);
   8508     if (!s || pos > (int)s->buffer.allocated) return 0;
   8509     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
   8510 }
   8511 NK_API char*
   8512 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
   8513 {
   8514     int i = 0;
   8515     int src_len = 0;
   8516     int glyph_len = 0;
   8517     char *text;
   8518     int text_len;
   8519 
   8520     NK_ASSERT(str);
   8521     NK_ASSERT(unicode);
   8522     NK_ASSERT(len);
   8523 
   8524     if (!str || !unicode || !len) return 0;
   8525     if (pos < 0) {
   8526         *unicode = 0;
   8527         *len = 0;
   8528         return 0;
   8529     }
   8530 
   8531     text = (char*)str->buffer.memory.ptr;
   8532     text_len = (int)str->buffer.allocated;
   8533     glyph_len = nk_utf_decode(text, unicode, text_len);
   8534     while (glyph_len) {
   8535         if (i == pos) {
   8536             *len = glyph_len;
   8537             break;
   8538         }
   8539 
   8540         i++;
   8541         src_len = src_len + glyph_len;
   8542         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
   8543     }
   8544     if (i != pos) return 0;
   8545     return text + src_len;
   8546 }
   8547 NK_API const char*
   8548 nk_str_at_char_const(const struct nk_str *s, int pos)
   8549 {
   8550     NK_ASSERT(s);
   8551     if (!s || pos > (int)s->buffer.allocated) return 0;
   8552     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
   8553 }
   8554 NK_API const char*
   8555 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
   8556 {
   8557     int i = 0;
   8558     int src_len = 0;
   8559     int glyph_len = 0;
   8560     char *text;
   8561     int text_len;
   8562 
   8563     NK_ASSERT(str);
   8564     NK_ASSERT(unicode);
   8565     NK_ASSERT(len);
   8566 
   8567     if (!str || !unicode || !len) return 0;
   8568     if (pos < 0) {
   8569         *unicode = 0;
   8570         *len = 0;
   8571         return 0;
   8572     }
   8573 
   8574     text = (char*)str->buffer.memory.ptr;
   8575     text_len = (int)str->buffer.allocated;
   8576     glyph_len = nk_utf_decode(text, unicode, text_len);
   8577     while (glyph_len) {
   8578         if (i == pos) {
   8579             *len = glyph_len;
   8580             break;
   8581         }
   8582 
   8583         i++;
   8584         src_len = src_len + glyph_len;
   8585         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
   8586     }
   8587     if (i != pos) return 0;
   8588     return text + src_len;
   8589 }
   8590 NK_API nk_rune
   8591 nk_str_rune_at(const struct nk_str *str, int pos)
   8592 {
   8593     int len;
   8594     nk_rune unicode = 0;
   8595     nk_str_at_const(str, pos, &unicode, &len);
   8596     return unicode;
   8597 }
   8598 NK_API char*
   8599 nk_str_get(struct nk_str *s)
   8600 {
   8601     NK_ASSERT(s);
   8602     if (!s || !s->len || !s->buffer.allocated) return 0;
   8603     return (char*)s->buffer.memory.ptr;
   8604 }
   8605 NK_API const char*
   8606 nk_str_get_const(const struct nk_str *s)
   8607 {
   8608     NK_ASSERT(s);
   8609     if (!s || !s->len || !s->buffer.allocated) return 0;
   8610     return (const char*)s->buffer.memory.ptr;
   8611 }
   8612 NK_API int
   8613 nk_str_len(struct nk_str *s)
   8614 {
   8615     NK_ASSERT(s);
   8616     if (!s || !s->len || !s->buffer.allocated) return 0;
   8617     return s->len;
   8618 }
   8619 NK_API int
   8620 nk_str_len_char(struct nk_str *s)
   8621 {
   8622     NK_ASSERT(s);
   8623     if (!s || !s->len || !s->buffer.allocated) return 0;
   8624     return (int)s->buffer.allocated;
   8625 }
   8626 NK_API void
   8627 nk_str_clear(struct nk_str *str)
   8628 {
   8629     NK_ASSERT(str);
   8630     nk_buffer_clear(&str->buffer);
   8631     str->len = 0;
   8632 }
   8633 NK_API void
   8634 nk_str_free(struct nk_str *str)
   8635 {
   8636     NK_ASSERT(str);
   8637     nk_buffer_free(&str->buffer);
   8638     str->len = 0;
   8639 }
   8640 
   8641 
   8642 
   8643 
   8644 
   8645 /* ==============================================================
   8646  *
   8647  *                          DRAW
   8648  *
   8649  * ===============================================================*/
   8650 NK_LIB void
   8651 nk_command_buffer_init(struct nk_command_buffer *cb,
   8652     struct nk_buffer *b, enum nk_command_clipping clip)
   8653 {
   8654     NK_ASSERT(cb);
   8655     NK_ASSERT(b);
   8656     if (!cb || !b) return;
   8657     cb->base = b;
   8658     cb->use_clipping = (int)clip;
   8659     cb->begin = b->allocated;
   8660     cb->end = b->allocated;
   8661     cb->last = b->allocated;
   8662 }
   8663 NK_LIB void
   8664 nk_command_buffer_reset(struct nk_command_buffer *b)
   8665 {
   8666     NK_ASSERT(b);
   8667     if (!b) return;
   8668     b->begin = 0;
   8669     b->end = 0;
   8670     b->last = 0;
   8671     b->clip = nk_null_rect;
   8672 #ifdef NK_INCLUDE_COMMAND_USERDATA
   8673     b->userdata.ptr = 0;
   8674 #endif
   8675 }
   8676 NK_LIB void*
   8677 nk_command_buffer_push(struct nk_command_buffer* b,
   8678     enum nk_command_type t, nk_size size)
   8679 {
   8680     NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
   8681     struct nk_command *cmd;
   8682     nk_size alignment;
   8683     void *unaligned;
   8684     void *memory;
   8685 
   8686     NK_ASSERT(b);
   8687     NK_ASSERT(b->base);
   8688     if (!b) return 0;
   8689     cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
   8690     if (!cmd) return 0;
   8691 
   8692     /* make sure the offset to the next command is aligned */
   8693     b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
   8694     unaligned = (nk_byte*)cmd + size;
   8695     memory = NK_ALIGN_PTR(unaligned, align);
   8696     alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
   8697 #ifdef NK_ZERO_COMMAND_MEMORY
   8698     NK_MEMSET(cmd, 0, size + alignment);
   8699 #endif
   8700 
   8701     cmd->type = t;
   8702     cmd->next = b->base->allocated + alignment;
   8703 #ifdef NK_INCLUDE_COMMAND_USERDATA
   8704     cmd->userdata = b->userdata;
   8705 #endif
   8706     b->end = cmd->next;
   8707     return cmd;
   8708 }
   8709 NK_API void
   8710 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
   8711 {
   8712     struct nk_command_scissor *cmd;
   8713     NK_ASSERT(b);
   8714     if (!b) return;
   8715 
   8716     b->clip.x = r.x;
   8717     b->clip.y = r.y;
   8718     b->clip.w = r.w;
   8719     b->clip.h = r.h;
   8720     cmd = (struct nk_command_scissor*)
   8721         nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
   8722 
   8723     if (!cmd) return;
   8724     cmd->x = (short)r.x;
   8725     cmd->y = (short)r.y;
   8726     cmd->w = (unsigned short)NK_MAX(0, r.w);
   8727     cmd->h = (unsigned short)NK_MAX(0, r.h);
   8728 }
   8729 NK_API void
   8730 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
   8731     float x1, float y1, float line_thickness, struct nk_color c)
   8732 {
   8733     struct nk_command_line *cmd;
   8734     NK_ASSERT(b);
   8735     if (!b || line_thickness <= 0) return;
   8736     cmd = (struct nk_command_line*)
   8737         nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
   8738     if (!cmd) return;
   8739     cmd->line_thickness = (unsigned short)line_thickness;
   8740     cmd->begin.x = (short)x0;
   8741     cmd->begin.y = (short)y0;
   8742     cmd->end.x = (short)x1;
   8743     cmd->end.y = (short)y1;
   8744     cmd->color = c;
   8745 }
   8746 NK_API void
   8747 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
   8748     float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
   8749     float bx, float by, float line_thickness, struct nk_color col)
   8750 {
   8751     struct nk_command_curve *cmd;
   8752     NK_ASSERT(b);
   8753     if (!b || col.a == 0 || line_thickness <= 0) return;
   8754 
   8755     cmd = (struct nk_command_curve*)
   8756         nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
   8757     if (!cmd) return;
   8758     cmd->line_thickness = (unsigned short)line_thickness;
   8759     cmd->begin.x = (short)ax;
   8760     cmd->begin.y = (short)ay;
   8761     cmd->ctrl[0].x = (short)ctrl0x;
   8762     cmd->ctrl[0].y = (short)ctrl0y;
   8763     cmd->ctrl[1].x = (short)ctrl1x;
   8764     cmd->ctrl[1].y = (short)ctrl1y;
   8765     cmd->end.x = (short)bx;
   8766     cmd->end.y = (short)by;
   8767     cmd->color = col;
   8768 }
   8769 NK_API void
   8770 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
   8771     float rounding, float line_thickness, struct nk_color c)
   8772 {
   8773     struct nk_command_rect *cmd;
   8774     NK_ASSERT(b);
   8775     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
   8776     if (b->use_clipping) {
   8777         const struct nk_rect *clip = &b->clip;
   8778         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
   8779             clip->x, clip->y, clip->w, clip->h)) return;
   8780     }
   8781     cmd = (struct nk_command_rect*)
   8782         nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
   8783     if (!cmd) return;
   8784     cmd->rounding = (unsigned short)rounding;
   8785     cmd->line_thickness = (unsigned short)line_thickness;
   8786     cmd->x = (short)rect.x;
   8787     cmd->y = (short)rect.y;
   8788     cmd->w = (unsigned short)NK_MAX(0, rect.w);
   8789     cmd->h = (unsigned short)NK_MAX(0, rect.h);
   8790     cmd->color = c;
   8791 }
   8792 NK_API void
   8793 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
   8794     float rounding, struct nk_color c)
   8795 {
   8796     struct nk_command_rect_filled *cmd;
   8797     NK_ASSERT(b);
   8798     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
   8799     if (b->use_clipping) {
   8800         const struct nk_rect *clip = &b->clip;
   8801         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
   8802             clip->x, clip->y, clip->w, clip->h)) return;
   8803     }
   8804 
   8805     cmd = (struct nk_command_rect_filled*)
   8806         nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
   8807     if (!cmd) return;
   8808     cmd->rounding = (unsigned short)rounding;
   8809     cmd->x = (short)rect.x;
   8810     cmd->y = (short)rect.y;
   8811     cmd->w = (unsigned short)NK_MAX(0, rect.w);
   8812     cmd->h = (unsigned short)NK_MAX(0, rect.h);
   8813     cmd->color = c;
   8814 }
   8815 NK_API void
   8816 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
   8817     struct nk_color left, struct nk_color top, struct nk_color right,
   8818     struct nk_color bottom)
   8819 {
   8820     struct nk_command_rect_multi_color *cmd;
   8821     NK_ASSERT(b);
   8822     if (!b || rect.w == 0 || rect.h == 0) return;
   8823     if (b->use_clipping) {
   8824         const struct nk_rect *clip = &b->clip;
   8825         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
   8826             clip->x, clip->y, clip->w, clip->h)) return;
   8827     }
   8828 
   8829     cmd = (struct nk_command_rect_multi_color*)
   8830         nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
   8831     if (!cmd) return;
   8832     cmd->x = (short)rect.x;
   8833     cmd->y = (short)rect.y;
   8834     cmd->w = (unsigned short)NK_MAX(0, rect.w);
   8835     cmd->h = (unsigned short)NK_MAX(0, rect.h);
   8836     cmd->left = left;
   8837     cmd->top = top;
   8838     cmd->right = right;
   8839     cmd->bottom = bottom;
   8840 }
   8841 NK_API void
   8842 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
   8843     float line_thickness, struct nk_color c)
   8844 {
   8845     struct nk_command_circle *cmd;
   8846     if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
   8847     if (b->use_clipping) {
   8848         const struct nk_rect *clip = &b->clip;
   8849         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
   8850             return;
   8851     }
   8852 
   8853     cmd = (struct nk_command_circle*)
   8854         nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
   8855     if (!cmd) return;
   8856     cmd->line_thickness = (unsigned short)line_thickness;
   8857     cmd->x = (short)r.x;
   8858     cmd->y = (short)r.y;
   8859     cmd->w = (unsigned short)NK_MAX(r.w, 0);
   8860     cmd->h = (unsigned short)NK_MAX(r.h, 0);
   8861     cmd->color = c;
   8862 }
   8863 NK_API void
   8864 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
   8865 {
   8866     struct nk_command_circle_filled *cmd;
   8867     NK_ASSERT(b);
   8868     if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
   8869     if (b->use_clipping) {
   8870         const struct nk_rect *clip = &b->clip;
   8871         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
   8872             return;
   8873     }
   8874 
   8875     cmd = (struct nk_command_circle_filled*)
   8876         nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
   8877     if (!cmd) return;
   8878     cmd->x = (short)r.x;
   8879     cmd->y = (short)r.y;
   8880     cmd->w = (unsigned short)NK_MAX(r.w, 0);
   8881     cmd->h = (unsigned short)NK_MAX(r.h, 0);
   8882     cmd->color = c;
   8883 }
   8884 NK_API void
   8885 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
   8886     float a_min, float a_max, float line_thickness, struct nk_color c)
   8887 {
   8888     struct nk_command_arc *cmd;
   8889     if (!b || c.a == 0 || line_thickness <= 0) return;
   8890     cmd = (struct nk_command_arc*)
   8891         nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
   8892     if (!cmd) return;
   8893     cmd->line_thickness = (unsigned short)line_thickness;
   8894     cmd->cx = (short)cx;
   8895     cmd->cy = (short)cy;
   8896     cmd->r = (unsigned short)radius;
   8897     cmd->a[0] = a_min;
   8898     cmd->a[1] = a_max;
   8899     cmd->color = c;
   8900 }
   8901 NK_API void
   8902 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
   8903     float a_min, float a_max, struct nk_color c)
   8904 {
   8905     struct nk_command_arc_filled *cmd;
   8906     NK_ASSERT(b);
   8907     if (!b || c.a == 0) return;
   8908     cmd = (struct nk_command_arc_filled*)
   8909         nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
   8910     if (!cmd) return;
   8911     cmd->cx = (short)cx;
   8912     cmd->cy = (short)cy;
   8913     cmd->r = (unsigned short)radius;
   8914     cmd->a[0] = a_min;
   8915     cmd->a[1] = a_max;
   8916     cmd->color = c;
   8917 }
   8918 NK_API void
   8919 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
   8920     float y1, float x2, float y2, float line_thickness, struct nk_color c)
   8921 {
   8922     struct nk_command_triangle *cmd;
   8923     NK_ASSERT(b);
   8924     if (!b || c.a == 0 || line_thickness <= 0) return;
   8925     if (b->use_clipping) {
   8926         const struct nk_rect *clip = &b->clip;
   8927         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
   8928             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
   8929             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
   8930             return;
   8931     }
   8932 
   8933     cmd = (struct nk_command_triangle*)
   8934         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
   8935     if (!cmd) return;
   8936     cmd->line_thickness = (unsigned short)line_thickness;
   8937     cmd->a.x = (short)x0;
   8938     cmd->a.y = (short)y0;
   8939     cmd->b.x = (short)x1;
   8940     cmd->b.y = (short)y1;
   8941     cmd->c.x = (short)x2;
   8942     cmd->c.y = (short)y2;
   8943     cmd->color = c;
   8944 }
   8945 NK_API void
   8946 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
   8947     float y1, float x2, float y2, struct nk_color c)
   8948 {
   8949     struct nk_command_triangle_filled *cmd;
   8950     NK_ASSERT(b);
   8951     if (!b || c.a == 0) return;
   8952     if (!b) return;
   8953     if (b->use_clipping) {
   8954         const struct nk_rect *clip = &b->clip;
   8955         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
   8956             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
   8957             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
   8958             return;
   8959     }
   8960 
   8961     cmd = (struct nk_command_triangle_filled*)
   8962         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
   8963     if (!cmd) return;
   8964     cmd->a.x = (short)x0;
   8965     cmd->a.y = (short)y0;
   8966     cmd->b.x = (short)x1;
   8967     cmd->b.y = (short)y1;
   8968     cmd->c.x = (short)x2;
   8969     cmd->c.y = (short)y2;
   8970     cmd->color = c;
   8971 }
   8972 NK_API void
   8973 nk_stroke_polygon(struct nk_command_buffer *b,  float *points, int point_count,
   8974     float line_thickness, struct nk_color col)
   8975 {
   8976     int i;
   8977     nk_size size = 0;
   8978     struct nk_command_polygon *cmd;
   8979 
   8980     NK_ASSERT(b);
   8981     if (!b || col.a == 0 || line_thickness <= 0) return;
   8982     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
   8983     cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
   8984     if (!cmd) return;
   8985     cmd->color = col;
   8986     cmd->line_thickness = (unsigned short)line_thickness;
   8987     cmd->point_count = (unsigned short)point_count;
   8988     for (i = 0; i < point_count; ++i) {
   8989         cmd->points[i].x = (short)points[i*2];
   8990         cmd->points[i].y = (short)points[i*2+1];
   8991     }
   8992 }
   8993 NK_API void
   8994 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
   8995     struct nk_color col)
   8996 {
   8997     int i;
   8998     nk_size size = 0;
   8999     struct nk_command_polygon_filled *cmd;
   9000 
   9001     NK_ASSERT(b);
   9002     if (!b || col.a == 0) return;
   9003     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
   9004     cmd = (struct nk_command_polygon_filled*)
   9005         nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
   9006     if (!cmd) return;
   9007     cmd->color = col;
   9008     cmd->point_count = (unsigned short)point_count;
   9009     for (i = 0; i < point_count; ++i) {
   9010         cmd->points[i].x = (short)points[i*2+0];
   9011         cmd->points[i].y = (short)points[i*2+1];
   9012     }
   9013 }
   9014 NK_API void
   9015 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count,
   9016     float line_thickness, struct nk_color col)
   9017 {
   9018     int i;
   9019     nk_size size = 0;
   9020     struct nk_command_polyline *cmd;
   9021 
   9022     NK_ASSERT(b);
   9023     if (!b || col.a == 0 || line_thickness <= 0) return;
   9024     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
   9025     cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
   9026     if (!cmd) return;
   9027     cmd->color = col;
   9028     cmd->point_count = (unsigned short)point_count;
   9029     cmd->line_thickness = (unsigned short)line_thickness;
   9030     for (i = 0; i < point_count; ++i) {
   9031         cmd->points[i].x = (short)points[i*2];
   9032         cmd->points[i].y = (short)points[i*2+1];
   9033     }
   9034 }
   9035 NK_API void
   9036 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
   9037     const struct nk_image *img, struct nk_color col)
   9038 {
   9039     struct nk_command_image *cmd;
   9040     NK_ASSERT(b);
   9041     if (!b) return;
   9042     if (b->use_clipping) {
   9043         const struct nk_rect *c = &b->clip;
   9044         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))
   9045             return;
   9046     }
   9047 
   9048     cmd = (struct nk_command_image*)
   9049         nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
   9050     if (!cmd) return;
   9051     cmd->x = (short)r.x;
   9052     cmd->y = (short)r.y;
   9053     cmd->w = (unsigned short)NK_MAX(0, r.w);
   9054     cmd->h = (unsigned short)NK_MAX(0, r.h);
   9055     cmd->img = *img;
   9056     cmd->col = col;
   9057 }
   9058 NK_API void
   9059 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
   9060     nk_command_custom_callback cb, nk_handle usr)
   9061 {
   9062     struct nk_command_custom *cmd;
   9063     NK_ASSERT(b);
   9064     if (!b) return;
   9065     if (b->use_clipping) {
   9066         const struct nk_rect *c = &b->clip;
   9067         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))
   9068             return;
   9069     }
   9070 
   9071     cmd = (struct nk_command_custom*)
   9072         nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
   9073     if (!cmd) return;
   9074     cmd->x = (short)r.x;
   9075     cmd->y = (short)r.y;
   9076     cmd->w = (unsigned short)NK_MAX(0, r.w);
   9077     cmd->h = (unsigned short)NK_MAX(0, r.h);
   9078     cmd->callback_data = usr;
   9079     cmd->callback = cb;
   9080 }
   9081 NK_API void
   9082 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
   9083     const char *string, int length, const struct nk_user_font *font,
   9084     struct nk_color bg, struct nk_color fg)
   9085 {
   9086     float text_width = 0;
   9087     struct nk_command_text *cmd;
   9088 
   9089     NK_ASSERT(b);
   9090     NK_ASSERT(font);
   9091     if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
   9092     if (b->use_clipping) {
   9093         const struct nk_rect *c = &b->clip;
   9094         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))
   9095             return;
   9096     }
   9097 
   9098     /* make sure text fits inside bounds */
   9099     text_width = font->width(font->userdata, font->height, string, length);
   9100     if (text_width > r.w){
   9101         int glyphs = 0;
   9102         float txt_width = (float)text_width;
   9103         length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
   9104     }
   9105 
   9106     if (!length) return;
   9107     cmd = (struct nk_command_text*)
   9108         nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
   9109     if (!cmd) return;
   9110     cmd->x = (short)r.x;
   9111     cmd->y = (short)r.y;
   9112     cmd->w = (unsigned short)r.w;
   9113     cmd->h = (unsigned short)r.h;
   9114     cmd->background = bg;
   9115     cmd->foreground = fg;
   9116     cmd->font = font;
   9117     cmd->length = length;
   9118     cmd->height = font->height;
   9119     NK_MEMCPY(cmd->string, string, (nk_size)length);
   9120     cmd->string[length] = '\0';
   9121 }
   9122 
   9123 
   9124 
   9125 
   9126 
   9127 /* ===============================================================
   9128  *
   9129  *                              VERTEX
   9130  *
   9131  * ===============================================================*/
   9132 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
   9133 NK_API void
   9134 nk_draw_list_init(struct nk_draw_list *list)
   9135 {
   9136     nk_size i = 0;
   9137     NK_ASSERT(list);
   9138     if (!list) return;
   9139     nk_zero(list, sizeof(*list));
   9140     for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
   9141         const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
   9142         list->circle_vtx[i].x = (float)NK_COS(a);
   9143         list->circle_vtx[i].y = (float)NK_SIN(a);
   9144     }
   9145 }
   9146 NK_API void
   9147 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
   9148     struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
   9149     enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
   9150 {
   9151     NK_ASSERT(canvas);
   9152     NK_ASSERT(config);
   9153     NK_ASSERT(cmds);
   9154     NK_ASSERT(vertices);
   9155     NK_ASSERT(elements);
   9156     if (!canvas || !config || !cmds || !vertices || !elements)
   9157         return;
   9158 
   9159     canvas->buffer = cmds;
   9160     canvas->config = *config;
   9161     canvas->elements = elements;
   9162     canvas->vertices = vertices;
   9163     canvas->line_AA = line_aa;
   9164     canvas->shape_AA = shape_aa;
   9165     canvas->clip_rect = nk_null_rect;
   9166 
   9167     canvas->cmd_offset = 0;
   9168     canvas->element_count = 0;
   9169     canvas->vertex_count = 0;
   9170     canvas->cmd_offset = 0;
   9171     canvas->cmd_count = 0;
   9172     canvas->path_count = 0;
   9173 }
   9174 NK_API const struct nk_draw_command*
   9175 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
   9176 {
   9177     nk_byte *memory;
   9178     nk_size offset;
   9179     const struct nk_draw_command *cmd;
   9180 
   9181     NK_ASSERT(buffer);
   9182     if (!buffer || !buffer->size || !canvas->cmd_count)
   9183         return 0;
   9184 
   9185     memory = (nk_byte*)buffer->memory.ptr;
   9186     offset = buffer->memory.size - canvas->cmd_offset;
   9187     cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
   9188     return cmd;
   9189 }
   9190 NK_API const struct nk_draw_command*
   9191 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
   9192 {
   9193     nk_size size;
   9194     nk_size offset;
   9195     nk_byte *memory;
   9196     const struct nk_draw_command *end;
   9197 
   9198     NK_ASSERT(buffer);
   9199     NK_ASSERT(canvas);
   9200     if (!buffer || !canvas)
   9201         return 0;
   9202 
   9203     memory = (nk_byte*)buffer->memory.ptr;
   9204     size = buffer->memory.size;
   9205     offset = size - canvas->cmd_offset;
   9206     end = nk_ptr_add(const struct nk_draw_command, memory, offset);
   9207     end -= (canvas->cmd_count-1);
   9208     return end;
   9209 }
   9210 NK_API const struct nk_draw_command*
   9211 nk__draw_list_next(const struct nk_draw_command *cmd,
   9212     const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
   9213 {
   9214     const struct nk_draw_command *end;
   9215     NK_ASSERT(buffer);
   9216     NK_ASSERT(canvas);
   9217     if (!cmd || !buffer || !canvas)
   9218         return 0;
   9219 
   9220     end = nk__draw_list_end(canvas, buffer);
   9221     if (cmd <= end) return 0;
   9222     return (cmd-1);
   9223 }
   9224 NK_INTERN struct nk_vec2*
   9225 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
   9226 {
   9227     struct nk_vec2 *points;
   9228     NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
   9229     NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
   9230     points = (struct nk_vec2*)
   9231         nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
   9232                         point_size * (nk_size)count, point_align);
   9233 
   9234     if (!points) return 0;
   9235     if (!list->path_offset) {
   9236         void *memory = nk_buffer_memory(list->buffer);
   9237         list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
   9238     }
   9239     list->path_count += (unsigned int)count;
   9240     return points;
   9241 }
   9242 NK_INTERN struct nk_vec2
   9243 nk_draw_list_path_last(struct nk_draw_list *list)
   9244 {
   9245     void *memory;
   9246     struct nk_vec2 *point;
   9247     NK_ASSERT(list->path_count);
   9248     memory = nk_buffer_memory(list->buffer);
   9249     point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
   9250     point += (list->path_count-1);
   9251     return *point;
   9252 }
   9253 NK_INTERN struct nk_draw_command*
   9254 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
   9255     nk_handle texture)
   9256 {
   9257     NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
   9258     NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
   9259     struct nk_draw_command *cmd;
   9260 
   9261     NK_ASSERT(list);
   9262     cmd = (struct nk_draw_command*)
   9263         nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
   9264 
   9265     if (!cmd) return 0;
   9266     if (!list->cmd_count) {
   9267         nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
   9268         nk_size total = nk_buffer_total(list->buffer);
   9269         memory = nk_ptr_add(nk_byte, memory, total);
   9270         list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
   9271     }
   9272 
   9273     cmd->elem_count = 0;
   9274     cmd->clip_rect = clip;
   9275     cmd->texture = texture;
   9276 #ifdef NK_INCLUDE_COMMAND_USERDATA
   9277     cmd->userdata = list->userdata;
   9278 #endif
   9279 
   9280     list->cmd_count++;
   9281     list->clip_rect = clip;
   9282     return cmd;
   9283 }
   9284 NK_INTERN struct nk_draw_command*
   9285 nk_draw_list_command_last(struct nk_draw_list *list)
   9286 {
   9287     void *memory;
   9288     nk_size size;
   9289     struct nk_draw_command *cmd;
   9290     NK_ASSERT(list->cmd_count);
   9291 
   9292     memory = nk_buffer_memory(list->buffer);
   9293     size = nk_buffer_total(list->buffer);
   9294     cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
   9295     return (cmd - (list->cmd_count-1));
   9296 }
   9297 NK_INTERN void
   9298 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
   9299 {
   9300     NK_ASSERT(list);
   9301     if (!list) return;
   9302     if (!list->cmd_count) {
   9303         nk_draw_list_push_command(list, rect, list->config.null.texture);
   9304     } else {
   9305         struct nk_draw_command *prev = nk_draw_list_command_last(list);
   9306         if (prev->elem_count == 0)
   9307             prev->clip_rect = rect;
   9308         nk_draw_list_push_command(list, rect, prev->texture);
   9309     }
   9310 }
   9311 NK_INTERN void
   9312 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
   9313 {
   9314     NK_ASSERT(list);
   9315     if (!list) return;
   9316     if (!list->cmd_count) {
   9317         nk_draw_list_push_command(list, nk_null_rect, texture);
   9318     } else {
   9319         struct nk_draw_command *prev = nk_draw_list_command_last(list);
   9320         if (prev->elem_count == 0) {
   9321             prev->texture = texture;
   9322         #ifdef NK_INCLUDE_COMMAND_USERDATA
   9323             prev->userdata = list->userdata;
   9324         #endif
   9325     } else if (prev->texture.id != texture.id
   9326         #ifdef NK_INCLUDE_COMMAND_USERDATA
   9327             || prev->userdata.id != list->userdata.id
   9328         #endif
   9329         ) nk_draw_list_push_command(list, prev->clip_rect, texture);
   9330     }
   9331 }
   9332 #ifdef NK_INCLUDE_COMMAND_USERDATA
   9333 NK_API void
   9334 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
   9335 {
   9336     list->userdata = userdata;
   9337 }
   9338 #endif
   9339 NK_INTERN void*
   9340 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
   9341 {
   9342     void *vtx;
   9343     NK_ASSERT(list);
   9344     if (!list) return 0;
   9345     vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
   9346         list->config.vertex_size*count, list->config.vertex_alignment);
   9347     if (!vtx) return 0;
   9348     list->vertex_count += (unsigned int)count;
   9349 
   9350     /* This assert triggers because your are drawing a lot of stuff and nuklear
   9351      * defined `nk_draw_index` as `nk_ushort` to safe space be default.
   9352      *
   9353      * So you reached the maximum number of indicies or rather vertexes.
   9354      * To solve this issue please change typdef `nk_draw_index` to `nk_uint`
   9355      * and don't forget to specify the new element size in your drawing
   9356      * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements`
   9357      * instead of specifing `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`.
   9358      * Sorry for the inconvenience. */
   9359     NK_ASSERT((sizeof(nk_draw_index) == 2 && list->vertex_count < NK_USHORT_MAX &&
   9360         "To many verticies for 16-bit vertex indicies. Please read comment above on how to solve this problem"));
   9361     return vtx;
   9362 }
   9363 NK_INTERN nk_draw_index*
   9364 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
   9365 {
   9366     nk_draw_index *ids;
   9367     struct nk_draw_command *cmd;
   9368     NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
   9369     NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
   9370     NK_ASSERT(list);
   9371     if (!list) return 0;
   9372 
   9373     ids = (nk_draw_index*)
   9374         nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
   9375     if (!ids) return 0;
   9376     cmd = nk_draw_list_command_last(list);
   9377     list->element_count += (unsigned int)count;
   9378     cmd->elem_count += (unsigned int)count;
   9379     return ids;
   9380 }
   9381 NK_INTERN int
   9382 nk_draw_vertex_layout_element_is_end_of_layout(
   9383     const struct nk_draw_vertex_layout_element *element)
   9384 {
   9385     return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
   9386             element->format == NK_FORMAT_COUNT);
   9387 }
   9388 NK_INTERN void
   9389 nk_draw_vertex_color(void *attr, const float *vals,
   9390     enum nk_draw_vertex_layout_format format)
   9391 {
   9392     /* if this triggers you tried to provide a value format for a color */
   9393     float val[4];
   9394     NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
   9395     NK_ASSERT(format <= NK_FORMAT_COLOR_END);
   9396     if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
   9397 
   9398     val[0] = NK_SATURATE(vals[0]);
   9399     val[1] = NK_SATURATE(vals[1]);
   9400     val[2] = NK_SATURATE(vals[2]);
   9401     val[3] = NK_SATURATE(vals[3]);
   9402 
   9403     switch (format) {
   9404     default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
   9405     case NK_FORMAT_R8G8B8A8:
   9406     case NK_FORMAT_R8G8B8: {
   9407         struct nk_color col = nk_rgba_fv(val);
   9408         NK_MEMCPY(attr, &col.r, sizeof(col));
   9409     } break;
   9410     case NK_FORMAT_B8G8R8A8: {
   9411         struct nk_color col = nk_rgba_fv(val);
   9412         struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
   9413         NK_MEMCPY(attr, &bgra, sizeof(bgra));
   9414     } break;
   9415     case NK_FORMAT_R16G15B16: {
   9416         nk_ushort col[3];
   9417         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
   9418         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
   9419         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
   9420         NK_MEMCPY(attr, col, sizeof(col));
   9421     } break;
   9422     case NK_FORMAT_R16G15B16A16: {
   9423         nk_ushort col[4];
   9424         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
   9425         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
   9426         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
   9427         col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX);
   9428         NK_MEMCPY(attr, col, sizeof(col));
   9429     } break;
   9430     case NK_FORMAT_R32G32B32: {
   9431         nk_uint col[3];
   9432         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
   9433         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
   9434         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
   9435         NK_MEMCPY(attr, col, sizeof(col));
   9436     } break;
   9437     case NK_FORMAT_R32G32B32A32: {
   9438         nk_uint col[4];
   9439         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
   9440         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
   9441         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
   9442         col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX);
   9443         NK_MEMCPY(attr, col, sizeof(col));
   9444     } break;
   9445     case NK_FORMAT_R32G32B32A32_FLOAT:
   9446         NK_MEMCPY(attr, val, sizeof(float)*4);
   9447         break;
   9448     case NK_FORMAT_R32G32B32A32_DOUBLE: {
   9449         double col[4];
   9450         col[0] = (double)val[0];
   9451         col[1] = (double)val[1];
   9452         col[2] = (double)val[2];
   9453         col[3] = (double)val[3];
   9454         NK_MEMCPY(attr, col, sizeof(col));
   9455     } break;
   9456     case NK_FORMAT_RGB32:
   9457     case NK_FORMAT_RGBA32: {
   9458         struct nk_color col = nk_rgba_fv(val);
   9459         nk_uint color = nk_color_u32(col);
   9460         NK_MEMCPY(attr, &color, sizeof(color));
   9461     } break; }
   9462 }
   9463 NK_INTERN void
   9464 nk_draw_vertex_element(void *dst, const float *values, int value_count,
   9465     enum nk_draw_vertex_layout_format format)
   9466 {
   9467     int value_index;
   9468     void *attribute = dst;
   9469     /* if this triggers you tried to provide a color format for a value */
   9470     NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
   9471     if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
   9472     for (value_index = 0; value_index < value_count; ++value_index) {
   9473         switch (format) {
   9474         default: NK_ASSERT(0 && "invalid vertex layout format"); break;
   9475         case NK_FORMAT_SCHAR: {
   9476             char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX);
   9477             NK_MEMCPY(attribute, &value, sizeof(value));
   9478             attribute = (void*)((char*)attribute + sizeof(char));
   9479         } break;
   9480         case NK_FORMAT_SSHORT: {
   9481             nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX);
   9482             NK_MEMCPY(attribute, &value, sizeof(value));
   9483             attribute = (void*)((char*)attribute + sizeof(value));
   9484         } break;
   9485         case NK_FORMAT_SINT: {
   9486             nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX);
   9487             NK_MEMCPY(attribute, &value, sizeof(value));
   9488             attribute = (void*)((char*)attribute + sizeof(nk_int));
   9489         } break;
   9490         case NK_FORMAT_UCHAR: {
   9491             unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX);
   9492             NK_MEMCPY(attribute, &value, sizeof(value));
   9493             attribute = (void*)((char*)attribute + sizeof(unsigned char));
   9494         } break;
   9495         case NK_FORMAT_USHORT: {
   9496             nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX);
   9497             NK_MEMCPY(attribute, &value, sizeof(value));
   9498             attribute = (void*)((char*)attribute + sizeof(value));
   9499             } break;
   9500         case NK_FORMAT_UINT: {
   9501             nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX);
   9502             NK_MEMCPY(attribute, &value, sizeof(value));
   9503             attribute = (void*)((char*)attribute + sizeof(nk_uint));
   9504         } break;
   9505         case NK_FORMAT_FLOAT:
   9506             NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
   9507             attribute = (void*)((char*)attribute + sizeof(float));
   9508             break;
   9509         case NK_FORMAT_DOUBLE: {
   9510             double value = (double)values[value_index];
   9511             NK_MEMCPY(attribute, &value, sizeof(value));
   9512             attribute = (void*)((char*)attribute + sizeof(double));
   9513             } break;
   9514         }
   9515     }
   9516 }
   9517 NK_INTERN void*
   9518 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
   9519     struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
   9520 {
   9521     void *result = (void*)((char*)dst + config->vertex_size);
   9522     const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
   9523     while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
   9524         void *address = (void*)((char*)dst + elem_iter->offset);
   9525         switch (elem_iter->attribute) {
   9526         case NK_VERTEX_ATTRIBUTE_COUNT:
   9527         default: NK_ASSERT(0 && "wrong element attribute"); break;
   9528         case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
   9529         case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
   9530         case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
   9531         }
   9532         elem_iter++;
   9533     }
   9534     return result;
   9535 }
   9536 NK_API void
   9537 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
   9538     const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
   9539     float thickness, enum nk_anti_aliasing aliasing)
   9540 {
   9541     nk_size count;
   9542     int thick_line;
   9543     struct nk_colorf col;
   9544     struct nk_colorf col_trans;
   9545     NK_ASSERT(list);
   9546     if (!list || points_count < 2) return;
   9547 
   9548     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
   9549     count = points_count;
   9550     if (!closed) count = points_count-1;
   9551     thick_line = thickness > 1.0f;
   9552 
   9553 #ifdef NK_INCLUDE_COMMAND_USERDATA
   9554     nk_draw_list_push_userdata(list, list->userdata);
   9555 #endif
   9556 
   9557     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
   9558     nk_color_fv(&col.r, color);
   9559     col_trans = col;
   9560     col_trans.a = 0;
   9561 
   9562     if (aliasing == NK_ANTI_ALIASING_ON) {
   9563         /* ANTI-ALIASED STROKE */
   9564         const float AA_SIZE = 1.0f;
   9565         NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
   9566         NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
   9567 
   9568         /* allocate vertices and elements  */
   9569         nk_size i1 = 0;
   9570         nk_size vertex_offset;
   9571         nk_size index = list->vertex_count;
   9572 
   9573         const nk_size idx_count = (thick_line) ?  (count * 18) : (count * 12);
   9574         const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
   9575 
   9576         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
   9577         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
   9578 
   9579         nk_size size;
   9580         struct nk_vec2 *normals, *temp;
   9581         if (!vtx || !ids) return;
   9582 
   9583         /* temporary allocate normals + points */
   9584         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
   9585         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
   9586         size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
   9587         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
   9588         if (!normals) return;
   9589         temp = normals + points_count;
   9590 
   9591         /* make sure vertex pointer is still correct */
   9592         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
   9593 
   9594         /* calculate normals */
   9595         for (i1 = 0; i1 < count; ++i1) {
   9596             const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
   9597             struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
   9598             float len;
   9599 
   9600             /* vec2 inverted length  */
   9601             len = nk_vec2_len_sqr(diff);
   9602             if (len != 0.0f)
   9603                 len = nk_inv_sqrt(len);
   9604             else len = 1.0f;
   9605 
   9606             diff = nk_vec2_muls(diff, len);
   9607             normals[i1].x = diff.y;
   9608             normals[i1].y = -diff.x;
   9609         }
   9610 
   9611         if (!closed)
   9612             normals[points_count-1] = normals[points_count-2];
   9613 
   9614         if (!thick_line) {
   9615             nk_size idx1, i;
   9616             if (!closed) {
   9617                 struct nk_vec2 d;
   9618                 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
   9619                 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
   9620                 d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
   9621                 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
   9622                 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
   9623             }
   9624 
   9625             /* fill elements */
   9626             idx1 = index;
   9627             for (i1 = 0; i1 < count; i1++) {
   9628                 struct nk_vec2 dm;
   9629                 float dmr2;
   9630                 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
   9631                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
   9632 
   9633                 /* average normals */
   9634                 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
   9635                 dmr2 = dm.x * dm.x + dm.y* dm.y;
   9636                 if (dmr2 > 0.000001f) {
   9637                     float scale = 1.0f/dmr2;
   9638                     scale = NK_MIN(100.0f, scale);
   9639                     dm = nk_vec2_muls(dm, scale);
   9640                 }
   9641 
   9642                 dm = nk_vec2_muls(dm, AA_SIZE);
   9643                 temp[i2*2+0] = nk_vec2_add(points[i2], dm);
   9644                 temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
   9645 
   9646                 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
   9647                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
   9648                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
   9649                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
   9650                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
   9651                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
   9652                 ids += 12;
   9653                 idx1 = idx2;
   9654             }
   9655 
   9656             /* fill vertices */
   9657             for (i = 0; i < points_count; ++i) {
   9658                 const struct nk_vec2 uv = list->config.null.uv;
   9659                 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
   9660                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
   9661                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
   9662             }
   9663         } else {
   9664             nk_size idx1, i;
   9665             const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
   9666             if (!closed) {
   9667                 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
   9668                 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
   9669 
   9670                 temp[0] = nk_vec2_add(points[0], d1);
   9671                 temp[1] = nk_vec2_add(points[0], d2);
   9672                 temp[2] = nk_vec2_sub(points[0], d2);
   9673                 temp[3] = nk_vec2_sub(points[0], d1);
   9674 
   9675                 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
   9676                 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
   9677 
   9678                 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
   9679                 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
   9680                 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
   9681                 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
   9682             }
   9683 
   9684             /* add all elements */
   9685             idx1 = index;
   9686             for (i1 = 0; i1 < count; ++i1) {
   9687                 struct nk_vec2 dm_out, dm_in;
   9688                 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
   9689                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
   9690 
   9691                 /* average normals */
   9692                 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
   9693                 float dmr2 = dm.x * dm.x + dm.y* dm.y;
   9694                 if (dmr2 > 0.000001f) {
   9695                     float scale = 1.0f/dmr2;
   9696                     scale = NK_MIN(100.0f, scale);
   9697                     dm = nk_vec2_muls(dm, scale);
   9698                 }
   9699 
   9700                 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
   9701                 dm_in = nk_vec2_muls(dm, half_inner_thickness);
   9702                 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
   9703                 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
   9704                 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
   9705                 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
   9706 
   9707                 /* add indexes */
   9708                 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
   9709                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
   9710                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
   9711                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
   9712                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
   9713                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
   9714                 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
   9715                 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
   9716                 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
   9717                 ids += 18;
   9718                 idx1 = idx2;
   9719             }
   9720 
   9721             /* add vertices */
   9722             for (i = 0; i < points_count; ++i) {
   9723                 const struct nk_vec2 uv = list->config.null.uv;
   9724                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
   9725                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
   9726                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
   9727                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
   9728             }
   9729         }
   9730         /* free temporary normals + points */
   9731         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
   9732     } else {
   9733         /* NON ANTI-ALIASED STROKE */
   9734         nk_size i1 = 0;
   9735         nk_size idx = list->vertex_count;
   9736         const nk_size idx_count = count * 6;
   9737         const nk_size vtx_count = count * 4;
   9738         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
   9739         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
   9740         if (!vtx || !ids) return;
   9741 
   9742         for (i1 = 0; i1 < count; ++i1) {
   9743             float dx, dy;
   9744             const struct nk_vec2 uv = list->config.null.uv;
   9745             const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
   9746             const struct nk_vec2 p1 = points[i1];
   9747             const struct nk_vec2 p2 = points[i2];
   9748             struct nk_vec2 diff = nk_vec2_sub(p2, p1);
   9749             float len;
   9750 
   9751             /* vec2 inverted length  */
   9752             len = nk_vec2_len_sqr(diff);
   9753             if (len != 0.0f)
   9754                 len = nk_inv_sqrt(len);
   9755             else len = 1.0f;
   9756             diff = nk_vec2_muls(diff, len);
   9757 
   9758             /* add vertices */
   9759             dx = diff.x * (thickness * 0.5f);
   9760             dy = diff.y * (thickness * 0.5f);
   9761 
   9762             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
   9763             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
   9764             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
   9765             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
   9766 
   9767             ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
   9768             ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
   9769             ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
   9770 
   9771             ids += 6;
   9772             idx += 4;
   9773         }
   9774     }
   9775 }
   9776 NK_API void
   9777 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
   9778     const struct nk_vec2 *points, const unsigned int points_count,
   9779     struct nk_color color, enum nk_anti_aliasing aliasing)
   9780 {
   9781     struct nk_colorf col;
   9782     struct nk_colorf col_trans;
   9783 
   9784     NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
   9785     NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
   9786     NK_ASSERT(list);
   9787     if (!list || points_count < 3) return;
   9788 
   9789 #ifdef NK_INCLUDE_COMMAND_USERDATA
   9790     nk_draw_list_push_userdata(list, list->userdata);
   9791 #endif
   9792 
   9793     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
   9794     nk_color_fv(&col.r, color);
   9795     col_trans = col;
   9796     col_trans.a = 0;
   9797 
   9798     if (aliasing == NK_ANTI_ALIASING_ON) {
   9799         nk_size i = 0;
   9800         nk_size i0 = 0;
   9801         nk_size i1 = 0;
   9802 
   9803         const float AA_SIZE = 1.0f;
   9804         nk_size vertex_offset = 0;
   9805         nk_size index = list->vertex_count;
   9806 
   9807         const nk_size idx_count = (points_count-2)*3 + points_count*6;
   9808         const nk_size vtx_count = (points_count*2);
   9809 
   9810         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
   9811         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
   9812 
   9813         nk_size size = 0;
   9814         struct nk_vec2 *normals = 0;
   9815         unsigned int vtx_inner_idx = (unsigned int)(index + 0);
   9816         unsigned int vtx_outer_idx = (unsigned int)(index + 1);
   9817         if (!vtx || !ids) return;
   9818 
   9819         /* temporary allocate normals */
   9820         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
   9821         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
   9822         size = pnt_size * points_count;
   9823         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
   9824         if (!normals) return;
   9825         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
   9826 
   9827         /* add elements */
   9828         for (i = 2; i < points_count; i++) {
   9829             ids[0] = (nk_draw_index)(vtx_inner_idx);
   9830             ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
   9831             ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
   9832             ids += 3;
   9833         }
   9834 
   9835         /* compute normals */
   9836         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
   9837             struct nk_vec2 p0 = points[i0];
   9838             struct nk_vec2 p1 = points[i1];
   9839             struct nk_vec2 diff = nk_vec2_sub(p1, p0);
   9840 
   9841             /* vec2 inverted length  */
   9842             float len = nk_vec2_len_sqr(diff);
   9843             if (len != 0.0f)
   9844                 len = nk_inv_sqrt(len);
   9845             else len = 1.0f;
   9846             diff = nk_vec2_muls(diff, len);
   9847 
   9848             normals[i0].x = diff.y;
   9849             normals[i0].y = -diff.x;
   9850         }
   9851 
   9852         /* add vertices + indexes */
   9853         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
   9854             const struct nk_vec2 uv = list->config.null.uv;
   9855             struct nk_vec2 n0 = normals[i0];
   9856             struct nk_vec2 n1 = normals[i1];
   9857             struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
   9858             float dmr2 = dm.x*dm.x + dm.y*dm.y;
   9859             if (dmr2 > 0.000001f) {
   9860                 float scale = 1.0f / dmr2;
   9861                 scale = NK_MIN(scale, 100.0f);
   9862                 dm = nk_vec2_muls(dm, scale);
   9863             }
   9864             dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
   9865 
   9866             /* add vertices */
   9867             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
   9868             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
   9869 
   9870             /* add indexes */
   9871             ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
   9872             ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
   9873             ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
   9874             ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
   9875             ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
   9876             ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
   9877             ids += 6;
   9878         }
   9879         /* free temporary normals + points */
   9880         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
   9881     } else {
   9882         nk_size i = 0;
   9883         nk_size index = list->vertex_count;
   9884         const nk_size idx_count = (points_count-2)*3;
   9885         const nk_size vtx_count = points_count;
   9886         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
   9887         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
   9888 
   9889         if (!vtx || !ids) return;
   9890         for (i = 0; i < vtx_count; ++i)
   9891             vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
   9892         for (i = 2; i < points_count; ++i) {
   9893             ids[0] = (nk_draw_index)index;
   9894             ids[1] = (nk_draw_index)(index+ i - 1);
   9895             ids[2] = (nk_draw_index)(index+i);
   9896             ids += 3;
   9897         }
   9898     }
   9899 }
   9900 NK_API void
   9901 nk_draw_list_path_clear(struct nk_draw_list *list)
   9902 {
   9903     NK_ASSERT(list);
   9904     if (!list) return;
   9905     nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
   9906     list->path_count = 0;
   9907     list->path_offset = 0;
   9908 }
   9909 NK_API void
   9910 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
   9911 {
   9912     struct nk_vec2 *points = 0;
   9913     struct nk_draw_command *cmd = 0;
   9914     NK_ASSERT(list);
   9915     if (!list) return;
   9916     if (!list->cmd_count)
   9917         nk_draw_list_add_clip(list, nk_null_rect);
   9918 
   9919     cmd = nk_draw_list_command_last(list);
   9920     if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
   9921         nk_draw_list_push_image(list, list->config.null.texture);
   9922 
   9923     points = nk_draw_list_alloc_path(list, 1);
   9924     if (!points) return;
   9925     points[0] = pos;
   9926 }
   9927 NK_API void
   9928 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
   9929     float radius, int a_min, int a_max)
   9930 {
   9931     int a = 0;
   9932     NK_ASSERT(list);
   9933     if (!list) return;
   9934     if (a_min <= a_max) {
   9935         for (a = a_min; a <= a_max; a++) {
   9936             const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
   9937             const float x = center.x + c.x * radius;
   9938             const float y = center.y + c.y * radius;
   9939             nk_draw_list_path_line_to(list, nk_vec2(x, y));
   9940         }
   9941     }
   9942 }
   9943 NK_API void
   9944 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
   9945     float radius, float a_min, float a_max, unsigned int segments)
   9946 {
   9947     unsigned int i = 0;
   9948     NK_ASSERT(list);
   9949     if (!list) return;
   9950     if (radius == 0.0f) return;
   9951 
   9952     /*  This algorithm for arc drawing relies on these two trigonometric identities[1]:
   9953             sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
   9954             cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
   9955 
   9956         Two coordinates (x, y) of a point on a circle centered on
   9957         the origin can be written in polar form as:
   9958             x = r * cos(a)
   9959             y = r * sin(a)
   9960         where r is the radius of the circle,
   9961             a is the angle between (x, y) and the origin.
   9962 
   9963         This allows us to rotate the coordinates around the
   9964         origin by an angle b using the following transformation:
   9965             x' = r * cos(a + b) = x * cos(b) - y * sin(b)
   9966             y' = r * sin(a + b) = y * cos(b) + x * sin(b)
   9967 
   9968         [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
   9969     */
   9970     {const float d_angle = (a_max - a_min) / (float)segments;
   9971     const float sin_d = (float)NK_SIN(d_angle);
   9972     const float cos_d = (float)NK_COS(d_angle);
   9973 
   9974     float cx = (float)NK_COS(a_min) * radius;
   9975     float cy = (float)NK_SIN(a_min) * radius;
   9976     for(i = 0; i <= segments; ++i) {
   9977         float new_cx, new_cy;
   9978         const float x = center.x + cx;
   9979         const float y = center.y + cy;
   9980         nk_draw_list_path_line_to(list, nk_vec2(x, y));
   9981 
   9982         new_cx = cx * cos_d - cy * sin_d;
   9983         new_cy = cy * cos_d + cx * sin_d;
   9984         cx = new_cx;
   9985         cy = new_cy;
   9986     }}
   9987 }
   9988 NK_API void
   9989 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
   9990     struct nk_vec2 b, float rounding)
   9991 {
   9992     float r;
   9993     NK_ASSERT(list);
   9994     if (!list) return;
   9995     r = rounding;
   9996     r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
   9997     r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
   9998 
   9999     if (r == 0.0f) {
  10000         nk_draw_list_path_line_to(list, a);
  10001         nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
  10002         nk_draw_list_path_line_to(list, b);
  10003         nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
  10004     } else {
  10005         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
  10006         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
  10007         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
  10008         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
  10009     }
  10010 }
  10011 NK_API void
  10012 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
  10013     struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
  10014 {
  10015     float t_step;
  10016     unsigned int i_step;
  10017     struct nk_vec2 p1;
  10018 
  10019     NK_ASSERT(list);
  10020     NK_ASSERT(list->path_count);
  10021     if (!list || !list->path_count) return;
  10022     num_segments = NK_MAX(num_segments, 1);
  10023 
  10024     p1 = nk_draw_list_path_last(list);
  10025     t_step = 1.0f/(float)num_segments;
  10026     for (i_step = 1; i_step <= num_segments; ++i_step) {
  10027         float t = t_step * (float)i_step;
  10028         float u = 1.0f - t;
  10029         float w1 = u*u*u;
  10030         float w2 = 3*u*u*t;
  10031         float w3 = 3*u*t*t;
  10032         float w4 = t * t *t;
  10033         float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
  10034         float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
  10035         nk_draw_list_path_line_to(list, nk_vec2(x,y));
  10036     }
  10037 }
  10038 NK_API void
  10039 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
  10040 {
  10041     struct nk_vec2 *points;
  10042     NK_ASSERT(list);
  10043     if (!list) return;
  10044     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
  10045     nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
  10046     nk_draw_list_path_clear(list);
  10047 }
  10048 NK_API void
  10049 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
  10050     enum nk_draw_list_stroke closed, float thickness)
  10051 {
  10052     struct nk_vec2 *points;
  10053     NK_ASSERT(list);
  10054     if (!list) return;
  10055     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
  10056     nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
  10057         closed, thickness, list->config.line_AA);
  10058     nk_draw_list_path_clear(list);
  10059 }
  10060 NK_API void
  10061 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
  10062     struct nk_vec2 b, struct nk_color col, float thickness)
  10063 {
  10064     NK_ASSERT(list);
  10065     if (!list || !col.a) return;
  10066     if (list->line_AA == NK_ANTI_ALIASING_ON) {
  10067         nk_draw_list_path_line_to(list, a);
  10068         nk_draw_list_path_line_to(list, b);
  10069     } else {
  10070         nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
  10071         nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
  10072     }
  10073     nk_draw_list_path_stroke(list,  col, NK_STROKE_OPEN, thickness);
  10074 }
  10075 NK_API void
  10076 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
  10077     struct nk_color col, float rounding)
  10078 {
  10079     NK_ASSERT(list);
  10080     if (!list || !col.a) return;
  10081 
  10082     if (list->line_AA == NK_ANTI_ALIASING_ON) {
  10083         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
  10084             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
  10085     } else {
  10086         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
  10087             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
  10088     } nk_draw_list_path_fill(list,  col);
  10089 }
  10090 NK_API void
  10091 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
  10092     struct nk_color col, float rounding, float thickness)
  10093 {
  10094     NK_ASSERT(list);
  10095     if (!list || !col.a) return;
  10096     if (list->line_AA == NK_ANTI_ALIASING_ON) {
  10097         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
  10098             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
  10099     } else {
  10100         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
  10101             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
  10102     } nk_draw_list_path_stroke(list,  col, NK_STROKE_CLOSED, thickness);
  10103 }
  10104 NK_API void
  10105 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
  10106     struct nk_color left, struct nk_color top, struct nk_color right,
  10107     struct nk_color bottom)
  10108 {
  10109     void *vtx;
  10110     struct nk_colorf col_left, col_top;
  10111     struct nk_colorf col_right, col_bottom;
  10112     nk_draw_index *idx;
  10113     nk_draw_index index;
  10114 
  10115     nk_color_fv(&col_left.r, left);
  10116     nk_color_fv(&col_right.r, right);
  10117     nk_color_fv(&col_top.r, top);
  10118     nk_color_fv(&col_bottom.r, bottom);
  10119 
  10120     NK_ASSERT(list);
  10121     if (!list) return;
  10122 
  10123     nk_draw_list_push_image(list, list->config.null.texture);
  10124     index = (nk_draw_index)list->vertex_count;
  10125     vtx = nk_draw_list_alloc_vertices(list, 4);
  10126     idx = nk_draw_list_alloc_elements(list, 6);
  10127     if (!vtx || !idx) return;
  10128 
  10129     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
  10130     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
  10131     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
  10132 
  10133     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
  10134     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
  10135     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
  10136     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
  10137 }
  10138 NK_API void
  10139 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
  10140     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
  10141 {
  10142     NK_ASSERT(list);
  10143     if (!list || !col.a) return;
  10144     nk_draw_list_path_line_to(list, a);
  10145     nk_draw_list_path_line_to(list, b);
  10146     nk_draw_list_path_line_to(list, c);
  10147     nk_draw_list_path_fill(list, col);
  10148 }
  10149 NK_API void
  10150 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
  10151     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
  10152 {
  10153     NK_ASSERT(list);
  10154     if (!list || !col.a) return;
  10155     nk_draw_list_path_line_to(list, a);
  10156     nk_draw_list_path_line_to(list, b);
  10157     nk_draw_list_path_line_to(list, c);
  10158     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
  10159 }
  10160 NK_API void
  10161 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
  10162     float radius, struct nk_color col, unsigned int segs)
  10163 {
  10164     float a_max;
  10165     NK_ASSERT(list);
  10166     if (!list || !col.a) return;
  10167     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
  10168     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
  10169     nk_draw_list_path_fill(list, col);
  10170 }
  10171 NK_API void
  10172 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
  10173     float radius, struct nk_color col, unsigned int segs, float thickness)
  10174 {
  10175     float a_max;
  10176     NK_ASSERT(list);
  10177     if (!list || !col.a) return;
  10178     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
  10179     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
  10180     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
  10181 }
  10182 NK_API void
  10183 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
  10184     struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
  10185     struct nk_color col, unsigned int segments, float thickness)
  10186 {
  10187     NK_ASSERT(list);
  10188     if (!list || !col.a) return;
  10189     nk_draw_list_path_line_to(list, p0);
  10190     nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
  10191     nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
  10192 }
  10193 NK_INTERN void
  10194 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
  10195     struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
  10196     struct nk_color color)
  10197 {
  10198     void *vtx;
  10199     struct nk_vec2 uvb;
  10200     struct nk_vec2 uvd;
  10201     struct nk_vec2 b;
  10202     struct nk_vec2 d;
  10203 
  10204     struct nk_colorf col;
  10205     nk_draw_index *idx;
  10206     nk_draw_index index;
  10207     NK_ASSERT(list);
  10208     if (!list) return;
  10209 
  10210     nk_color_fv(&col.r, color);
  10211     uvb = nk_vec2(uvc.x, uva.y);
  10212     uvd = nk_vec2(uva.x, uvc.y);
  10213     b = nk_vec2(c.x, a.y);
  10214     d = nk_vec2(a.x, c.y);
  10215 
  10216     index = (nk_draw_index)list->vertex_count;
  10217     vtx = nk_draw_list_alloc_vertices(list, 4);
  10218     idx = nk_draw_list_alloc_elements(list, 6);
  10219     if (!vtx || !idx) return;
  10220 
  10221     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
  10222     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
  10223     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
  10224 
  10225     vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
  10226     vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
  10227     vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
  10228     vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
  10229 }
  10230 NK_API void
  10231 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
  10232     struct nk_rect rect, struct nk_color color)
  10233 {
  10234     NK_ASSERT(list);
  10235     if (!list) return;
  10236     /* push new command with given texture */
  10237     nk_draw_list_push_image(list, texture.handle);
  10238     if (nk_image_is_subimage(&texture)) {
  10239         /* add region inside of the texture  */
  10240         struct nk_vec2 uv[2];
  10241         uv[0].x = (float)texture.region[0]/(float)texture.w;
  10242         uv[0].y = (float)texture.region[1]/(float)texture.h;
  10243         uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
  10244         uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
  10245         nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
  10246             nk_vec2(rect.x + rect.w, rect.y + rect.h),  uv[0], uv[1], color);
  10247     } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
  10248             nk_vec2(rect.x + rect.w, rect.y + rect.h),
  10249             nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
  10250 }
  10251 NK_API void
  10252 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
  10253     struct nk_rect rect, const char *text, int len, float font_height,
  10254     struct nk_color fg)
  10255 {
  10256     float x = 0;
  10257     int text_len = 0;
  10258     nk_rune unicode = 0;
  10259     nk_rune next = 0;
  10260     int glyph_len = 0;
  10261     int next_glyph_len = 0;
  10262     struct nk_user_font_glyph g;
  10263 
  10264     NK_ASSERT(list);
  10265     if (!list || !len || !text) return;
  10266     if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
  10267         list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
  10268 
  10269     nk_draw_list_push_image(list, font->texture);
  10270     x = rect.x;
  10271     glyph_len = nk_utf_decode(text, &unicode, len);
  10272     if (!glyph_len) return;
  10273 
  10274     /* draw every glyph image */
  10275     fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
  10276     while (text_len < len && glyph_len) {
  10277         float gx, gy, gh, gw;
  10278         float char_width = 0;
  10279         if (unicode == NK_UTF_INVALID) break;
  10280 
  10281         /* query currently drawn glyph information */
  10282         next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
  10283         font->query(font->userdata, font_height, &g, unicode,
  10284                     (next == NK_UTF_INVALID) ? '\0' : next);
  10285 
  10286         /* calculate and draw glyph drawing rectangle and image */
  10287         gx = x + g.offset.x;
  10288         gy = rect.y + g.offset.y;
  10289         gw = g.width; gh = g.height;
  10290         char_width = g.xadvance;
  10291         nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
  10292             g.uv[0], g.uv[1], fg);
  10293 
  10294         /* offset next glyph */
  10295         text_len += glyph_len;
  10296         x += char_width;
  10297         glyph_len = next_glyph_len;
  10298         unicode = next;
  10299     }
  10300 }
  10301 NK_API nk_flags
  10302 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
  10303     struct nk_buffer *vertices, struct nk_buffer *elements,
  10304     const struct nk_convert_config *config)
  10305 {
  10306     nk_flags res = NK_CONVERT_SUCCESS;
  10307     const struct nk_command *cmd;
  10308     NK_ASSERT(ctx);
  10309     NK_ASSERT(cmds);
  10310     NK_ASSERT(vertices);
  10311     NK_ASSERT(elements);
  10312     NK_ASSERT(config);
  10313     NK_ASSERT(config->vertex_layout);
  10314     NK_ASSERT(config->vertex_size);
  10315     if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
  10316         return NK_CONVERT_INVALID_PARAM;
  10317 
  10318     nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
  10319         config->line_AA, config->shape_AA);
  10320     nk_foreach(cmd, ctx)
  10321     {
  10322 #ifdef NK_INCLUDE_COMMAND_USERDATA
  10323         ctx->draw_list.userdata = cmd->userdata;
  10324 #endif
  10325         switch (cmd->type) {
  10326         case NK_COMMAND_NOP: break;
  10327         case NK_COMMAND_SCISSOR: {
  10328             const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
  10329             nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
  10330         } break;
  10331         case NK_COMMAND_LINE: {
  10332             const struct nk_command_line *l = (const struct nk_command_line*)cmd;
  10333             nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
  10334                 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
  10335         } break;
  10336         case NK_COMMAND_CURVE: {
  10337             const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
  10338             nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
  10339                 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
  10340                 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
  10341                 config->curve_segment_count, q->line_thickness);
  10342         } break;
  10343         case NK_COMMAND_RECT: {
  10344             const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
  10345             nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
  10346                 r->color, (float)r->rounding, r->line_thickness);
  10347         } break;
  10348         case NK_COMMAND_RECT_FILLED: {
  10349             const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
  10350             nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
  10351                 r->color, (float)r->rounding);
  10352         } break;
  10353         case NK_COMMAND_RECT_MULTI_COLOR: {
  10354             const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
  10355             nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
  10356                 r->left, r->top, r->right, r->bottom);
  10357         } break;
  10358         case NK_COMMAND_CIRCLE: {
  10359             const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
  10360             nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
  10361                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
  10362                 config->circle_segment_count, c->line_thickness);
  10363         } break;
  10364         case NK_COMMAND_CIRCLE_FILLED: {
  10365             const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
  10366             nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
  10367                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
  10368                 config->circle_segment_count);
  10369         } break;
  10370         case NK_COMMAND_ARC: {
  10371             const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
  10372             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
  10373             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
  10374                 c->a[0], c->a[1], config->arc_segment_count);
  10375             nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
  10376         } break;
  10377         case NK_COMMAND_ARC_FILLED: {
  10378             const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
  10379             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
  10380             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
  10381                 c->a[0], c->a[1], config->arc_segment_count);
  10382             nk_draw_list_path_fill(&ctx->draw_list, c->color);
  10383         } break;
  10384         case NK_COMMAND_TRIANGLE: {
  10385             const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
  10386             nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
  10387                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
  10388                 t->line_thickness);
  10389         } break;
  10390         case NK_COMMAND_TRIANGLE_FILLED: {
  10391             const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
  10392             nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
  10393                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
  10394         } break;
  10395         case NK_COMMAND_POLYGON: {
  10396             int i;
  10397             const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
  10398             for (i = 0; i < p->point_count; ++i) {
  10399                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
  10400                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
  10401             }
  10402             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
  10403         } break;
  10404         case NK_COMMAND_POLYGON_FILLED: {
  10405             int i;
  10406             const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
  10407             for (i = 0; i < p->point_count; ++i) {
  10408                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
  10409                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
  10410             }
  10411             nk_draw_list_path_fill(&ctx->draw_list, p->color);
  10412         } break;
  10413         case NK_COMMAND_POLYLINE: {
  10414             int i;
  10415             const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
  10416             for (i = 0; i < p->point_count; ++i) {
  10417                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
  10418                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
  10419             }
  10420             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
  10421         } break;
  10422         case NK_COMMAND_TEXT: {
  10423             const struct nk_command_text *t = (const struct nk_command_text*)cmd;
  10424             nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
  10425                 t->string, t->length, t->height, t->foreground);
  10426         } break;
  10427         case NK_COMMAND_IMAGE: {
  10428             const struct nk_command_image *i = (const struct nk_command_image*)cmd;
  10429             nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
  10430         } break;
  10431         case NK_COMMAND_CUSTOM: {
  10432             const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
  10433             c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
  10434         } break;
  10435         default: break;
  10436         }
  10437     }
  10438     res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
  10439     res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
  10440     res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
  10441     return res;
  10442 }
  10443 NK_API const struct nk_draw_command*
  10444 nk__draw_begin(const struct nk_context *ctx,
  10445     const struct nk_buffer *buffer)
  10446 {
  10447     return nk__draw_list_begin(&ctx->draw_list, buffer);
  10448 }
  10449 NK_API const struct nk_draw_command*
  10450 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
  10451 {
  10452     return nk__draw_list_end(&ctx->draw_list, buffer);
  10453 }
  10454 NK_API const struct nk_draw_command*
  10455 nk__draw_next(const struct nk_draw_command *cmd,
  10456     const struct nk_buffer *buffer, const struct nk_context *ctx)
  10457 {
  10458     return nk__draw_list_next(cmd, buffer, &ctx->draw_list);
  10459 }
  10460 #endif
  10461 
  10462 
  10463 
  10464 
  10465 
  10466 #ifdef NK_INCLUDE_FONT_BAKING
  10467 /* -------------------------------------------------------------
  10468  *
  10469  *                          RECT PACK
  10470  *
  10471  * --------------------------------------------------------------*/
  10472 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
  10473 /* Sean Barrett 2014 */
  10474 #define NK_RP__MAXVAL  0xffff
  10475 typedef unsigned short nk_rp_coord;
  10476 
  10477 struct nk_rp_rect {
  10478     /* reserved for your use: */
  10479     int id;
  10480     /* input: */
  10481     nk_rp_coord w, h;
  10482     /* output: */
  10483     nk_rp_coord x, y;
  10484     int was_packed;
  10485     /* non-zero if valid packing */
  10486 }; /* 16 bytes, nominally */
  10487 
  10488 struct nk_rp_node {
  10489     nk_rp_coord  x,y;
  10490     struct nk_rp_node  *next;
  10491 };
  10492 
  10493 struct nk_rp_context {
  10494     int width;
  10495     int height;
  10496     int align;
  10497     int init_mode;
  10498     int heuristic;
  10499     int num_nodes;
  10500     struct nk_rp_node *active_head;
  10501     struct nk_rp_node *free_head;
  10502     struct nk_rp_node extra[2];
  10503     /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
  10504 };
  10505 
  10506 struct nk_rp__findresult {
  10507     int x,y;
  10508     struct nk_rp_node **prev_link;
  10509 };
  10510 
  10511 enum NK_RP_HEURISTIC {
  10512     NK_RP_HEURISTIC_Skyline_default=0,
  10513     NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
  10514     NK_RP_HEURISTIC_Skyline_BF_sortHeight
  10515 };
  10516 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
  10517 
  10518 NK_INTERN void
  10519 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
  10520 {
  10521     if (allow_out_of_mem)
  10522         /* if it's ok to run out of memory, then don't bother aligning them; */
  10523         /* this gives better packing, but may fail due to OOM (even though */
  10524         /* the rectangles easily fit). @TODO a smarter approach would be to only */
  10525         /* quantize once we've hit OOM, then we could get rid of this parameter. */
  10526         context->align = 1;
  10527     else {
  10528         /* if it's not ok to run out of memory, then quantize the widths */
  10529         /* so that num_nodes is always enough nodes. */
  10530         /* */
  10531         /* I.e. num_nodes * align >= width */
  10532         /*                  align >= width / num_nodes */
  10533         /*                  align = ceil(width/num_nodes) */
  10534         context->align = (context->width + context->num_nodes-1) / context->num_nodes;
  10535     }
  10536 }
  10537 NK_INTERN void
  10538 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
  10539     struct nk_rp_node *nodes, int num_nodes)
  10540 {
  10541     int i;
  10542 #ifndef STBRP_LARGE_RECTS
  10543     NK_ASSERT(width <= 0xffff && height <= 0xffff);
  10544 #endif
  10545 
  10546     for (i=0; i < num_nodes-1; ++i)
  10547         nodes[i].next = &nodes[i+1];
  10548     nodes[i].next = 0;
  10549     context->init_mode = NK_RP__INIT_skyline;
  10550     context->heuristic = NK_RP_HEURISTIC_Skyline_default;
  10551     context->free_head = &nodes[0];
  10552     context->active_head = &context->extra[0];
  10553     context->width = width;
  10554     context->height = height;
  10555     context->num_nodes = num_nodes;
  10556     nk_rp_setup_allow_out_of_mem(context, 0);
  10557 
  10558     /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
  10559     context->extra[0].x = 0;
  10560     context->extra[0].y = 0;
  10561     context->extra[0].next = &context->extra[1];
  10562     context->extra[1].x = (nk_rp_coord) width;
  10563     context->extra[1].y = 65535;
  10564     context->extra[1].next = 0;
  10565 }
  10566 /* find minimum y position if it starts at x1 */
  10567 NK_INTERN int
  10568 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
  10569     int x0, int width, int *pwaste)
  10570 {
  10571     struct nk_rp_node *node = first;
  10572     int x1 = x0 + width;
  10573     int min_y, visited_width, waste_area;
  10574     NK_ASSERT(first->x <= x0);
  10575     NK_UNUSED(c);
  10576 
  10577     NK_ASSERT(node->next->x > x0);
  10578     /* we ended up handling this in the caller for efficiency */
  10579     NK_ASSERT(node->x <= x0);
  10580 
  10581     min_y = 0;
  10582     waste_area = 0;
  10583     visited_width = 0;
  10584     while (node->x < x1)
  10585     {
  10586         if (node->y > min_y) {
  10587             /* raise min_y higher. */
  10588             /* we've accounted for all waste up to min_y, */
  10589             /* but we'll now add more waste for everything we've visited */
  10590             waste_area += visited_width * (node->y - min_y);
  10591             min_y = node->y;
  10592             /* the first time through, visited_width might be reduced */
  10593             if (node->x < x0)
  10594             visited_width += node->next->x - x0;
  10595             else
  10596             visited_width += node->next->x - node->x;
  10597         } else {
  10598             /* add waste area */
  10599             int under_width = node->next->x - node->x;
  10600             if (under_width + visited_width > width)
  10601             under_width = width - visited_width;
  10602             waste_area += under_width * (min_y - node->y);
  10603             visited_width += under_width;
  10604         }
  10605         node = node->next;
  10606     }
  10607     *pwaste = waste_area;
  10608     return min_y;
  10609 }
  10610 NK_INTERN struct nk_rp__findresult
  10611 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
  10612 {
  10613     int best_waste = (1<<30), best_x, best_y = (1 << 30);
  10614     struct nk_rp__findresult fr;
  10615     struct nk_rp_node **prev, *node, *tail, **best = 0;
  10616 
  10617     /* align to multiple of c->align */
  10618     width = (width + c->align - 1);
  10619     width -= width % c->align;
  10620     NK_ASSERT(width % c->align == 0);
  10621 
  10622     node = c->active_head;
  10623     prev = &c->active_head;
  10624     while (node->x + width <= c->width) {
  10625         int y,waste;
  10626         y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
  10627         /* actually just want to test BL */
  10628         if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
  10629             /* bottom left */
  10630             if (y < best_y) {
  10631             best_y = y;
  10632             best = prev;
  10633             }
  10634         } else {
  10635             /* best-fit */
  10636             if (y + height <= c->height) {
  10637                 /* can only use it if it first vertically */
  10638                 if (y < best_y || (y == best_y && waste < best_waste)) {
  10639                     best_y = y;
  10640                     best_waste = waste;
  10641                     best = prev;
  10642                 }
  10643             }
  10644         }
  10645         prev = &node->next;
  10646         node = node->next;
  10647     }
  10648     best_x = (best == 0) ? 0 : (*best)->x;
  10649 
  10650     /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
  10651     /* */
  10652     /* e.g, if fitting */
  10653     /* */
  10654     /*     ____________________ */
  10655     /*    |____________________| */
  10656     /* */
  10657     /*            into */
  10658     /* */
  10659     /*   |                         | */
  10660     /*   |             ____________| */
  10661     /*   |____________| */
  10662     /* */
  10663     /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
  10664     /* */
  10665     /* This makes BF take about 2x the time */
  10666     if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
  10667     {
  10668         tail = c->active_head;
  10669         node = c->active_head;
  10670         prev = &c->active_head;
  10671         /* find first node that's admissible */
  10672         while (tail->x < width)
  10673             tail = tail->next;
  10674         while (tail)
  10675         {
  10676             int xpos = tail->x - width;
  10677             int y,waste;
  10678             NK_ASSERT(xpos >= 0);
  10679             /* find the left position that matches this */
  10680             while (node->next->x <= xpos) {
  10681                 prev = &node->next;
  10682                 node = node->next;
  10683             }
  10684             NK_ASSERT(node->next->x > xpos && node->x <= xpos);
  10685             y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
  10686             if (y + height < c->height) {
  10687                 if (y <= best_y) {
  10688                     if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
  10689                         best_x = xpos;
  10690                         NK_ASSERT(y <= best_y);
  10691                         best_y = y;
  10692                         best_waste = waste;
  10693                         best = prev;
  10694                     }
  10695                 }
  10696             }
  10697             tail = tail->next;
  10698         }
  10699     }
  10700     fr.prev_link = best;
  10701     fr.x = best_x;
  10702     fr.y = best_y;
  10703     return fr;
  10704 }
  10705 NK_INTERN struct nk_rp__findresult
  10706 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
  10707 {
  10708     /* find best position according to heuristic */
  10709     struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
  10710     struct nk_rp_node *node, *cur;
  10711 
  10712     /* bail if: */
  10713     /*    1. it failed */
  10714     /*    2. the best node doesn't fit (we don't always check this) */
  10715     /*    3. we're out of memory */
  10716     if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
  10717         res.prev_link = 0;
  10718         return res;
  10719     }
  10720 
  10721     /* on success, create new node */
  10722     node = context->free_head;
  10723     node->x = (nk_rp_coord) res.x;
  10724     node->y = (nk_rp_coord) (res.y + height);
  10725 
  10726     context->free_head = node->next;
  10727 
  10728     /* insert the new node into the right starting point, and */
  10729     /* let 'cur' point to the remaining nodes needing to be */
  10730     /* stitched back in */
  10731     cur = *res.prev_link;
  10732     if (cur->x < res.x) {
  10733         /* preserve the existing one, so start testing with the next one */
  10734         struct nk_rp_node *next = cur->next;
  10735         cur->next = node;
  10736         cur = next;
  10737     } else {
  10738         *res.prev_link = node;
  10739     }
  10740 
  10741     /* from here, traverse cur and free the nodes, until we get to one */
  10742     /* that shouldn't be freed */
  10743     while (cur->next && cur->next->x <= res.x + width) {
  10744         struct nk_rp_node *next = cur->next;
  10745         /* move the current node to the free list */
  10746         cur->next = context->free_head;
  10747         context->free_head = cur;
  10748         cur = next;
  10749     }
  10750     /* stitch the list back in */
  10751     node->next = cur;
  10752 
  10753     if (cur->x < res.x + width)
  10754         cur->x = (nk_rp_coord) (res.x + width);
  10755     return res;
  10756 }
  10757 NK_INTERN int
  10758 nk_rect_height_compare(const void *a, const void *b)
  10759 {
  10760     const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
  10761     const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
  10762     if (p->h > q->h)
  10763         return -1;
  10764     if (p->h < q->h)
  10765         return  1;
  10766     return (p->w > q->w) ? -1 : (p->w < q->w);
  10767 }
  10768 NK_INTERN int
  10769 nk_rect_original_order(const void *a, const void *b)
  10770 {
  10771     const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
  10772     const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
  10773     return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
  10774 }
  10775 NK_INTERN void
  10776 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
  10777 {
  10778     /* iterative quick sort */
  10779     #define NK_MAX_SORT_STACK 64
  10780     unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
  10781     unsigned seed = len/2 * 69069+1;
  10782     for (;;) {
  10783         for (; left+1 < len; len++) {
  10784             struct nk_rp_rect pivot, tmp;
  10785             if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
  10786             pivot = array[left+seed%(len-left)];
  10787             seed = seed * 69069 + 1;
  10788             stack[pos++] = len;
  10789             for (right = left-1;;) {
  10790                 while (cmp(&array[++right], &pivot) < 0);
  10791                 while (cmp(&pivot, &array[--len]) < 0);
  10792                 if (right >= len) break;
  10793                 tmp = array[right];
  10794                 array[right] = array[len];
  10795                 array[len] = tmp;
  10796             }
  10797         }
  10798         if (pos == 0) break;
  10799         left = len;
  10800         len = stack[--pos];
  10801     }
  10802     #undef NK_MAX_SORT_STACK
  10803 }
  10804 NK_INTERN void
  10805 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
  10806 {
  10807     int i;
  10808     /* we use the 'was_packed' field internally to allow sorting/unsorting */
  10809     for (i=0; i < num_rects; ++i) {
  10810         rects[i].was_packed = i;
  10811     }
  10812 
  10813     /* sort according to heuristic */
  10814     nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
  10815 
  10816     for (i=0; i < num_rects; ++i) {
  10817         struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
  10818         if (fr.prev_link) {
  10819             rects[i].x = (nk_rp_coord) fr.x;
  10820             rects[i].y = (nk_rp_coord) fr.y;
  10821         } else {
  10822             rects[i].x = rects[i].y = NK_RP__MAXVAL;
  10823         }
  10824     }
  10825 
  10826     /* unsort */
  10827     nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
  10828 
  10829     /* set was_packed flags */
  10830     for (i=0; i < num_rects; ++i)
  10831         rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
  10832 }
  10833 
  10834 /*
  10835  * ==============================================================
  10836  *
  10837  *                          TRUETYPE
  10838  *
  10839  * ===============================================================
  10840  */
  10841 /* stb_truetype.h - v1.07 - public domain */
  10842 #define NK_TT_MAX_OVERSAMPLE   8
  10843 #define NK_TT__OVER_MASK  (NK_TT_MAX_OVERSAMPLE-1)
  10844 
  10845 struct nk_tt_bakedchar {
  10846     unsigned short x0,y0,x1,y1;
  10847     /* coordinates of bbox in bitmap */
  10848     float xoff,yoff,xadvance;
  10849 };
  10850 
  10851 struct nk_tt_aligned_quad{
  10852     float x0,y0,s0,t0; /* top-left */
  10853     float x1,y1,s1,t1; /* bottom-right */
  10854 };
  10855 
  10856 struct nk_tt_packedchar {
  10857     unsigned short x0,y0,x1,y1;
  10858     /* coordinates of bbox in bitmap */
  10859     float xoff,yoff,xadvance;
  10860     float xoff2,yoff2;
  10861 };
  10862 
  10863 struct nk_tt_pack_range {
  10864     float font_size;
  10865     int first_unicode_codepoint_in_range;
  10866     /* if non-zero, then the chars are continuous, and this is the first codepoint */
  10867     int *array_of_unicode_codepoints;
  10868     /* if non-zero, then this is an array of unicode codepoints */
  10869     int num_chars;
  10870     struct nk_tt_packedchar *chardata_for_range; /* output */
  10871     unsigned char h_oversample, v_oversample;
  10872     /* don't set these, they're used internally */
  10873 };
  10874 
  10875 struct nk_tt_pack_context {
  10876     void *pack_info;
  10877     int   width;
  10878     int   height;
  10879     int   stride_in_bytes;
  10880     int   padding;
  10881     unsigned int   h_oversample, v_oversample;
  10882     unsigned char *pixels;
  10883     void  *nodes;
  10884 };
  10885 
  10886 struct nk_tt_fontinfo {
  10887     const unsigned char* data; /* pointer to .ttf file */
  10888     int fontstart;/* offset of start of font */
  10889     int numGlyphs;/* number of glyphs, needed for range checking */
  10890     int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
  10891     int index_map; /* a cmap mapping for our chosen character encoding */
  10892     int indexToLocFormat; /* format needed to map from glyph index to glyph */
  10893 };
  10894 
  10895 enum {
  10896   NK_TT_vmove=1,
  10897   NK_TT_vline,
  10898   NK_TT_vcurve
  10899 };
  10900 
  10901 struct nk_tt_vertex {
  10902     short x,y,cx,cy;
  10903     unsigned char type,padding;
  10904 };
  10905 
  10906 struct nk_tt__bitmap{
  10907    int w,h,stride;
  10908    unsigned char *pixels;
  10909 };
  10910 
  10911 struct nk_tt__hheap_chunk {
  10912     struct nk_tt__hheap_chunk *next;
  10913 };
  10914 struct nk_tt__hheap {
  10915     struct nk_allocator alloc;
  10916     struct nk_tt__hheap_chunk *head;
  10917     void   *first_free;
  10918     int    num_remaining_in_head_chunk;
  10919 };
  10920 
  10921 struct nk_tt__edge {
  10922     float x0,y0, x1,y1;
  10923     int invert;
  10924 };
  10925 
  10926 struct nk_tt__active_edge {
  10927     struct nk_tt__active_edge *next;
  10928     float fx,fdx,fdy;
  10929     float direction;
  10930     float sy;
  10931     float ey;
  10932 };
  10933 struct nk_tt__point {float x,y;};
  10934 
  10935 #define NK_TT_MACSTYLE_DONTCARE     0
  10936 #define NK_TT_MACSTYLE_BOLD         1
  10937 #define NK_TT_MACSTYLE_ITALIC       2
  10938 #define NK_TT_MACSTYLE_UNDERSCORE   4
  10939 #define NK_TT_MACSTYLE_NONE         8
  10940 /* <= not same as 0, this makes us check the bitfield is 0 */
  10941 
  10942 enum { /* platformID */
  10943    NK_TT_PLATFORM_ID_UNICODE   =0,
  10944    NK_TT_PLATFORM_ID_MAC       =1,
  10945    NK_TT_PLATFORM_ID_ISO       =2,
  10946    NK_TT_PLATFORM_ID_MICROSOFT =3
  10947 };
  10948 
  10949 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
  10950    NK_TT_UNICODE_EID_UNICODE_1_0    =0,
  10951    NK_TT_UNICODE_EID_UNICODE_1_1    =1,
  10952    NK_TT_UNICODE_EID_ISO_10646      =2,
  10953    NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
  10954    NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
  10955 };
  10956 
  10957 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
  10958    NK_TT_MS_EID_SYMBOL        =0,
  10959    NK_TT_MS_EID_UNICODE_BMP   =1,
  10960    NK_TT_MS_EID_SHIFTJIS      =2,
  10961    NK_TT_MS_EID_UNICODE_FULL  =10
  10962 };
  10963 
  10964 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
  10965    NK_TT_MAC_EID_ROMAN        =0,   NK_TT_MAC_EID_ARABIC       =4,
  10966    NK_TT_MAC_EID_JAPANESE     =1,   NK_TT_MAC_EID_HEBREW       =5,
  10967    NK_TT_MAC_EID_CHINESE_TRAD =2,   NK_TT_MAC_EID_GREEK        =6,
  10968    NK_TT_MAC_EID_KOREAN       =3,   NK_TT_MAC_EID_RUSSIAN      =7
  10969 };
  10970 
  10971 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
  10972        /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
  10973    NK_TT_MS_LANG_ENGLISH     =0x0409,   NK_TT_MS_LANG_ITALIAN     =0x0410,
  10974    NK_TT_MS_LANG_CHINESE     =0x0804,   NK_TT_MS_LANG_JAPANESE    =0x0411,
  10975    NK_TT_MS_LANG_DUTCH       =0x0413,   NK_TT_MS_LANG_KOREAN      =0x0412,
  10976    NK_TT_MS_LANG_FRENCH      =0x040c,   NK_TT_MS_LANG_RUSSIAN     =0x0419,
  10977    NK_TT_MS_LANG_GERMAN      =0x0407,   NK_TT_MS_LANG_SPANISH     =0x0409,
  10978    NK_TT_MS_LANG_HEBREW      =0x040d,   NK_TT_MS_LANG_SWEDISH     =0x041D
  10979 };
  10980 
  10981 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
  10982    NK_TT_MAC_LANG_ENGLISH      =0 ,   NK_TT_MAC_LANG_JAPANESE     =11,
  10983    NK_TT_MAC_LANG_ARABIC       =12,   NK_TT_MAC_LANG_KOREAN       =23,
  10984    NK_TT_MAC_LANG_DUTCH        =4 ,   NK_TT_MAC_LANG_RUSSIAN      =32,
  10985    NK_TT_MAC_LANG_FRENCH       =1 ,   NK_TT_MAC_LANG_SPANISH      =6 ,
  10986    NK_TT_MAC_LANG_GERMAN       =2 ,   NK_TT_MAC_LANG_SWEDISH      =5 ,
  10987    NK_TT_MAC_LANG_HEBREW       =10,   NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
  10988    NK_TT_MAC_LANG_ITALIAN      =3 ,   NK_TT_MAC_LANG_CHINESE_TRAD =19
  10989 };
  10990 
  10991 #define nk_ttBYTE(p)     (* (const nk_byte *) (p))
  10992 #define nk_ttCHAR(p)     (* (const char *) (p))
  10993 
  10994 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
  10995    #define nk_ttUSHORT(p)   (* (nk_ushort *) (p))
  10996    #define nk_ttSHORT(p)    (* (nk_short *) (p))
  10997    #define nk_ttULONG(p)    (* (nk_uint *) (p))
  10998    #define nk_ttLONG(p)     (* (nk_int *) (p))
  10999 #else
  11000     static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
  11001     static nk_short nk_ttSHORT(const nk_byte *p)   { return (nk_short)(p[0]*256 + p[1]); }
  11002     static nk_uint nk_ttULONG(const nk_byte *p)  { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
  11003 #endif
  11004 
  11005 #define nk_tt_tag4(p,c0,c1,c2,c3)\
  11006     ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
  11007 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
  11008 
  11009 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
  11010                                 int glyph_index, struct nk_tt_vertex **pvertices);
  11011 
  11012 NK_INTERN nk_uint
  11013 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
  11014 {
  11015     /* @OPTIMIZE: binary search */
  11016     nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
  11017     nk_uint tabledir = fontstart + 12;
  11018     nk_int i;
  11019     for (i = 0; i < num_tables; ++i) {
  11020         nk_uint loc = tabledir + (nk_uint)(16*i);
  11021         if (nk_tt_tag(data+loc+0, tag))
  11022             return nk_ttULONG(data+loc+8);
  11023     }
  11024     return 0;
  11025 }
  11026 NK_INTERN int
  11027 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
  11028 {
  11029     nk_uint cmap, t;
  11030     nk_int i,numTables;
  11031     const nk_byte *data = (const nk_byte *) data2;
  11032 
  11033     info->data = data;
  11034     info->fontstart = fontstart;
  11035 
  11036     cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap");       /* required */
  11037     info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
  11038     info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
  11039     info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
  11040     info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
  11041     info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
  11042     info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
  11043     if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
  11044         return 0;
  11045 
  11046     t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
  11047     if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
  11048     else info->numGlyphs = 0xffff;
  11049 
  11050     /* find a cmap encoding table we understand *now* to avoid searching */
  11051     /* later. (todo: could make this installable) */
  11052     /* the same regardless of glyph. */
  11053     numTables = nk_ttUSHORT(data + cmap + 2);
  11054     info->index_map = 0;
  11055     for (i=0; i < numTables; ++i)
  11056     {
  11057         nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
  11058         /* find an encoding we understand: */
  11059         switch(nk_ttUSHORT(data+encoding_record)) {
  11060         case NK_TT_PLATFORM_ID_MICROSOFT:
  11061             switch (nk_ttUSHORT(data+encoding_record+2)) {
  11062             case NK_TT_MS_EID_UNICODE_BMP:
  11063             case NK_TT_MS_EID_UNICODE_FULL:
  11064                 /* MS/Unicode */
  11065                 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
  11066                 break;
  11067             default: break;
  11068             } break;
  11069         case NK_TT_PLATFORM_ID_UNICODE:
  11070             /* Mac/iOS has these */
  11071             /* all the encodingIDs are unicode, so we don't bother to check it */
  11072             info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
  11073             break;
  11074         default: break;
  11075         }
  11076     }
  11077     if (info->index_map == 0)
  11078         return 0;
  11079     info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
  11080     return 1;
  11081 }
  11082 NK_INTERN int
  11083 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
  11084 {
  11085     const nk_byte *data = info->data;
  11086     nk_uint index_map = (nk_uint)info->index_map;
  11087 
  11088     nk_ushort format = nk_ttUSHORT(data + index_map + 0);
  11089     if (format == 0) { /* apple byte encoding */
  11090         nk_int bytes = nk_ttUSHORT(data + index_map + 2);
  11091         if (unicode_codepoint < bytes-6)
  11092             return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
  11093         return 0;
  11094     } else if (format == 6) {
  11095         nk_uint first = nk_ttUSHORT(data + index_map + 6);
  11096         nk_uint count = nk_ttUSHORT(data + index_map + 8);
  11097         if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
  11098             return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
  11099         return 0;
  11100     } else if (format == 2) {
  11101         NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
  11102         return 0;
  11103     } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
  11104         nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
  11105         nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
  11106         nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
  11107         nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
  11108 
  11109         /* do a binary search of the segments */
  11110         nk_uint endCount = index_map + 14;
  11111         nk_uint search = endCount;
  11112 
  11113         if (unicode_codepoint > 0xffff)
  11114             return 0;
  11115 
  11116         /* they lie from endCount .. endCount + segCount */
  11117         /* but searchRange is the nearest power of two, so... */
  11118         if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
  11119             search += (nk_uint)(rangeShift*2);
  11120 
  11121         /* now decrement to bias correctly to find smallest */
  11122         search -= 2;
  11123         while (entrySelector) {
  11124             nk_ushort end;
  11125             searchRange >>= 1;
  11126             end = nk_ttUSHORT(data + search + searchRange*2);
  11127             if (unicode_codepoint > end)
  11128                 search += (nk_uint)(searchRange*2);
  11129             --entrySelector;
  11130         }
  11131         search += 2;
  11132 
  11133       {
  11134          nk_ushort offset, start;
  11135          nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
  11136 
  11137          NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
  11138          start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
  11139          if (unicode_codepoint < start)
  11140             return 0;
  11141 
  11142          offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
  11143          if (offset == 0)
  11144             return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
  11145 
  11146          return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
  11147       }
  11148    } else if (format == 12 || format == 13) {
  11149         nk_uint ngroups = nk_ttULONG(data+index_map+12);
  11150         nk_int low,high;
  11151         low = 0; high = (nk_int)ngroups;
  11152         /* Binary search the right group. */
  11153         while (low < high) {
  11154             nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
  11155             nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
  11156             nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
  11157             if ((nk_uint) unicode_codepoint < start_char)
  11158                 high = mid;
  11159             else if ((nk_uint) unicode_codepoint > end_char)
  11160                 low = mid+1;
  11161             else {
  11162                 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
  11163                 if (format == 12)
  11164                     return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
  11165                 else /* format == 13 */
  11166                     return (int)start_glyph;
  11167             }
  11168         }
  11169         return 0; /* not found */
  11170     }
  11171     /* @TODO */
  11172     NK_ASSERT(0);
  11173     return 0;
  11174 }
  11175 NK_INTERN void
  11176 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
  11177 {
  11178     v->type = type;
  11179     v->x = (nk_short) x;
  11180     v->y = (nk_short) y;
  11181     v->cx = (nk_short) cx;
  11182     v->cy = (nk_short) cy;
  11183 }
  11184 NK_INTERN int
  11185 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
  11186 {
  11187     int g1,g2;
  11188     if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
  11189     if (info->indexToLocFormat >= 2)    return -1; /* unknown index->glyph map format */
  11190 
  11191     if (info->indexToLocFormat == 0) {
  11192         g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
  11193         g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
  11194     } else {
  11195         g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
  11196         g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
  11197     }
  11198     return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
  11199 }
  11200 NK_INTERN int
  11201 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
  11202     int *x0, int *y0, int *x1, int *y1)
  11203 {
  11204     int g = nk_tt__GetGlyfOffset(info, glyph_index);
  11205     if (g < 0) return 0;
  11206 
  11207     if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
  11208     if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
  11209     if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
  11210     if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
  11211     return 1;
  11212 }
  11213 NK_INTERN int
  11214 nk_tt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
  11215     int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
  11216 {
  11217    if (start_off) {
  11218       if (was_off)
  11219          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
  11220       nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
  11221    } else {
  11222       if (was_off)
  11223          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
  11224       else
  11225          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
  11226    }
  11227    return num_vertices;
  11228 }
  11229 NK_INTERN int
  11230 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
  11231     int glyph_index, struct nk_tt_vertex **pvertices)
  11232 {
  11233     nk_short numberOfContours;
  11234     const nk_byte *endPtsOfContours;
  11235     const nk_byte *data = info->data;
  11236     struct nk_tt_vertex *vertices=0;
  11237     int num_vertices=0;
  11238     int g = nk_tt__GetGlyfOffset(info, glyph_index);
  11239     *pvertices = 0;
  11240 
  11241     if (g < 0) return 0;
  11242     numberOfContours = nk_ttSHORT(data + g);
  11243     if (numberOfContours > 0) {
  11244         nk_byte flags=0,flagcount;
  11245         nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
  11246         nk_int x,y,cx,cy,sx,sy, scx,scy;
  11247         const nk_byte *points;
  11248         endPtsOfContours = (data + g + 10);
  11249         ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
  11250         points = data + g + 10 + numberOfContours * 2 + 2 + ins;
  11251 
  11252         n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
  11253         m = n + 2*numberOfContours;  /* a loose bound on how many vertices we might need */
  11254         vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
  11255         if (vertices == 0)
  11256             return 0;
  11257 
  11258         next_move = 0;
  11259         flagcount=0;
  11260 
  11261         /* in first pass, we load uninterpreted data into the allocated array */
  11262         /* above, shifted to the end of the array so we won't overwrite it when */
  11263         /* we create our final data starting from the front */
  11264         off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
  11265 
  11266         /* first load flags */
  11267         for (i=0; i < n; ++i) {
  11268             if (flagcount == 0) {
  11269                 flags = *points++;
  11270                 if (flags & 8)
  11271                     flagcount = *points++;
  11272             } else --flagcount;
  11273             vertices[off+i].type = flags;
  11274         }
  11275 
  11276         /* now load x coordinates */
  11277         x=0;
  11278         for (i=0; i < n; ++i) {
  11279             flags = vertices[off+i].type;
  11280             if (flags & 2) {
  11281                 nk_short dx = *points++;
  11282                 x += (flags & 16) ? dx : -dx; /* ??? */
  11283             } else {
  11284                 if (!(flags & 16)) {
  11285                     x = x + (nk_short) (points[0]*256 + points[1]);
  11286                     points += 2;
  11287                 }
  11288             }
  11289             vertices[off+i].x = (nk_short) x;
  11290         }
  11291 
  11292         /* now load y coordinates */
  11293         y=0;
  11294         for (i=0; i < n; ++i) {
  11295             flags = vertices[off+i].type;
  11296             if (flags & 4) {
  11297                 nk_short dy = *points++;
  11298                 y += (flags & 32) ? dy : -dy; /* ??? */
  11299             } else {
  11300                 if (!(flags & 32)) {
  11301                     y = y + (nk_short) (points[0]*256 + points[1]);
  11302                     points += 2;
  11303                 }
  11304             }
  11305             vertices[off+i].y = (nk_short) y;
  11306         }
  11307 
  11308         /* now convert them to our format */
  11309         num_vertices=0;
  11310         sx = sy = cx = cy = scx = scy = 0;
  11311         for (i=0; i < n; ++i)
  11312         {
  11313             flags = vertices[off+i].type;
  11314             x     = (nk_short) vertices[off+i].x;
  11315             y     = (nk_short) vertices[off+i].y;
  11316 
  11317             if (next_move == i) {
  11318                 if (i != 0)
  11319                     num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
  11320 
  11321                 /* now start the new one                */
  11322                 start_off = !(flags & 1);
  11323                 if (start_off) {
  11324                     /* if we start off with an off-curve point, then when we need to find a point on the curve */
  11325                     /* where we can start, and we need to save some state for when we wraparound. */
  11326                     scx = x;
  11327                     scy = y;
  11328                     if (!(vertices[off+i+1].type & 1)) {
  11329                         /* next point is also a curve point, so interpolate an on-point curve */
  11330                         sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
  11331                         sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
  11332                     } else {
  11333                         /* otherwise just use the next point as our start point */
  11334                         sx = (nk_int) vertices[off+i+1].x;
  11335                         sy = (nk_int) vertices[off+i+1].y;
  11336                         ++i; /* we're using point i+1 as the starting point, so skip it */
  11337                     }
  11338                 } else {
  11339                     sx = x;
  11340                     sy = y;
  11341                 }
  11342                 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
  11343                 was_off = 0;
  11344                 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
  11345                 ++j;
  11346             } else {
  11347                 if (!(flags & 1))
  11348                 { /* if it's a curve */
  11349                     if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
  11350                         nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
  11351                     cx = x;
  11352                     cy = y;
  11353                     was_off = 1;
  11354                 } else {
  11355                     if (was_off)
  11356                         nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
  11357                     else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
  11358                     was_off = 0;
  11359                 }
  11360             }
  11361         }
  11362         num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
  11363     } else if (numberOfContours == -1) {
  11364         /* Compound shapes. */
  11365         int more = 1;
  11366         const nk_byte *comp = data + g + 10;
  11367         num_vertices = 0;
  11368         vertices = 0;
  11369 
  11370         while (more)
  11371         {
  11372             nk_ushort flags, gidx;
  11373             int comp_num_verts = 0, i;
  11374             struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
  11375             float mtx[6] = {1,0,0,1,0,0}, m, n;
  11376 
  11377             flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
  11378             gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
  11379 
  11380             if (flags & 2) { /* XY values */
  11381                 if (flags & 1) { /* shorts */
  11382                     mtx[4] = nk_ttSHORT(comp); comp+=2;
  11383                     mtx[5] = nk_ttSHORT(comp); comp+=2;
  11384                 } else {
  11385                     mtx[4] = nk_ttCHAR(comp); comp+=1;
  11386                     mtx[5] = nk_ttCHAR(comp); comp+=1;
  11387                 }
  11388             } else {
  11389                 /* @TODO handle matching point */
  11390                 NK_ASSERT(0);
  11391             }
  11392             if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
  11393                 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
  11394                 mtx[1] = mtx[2] = 0;
  11395             } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
  11396                 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
  11397                 mtx[1] = mtx[2] = 0;
  11398                 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
  11399             } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
  11400                 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
  11401                 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
  11402                 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
  11403                 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
  11404             }
  11405 
  11406              /* Find transformation scales. */
  11407             m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
  11408             n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
  11409 
  11410              /* Get indexed glyph. */
  11411             comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
  11412             if (comp_num_verts > 0)
  11413             {
  11414                 /* Transform vertices. */
  11415                 for (i = 0; i < comp_num_verts; ++i) {
  11416                     struct nk_tt_vertex* v = &comp_verts[i];
  11417                     short x,y;
  11418                     x=v->x; y=v->y;
  11419                     v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
  11420                     v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
  11421                     x=v->cx; y=v->cy;
  11422                     v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
  11423                     v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
  11424                 }
  11425                 /* Append vertices. */
  11426                 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
  11427                     (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
  11428                 if (!tmp) {
  11429                     if (vertices) alloc->free(alloc->userdata, vertices);
  11430                     if (comp_verts) alloc->free(alloc->userdata, comp_verts);
  11431                     return 0;
  11432                 }
  11433                 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
  11434                 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
  11435                 if (vertices) alloc->free(alloc->userdata,vertices);
  11436                 vertices = tmp;
  11437                 alloc->free(alloc->userdata,comp_verts);
  11438                 num_vertices += comp_num_verts;
  11439             }
  11440             /* More components ? */
  11441             more = flags & (1<<5);
  11442         }
  11443     } else if (numberOfContours < 0) {
  11444         /* @TODO other compound variations? */
  11445         NK_ASSERT(0);
  11446     } else {
  11447         /* numberOfCounters == 0, do nothing */
  11448     }
  11449     *pvertices = vertices;
  11450     return num_vertices;
  11451 }
  11452 NK_INTERN void
  11453 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
  11454     int *advanceWidth, int *leftSideBearing)
  11455 {
  11456     nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
  11457     if (glyph_index < numOfLongHorMetrics) {
  11458         if (advanceWidth)
  11459             *advanceWidth    = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
  11460         if (leftSideBearing)
  11461             *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
  11462     } else {
  11463         if (advanceWidth)
  11464             *advanceWidth    = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
  11465         if (leftSideBearing)
  11466             *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
  11467     }
  11468 }
  11469 NK_INTERN void
  11470 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
  11471     int *ascent, int *descent, int *lineGap)
  11472 {
  11473    if (ascent ) *ascent  = nk_ttSHORT(info->data+info->hhea + 4);
  11474    if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
  11475    if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
  11476 }
  11477 NK_INTERN float
  11478 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
  11479 {
  11480    int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
  11481    return (float) height / (float)fheight;
  11482 }
  11483 NK_INTERN float
  11484 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
  11485 {
  11486    int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
  11487    return pixels / (float)unitsPerEm;
  11488 }
  11489 
  11490 /*-------------------------------------------------------------
  11491  *            antialiasing software rasterizer
  11492  * --------------------------------------------------------------*/
  11493 NK_INTERN void
  11494 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
  11495     int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
  11496     int *ix0, int *iy0, int *ix1, int *iy1)
  11497 {
  11498     int x0,y0,x1,y1;
  11499     if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
  11500         /* e.g. space character */
  11501         if (ix0) *ix0 = 0;
  11502         if (iy0) *iy0 = 0;
  11503         if (ix1) *ix1 = 0;
  11504         if (iy1) *iy1 = 0;
  11505     } else {
  11506         /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
  11507         if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
  11508         if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
  11509         if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
  11510         if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
  11511     }
  11512 }
  11513 NK_INTERN void
  11514 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
  11515     float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
  11516 {
  11517    nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
  11518 }
  11519 
  11520 /*-------------------------------------------------------------
  11521  *                          Rasterizer
  11522  * --------------------------------------------------------------*/
  11523 NK_INTERN void*
  11524 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
  11525 {
  11526     if (hh->first_free) {
  11527         void *p = hh->first_free;
  11528         hh->first_free = * (void **) p;
  11529         return p;
  11530     } else {
  11531         if (hh->num_remaining_in_head_chunk == 0) {
  11532             int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
  11533             struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
  11534                 hh->alloc.alloc(hh->alloc.userdata, 0,
  11535                 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
  11536             if (c == 0) return 0;
  11537             c->next = hh->head;
  11538             hh->head = c;
  11539             hh->num_remaining_in_head_chunk = count;
  11540         }
  11541         --hh->num_remaining_in_head_chunk;
  11542         return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
  11543     }
  11544 }
  11545 NK_INTERN void
  11546 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
  11547 {
  11548     *(void **) p = hh->first_free;
  11549     hh->first_free = p;
  11550 }
  11551 NK_INTERN void
  11552 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
  11553 {
  11554     struct nk_tt__hheap_chunk *c = hh->head;
  11555     while (c) {
  11556         struct nk_tt__hheap_chunk *n = c->next;
  11557         hh->alloc.free(hh->alloc.userdata, c);
  11558         c = n;
  11559     }
  11560 }
  11561 NK_INTERN struct nk_tt__active_edge*
  11562 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
  11563     int off_x, float start_point)
  11564 {
  11565     struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
  11566         nk_tt__hheap_alloc(hh, sizeof(*z));
  11567     float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
  11568     /*STBTT_assert(e->y0 <= start_point); */
  11569     if (!z) return z;
  11570     z->fdx = dxdy;
  11571     z->fdy = (dxdy != 0) ? (1/dxdy): 0;
  11572     z->fx = e->x0 + dxdy * (start_point - e->y0);
  11573     z->fx -= (float)off_x;
  11574     z->direction = e->invert ? 1.0f : -1.0f;
  11575     z->sy = e->y0;
  11576     z->ey = e->y1;
  11577     z->next = 0;
  11578     return z;
  11579 }
  11580 NK_INTERN void
  11581 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
  11582     float x0, float y0, float x1, float y1)
  11583 {
  11584     if (y0 == y1) return;
  11585     NK_ASSERT(y0 < y1);
  11586     NK_ASSERT(e->sy <= e->ey);
  11587     if (y0 > e->ey) return;
  11588     if (y1 < e->sy) return;
  11589     if (y0 < e->sy) {
  11590         x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
  11591         y0 = e->sy;
  11592     }
  11593     if (y1 > e->ey) {
  11594         x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
  11595         y1 = e->ey;
  11596     }
  11597 
  11598     if (x0 == x) NK_ASSERT(x1 <= x+1);
  11599     else if (x0 == x+1) NK_ASSERT(x1 >= x);
  11600     else if (x0 <= x) NK_ASSERT(x1 <= x);
  11601     else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
  11602     else NK_ASSERT(x1 >= x && x1 <= x+1);
  11603 
  11604     if (x0 <= x && x1 <= x)
  11605         scanline[x] += e->direction * (y1-y0);
  11606     else if (x0 >= x+1 && x1 >= x+1);
  11607     else {
  11608         NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
  11609         /* coverage = 1 - average x position */
  11610         scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
  11611     }
  11612 }
  11613 NK_INTERN void
  11614 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
  11615     struct nk_tt__active_edge *e, float y_top)
  11616 {
  11617     float y_bottom = y_top+1;
  11618     while (e)
  11619     {
  11620         /* brute force every pixel */
  11621         /* compute intersection points with top & bottom */
  11622         NK_ASSERT(e->ey >= y_top);
  11623         if (e->fdx == 0) {
  11624             float x0 = e->fx;
  11625             if (x0 < len) {
  11626                 if (x0 >= 0) {
  11627                     nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
  11628                     nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
  11629                 } else {
  11630                     nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
  11631                 }
  11632             }
  11633         } else {
  11634             float x0 = e->fx;
  11635             float dx = e->fdx;
  11636             float xb = x0 + dx;
  11637             float x_top, x_bottom;
  11638             float y0,y1;
  11639             float dy = e->fdy;
  11640             NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
  11641 
  11642             /* compute endpoints of line segment clipped to this scanline (if the */
  11643             /* line segment starts on this scanline. x0 is the intersection of the */
  11644             /* line with y_top, but that may be off the line segment. */
  11645             if (e->sy > y_top) {
  11646                 x_top = x0 + dx * (e->sy - y_top);
  11647                 y0 = e->sy;
  11648             } else {
  11649                 x_top = x0;
  11650                 y0 = y_top;
  11651             }
  11652 
  11653             if (e->ey < y_bottom) {
  11654                 x_bottom = x0 + dx * (e->ey - y_top);
  11655                 y1 = e->ey;
  11656             } else {
  11657                 x_bottom = xb;
  11658                 y1 = y_bottom;
  11659             }
  11660 
  11661             if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
  11662             {
  11663                 /* from here on, we don't have to range check x values */
  11664                 if ((int) x_top == (int) x_bottom) {
  11665                     float height;
  11666                     /* simple case, only spans one pixel */
  11667                     int x = (int) x_top;
  11668                     height = y1 - y0;
  11669                     NK_ASSERT(x >= 0 && x < len);
  11670                     scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f)  * (float)height;
  11671                     scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
  11672                 } else {
  11673                     int x,x1,x2;
  11674                     float y_crossing, step, sign, area;
  11675                     /* covers 2+ pixels */
  11676                     if (x_top > x_bottom)
  11677                     {
  11678                         /* flip scanline vertically; signed area is the same */
  11679                         float t;
  11680                         y0 = y_bottom - (y0 - y_top);
  11681                         y1 = y_bottom - (y1 - y_top);
  11682                         t = y0; y0 = y1; y1 = t;
  11683                         t = x_bottom; x_bottom = x_top; x_top = t;
  11684                         dx = -dx;
  11685                         dy = -dy;
  11686                         t = x0; x0 = xb; xb = t;
  11687                     }
  11688 
  11689                     x1 = (int) x_top;
  11690                     x2 = (int) x_bottom;
  11691                     /* compute intersection with y axis at x1+1 */
  11692                     y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
  11693 
  11694                     sign = e->direction;
  11695                     /* area of the rectangle covered from y0..y_crossing */
  11696                     area = sign * (y_crossing-y0);
  11697                     /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
  11698                     scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
  11699 
  11700                     step = sign * dy;
  11701                     for (x = x1+1; x < x2; ++x) {
  11702                         scanline[x] += area + step/2;
  11703                         area += step;
  11704                     }
  11705                     y_crossing += (float)dy * (float)(x2 - (x1+1));
  11706 
  11707                     scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
  11708                     scanline_fill[x2] += sign * (y1-y0);
  11709                 }
  11710             }
  11711             else
  11712             {
  11713                 /* if edge goes outside of box we're drawing, we require */
  11714                 /* clipping logic. since this does not match the intended use */
  11715                 /* of this library, we use a different, very slow brute */
  11716                 /* force implementation */
  11717                 int x;
  11718                 for (x=0; x < len; ++x)
  11719                 {
  11720                     /* cases: */
  11721                     /* */
  11722                     /* there can be up to two intersections with the pixel. any intersection */
  11723                     /* with left or right edges can be handled by splitting into two (or three) */
  11724                     /* regions. intersections with top & bottom do not necessitate case-wise logic. */
  11725                     /* */
  11726                     /* the old way of doing this found the intersections with the left & right edges, */
  11727                     /* then used some simple logic to produce up to three segments in sorted order */
  11728                     /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
  11729                     /* across the x border, then the corresponding y position might not be distinct */
  11730                     /* from the other y segment, and it might ignored as an empty segment. to avoid */
  11731                     /* that, we need to explicitly produce segments based on x positions. */
  11732 
  11733                     /* rename variables to clear pairs */
  11734                     float ya = y_top;
  11735                     float x1 = (float) (x);
  11736                     float x2 = (float) (x+1);
  11737                     float x3 = xb;
  11738                     float y3 = y_bottom;
  11739                     float yb,y2;
  11740 
  11741                     yb = ((float)x - x0) / dx + y_top;
  11742                     y2 = ((float)x+1 - x0) / dx + y_top;
  11743 
  11744                     if (x0 < x1 && x3 > x2) {         /* three segments descending down-right */
  11745                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
  11746                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
  11747                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  11748                     } else if (x3 < x1 && x0 > x2) {  /* three segments descending down-left */
  11749                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
  11750                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
  11751                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
  11752                     } else if (x0 < x1 && x3 > x1) {  /* two segments across x, down-right */
  11753                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
  11754                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
  11755                     } else if (x3 < x1 && x0 > x1) {  /* two segments across x, down-left */
  11756                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
  11757                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
  11758                     } else if (x0 < x2 && x3 > x2) {  /* two segments across x+1, down-right */
  11759                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
  11760                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  11761                     } else if (x3 < x2 && x0 > x2) {  /* two segments across x+1, down-left */
  11762                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
  11763                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  11764                     } else {  /* one segment */
  11765                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
  11766                     }
  11767                 }
  11768             }
  11769         }
  11770         e = e->next;
  11771     }
  11772 }
  11773 NK_INTERN void
  11774 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
  11775     int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
  11776 {
  11777     /* directly AA rasterize edges w/o supersampling */
  11778     struct nk_tt__hheap hh;
  11779     struct nk_tt__active_edge *active = 0;
  11780     int y,j=0, i;
  11781     float scanline_data[129], *scanline, *scanline2;
  11782 
  11783     NK_UNUSED(vsubsample);
  11784     nk_zero_struct(hh);
  11785     hh.alloc = *alloc;
  11786 
  11787     if (result->w > 64)
  11788         scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
  11789     else scanline = scanline_data;
  11790 
  11791     scanline2 = scanline + result->w;
  11792     y = off_y;
  11793     e[n].y0 = (float) (off_y + result->h) + 1;
  11794 
  11795     while (j < result->h)
  11796     {
  11797         /* find center of pixel for this scanline */
  11798         float scan_y_top    = (float)y + 0.0f;
  11799         float scan_y_bottom = (float)y + 1.0f;
  11800         struct nk_tt__active_edge **step = &active;
  11801 
  11802         NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
  11803         NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
  11804 
  11805         /* update all active edges; */
  11806         /* remove all active edges that terminate before the top of this scanline */
  11807         while (*step) {
  11808             struct nk_tt__active_edge * z = *step;
  11809             if (z->ey <= scan_y_top) {
  11810                 *step = z->next; /* delete from list */
  11811                 NK_ASSERT(z->direction);
  11812                 z->direction = 0;
  11813                 nk_tt__hheap_free(&hh, z);
  11814             } else {
  11815                 step = &((*step)->next); /* advance through list */
  11816             }
  11817         }
  11818 
  11819         /* insert all edges that start before the bottom of this scanline */
  11820         while (e->y0 <= scan_y_bottom) {
  11821             if (e->y0 != e->y1) {
  11822                 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
  11823                 if (z != 0) {
  11824                     NK_ASSERT(z->ey >= scan_y_top);
  11825                     /* insert at front */
  11826                     z->next = active;
  11827                     active = z;
  11828                 }
  11829             }
  11830             ++e;
  11831         }
  11832 
  11833         /* now process all active edges */
  11834         if (active)
  11835             nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
  11836 
  11837         {
  11838             float sum = 0;
  11839             for (i=0; i < result->w; ++i) {
  11840                 float k;
  11841                 int m;
  11842                 sum += scanline2[i];
  11843                 k = scanline[i] + sum;
  11844                 k = (float) NK_ABS(k) * 255.0f + 0.5f;
  11845                 m = (int) k;
  11846                 if (m > 255) m = 255;
  11847                 result->pixels[j*result->stride + i] = (unsigned char) m;
  11848             }
  11849         }
  11850         /* advance all the edges */
  11851         step = &active;
  11852         while (*step) {
  11853             struct nk_tt__active_edge *z = *step;
  11854             z->fx += z->fdx; /* advance to position for current scanline */
  11855             step = &((*step)->next); /* advance through list */
  11856         }
  11857         ++y;
  11858         ++j;
  11859     }
  11860     nk_tt__hheap_cleanup(&hh);
  11861     if (scanline != scanline_data)
  11862         alloc->free(alloc->userdata, scanline);
  11863 }
  11864 NK_INTERN void
  11865 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
  11866 {
  11867     int i,j;
  11868     #define NK_TT__COMPARE(a,b)  ((a)->y0 < (b)->y0)
  11869     for (i=1; i < n; ++i) {
  11870         struct nk_tt__edge t = p[i], *a = &t;
  11871         j = i;
  11872         while (j > 0) {
  11873             struct nk_tt__edge *b = &p[j-1];
  11874             int c = NK_TT__COMPARE(a,b);
  11875             if (!c) break;
  11876             p[j] = p[j-1];
  11877             --j;
  11878         }
  11879         if (i != j)
  11880             p[j] = t;
  11881     }
  11882 }
  11883 NK_INTERN void
  11884 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
  11885 {
  11886     /* threshold for transitioning to insertion sort */
  11887     while (n > 12) {
  11888         struct nk_tt__edge t;
  11889         int c01,c12,c,m,i,j;
  11890 
  11891         /* compute median of three */
  11892         m = n >> 1;
  11893         c01 = NK_TT__COMPARE(&p[0],&p[m]);
  11894         c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
  11895 
  11896         /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
  11897         if (c01 != c12) {
  11898             /* otherwise, we'll need to swap something else to middle */
  11899             int z;
  11900             c = NK_TT__COMPARE(&p[0],&p[n-1]);
  11901             /* 0>mid && mid<n:  0>n => n; 0<n => 0 */
  11902             /* 0<mid && mid>n:  0>n => 0; 0<n => n */
  11903             z = (c == c12) ? 0 : n-1;
  11904             t = p[z];
  11905             p[z] = p[m];
  11906             p[m] = t;
  11907         }
  11908 
  11909         /* now p[m] is the median-of-three */
  11910         /* swap it to the beginning so it won't move around */
  11911         t = p[0];
  11912         p[0] = p[m];
  11913         p[m] = t;
  11914 
  11915         /* partition loop */
  11916         i=1;
  11917         j=n-1;
  11918         for(;;) {
  11919             /* handling of equality is crucial here */
  11920             /* for sentinels & efficiency with duplicates */
  11921             for (;;++i) {
  11922                 if (!NK_TT__COMPARE(&p[i], &p[0])) break;
  11923             }
  11924             for (;;--j) {
  11925                 if (!NK_TT__COMPARE(&p[0], &p[j])) break;
  11926             }
  11927 
  11928             /* make sure we haven't crossed */
  11929              if (i >= j) break;
  11930              t = p[i];
  11931              p[i] = p[j];
  11932              p[j] = t;
  11933 
  11934             ++i;
  11935             --j;
  11936 
  11937         }
  11938 
  11939         /* recurse on smaller side, iterate on larger */
  11940         if (j < (n-i)) {
  11941             nk_tt__sort_edges_quicksort(p,j);
  11942             p = p+i;
  11943             n = n-i;
  11944         } else {
  11945             nk_tt__sort_edges_quicksort(p+i, n-i);
  11946             n = j;
  11947         }
  11948     }
  11949 }
  11950 NK_INTERN void
  11951 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
  11952 {
  11953    nk_tt__sort_edges_quicksort(p, n);
  11954    nk_tt__sort_edges_ins_sort(p, n);
  11955 }
  11956 NK_INTERN void
  11957 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
  11958     int *wcount, int windings, float scale_x, float scale_y,
  11959     float shift_x, float shift_y, int off_x, int off_y, int invert,
  11960     struct nk_allocator *alloc)
  11961 {
  11962     float y_scale_inv = invert ? -scale_y : scale_y;
  11963     struct nk_tt__edge *e;
  11964     int n,i,j,k,m;
  11965     int vsubsample = 1;
  11966     /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
  11967 
  11968     /* now we have to blow out the windings into explicit edge lists */
  11969     n = 0;
  11970     for (i=0; i < windings; ++i)
  11971         n += wcount[i];
  11972 
  11973     e = (struct nk_tt__edge*)
  11974        alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
  11975     if (e == 0) return;
  11976     n = 0;
  11977 
  11978     m=0;
  11979     for (i=0; i < windings; ++i)
  11980     {
  11981         struct nk_tt__point *p = pts + m;
  11982         m += wcount[i];
  11983         j = wcount[i]-1;
  11984         for (k=0; k < wcount[i]; j=k++) {
  11985             int a=k,b=j;
  11986             /* skip the edge if horizontal */
  11987             if (p[j].y == p[k].y)
  11988                 continue;
  11989 
  11990             /* add edge from j to k to the list */
  11991             e[n].invert = 0;
  11992             if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
  11993                 e[n].invert = 1;
  11994                 a=j,b=k;
  11995             }
  11996             e[n].x0 = p[a].x * scale_x + shift_x;
  11997             e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
  11998             e[n].x1 = p[b].x * scale_x + shift_x;
  11999             e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
  12000             ++n;
  12001         }
  12002     }
  12003 
  12004     /* now sort the edges by their highest point (should snap to integer, and then by x) */
  12005     /*STBTT_sort(e, n, sizeof(e[0]), nk_tt__edge_compare); */
  12006     nk_tt__sort_edges(e, n);
  12007     /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
  12008     nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
  12009     alloc->free(alloc->userdata, e);
  12010 }
  12011 NK_INTERN void
  12012 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
  12013 {
  12014     if (!points) return; /* during first pass, it's unallocated */
  12015     points[n].x = x;
  12016     points[n].y = y;
  12017 }
  12018 NK_INTERN int
  12019 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
  12020     float x0, float y0, float x1, float y1, float x2, float y2,
  12021     float objspace_flatness_squared, int n)
  12022 {
  12023     /* tesselate until threshold p is happy...
  12024      * @TODO warped to compensate for non-linear stretching */
  12025     /* midpoint */
  12026     float mx = (x0 + 2*x1 + x2)/4;
  12027     float my = (y0 + 2*y1 + y2)/4;
  12028     /* versus directly drawn line */
  12029     float dx = (x0+x2)/2 - mx;
  12030     float dy = (y0+y2)/2 - my;
  12031     if (n > 16) /* 65536 segments on one curve better be enough! */
  12032         return 1;
  12033 
  12034     /* half-pixel error allowed... need to be smaller if AA */
  12035     if (dx*dx+dy*dy > objspace_flatness_squared) {
  12036         nk_tt__tesselate_curve(points, num_points, x0,y0,
  12037             (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
  12038         nk_tt__tesselate_curve(points, num_points, mx,my,
  12039             (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
  12040     } else {
  12041         nk_tt__add_point(points, *num_points,x2,y2);
  12042         *num_points = *num_points+1;
  12043     }
  12044     return 1;
  12045 }
  12046 NK_INTERN struct nk_tt__point*
  12047 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
  12048     float objspace_flatness, int **contour_lengths, int *num_contours,
  12049     struct nk_allocator *alloc)
  12050 {
  12051     /* returns number of contours */
  12052     struct nk_tt__point *points=0;
  12053     int num_points=0;
  12054     float objspace_flatness_squared = objspace_flatness * objspace_flatness;
  12055     int i;
  12056     int n=0;
  12057     int start=0;
  12058     int pass;
  12059 
  12060     /* count how many "moves" there are to get the contour count */
  12061     for (i=0; i < num_verts; ++i)
  12062         if (vertices[i].type == NK_TT_vmove) ++n;
  12063 
  12064     *num_contours = n;
  12065     if (n == 0) return 0;
  12066 
  12067     *contour_lengths = (int *)
  12068         alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
  12069     if (*contour_lengths == 0) {
  12070         *num_contours = 0;
  12071         return 0;
  12072     }
  12073 
  12074     /* make two passes through the points so we don't need to realloc */
  12075     for (pass=0; pass < 2; ++pass)
  12076     {
  12077         float x=0,y=0;
  12078         if (pass == 1) {
  12079             points = (struct nk_tt__point *)
  12080                 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
  12081             if (points == 0) goto error;
  12082         }
  12083         num_points = 0;
  12084         n= -1;
  12085 
  12086         for (i=0; i < num_verts; ++i)
  12087         {
  12088             switch (vertices[i].type) {
  12089             case NK_TT_vmove:
  12090                 /* start the next contour */
  12091                 if (n >= 0)
  12092                 (*contour_lengths)[n] = num_points - start;
  12093                 ++n;
  12094                 start = num_points;
  12095 
  12096                 x = vertices[i].x, y = vertices[i].y;
  12097                 nk_tt__add_point(points, num_points++, x,y);
  12098                 break;
  12099             case NK_TT_vline:
  12100                x = vertices[i].x, y = vertices[i].y;
  12101                nk_tt__add_point(points, num_points++, x, y);
  12102                break;
  12103             case NK_TT_vcurve:
  12104                nk_tt__tesselate_curve(points, &num_points, x,y,
  12105                                         vertices[i].cx, vertices[i].cy,
  12106                                         vertices[i].x,  vertices[i].y,
  12107                                         objspace_flatness_squared, 0);
  12108                x = vertices[i].x, y = vertices[i].y;
  12109                break;
  12110             default: break;
  12111          }
  12112       }
  12113       (*contour_lengths)[n] = num_points - start;
  12114    }
  12115    return points;
  12116 
  12117 error:
  12118    alloc->free(alloc->userdata, points);
  12119    alloc->free(alloc->userdata, *contour_lengths);
  12120    *contour_lengths = 0;
  12121    *num_contours = 0;
  12122    return 0;
  12123 }
  12124 NK_INTERN void
  12125 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
  12126     struct nk_tt_vertex *vertices, int num_verts,
  12127     float scale_x, float scale_y, float shift_x, float shift_y,
  12128     int x_off, int y_off, int invert, struct nk_allocator *alloc)
  12129 {
  12130     float scale = scale_x > scale_y ? scale_y : scale_x;
  12131     int winding_count, *winding_lengths;
  12132     struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
  12133         flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
  12134 
  12135     NK_ASSERT(alloc);
  12136     if (windings) {
  12137         nk_tt__rasterize(result, windings, winding_lengths, winding_count,
  12138             scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
  12139         alloc->free(alloc->userdata, winding_lengths);
  12140         alloc->free(alloc->userdata, windings);
  12141     }
  12142 }
  12143 NK_INTERN void
  12144 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
  12145     int out_w, int out_h, int out_stride, float scale_x, float scale_y,
  12146     float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
  12147 {
  12148     int ix0,iy0;
  12149     struct nk_tt_vertex *vertices;
  12150     int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
  12151     struct nk_tt__bitmap gbm;
  12152 
  12153     nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
  12154         shift_y, &ix0,&iy0,0,0);
  12155     gbm.pixels = output;
  12156     gbm.w = out_w;
  12157     gbm.h = out_h;
  12158     gbm.stride = out_stride;
  12159 
  12160     if (gbm.w && gbm.h)
  12161         nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
  12162             shift_x, shift_y, ix0,iy0, 1, alloc);
  12163     alloc->free(alloc->userdata, vertices);
  12164 }
  12165 
  12166 /*-------------------------------------------------------------
  12167  *                          Bitmap baking
  12168  * --------------------------------------------------------------*/
  12169 NK_INTERN int
  12170 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
  12171     int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
  12172 {
  12173     int num_nodes = pw - padding;
  12174     struct nk_rp_context *context = (struct nk_rp_context *)
  12175         alloc->alloc(alloc->userdata,0, sizeof(*context));
  12176     struct nk_rp_node *nodes = (struct nk_rp_node*)
  12177         alloc->alloc(alloc->userdata,0, (sizeof(*nodes  ) * (nk_size)num_nodes));
  12178 
  12179     if (context == 0 || nodes == 0) {
  12180         if (context != 0) alloc->free(alloc->userdata, context);
  12181         if (nodes   != 0) alloc->free(alloc->userdata, nodes);
  12182         return 0;
  12183     }
  12184 
  12185     spc->width = pw;
  12186     spc->height = ph;
  12187     spc->pixels = pixels;
  12188     spc->pack_info = context;
  12189     spc->nodes = nodes;
  12190     spc->padding = padding;
  12191     spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
  12192     spc->h_oversample = 1;
  12193     spc->v_oversample = 1;
  12194 
  12195     nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
  12196     if (pixels)
  12197         NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
  12198     return 1;
  12199 }
  12200 NK_INTERN void
  12201 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
  12202 {
  12203     alloc->free(alloc->userdata, spc->nodes);
  12204     alloc->free(alloc->userdata, spc->pack_info);
  12205 }
  12206 NK_INTERN void
  12207 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
  12208     unsigned int h_oversample, unsigned int v_oversample)
  12209 {
  12210    NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
  12211    NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
  12212    if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
  12213       spc->h_oversample = h_oversample;
  12214    if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
  12215       spc->v_oversample = v_oversample;
  12216 }
  12217 NK_INTERN void
  12218 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
  12219     int kernel_width)
  12220 {
  12221     unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
  12222     int safe_w = w - kernel_width;
  12223     int j;
  12224 
  12225     for (j=0; j < h; ++j)
  12226     {
  12227         int i;
  12228         unsigned int total;
  12229         NK_MEMSET(buffer, 0, (nk_size)kernel_width);
  12230 
  12231         total = 0;
  12232 
  12233         /* make kernel_width a constant in common cases so compiler can optimize out the divide */
  12234         switch (kernel_width) {
  12235         case 2:
  12236             for (i=0; i <= safe_w; ++i) {
  12237                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
  12238                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
  12239                 pixels[i] = (unsigned char) (total / 2);
  12240             }
  12241             break;
  12242         case 3:
  12243             for (i=0; i <= safe_w; ++i) {
  12244                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
  12245                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
  12246                 pixels[i] = (unsigned char) (total / 3);
  12247             }
  12248             break;
  12249         case 4:
  12250             for (i=0; i <= safe_w; ++i) {
  12251                 total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
  12252                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
  12253                 pixels[i] = (unsigned char) (total / 4);
  12254             }
  12255             break;
  12256         case 5:
  12257             for (i=0; i <= safe_w; ++i) {
  12258                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
  12259                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
  12260                 pixels[i] = (unsigned char) (total / 5);
  12261             }
  12262             break;
  12263         default:
  12264             for (i=0; i <= safe_w; ++i) {
  12265                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
  12266                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
  12267                 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
  12268             }
  12269             break;
  12270         }
  12271 
  12272         for (; i < w; ++i) {
  12273             NK_ASSERT(pixels[i] == 0);
  12274             total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
  12275             pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
  12276         }
  12277         pixels += stride_in_bytes;
  12278     }
  12279 }
  12280 NK_INTERN void
  12281 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
  12282     int kernel_width)
  12283 {
  12284     unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
  12285     int safe_h = h - kernel_width;
  12286     int j;
  12287 
  12288     for (j=0; j < w; ++j)
  12289     {
  12290         int i;
  12291         unsigned int total;
  12292         NK_MEMSET(buffer, 0, (nk_size)kernel_width);
  12293 
  12294         total = 0;
  12295 
  12296         /* make kernel_width a constant in common cases so compiler can optimize out the divide */
  12297         switch (kernel_width) {
  12298         case 2:
  12299             for (i=0; i <= safe_h; ++i) {
  12300                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
  12301                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
  12302                 pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
  12303             }
  12304             break;
  12305          case 3:
  12306             for (i=0; i <= safe_h; ++i) {
  12307                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
  12308                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
  12309                 pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
  12310             }
  12311             break;
  12312          case 4:
  12313             for (i=0; i <= safe_h; ++i) {
  12314                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
  12315                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
  12316                 pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
  12317             }
  12318             break;
  12319          case 5:
  12320             for (i=0; i <= safe_h; ++i) {
  12321                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
  12322                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
  12323                 pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
  12324             }
  12325             break;
  12326          default:
  12327             for (i=0; i <= safe_h; ++i) {
  12328                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
  12329                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
  12330                 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
  12331             }
  12332             break;
  12333         }
  12334 
  12335         for (; i < h; ++i) {
  12336             NK_ASSERT(pixels[i*stride_in_bytes] == 0);
  12337             total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
  12338             pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
  12339         }
  12340         pixels += 1;
  12341     }
  12342 }
  12343 NK_INTERN float
  12344 nk_tt__oversample_shift(int oversample)
  12345 {
  12346     if (!oversample)
  12347         return 0.0f;
  12348 
  12349     /* The prefilter is a box filter of width "oversample", */
  12350     /* which shifts phase by (oversample - 1)/2 pixels in */
  12351     /* oversampled space. We want to shift in the opposite */
  12352     /* direction to counter this. */
  12353     return (float)-(oversample - 1) / (2.0f * (float)oversample);
  12354 }
  12355 NK_INTERN int
  12356 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
  12357     struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
  12358     int num_ranges, struct nk_rp_rect *rects)
  12359 {
  12360     /* rects array must be big enough to accommodate all characters in the given ranges */
  12361     int i,j,k;
  12362     k = 0;
  12363 
  12364     for (i=0; i < num_ranges; ++i) {
  12365         float fh = ranges[i].font_size;
  12366         float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
  12367             nk_tt_ScaleForMappingEmToPixels(info, -fh);
  12368         ranges[i].h_oversample = (unsigned char) spc->h_oversample;
  12369         ranges[i].v_oversample = (unsigned char) spc->v_oversample;
  12370         for (j=0; j < ranges[i].num_chars; ++j) {
  12371             int x0,y0,x1,y1;
  12372             int codepoint = ranges[i].first_unicode_codepoint_in_range ?
  12373                 ranges[i].first_unicode_codepoint_in_range + j :
  12374                 ranges[i].array_of_unicode_codepoints[j];
  12375 
  12376             int glyph = nk_tt_FindGlyphIndex(info, codepoint);
  12377             nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
  12378                 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
  12379             rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
  12380             rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
  12381             ++k;
  12382         }
  12383     }
  12384     return k;
  12385 }
  12386 NK_INTERN int
  12387 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
  12388     struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
  12389     int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
  12390 {
  12391     int i,j,k, return_value = 1;
  12392     /* save current values */
  12393     int old_h_over = (int)spc->h_oversample;
  12394     int old_v_over = (int)spc->v_oversample;
  12395     /* rects array must be big enough to accommodate all characters in the given ranges */
  12396 
  12397     k = 0;
  12398     for (i=0; i < num_ranges; ++i)
  12399     {
  12400         float fh = ranges[i].font_size;
  12401         float recip_h,recip_v,sub_x,sub_y;
  12402         float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
  12403             nk_tt_ScaleForMappingEmToPixels(info, -fh);
  12404 
  12405         spc->h_oversample = ranges[i].h_oversample;
  12406         spc->v_oversample = ranges[i].v_oversample;
  12407 
  12408         recip_h = 1.0f / (float)spc->h_oversample;
  12409         recip_v = 1.0f / (float)spc->v_oversample;
  12410 
  12411         sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
  12412         sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
  12413 
  12414         for (j=0; j < ranges[i].num_chars; ++j)
  12415         {
  12416             struct nk_rp_rect *r = &rects[k];
  12417             if (r->was_packed)
  12418             {
  12419                 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
  12420                 int advance, lsb, x0,y0,x1,y1;
  12421                 int codepoint = ranges[i].first_unicode_codepoint_in_range ?
  12422                     ranges[i].first_unicode_codepoint_in_range + j :
  12423                     ranges[i].array_of_unicode_codepoints[j];
  12424                 int glyph = nk_tt_FindGlyphIndex(info, codepoint);
  12425                 nk_rp_coord pad = (nk_rp_coord) spc->padding;
  12426 
  12427                 /* pad on left and top */
  12428                 r->x = (nk_rp_coord)((int)r->x + (int)pad);
  12429                 r->y = (nk_rp_coord)((int)r->y + (int)pad);
  12430                 r->w = (nk_rp_coord)((int)r->w - (int)pad);
  12431                 r->h = (nk_rp_coord)((int)r->h - (int)pad);
  12432 
  12433                 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
  12434                 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
  12435                         (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
  12436                 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
  12437                     (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
  12438                     spc->stride_in_bytes, scale * (float)spc->h_oversample,
  12439                     scale * (float)spc->v_oversample, 0,0, glyph, alloc);
  12440 
  12441                 if (spc->h_oversample > 1)
  12442                    nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
  12443                         r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
  12444 
  12445                 if (spc->v_oversample > 1)
  12446                    nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
  12447                         r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
  12448 
  12449                 bc->x0       = (nk_ushort)  r->x;
  12450                 bc->y0       = (nk_ushort)  r->y;
  12451                 bc->x1       = (nk_ushort) (r->x + r->w);
  12452                 bc->y1       = (nk_ushort) (r->y + r->h);
  12453                 bc->xadvance = scale * (float)advance;
  12454                 bc->xoff     = (float)  x0 * recip_h + sub_x;
  12455                 bc->yoff     = (float)  y0 * recip_v + sub_y;
  12456                 bc->xoff2    = ((float)x0 + r->w) * recip_h + sub_x;
  12457                 bc->yoff2    = ((float)y0 + r->h) * recip_v + sub_y;
  12458             } else {
  12459                 return_value = 0; /* if any fail, report failure */
  12460             }
  12461             ++k;
  12462         }
  12463     }
  12464     /* restore original values */
  12465     spc->h_oversample = (unsigned int)old_h_over;
  12466     spc->v_oversample = (unsigned int)old_v_over;
  12467     return return_value;
  12468 }
  12469 NK_INTERN void
  12470 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
  12471     int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
  12472     int align_to_integer)
  12473 {
  12474     float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
  12475     struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
  12476     if (align_to_integer) {
  12477         int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
  12478         int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
  12479 
  12480         float x = (float)tx;
  12481         float y = (float)ty;
  12482 
  12483         q->x0 = x;
  12484         q->y0 = y;
  12485         q->x1 = x + b->xoff2 - b->xoff;
  12486         q->y1 = y + b->yoff2 - b->yoff;
  12487     } else {
  12488         q->x0 = *xpos + b->xoff;
  12489         q->y0 = *ypos + b->yoff;
  12490         q->x1 = *xpos + b->xoff2;
  12491         q->y1 = *ypos + b->yoff2;
  12492     }
  12493     q->s0 = b->x0 * ipw;
  12494     q->t0 = b->y0 * iph;
  12495     q->s1 = b->x1 * ipw;
  12496     q->t1 = b->y1 * iph;
  12497     *xpos += b->xadvance;
  12498 }
  12499 
  12500 /* -------------------------------------------------------------
  12501  *
  12502  *                          FONT BAKING
  12503  *
  12504  * --------------------------------------------------------------*/
  12505 struct nk_font_bake_data {
  12506     struct nk_tt_fontinfo info;
  12507     struct nk_rp_rect *rects;
  12508     struct nk_tt_pack_range *ranges;
  12509     nk_rune range_count;
  12510 };
  12511 
  12512 struct nk_font_baker {
  12513     struct nk_allocator alloc;
  12514     struct nk_tt_pack_context spc;
  12515     struct nk_font_bake_data *build;
  12516     struct nk_tt_packedchar *packed_chars;
  12517     struct nk_rp_rect *rects;
  12518     struct nk_tt_pack_range *ranges;
  12519 };
  12520 
  12521 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
  12522 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
  12523 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
  12524 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
  12525 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
  12526 
  12527 NK_INTERN int
  12528 nk_range_count(const nk_rune *range)
  12529 {
  12530     const nk_rune *iter = range;
  12531     NK_ASSERT(range);
  12532     if (!range) return 0;
  12533     while (*(iter++) != 0);
  12534     return (iter == range) ? 0 : (int)((iter - range)/2);
  12535 }
  12536 NK_INTERN int
  12537 nk_range_glyph_count(const nk_rune *range, int count)
  12538 {
  12539     int i = 0;
  12540     int total_glyphs = 0;
  12541     for (i = 0; i < count; ++i) {
  12542         int diff;
  12543         nk_rune f = range[(i*2)+0];
  12544         nk_rune t = range[(i*2)+1];
  12545         NK_ASSERT(t >= f);
  12546         diff = (int)((t - f) + 1);
  12547         total_glyphs += diff;
  12548     }
  12549     return total_glyphs;
  12550 }
  12551 NK_API const nk_rune*
  12552 nk_font_default_glyph_ranges(void)
  12553 {
  12554     NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
  12555     return ranges;
  12556 }
  12557 NK_API const nk_rune*
  12558 nk_font_chinese_glyph_ranges(void)
  12559 {
  12560     NK_STORAGE const nk_rune ranges[] = {
  12561         0x0020, 0x00FF,
  12562         0x3000, 0x30FF,
  12563         0x31F0, 0x31FF,
  12564         0xFF00, 0xFFEF,
  12565         0x4e00, 0x9FAF,
  12566         0
  12567     };
  12568     return ranges;
  12569 }
  12570 NK_API const nk_rune*
  12571 nk_font_cyrillic_glyph_ranges(void)
  12572 {
  12573     NK_STORAGE const nk_rune ranges[] = {
  12574         0x0020, 0x00FF,
  12575         0x0400, 0x052F,
  12576         0x2DE0, 0x2DFF,
  12577         0xA640, 0xA69F,
  12578         0
  12579     };
  12580     return ranges;
  12581 }
  12582 NK_API const nk_rune*
  12583 nk_font_korean_glyph_ranges(void)
  12584 {
  12585     NK_STORAGE const nk_rune ranges[] = {
  12586         0x0020, 0x00FF,
  12587         0x3131, 0x3163,
  12588         0xAC00, 0xD79D,
  12589         0
  12590     };
  12591     return ranges;
  12592 }
  12593 NK_INTERN void
  12594 nk_font_baker_memory(nk_size *temp, int *glyph_count,
  12595     struct nk_font_config *config_list, int count)
  12596 {
  12597     int range_count = 0;
  12598     int total_range_count = 0;
  12599     struct nk_font_config *iter, *i;
  12600 
  12601     NK_ASSERT(config_list);
  12602     NK_ASSERT(glyph_count);
  12603     if (!config_list) {
  12604         *temp = 0;
  12605         *glyph_count = 0;
  12606         return;
  12607     }
  12608     *glyph_count = 0;
  12609     for (iter = config_list; iter; iter = iter->next) {
  12610         i = iter;
  12611         do {if (!i->range) iter->range = nk_font_default_glyph_ranges();
  12612             range_count = nk_range_count(i->range);
  12613             total_range_count += range_count;
  12614             *glyph_count += nk_range_glyph_count(i->range, range_count);
  12615         } while ((i = i->n) != iter);
  12616     }
  12617     *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
  12618     *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
  12619     *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
  12620     *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
  12621     *temp += sizeof(struct nk_font_baker);
  12622     *temp += nk_rect_align + nk_range_align + nk_char_align;
  12623     *temp += nk_build_align + nk_baker_align;
  12624 }
  12625 NK_INTERN struct nk_font_baker*
  12626 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
  12627 {
  12628     struct nk_font_baker *baker;
  12629     if (!memory) return 0;
  12630     /* setup baker inside a memory block  */
  12631     baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
  12632     baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
  12633     baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
  12634     baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
  12635     baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
  12636     baker->alloc = *alloc;
  12637     return baker;
  12638 }
  12639 NK_INTERN int
  12640 nk_font_bake_pack(struct nk_font_baker *baker,
  12641     nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
  12642     const struct nk_font_config *config_list, int count,
  12643     struct nk_allocator *alloc)
  12644 {
  12645     NK_STORAGE const nk_size max_height = 1024 * 32;
  12646     const struct nk_font_config *config_iter, *it;
  12647     int total_glyph_count = 0;
  12648     int total_range_count = 0;
  12649     int range_count = 0;
  12650     int i = 0;
  12651 
  12652     NK_ASSERT(image_memory);
  12653     NK_ASSERT(width);
  12654     NK_ASSERT(height);
  12655     NK_ASSERT(config_list);
  12656     NK_ASSERT(count);
  12657     NK_ASSERT(alloc);
  12658 
  12659     if (!image_memory || !width || !height || !config_list || !count) return nk_false;
  12660     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
  12661         it = config_iter;
  12662         do {range_count = nk_range_count(it->range);
  12663             total_range_count += range_count;
  12664             total_glyph_count += nk_range_glyph_count(it->range, range_count);
  12665         } while ((it = it->n) != config_iter);
  12666     }
  12667     /* setup font baker from temporary memory */
  12668     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
  12669         it = config_iter;
  12670         do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0))
  12671             return nk_false;
  12672         } while ((it = it->n) != config_iter);
  12673     }
  12674     *height = 0;
  12675     *width = (total_glyph_count > 1000) ? 1024 : 512;
  12676     nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
  12677     {
  12678         int input_i = 0;
  12679         int range_n = 0;
  12680         int rect_n = 0;
  12681         int char_n = 0;
  12682 
  12683         if (custom) {
  12684             /* pack custom user data first so it will be in the upper left corner*/
  12685             struct nk_rp_rect custom_space;
  12686             nk_zero(&custom_space, sizeof(custom_space));
  12687             custom_space.w = (nk_rp_coord)(custom->w);
  12688             custom_space.h = (nk_rp_coord)(custom->h);
  12689 
  12690             nk_tt_PackSetOversampling(&baker->spc, 1, 1);
  12691             nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
  12692             *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
  12693 
  12694             custom->x = (short)custom_space.x;
  12695             custom->y = (short)custom_space.y;
  12696             custom->w = (short)custom_space.w;
  12697             custom->h = (short)custom_space.h;
  12698         }
  12699 
  12700         /* first font pass: pack all glyphs */
  12701         for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
  12702             config_iter = config_iter->next) {
  12703             it = config_iter;
  12704             do {int n = 0;
  12705                 int glyph_count;
  12706                 const nk_rune *in_range;
  12707                 const struct nk_font_config *cfg = it;
  12708                 struct nk_font_bake_data *tmp = &baker->build[input_i++];
  12709 
  12710                 /* count glyphs + ranges in current font */
  12711                 glyph_count = 0; range_count = 0;
  12712                 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
  12713                     glyph_count += (int)(in_range[1] - in_range[0]) + 1;
  12714                     range_count++;
  12715                 }
  12716 
  12717                 /* setup ranges  */
  12718                 tmp->ranges = baker->ranges + range_n;
  12719                 tmp->range_count = (nk_rune)range_count;
  12720                 range_n += range_count;
  12721                 for (i = 0; i < range_count; ++i) {
  12722                     in_range = &cfg->range[i * 2];
  12723                     tmp->ranges[i].font_size = cfg->size;
  12724                     tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
  12725                     tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
  12726                     tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
  12727                     char_n += tmp->ranges[i].num_chars;
  12728                 }
  12729 
  12730                 /* pack */
  12731                 tmp->rects = baker->rects + rect_n;
  12732                 rect_n += glyph_count;
  12733                 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
  12734                 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
  12735                     tmp->ranges, (int)tmp->range_count, tmp->rects);
  12736                 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
  12737 
  12738                 /* texture height */
  12739                 for (i = 0; i < n; ++i) {
  12740                     if (tmp->rects[i].was_packed)
  12741                         *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
  12742                 }
  12743             } while ((it = it->n) != config_iter);
  12744         }
  12745         NK_ASSERT(rect_n == total_glyph_count);
  12746         NK_ASSERT(char_n == total_glyph_count);
  12747         NK_ASSERT(range_n == total_range_count);
  12748     }
  12749     *height = (int)nk_round_up_pow2((nk_uint)*height);
  12750     *image_memory = (nk_size)(*width) * (nk_size)(*height);
  12751     return nk_true;
  12752 }
  12753 NK_INTERN void
  12754 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
  12755     struct nk_font_glyph *glyphs, int glyphs_count,
  12756     const struct nk_font_config *config_list, int font_count)
  12757 {
  12758     int input_i = 0;
  12759     nk_rune glyph_n = 0;
  12760     const struct nk_font_config *config_iter;
  12761     const struct nk_font_config *it;
  12762 
  12763     NK_ASSERT(image_memory);
  12764     NK_ASSERT(width);
  12765     NK_ASSERT(height);
  12766     NK_ASSERT(config_list);
  12767     NK_ASSERT(baker);
  12768     NK_ASSERT(font_count);
  12769     NK_ASSERT(glyphs_count);
  12770     if (!image_memory || !width || !height || !config_list ||
  12771         !font_count || !glyphs || !glyphs_count)
  12772         return;
  12773 
  12774     /* second font pass: render glyphs */
  12775     nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
  12776     baker->spc.pixels = (unsigned char*)image_memory;
  12777     baker->spc.height = (int)height;
  12778     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
  12779         config_iter = config_iter->next) {
  12780         it = config_iter;
  12781         do {const struct nk_font_config *cfg = it;
  12782             struct nk_font_bake_data *tmp = &baker->build[input_i++];
  12783             nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
  12784             nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
  12785                 (int)tmp->range_count, tmp->rects, &baker->alloc);
  12786         } while ((it = it->n) != config_iter);
  12787     } nk_tt_PackEnd(&baker->spc, &baker->alloc);
  12788 
  12789     /* third pass: setup font and glyphs */
  12790     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
  12791         config_iter = config_iter->next) {
  12792         it = config_iter;
  12793         do {nk_size i = 0;
  12794             int char_idx = 0;
  12795             nk_rune glyph_count = 0;
  12796             const struct nk_font_config *cfg = it;
  12797             struct nk_font_bake_data *tmp = &baker->build[input_i++];
  12798             struct nk_baked_font *dst_font = cfg->font;
  12799 
  12800             float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
  12801             int unscaled_ascent, unscaled_descent, unscaled_line_gap;
  12802             nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
  12803                                     &unscaled_line_gap);
  12804 
  12805             /* fill baked font */
  12806             if (!cfg->merge_mode) {
  12807                 dst_font->ranges = cfg->range;
  12808                 dst_font->height = cfg->size;
  12809                 dst_font->ascent = ((float)unscaled_ascent * font_scale);
  12810                 dst_font->descent = ((float)unscaled_descent * font_scale);
  12811                 dst_font->glyph_offset = glyph_n;
  12812             }
  12813 
  12814             /* fill own baked font glyph array */
  12815             for (i = 0; i < tmp->range_count; ++i) {
  12816                 struct nk_tt_pack_range *range = &tmp->ranges[i];
  12817                 for (char_idx = 0; char_idx < range->num_chars; char_idx++)
  12818                 {
  12819                     nk_rune codepoint = 0;
  12820                     float dummy_x = 0, dummy_y = 0;
  12821                     struct nk_tt_aligned_quad q;
  12822                     struct nk_font_glyph *glyph;
  12823 
  12824                     /* query glyph bounds from stb_truetype */
  12825                     const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
  12826                     if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
  12827                     codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
  12828                     nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
  12829                         (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
  12830 
  12831                     /* fill own glyph type with data */
  12832                     glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count];
  12833                     glyph->codepoint = codepoint;
  12834                     glyph->x0 = q.x0; glyph->y0 = q.y0;
  12835                     glyph->x1 = q.x1; glyph->y1 = q.y1;
  12836                     glyph->y0 += (dst_font->ascent + 0.5f);
  12837                     glyph->y1 += (dst_font->ascent + 0.5f);
  12838                     glyph->w = glyph->x1 - glyph->x0 + 0.5f;
  12839                     glyph->h = glyph->y1 - glyph->y0;
  12840 
  12841                     if (cfg->coord_type == NK_COORD_PIXEL) {
  12842                         glyph->u0 = q.s0 * (float)width;
  12843                         glyph->v0 = q.t0 * (float)height;
  12844                         glyph->u1 = q.s1 * (float)width;
  12845                         glyph->v1 = q.t1 * (float)height;
  12846                     } else {
  12847                         glyph->u0 = q.s0;
  12848                         glyph->v0 = q.t0;
  12849                         glyph->u1 = q.s1;
  12850                         glyph->v1 = q.t1;
  12851                     }
  12852                     glyph->xadvance = (pc->xadvance + cfg->spacing.x);
  12853                     if (cfg->pixel_snap)
  12854                         glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
  12855                     glyph_count++;
  12856                 }
  12857             }
  12858             dst_font->glyph_count += glyph_count;
  12859             glyph_n += glyph_count;
  12860         } while ((it = it->n) != config_iter);
  12861     }
  12862 }
  12863 NK_INTERN void
  12864 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
  12865     struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
  12866     int tex_height, char white, char black)
  12867 {
  12868     nk_byte *pixels;
  12869     int y = 0;
  12870     int x = 0;
  12871     int n = 0;
  12872 
  12873     NK_ASSERT(img_memory);
  12874     NK_ASSERT(img_width);
  12875     NK_ASSERT(img_height);
  12876     NK_ASSERT(texture_data_mask);
  12877     NK_UNUSED(tex_height);
  12878     if (!img_memory || !img_width || !img_height || !texture_data_mask)
  12879         return;
  12880 
  12881     pixels = (nk_byte*)img_memory;
  12882     for (y = 0, n = 0; y < tex_height; ++y) {
  12883         for (x = 0; x < tex_width; ++x, ++n) {
  12884             const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
  12885             const int off1 = off0 + 1 + tex_width;
  12886             pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
  12887             pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
  12888         }
  12889     }
  12890 }
  12891 NK_INTERN void
  12892 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
  12893     const void *in_memory)
  12894 {
  12895     int n = 0;
  12896     nk_rune *dst;
  12897     const nk_byte *src;
  12898 
  12899     NK_ASSERT(out_memory);
  12900     NK_ASSERT(in_memory);
  12901     NK_ASSERT(img_width);
  12902     NK_ASSERT(img_height);
  12903     if (!out_memory || !in_memory || !img_height || !img_width) return;
  12904 
  12905     dst = (nk_rune*)out_memory;
  12906     src = (const nk_byte*)in_memory;
  12907     for (n = (int)(img_width * img_height); n > 0; n--)
  12908         *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
  12909 }
  12910 
  12911 /* -------------------------------------------------------------
  12912  *
  12913  *                          FONT
  12914  *
  12915  * --------------------------------------------------------------*/
  12916 NK_INTERN float
  12917 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
  12918 {
  12919     nk_rune unicode;
  12920     int text_len  = 0;
  12921     float text_width = 0;
  12922     int glyph_len = 0;
  12923     float scale = 0;
  12924 
  12925     struct nk_font *font = (struct nk_font*)handle.ptr;
  12926     NK_ASSERT(font);
  12927     NK_ASSERT(font->glyphs);
  12928     if (!font || !text || !len)
  12929         return 0;
  12930 
  12931     scale = height/font->info.height;
  12932     glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
  12933     if (!glyph_len) return 0;
  12934     while (text_len <= (int)len && glyph_len) {
  12935         const struct nk_font_glyph *g;
  12936         if (unicode == NK_UTF_INVALID) break;
  12937 
  12938         /* query currently drawn glyph information */
  12939         g = nk_font_find_glyph(font, unicode);
  12940         text_width += g->xadvance * scale;
  12941 
  12942         /* offset next glyph */
  12943         glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
  12944         text_len += glyph_len;
  12945     }
  12946     return text_width;
  12947 }
  12948 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  12949 NK_INTERN void
  12950 nk_font_query_font_glyph(nk_handle handle, float height,
  12951     struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
  12952 {
  12953     float scale;
  12954     const struct nk_font_glyph *g;
  12955     struct nk_font *font;
  12956 
  12957     NK_ASSERT(glyph);
  12958     NK_UNUSED(next_codepoint);
  12959 
  12960     font = (struct nk_font*)handle.ptr;
  12961     NK_ASSERT(font);
  12962     NK_ASSERT(font->glyphs);
  12963     if (!font || !glyph)
  12964         return;
  12965 
  12966     scale = height/font->info.height;
  12967     g = nk_font_find_glyph(font, codepoint);
  12968     glyph->width = (g->x1 - g->x0) * scale;
  12969     glyph->height = (g->y1 - g->y0) * scale;
  12970     glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
  12971     glyph->xadvance = (g->xadvance * scale);
  12972     glyph->uv[0] = nk_vec2(g->u0, g->v0);
  12973     glyph->uv[1] = nk_vec2(g->u1, g->v1);
  12974 }
  12975 #endif
  12976 NK_API const struct nk_font_glyph*
  12977 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
  12978 {
  12979     int i = 0;
  12980     int count;
  12981     int total_glyphs = 0;
  12982     const struct nk_font_glyph *glyph = 0;
  12983     const struct nk_font_config *iter = 0;
  12984 
  12985     NK_ASSERT(font);
  12986     NK_ASSERT(font->glyphs);
  12987     NK_ASSERT(font->info.ranges);
  12988     if (!font || !font->glyphs) return 0;
  12989 
  12990     glyph = font->fallback;
  12991     iter = font->config;
  12992     do {count = nk_range_count(iter->range);
  12993         for (i = 0; i < count; ++i) {
  12994             nk_rune f = iter->range[(i*2)+0];
  12995             nk_rune t = iter->range[(i*2)+1];
  12996             int diff = (int)((t - f) + 1);
  12997             if (unicode >= f && unicode <= t)
  12998                 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
  12999             total_glyphs += diff;
  13000         }
  13001     } while ((iter = iter->n) != font->config);
  13002     return glyph;
  13003 }
  13004 NK_INTERN void
  13005 nk_font_init(struct nk_font *font, float pixel_height,
  13006     nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
  13007     const struct nk_baked_font *baked_font, nk_handle atlas)
  13008 {
  13009     struct nk_baked_font baked;
  13010     NK_ASSERT(font);
  13011     NK_ASSERT(glyphs);
  13012     NK_ASSERT(baked_font);
  13013     if (!font || !glyphs || !baked_font)
  13014         return;
  13015 
  13016     baked = *baked_font;
  13017     font->fallback = 0;
  13018     font->info = baked;
  13019     font->scale = (float)pixel_height / (float)font->info.height;
  13020     font->glyphs = &glyphs[baked_font->glyph_offset];
  13021     font->texture = atlas;
  13022     font->fallback_codepoint = fallback_codepoint;
  13023     font->fallback = nk_font_find_glyph(font, fallback_codepoint);
  13024 
  13025     font->handle.height = font->info.height * font->scale;
  13026     font->handle.width = nk_font_text_width;
  13027     font->handle.userdata.ptr = font;
  13028 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  13029     font->handle.query = nk_font_query_font_glyph;
  13030     font->handle.texture = font->texture;
  13031 #endif
  13032 }
  13033 
  13034 /* ---------------------------------------------------------------------------
  13035  *
  13036  *                          DEFAULT FONT
  13037  *
  13038  * ProggyClean.ttf
  13039  * Copyright (c) 2004, 2005 Tristan Grimmer
  13040  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
  13041  * Download and more information at http://upperbounds.net
  13042  *-----------------------------------------------------------------------------*/
  13043 #ifdef __clang__
  13044 #pragma clang diagnostic push
  13045 #pragma clang diagnostic ignored "-Woverlength-strings"
  13046 #elif defined(__GNUC__) || defined(__GNUG__)
  13047 #pragma GCC diagnostic push
  13048 #pragma GCC diagnostic ignored "-Woverlength-strings"
  13049 #endif
  13050 
  13051 #ifdef NK_INCLUDE_DEFAULT_FONT
  13052 
  13053 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
  13054     "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
  13055     "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#"
  13056     "`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"
  13057     "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"
  13058     "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"
  13059     "*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)"
  13060     "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"
  13061     "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."
  13062     "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"
  13063     "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(,)"
  13064     "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#"
  13065     "'/###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"
  13066     "_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"
  13067     "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/"
  13068     "/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"
  13069     "%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&#"
  13070     "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)("
  13071     "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"
  13072     "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"
  13073     "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^-"
  13074     "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-"
  13075     "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"
  13076     "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%"
  13077     "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]"
  13078     "%(?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"
  13079     "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:"
  13080     "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("
  13081     "$/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<"
  13082     "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'?"
  13083     "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/;"
  13084     ")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"
  13085     "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("
  13086     "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"
  13087     "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
  13088     "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<-"
  13089     "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"
  13090     "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"
  13091     ".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@@"
  13092     "$&)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*"
  13093     "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"
  13094     "@-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&#"
  13095     "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#"
  13096     "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"
  13097     "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"
  13098     "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&#"
  13099     "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"
  13100     ":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+"
  13101     "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*"
  13102     "$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"
  13103     ":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"
  13104     "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"
  13105     "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"
  13106     "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"
  13107     ":^#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@&]>"
  13108     "_>@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%"
  13109     "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;"
  13110     "^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:"
  13111     "+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%"
  13112     "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-"
  13113     "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*"
  13114     "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"
  13115     "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
  13116     "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`"
  13117     "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]%/"
  13118     "+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"
  13119     "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"
  13120     "?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"
  13121     "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"
  13122     ">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'>"
  13123     "[%$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"
  13124     "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#"
  13125     "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$"
  13126     "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,)"
  13127     "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"
  13128     "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"
  13129     "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"
  13130     "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(#"
  13131     ";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&>"
  13132     "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#"
  13133     "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"
  13134     "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#"
  13135     "/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-#"
  13136     "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#"
  13137     "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
  13138     "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
  13139     "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
  13140 
  13141 #endif /* NK_INCLUDE_DEFAULT_FONT */
  13142 
  13143 #define NK_CURSOR_DATA_W 90
  13144 #define NK_CURSOR_DATA_H 27
  13145 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
  13146 {
  13147     "..-         -XXXXXXX-    X    -           X           -XXXXXXX          -          XXXXXXX"
  13148     "..-         -X.....X-   X.X   -          X.X          -X.....X          -          X.....X"
  13149     "---         -XXX.XXX-  X...X  -         X...X         -X....X           -           X....X"
  13150     "X           -  X.X  - X.....X -        X.....X        -X...X            -            X...X"
  13151     "XX          -  X.X  -X.......X-       X.......X       -X..X.X           -           X.X..X"
  13152     "X.X         -  X.X  -XXXX.XXXX-       XXXX.XXXX       -X.X X.X          -          X.X X.X"
  13153     "X..X        -  X.X  -   X.X   -          X.X          -XX   X.X         -         X.X   XX"
  13154     "X...X       -  X.X  -   X.X   -    XX    X.X    XX    -      X.X        -        X.X      "
  13155     "X....X      -  X.X  -   X.X   -   X.X    X.X    X.X   -       X.X       -       X.X       "
  13156     "X.....X     -  X.X  -   X.X   -  X..X    X.X    X..X  -        X.X      -      X.X        "
  13157     "X......X    -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -         X.X   XX-XX   X.X         "
  13158     "X.......X   -  X.X  -   X.X   -X.....................X-          X.X X.X-X.X X.X          "
  13159     "X........X  -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -           X.X..X-X..X.X           "
  13160     "X.........X -XXX.XXX-   X.X   -  X..X    X.X    X..X  -            X...X-X...X            "
  13161     "X..........X-X.....X-   X.X   -   X.X    X.X    X.X   -           X....X-X....X           "
  13162     "X......XXXXX-XXXXXXX-   X.X   -    XX    X.X    XX    -          X.....X-X.....X          "
  13163     "X...X..X    ---------   X.X   -          X.X          -          XXXXXXX-XXXXXXX          "
  13164     "X..X X..X   -       -XXXX.XXXX-       XXXX.XXXX       ------------------------------------"
  13165     "X.X  X..X   -       -X.......X-       X.......X       -    XX           XX    -           "
  13166     "XX    X..X  -       - X.....X -        X.....X        -   X.X           X.X   -           "
  13167     "      X..X          -  X...X  -         X...X         -  X..X           X..X  -           "
  13168     "       XX           -   X.X   -          X.X          - X...XXXXXXXXXXXXX...X -           "
  13169     "------------        -    X    -           X           -X.....................X-           "
  13170     "                    ----------------------------------- X...XXXXXXXXXXXXX...X -           "
  13171     "                                                      -  X..X           X..X  -           "
  13172     "                                                      -   X.X           X.X   -           "
  13173     "                                                      -    XX           XX    -           "
  13174 };
  13175 
  13176 #ifdef __clang__
  13177 #pragma clang diagnostic pop
  13178 #elif defined(__GNUC__) || defined(__GNUG__)
  13179 #pragma GCC diagnostic pop
  13180 #endif
  13181 
  13182 NK_GLOBAL unsigned char *nk__barrier;
  13183 NK_GLOBAL unsigned char *nk__barrier2;
  13184 NK_GLOBAL unsigned char *nk__barrier3;
  13185 NK_GLOBAL unsigned char *nk__barrier4;
  13186 NK_GLOBAL unsigned char *nk__dout;
  13187 
  13188 NK_INTERN unsigned int
  13189 nk_decompress_length(unsigned char *input)
  13190 {
  13191     return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
  13192 }
  13193 NK_INTERN void
  13194 nk__match(unsigned char *data, unsigned int length)
  13195 {
  13196     /* INVERSE of memmove... write each byte before copying the next...*/
  13197     NK_ASSERT (nk__dout + length <= nk__barrier);
  13198     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
  13199     if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
  13200     while (length--) *nk__dout++ = *data++;
  13201 }
  13202 NK_INTERN void
  13203 nk__lit(unsigned char *data, unsigned int length)
  13204 {
  13205     NK_ASSERT (nk__dout + length <= nk__barrier);
  13206     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
  13207     if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
  13208     NK_MEMCPY(nk__dout, data, length);
  13209     nk__dout += length;
  13210 }
  13211 NK_INTERN unsigned char*
  13212 nk_decompress_token(unsigned char *i)
  13213 {
  13214     #define nk__in2(x)   ((i[x] << 8) + i[(x)+1])
  13215     #define nk__in3(x)   ((i[x] << 16) + nk__in2((x)+1))
  13216     #define nk__in4(x)   ((i[x] << 24) + nk__in3((x)+1))
  13217 
  13218     if (*i >= 0x20) { /* use fewer if's for cases that expand small */
  13219         if (*i >= 0x80)       nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
  13220         else if (*i >= 0x40)  nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
  13221         else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
  13222     } else { /* more ifs for cases that expand large, since overhead is amortized */
  13223         if (*i >= 0x18)       nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
  13224         else if (*i >= 0x10)  nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
  13225         else if (*i >= 0x08)  nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
  13226         else if (*i == 0x07)  nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
  13227         else if (*i == 0x06)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
  13228         else if (*i == 0x04)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
  13229     }
  13230     return i;
  13231 }
  13232 NK_INTERN unsigned int
  13233 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
  13234 {
  13235     const unsigned long ADLER_MOD = 65521;
  13236     unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
  13237     unsigned long blocklen, i;
  13238 
  13239     blocklen = buflen % 5552;
  13240     while (buflen) {
  13241         for (i=0; i + 7 < blocklen; i += 8) {
  13242             s1 += buffer[0]; s2 += s1;
  13243             s1 += buffer[1]; s2 += s1;
  13244             s1 += buffer[2]; s2 += s1;
  13245             s1 += buffer[3]; s2 += s1;
  13246             s1 += buffer[4]; s2 += s1;
  13247             s1 += buffer[5]; s2 += s1;
  13248             s1 += buffer[6]; s2 += s1;
  13249             s1 += buffer[7]; s2 += s1;
  13250             buffer += 8;
  13251         }
  13252         for (; i < blocklen; ++i) {
  13253             s1 += *buffer++; s2 += s1;
  13254         }
  13255 
  13256         s1 %= ADLER_MOD; s2 %= ADLER_MOD;
  13257         buflen -= (unsigned int)blocklen;
  13258         blocklen = 5552;
  13259     }
  13260     return (unsigned int)(s2 << 16) + (unsigned int)s1;
  13261 }
  13262 NK_INTERN unsigned int
  13263 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
  13264 {
  13265     unsigned int olen;
  13266     if (nk__in4(0) != 0x57bC0000) return 0;
  13267     if (nk__in4(4) != 0)          return 0; /* error! stream is > 4GB */
  13268     olen = nk_decompress_length(i);
  13269     nk__barrier2 = i;
  13270     nk__barrier3 = i+length;
  13271     nk__barrier = output + olen;
  13272     nk__barrier4 = output;
  13273     i += 16;
  13274 
  13275     nk__dout = output;
  13276     for (;;) {
  13277         unsigned char *old_i = i;
  13278         i = nk_decompress_token(i);
  13279         if (i == old_i) {
  13280             if (*i == 0x05 && i[1] == 0xfa) {
  13281                 NK_ASSERT(nk__dout == output + olen);
  13282                 if (nk__dout != output + olen) return 0;
  13283                 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
  13284                     return 0;
  13285                 return olen;
  13286             } else {
  13287                 NK_ASSERT(0); /* NOTREACHED */
  13288                 return 0;
  13289             }
  13290         }
  13291         NK_ASSERT(nk__dout <= output + olen);
  13292         if (nk__dout > output + olen)
  13293             return 0;
  13294     }
  13295 }
  13296 NK_INTERN unsigned int
  13297 nk_decode_85_byte(char c)
  13298 {
  13299     return (unsigned int)((c >= '\\') ? c-36 : c-35);
  13300 }
  13301 NK_INTERN void
  13302 nk_decode_85(unsigned char* dst, const unsigned char* src)
  13303 {
  13304     while (*src)
  13305     {
  13306         unsigned int tmp =
  13307             nk_decode_85_byte((char)src[0]) +
  13308             85 * (nk_decode_85_byte((char)src[1]) +
  13309             85 * (nk_decode_85_byte((char)src[2]) +
  13310             85 * (nk_decode_85_byte((char)src[3]) +
  13311             85 * nk_decode_85_byte((char)src[4]))));
  13312 
  13313         /* we can't assume little-endianess. */
  13314         dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
  13315         dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
  13316         dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
  13317         dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
  13318 
  13319         src += 5;
  13320         dst += 4;
  13321     }
  13322 }
  13323 
  13324 /* -------------------------------------------------------------
  13325  *
  13326  *                          FONT ATLAS
  13327  *
  13328  * --------------------------------------------------------------*/
  13329 NK_API struct nk_font_config
  13330 nk_font_config(float pixel_height)
  13331 {
  13332     struct nk_font_config cfg;
  13333     nk_zero_struct(cfg);
  13334     cfg.ttf_blob = 0;
  13335     cfg.ttf_size = 0;
  13336     cfg.ttf_data_owned_by_atlas = 0;
  13337     cfg.size = pixel_height;
  13338     cfg.oversample_h = 3;
  13339     cfg.oversample_v = 1;
  13340     cfg.pixel_snap = 0;
  13341     cfg.coord_type = NK_COORD_UV;
  13342     cfg.spacing = nk_vec2(0,0);
  13343     cfg.range = nk_font_default_glyph_ranges();
  13344     cfg.merge_mode = 0;
  13345     cfg.fallback_glyph = '?';
  13346     cfg.font = 0;
  13347     cfg.n = 0;
  13348     return cfg;
  13349 }
  13350 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
  13351 NK_API void
  13352 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
  13353 {
  13354     NK_ASSERT(atlas);
  13355     if (!atlas) return;
  13356     nk_zero_struct(*atlas);
  13357     atlas->temporary.userdata.ptr = 0;
  13358     atlas->temporary.alloc = nk_malloc;
  13359     atlas->temporary.free = nk_mfree;
  13360     atlas->permanent.userdata.ptr = 0;
  13361     atlas->permanent.alloc = nk_malloc;
  13362     atlas->permanent.free = nk_mfree;
  13363 }
  13364 #endif
  13365 NK_API void
  13366 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
  13367 {
  13368     NK_ASSERT(atlas);
  13369     NK_ASSERT(alloc);
  13370     if (!atlas || !alloc) return;
  13371     nk_zero_struct(*atlas);
  13372     atlas->permanent = *alloc;
  13373     atlas->temporary = *alloc;
  13374 }
  13375 NK_API void
  13376 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
  13377     struct nk_allocator *permanent, struct nk_allocator *temporary)
  13378 {
  13379     NK_ASSERT(atlas);
  13380     NK_ASSERT(permanent);
  13381     NK_ASSERT(temporary);
  13382     if (!atlas || !permanent || !temporary) return;
  13383     nk_zero_struct(*atlas);
  13384     atlas->permanent = *permanent;
  13385     atlas->temporary = *temporary;
  13386 }
  13387 NK_API void
  13388 nk_font_atlas_begin(struct nk_font_atlas *atlas)
  13389 {
  13390     NK_ASSERT(atlas);
  13391     NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
  13392     NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
  13393     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
  13394         !atlas->temporary.alloc || !atlas->temporary.free) return;
  13395     if (atlas->glyphs) {
  13396         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
  13397         atlas->glyphs = 0;
  13398     }
  13399     if (atlas->pixel) {
  13400         atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
  13401         atlas->pixel = 0;
  13402     }
  13403 }
  13404 NK_API struct nk_font*
  13405 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
  13406 {
  13407     struct nk_font *font = 0;
  13408     struct nk_font_config *cfg;
  13409 
  13410     NK_ASSERT(atlas);
  13411     NK_ASSERT(atlas->permanent.alloc);
  13412     NK_ASSERT(atlas->permanent.free);
  13413     NK_ASSERT(atlas->temporary.alloc);
  13414     NK_ASSERT(atlas->temporary.free);
  13415 
  13416     NK_ASSERT(config);
  13417     NK_ASSERT(config->ttf_blob);
  13418     NK_ASSERT(config->ttf_size);
  13419     NK_ASSERT(config->size > 0.0f);
  13420 
  13421     if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
  13422         !atlas->permanent.alloc || !atlas->permanent.free ||
  13423         !atlas->temporary.alloc || !atlas->temporary.free)
  13424         return 0;
  13425 
  13426     /* allocate font config  */
  13427     cfg = (struct nk_font_config*)
  13428         atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
  13429     NK_MEMCPY(cfg, config, sizeof(*config));
  13430     cfg->n = cfg;
  13431     cfg->p = cfg;
  13432 
  13433     if (!config->merge_mode) {
  13434         /* insert font config into list */
  13435         if (!atlas->config) {
  13436             atlas->config = cfg;
  13437             cfg->next = 0;
  13438         } else {
  13439             struct nk_font_config *i = atlas->config;
  13440             while (i->next) i = i->next;
  13441             i->next = cfg;
  13442             cfg->next = 0;
  13443         }
  13444         /* allocate new font */
  13445         font = (struct nk_font*)
  13446             atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
  13447         NK_ASSERT(font);
  13448         nk_zero(font, sizeof(*font));
  13449         if (!font) return 0;
  13450         font->config = cfg;
  13451 
  13452         /* insert font into list */
  13453         if (!atlas->fonts) {
  13454             atlas->fonts = font;
  13455             font->next = 0;
  13456         } else {
  13457             struct nk_font *i = atlas->fonts;
  13458             while (i->next) i = i->next;
  13459             i->next = font;
  13460             font->next = 0;
  13461         }
  13462         cfg->font = &font->info;
  13463     } else {
  13464         /* extend previously added font */
  13465         struct nk_font *f = 0;
  13466         struct nk_font_config *c = 0;
  13467         NK_ASSERT(atlas->font_num);
  13468         f = atlas->fonts;
  13469         c = f->config;
  13470         cfg->font = &f->info;
  13471 
  13472         cfg->n = c;
  13473         cfg->p = c->p;
  13474         c->p->n = cfg;
  13475         c->p = cfg;
  13476     }
  13477     /* create own copy of .TTF font blob */
  13478     if (!config->ttf_data_owned_by_atlas) {
  13479         cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
  13480         NK_ASSERT(cfg->ttf_blob);
  13481         if (!cfg->ttf_blob) {
  13482             atlas->font_num++;
  13483             return 0;
  13484         }
  13485         NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
  13486         cfg->ttf_data_owned_by_atlas = 1;
  13487     }
  13488     atlas->font_num++;
  13489     return font;
  13490 }
  13491 NK_API struct nk_font*
  13492 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
  13493     nk_size size, float height, const struct nk_font_config *config)
  13494 {
  13495     struct nk_font_config cfg;
  13496     NK_ASSERT(memory);
  13497     NK_ASSERT(size);
  13498 
  13499     NK_ASSERT(atlas);
  13500     NK_ASSERT(atlas->temporary.alloc);
  13501     NK_ASSERT(atlas->temporary.free);
  13502     NK_ASSERT(atlas->permanent.alloc);
  13503     NK_ASSERT(atlas->permanent.free);
  13504     if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
  13505         !atlas->permanent.alloc || !atlas->permanent.free)
  13506         return 0;
  13507 
  13508     cfg = (config) ? *config: nk_font_config(height);
  13509     cfg.ttf_blob = memory;
  13510     cfg.ttf_size = size;
  13511     cfg.size = height;
  13512     cfg.ttf_data_owned_by_atlas = 0;
  13513     return nk_font_atlas_add(atlas, &cfg);
  13514 }
  13515 #ifdef NK_INCLUDE_STANDARD_IO
  13516 NK_API struct nk_font*
  13517 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
  13518     float height, const struct nk_font_config *config)
  13519 {
  13520     nk_size size;
  13521     char *memory;
  13522     struct nk_font_config cfg;
  13523 
  13524     NK_ASSERT(atlas);
  13525     NK_ASSERT(atlas->temporary.alloc);
  13526     NK_ASSERT(atlas->temporary.free);
  13527     NK_ASSERT(atlas->permanent.alloc);
  13528     NK_ASSERT(atlas->permanent.free);
  13529 
  13530     if (!atlas || !file_path) return 0;
  13531     memory = nk_file_load(file_path, &size, &atlas->permanent);
  13532     if (!memory) return 0;
  13533 
  13534     cfg = (config) ? *config: nk_font_config(height);
  13535     cfg.ttf_blob = memory;
  13536     cfg.ttf_size = size;
  13537     cfg.size = height;
  13538     cfg.ttf_data_owned_by_atlas = 1;
  13539     return nk_font_atlas_add(atlas, &cfg);
  13540 }
  13541 #endif
  13542 NK_API struct nk_font*
  13543 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
  13544     void *compressed_data, nk_size compressed_size, float height,
  13545     const struct nk_font_config *config)
  13546 {
  13547     unsigned int decompressed_size;
  13548     void *decompressed_data;
  13549     struct nk_font_config cfg;
  13550 
  13551     NK_ASSERT(atlas);
  13552     NK_ASSERT(atlas->temporary.alloc);
  13553     NK_ASSERT(atlas->temporary.free);
  13554     NK_ASSERT(atlas->permanent.alloc);
  13555     NK_ASSERT(atlas->permanent.free);
  13556 
  13557     NK_ASSERT(compressed_data);
  13558     NK_ASSERT(compressed_size);
  13559     if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
  13560         !atlas->permanent.alloc || !atlas->permanent.free)
  13561         return 0;
  13562 
  13563     decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
  13564     decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
  13565     NK_ASSERT(decompressed_data);
  13566     if (!decompressed_data) return 0;
  13567     nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
  13568         (unsigned int)compressed_size);
  13569 
  13570     cfg = (config) ? *config: nk_font_config(height);
  13571     cfg.ttf_blob = decompressed_data;
  13572     cfg.ttf_size = decompressed_size;
  13573     cfg.size = height;
  13574     cfg.ttf_data_owned_by_atlas = 1;
  13575     return nk_font_atlas_add(atlas, &cfg);
  13576 }
  13577 NK_API struct nk_font*
  13578 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
  13579     const char *data_base85, float height, const struct nk_font_config *config)
  13580 {
  13581     int compressed_size;
  13582     void *compressed_data;
  13583     struct nk_font *font;
  13584 
  13585     NK_ASSERT(atlas);
  13586     NK_ASSERT(atlas->temporary.alloc);
  13587     NK_ASSERT(atlas->temporary.free);
  13588     NK_ASSERT(atlas->permanent.alloc);
  13589     NK_ASSERT(atlas->permanent.free);
  13590 
  13591     NK_ASSERT(data_base85);
  13592     if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
  13593         !atlas->permanent.alloc || !atlas->permanent.free)
  13594         return 0;
  13595 
  13596     compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
  13597     compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
  13598     NK_ASSERT(compressed_data);
  13599     if (!compressed_data) return 0;
  13600     nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
  13601     font = nk_font_atlas_add_compressed(atlas, compressed_data,
  13602                     (nk_size)compressed_size, height, config);
  13603     atlas->temporary.free(atlas->temporary.userdata, compressed_data);
  13604     return font;
  13605 }
  13606 
  13607 #ifdef NK_INCLUDE_DEFAULT_FONT
  13608 NK_API struct nk_font*
  13609 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
  13610     float pixel_height, const struct nk_font_config *config)
  13611 {
  13612     NK_ASSERT(atlas);
  13613     NK_ASSERT(atlas->temporary.alloc);
  13614     NK_ASSERT(atlas->temporary.free);
  13615     NK_ASSERT(atlas->permanent.alloc);
  13616     NK_ASSERT(atlas->permanent.free);
  13617     return nk_font_atlas_add_compressed_base85(atlas,
  13618         nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
  13619 }
  13620 #endif
  13621 NK_API const void*
  13622 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
  13623     enum nk_font_atlas_format fmt)
  13624 {
  13625     int i = 0;
  13626     void *tmp = 0;
  13627     nk_size tmp_size, img_size;
  13628     struct nk_font *font_iter;
  13629     struct nk_font_baker *baker;
  13630 
  13631     NK_ASSERT(atlas);
  13632     NK_ASSERT(atlas->temporary.alloc);
  13633     NK_ASSERT(atlas->temporary.free);
  13634     NK_ASSERT(atlas->permanent.alloc);
  13635     NK_ASSERT(atlas->permanent.free);
  13636 
  13637     NK_ASSERT(width);
  13638     NK_ASSERT(height);
  13639     if (!atlas || !width || !height ||
  13640         !atlas->temporary.alloc || !atlas->temporary.free ||
  13641         !atlas->permanent.alloc || !atlas->permanent.free)
  13642         return 0;
  13643 
  13644 #ifdef NK_INCLUDE_DEFAULT_FONT
  13645     /* no font added so just use default font */
  13646     if (!atlas->font_num)
  13647         atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
  13648 #endif
  13649     NK_ASSERT(atlas->font_num);
  13650     if (!atlas->font_num) return 0;
  13651 
  13652     /* allocate temporary baker memory required for the baking process */
  13653     nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
  13654     tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
  13655     NK_ASSERT(tmp);
  13656     if (!tmp) goto failed;
  13657 
  13658     /* allocate glyph memory for all fonts */
  13659     baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
  13660     atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
  13661         atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
  13662     NK_ASSERT(atlas->glyphs);
  13663     if (!atlas->glyphs)
  13664         goto failed;
  13665 
  13666     /* pack all glyphs into a tight fit space */
  13667     atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
  13668     atlas->custom.h = NK_CURSOR_DATA_H + 1;
  13669     if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
  13670         atlas->config, atlas->font_num, &atlas->temporary))
  13671         goto failed;
  13672 
  13673     /* allocate memory for the baked image font atlas */
  13674     atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
  13675     NK_ASSERT(atlas->pixel);
  13676     if (!atlas->pixel)
  13677         goto failed;
  13678 
  13679     /* bake glyphs and custom white pixel into image */
  13680     nk_font_bake(baker, atlas->pixel, *width, *height,
  13681         atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
  13682     nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
  13683             nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
  13684 
  13685     if (fmt == NK_FONT_ATLAS_RGBA32) {
  13686         /* convert alpha8 image into rgba32 image */
  13687         void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
  13688                             (nk_size)(*width * *height * 4));
  13689         NK_ASSERT(img_rgba);
  13690         if (!img_rgba) goto failed;
  13691         nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
  13692         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
  13693         atlas->pixel = img_rgba;
  13694     }
  13695     atlas->tex_width = *width;
  13696     atlas->tex_height = *height;
  13697 
  13698     /* initialize each font */
  13699     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
  13700         struct nk_font *font = font_iter;
  13701         struct nk_font_config *config = font->config;
  13702         nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
  13703             config->font, nk_handle_ptr(0));
  13704     }
  13705 
  13706     /* initialize each cursor */
  13707     {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
  13708         /* Pos      Size        Offset */
  13709         {{ 0, 3},   {12,19},    { 0, 0}},
  13710         {{13, 0},   { 7,16},    { 4, 8}},
  13711         {{31, 0},   {23,23},    {11,11}},
  13712         {{21, 0},   { 9, 23},   { 5,11}},
  13713         {{55,18},   {23, 9},    {11, 5}},
  13714         {{73, 0},   {17,17},    { 9, 9}},
  13715         {{55, 0},   {17,17},    { 9, 9}}
  13716     };
  13717     for (i = 0; i < NK_CURSOR_COUNT; ++i) {
  13718         struct nk_cursor *cursor = &atlas->cursors[i];
  13719         cursor->img.w = (unsigned short)*width;
  13720         cursor->img.h = (unsigned short)*height;
  13721         cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
  13722         cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
  13723         cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
  13724         cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
  13725         cursor->size = nk_cursor_data[i][1];
  13726         cursor->offset = nk_cursor_data[i][2];
  13727     }}
  13728     /* free temporary memory */
  13729     atlas->temporary.free(atlas->temporary.userdata, tmp);
  13730     return atlas->pixel;
  13731 
  13732 failed:
  13733     /* error so cleanup all memory */
  13734     if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
  13735     if (atlas->glyphs) {
  13736         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
  13737         atlas->glyphs = 0;
  13738     }
  13739     if (atlas->pixel) {
  13740         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
  13741         atlas->pixel = 0;
  13742     }
  13743     return 0;
  13744 }
  13745 NK_API void
  13746 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
  13747     struct nk_draw_null_texture *null)
  13748 {
  13749     int i = 0;
  13750     struct nk_font *font_iter;
  13751     NK_ASSERT(atlas);
  13752     if (!atlas) {
  13753         if (!null) return;
  13754         null->texture = texture;
  13755         null->uv = nk_vec2(0.5f,0.5f);
  13756     }
  13757     if (null) {
  13758         null->texture = texture;
  13759         null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
  13760         null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
  13761     }
  13762     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
  13763         font_iter->texture = texture;
  13764 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  13765         font_iter->handle.texture = texture;
  13766 #endif
  13767     }
  13768     for (i = 0; i < NK_CURSOR_COUNT; ++i)
  13769         atlas->cursors[i].img.handle = texture;
  13770 
  13771     atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
  13772     atlas->pixel = 0;
  13773     atlas->tex_width = 0;
  13774     atlas->tex_height = 0;
  13775     atlas->custom.x = 0;
  13776     atlas->custom.y = 0;
  13777     atlas->custom.w = 0;
  13778     atlas->custom.h = 0;
  13779 }
  13780 NK_API void
  13781 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
  13782 {
  13783     NK_ASSERT(atlas);
  13784     NK_ASSERT(atlas->temporary.alloc);
  13785     NK_ASSERT(atlas->temporary.free);
  13786     NK_ASSERT(atlas->permanent.alloc);
  13787     NK_ASSERT(atlas->permanent.free);
  13788     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
  13789     if (atlas->config) {
  13790         struct nk_font_config *iter;
  13791         for (iter = atlas->config; iter; iter = iter->next) {
  13792             struct nk_font_config *i;
  13793             for (i = iter->n; i != iter; i = i->n) {
  13794                 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
  13795                 i->ttf_blob = 0;
  13796             }
  13797             atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
  13798             iter->ttf_blob = 0;
  13799         }
  13800     }
  13801 }
  13802 NK_API void
  13803 nk_font_atlas_clear(struct nk_font_atlas *atlas)
  13804 {
  13805     NK_ASSERT(atlas);
  13806     NK_ASSERT(atlas->temporary.alloc);
  13807     NK_ASSERT(atlas->temporary.free);
  13808     NK_ASSERT(atlas->permanent.alloc);
  13809     NK_ASSERT(atlas->permanent.free);
  13810     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
  13811 
  13812     if (atlas->config) {
  13813         struct nk_font_config *iter, *next;
  13814         for (iter = atlas->config; iter; iter = next) {
  13815             struct nk_font_config *i, *n;
  13816             for (i = iter->n; i != iter; i = n) {
  13817                 n = i->n;
  13818                 if (i->ttf_blob)
  13819                     atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
  13820                 atlas->permanent.free(atlas->permanent.userdata, i);
  13821             }
  13822             next = iter->next;
  13823             if (i->ttf_blob)
  13824                 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
  13825             atlas->permanent.free(atlas->permanent.userdata, iter);
  13826         }
  13827         atlas->config = 0;
  13828     }
  13829     if (atlas->fonts) {
  13830         struct nk_font *iter, *next;
  13831         for (iter = atlas->fonts; iter; iter = next) {
  13832             next = iter->next;
  13833             atlas->permanent.free(atlas->permanent.userdata, iter);
  13834         }
  13835         atlas->fonts = 0;
  13836     }
  13837     if (atlas->glyphs)
  13838         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
  13839     nk_zero_struct(*atlas);
  13840 }
  13841 #endif
  13842 
  13843 
  13844 
  13845 
  13846 
  13847 /* ===============================================================
  13848  *
  13849  *                          INPUT
  13850  *
  13851  * ===============================================================*/
  13852 NK_API void
  13853 nk_input_begin(struct nk_context *ctx)
  13854 {
  13855     int i;
  13856     struct nk_input *in;
  13857     NK_ASSERT(ctx);
  13858     if (!ctx) return;
  13859     in = &ctx->input;
  13860     for (i = 0; i < NK_BUTTON_MAX; ++i)
  13861         in->mouse.buttons[i].clicked = 0;
  13862 
  13863     in->keyboard.text_len = 0;
  13864     in->mouse.scroll_delta = nk_vec2(0,0);
  13865     in->mouse.prev.x = in->mouse.pos.x;
  13866     in->mouse.prev.y = in->mouse.pos.y;
  13867     in->mouse.delta.x = 0;
  13868     in->mouse.delta.y = 0;
  13869     for (i = 0; i < NK_KEY_MAX; i++)
  13870         in->keyboard.keys[i].clicked = 0;
  13871 }
  13872 NK_API void
  13873 nk_input_end(struct nk_context *ctx)
  13874 {
  13875     struct nk_input *in;
  13876     NK_ASSERT(ctx);
  13877     if (!ctx) return;
  13878     in = &ctx->input;
  13879     if (in->mouse.grab)
  13880         in->mouse.grab = 0;
  13881     if (in->mouse.ungrab) {
  13882         in->mouse.grabbed = 0;
  13883         in->mouse.ungrab = 0;
  13884         in->mouse.grab = 0;
  13885     }
  13886 }
  13887 NK_API void
  13888 nk_input_motion(struct nk_context *ctx, int x, int y)
  13889 {
  13890     struct nk_input *in;
  13891     NK_ASSERT(ctx);
  13892     if (!ctx) return;
  13893     in = &ctx->input;
  13894     in->mouse.pos.x = (float)x;
  13895     in->mouse.pos.y = (float)y;
  13896     in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
  13897     in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
  13898 }
  13899 NK_API void
  13900 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
  13901 {
  13902     struct nk_input *in;
  13903     NK_ASSERT(ctx);
  13904     if (!ctx) return;
  13905     in = &ctx->input;
  13906     if (in->keyboard.keys[key].down != down)
  13907         in->keyboard.keys[key].clicked++;
  13908     in->keyboard.keys[key].down = down;
  13909 }
  13910 NK_API void
  13911 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
  13912 {
  13913     struct nk_mouse_button *btn;
  13914     struct nk_input *in;
  13915     NK_ASSERT(ctx);
  13916     if (!ctx) return;
  13917     in = &ctx->input;
  13918     if (in->mouse.buttons[id].down == down) return;
  13919 
  13920     btn = &in->mouse.buttons[id];
  13921     btn->clicked_pos.x = (float)x;
  13922     btn->clicked_pos.y = (float)y;
  13923     btn->down = down;
  13924     btn->clicked++;
  13925 }
  13926 NK_API void
  13927 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
  13928 {
  13929     NK_ASSERT(ctx);
  13930     if (!ctx) return;
  13931     ctx->input.mouse.scroll_delta.x += val.x;
  13932     ctx->input.mouse.scroll_delta.y += val.y;
  13933 }
  13934 NK_API void
  13935 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
  13936 {
  13937     int len = 0;
  13938     nk_rune unicode;
  13939     struct nk_input *in;
  13940 
  13941     NK_ASSERT(ctx);
  13942     if (!ctx) return;
  13943     in = &ctx->input;
  13944 
  13945     len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
  13946     if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
  13947         nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
  13948             NK_INPUT_MAX - in->keyboard.text_len);
  13949         in->keyboard.text_len += len;
  13950     }
  13951 }
  13952 NK_API void
  13953 nk_input_char(struct nk_context *ctx, char c)
  13954 {
  13955     nk_glyph glyph;
  13956     NK_ASSERT(ctx);
  13957     if (!ctx) return;
  13958     glyph[0] = c;
  13959     nk_input_glyph(ctx, glyph);
  13960 }
  13961 NK_API void
  13962 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
  13963 {
  13964     nk_glyph rune;
  13965     NK_ASSERT(ctx);
  13966     if (!ctx) return;
  13967     nk_utf_encode(unicode, rune, NK_UTF_SIZE);
  13968     nk_input_glyph(ctx, rune);
  13969 }
  13970 NK_API int
  13971 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
  13972 {
  13973     const struct nk_mouse_button *btn;
  13974     if (!i) return nk_false;
  13975     btn = &i->mouse.buttons[id];
  13976     return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
  13977 }
  13978 NK_API int
  13979 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
  13980     struct nk_rect b)
  13981 {
  13982     const struct nk_mouse_button *btn;
  13983     if (!i) return nk_false;
  13984     btn = &i->mouse.buttons[id];
  13985     if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
  13986         return nk_false;
  13987     return nk_true;
  13988 }
  13989 NK_API int
  13990 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
  13991     struct nk_rect b, int down)
  13992 {
  13993     const struct nk_mouse_button *btn;
  13994     if (!i) return nk_false;
  13995     btn = &i->mouse.buttons[id];
  13996     return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
  13997 }
  13998 NK_API int
  13999 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
  14000     struct nk_rect b)
  14001 {
  14002     const struct nk_mouse_button *btn;
  14003     if (!i) return nk_false;
  14004     btn = &i->mouse.buttons[id];
  14005     return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
  14006             btn->clicked) ? nk_true : nk_false;
  14007 }
  14008 NK_API int
  14009 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
  14010     struct nk_rect b, int down)
  14011 {
  14012     const struct nk_mouse_button *btn;
  14013     if (!i) return nk_false;
  14014     btn = &i->mouse.buttons[id];
  14015     return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
  14016             btn->clicked) ? nk_true : nk_false;
  14017 }
  14018 NK_API int
  14019 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
  14020 {
  14021     int i, down = 0;
  14022     for (i = 0; i < NK_BUTTON_MAX; ++i)
  14023         down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
  14024     return down;
  14025 }
  14026 NK_API int
  14027 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
  14028 {
  14029     if (!i) return nk_false;
  14030     return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
  14031 }
  14032 NK_API int
  14033 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
  14034 {
  14035     if (!i) return nk_false;
  14036     return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
  14037 }
  14038 NK_API int
  14039 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
  14040 {
  14041     if (!i) return nk_false;
  14042     if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
  14043     return nk_input_is_mouse_click_in_rect(i, id, rect);
  14044 }
  14045 NK_API int
  14046 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
  14047 {
  14048     if (!i) return nk_false;
  14049     return i->mouse.buttons[id].down;
  14050 }
  14051 NK_API int
  14052 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
  14053 {
  14054     const struct nk_mouse_button *b;
  14055     if (!i) return nk_false;
  14056     b = &i->mouse.buttons[id];
  14057     if (b->down && b->clicked)
  14058         return nk_true;
  14059     return nk_false;
  14060 }
  14061 NK_API int
  14062 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
  14063 {
  14064     if (!i) return nk_false;
  14065     return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
  14066 }
  14067 NK_API int
  14068 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
  14069 {
  14070     const struct nk_key *k;
  14071     if (!i) return nk_false;
  14072     k = &i->keyboard.keys[key];
  14073     if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
  14074         return nk_true;
  14075     return nk_false;
  14076 }
  14077 NK_API int
  14078 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
  14079 {
  14080     const struct nk_key *k;
  14081     if (!i) return nk_false;
  14082     k = &i->keyboard.keys[key];
  14083     if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
  14084         return nk_true;
  14085     return nk_false;
  14086 }
  14087 NK_API int
  14088 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
  14089 {
  14090     const struct nk_key *k;
  14091     if (!i) return nk_false;
  14092     k = &i->keyboard.keys[key];
  14093     if (k->down) return nk_true;
  14094     return nk_false;
  14095 }
  14096 
  14097 
  14098 
  14099 
  14100 
  14101 /* ===============================================================
  14102  *
  14103  *                              STYLE
  14104  *
  14105  * ===============================================================*/
  14106 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
  14107 #define NK_COLOR_MAP(NK_COLOR)\
  14108     NK_COLOR(NK_COLOR_TEXT,                     175,175,175,255) \
  14109     NK_COLOR(NK_COLOR_WINDOW,                   45, 45, 45, 255) \
  14110     NK_COLOR(NK_COLOR_HEADER,                   40, 40, 40, 255) \
  14111     NK_COLOR(NK_COLOR_BORDER,                   65, 65, 65, 255) \
  14112     NK_COLOR(NK_COLOR_BUTTON,                   50, 50, 50, 255) \
  14113     NK_COLOR(NK_COLOR_BUTTON_HOVER,             40, 40, 40, 255) \
  14114     NK_COLOR(NK_COLOR_BUTTON_ACTIVE,            35, 35, 35, 255) \
  14115     NK_COLOR(NK_COLOR_TOGGLE,                   100,100,100,255) \
  14116     NK_COLOR(NK_COLOR_TOGGLE_HOVER,             120,120,120,255) \
  14117     NK_COLOR(NK_COLOR_TOGGLE_CURSOR,            45, 45, 45, 255) \
  14118     NK_COLOR(NK_COLOR_SELECT,                   45, 45, 45, 255) \
  14119     NK_COLOR(NK_COLOR_SELECT_ACTIVE,            35, 35, 35,255) \
  14120     NK_COLOR(NK_COLOR_SLIDER,                   38, 38, 38, 255) \
  14121     NK_COLOR(NK_COLOR_SLIDER_CURSOR,            100,100,100,255) \
  14122     NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER,      120,120,120,255) \
  14123     NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE,     150,150,150,255) \
  14124     NK_COLOR(NK_COLOR_PROPERTY,                 38, 38, 38, 255) \
  14125     NK_COLOR(NK_COLOR_EDIT,                     38, 38, 38, 255)  \
  14126     NK_COLOR(NK_COLOR_EDIT_CURSOR,              175,175,175,255) \
  14127     NK_COLOR(NK_COLOR_COMBO,                    45, 45, 45, 255) \
  14128     NK_COLOR(NK_COLOR_CHART,                    120,120,120,255) \
  14129     NK_COLOR(NK_COLOR_CHART_COLOR,              45, 45, 45, 255) \
  14130     NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,    255, 0,  0, 255) \
  14131     NK_COLOR(NK_COLOR_SCROLLBAR,                40, 40, 40, 255) \
  14132     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR,         100,100,100,255) \
  14133     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,   120,120,120,255) \
  14134     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,  150,150,150,255) \
  14135     NK_COLOR(NK_COLOR_TAB_HEADER,               40, 40, 40,255)
  14136 
  14137 NK_GLOBAL const struct nk_color
  14138 nk_default_color_style[NK_COLOR_COUNT] = {
  14139 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
  14140     NK_COLOR_MAP(NK_COLOR)
  14141 #undef NK_COLOR
  14142 };
  14143 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
  14144 #define NK_COLOR(a,b,c,d,e) #a,
  14145     NK_COLOR_MAP(NK_COLOR)
  14146 #undef NK_COLOR
  14147 };
  14148 
  14149 NK_API const char*
  14150 nk_style_get_color_by_name(enum nk_style_colors c)
  14151 {
  14152     return nk_color_names[c];
  14153 }
  14154 NK_API struct nk_style_item
  14155 nk_style_item_image(struct nk_image img)
  14156 {
  14157     struct nk_style_item i;
  14158     i.type = NK_STYLE_ITEM_IMAGE;
  14159     i.data.image = img;
  14160     return i;
  14161 }
  14162 NK_API struct nk_style_item
  14163 nk_style_item_color(struct nk_color col)
  14164 {
  14165     struct nk_style_item i;
  14166     i.type = NK_STYLE_ITEM_COLOR;
  14167     i.data.color = col;
  14168     return i;
  14169 }
  14170 NK_API struct nk_style_item
  14171 nk_style_item_hide(void)
  14172 {
  14173     struct nk_style_item i;
  14174     i.type = NK_STYLE_ITEM_COLOR;
  14175     i.data.color = nk_rgba(0,0,0,0);
  14176     return i;
  14177 }
  14178 NK_API void
  14179 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
  14180 {
  14181     struct nk_style *style;
  14182     struct nk_style_text *text;
  14183     struct nk_style_button *button;
  14184     struct nk_style_toggle *toggle;
  14185     struct nk_style_selectable *select;
  14186     struct nk_style_slider *slider;
  14187     struct nk_style_progress *prog;
  14188     struct nk_style_scrollbar *scroll;
  14189     struct nk_style_edit *edit;
  14190     struct nk_style_property *property;
  14191     struct nk_style_combo *combo;
  14192     struct nk_style_chart *chart;
  14193     struct nk_style_tab *tab;
  14194     struct nk_style_window *win;
  14195 
  14196     NK_ASSERT(ctx);
  14197     if (!ctx) return;
  14198     style = &ctx->style;
  14199     table = (!table) ? nk_default_color_style: table;
  14200 
  14201     /* default text */
  14202     text = &style->text;
  14203     text->color = table[NK_COLOR_TEXT];
  14204     text->padding = nk_vec2(0,0);
  14205 
  14206     /* default button */
  14207     button = &style->button;
  14208     nk_zero_struct(*button);
  14209     button->normal          = nk_style_item_color(table[NK_COLOR_BUTTON]);
  14210     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
  14211     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
  14212     button->border_color    = table[NK_COLOR_BORDER];
  14213     button->text_background = table[NK_COLOR_BUTTON];
  14214     button->text_normal     = table[NK_COLOR_TEXT];
  14215     button->text_hover      = table[NK_COLOR_TEXT];
  14216     button->text_active     = table[NK_COLOR_TEXT];
  14217     button->padding         = nk_vec2(2.0f,2.0f);
  14218     button->image_padding   = nk_vec2(0.0f,0.0f);
  14219     button->touch_padding   = nk_vec2(0.0f, 0.0f);
  14220     button->userdata        = nk_handle_ptr(0);
  14221     button->text_alignment  = NK_TEXT_CENTERED;
  14222     button->border          = 1.0f;
  14223     button->rounding        = 4.0f;
  14224     button->draw_begin      = 0;
  14225     button->draw_end        = 0;
  14226 
  14227     /* contextual button */
  14228     button = &style->contextual_button;
  14229     nk_zero_struct(*button);
  14230     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  14231     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
  14232     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
  14233     button->border_color    = table[NK_COLOR_WINDOW];
  14234     button->text_background = table[NK_COLOR_WINDOW];
  14235     button->text_normal     = table[NK_COLOR_TEXT];
  14236     button->text_hover      = table[NK_COLOR_TEXT];
  14237     button->text_active     = table[NK_COLOR_TEXT];
  14238     button->padding         = nk_vec2(2.0f,2.0f);
  14239     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14240     button->userdata        = nk_handle_ptr(0);
  14241     button->text_alignment  = NK_TEXT_CENTERED;
  14242     button->border          = 0.0f;
  14243     button->rounding        = 0.0f;
  14244     button->draw_begin      = 0;
  14245     button->draw_end        = 0;
  14246 
  14247     /* menu button */
  14248     button = &style->menu_button;
  14249     nk_zero_struct(*button);
  14250     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  14251     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
  14252     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  14253     button->border_color    = table[NK_COLOR_WINDOW];
  14254     button->text_background = table[NK_COLOR_WINDOW];
  14255     button->text_normal     = table[NK_COLOR_TEXT];
  14256     button->text_hover      = table[NK_COLOR_TEXT];
  14257     button->text_active     = table[NK_COLOR_TEXT];
  14258     button->padding         = nk_vec2(2.0f,2.0f);
  14259     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14260     button->userdata        = nk_handle_ptr(0);
  14261     button->text_alignment  = NK_TEXT_CENTERED;
  14262     button->border          = 0.0f;
  14263     button->rounding        = 1.0f;
  14264     button->draw_begin      = 0;
  14265     button->draw_end        = 0;
  14266 
  14267     /* checkbox toggle */
  14268     toggle = &style->checkbox;
  14269     nk_zero_struct(*toggle);
  14270     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
  14271     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
  14272     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
  14273     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
  14274     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
  14275     toggle->userdata        = nk_handle_ptr(0);
  14276     toggle->text_background = table[NK_COLOR_WINDOW];
  14277     toggle->text_normal     = table[NK_COLOR_TEXT];
  14278     toggle->text_hover      = table[NK_COLOR_TEXT];
  14279     toggle->text_active     = table[NK_COLOR_TEXT];
  14280     toggle->padding         = nk_vec2(2.0f, 2.0f);
  14281     toggle->touch_padding   = nk_vec2(0,0);
  14282     toggle->border_color    = nk_rgba(0,0,0,0);
  14283     toggle->border          = 0.0f;
  14284     toggle->spacing         = 4;
  14285 
  14286     /* option toggle */
  14287     toggle = &style->option;
  14288     nk_zero_struct(*toggle);
  14289     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
  14290     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
  14291     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
  14292     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
  14293     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
  14294     toggle->userdata        = nk_handle_ptr(0);
  14295     toggle->text_background = table[NK_COLOR_WINDOW];
  14296     toggle->text_normal     = table[NK_COLOR_TEXT];
  14297     toggle->text_hover      = table[NK_COLOR_TEXT];
  14298     toggle->text_active     = table[NK_COLOR_TEXT];
  14299     toggle->padding         = nk_vec2(3.0f, 3.0f);
  14300     toggle->touch_padding   = nk_vec2(0,0);
  14301     toggle->border_color    = nk_rgba(0,0,0,0);
  14302     toggle->border          = 0.0f;
  14303     toggle->spacing         = 4;
  14304 
  14305     /* selectable */
  14306     select = &style->selectable;
  14307     nk_zero_struct(*select);
  14308     select->normal          = nk_style_item_color(table[NK_COLOR_SELECT]);
  14309     select->hover           = nk_style_item_color(table[NK_COLOR_SELECT]);
  14310     select->pressed         = nk_style_item_color(table[NK_COLOR_SELECT]);
  14311     select->normal_active   = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
  14312     select->hover_active    = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
  14313     select->pressed_active  = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
  14314     select->text_normal     = table[NK_COLOR_TEXT];
  14315     select->text_hover      = table[NK_COLOR_TEXT];
  14316     select->text_pressed    = table[NK_COLOR_TEXT];
  14317     select->text_normal_active  = table[NK_COLOR_TEXT];
  14318     select->text_hover_active   = table[NK_COLOR_TEXT];
  14319     select->text_pressed_active = table[NK_COLOR_TEXT];
  14320     select->padding         = nk_vec2(2.0f,2.0f);
  14321     select->image_padding   = nk_vec2(2.0f,2.0f);
  14322     select->touch_padding   = nk_vec2(0,0);
  14323     select->userdata        = nk_handle_ptr(0);
  14324     select->rounding        = 0.0f;
  14325     select->draw_begin      = 0;
  14326     select->draw_end        = 0;
  14327 
  14328     /* slider */
  14329     slider = &style->slider;
  14330     nk_zero_struct(*slider);
  14331     slider->normal          = nk_style_item_hide();
  14332     slider->hover           = nk_style_item_hide();
  14333     slider->active          = nk_style_item_hide();
  14334     slider->bar_normal      = table[NK_COLOR_SLIDER];
  14335     slider->bar_hover       = table[NK_COLOR_SLIDER];
  14336     slider->bar_active      = table[NK_COLOR_SLIDER];
  14337     slider->bar_filled      = table[NK_COLOR_SLIDER_CURSOR];
  14338     slider->cursor_normal   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
  14339     slider->cursor_hover    = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
  14340     slider->cursor_active   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
  14341     slider->inc_symbol      = NK_SYMBOL_TRIANGLE_RIGHT;
  14342     slider->dec_symbol      = NK_SYMBOL_TRIANGLE_LEFT;
  14343     slider->cursor_size     = nk_vec2(16,16);
  14344     slider->padding         = nk_vec2(2,2);
  14345     slider->spacing         = nk_vec2(2,2);
  14346     slider->userdata        = nk_handle_ptr(0);
  14347     slider->show_buttons    = nk_false;
  14348     slider->bar_height      = 8;
  14349     slider->rounding        = 0;
  14350     slider->draw_begin      = 0;
  14351     slider->draw_end        = 0;
  14352 
  14353     /* slider buttons */
  14354     button = &style->slider.inc_button;
  14355     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
  14356     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
  14357     button->active          = nk_style_item_color(nk_rgb(44,44,44));
  14358     button->border_color    = nk_rgb(65,65,65);
  14359     button->text_background = nk_rgb(40,40,40);
  14360     button->text_normal     = nk_rgb(175,175,175);
  14361     button->text_hover      = nk_rgb(175,175,175);
  14362     button->text_active     = nk_rgb(175,175,175);
  14363     button->padding         = nk_vec2(8.0f,8.0f);
  14364     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14365     button->userdata        = nk_handle_ptr(0);
  14366     button->text_alignment  = NK_TEXT_CENTERED;
  14367     button->border          = 1.0f;
  14368     button->rounding        = 0.0f;
  14369     button->draw_begin      = 0;
  14370     button->draw_end        = 0;
  14371     style->slider.dec_button = style->slider.inc_button;
  14372 
  14373     /* progressbar */
  14374     prog = &style->progress;
  14375     nk_zero_struct(*prog);
  14376     prog->normal            = nk_style_item_color(table[NK_COLOR_SLIDER]);
  14377     prog->hover             = nk_style_item_color(table[NK_COLOR_SLIDER]);
  14378     prog->active            = nk_style_item_color(table[NK_COLOR_SLIDER]);
  14379     prog->cursor_normal     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
  14380     prog->cursor_hover      = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
  14381     prog->cursor_active     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
  14382     prog->border_color      = nk_rgba(0,0,0,0);
  14383     prog->cursor_border_color = nk_rgba(0,0,0,0);
  14384     prog->userdata          = nk_handle_ptr(0);
  14385     prog->padding           = nk_vec2(4,4);
  14386     prog->rounding          = 0;
  14387     prog->border            = 0;
  14388     prog->cursor_rounding   = 0;
  14389     prog->cursor_border     = 0;
  14390     prog->draw_begin        = 0;
  14391     prog->draw_end          = 0;
  14392 
  14393     /* scrollbars */
  14394     scroll = &style->scrollh;
  14395     nk_zero_struct(*scroll);
  14396     scroll->normal          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
  14397     scroll->hover           = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
  14398     scroll->active          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
  14399     scroll->cursor_normal   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]);
  14400     scroll->cursor_hover    = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]);
  14401     scroll->cursor_active   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]);
  14402     scroll->dec_symbol      = NK_SYMBOL_CIRCLE_SOLID;
  14403     scroll->inc_symbol      = NK_SYMBOL_CIRCLE_SOLID;
  14404     scroll->userdata        = nk_handle_ptr(0);
  14405     scroll->border_color    = table[NK_COLOR_SCROLLBAR];
  14406     scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
  14407     scroll->padding         = nk_vec2(0,0);
  14408     scroll->show_buttons    = nk_false;
  14409     scroll->border          = 0;
  14410     scroll->rounding        = 0;
  14411     scroll->border_cursor   = 0;
  14412     scroll->rounding_cursor = 0;
  14413     scroll->draw_begin      = 0;
  14414     scroll->draw_end        = 0;
  14415     style->scrollv = style->scrollh;
  14416 
  14417     /* scrollbars buttons */
  14418     button = &style->scrollh.inc_button;
  14419     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
  14420     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
  14421     button->active          = nk_style_item_color(nk_rgb(44,44,44));
  14422     button->border_color    = nk_rgb(65,65,65);
  14423     button->text_background = nk_rgb(40,40,40);
  14424     button->text_normal     = nk_rgb(175,175,175);
  14425     button->text_hover      = nk_rgb(175,175,175);
  14426     button->text_active     = nk_rgb(175,175,175);
  14427     button->padding         = nk_vec2(4.0f,4.0f);
  14428     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14429     button->userdata        = nk_handle_ptr(0);
  14430     button->text_alignment  = NK_TEXT_CENTERED;
  14431     button->border          = 1.0f;
  14432     button->rounding        = 0.0f;
  14433     button->draw_begin      = 0;
  14434     button->draw_end        = 0;
  14435     style->scrollh.dec_button = style->scrollh.inc_button;
  14436     style->scrollv.inc_button = style->scrollh.inc_button;
  14437     style->scrollv.dec_button = style->scrollh.inc_button;
  14438 
  14439     /* edit */
  14440     edit = &style->edit;
  14441     nk_zero_struct(*edit);
  14442     edit->normal            = nk_style_item_color(table[NK_COLOR_EDIT]);
  14443     edit->hover             = nk_style_item_color(table[NK_COLOR_EDIT]);
  14444     edit->active            = nk_style_item_color(table[NK_COLOR_EDIT]);
  14445     edit->cursor_normal     = table[NK_COLOR_TEXT];
  14446     edit->cursor_hover      = table[NK_COLOR_TEXT];
  14447     edit->cursor_text_normal= table[NK_COLOR_EDIT];
  14448     edit->cursor_text_hover = table[NK_COLOR_EDIT];
  14449     edit->border_color      = table[NK_COLOR_BORDER];
  14450     edit->text_normal       = table[NK_COLOR_TEXT];
  14451     edit->text_hover        = table[NK_COLOR_TEXT];
  14452     edit->text_active       = table[NK_COLOR_TEXT];
  14453     edit->selected_normal   = table[NK_COLOR_TEXT];
  14454     edit->selected_hover    = table[NK_COLOR_TEXT];
  14455     edit->selected_text_normal  = table[NK_COLOR_EDIT];
  14456     edit->selected_text_hover   = table[NK_COLOR_EDIT];
  14457     edit->scrollbar_size    = nk_vec2(10,10);
  14458     edit->scrollbar         = style->scrollv;
  14459     edit->padding           = nk_vec2(4,4);
  14460     edit->row_padding       = 2;
  14461     edit->cursor_size       = 4;
  14462     edit->border            = 1;
  14463     edit->rounding          = 0;
  14464 
  14465     /* property */
  14466     property = &style->property;
  14467     nk_zero_struct(*property);
  14468     property->normal        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14469     property->hover         = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14470     property->active        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14471     property->border_color  = table[NK_COLOR_BORDER];
  14472     property->label_normal  = table[NK_COLOR_TEXT];
  14473     property->label_hover   = table[NK_COLOR_TEXT];
  14474     property->label_active  = table[NK_COLOR_TEXT];
  14475     property->sym_left      = NK_SYMBOL_TRIANGLE_LEFT;
  14476     property->sym_right     = NK_SYMBOL_TRIANGLE_RIGHT;
  14477     property->userdata      = nk_handle_ptr(0);
  14478     property->padding       = nk_vec2(4,4);
  14479     property->border        = 1;
  14480     property->rounding      = 10;
  14481     property->draw_begin    = 0;
  14482     property->draw_end      = 0;
  14483 
  14484     /* property buttons */
  14485     button = &style->property.dec_button;
  14486     nk_zero_struct(*button);
  14487     button->normal          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14488     button->hover           = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14489     button->active          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14490     button->border_color    = nk_rgba(0,0,0,0);
  14491     button->text_background = table[NK_COLOR_PROPERTY];
  14492     button->text_normal     = table[NK_COLOR_TEXT];
  14493     button->text_hover      = table[NK_COLOR_TEXT];
  14494     button->text_active     = table[NK_COLOR_TEXT];
  14495     button->padding         = nk_vec2(0.0f,0.0f);
  14496     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14497     button->userdata        = nk_handle_ptr(0);
  14498     button->text_alignment  = NK_TEXT_CENTERED;
  14499     button->border          = 0.0f;
  14500     button->rounding        = 0.0f;
  14501     button->draw_begin      = 0;
  14502     button->draw_end        = 0;
  14503     style->property.inc_button = style->property.dec_button;
  14504 
  14505     /* property edit */
  14506     edit = &style->property.edit;
  14507     nk_zero_struct(*edit);
  14508     edit->normal            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14509     edit->hover             = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14510     edit->active            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
  14511     edit->border_color      = nk_rgba(0,0,0,0);
  14512     edit->cursor_normal     = table[NK_COLOR_TEXT];
  14513     edit->cursor_hover      = table[NK_COLOR_TEXT];
  14514     edit->cursor_text_normal= table[NK_COLOR_EDIT];
  14515     edit->cursor_text_hover = table[NK_COLOR_EDIT];
  14516     edit->text_normal       = table[NK_COLOR_TEXT];
  14517     edit->text_hover        = table[NK_COLOR_TEXT];
  14518     edit->text_active       = table[NK_COLOR_TEXT];
  14519     edit->selected_normal   = table[NK_COLOR_TEXT];
  14520     edit->selected_hover    = table[NK_COLOR_TEXT];
  14521     edit->selected_text_normal  = table[NK_COLOR_EDIT];
  14522     edit->selected_text_hover   = table[NK_COLOR_EDIT];
  14523     edit->padding           = nk_vec2(0,0);
  14524     edit->cursor_size       = 8;
  14525     edit->border            = 0;
  14526     edit->rounding          = 0;
  14527 
  14528     /* chart */
  14529     chart = &style->chart;
  14530     nk_zero_struct(*chart);
  14531     chart->background       = nk_style_item_color(table[NK_COLOR_CHART]);
  14532     chart->border_color     = table[NK_COLOR_BORDER];
  14533     chart->selected_color   = table[NK_COLOR_CHART_COLOR_HIGHLIGHT];
  14534     chart->color            = table[NK_COLOR_CHART_COLOR];
  14535     chart->padding          = nk_vec2(4,4);
  14536     chart->border           = 0;
  14537     chart->rounding         = 0;
  14538 
  14539     /* combo */
  14540     combo = &style->combo;
  14541     combo->normal           = nk_style_item_color(table[NK_COLOR_COMBO]);
  14542     combo->hover            = nk_style_item_color(table[NK_COLOR_COMBO]);
  14543     combo->active           = nk_style_item_color(table[NK_COLOR_COMBO]);
  14544     combo->border_color     = table[NK_COLOR_BORDER];
  14545     combo->label_normal     = table[NK_COLOR_TEXT];
  14546     combo->label_hover      = table[NK_COLOR_TEXT];
  14547     combo->label_active     = table[NK_COLOR_TEXT];
  14548     combo->sym_normal       = NK_SYMBOL_TRIANGLE_DOWN;
  14549     combo->sym_hover        = NK_SYMBOL_TRIANGLE_DOWN;
  14550     combo->sym_active       = NK_SYMBOL_TRIANGLE_DOWN;
  14551     combo->content_padding  = nk_vec2(4,4);
  14552     combo->button_padding   = nk_vec2(0,4);
  14553     combo->spacing          = nk_vec2(4,0);
  14554     combo->border           = 1;
  14555     combo->rounding         = 0;
  14556 
  14557     /* combo button */
  14558     button = &style->combo.button;
  14559     nk_zero_struct(*button);
  14560     button->normal          = nk_style_item_color(table[NK_COLOR_COMBO]);
  14561     button->hover           = nk_style_item_color(table[NK_COLOR_COMBO]);
  14562     button->active          = nk_style_item_color(table[NK_COLOR_COMBO]);
  14563     button->border_color    = nk_rgba(0,0,0,0);
  14564     button->text_background = table[NK_COLOR_COMBO];
  14565     button->text_normal     = table[NK_COLOR_TEXT];
  14566     button->text_hover      = table[NK_COLOR_TEXT];
  14567     button->text_active     = table[NK_COLOR_TEXT];
  14568     button->padding         = nk_vec2(2.0f,2.0f);
  14569     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14570     button->userdata        = nk_handle_ptr(0);
  14571     button->text_alignment  = NK_TEXT_CENTERED;
  14572     button->border          = 0.0f;
  14573     button->rounding        = 0.0f;
  14574     button->draw_begin      = 0;
  14575     button->draw_end        = 0;
  14576 
  14577     /* tab */
  14578     tab = &style->tab;
  14579     tab->background         = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
  14580     tab->border_color       = table[NK_COLOR_BORDER];
  14581     tab->text               = table[NK_COLOR_TEXT];
  14582     tab->sym_minimize       = NK_SYMBOL_TRIANGLE_RIGHT;
  14583     tab->sym_maximize       = NK_SYMBOL_TRIANGLE_DOWN;
  14584     tab->padding            = nk_vec2(4,4);
  14585     tab->spacing            = nk_vec2(4,4);
  14586     tab->indent             = 10.0f;
  14587     tab->border             = 1;
  14588     tab->rounding           = 0;
  14589 
  14590     /* tab button */
  14591     button = &style->tab.tab_minimize_button;
  14592     nk_zero_struct(*button);
  14593     button->normal          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
  14594     button->hover           = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
  14595     button->active          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
  14596     button->border_color    = nk_rgba(0,0,0,0);
  14597     button->text_background = table[NK_COLOR_TAB_HEADER];
  14598     button->text_normal     = table[NK_COLOR_TEXT];
  14599     button->text_hover      = table[NK_COLOR_TEXT];
  14600     button->text_active     = table[NK_COLOR_TEXT];
  14601     button->padding         = nk_vec2(2.0f,2.0f);
  14602     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14603     button->userdata        = nk_handle_ptr(0);
  14604     button->text_alignment  = NK_TEXT_CENTERED;
  14605     button->border          = 0.0f;
  14606     button->rounding        = 0.0f;
  14607     button->draw_begin      = 0;
  14608     button->draw_end        = 0;
  14609     style->tab.tab_maximize_button =*button;
  14610 
  14611     /* node button */
  14612     button = &style->tab.node_minimize_button;
  14613     nk_zero_struct(*button);
  14614     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  14615     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
  14616     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
  14617     button->border_color    = nk_rgba(0,0,0,0);
  14618     button->text_background = table[NK_COLOR_TAB_HEADER];
  14619     button->text_normal     = table[NK_COLOR_TEXT];
  14620     button->text_hover      = table[NK_COLOR_TEXT];
  14621     button->text_active     = table[NK_COLOR_TEXT];
  14622     button->padding         = nk_vec2(2.0f,2.0f);
  14623     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14624     button->userdata        = nk_handle_ptr(0);
  14625     button->text_alignment  = NK_TEXT_CENTERED;
  14626     button->border          = 0.0f;
  14627     button->rounding        = 0.0f;
  14628     button->draw_begin      = 0;
  14629     button->draw_end        = 0;
  14630     style->tab.node_maximize_button =*button;
  14631 
  14632     /* window header */
  14633     win = &style->window;
  14634     win->header.align = NK_HEADER_RIGHT;
  14635     win->header.close_symbol = NK_SYMBOL_X;
  14636     win->header.minimize_symbol = NK_SYMBOL_MINUS;
  14637     win->header.maximize_symbol = NK_SYMBOL_PLUS;
  14638     win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]);
  14639     win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]);
  14640     win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]);
  14641     win->header.label_normal = table[NK_COLOR_TEXT];
  14642     win->header.label_hover = table[NK_COLOR_TEXT];
  14643     win->header.label_active = table[NK_COLOR_TEXT];
  14644     win->header.label_padding = nk_vec2(4,4);
  14645     win->header.padding = nk_vec2(4,4);
  14646     win->header.spacing = nk_vec2(0,0);
  14647 
  14648     /* window header close button */
  14649     button = &style->window.header.close_button;
  14650     nk_zero_struct(*button);
  14651     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
  14652     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
  14653     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
  14654     button->border_color    = nk_rgba(0,0,0,0);
  14655     button->text_background = table[NK_COLOR_HEADER];
  14656     button->text_normal     = table[NK_COLOR_TEXT];
  14657     button->text_hover      = table[NK_COLOR_TEXT];
  14658     button->text_active     = table[NK_COLOR_TEXT];
  14659     button->padding         = nk_vec2(0.0f,0.0f);
  14660     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14661     button->userdata        = nk_handle_ptr(0);
  14662     button->text_alignment  = NK_TEXT_CENTERED;
  14663     button->border          = 0.0f;
  14664     button->rounding        = 0.0f;
  14665     button->draw_begin      = 0;
  14666     button->draw_end        = 0;
  14667 
  14668     /* window header minimize button */
  14669     button = &style->window.header.minimize_button;
  14670     nk_zero_struct(*button);
  14671     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
  14672     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
  14673     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
  14674     button->border_color    = nk_rgba(0,0,0,0);
  14675     button->text_background = table[NK_COLOR_HEADER];
  14676     button->text_normal     = table[NK_COLOR_TEXT];
  14677     button->text_hover      = table[NK_COLOR_TEXT];
  14678     button->text_active     = table[NK_COLOR_TEXT];
  14679     button->padding         = nk_vec2(0.0f,0.0f);
  14680     button->touch_padding   = nk_vec2(0.0f,0.0f);
  14681     button->userdata        = nk_handle_ptr(0);
  14682     button->text_alignment  = NK_TEXT_CENTERED;
  14683     button->border          = 0.0f;
  14684     button->rounding        = 0.0f;
  14685     button->draw_begin      = 0;
  14686     button->draw_end        = 0;
  14687 
  14688     /* window */
  14689     win->background = table[NK_COLOR_WINDOW];
  14690     win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]);
  14691     win->border_color = table[NK_COLOR_BORDER];
  14692     win->popup_border_color = table[NK_COLOR_BORDER];
  14693     win->combo_border_color = table[NK_COLOR_BORDER];
  14694     win->contextual_border_color = table[NK_COLOR_BORDER];
  14695     win->menu_border_color = table[NK_COLOR_BORDER];
  14696     win->group_border_color = table[NK_COLOR_BORDER];
  14697     win->tooltip_border_color = table[NK_COLOR_BORDER];
  14698     win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
  14699 
  14700     win->rounding = 0.0f;
  14701     win->spacing = nk_vec2(4,4);
  14702     win->scrollbar_size = nk_vec2(10,10);
  14703     win->min_size = nk_vec2(64,64);
  14704 
  14705     win->combo_border = 1.0f;
  14706     win->contextual_border = 1.0f;
  14707     win->menu_border = 1.0f;
  14708     win->group_border = 1.0f;
  14709     win->tooltip_border = 1.0f;
  14710     win->popup_border = 1.0f;
  14711     win->border = 2.0f;
  14712     win->min_row_height_padding = 8;
  14713 
  14714     win->padding = nk_vec2(4,4);
  14715     win->group_padding = nk_vec2(4,4);
  14716     win->popup_padding = nk_vec2(4,4);
  14717     win->combo_padding = nk_vec2(4,4);
  14718     win->contextual_padding = nk_vec2(4,4);
  14719     win->menu_padding = nk_vec2(4,4);
  14720     win->tooltip_padding = nk_vec2(4,4);
  14721 }
  14722 NK_API void
  14723 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
  14724 {
  14725     struct nk_style *style;
  14726     NK_ASSERT(ctx);
  14727 
  14728     if (!ctx) return;
  14729     style = &ctx->style;
  14730     style->font = font;
  14731     ctx->stacks.fonts.head = 0;
  14732     if (ctx->current)
  14733         nk_layout_reset_min_row_height(ctx);
  14734 }
  14735 NK_API int
  14736 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
  14737 {
  14738     struct nk_config_stack_user_font *font_stack;
  14739     struct nk_config_stack_user_font_element *element;
  14740 
  14741     NK_ASSERT(ctx);
  14742     if (!ctx) return 0;
  14743 
  14744     font_stack = &ctx->stacks.fonts;
  14745     NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
  14746     if (font_stack->head >= (int)NK_LEN(font_stack->elements))
  14747         return 0;
  14748 
  14749     element = &font_stack->elements[font_stack->head++];
  14750     element->address = &ctx->style.font;
  14751     element->old_value = ctx->style.font;
  14752     ctx->style.font = font;
  14753     return 1;
  14754 }
  14755 NK_API int
  14756 nk_style_pop_font(struct nk_context *ctx)
  14757 {
  14758     struct nk_config_stack_user_font *font_stack;
  14759     struct nk_config_stack_user_font_element *element;
  14760 
  14761     NK_ASSERT(ctx);
  14762     if (!ctx) return 0;
  14763 
  14764     font_stack = &ctx->stacks.fonts;
  14765     NK_ASSERT(font_stack->head > 0);
  14766     if (font_stack->head < 1)
  14767         return 0;
  14768 
  14769     element = &font_stack->elements[--font_stack->head];
  14770     *element->address = element->old_value;
  14771     return 1;
  14772 }
  14773 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
  14774 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
  14775 {\
  14776     struct nk_config_stack_##type * type_stack;\
  14777     struct nk_config_stack_##type##_element *element;\
  14778     NK_ASSERT(ctx);\
  14779     if (!ctx) return 0;\
  14780     type_stack = &ctx->stacks.stack;\
  14781     NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
  14782     if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
  14783         return 0;\
  14784     element = &type_stack->elements[type_stack->head++];\
  14785     element->address = address;\
  14786     element->old_value = *address;\
  14787     *address = value;\
  14788     return 1;\
  14789 }
  14790 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
  14791 nk_style_pop_##type(struct nk_context *ctx)\
  14792 {\
  14793     struct nk_config_stack_##type *type_stack;\
  14794     struct nk_config_stack_##type##_element *element;\
  14795     NK_ASSERT(ctx);\
  14796     if (!ctx) return 0;\
  14797     type_stack = &ctx->stacks.stack;\
  14798     NK_ASSERT(type_stack->head > 0);\
  14799     if (type_stack->head < 1)\
  14800         return 0;\
  14801     element = &type_stack->elements[--type_stack->head];\
  14802     *element->address = element->old_value;\
  14803     return 1;\
  14804 }
  14805 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
  14806 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
  14807 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
  14808 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
  14809 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
  14810 
  14811 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
  14812 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
  14813 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
  14814 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
  14815 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
  14816 
  14817 NK_API int
  14818 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
  14819 {
  14820     struct nk_style *style;
  14821     NK_ASSERT(ctx);
  14822     if (!ctx) return 0;
  14823     style = &ctx->style;
  14824     if (style->cursors[c]) {
  14825         style->cursor_active = style->cursors[c];
  14826         return 1;
  14827     }
  14828     return 0;
  14829 }
  14830 NK_API void
  14831 nk_style_show_cursor(struct nk_context *ctx)
  14832 {
  14833     ctx->style.cursor_visible = nk_true;
  14834 }
  14835 NK_API void
  14836 nk_style_hide_cursor(struct nk_context *ctx)
  14837 {
  14838     ctx->style.cursor_visible = nk_false;
  14839 }
  14840 NK_API void
  14841 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
  14842     const struct nk_cursor *c)
  14843 {
  14844     struct nk_style *style;
  14845     NK_ASSERT(ctx);
  14846     if (!ctx) return;
  14847     style = &ctx->style;
  14848     style->cursors[cursor] = c;
  14849 }
  14850 NK_API void
  14851 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors)
  14852 {
  14853     int i = 0;
  14854     struct nk_style *style;
  14855     NK_ASSERT(ctx);
  14856     if (!ctx) return;
  14857     style = &ctx->style;
  14858     for (i = 0; i < NK_CURSOR_COUNT; ++i)
  14859         style->cursors[i] = &cursors[i];
  14860     style->cursor_visible = nk_true;
  14861 }
  14862 
  14863 
  14864 
  14865 
  14866 
  14867 /* ==============================================================
  14868  *
  14869  *                          CONTEXT
  14870  *
  14871  * ===============================================================*/
  14872 NK_INTERN void
  14873 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
  14874 {
  14875     NK_ASSERT(ctx);
  14876     if (!ctx) return;
  14877     nk_zero_struct(*ctx);
  14878     nk_style_default(ctx);
  14879     ctx->seq = 1;
  14880     if (font) ctx->style.font = font;
  14881 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  14882     nk_draw_list_init(&ctx->draw_list);
  14883 #endif
  14884 }
  14885 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
  14886 NK_API int
  14887 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
  14888 {
  14889     struct nk_allocator alloc;
  14890     alloc.userdata.ptr = 0;
  14891     alloc.alloc = nk_malloc;
  14892     alloc.free = nk_mfree;
  14893     return nk_init(ctx, &alloc, font);
  14894 }
  14895 #endif
  14896 NK_API int
  14897 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
  14898     const struct nk_user_font *font)
  14899 {
  14900     NK_ASSERT(memory);
  14901     if (!memory) return 0;
  14902     nk_setup(ctx, font);
  14903     nk_buffer_init_fixed(&ctx->memory, memory, size);
  14904     ctx->use_pool = nk_false;
  14905     return 1;
  14906 }
  14907 NK_API int
  14908 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
  14909     struct nk_buffer *pool, const struct nk_user_font *font)
  14910 {
  14911     NK_ASSERT(cmds);
  14912     NK_ASSERT(pool);
  14913     if (!cmds || !pool) return 0;
  14914 
  14915     nk_setup(ctx, font);
  14916     ctx->memory = *cmds;
  14917     if (pool->type == NK_BUFFER_FIXED) {
  14918         /* take memory from buffer and alloc fixed pool */
  14919         nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
  14920     } else {
  14921         /* create dynamic pool from buffer allocator */
  14922         struct nk_allocator *alloc = &pool->pool;
  14923         nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
  14924     }
  14925     ctx->use_pool = nk_true;
  14926     return 1;
  14927 }
  14928 NK_API int
  14929 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
  14930     const struct nk_user_font *font)
  14931 {
  14932     NK_ASSERT(alloc);
  14933     if (!alloc) return 0;
  14934     nk_setup(ctx, font);
  14935     nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
  14936     nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
  14937     ctx->use_pool = nk_true;
  14938     return 1;
  14939 }
  14940 #ifdef NK_INCLUDE_COMMAND_USERDATA
  14941 NK_API void
  14942 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
  14943 {
  14944     if (!ctx) return;
  14945     ctx->userdata = handle;
  14946     if (ctx->current)
  14947         ctx->current->buffer.userdata = handle;
  14948 }
  14949 #endif
  14950 NK_API void
  14951 nk_free(struct nk_context *ctx)
  14952 {
  14953     NK_ASSERT(ctx);
  14954     if (!ctx) return;
  14955     nk_buffer_free(&ctx->memory);
  14956     if (ctx->use_pool)
  14957         nk_pool_free(&ctx->pool);
  14958 
  14959     nk_zero(&ctx->input, sizeof(ctx->input));
  14960     nk_zero(&ctx->style, sizeof(ctx->style));
  14961     nk_zero(&ctx->memory, sizeof(ctx->memory));
  14962 
  14963     ctx->seq = 0;
  14964     ctx->build = 0;
  14965     ctx->begin = 0;
  14966     ctx->end = 0;
  14967     ctx->active = 0;
  14968     ctx->current = 0;
  14969     ctx->freelist = 0;
  14970     ctx->count = 0;
  14971 }
  14972 NK_API void
  14973 nk_clear(struct nk_context *ctx)
  14974 {
  14975     struct nk_window *iter;
  14976     struct nk_window *next;
  14977     NK_ASSERT(ctx);
  14978 
  14979     if (!ctx) return;
  14980     if (ctx->use_pool)
  14981         nk_buffer_clear(&ctx->memory);
  14982     else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
  14983 
  14984     ctx->build = 0;
  14985     ctx->memory.calls = 0;
  14986     ctx->last_widget_state = 0;
  14987     ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
  14988     NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
  14989 
  14990     /* garbage collector */
  14991     iter = ctx->begin;
  14992     while (iter) {
  14993         /* make sure valid minimized windows do not get removed */
  14994         if ((iter->flags & NK_WINDOW_MINIMIZED) &&
  14995             !(iter->flags & NK_WINDOW_CLOSED) &&
  14996             iter->seq == ctx->seq) {
  14997             iter = iter->next;
  14998             continue;
  14999         }
  15000         /* remove hotness from hidden or closed windows*/
  15001         if (((iter->flags & NK_WINDOW_HIDDEN) ||
  15002             (iter->flags & NK_WINDOW_CLOSED)) &&
  15003             iter == ctx->active) {
  15004             ctx->active = iter->prev;
  15005             ctx->end = iter->prev;
  15006             if (!ctx->end)
  15007                 ctx->begin = 0;
  15008             if (ctx->active)
  15009                 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
  15010         }
  15011         /* free unused popup windows */
  15012         if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
  15013             nk_free_window(ctx, iter->popup.win);
  15014             iter->popup.win = 0;
  15015         }
  15016         /* remove unused window state tables */
  15017         {struct nk_table *n, *it = iter->tables;
  15018         while (it) {
  15019             n = it->next;
  15020             if (it->seq != ctx->seq) {
  15021                 nk_remove_table(iter, it);
  15022                 nk_zero(it, sizeof(union nk_page_data));
  15023                 nk_free_table(ctx, it);
  15024                 if (it == iter->tables)
  15025                     iter->tables = n;
  15026             } it = n;
  15027         }}
  15028         /* window itself is not used anymore so free */
  15029         if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
  15030             next = iter->next;
  15031             nk_remove_window(ctx, iter);
  15032             nk_free_window(ctx, iter);
  15033             iter = next;
  15034         } else iter = iter->next;
  15035     }
  15036     ctx->seq++;
  15037 }
  15038 NK_LIB void
  15039 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
  15040 {
  15041     NK_ASSERT(ctx);
  15042     NK_ASSERT(buffer);
  15043     if (!ctx || !buffer) return;
  15044     buffer->begin = ctx->memory.allocated;
  15045     buffer->end = buffer->begin;
  15046     buffer->last = buffer->begin;
  15047     buffer->clip = nk_null_rect;
  15048 }
  15049 NK_LIB void
  15050 nk_start(struct nk_context *ctx, struct nk_window *win)
  15051 {
  15052     NK_ASSERT(ctx);
  15053     NK_ASSERT(win);
  15054     nk_start_buffer(ctx, &win->buffer);
  15055 }
  15056 NK_LIB void
  15057 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
  15058 {
  15059     struct nk_popup_buffer *buf;
  15060     NK_ASSERT(ctx);
  15061     NK_ASSERT(win);
  15062     if (!ctx || !win) return;
  15063 
  15064     /* save buffer fill state for popup */
  15065     buf = &win->popup.buf;
  15066     buf->begin = win->buffer.end;
  15067     buf->end = win->buffer.end;
  15068     buf->parent = win->buffer.last;
  15069     buf->last = buf->begin;
  15070     buf->active = nk_true;
  15071 }
  15072 NK_LIB void
  15073 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
  15074 {
  15075     struct nk_popup_buffer *buf;
  15076     NK_ASSERT(ctx);
  15077     NK_ASSERT(win);
  15078     if (!ctx || !win) return;
  15079 
  15080     buf = &win->popup.buf;
  15081     buf->last = win->buffer.last;
  15082     buf->end = win->buffer.end;
  15083 }
  15084 NK_LIB void
  15085 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
  15086 {
  15087     NK_ASSERT(ctx);
  15088     NK_ASSERT(buffer);
  15089     if (!ctx || !buffer) return;
  15090     buffer->end = ctx->memory.allocated;
  15091 }
  15092 NK_LIB void
  15093 nk_finish(struct nk_context *ctx, struct nk_window *win)
  15094 {
  15095     struct nk_popup_buffer *buf;
  15096     struct nk_command *parent_last;
  15097     void *memory;
  15098 
  15099     NK_ASSERT(ctx);
  15100     NK_ASSERT(win);
  15101     if (!ctx || !win) return;
  15102     nk_finish_buffer(ctx, &win->buffer);
  15103     if (!win->popup.buf.active) return;
  15104 
  15105     buf = &win->popup.buf;
  15106     memory = ctx->memory.memory.ptr;
  15107     parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
  15108     parent_last->next = buf->end;
  15109 }
  15110 NK_LIB void
  15111 nk_build(struct nk_context *ctx)
  15112 {
  15113     struct nk_window *it = 0;
  15114     struct nk_command *cmd = 0;
  15115     nk_byte *buffer = 0;
  15116 
  15117     /* draw cursor overlay */
  15118     if (!ctx->style.cursor_active)
  15119         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
  15120     if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
  15121         struct nk_rect mouse_bounds;
  15122         const struct nk_cursor *cursor = ctx->style.cursor_active;
  15123         nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
  15124         nk_start_buffer(ctx, &ctx->overlay);
  15125 
  15126         mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
  15127         mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
  15128         mouse_bounds.w = cursor->size.x;
  15129         mouse_bounds.h = cursor->size.y;
  15130 
  15131         nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
  15132         nk_finish_buffer(ctx, &ctx->overlay);
  15133     }
  15134     /* build one big draw command list out of all window buffers */
  15135     it = ctx->begin;
  15136     buffer = (nk_byte*)ctx->memory.memory.ptr;
  15137     while (it != 0) {
  15138         struct nk_window *next = it->next;
  15139         if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
  15140             it->seq != ctx->seq)
  15141             goto cont;
  15142 
  15143         cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
  15144         while (next && ((next->buffer.last == next->buffer.begin) ||
  15145             (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
  15146             next = next->next; /* skip empty command buffers */
  15147 
  15148         if (next) cmd->next = next->buffer.begin;
  15149         cont: it = next;
  15150     }
  15151     /* append all popup draw commands into lists */
  15152     it = ctx->begin;
  15153     while (it != 0) {
  15154         struct nk_window *next = it->next;
  15155         struct nk_popup_buffer *buf;
  15156         if (!it->popup.buf.active)
  15157             goto skip;
  15158 
  15159         buf = &it->popup.buf;
  15160         cmd->next = buf->begin;
  15161         cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
  15162         buf->active = nk_false;
  15163         skip: it = next;
  15164     }
  15165     if (cmd) {
  15166         /* append overlay commands */
  15167         if (ctx->overlay.end != ctx->overlay.begin)
  15168             cmd->next = ctx->overlay.begin;
  15169         else cmd->next = ctx->memory.allocated;
  15170     }
  15171 }
  15172 NK_API const struct nk_command*
  15173 nk__begin(struct nk_context *ctx)
  15174 {
  15175     struct nk_window *iter;
  15176     nk_byte *buffer;
  15177     NK_ASSERT(ctx);
  15178     if (!ctx) return 0;
  15179     if (!ctx->count) return 0;
  15180 
  15181     buffer = (nk_byte*)ctx->memory.memory.ptr;
  15182     if (!ctx->build) {
  15183         nk_build(ctx);
  15184         ctx->build = nk_true;
  15185     }
  15186     iter = ctx->begin;
  15187     while (iter && ((iter->buffer.begin == iter->buffer.end) ||
  15188         (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
  15189         iter = iter->next;
  15190     if (!iter) return 0;
  15191     return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
  15192 }
  15193 
  15194 NK_API const struct nk_command*
  15195 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
  15196 {
  15197     nk_byte *buffer;
  15198     const struct nk_command *next;
  15199     NK_ASSERT(ctx);
  15200     if (!ctx || !cmd || !ctx->count) return 0;
  15201     if (cmd->next >= ctx->memory.allocated) return 0;
  15202     buffer = (nk_byte*)ctx->memory.memory.ptr;
  15203     next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
  15204     return next;
  15205 }
  15206 
  15207 
  15208 
  15209 
  15210 
  15211 
  15212 /* ===============================================================
  15213  *
  15214  *                              POOL
  15215  *
  15216  * ===============================================================*/
  15217 NK_LIB void
  15218 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
  15219     unsigned int capacity)
  15220 {
  15221     nk_zero(pool, sizeof(*pool));
  15222     pool->alloc = *alloc;
  15223     pool->capacity = capacity;
  15224     pool->type = NK_BUFFER_DYNAMIC;
  15225     pool->pages = 0;
  15226 }
  15227 NK_LIB void
  15228 nk_pool_free(struct nk_pool *pool)
  15229 {
  15230     struct nk_page *iter = pool->pages;
  15231     if (!pool) return;
  15232     if (pool->type == NK_BUFFER_FIXED) return;
  15233     while (iter) {
  15234         struct nk_page *next = iter->next;
  15235         pool->alloc.free(pool->alloc.userdata, iter);
  15236         iter = next;
  15237     }
  15238 }
  15239 NK_LIB void
  15240 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
  15241 {
  15242     nk_zero(pool, sizeof(*pool));
  15243     NK_ASSERT(size >= sizeof(struct nk_page));
  15244     if (size < sizeof(struct nk_page)) return;
  15245     pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
  15246     pool->pages = (struct nk_page*)memory;
  15247     pool->type = NK_BUFFER_FIXED;
  15248     pool->size = size;
  15249 }
  15250 NK_LIB struct nk_page_element*
  15251 nk_pool_alloc(struct nk_pool *pool)
  15252 {
  15253     if (!pool->pages || pool->pages->size >= pool->capacity) {
  15254         /* allocate new page */
  15255         struct nk_page *page;
  15256         if (pool->type == NK_BUFFER_FIXED) {
  15257             NK_ASSERT(pool->pages);
  15258             if (!pool->pages) return 0;
  15259             NK_ASSERT(pool->pages->size < pool->capacity);
  15260             return 0;
  15261         } else {
  15262             nk_size size = sizeof(struct nk_page);
  15263             size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
  15264             page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
  15265             page->next = pool->pages;
  15266             pool->pages = page;
  15267             page->size = 0;
  15268         }
  15269     } return &pool->pages->win[pool->pages->size++];
  15270 }
  15271 
  15272 
  15273 
  15274 
  15275 
  15276 /* ===============================================================
  15277  *
  15278  *                          PAGE ELEMENT
  15279  *
  15280  * ===============================================================*/
  15281 NK_LIB struct nk_page_element*
  15282 nk_create_page_element(struct nk_context *ctx)
  15283 {
  15284     struct nk_page_element *elem;
  15285     if (ctx->freelist) {
  15286         /* unlink page element from free list */
  15287         elem = ctx->freelist;
  15288         ctx->freelist = elem->next;
  15289     } else if (ctx->use_pool) {
  15290         /* allocate page element from memory pool */
  15291         elem = nk_pool_alloc(&ctx->pool);
  15292         NK_ASSERT(elem);
  15293         if (!elem) return 0;
  15294     } else {
  15295         /* allocate new page element from back of fixed size memory buffer */
  15296         NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
  15297         NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
  15298         elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
  15299         NK_ASSERT(elem);
  15300         if (!elem) return 0;
  15301     }
  15302     nk_zero_struct(*elem);
  15303     elem->next = 0;
  15304     elem->prev = 0;
  15305     return elem;
  15306 }
  15307 NK_LIB void
  15308 nk_link_page_element_into_freelist(struct nk_context *ctx,
  15309     struct nk_page_element *elem)
  15310 {
  15311     /* link table into freelist */
  15312     if (!ctx->freelist) {
  15313         ctx->freelist = elem;
  15314     } else {
  15315         elem->next = ctx->freelist;
  15316         ctx->freelist = elem;
  15317     }
  15318 }
  15319 NK_LIB void
  15320 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
  15321 {
  15322     /* we have a pool so just add to free list */
  15323     if (ctx->use_pool) {
  15324         nk_link_page_element_into_freelist(ctx, elem);
  15325         return;
  15326     }
  15327     /* if possible remove last element from back of fixed memory buffer */
  15328     {void *elem_end = (void*)(elem + 1);
  15329     void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
  15330     if (elem_end == buffer_end)
  15331         ctx->memory.size -= sizeof(struct nk_page_element);
  15332     else nk_link_page_element_into_freelist(ctx, elem);}
  15333 }
  15334 
  15335 
  15336 
  15337 
  15338 
  15339 /* ===============================================================
  15340  *
  15341  *                              TABLE
  15342  *
  15343  * ===============================================================*/
  15344 NK_LIB struct nk_table*
  15345 nk_create_table(struct nk_context *ctx)
  15346 {
  15347     struct nk_page_element *elem;
  15348     elem = nk_create_page_element(ctx);
  15349     if (!elem) return 0;
  15350     nk_zero_struct(*elem);
  15351     return &elem->data.tbl;
  15352 }
  15353 NK_LIB void
  15354 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
  15355 {
  15356     union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
  15357     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
  15358     nk_free_page_element(ctx, pe);
  15359 }
  15360 NK_LIB void
  15361 nk_push_table(struct nk_window *win, struct nk_table *tbl)
  15362 {
  15363     if (!win->tables) {
  15364         win->tables = tbl;
  15365         tbl->next = 0;
  15366         tbl->prev = 0;
  15367         tbl->size = 0;
  15368         win->table_count = 1;
  15369         return;
  15370     }
  15371     win->tables->prev = tbl;
  15372     tbl->next = win->tables;
  15373     tbl->prev = 0;
  15374     tbl->size = 0;
  15375     win->tables = tbl;
  15376     win->table_count++;
  15377 }
  15378 NK_LIB void
  15379 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
  15380 {
  15381     if (win->tables == tbl)
  15382         win->tables = tbl->next;
  15383     if (tbl->next)
  15384         tbl->next->prev = tbl->prev;
  15385     if (tbl->prev)
  15386         tbl->prev->next = tbl->next;
  15387     tbl->next = 0;
  15388     tbl->prev = 0;
  15389 }
  15390 NK_LIB nk_uint*
  15391 nk_add_value(struct nk_context *ctx, struct nk_window *win,
  15392             nk_hash name, nk_uint value)
  15393 {
  15394     NK_ASSERT(ctx);
  15395     NK_ASSERT(win);
  15396     if (!win || !ctx) return 0;
  15397     if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
  15398         struct nk_table *tbl = nk_create_table(ctx);
  15399         NK_ASSERT(tbl);
  15400         if (!tbl) return 0;
  15401         nk_push_table(win, tbl);
  15402     }
  15403     win->tables->seq = win->seq;
  15404     win->tables->keys[win->tables->size] = name;
  15405     win->tables->values[win->tables->size] = value;
  15406     return &win->tables->values[win->tables->size++];
  15407 }
  15408 NK_LIB nk_uint*
  15409 nk_find_value(struct nk_window *win, nk_hash name)
  15410 {
  15411     struct nk_table *iter = win->tables;
  15412     while (iter) {
  15413         unsigned int i = 0;
  15414         unsigned int size = iter->size;
  15415         for (i = 0; i < size; ++i) {
  15416             if (iter->keys[i] == name) {
  15417                 iter->seq = win->seq;
  15418                 return &iter->values[i];
  15419             }
  15420         } size = NK_VALUE_PAGE_CAPACITY;
  15421         iter = iter->next;
  15422     }
  15423     return 0;
  15424 }
  15425 
  15426 
  15427 
  15428 
  15429 
  15430 /* ===============================================================
  15431  *
  15432  *                              PANEL
  15433  *
  15434  * ===============================================================*/
  15435 NK_LIB void*
  15436 nk_create_panel(struct nk_context *ctx)
  15437 {
  15438     struct nk_page_element *elem;
  15439     elem = nk_create_page_element(ctx);
  15440     if (!elem) return 0;
  15441     nk_zero_struct(*elem);
  15442     return &elem->data.pan;
  15443 }
  15444 NK_LIB void
  15445 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
  15446 {
  15447     union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
  15448     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
  15449     nk_free_page_element(ctx, pe);
  15450 }
  15451 NK_LIB int
  15452 nk_panel_has_header(nk_flags flags, const char *title)
  15453 {
  15454     int active = 0;
  15455     active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
  15456     active = active || (flags & NK_WINDOW_TITLE);
  15457     active = active && !(flags & NK_WINDOW_HIDDEN) && title;
  15458     return active;
  15459 }
  15460 NK_LIB struct nk_vec2
  15461 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
  15462 {
  15463     switch (type) {
  15464     default:
  15465     case NK_PANEL_WINDOW: return style->window.padding;
  15466     case NK_PANEL_GROUP: return style->window.group_padding;
  15467     case NK_PANEL_POPUP: return style->window.popup_padding;
  15468     case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
  15469     case NK_PANEL_COMBO: return style->window.combo_padding;
  15470     case NK_PANEL_MENU: return style->window.menu_padding;
  15471     case NK_PANEL_TOOLTIP: return style->window.menu_padding;}
  15472 }
  15473 NK_LIB float
  15474 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
  15475     enum nk_panel_type type)
  15476 {
  15477     if (flags & NK_WINDOW_BORDER) {
  15478         switch (type) {
  15479         default:
  15480         case NK_PANEL_WINDOW: return style->window.border;
  15481         case NK_PANEL_GROUP: return style->window.group_border;
  15482         case NK_PANEL_POPUP: return style->window.popup_border;
  15483         case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
  15484         case NK_PANEL_COMBO: return style->window.combo_border;
  15485         case NK_PANEL_MENU: return style->window.menu_border;
  15486         case NK_PANEL_TOOLTIP: return style->window.menu_border;
  15487     }} else return 0;
  15488 }
  15489 NK_LIB struct nk_color
  15490 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
  15491 {
  15492     switch (type) {
  15493     default:
  15494     case NK_PANEL_WINDOW: return style->window.border_color;
  15495     case NK_PANEL_GROUP: return style->window.group_border_color;
  15496     case NK_PANEL_POPUP: return style->window.popup_border_color;
  15497     case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
  15498     case NK_PANEL_COMBO: return style->window.combo_border_color;
  15499     case NK_PANEL_MENU: return style->window.menu_border_color;
  15500     case NK_PANEL_TOOLTIP: return style->window.menu_border_color;}
  15501 }
  15502 NK_LIB int
  15503 nk_panel_is_sub(enum nk_panel_type type)
  15504 {
  15505     return (type & NK_PANEL_SET_SUB)?1:0;
  15506 }
  15507 NK_LIB int
  15508 nk_panel_is_nonblock(enum nk_panel_type type)
  15509 {
  15510     return (type & NK_PANEL_SET_NONBLOCK)?1:0;
  15511 }
  15512 NK_LIB int
  15513 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
  15514 {
  15515     struct nk_input *in;
  15516     struct nk_window *win;
  15517     struct nk_panel *layout;
  15518     struct nk_command_buffer *out;
  15519     const struct nk_style *style;
  15520     const struct nk_user_font *font;
  15521 
  15522     struct nk_vec2 scrollbar_size;
  15523     struct nk_vec2 panel_padding;
  15524 
  15525     NK_ASSERT(ctx);
  15526     NK_ASSERT(ctx->current);
  15527     NK_ASSERT(ctx->current->layout);
  15528     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
  15529     nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
  15530     if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
  15531         nk_zero(ctx->current->layout, sizeof(struct nk_panel));
  15532         ctx->current->layout->type = panel_type;
  15533         return 0;
  15534     }
  15535     /* pull state into local stack */
  15536     style = &ctx->style;
  15537     font = style->font;
  15538     win = ctx->current;
  15539     layout = win->layout;
  15540     out = &win->buffer;
  15541     in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
  15542 #ifdef NK_INCLUDE_COMMAND_USERDATA
  15543     win->buffer.userdata = ctx->userdata;
  15544 #endif
  15545     /* pull style configuration into local stack */
  15546     scrollbar_size = style->window.scrollbar_size;
  15547     panel_padding = nk_panel_get_padding(style, panel_type);
  15548 
  15549     /* window movement */
  15550     if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
  15551         int left_mouse_down;
  15552         int left_mouse_clicked;
  15553         int left_mouse_click_in_cursor;
  15554 
  15555         /* calculate draggable window space */
  15556         struct nk_rect header;
  15557         header.x = win->bounds.x;
  15558         header.y = win->bounds.y;
  15559         header.w = win->bounds.w;
  15560         if (nk_panel_has_header(win->flags, title)) {
  15561             header.h = font->height + 2.0f * style->window.header.padding.y;
  15562             header.h += 2.0f * style->window.header.label_padding.y;
  15563         } else header.h = panel_padding.y;
  15564 
  15565         /* window movement by dragging */
  15566         left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
  15567         left_mouse_clicked = (int)in->mouse.buttons[NK_BUTTON_LEFT].clicked;
  15568         left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
  15569             NK_BUTTON_LEFT, header, nk_true);
  15570         if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
  15571             win->bounds.x = win->bounds.x + in->mouse.delta.x;
  15572             win->bounds.y = win->bounds.y + in->mouse.delta.y;
  15573             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
  15574             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
  15575             ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
  15576         }
  15577     }
  15578 
  15579     /* setup panel */
  15580     layout->type = panel_type;
  15581     layout->flags = win->flags;
  15582     layout->bounds = win->bounds;
  15583     layout->bounds.x += panel_padding.x;
  15584     layout->bounds.w -= 2*panel_padding.x;
  15585     if (win->flags & NK_WINDOW_BORDER) {
  15586         layout->border = nk_panel_get_border(style, win->flags, panel_type);
  15587         layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
  15588     } else layout->border = 0;
  15589     layout->at_y = layout->bounds.y;
  15590     layout->at_x = layout->bounds.x;
  15591     layout->max_x = 0;
  15592     layout->header_height = 0;
  15593     layout->footer_height = 0;
  15594     nk_layout_reset_min_row_height(ctx);
  15595     layout->row.index = 0;
  15596     layout->row.columns = 0;
  15597     layout->row.ratio = 0;
  15598     layout->row.item_width = 0;
  15599     layout->row.tree_depth = 0;
  15600     layout->row.height = panel_padding.y;
  15601     layout->has_scrolling = nk_true;
  15602     if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
  15603         layout->bounds.w -= scrollbar_size.x;
  15604     if (!nk_panel_is_nonblock(panel_type)) {
  15605         layout->footer_height = 0;
  15606         if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
  15607             layout->footer_height = scrollbar_size.y;
  15608         layout->bounds.h -= layout->footer_height;
  15609     }
  15610 
  15611     /* panel header */
  15612     if (nk_panel_has_header(win->flags, title))
  15613     {
  15614         struct nk_text text;
  15615         struct nk_rect header;
  15616         const struct nk_style_item *background = 0;
  15617 
  15618         /* calculate header bounds */
  15619         header.x = win->bounds.x;
  15620         header.y = win->bounds.y;
  15621         header.w = win->bounds.w;
  15622         header.h = font->height + 2.0f * style->window.header.padding.y;
  15623         header.h += (2.0f * style->window.header.label_padding.y);
  15624 
  15625         /* shrink panel by header */
  15626         layout->header_height = header.h;
  15627         layout->bounds.y += header.h;
  15628         layout->bounds.h -= header.h;
  15629         layout->at_y += header.h;
  15630 
  15631         /* select correct header background and text color */
  15632         if (ctx->active == win) {
  15633             background = &style->window.header.active;
  15634             text.text = style->window.header.label_active;
  15635         } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
  15636             background = &style->window.header.hover;
  15637             text.text = style->window.header.label_hover;
  15638         } else {
  15639             background = &style->window.header.normal;
  15640             text.text = style->window.header.label_normal;
  15641         }
  15642 
  15643         /* draw header background */
  15644         header.h += 1.0f;
  15645         if (background->type == NK_STYLE_ITEM_IMAGE) {
  15646             text.background = nk_rgba(0,0,0,0);
  15647             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  15648         } else {
  15649             text.background = background->data.color;
  15650             nk_fill_rect(out, header, 0, background->data.color);
  15651         }
  15652 
  15653         /* window close button */
  15654         {struct nk_rect button;
  15655         button.y = header.y + style->window.header.padding.y;
  15656         button.h = header.h - 2 * style->window.header.padding.y;
  15657         button.w = button.h;
  15658         if (win->flags & NK_WINDOW_CLOSABLE) {
  15659             nk_flags ws = 0;
  15660             if (style->window.header.align == NK_HEADER_RIGHT) {
  15661                 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
  15662                 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
  15663             } else {
  15664                 button.x = header.x + style->window.header.padding.x;
  15665                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
  15666             }
  15667 
  15668             if (nk_do_button_symbol(&ws, &win->buffer, button,
  15669                 style->window.header.close_symbol, NK_BUTTON_DEFAULT,
  15670                 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
  15671             {
  15672                 layout->flags |= NK_WINDOW_HIDDEN;
  15673                 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
  15674             }
  15675         }
  15676 
  15677         /* window minimize button */
  15678         if (win->flags & NK_WINDOW_MINIMIZABLE) {
  15679             nk_flags ws = 0;
  15680             if (style->window.header.align == NK_HEADER_RIGHT) {
  15681                 button.x = (header.w + header.x) - button.w;
  15682                 if (!(win->flags & NK_WINDOW_CLOSABLE)) {
  15683                     button.x -= style->window.header.padding.x;
  15684                     header.w -= style->window.header.padding.x;
  15685                 }
  15686                 header.w -= button.w + style->window.header.spacing.x;
  15687             } else {
  15688                 button.x = header.x;
  15689                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
  15690             }
  15691             if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
  15692                 style->window.header.maximize_symbol: style->window.header.minimize_symbol,
  15693                 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
  15694                 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
  15695                     layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
  15696                     layout->flags | NK_WINDOW_MINIMIZED;
  15697         }}
  15698 
  15699         {/* window header title */
  15700         int text_len = nk_strlen(title);
  15701         struct nk_rect label = {0,0,0,0};
  15702         float t = font->width(font->userdata, font->height, title, text_len);
  15703         text.padding = nk_vec2(0,0);
  15704 
  15705         label.x = header.x + style->window.header.padding.x;
  15706         label.x += style->window.header.label_padding.x;
  15707         label.y = header.y + style->window.header.label_padding.y;
  15708         label.h = font->height + 2 * style->window.header.label_padding.y;
  15709         label.w = t + 2 * style->window.header.spacing.x;
  15710         label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
  15711         nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
  15712     }
  15713 
  15714     /* draw window background */
  15715     if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
  15716         struct nk_rect body;
  15717         body.x = win->bounds.x;
  15718         body.w = win->bounds.w;
  15719         body.y = (win->bounds.y + layout->header_height);
  15720         body.h = (win->bounds.h - layout->header_height);
  15721         if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE)
  15722             nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
  15723         else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
  15724     }
  15725 
  15726     /* set clipping rectangle */
  15727     {struct nk_rect clip;
  15728     layout->clip = layout->bounds;
  15729     nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
  15730         layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
  15731     nk_push_scissor(out, clip);
  15732     layout->clip = clip;}
  15733     return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
  15734 }
  15735 NK_LIB void
  15736 nk_panel_end(struct nk_context *ctx)
  15737 {
  15738     struct nk_input *in;
  15739     struct nk_window *window;
  15740     struct nk_panel *layout;
  15741     const struct nk_style *style;
  15742     struct nk_command_buffer *out;
  15743 
  15744     struct nk_vec2 scrollbar_size;
  15745     struct nk_vec2 panel_padding;
  15746 
  15747     NK_ASSERT(ctx);
  15748     NK_ASSERT(ctx->current);
  15749     NK_ASSERT(ctx->current->layout);
  15750     if (!ctx || !ctx->current || !ctx->current->layout)
  15751         return;
  15752 
  15753     window = ctx->current;
  15754     layout = window->layout;
  15755     style = &ctx->style;
  15756     out = &window->buffer;
  15757     in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
  15758     if (!nk_panel_is_sub(layout->type))
  15759         nk_push_scissor(out, nk_null_rect);
  15760 
  15761     /* cache configuration data */
  15762     scrollbar_size = style->window.scrollbar_size;
  15763     panel_padding = nk_panel_get_padding(style, layout->type);
  15764 
  15765     /* update the current cursor Y-position to point over the last added widget */
  15766     layout->at_y += layout->row.height;
  15767 
  15768     /* dynamic panels */
  15769     if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
  15770     {
  15771         /* update panel height to fit dynamic growth */
  15772         struct nk_rect empty_space;
  15773         if (layout->at_y < (layout->bounds.y + layout->bounds.h))
  15774             layout->bounds.h = layout->at_y - layout->bounds.y;
  15775 
  15776         /* fill top empty space */
  15777         empty_space.x = window->bounds.x;
  15778         empty_space.y = layout->bounds.y;
  15779         empty_space.h = panel_padding.y;
  15780         empty_space.w = window->bounds.w;
  15781         nk_fill_rect(out, empty_space, 0, style->window.background);
  15782 
  15783         /* fill left empty space */
  15784         empty_space.x = window->bounds.x;
  15785         empty_space.y = layout->bounds.y;
  15786         empty_space.w = panel_padding.x + layout->border;
  15787         empty_space.h = layout->bounds.h;
  15788         nk_fill_rect(out, empty_space, 0, style->window.background);
  15789 
  15790         /* fill right empty space */
  15791         empty_space.x = layout->bounds.x + layout->bounds.w - layout->border;
  15792         empty_space.y = layout->bounds.y;
  15793         empty_space.w = panel_padding.x + layout->border;
  15794         empty_space.h = layout->bounds.h;
  15795         if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
  15796             empty_space.w += scrollbar_size.x;
  15797         nk_fill_rect(out, empty_space, 0, style->window.background);
  15798 
  15799         /* fill bottom empty space */
  15800         if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) {
  15801             empty_space.x = window->bounds.x;
  15802             empty_space.y = layout->bounds.y + layout->bounds.h;
  15803             empty_space.w = window->bounds.w;
  15804             empty_space.h = scrollbar_size.y;
  15805             nk_fill_rect(out, empty_space, 0, style->window.background);
  15806         }
  15807     }
  15808 
  15809     /* scrollbars */
  15810     if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
  15811         !(layout->flags & NK_WINDOW_MINIMIZED) &&
  15812         window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
  15813     {
  15814         struct nk_rect scroll;
  15815         int scroll_has_scrolling;
  15816         float scroll_target;
  15817         float scroll_offset;
  15818         float scroll_step;
  15819         float scroll_inc;
  15820 
  15821         /* mouse wheel scrolling */
  15822         if (nk_panel_is_sub(layout->type))
  15823         {
  15824             /* sub-window mouse wheel scrolling */
  15825             struct nk_window *root_window = window;
  15826             struct nk_panel *root_panel = window->layout;
  15827             while (root_panel->parent)
  15828                 root_panel = root_panel->parent;
  15829             while (root_window->parent)
  15830                 root_window = root_window->parent;
  15831 
  15832             /* only allow scrolling if parent window is active */
  15833             scroll_has_scrolling = 0;
  15834             if ((root_window == ctx->active) && layout->has_scrolling) {
  15835                 /* and panel is being hovered and inside clip rect*/
  15836                 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
  15837                     NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
  15838                         root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
  15839                 {
  15840                     /* deactivate all parent scrolling */
  15841                     root_panel = window->layout;
  15842                     while (root_panel->parent) {
  15843                         root_panel->has_scrolling = nk_false;
  15844                         root_panel = root_panel->parent;
  15845                     }
  15846                     root_panel->has_scrolling = nk_false;
  15847                     scroll_has_scrolling = nk_true;
  15848                 }
  15849             }
  15850         } else if (!nk_panel_is_sub(layout->type)) {
  15851             /* window mouse wheel scrolling */
  15852             scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
  15853             if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
  15854                 window->scrolled = nk_true;
  15855             else window->scrolled = nk_false;
  15856         } else scroll_has_scrolling = nk_false;
  15857 
  15858         {
  15859             /* vertical scrollbar */
  15860             nk_flags state = 0;
  15861             scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
  15862             scroll.y = layout->bounds.y;
  15863             scroll.w = scrollbar_size.x;
  15864             scroll.h = layout->bounds.h;
  15865 
  15866             scroll_offset = (float)*layout->offset_y;
  15867             scroll_step = scroll.h * 0.10f;
  15868             scroll_inc = scroll.h * 0.01f;
  15869             scroll_target = (float)(int)(layout->at_y - scroll.y);
  15870             scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
  15871                 scroll_offset, scroll_target, scroll_step, scroll_inc,
  15872                 &ctx->style.scrollv, in, style->font);
  15873             *layout->offset_y = (nk_uint)scroll_offset;
  15874             if (in && scroll_has_scrolling)
  15875                 in->mouse.scroll_delta.y = 0;
  15876         }
  15877         {
  15878             /* horizontal scrollbar */
  15879             nk_flags state = 0;
  15880             scroll.x = layout->bounds.x;
  15881             scroll.y = layout->bounds.y + layout->bounds.h;
  15882             scroll.w = layout->bounds.w;
  15883             scroll.h = scrollbar_size.y;
  15884 
  15885             scroll_offset = (float)*layout->offset_x;
  15886             scroll_target = (float)(int)(layout->max_x - scroll.x);
  15887             scroll_step = layout->max_x * 0.05f;
  15888             scroll_inc = layout->max_x * 0.005f;
  15889             scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
  15890                 scroll_offset, scroll_target, scroll_step, scroll_inc,
  15891                 &ctx->style.scrollh, in, style->font);
  15892             *layout->offset_x = (nk_uint)scroll_offset;
  15893         }
  15894     }
  15895 
  15896     /* hide scroll if no user input */
  15897     if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
  15898         int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
  15899         int is_window_hovered = nk_window_is_hovered(ctx);
  15900         int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
  15901         if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
  15902             window->scrollbar_hiding_timer += ctx->delta_time_seconds;
  15903         else window->scrollbar_hiding_timer = 0;
  15904     } else window->scrollbar_hiding_timer = 0;
  15905 
  15906     /* window border */
  15907     if (layout->flags & NK_WINDOW_BORDER)
  15908     {
  15909         struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
  15910         const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED)
  15911             ? (style->window.border + window->bounds.y + layout->header_height)
  15912             : ((layout->flags & NK_WINDOW_DYNAMIC)
  15913                 ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
  15914                 : (window->bounds.y + window->bounds.h));
  15915         struct nk_rect b = window->bounds;
  15916         b.h = padding_y - window->bounds.y;
  15917         nk_stroke_rect(out, b, 0, layout->border, border_color);
  15918     }
  15919 
  15920     /* scaler */
  15921     if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
  15922     {
  15923         /* calculate scaler bounds */
  15924         struct nk_rect scaler;
  15925         scaler.w = scrollbar_size.x;
  15926         scaler.h = scrollbar_size.y;
  15927         scaler.y = layout->bounds.y + layout->bounds.h;
  15928         if (layout->flags & NK_WINDOW_SCALE_LEFT)
  15929             scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
  15930         else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
  15931         if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
  15932             scaler.x -= scaler.w;
  15933 
  15934         /* draw scaler */
  15935         {const struct nk_style_item *item = &style->window.scaler;
  15936         if (item->type == NK_STYLE_ITEM_IMAGE)
  15937             nk_draw_image(out, scaler, &item->data.image, nk_white);
  15938         else {
  15939             if (layout->flags & NK_WINDOW_SCALE_LEFT) {
  15940                 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
  15941                     scaler.y + scaler.h, scaler.x + scaler.w,
  15942                     scaler.y + scaler.h, item->data.color);
  15943             } else {
  15944                 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
  15945                     scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
  15946             }
  15947         }}
  15948 
  15949         /* do window scaling */
  15950         if (!(window->flags & NK_WINDOW_ROM)) {
  15951             struct nk_vec2 window_size = style->window.min_size;
  15952             int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
  15953             int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
  15954                     NK_BUTTON_LEFT, scaler, nk_true);
  15955 
  15956             if (left_mouse_down && left_mouse_click_in_scaler) {
  15957                 float delta_x = in->mouse.delta.x;
  15958                 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
  15959                     delta_x = -delta_x;
  15960                     window->bounds.x += in->mouse.delta.x;
  15961                 }
  15962                 /* dragging in x-direction  */
  15963                 if (window->bounds.w + delta_x >= window_size.x) {
  15964                     if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
  15965                         window->bounds.w = window->bounds.w + delta_x;
  15966                         scaler.x += in->mouse.delta.x;
  15967                     }
  15968                 }
  15969                 /* dragging in y-direction (only possible if static window) */
  15970                 if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
  15971                     if (window_size.y < window->bounds.h + in->mouse.delta.y) {
  15972                         if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
  15973                             window->bounds.h = window->bounds.h + in->mouse.delta.y;
  15974                             scaler.y += in->mouse.delta.y;
  15975                         }
  15976                     }
  15977                 }
  15978                 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
  15979                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
  15980                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
  15981             }
  15982         }
  15983     }
  15984     if (!nk_panel_is_sub(layout->type)) {
  15985         /* window is hidden so clear command buffer  */
  15986         if (layout->flags & NK_WINDOW_HIDDEN)
  15987             nk_command_buffer_reset(&window->buffer);
  15988         /* window is visible and not tab */
  15989         else nk_finish(ctx, window);
  15990     }
  15991 
  15992     /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
  15993     if (layout->flags & NK_WINDOW_REMOVE_ROM) {
  15994         layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
  15995         layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
  15996     }
  15997     window->flags = layout->flags;
  15998 
  15999     /* property garbage collector */
  16000     if (window->property.active && window->property.old != window->property.seq &&
  16001         window->property.active == window->property.prev) {
  16002         nk_zero(&window->property, sizeof(window->property));
  16003     } else {
  16004         window->property.old = window->property.seq;
  16005         window->property.prev = window->property.active;
  16006         window->property.seq = 0;
  16007     }
  16008     /* edit garbage collector */
  16009     if (window->edit.active && window->edit.old != window->edit.seq &&
  16010        window->edit.active == window->edit.prev) {
  16011         nk_zero(&window->edit, sizeof(window->edit));
  16012     } else {
  16013         window->edit.old = window->edit.seq;
  16014         window->edit.prev = window->edit.active;
  16015         window->edit.seq = 0;
  16016     }
  16017     /* contextual garbage collector */
  16018     if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
  16019         window->popup.con_count = 0;
  16020         window->popup.con_old = 0;
  16021         window->popup.active_con = 0;
  16022     } else {
  16023         window->popup.con_old = window->popup.con_count;
  16024         window->popup.con_count = 0;
  16025     }
  16026     window->popup.combo_count = 0;
  16027     /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
  16028     NK_ASSERT(!layout->row.tree_depth);
  16029 }
  16030 
  16031 
  16032 
  16033 
  16034 
  16035 /* ===============================================================
  16036  *
  16037  *                              WINDOW
  16038  *
  16039  * ===============================================================*/
  16040 NK_LIB void*
  16041 nk_create_window(struct nk_context *ctx)
  16042 {
  16043     struct nk_page_element *elem;
  16044     elem = nk_create_page_element(ctx);
  16045     if (!elem) return 0;
  16046     elem->data.win.seq = ctx->seq;
  16047     return &elem->data.win;
  16048 }
  16049 NK_LIB void
  16050 nk_free_window(struct nk_context *ctx, struct nk_window *win)
  16051 {
  16052     /* unlink windows from list */
  16053     struct nk_table *it = win->tables;
  16054     if (win->popup.win) {
  16055         nk_free_window(ctx, win->popup.win);
  16056         win->popup.win = 0;
  16057     }
  16058     win->next = 0;
  16059     win->prev = 0;
  16060 
  16061     while (it) {
  16062         /*free window state tables */
  16063         struct nk_table *n = it->next;
  16064         nk_remove_table(win, it);
  16065         nk_free_table(ctx, it);
  16066         if (it == win->tables)
  16067             win->tables = n;
  16068         it = n;
  16069     }
  16070 
  16071     /* link windows into freelist */
  16072     {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
  16073     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
  16074     nk_free_page_element(ctx, pe);}
  16075 }
  16076 NK_LIB struct nk_window*
  16077 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
  16078 {
  16079     struct nk_window *iter;
  16080     iter = ctx->begin;
  16081     while (iter) {
  16082         NK_ASSERT(iter != iter->next);
  16083         if (iter->name == hash) {
  16084             int max_len = nk_strlen(iter->name_string);
  16085             if (!nk_stricmpn(iter->name_string, name, max_len))
  16086                 return iter;
  16087         }
  16088         iter = iter->next;
  16089     }
  16090     return 0;
  16091 }
  16092 NK_LIB void
  16093 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
  16094     enum nk_window_insert_location loc)
  16095 {
  16096     const struct nk_window *iter;
  16097     NK_ASSERT(ctx);
  16098     NK_ASSERT(win);
  16099     if (!win || !ctx) return;
  16100 
  16101     iter = ctx->begin;
  16102     while (iter) {
  16103         NK_ASSERT(iter != iter->next);
  16104         NK_ASSERT(iter != win);
  16105         if (iter == win) return;
  16106         iter = iter->next;
  16107     }
  16108 
  16109     if (!ctx->begin) {
  16110         win->next = 0;
  16111         win->prev = 0;
  16112         ctx->begin = win;
  16113         ctx->end = win;
  16114         ctx->count = 1;
  16115         return;
  16116     }
  16117     if (loc == NK_INSERT_BACK) {
  16118         struct nk_window *end;
  16119         end = ctx->end;
  16120         end->flags |= NK_WINDOW_ROM;
  16121         end->next = win;
  16122         win->prev = ctx->end;
  16123         win->next = 0;
  16124         ctx->end = win;
  16125         ctx->active = ctx->end;
  16126         ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
  16127     } else {
  16128         /*ctx->end->flags |= NK_WINDOW_ROM;*/
  16129         ctx->begin->prev = win;
  16130         win->next = ctx->begin;
  16131         win->prev = 0;
  16132         ctx->begin = win;
  16133         ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
  16134     }
  16135     ctx->count++;
  16136 }
  16137 NK_LIB void
  16138 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
  16139 {
  16140     if (win == ctx->begin || win == ctx->end) {
  16141         if (win == ctx->begin) {
  16142             ctx->begin = win->next;
  16143             if (win->next)
  16144                 win->next->prev = 0;
  16145         }
  16146         if (win == ctx->end) {
  16147             ctx->end = win->prev;
  16148             if (win->prev)
  16149                 win->prev->next = 0;
  16150         }
  16151     } else {
  16152         if (win->next)
  16153             win->next->prev = win->prev;
  16154         if (win->prev)
  16155             win->prev->next = win->next;
  16156     }
  16157     if (win == ctx->active || !ctx->active) {
  16158         ctx->active = ctx->end;
  16159         if (ctx->end)
  16160             ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
  16161     }
  16162     win->next = 0;
  16163     win->prev = 0;
  16164     ctx->count--;
  16165 }
  16166 NK_API int
  16167 nk_begin(struct nk_context *ctx, const char *title,
  16168     struct nk_rect bounds, nk_flags flags)
  16169 {
  16170     return nk_begin_titled(ctx, title, title, bounds, flags);
  16171 }
  16172 NK_API int
  16173 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
  16174     struct nk_rect bounds, nk_flags flags)
  16175 {
  16176     struct nk_window *win;
  16177     struct nk_style *style;
  16178     nk_hash title_hash;
  16179     int title_len;
  16180     int ret = 0;
  16181 
  16182     NK_ASSERT(ctx);
  16183     NK_ASSERT(name);
  16184     NK_ASSERT(title);
  16185     NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
  16186     NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
  16187     if (!ctx || ctx->current || !title || !name)
  16188         return 0;
  16189 
  16190     /* find or create window */
  16191     style = &ctx->style;
  16192     title_len = (int)nk_strlen(name);
  16193     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16194     win = nk_find_window(ctx, title_hash, name);
  16195     if (!win) {
  16196         /* create new window */
  16197         nk_size name_length = (nk_size)nk_strlen(name);
  16198         win = (struct nk_window*)nk_create_window(ctx);
  16199         NK_ASSERT(win);
  16200         if (!win) return 0;
  16201 
  16202         if (flags & NK_WINDOW_BACKGROUND)
  16203             nk_insert_window(ctx, win, NK_INSERT_FRONT);
  16204         else nk_insert_window(ctx, win, NK_INSERT_BACK);
  16205         nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
  16206 
  16207         win->flags = flags;
  16208         win->bounds = bounds;
  16209         win->name = title_hash;
  16210         name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
  16211         NK_MEMCPY(win->name_string, name, name_length);
  16212         win->name_string[name_length] = 0;
  16213         win->popup.win = 0;
  16214         if (!ctx->active)
  16215             ctx->active = win;
  16216     } else {
  16217         /* update window */
  16218         win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
  16219         win->flags |= flags;
  16220         if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
  16221             win->bounds = bounds;
  16222         /* If this assert triggers you either:
  16223          *
  16224          * I.) Have more than one window with the same name or
  16225          * II.) You forgot to actually draw the window.
  16226          *      More specific you did not call `nk_clear` (nk_clear will be
  16227          *      automatically called for you if you are using one of the
  16228          *      provided demo backends). */
  16229         NK_ASSERT(win->seq != ctx->seq);
  16230         win->seq = ctx->seq;
  16231         if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
  16232             ctx->active = win;
  16233             ctx->end = win;
  16234         }
  16235     }
  16236     if (win->flags & NK_WINDOW_HIDDEN) {
  16237         ctx->current = win;
  16238         win->layout = 0;
  16239         return 0;
  16240     } else nk_start(ctx, win);
  16241 
  16242     /* window overlapping */
  16243     if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
  16244     {
  16245         int inpanel, ishovered;
  16246         struct nk_window *iter = win;
  16247         float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
  16248             (2.0f * style->window.header.label_padding.y);
  16249         struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
  16250             win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
  16251 
  16252         /* activate window if hovered and no other window is overlapping this window */
  16253         inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
  16254         inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
  16255         ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
  16256         if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
  16257             iter = win->next;
  16258             while (iter) {
  16259                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
  16260                     iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
  16261                 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
  16262                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
  16263                     (!(iter->flags & NK_WINDOW_HIDDEN)))
  16264                     break;
  16265 
  16266                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
  16267                     NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
  16268                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
  16269                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
  16270                     break;
  16271                 iter = iter->next;
  16272             }
  16273         }
  16274 
  16275         /* activate window if clicked */
  16276         if (iter && inpanel && (win != ctx->end)) {
  16277             iter = win->next;
  16278             while (iter) {
  16279                 /* try to find a panel with higher priority in the same position */
  16280                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
  16281                 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
  16282                 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
  16283                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
  16284                     !(iter->flags & NK_WINDOW_HIDDEN))
  16285                     break;
  16286                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
  16287                     NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
  16288                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
  16289                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
  16290                     break;
  16291                 iter = iter->next;
  16292             }
  16293         }
  16294         if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
  16295             win->flags |= (nk_flags)NK_WINDOW_ROM;
  16296             iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
  16297             ctx->active = iter;
  16298             if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
  16299                 /* current window is active in that position so transfer to top
  16300                  * at the highest priority in stack */
  16301                 nk_remove_window(ctx, iter);
  16302                 nk_insert_window(ctx, iter, NK_INSERT_BACK);
  16303             }
  16304         } else {
  16305             if (!iter && ctx->end != win) {
  16306                 if (!(win->flags & NK_WINDOW_BACKGROUND)) {
  16307                     /* current window is active in that position so transfer to top
  16308                      * at the highest priority in stack */
  16309                     nk_remove_window(ctx, win);
  16310                     nk_insert_window(ctx, win, NK_INSERT_BACK);
  16311                 }
  16312                 win->flags &= ~(nk_flags)NK_WINDOW_ROM;
  16313                 ctx->active = win;
  16314             }
  16315             if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
  16316                 win->flags |= NK_WINDOW_ROM;
  16317         }
  16318     }
  16319     win->layout = (struct nk_panel*)nk_create_panel(ctx);
  16320     ctx->current = win;
  16321     ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
  16322     win->layout->offset_x = &win->scrollbar.x;
  16323     win->layout->offset_y = &win->scrollbar.y;
  16324     return ret;
  16325 }
  16326 NK_API void
  16327 nk_end(struct nk_context *ctx)
  16328 {
  16329     struct nk_panel *layout;
  16330     NK_ASSERT(ctx);
  16331     NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
  16332     if (!ctx || !ctx->current)
  16333         return;
  16334 
  16335     layout = ctx->current->layout;
  16336     if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
  16337         ctx->current = 0;
  16338         return;
  16339     }
  16340     nk_panel_end(ctx);
  16341     nk_free_panel(ctx, ctx->current->layout);
  16342     ctx->current = 0;
  16343 }
  16344 NK_API struct nk_rect
  16345 nk_window_get_bounds(const struct nk_context *ctx)
  16346 {
  16347     NK_ASSERT(ctx);
  16348     NK_ASSERT(ctx->current);
  16349     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
  16350     return ctx->current->bounds;
  16351 }
  16352 NK_API struct nk_vec2
  16353 nk_window_get_position(const struct nk_context *ctx)
  16354 {
  16355     NK_ASSERT(ctx);
  16356     NK_ASSERT(ctx->current);
  16357     if (!ctx || !ctx->current) return nk_vec2(0,0);
  16358     return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
  16359 }
  16360 NK_API struct nk_vec2
  16361 nk_window_get_size(const struct nk_context *ctx)
  16362 {
  16363     NK_ASSERT(ctx);
  16364     NK_ASSERT(ctx->current);
  16365     if (!ctx || !ctx->current) return nk_vec2(0,0);
  16366     return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
  16367 }
  16368 NK_API float
  16369 nk_window_get_width(const struct nk_context *ctx)
  16370 {
  16371     NK_ASSERT(ctx);
  16372     NK_ASSERT(ctx->current);
  16373     if (!ctx || !ctx->current) return 0;
  16374     return ctx->current->bounds.w;
  16375 }
  16376 NK_API float
  16377 nk_window_get_height(const struct nk_context *ctx)
  16378 {
  16379     NK_ASSERT(ctx);
  16380     NK_ASSERT(ctx->current);
  16381     if (!ctx || !ctx->current) return 0;
  16382     return ctx->current->bounds.h;
  16383 }
  16384 NK_API struct nk_rect
  16385 nk_window_get_content_region(struct nk_context *ctx)
  16386 {
  16387     NK_ASSERT(ctx);
  16388     NK_ASSERT(ctx->current);
  16389     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
  16390     return ctx->current->layout->clip;
  16391 }
  16392 NK_API struct nk_vec2
  16393 nk_window_get_content_region_min(struct nk_context *ctx)
  16394 {
  16395     NK_ASSERT(ctx);
  16396     NK_ASSERT(ctx->current);
  16397     NK_ASSERT(ctx->current->layout);
  16398     if (!ctx || !ctx->current) return nk_vec2(0,0);
  16399     return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
  16400 }
  16401 NK_API struct nk_vec2
  16402 nk_window_get_content_region_max(struct nk_context *ctx)
  16403 {
  16404     NK_ASSERT(ctx);
  16405     NK_ASSERT(ctx->current);
  16406     NK_ASSERT(ctx->current->layout);
  16407     if (!ctx || !ctx->current) return nk_vec2(0,0);
  16408     return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
  16409         ctx->current->layout->clip.y + ctx->current->layout->clip.h);
  16410 }
  16411 NK_API struct nk_vec2
  16412 nk_window_get_content_region_size(struct nk_context *ctx)
  16413 {
  16414     NK_ASSERT(ctx);
  16415     NK_ASSERT(ctx->current);
  16416     NK_ASSERT(ctx->current->layout);
  16417     if (!ctx || !ctx->current) return nk_vec2(0,0);
  16418     return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
  16419 }
  16420 NK_API struct nk_command_buffer*
  16421 nk_window_get_canvas(struct nk_context *ctx)
  16422 {
  16423     NK_ASSERT(ctx);
  16424     NK_ASSERT(ctx->current);
  16425     NK_ASSERT(ctx->current->layout);
  16426     if (!ctx || !ctx->current) return 0;
  16427     return &ctx->current->buffer;
  16428 }
  16429 NK_API struct nk_panel*
  16430 nk_window_get_panel(struct nk_context *ctx)
  16431 {
  16432     NK_ASSERT(ctx);
  16433     NK_ASSERT(ctx->current);
  16434     if (!ctx || !ctx->current) return 0;
  16435     return ctx->current->layout;
  16436 }
  16437 NK_API int
  16438 nk_window_has_focus(const struct nk_context *ctx)
  16439 {
  16440     NK_ASSERT(ctx);
  16441     NK_ASSERT(ctx->current);
  16442     NK_ASSERT(ctx->current->layout);
  16443     if (!ctx || !ctx->current) return 0;
  16444     return ctx->current == ctx->active;
  16445 }
  16446 NK_API int
  16447 nk_window_is_hovered(struct nk_context *ctx)
  16448 {
  16449     NK_ASSERT(ctx);
  16450     NK_ASSERT(ctx->current);
  16451     if (!ctx || !ctx->current) return 0;
  16452     if(ctx->current->flags & NK_WINDOW_HIDDEN)
  16453         return 0;
  16454     return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
  16455 }
  16456 NK_API int
  16457 nk_window_is_any_hovered(struct nk_context *ctx)
  16458 {
  16459     struct nk_window *iter;
  16460     NK_ASSERT(ctx);
  16461     if (!ctx) return 0;
  16462     iter = ctx->begin;
  16463     while (iter) {
  16464         /* check if window is being hovered */
  16465         if(!(iter->flags & NK_WINDOW_HIDDEN)) {
  16466             /* check if window popup is being hovered */
  16467             if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
  16468                 return 1;
  16469 
  16470             if (iter->flags & NK_WINDOW_MINIMIZED) {
  16471                 struct nk_rect header = iter->bounds;
  16472                 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
  16473                 if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
  16474                     return 1;
  16475             } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
  16476                 return 1;
  16477             }
  16478         }
  16479         iter = iter->next;
  16480     }
  16481     return 0;
  16482 }
  16483 NK_API int
  16484 nk_item_is_any_active(struct nk_context *ctx)
  16485 {
  16486     int any_hovered = nk_window_is_any_hovered(ctx);
  16487     int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
  16488     return any_hovered || any_active;
  16489 }
  16490 NK_API int
  16491 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
  16492 {
  16493     int title_len;
  16494     nk_hash title_hash;
  16495     struct nk_window *win;
  16496     NK_ASSERT(ctx);
  16497     if (!ctx) return 0;
  16498 
  16499     title_len = (int)nk_strlen(name);
  16500     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16501     win = nk_find_window(ctx, title_hash, name);
  16502     if (!win) return 0;
  16503     return win->flags & NK_WINDOW_MINIMIZED;
  16504 }
  16505 NK_API int
  16506 nk_window_is_closed(struct nk_context *ctx, const char *name)
  16507 {
  16508     int title_len;
  16509     nk_hash title_hash;
  16510     struct nk_window *win;
  16511     NK_ASSERT(ctx);
  16512     if (!ctx) return 1;
  16513 
  16514     title_len = (int)nk_strlen(name);
  16515     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16516     win = nk_find_window(ctx, title_hash, name);
  16517     if (!win) return 1;
  16518     return (win->flags & NK_WINDOW_CLOSED);
  16519 }
  16520 NK_API int
  16521 nk_window_is_hidden(struct nk_context *ctx, const char *name)
  16522 {
  16523     int title_len;
  16524     nk_hash title_hash;
  16525     struct nk_window *win;
  16526     NK_ASSERT(ctx);
  16527     if (!ctx) return 1;
  16528 
  16529     title_len = (int)nk_strlen(name);
  16530     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16531     win = nk_find_window(ctx, title_hash, name);
  16532     if (!win) return 1;
  16533     return (win->flags & NK_WINDOW_HIDDEN);
  16534 }
  16535 NK_API int
  16536 nk_window_is_active(struct nk_context *ctx, const char *name)
  16537 {
  16538     int title_len;
  16539     nk_hash title_hash;
  16540     struct nk_window *win;
  16541     NK_ASSERT(ctx);
  16542     if (!ctx) return 0;
  16543 
  16544     title_len = (int)nk_strlen(name);
  16545     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16546     win = nk_find_window(ctx, title_hash, name);
  16547     if (!win) return 0;
  16548     return win == ctx->active;
  16549 }
  16550 NK_API struct nk_window*
  16551 nk_window_find(struct nk_context *ctx, const char *name)
  16552 {
  16553     int title_len;
  16554     nk_hash title_hash;
  16555     title_len = (int)nk_strlen(name);
  16556     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16557     return nk_find_window(ctx, title_hash, name);
  16558 }
  16559 NK_API void
  16560 nk_window_close(struct nk_context *ctx, const char *name)
  16561 {
  16562     struct nk_window *win;
  16563     NK_ASSERT(ctx);
  16564     if (!ctx) return;
  16565     win = nk_window_find(ctx, name);
  16566     if (!win) return;
  16567     NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
  16568     if (ctx->current == win) return;
  16569     win->flags |= NK_WINDOW_HIDDEN;
  16570     win->flags |= NK_WINDOW_CLOSED;
  16571 }
  16572 NK_API void
  16573 nk_window_set_bounds(struct nk_context *ctx,
  16574     const char *name, struct nk_rect bounds)
  16575 {
  16576     struct nk_window *win;
  16577     NK_ASSERT(ctx);
  16578     if (!ctx) return;
  16579     win = nk_window_find(ctx, name);
  16580     if (!win) return;
  16581     NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
  16582     win->bounds = bounds;
  16583 }
  16584 NK_API void
  16585 nk_window_set_position(struct nk_context *ctx,
  16586     const char *name, struct nk_vec2 pos)
  16587 {
  16588     struct nk_window *win = nk_window_find(ctx, name);
  16589     if (!win) return;
  16590     win->bounds.x = pos.x;
  16591     win->bounds.y = pos.y;
  16592 }
  16593 NK_API void
  16594 nk_window_set_size(struct nk_context *ctx,
  16595     const char *name, struct nk_vec2 size)
  16596 {
  16597     struct nk_window *win = nk_window_find(ctx, name);
  16598     if (!win) return;
  16599     win->bounds.w = size.x;
  16600     win->bounds.h = size.y;
  16601 }
  16602 NK_API void
  16603 nk_window_collapse(struct nk_context *ctx, const char *name,
  16604                     enum nk_collapse_states c)
  16605 {
  16606     int title_len;
  16607     nk_hash title_hash;
  16608     struct nk_window *win;
  16609     NK_ASSERT(ctx);
  16610     if (!ctx) return;
  16611 
  16612     title_len = (int)nk_strlen(name);
  16613     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16614     win = nk_find_window(ctx, title_hash, name);
  16615     if (!win) return;
  16616     if (c == NK_MINIMIZED)
  16617         win->flags |= NK_WINDOW_MINIMIZED;
  16618     else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
  16619 }
  16620 NK_API void
  16621 nk_window_collapse_if(struct nk_context *ctx, const char *name,
  16622     enum nk_collapse_states c, int cond)
  16623 {
  16624     NK_ASSERT(ctx);
  16625     if (!ctx || !cond) return;
  16626     nk_window_collapse(ctx, name, c);
  16627 }
  16628 NK_API void
  16629 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
  16630 {
  16631     int title_len;
  16632     nk_hash title_hash;
  16633     struct nk_window *win;
  16634     NK_ASSERT(ctx);
  16635     if (!ctx) return;
  16636 
  16637     title_len = (int)nk_strlen(name);
  16638     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16639     win = nk_find_window(ctx, title_hash, name);
  16640     if (!win) return;
  16641     if (s == NK_HIDDEN) {
  16642         win->flags |= NK_WINDOW_HIDDEN;
  16643     } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
  16644 }
  16645 NK_API void
  16646 nk_window_show_if(struct nk_context *ctx, const char *name,
  16647     enum nk_show_states s, int cond)
  16648 {
  16649     NK_ASSERT(ctx);
  16650     if (!ctx || !cond) return;
  16651     nk_window_show(ctx, name, s);
  16652 }
  16653 
  16654 NK_API void
  16655 nk_window_set_focus(struct nk_context *ctx, const char *name)
  16656 {
  16657     int title_len;
  16658     nk_hash title_hash;
  16659     struct nk_window *win;
  16660     NK_ASSERT(ctx);
  16661     if (!ctx) return;
  16662 
  16663     title_len = (int)nk_strlen(name);
  16664     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
  16665     win = nk_find_window(ctx, title_hash, name);
  16666     if (win && ctx->end != win) {
  16667         nk_remove_window(ctx, win);
  16668         nk_insert_window(ctx, win, NK_INSERT_BACK);
  16669     }
  16670     ctx->active = win;
  16671 }
  16672 
  16673 
  16674 
  16675 
  16676 
  16677 /* ===============================================================
  16678  *
  16679  *                              POPUP
  16680  *
  16681  * ===============================================================*/
  16682 NK_API int
  16683 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
  16684     const char *title, nk_flags flags, struct nk_rect rect)
  16685 {
  16686     struct nk_window *popup;
  16687     struct nk_window *win;
  16688     struct nk_panel *panel;
  16689 
  16690     int title_len;
  16691     nk_hash title_hash;
  16692     nk_size allocated;
  16693 
  16694     NK_ASSERT(ctx);
  16695     NK_ASSERT(title);
  16696     NK_ASSERT(ctx->current);
  16697     NK_ASSERT(ctx->current->layout);
  16698     if (!ctx || !ctx->current || !ctx->current->layout)
  16699         return 0;
  16700 
  16701     win = ctx->current;
  16702     panel = win->layout;
  16703     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
  16704     (void)panel;
  16705     title_len = (int)nk_strlen(title);
  16706     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
  16707 
  16708     popup = win->popup.win;
  16709     if (!popup) {
  16710         popup = (struct nk_window*)nk_create_window(ctx);
  16711         popup->parent = win;
  16712         win->popup.win = popup;
  16713         win->popup.active = 0;
  16714         win->popup.type = NK_PANEL_POPUP;
  16715     }
  16716 
  16717     /* make sure we have correct popup */
  16718     if (win->popup.name != title_hash) {
  16719         if (!win->popup.active) {
  16720             nk_zero(popup, sizeof(*popup));
  16721             win->popup.name = title_hash;
  16722             win->popup.active = 1;
  16723             win->popup.type = NK_PANEL_POPUP;
  16724         } else return 0;
  16725     }
  16726 
  16727     /* popup position is local to window */
  16728     ctx->current = popup;
  16729     rect.x += win->layout->clip.x;
  16730     rect.y += win->layout->clip.y;
  16731 
  16732     /* setup popup data */
  16733     popup->parent = win;
  16734     popup->bounds = rect;
  16735     popup->seq = ctx->seq;
  16736     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
  16737     popup->flags = flags;
  16738     popup->flags |= NK_WINDOW_BORDER;
  16739     if (type == NK_POPUP_DYNAMIC)
  16740         popup->flags |= NK_WINDOW_DYNAMIC;
  16741 
  16742     popup->buffer = win->buffer;
  16743     nk_start_popup(ctx, win);
  16744     allocated = ctx->memory.allocated;
  16745     nk_push_scissor(&popup->buffer, nk_null_rect);
  16746 
  16747     if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
  16748         /* popup is running therefore invalidate parent panels */
  16749         struct nk_panel *root;
  16750         root = win->layout;
  16751         while (root) {
  16752             root->flags |= NK_WINDOW_ROM;
  16753             root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
  16754             root = root->parent;
  16755         }
  16756         win->popup.active = 1;
  16757         popup->layout->offset_x = &popup->scrollbar.x;
  16758         popup->layout->offset_y = &popup->scrollbar.y;
  16759         popup->layout->parent = win->layout;
  16760         return 1;
  16761     } else {
  16762         /* popup was closed/is invalid so cleanup */
  16763         struct nk_panel *root;
  16764         root = win->layout;
  16765         while (root) {
  16766             root->flags |= NK_WINDOW_REMOVE_ROM;
  16767             root = root->parent;
  16768         }
  16769         win->popup.buf.active = 0;
  16770         win->popup.active = 0;
  16771         ctx->memory.allocated = allocated;
  16772         ctx->current = win;
  16773         nk_free_panel(ctx, popup->layout);
  16774         popup->layout = 0;
  16775         return 0;
  16776     }
  16777 }
  16778 NK_LIB int
  16779 nk_nonblock_begin(struct nk_context *ctx,
  16780     nk_flags flags, struct nk_rect body, struct nk_rect header,
  16781     enum nk_panel_type panel_type)
  16782 {
  16783     struct nk_window *popup;
  16784     struct nk_window *win;
  16785     struct nk_panel *panel;
  16786     int is_active = nk_true;
  16787 
  16788     NK_ASSERT(ctx);
  16789     NK_ASSERT(ctx->current);
  16790     NK_ASSERT(ctx->current->layout);
  16791     if (!ctx || !ctx->current || !ctx->current->layout)
  16792         return 0;
  16793 
  16794     /* popups cannot have popups */
  16795     win = ctx->current;
  16796     panel = win->layout;
  16797     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
  16798     (void)panel;
  16799     popup = win->popup.win;
  16800     if (!popup) {
  16801         /* create window for nonblocking popup */
  16802         popup = (struct nk_window*)nk_create_window(ctx);
  16803         popup->parent = win;
  16804         win->popup.win = popup;
  16805         win->popup.type = panel_type;
  16806         nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
  16807     } else {
  16808         /* close the popup if user pressed outside or in the header */
  16809         int pressed, in_body, in_header;
  16810         pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
  16811         in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
  16812         in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
  16813         if (pressed && (!in_body || in_header))
  16814             is_active = nk_false;
  16815     }
  16816     win->popup.header = header;
  16817 
  16818     if (!is_active) {
  16819         /* remove read only mode from all parent panels */
  16820         struct nk_panel *root = win->layout;
  16821         while (root) {
  16822             root->flags |= NK_WINDOW_REMOVE_ROM;
  16823             root = root->parent;
  16824         }
  16825         return is_active;
  16826     }
  16827     popup->bounds = body;
  16828     popup->parent = win;
  16829     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
  16830     popup->flags = flags;
  16831     popup->flags |= NK_WINDOW_BORDER;
  16832     popup->flags |= NK_WINDOW_DYNAMIC;
  16833     popup->seq = ctx->seq;
  16834     win->popup.active = 1;
  16835     NK_ASSERT(popup->layout);
  16836 
  16837     nk_start_popup(ctx, win);
  16838     popup->buffer = win->buffer;
  16839     nk_push_scissor(&popup->buffer, nk_null_rect);
  16840     ctx->current = popup;
  16841 
  16842     nk_panel_begin(ctx, 0, panel_type);
  16843     win->buffer = popup->buffer;
  16844     popup->layout->parent = win->layout;
  16845     popup->layout->offset_x = &popup->scrollbar.x;
  16846     popup->layout->offset_y = &popup->scrollbar.y;
  16847 
  16848     /* set read only mode to all parent panels */
  16849     {struct nk_panel *root;
  16850     root = win->layout;
  16851     while (root) {
  16852         root->flags |= NK_WINDOW_ROM;
  16853         root = root->parent;
  16854     }}
  16855     return is_active;
  16856 }
  16857 NK_API void
  16858 nk_popup_close(struct nk_context *ctx)
  16859 {
  16860     struct nk_window *popup;
  16861     NK_ASSERT(ctx);
  16862     if (!ctx || !ctx->current) return;
  16863 
  16864     popup = ctx->current;
  16865     NK_ASSERT(popup->parent);
  16866     NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
  16867     popup->flags |= NK_WINDOW_HIDDEN;
  16868 }
  16869 NK_API void
  16870 nk_popup_end(struct nk_context *ctx)
  16871 {
  16872     struct nk_window *win;
  16873     struct nk_window *popup;
  16874 
  16875     NK_ASSERT(ctx);
  16876     NK_ASSERT(ctx->current);
  16877     NK_ASSERT(ctx->current->layout);
  16878     if (!ctx || !ctx->current || !ctx->current->layout)
  16879         return;
  16880 
  16881     popup = ctx->current;
  16882     if (!popup->parent) return;
  16883     win = popup->parent;
  16884     if (popup->flags & NK_WINDOW_HIDDEN) {
  16885         struct nk_panel *root;
  16886         root = win->layout;
  16887         while (root) {
  16888             root->flags |= NK_WINDOW_REMOVE_ROM;
  16889             root = root->parent;
  16890         }
  16891         win->popup.active = 0;
  16892     }
  16893     nk_push_scissor(&popup->buffer, nk_null_rect);
  16894     nk_end(ctx);
  16895 
  16896     win->buffer = popup->buffer;
  16897     nk_finish_popup(ctx, win);
  16898     ctx->current = win;
  16899     nk_push_scissor(&win->buffer, win->layout->clip);
  16900 }
  16901 
  16902 
  16903 
  16904 
  16905 
  16906 /* ==============================================================
  16907  *
  16908  *                          CONTEXTUAL
  16909  *
  16910  * ===============================================================*/
  16911 NK_API int
  16912 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
  16913     struct nk_rect trigger_bounds)
  16914 {
  16915     struct nk_window *win;
  16916     struct nk_window *popup;
  16917     struct nk_rect body;
  16918 
  16919     NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0};
  16920     int is_clicked = 0;
  16921     int is_open = 0;
  16922     int ret = 0;
  16923 
  16924     NK_ASSERT(ctx);
  16925     NK_ASSERT(ctx->current);
  16926     NK_ASSERT(ctx->current->layout);
  16927     if (!ctx || !ctx->current || !ctx->current->layout)
  16928         return 0;
  16929 
  16930     win = ctx->current;
  16931     ++win->popup.con_count;
  16932     if (ctx->current != ctx->active)
  16933         return 0;
  16934 
  16935     /* check if currently active contextual is active */
  16936     popup = win->popup.win;
  16937     is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
  16938     is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
  16939     if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
  16940         return 0;
  16941     if (!is_open && win->popup.active_con)
  16942         win->popup.active_con = 0;
  16943     if ((!is_open && !is_clicked))
  16944         return 0;
  16945 
  16946     /* calculate contextual position on click */
  16947     win->popup.active_con = win->popup.con_count;
  16948     if (is_clicked) {
  16949         body.x = ctx->input.mouse.pos.x;
  16950         body.y = ctx->input.mouse.pos.y;
  16951     } else {
  16952         body.x = popup->bounds.x;
  16953         body.y = popup->bounds.y;
  16954     }
  16955     body.w = size.x;
  16956     body.h = size.y;
  16957 
  16958     /* start nonblocking contextual popup */
  16959     ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
  16960             null_rect, NK_PANEL_CONTEXTUAL);
  16961     if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
  16962     else {
  16963         win->popup.active_con = 0;
  16964         win->popup.type = NK_PANEL_NONE;
  16965         if (win->popup.win)
  16966             win->popup.win->flags = 0;
  16967     }
  16968     return ret;
  16969 }
  16970 NK_API int
  16971 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
  16972     nk_flags alignment)
  16973 {
  16974     struct nk_window *win;
  16975     const struct nk_input *in;
  16976     const struct nk_style *style;
  16977 
  16978     struct nk_rect bounds;
  16979     enum nk_widget_layout_states state;
  16980 
  16981     NK_ASSERT(ctx);
  16982     NK_ASSERT(ctx->current);
  16983     NK_ASSERT(ctx->current->layout);
  16984     if (!ctx || !ctx->current || !ctx->current->layout)
  16985         return 0;
  16986 
  16987     win = ctx->current;
  16988     style = &ctx->style;
  16989     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
  16990     if (!state) return nk_false;
  16991 
  16992     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  16993     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
  16994         text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
  16995         nk_contextual_close(ctx);
  16996         return nk_true;
  16997     }
  16998     return nk_false;
  16999 }
  17000 NK_API int
  17001 nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
  17002 {
  17003     return nk_contextual_item_text(ctx, label, nk_strlen(label), align);
  17004 }
  17005 NK_API int
  17006 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
  17007     const char *text, int len, nk_flags align)
  17008 {
  17009     struct nk_window *win;
  17010     const struct nk_input *in;
  17011     const struct nk_style *style;
  17012 
  17013     struct nk_rect bounds;
  17014     enum nk_widget_layout_states state;
  17015 
  17016     NK_ASSERT(ctx);
  17017     NK_ASSERT(ctx->current);
  17018     NK_ASSERT(ctx->current->layout);
  17019     if (!ctx || !ctx->current || !ctx->current->layout)
  17020         return 0;
  17021 
  17022     win = ctx->current;
  17023     style = &ctx->style;
  17024     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
  17025     if (!state) return nk_false;
  17026 
  17027     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  17028     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
  17029         img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
  17030         nk_contextual_close(ctx);
  17031         return nk_true;
  17032     }
  17033     return nk_false;
  17034 }
  17035 NK_API int
  17036 nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
  17037     const char *label, nk_flags align)
  17038 {
  17039     return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);
  17040 }
  17041 NK_API int
  17042 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
  17043     const char *text, int len, nk_flags align)
  17044 {
  17045     struct nk_window *win;
  17046     const struct nk_input *in;
  17047     const struct nk_style *style;
  17048 
  17049     struct nk_rect bounds;
  17050     enum nk_widget_layout_states state;
  17051 
  17052     NK_ASSERT(ctx);
  17053     NK_ASSERT(ctx->current);
  17054     NK_ASSERT(ctx->current->layout);
  17055     if (!ctx || !ctx->current || !ctx->current->layout)
  17056         return 0;
  17057 
  17058     win = ctx->current;
  17059     style = &ctx->style;
  17060     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
  17061     if (!state) return nk_false;
  17062 
  17063     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  17064     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
  17065         symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
  17066         nk_contextual_close(ctx);
  17067         return nk_true;
  17068     }
  17069     return nk_false;
  17070 }
  17071 NK_API int
  17072 nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
  17073     const char *text, nk_flags align)
  17074 {
  17075     return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);
  17076 }
  17077 NK_API void
  17078 nk_contextual_close(struct nk_context *ctx)
  17079 {
  17080     NK_ASSERT(ctx);
  17081     NK_ASSERT(ctx->current);
  17082     NK_ASSERT(ctx->current->layout);
  17083     if (!ctx || !ctx->current || !ctx->current->layout) return;
  17084     nk_popup_close(ctx);
  17085 }
  17086 NK_API void
  17087 nk_contextual_end(struct nk_context *ctx)
  17088 {
  17089     struct nk_window *popup;
  17090     struct nk_panel *panel;
  17091     NK_ASSERT(ctx);
  17092     NK_ASSERT(ctx->current);
  17093     if (!ctx || !ctx->current) return;
  17094 
  17095     popup = ctx->current;
  17096     panel = popup->layout;
  17097     NK_ASSERT(popup->parent);
  17098     NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
  17099     if (panel->flags & NK_WINDOW_DYNAMIC) {
  17100         /* Close behavior
  17101         This is a bit of a hack solution since we do not know before we end our popup
  17102         how big it will be. We therefore do not directly know when a
  17103         click outside the non-blocking popup must close it at that direct frame.
  17104         Instead it will be closed in the next frame.*/
  17105         struct nk_rect body = {0,0,0,0};
  17106         if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
  17107             struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
  17108             body = panel->bounds;
  17109             body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
  17110             body.h = (panel->bounds.y + panel->bounds.h) - body.y;
  17111         }
  17112         {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
  17113         int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
  17114         if (pressed && in_body)
  17115             popup->flags |= NK_WINDOW_HIDDEN;
  17116         }
  17117     }
  17118     if (popup->flags & NK_WINDOW_HIDDEN)
  17119         popup->seq = 0;
  17120     nk_popup_end(ctx);
  17121     return;
  17122 }
  17123 
  17124 
  17125 
  17126 
  17127 
  17128 /* ===============================================================
  17129  *
  17130  *                              MENU
  17131  *
  17132  * ===============================================================*/
  17133 NK_API void
  17134 nk_menubar_begin(struct nk_context *ctx)
  17135 {
  17136     struct nk_panel *layout;
  17137     NK_ASSERT(ctx);
  17138     NK_ASSERT(ctx->current);
  17139     NK_ASSERT(ctx->current->layout);
  17140     if (!ctx || !ctx->current || !ctx->current->layout)
  17141         return;
  17142 
  17143     layout = ctx->current->layout;
  17144     NK_ASSERT(layout->at_y == layout->bounds.y);
  17145     /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
  17146     If you want a menubar the first nuklear function after `nk_begin` has to be a
  17147     `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
  17148     widgets (also supports multiple rows).
  17149     Example:
  17150         if (nk_begin(...)) {
  17151             nk_menubar_begin(...);
  17152                 nk_layout_xxxx(...);
  17153                 nk_button(...);
  17154                 nk_layout_xxxx(...);
  17155                 nk_button(...);
  17156             nk_menubar_end(...);
  17157         }
  17158         nk_end(...);
  17159     */
  17160     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
  17161         return;
  17162 
  17163     layout->menu.x = layout->at_x;
  17164     layout->menu.y = layout->at_y + layout->row.height;
  17165     layout->menu.w = layout->bounds.w;
  17166     layout->menu.offset.x = *layout->offset_x;
  17167     layout->menu.offset.y = *layout->offset_y;
  17168     *layout->offset_y = 0;
  17169 }
  17170 NK_API void
  17171 nk_menubar_end(struct nk_context *ctx)
  17172 {
  17173     struct nk_window *win;
  17174     struct nk_panel *layout;
  17175     struct nk_command_buffer *out;
  17176 
  17177     NK_ASSERT(ctx);
  17178     NK_ASSERT(ctx->current);
  17179     NK_ASSERT(ctx->current->layout);
  17180     if (!ctx || !ctx->current || !ctx->current->layout)
  17181         return;
  17182 
  17183     win = ctx->current;
  17184     out = &win->buffer;
  17185     layout = win->layout;
  17186     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
  17187         return;
  17188 
  17189     layout->menu.h = layout->at_y - layout->menu.y;
  17190     layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
  17191     layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
  17192 
  17193     *layout->offset_x = layout->menu.offset.x;
  17194     *layout->offset_y = layout->menu.offset.y;
  17195     layout->at_y = layout->bounds.y - layout->row.height;
  17196 
  17197     layout->clip.y = layout->bounds.y;
  17198     layout->clip.h = layout->bounds.h;
  17199     nk_push_scissor(out, layout->clip);
  17200 }
  17201 NK_INTERN int
  17202 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
  17203     const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
  17204 {
  17205     int is_open = 0;
  17206     int is_active = 0;
  17207     struct nk_rect body;
  17208     struct nk_window *popup;
  17209     nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
  17210 
  17211     NK_ASSERT(ctx);
  17212     NK_ASSERT(ctx->current);
  17213     NK_ASSERT(ctx->current->layout);
  17214     if (!ctx || !ctx->current || !ctx->current->layout)
  17215         return 0;
  17216 
  17217     body.x = header.x;
  17218     body.w = size.x;
  17219     body.y = header.y + header.h;
  17220     body.h = size.y;
  17221 
  17222     popup = win->popup.win;
  17223     is_open = popup ? nk_true : nk_false;
  17224     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
  17225     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
  17226         (!is_open && !is_active && !is_clicked)) return 0;
  17227     if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
  17228         return 0;
  17229 
  17230     win->popup.type = NK_PANEL_MENU;
  17231     win->popup.name = hash;
  17232     return 1;
  17233 }
  17234 NK_API int
  17235 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
  17236     nk_flags align, struct nk_vec2 size)
  17237 {
  17238     struct nk_window *win;
  17239     const struct nk_input *in;
  17240     struct nk_rect header;
  17241     int is_clicked = nk_false;
  17242     nk_flags state;
  17243 
  17244     NK_ASSERT(ctx);
  17245     NK_ASSERT(ctx->current);
  17246     NK_ASSERT(ctx->current->layout);
  17247     if (!ctx || !ctx->current || !ctx->current->layout)
  17248         return 0;
  17249 
  17250     win = ctx->current;
  17251     state = nk_widget(&header, ctx);
  17252     if (!state) return 0;
  17253     in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  17254     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
  17255         title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
  17256         is_clicked = nk_true;
  17257     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  17258 }
  17259 NK_API int nk_menu_begin_label(struct nk_context *ctx,
  17260     const char *text, nk_flags align, struct nk_vec2 size)
  17261 {
  17262     return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);
  17263 }
  17264 NK_API int
  17265 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
  17266     struct nk_vec2 size)
  17267 {
  17268     struct nk_window *win;
  17269     struct nk_rect header;
  17270     const struct nk_input *in;
  17271     int is_clicked = nk_false;
  17272     nk_flags state;
  17273 
  17274     NK_ASSERT(ctx);
  17275     NK_ASSERT(ctx->current);
  17276     NK_ASSERT(ctx->current->layout);
  17277     if (!ctx || !ctx->current || !ctx->current->layout)
  17278         return 0;
  17279 
  17280     win = ctx->current;
  17281     state = nk_widget(&header, ctx);
  17282     if (!state) return 0;
  17283     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  17284     if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
  17285         img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
  17286         is_clicked = nk_true;
  17287     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
  17288 }
  17289 NK_API int
  17290 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
  17291     enum nk_symbol_type sym, struct nk_vec2 size)
  17292 {
  17293     struct nk_window *win;
  17294     const struct nk_input *in;
  17295     struct nk_rect header;
  17296     int is_clicked = nk_false;
  17297     nk_flags state;
  17298 
  17299     NK_ASSERT(ctx);
  17300     NK_ASSERT(ctx->current);
  17301     NK_ASSERT(ctx->current->layout);
  17302     if (!ctx || !ctx->current || !ctx->current->layout)
  17303         return 0;
  17304 
  17305     win = ctx->current;
  17306     state = nk_widget(&header, ctx);
  17307     if (!state) return 0;
  17308     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  17309     if (nk_do_button_symbol(&ctx->last_widget_state,  &win->buffer, header,
  17310         sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
  17311         is_clicked = nk_true;
  17312     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
  17313 }
  17314 NK_API int
  17315 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
  17316     nk_flags align, struct nk_image img, struct nk_vec2 size)
  17317 {
  17318     struct nk_window *win;
  17319     struct nk_rect header;
  17320     const struct nk_input *in;
  17321     int is_clicked = nk_false;
  17322     nk_flags state;
  17323 
  17324     NK_ASSERT(ctx);
  17325     NK_ASSERT(ctx->current);
  17326     NK_ASSERT(ctx->current->layout);
  17327     if (!ctx || !ctx->current || !ctx->current->layout)
  17328         return 0;
  17329 
  17330     win = ctx->current;
  17331     state = nk_widget(&header, ctx);
  17332     if (!state) return 0;
  17333     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  17334     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
  17335         header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
  17336         ctx->style.font, in))
  17337         is_clicked = nk_true;
  17338     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  17339 }
  17340 NK_API int
  17341 nk_menu_begin_image_label(struct nk_context *ctx,
  17342     const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
  17343 {
  17344     return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);
  17345 }
  17346 NK_API int
  17347 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
  17348     nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
  17349 {
  17350     struct nk_window *win;
  17351     struct nk_rect header;
  17352     const struct nk_input *in;
  17353     int is_clicked = nk_false;
  17354     nk_flags state;
  17355 
  17356     NK_ASSERT(ctx);
  17357     NK_ASSERT(ctx->current);
  17358     NK_ASSERT(ctx->current->layout);
  17359     if (!ctx || !ctx->current || !ctx->current->layout)
  17360         return 0;
  17361 
  17362     win = ctx->current;
  17363     state = nk_widget(&header, ctx);
  17364     if (!state) return 0;
  17365 
  17366     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  17367     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
  17368         header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
  17369         ctx->style.font, in)) is_clicked = nk_true;
  17370     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
  17371 }
  17372 NK_API int
  17373 nk_menu_begin_symbol_label(struct nk_context *ctx,
  17374     const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
  17375 {
  17376     return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);
  17377 }
  17378 NK_API int
  17379 nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
  17380 {
  17381     return nk_contextual_item_text(ctx, title, len, align);
  17382 }
  17383 NK_API int
  17384 nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
  17385 {
  17386     return nk_contextual_item_label(ctx, label, align);
  17387 }
  17388 NK_API int
  17389 nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
  17390     const char *label, nk_flags align)
  17391 {
  17392     return nk_contextual_item_image_label(ctx, img, label, align);
  17393 }
  17394 NK_API int
  17395 nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
  17396     const char *text, int len, nk_flags align)
  17397 {
  17398     return nk_contextual_item_image_text(ctx, img, text, len, align);
  17399 }
  17400 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  17401     const char *text, int len, nk_flags align)
  17402 {
  17403     return nk_contextual_item_symbol_text(ctx, sym, text, len, align);
  17404 }
  17405 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  17406     const char *label, nk_flags align)
  17407 {
  17408     return nk_contextual_item_symbol_label(ctx, sym, label, align);
  17409 }
  17410 NK_API void nk_menu_close(struct nk_context *ctx)
  17411 {
  17412     nk_contextual_close(ctx);
  17413 }
  17414 NK_API void
  17415 nk_menu_end(struct nk_context *ctx)
  17416 {
  17417     nk_contextual_end(ctx);
  17418 }
  17419 
  17420 
  17421 
  17422 
  17423 
  17424 /* ===============================================================
  17425  *
  17426  *                          LAYOUT
  17427  *
  17428  * ===============================================================*/
  17429 NK_API void
  17430 nk_layout_set_min_row_height(struct nk_context *ctx, float height)
  17431 {
  17432     struct nk_window *win;
  17433     struct nk_panel *layout;
  17434 
  17435     NK_ASSERT(ctx);
  17436     NK_ASSERT(ctx->current);
  17437     NK_ASSERT(ctx->current->layout);
  17438     if (!ctx || !ctx->current || !ctx->current->layout)
  17439         return;
  17440 
  17441     win = ctx->current;
  17442     layout = win->layout;
  17443     layout->row.min_height = height;
  17444 }
  17445 NK_API void
  17446 nk_layout_reset_min_row_height(struct nk_context *ctx)
  17447 {
  17448     struct nk_window *win;
  17449     struct nk_panel *layout;
  17450 
  17451     NK_ASSERT(ctx);
  17452     NK_ASSERT(ctx->current);
  17453     NK_ASSERT(ctx->current->layout);
  17454     if (!ctx || !ctx->current || !ctx->current->layout)
  17455         return;
  17456 
  17457     win = ctx->current;
  17458     layout = win->layout;
  17459     layout->row.min_height = ctx->style.font->height;
  17460     layout->row.min_height += ctx->style.text.padding.y*2;
  17461     layout->row.min_height += ctx->style.window.min_row_height_padding*2;
  17462 }
  17463 NK_LIB float
  17464 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
  17465     float total_space, int columns)
  17466 {
  17467     float panel_padding;
  17468     float panel_spacing;
  17469     float panel_space;
  17470 
  17471     struct nk_vec2 spacing;
  17472     struct nk_vec2 padding;
  17473 
  17474     spacing = style->window.spacing;
  17475     padding = nk_panel_get_padding(style, type);
  17476 
  17477     /* calculate the usable panel space */
  17478     panel_padding = 2 * padding.x;
  17479     panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
  17480     panel_space  = total_space - panel_padding - panel_spacing;
  17481     return panel_space;
  17482 }
  17483 NK_LIB void
  17484 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
  17485     float height, int cols)
  17486 {
  17487     struct nk_panel *layout;
  17488     const struct nk_style *style;
  17489     struct nk_command_buffer *out;
  17490 
  17491     struct nk_vec2 item_spacing;
  17492     struct nk_color color;
  17493 
  17494     NK_ASSERT(ctx);
  17495     NK_ASSERT(ctx->current);
  17496     NK_ASSERT(ctx->current->layout);
  17497     if (!ctx || !ctx->current || !ctx->current->layout)
  17498         return;
  17499 
  17500     /* prefetch some configuration data */
  17501     layout = win->layout;
  17502     style = &ctx->style;
  17503     out = &win->buffer;
  17504     color = style->window.background;
  17505     item_spacing = style->window.spacing;
  17506 
  17507     /*  if one of these triggers you forgot to add an `if` condition around either
  17508         a window, group, popup, combobox or contextual menu `begin` and `end` block.
  17509         Example:
  17510             if (nk_begin(...) {...} nk_end(...); or
  17511             if (nk_group_begin(...) { nk_group_end(...);} */
  17512     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
  17513     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
  17514     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
  17515 
  17516     /* update the current row and set the current row layout */
  17517     layout->row.index = 0;
  17518     layout->at_y += layout->row.height;
  17519     layout->row.columns = cols;
  17520     if (height == 0.0f)
  17521         layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
  17522     else layout->row.height = height + item_spacing.y;
  17523 
  17524     layout->row.item_offset = 0;
  17525     if (layout->flags & NK_WINDOW_DYNAMIC) {
  17526         /* draw background for dynamic panels */
  17527         struct nk_rect background;
  17528         background.x = win->bounds.x;
  17529         background.w = win->bounds.w;
  17530         background.y = layout->at_y - 1.0f;
  17531         background.h = layout->row.height + 1.0f;
  17532         nk_fill_rect(out, background, 0, color);
  17533     }
  17534 }
  17535 NK_LIB void
  17536 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
  17537     float height, int cols, int width)
  17538 {
  17539     /* update the current row and set the current row layout */
  17540     struct nk_window *win;
  17541     NK_ASSERT(ctx);
  17542     NK_ASSERT(ctx->current);
  17543     NK_ASSERT(ctx->current->layout);
  17544     if (!ctx || !ctx->current || !ctx->current->layout)
  17545         return;
  17546 
  17547     win = ctx->current;
  17548     nk_panel_layout(ctx, win, height, cols);
  17549     if (fmt == NK_DYNAMIC)
  17550         win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED;
  17551     else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
  17552 
  17553     win->layout->row.ratio = 0;
  17554     win->layout->row.filled = 0;
  17555     win->layout->row.item_offset = 0;
  17556     win->layout->row.item_width = (float)width;
  17557 }
  17558 NK_API float
  17559 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
  17560 {
  17561     struct nk_window *win;
  17562     NK_ASSERT(ctx);
  17563     NK_ASSERT(pixel_width);
  17564     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
  17565     win = ctx->current;
  17566     return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
  17567 }
  17568 NK_API void
  17569 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
  17570 {
  17571     nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
  17572 }
  17573 NK_API void
  17574 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
  17575 {
  17576     nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
  17577 }
  17578 NK_API void
  17579 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
  17580     float row_height, int cols)
  17581 {
  17582     struct nk_window *win;
  17583     struct nk_panel *layout;
  17584 
  17585     NK_ASSERT(ctx);
  17586     NK_ASSERT(ctx->current);
  17587     NK_ASSERT(ctx->current->layout);
  17588     if (!ctx || !ctx->current || !ctx->current->layout)
  17589         return;
  17590 
  17591     win = ctx->current;
  17592     layout = win->layout;
  17593     nk_panel_layout(ctx, win, row_height, cols);
  17594     if (fmt == NK_DYNAMIC)
  17595         layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
  17596     else layout->row.type = NK_LAYOUT_STATIC_ROW;
  17597 
  17598     layout->row.ratio = 0;
  17599     layout->row.filled = 0;
  17600     layout->row.item_width = 0;
  17601     layout->row.item_offset = 0;
  17602     layout->row.columns = cols;
  17603 }
  17604 NK_API void
  17605 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
  17606 {
  17607     struct nk_window *win;
  17608     struct nk_panel *layout;
  17609 
  17610     NK_ASSERT(ctx);
  17611     NK_ASSERT(ctx->current);
  17612     NK_ASSERT(ctx->current->layout);
  17613     if (!ctx || !ctx->current || !ctx->current->layout)
  17614         return;
  17615 
  17616     win = ctx->current;
  17617     layout = win->layout;
  17618     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
  17619     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
  17620         return;
  17621 
  17622     if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
  17623         float ratio = ratio_or_width;
  17624         if ((ratio + layout->row.filled) > 1.0f) return;
  17625         if (ratio > 0.0f)
  17626             layout->row.item_width = NK_SATURATE(ratio);
  17627         else layout->row.item_width = 1.0f - layout->row.filled;
  17628     } else layout->row.item_width = ratio_or_width;
  17629 }
  17630 NK_API void
  17631 nk_layout_row_end(struct nk_context *ctx)
  17632 {
  17633     struct nk_window *win;
  17634     struct nk_panel *layout;
  17635 
  17636     NK_ASSERT(ctx);
  17637     NK_ASSERT(ctx->current);
  17638     NK_ASSERT(ctx->current->layout);
  17639     if (!ctx || !ctx->current || !ctx->current->layout)
  17640         return;
  17641 
  17642     win = ctx->current;
  17643     layout = win->layout;
  17644     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
  17645     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
  17646         return;
  17647     layout->row.item_width = 0;
  17648     layout->row.item_offset = 0;
  17649 }
  17650 NK_API void
  17651 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
  17652     float height, int cols, const float *ratio)
  17653 {
  17654     int i;
  17655     int n_undef = 0;
  17656     struct nk_window *win;
  17657     struct nk_panel *layout;
  17658 
  17659     NK_ASSERT(ctx);
  17660     NK_ASSERT(ctx->current);
  17661     NK_ASSERT(ctx->current->layout);
  17662     if (!ctx || !ctx->current || !ctx->current->layout)
  17663         return;
  17664 
  17665     win = ctx->current;
  17666     layout = win->layout;
  17667     nk_panel_layout(ctx, win, height, cols);
  17668     if (fmt == NK_DYNAMIC) {
  17669         /* calculate width of undefined widget ratios */
  17670         float r = 0;
  17671         layout->row.ratio = ratio;
  17672         for (i = 0; i < cols; ++i) {
  17673             if (ratio[i] < 0.0f)
  17674                 n_undef++;
  17675             else r += ratio[i];
  17676         }
  17677         r = NK_SATURATE(1.0f - r);
  17678         layout->row.type = NK_LAYOUT_DYNAMIC;
  17679         layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
  17680     } else {
  17681         layout->row.ratio = ratio;
  17682         layout->row.type = NK_LAYOUT_STATIC;
  17683         layout->row.item_width = 0;
  17684         layout->row.item_offset = 0;
  17685     }
  17686     layout->row.item_offset = 0;
  17687     layout->row.filled = 0;
  17688 }
  17689 NK_API void
  17690 nk_layout_row_template_begin(struct nk_context *ctx, float height)
  17691 {
  17692     struct nk_window *win;
  17693     struct nk_panel *layout;
  17694 
  17695     NK_ASSERT(ctx);
  17696     NK_ASSERT(ctx->current);
  17697     NK_ASSERT(ctx->current->layout);
  17698     if (!ctx || !ctx->current || !ctx->current->layout)
  17699         return;
  17700 
  17701     win = ctx->current;
  17702     layout = win->layout;
  17703     nk_panel_layout(ctx, win, height, 1);
  17704     layout->row.type = NK_LAYOUT_TEMPLATE;
  17705     layout->row.columns = 0;
  17706     layout->row.ratio = 0;
  17707     layout->row.item_width = 0;
  17708     layout->row.item_height = 0;
  17709     layout->row.item_offset = 0;
  17710     layout->row.filled = 0;
  17711     layout->row.item.x = 0;
  17712     layout->row.item.y = 0;
  17713     layout->row.item.w = 0;
  17714     layout->row.item.h = 0;
  17715 }
  17716 NK_API void
  17717 nk_layout_row_template_push_dynamic(struct nk_context *ctx)
  17718 {
  17719     struct nk_window *win;
  17720     struct nk_panel *layout;
  17721 
  17722     NK_ASSERT(ctx);
  17723     NK_ASSERT(ctx->current);
  17724     NK_ASSERT(ctx->current->layout);
  17725     if (!ctx || !ctx->current || !ctx->current->layout)
  17726         return;
  17727 
  17728     win = ctx->current;
  17729     layout = win->layout;
  17730     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
  17731     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
  17732     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
  17733     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
  17734     layout->row.templates[layout->row.columns++] = -1.0f;
  17735 }
  17736 NK_API void
  17737 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
  17738 {
  17739     struct nk_window *win;
  17740     struct nk_panel *layout;
  17741 
  17742     NK_ASSERT(ctx);
  17743     NK_ASSERT(ctx->current);
  17744     NK_ASSERT(ctx->current->layout);
  17745     if (!ctx || !ctx->current || !ctx->current->layout)
  17746         return;
  17747 
  17748     win = ctx->current;
  17749     layout = win->layout;
  17750     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
  17751     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
  17752     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
  17753     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
  17754     layout->row.templates[layout->row.columns++] = -min_width;
  17755 }
  17756 NK_API void
  17757 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
  17758 {
  17759     struct nk_window *win;
  17760     struct nk_panel *layout;
  17761 
  17762     NK_ASSERT(ctx);
  17763     NK_ASSERT(ctx->current);
  17764     NK_ASSERT(ctx->current->layout);
  17765     if (!ctx || !ctx->current || !ctx->current->layout)
  17766         return;
  17767 
  17768     win = ctx->current;
  17769     layout = win->layout;
  17770     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
  17771     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
  17772     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
  17773     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
  17774     layout->row.templates[layout->row.columns++] = width;
  17775 }
  17776 NK_API void
  17777 nk_layout_row_template_end(struct nk_context *ctx)
  17778 {
  17779     struct nk_window *win;
  17780     struct nk_panel *layout;
  17781 
  17782     int i = 0;
  17783     int variable_count = 0;
  17784     int min_variable_count = 0;
  17785     float min_fixed_width = 0.0f;
  17786     float total_fixed_width = 0.0f;
  17787     float max_variable_width = 0.0f;
  17788 
  17789     NK_ASSERT(ctx);
  17790     NK_ASSERT(ctx->current);
  17791     NK_ASSERT(ctx->current->layout);
  17792     if (!ctx || !ctx->current || !ctx->current->layout)
  17793         return;
  17794 
  17795     win = ctx->current;
  17796     layout = win->layout;
  17797     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
  17798     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
  17799     for (i = 0; i < layout->row.columns; ++i) {
  17800         float width = layout->row.templates[i];
  17801         if (width >= 0.0f) {
  17802             total_fixed_width += width;
  17803             min_fixed_width += width;
  17804         } else if (width < -1.0f) {
  17805             width = -width;
  17806             total_fixed_width += width;
  17807             max_variable_width = NK_MAX(max_variable_width, width);
  17808             variable_count++;
  17809         } else {
  17810             min_variable_count++;
  17811             variable_count++;
  17812         }
  17813     }
  17814     if (variable_count) {
  17815         float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
  17816                             layout->bounds.w, layout->row.columns);
  17817         float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
  17818         int enough_space = var_width >= max_variable_width;
  17819         if (!enough_space)
  17820             var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
  17821         for (i = 0; i < layout->row.columns; ++i) {
  17822             float *width = &layout->row.templates[i];
  17823             *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
  17824         }
  17825     }
  17826 }
  17827 NK_API void
  17828 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
  17829     float height, int widget_count)
  17830 {
  17831     struct nk_window *win;
  17832     struct nk_panel *layout;
  17833 
  17834     NK_ASSERT(ctx);
  17835     NK_ASSERT(ctx->current);
  17836     NK_ASSERT(ctx->current->layout);
  17837     if (!ctx || !ctx->current || !ctx->current->layout)
  17838         return;
  17839 
  17840     win = ctx->current;
  17841     layout = win->layout;
  17842     nk_panel_layout(ctx, win, height, widget_count);
  17843     if (fmt == NK_STATIC)
  17844         layout->row.type = NK_LAYOUT_STATIC_FREE;
  17845     else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
  17846 
  17847     layout->row.ratio = 0;
  17848     layout->row.filled = 0;
  17849     layout->row.item_width = 0;
  17850     layout->row.item_offset = 0;
  17851 }
  17852 NK_API void
  17853 nk_layout_space_end(struct nk_context *ctx)
  17854 {
  17855     struct nk_window *win;
  17856     struct nk_panel *layout;
  17857 
  17858     NK_ASSERT(ctx);
  17859     NK_ASSERT(ctx->current);
  17860     NK_ASSERT(ctx->current->layout);
  17861     if (!ctx || !ctx->current || !ctx->current->layout)
  17862         return;
  17863 
  17864     win = ctx->current;
  17865     layout = win->layout;
  17866     layout->row.item_width = 0;
  17867     layout->row.item_height = 0;
  17868     layout->row.item_offset = 0;
  17869     nk_zero(&layout->row.item, sizeof(layout->row.item));
  17870 }
  17871 NK_API void
  17872 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
  17873 {
  17874     struct nk_window *win;
  17875     struct nk_panel *layout;
  17876 
  17877     NK_ASSERT(ctx);
  17878     NK_ASSERT(ctx->current);
  17879     NK_ASSERT(ctx->current->layout);
  17880     if (!ctx || !ctx->current || !ctx->current->layout)
  17881         return;
  17882 
  17883     win = ctx->current;
  17884     layout = win->layout;
  17885     layout->row.item = rect;
  17886 }
  17887 NK_API struct nk_rect
  17888 nk_layout_space_bounds(struct nk_context *ctx)
  17889 {
  17890     struct nk_rect ret;
  17891     struct nk_window *win;
  17892     struct nk_panel *layout;
  17893 
  17894     NK_ASSERT(ctx);
  17895     NK_ASSERT(ctx->current);
  17896     NK_ASSERT(ctx->current->layout);
  17897     win = ctx->current;
  17898     layout = win->layout;
  17899 
  17900     ret.x = layout->clip.x;
  17901     ret.y = layout->clip.y;
  17902     ret.w = layout->clip.w;
  17903     ret.h = layout->row.height;
  17904     return ret;
  17905 }
  17906 NK_API struct nk_rect
  17907 nk_layout_widget_bounds(struct nk_context *ctx)
  17908 {
  17909     struct nk_rect ret;
  17910     struct nk_window *win;
  17911     struct nk_panel *layout;
  17912 
  17913     NK_ASSERT(ctx);
  17914     NK_ASSERT(ctx->current);
  17915     NK_ASSERT(ctx->current->layout);
  17916     win = ctx->current;
  17917     layout = win->layout;
  17918 
  17919     ret.x = layout->at_x;
  17920     ret.y = layout->at_y;
  17921     ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
  17922     ret.h = layout->row.height;
  17923     return ret;
  17924 }
  17925 NK_API struct nk_vec2
  17926 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
  17927 {
  17928     struct nk_window *win;
  17929     struct nk_panel *layout;
  17930 
  17931     NK_ASSERT(ctx);
  17932     NK_ASSERT(ctx->current);
  17933     NK_ASSERT(ctx->current->layout);
  17934     win = ctx->current;
  17935     layout = win->layout;
  17936 
  17937     ret.x += layout->at_x - (float)*layout->offset_x;
  17938     ret.y += layout->at_y - (float)*layout->offset_y;
  17939     return ret;
  17940 }
  17941 NK_API struct nk_vec2
  17942 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
  17943 {
  17944     struct nk_window *win;
  17945     struct nk_panel *layout;
  17946 
  17947     NK_ASSERT(ctx);
  17948     NK_ASSERT(ctx->current);
  17949     NK_ASSERT(ctx->current->layout);
  17950     win = ctx->current;
  17951     layout = win->layout;
  17952 
  17953     ret.x += -layout->at_x + (float)*layout->offset_x;
  17954     ret.y += -layout->at_y + (float)*layout->offset_y;
  17955     return ret;
  17956 }
  17957 NK_API struct nk_rect
  17958 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret)
  17959 {
  17960     struct nk_window *win;
  17961     struct nk_panel *layout;
  17962 
  17963     NK_ASSERT(ctx);
  17964     NK_ASSERT(ctx->current);
  17965     NK_ASSERT(ctx->current->layout);
  17966     win = ctx->current;
  17967     layout = win->layout;
  17968 
  17969     ret.x += layout->at_x - (float)*layout->offset_x;
  17970     ret.y += layout->at_y - (float)*layout->offset_y;
  17971     return ret;
  17972 }
  17973 NK_API struct nk_rect
  17974 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret)
  17975 {
  17976     struct nk_window *win;
  17977     struct nk_panel *layout;
  17978 
  17979     NK_ASSERT(ctx);
  17980     NK_ASSERT(ctx->current);
  17981     NK_ASSERT(ctx->current->layout);
  17982     win = ctx->current;
  17983     layout = win->layout;
  17984 
  17985     ret.x += -layout->at_x + (float)*layout->offset_x;
  17986     ret.y += -layout->at_y + (float)*layout->offset_y;
  17987     return ret;
  17988 }
  17989 NK_LIB void
  17990 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
  17991 {
  17992     struct nk_panel *layout = win->layout;
  17993     struct nk_vec2 spacing = ctx->style.window.spacing;
  17994     const float row_height = layout->row.height - spacing.y;
  17995     nk_panel_layout(ctx, win, row_height, layout->row.columns);
  17996 }
  17997 NK_LIB void
  17998 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
  17999     struct nk_window *win, int modify)
  18000 {
  18001     struct nk_panel *layout;
  18002     const struct nk_style *style;
  18003 
  18004     struct nk_vec2 spacing;
  18005     struct nk_vec2 padding;
  18006 
  18007     float item_offset = 0;
  18008     float item_width = 0;
  18009     float item_spacing = 0;
  18010     float panel_space = 0;
  18011 
  18012     NK_ASSERT(ctx);
  18013     NK_ASSERT(ctx->current);
  18014     NK_ASSERT(ctx->current->layout);
  18015     if (!ctx || !ctx->current || !ctx->current->layout)
  18016         return;
  18017 
  18018     win = ctx->current;
  18019     layout = win->layout;
  18020     style = &ctx->style;
  18021     NK_ASSERT(bounds);
  18022 
  18023     spacing = style->window.spacing;
  18024     padding = nk_panel_get_padding(style, layout->type);
  18025     panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
  18026                                             layout->bounds.w, layout->row.columns);
  18027 
  18028     /* calculate the width of one item inside the current layout space */
  18029     switch (layout->row.type) {
  18030     case NK_LAYOUT_DYNAMIC_FIXED: {
  18031         /* scaling fixed size widgets item width */
  18032         item_width = NK_MAX(1.0f,panel_space) / (float)layout->row.columns;
  18033         item_offset = (float)layout->row.index * item_width;
  18034         item_spacing = (float)layout->row.index * spacing.x;
  18035     } break;
  18036     case NK_LAYOUT_DYNAMIC_ROW: {
  18037         /* scaling single ratio widget width */
  18038         item_width = layout->row.item_width * panel_space;
  18039         item_offset = layout->row.item_offset;
  18040         item_spacing = 0;
  18041 
  18042         if (modify) {
  18043             layout->row.item_offset += item_width + spacing.x;
  18044             layout->row.filled += layout->row.item_width;
  18045             layout->row.index = 0;
  18046         }
  18047     } break;
  18048     case NK_LAYOUT_DYNAMIC_FREE: {
  18049         /* panel width depended free widget placing */
  18050         bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
  18051         bounds->x -= (float)*layout->offset_x;
  18052         bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
  18053         bounds->y -= (float)*layout->offset_y;
  18054         bounds->w = layout->bounds.w  * layout->row.item.w;
  18055         bounds->h = layout->row.height * layout->row.item.h;
  18056         return;
  18057     }
  18058     case NK_LAYOUT_DYNAMIC: {
  18059         /* scaling arrays of panel width ratios for every widget */
  18060         float ratio;
  18061         NK_ASSERT(layout->row.ratio);
  18062         ratio = (layout->row.ratio[layout->row.index] < 0) ?
  18063             layout->row.item_width : layout->row.ratio[layout->row.index];
  18064 
  18065         item_spacing = (float)layout->row.index * spacing.x;
  18066         item_width = (ratio * panel_space);
  18067         item_offset = layout->row.item_offset;
  18068 
  18069         if (modify) {
  18070             layout->row.item_offset += item_width;
  18071             layout->row.filled += ratio;
  18072         }
  18073     } break;
  18074     case NK_LAYOUT_STATIC_FIXED: {
  18075         /* non-scaling fixed widgets item width */
  18076         item_width = layout->row.item_width;
  18077         item_offset = (float)layout->row.index * item_width;
  18078         item_spacing = (float)layout->row.index * spacing.x;
  18079     } break;
  18080     case NK_LAYOUT_STATIC_ROW: {
  18081         /* scaling single ratio widget width */
  18082         item_width = layout->row.item_width;
  18083         item_offset = layout->row.item_offset;
  18084         item_spacing = (float)layout->row.index * spacing.x;
  18085         if (modify) layout->row.item_offset += item_width;
  18086     } break;
  18087     case NK_LAYOUT_STATIC_FREE: {
  18088         /* free widget placing */
  18089         bounds->x = layout->at_x + layout->row.item.x;
  18090         bounds->w = layout->row.item.w;
  18091         if (((bounds->x + bounds->w) > layout->max_x) && modify)
  18092             layout->max_x = (bounds->x + bounds->w);
  18093         bounds->x -= (float)*layout->offset_x;
  18094         bounds->y = layout->at_y + layout->row.item.y;
  18095         bounds->y -= (float)*layout->offset_y;
  18096         bounds->h = layout->row.item.h;
  18097         return;
  18098     }
  18099     case NK_LAYOUT_STATIC: {
  18100         /* non-scaling array of panel pixel width for every widget */
  18101         item_spacing = (float)layout->row.index * spacing.x;
  18102         item_width = layout->row.ratio[layout->row.index];
  18103         item_offset = layout->row.item_offset;
  18104         if (modify) layout->row.item_offset += item_width;
  18105     } break;
  18106     case NK_LAYOUT_TEMPLATE: {
  18107         /* stretchy row layout with combined dynamic/static widget width*/
  18108         NK_ASSERT(layout->row.index < layout->row.columns);
  18109         NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
  18110         item_width = layout->row.templates[layout->row.index];
  18111         item_offset = layout->row.item_offset;
  18112         item_spacing = (float)layout->row.index * spacing.x;
  18113         if (modify) layout->row.item_offset += item_width;
  18114     } break;
  18115     default: NK_ASSERT(0); break;
  18116     };
  18117 
  18118     /* set the bounds of the newly allocated widget */
  18119     bounds->w = item_width;
  18120     bounds->h = layout->row.height - spacing.y;
  18121     bounds->y = layout->at_y - (float)*layout->offset_y;
  18122     bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
  18123     if (((bounds->x + bounds->w) > layout->max_x) && modify)
  18124         layout->max_x = bounds->x + bounds->w;
  18125     bounds->x -= (float)*layout->offset_x;
  18126 }
  18127 NK_LIB void
  18128 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
  18129 {
  18130     struct nk_window *win;
  18131     struct nk_panel *layout;
  18132 
  18133     NK_ASSERT(ctx);
  18134     NK_ASSERT(ctx->current);
  18135     NK_ASSERT(ctx->current->layout);
  18136     if (!ctx || !ctx->current || !ctx->current->layout)
  18137         return;
  18138 
  18139     /* check if the end of the row has been hit and begin new row if so */
  18140     win = ctx->current;
  18141     layout = win->layout;
  18142     if (layout->row.index >= layout->row.columns)
  18143         nk_panel_alloc_row(ctx, win);
  18144 
  18145     /* calculate widget position and size */
  18146     nk_layout_widget_space(bounds, ctx, win, nk_true);
  18147     layout->row.index++;
  18148 }
  18149 NK_LIB void
  18150 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
  18151 {
  18152     float y;
  18153     int index;
  18154     struct nk_window *win;
  18155     struct nk_panel *layout;
  18156 
  18157     NK_ASSERT(ctx);
  18158     NK_ASSERT(ctx->current);
  18159     NK_ASSERT(ctx->current->layout);
  18160     if (!ctx || !ctx->current || !ctx->current->layout)
  18161         return;
  18162 
  18163     win = ctx->current;
  18164     layout = win->layout;
  18165     y = layout->at_y;
  18166     index = layout->row.index;
  18167     if (layout->row.index >= layout->row.columns) {
  18168         layout->at_y += layout->row.height;
  18169         layout->row.index = 0;
  18170     }
  18171     nk_layout_widget_space(bounds, ctx, win, nk_false);
  18172     if (!layout->row.index) {
  18173         bounds->x -= layout->row.item_offset;
  18174     }
  18175     layout->at_y = y;
  18176     layout->row.index = index;
  18177 }
  18178 
  18179 
  18180 
  18181 
  18182 
  18183 /* ===============================================================
  18184  *
  18185  *                              TREE
  18186  *
  18187  * ===============================================================*/
  18188 NK_INTERN int
  18189 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
  18190     struct nk_image *img, const char *title, enum nk_collapse_states *state)
  18191 {
  18192     struct nk_window *win;
  18193     struct nk_panel *layout;
  18194     const struct nk_style *style;
  18195     struct nk_command_buffer *out;
  18196     const struct nk_input *in;
  18197     const struct nk_style_button *button;
  18198     enum nk_symbol_type symbol;
  18199     float row_height;
  18200 
  18201     struct nk_vec2 item_spacing;
  18202     struct nk_rect header = {0,0,0,0};
  18203     struct nk_rect sym = {0,0,0,0};
  18204     struct nk_text text;
  18205 
  18206     nk_flags ws = 0;
  18207     enum nk_widget_layout_states widget_state;
  18208 
  18209     NK_ASSERT(ctx);
  18210     NK_ASSERT(ctx->current);
  18211     NK_ASSERT(ctx->current->layout);
  18212     if (!ctx || !ctx->current || !ctx->current->layout)
  18213         return 0;
  18214 
  18215     /* cache some data */
  18216     win = ctx->current;
  18217     layout = win->layout;
  18218     out = &win->buffer;
  18219     style = &ctx->style;
  18220     item_spacing = style->window.spacing;
  18221 
  18222     /* calculate header bounds and draw background */
  18223     row_height = style->font->height + 2 * style->tab.padding.y;
  18224     nk_layout_set_min_row_height(ctx, row_height);
  18225     nk_layout_row_dynamic(ctx, row_height, 1);
  18226     nk_layout_reset_min_row_height(ctx);
  18227 
  18228     widget_state = nk_widget(&header, ctx);
  18229     if (type == NK_TREE_TAB) {
  18230         const struct nk_style_item *background = &style->tab.background;
  18231         if (background->type == NK_STYLE_ITEM_IMAGE) {
  18232             nk_draw_image(out, header, &background->data.image, nk_white);
  18233             text.background = nk_rgba(0,0,0,0);
  18234         } else {
  18235             text.background = background->data.color;
  18236             nk_fill_rect(out, header, 0, style->tab.border_color);
  18237             nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
  18238                 style->tab.rounding, background->data.color);
  18239         }
  18240     } else text.background = style->window.background;
  18241 
  18242     /* update node state */
  18243     in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
  18244     in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
  18245     if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
  18246         *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
  18247 
  18248     /* select correct button style */
  18249     if (*state == NK_MAXIMIZED) {
  18250         symbol = style->tab.sym_maximize;
  18251         if (type == NK_TREE_TAB)
  18252             button = &style->tab.tab_maximize_button;
  18253         else button = &style->tab.node_maximize_button;
  18254     } else {
  18255         symbol = style->tab.sym_minimize;
  18256         if (type == NK_TREE_TAB)
  18257             button = &style->tab.tab_minimize_button;
  18258         else button = &style->tab.node_minimize_button;
  18259     }
  18260 
  18261     {/* draw triangle button */
  18262     sym.w = sym.h = style->font->height;
  18263     sym.y = header.y + style->tab.padding.y;
  18264     sym.x = header.x + style->tab.padding.x;
  18265     nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
  18266         button, 0, style->font);
  18267 
  18268     if (img) {
  18269         /* draw optional image icon */
  18270         sym.x = sym.x + sym.w + 4 * item_spacing.x;
  18271         nk_draw_image(&win->buffer, sym, img, nk_white);
  18272         sym.w = style->font->height + style->tab.spacing.x;}
  18273     }
  18274 
  18275     {/* draw label */
  18276     struct nk_rect label;
  18277     header.w = NK_MAX(header.w, sym.w + item_spacing.x);
  18278     label.x = sym.x + sym.w + item_spacing.x;
  18279     label.y = sym.y;
  18280     label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
  18281     label.h = style->font->height;
  18282     text.text = style->tab.text;
  18283     text.padding = nk_vec2(0,0);
  18284     nk_widget_text(out, label, title, nk_strlen(title), &text,
  18285         NK_TEXT_LEFT, style->font);}
  18286 
  18287     /* increase x-axis cursor widget position pointer */
  18288     if (*state == NK_MAXIMIZED) {
  18289         layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
  18290         layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
  18291         layout->bounds.w -= (style->tab.indent + style->window.padding.x);
  18292         layout->row.tree_depth++;
  18293         return nk_true;
  18294     } else return nk_false;
  18295 }
  18296 NK_INTERN int
  18297 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
  18298     struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
  18299     const char *hash, int len, int line)
  18300 {
  18301     struct nk_window *win = ctx->current;
  18302     int title_len = 0;
  18303     nk_hash tree_hash = 0;
  18304     nk_uint *state = 0;
  18305 
  18306     /* retrieve tree state from internal widget state tables */
  18307     if (!hash) {
  18308         title_len = (int)nk_strlen(title);
  18309         tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
  18310     } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
  18311     state = nk_find_value(win, tree_hash);
  18312     if (!state) {
  18313         state = nk_add_value(ctx, win, tree_hash, 0);
  18314         *state = initial_state;
  18315     }
  18316     return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
  18317 }
  18318 NK_API int
  18319 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
  18320     const char *title, enum nk_collapse_states *state)
  18321 {
  18322     return nk_tree_state_base(ctx, type, 0, title, state);
  18323 }
  18324 NK_API int
  18325 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
  18326     struct nk_image img, const char *title, enum nk_collapse_states *state)
  18327 {
  18328     return nk_tree_state_base(ctx, type, &img, title, state);
  18329 }
  18330 NK_API void
  18331 nk_tree_state_pop(struct nk_context *ctx)
  18332 {
  18333     struct nk_window *win = 0;
  18334     struct nk_panel *layout = 0;
  18335 
  18336     NK_ASSERT(ctx);
  18337     NK_ASSERT(ctx->current);
  18338     NK_ASSERT(ctx->current->layout);
  18339     if (!ctx || !ctx->current || !ctx->current->layout)
  18340         return;
  18341 
  18342     win = ctx->current;
  18343     layout = win->layout;
  18344     layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
  18345     layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
  18346     NK_ASSERT(layout->row.tree_depth);
  18347     layout->row.tree_depth--;
  18348 }
  18349 NK_API int
  18350 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
  18351     const char *title, enum nk_collapse_states initial_state,
  18352     const char *hash, int len, int line)
  18353 {
  18354     return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);
  18355 }
  18356 NK_API int
  18357 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
  18358     struct nk_image img, const char *title, enum nk_collapse_states initial_state,
  18359     const char *hash, int len,int seed)
  18360 {
  18361     return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);
  18362 }
  18363 NK_API void
  18364 nk_tree_pop(struct nk_context *ctx)
  18365 {
  18366     nk_tree_state_pop(ctx);
  18367 }
  18368 NK_INTERN int
  18369 nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type,
  18370     struct nk_image *img, const char *title, int title_len,
  18371     enum nk_collapse_states *state, int *selected)
  18372 {
  18373     struct nk_window *win;
  18374     struct nk_panel *layout;
  18375     const struct nk_style *style;
  18376     struct nk_command_buffer *out;
  18377     const struct nk_input *in;
  18378     const struct nk_style_button *button;
  18379     enum nk_symbol_type symbol;
  18380     float row_height;
  18381     struct nk_vec2 padding;
  18382 
  18383     int text_len;
  18384     float text_width;
  18385 
  18386     struct nk_vec2 item_spacing;
  18387     struct nk_rect header = {0,0,0,0};
  18388     struct nk_rect sym = {0,0,0,0};
  18389     struct nk_text text;
  18390 
  18391     nk_flags ws = 0;
  18392     enum nk_widget_layout_states widget_state;
  18393 
  18394     NK_ASSERT(ctx);
  18395     NK_ASSERT(ctx->current);
  18396     NK_ASSERT(ctx->current->layout);
  18397     if (!ctx || !ctx->current || !ctx->current->layout)
  18398         return 0;
  18399 
  18400     /* cache some data */
  18401     win = ctx->current;
  18402     layout = win->layout;
  18403     out = &win->buffer;
  18404     style = &ctx->style;
  18405     item_spacing = style->window.spacing;
  18406     padding = style->selectable.padding;
  18407 
  18408     /* calculate header bounds and draw background */
  18409     row_height = style->font->height + 2 * style->tab.padding.y;
  18410     nk_layout_set_min_row_height(ctx, row_height);
  18411     nk_layout_row_dynamic(ctx, row_height, 1);
  18412     nk_layout_reset_min_row_height(ctx);
  18413 
  18414     widget_state = nk_widget(&header, ctx);
  18415     if (type == NK_TREE_TAB) {
  18416         const struct nk_style_item *background = &style->tab.background;
  18417         if (background->type == NK_STYLE_ITEM_IMAGE) {
  18418             nk_draw_image(out, header, &background->data.image, nk_white);
  18419             text.background = nk_rgba(0,0,0,0);
  18420         } else {
  18421             text.background = background->data.color;
  18422             nk_fill_rect(out, header, 0, style->tab.border_color);
  18423             nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
  18424                 style->tab.rounding, background->data.color);
  18425         }
  18426     } else text.background = style->window.background;
  18427 
  18428     in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
  18429     in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
  18430 
  18431     /* select correct button style */
  18432     if (*state == NK_MAXIMIZED) {
  18433         symbol = style->tab.sym_maximize;
  18434         if (type == NK_TREE_TAB)
  18435             button = &style->tab.tab_maximize_button;
  18436         else button = &style->tab.node_maximize_button;
  18437     } else {
  18438         symbol = style->tab.sym_minimize;
  18439         if (type == NK_TREE_TAB)
  18440             button = &style->tab.tab_minimize_button;
  18441         else button = &style->tab.node_minimize_button;
  18442     }
  18443     {/* draw triangle button */
  18444     sym.w = sym.h = style->font->height;
  18445     sym.y = header.y + style->tab.padding.y;
  18446     sym.x = header.x + style->tab.padding.x;
  18447     if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font))
  18448         *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;}
  18449 
  18450     /* draw label */
  18451     {nk_flags dummy = 0;
  18452     struct nk_rect label;
  18453     /* calculate size of the text and tooltip */
  18454     text_len = nk_strlen(title);
  18455     text_width = style->font->width(style->font->userdata, style->font->height, title, text_len);
  18456     text_width += (4 * padding.x);
  18457 
  18458     header.w = NK_MAX(header.w, sym.w + item_spacing.x);
  18459     label.x = sym.x + sym.w + item_spacing.x;
  18460     label.y = sym.y;
  18461     label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width);
  18462     label.h = style->font->height;
  18463 
  18464     if (img) {
  18465         nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
  18466             selected, img, &style->selectable, in, style->font);
  18467     } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
  18468             selected, &style->selectable, in, style->font);
  18469     }
  18470     /* increase x-axis cursor widget position pointer */
  18471     if (*state == NK_MAXIMIZED) {
  18472         layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
  18473         layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
  18474         layout->bounds.w -= (style->tab.indent + style->window.padding.x);
  18475         layout->row.tree_depth++;
  18476         return nk_true;
  18477     } else return nk_false;
  18478 }
  18479 NK_INTERN int
  18480 nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type,
  18481     struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
  18482     int *selected, const char *hash, int len, int line)
  18483 {
  18484     struct nk_window *win = ctx->current;
  18485     int title_len = 0;
  18486     nk_hash tree_hash = 0;
  18487     nk_uint *state = 0;
  18488 
  18489     /* retrieve tree state from internal widget state tables */
  18490     if (!hash) {
  18491         title_len = (int)nk_strlen(title);
  18492         tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
  18493     } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
  18494     state = nk_find_value(win, tree_hash);
  18495     if (!state) {
  18496         state = nk_add_value(ctx, win, tree_hash, 0);
  18497         *state = initial_state;
  18498     } return nk_tree_element_image_push_hashed_base(ctx, type, img, title,
  18499         nk_strlen(title), (enum nk_collapse_states*)state, selected);
  18500 }
  18501 NK_API int
  18502 nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
  18503     const char *title, enum nk_collapse_states initial_state,
  18504     int *selected, const char *hash, int len, int seed)
  18505 {
  18506     return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed);
  18507 }
  18508 NK_API int
  18509 nk_tree_element_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
  18510     struct nk_image img, const char *title, enum nk_collapse_states initial_state,
  18511     int *selected, const char *hash, int len,int seed)
  18512 {
  18513     return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed);
  18514 }
  18515 NK_API void
  18516 nk_tree_element_pop(struct nk_context *ctx)
  18517 {
  18518     nk_tree_state_pop(ctx);
  18519 }
  18520 
  18521 
  18522 
  18523 
  18524 
  18525 /* ===============================================================
  18526  *
  18527  *                          GROUP
  18528  *
  18529  * ===============================================================*/
  18530 NK_API int
  18531 nk_group_scrolled_offset_begin(struct nk_context *ctx,
  18532     nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
  18533 {
  18534     struct nk_rect bounds;
  18535     struct nk_window panel;
  18536     struct nk_window *win;
  18537 
  18538     win = ctx->current;
  18539     nk_panel_alloc_space(&bounds, ctx);
  18540     {const struct nk_rect *c = &win->layout->clip;
  18541     if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
  18542         !(flags & NK_WINDOW_MOVABLE)) {
  18543         return 0;
  18544     }}
  18545     if (win->flags & NK_WINDOW_ROM)
  18546         flags |= NK_WINDOW_ROM;
  18547 
  18548     /* initialize a fake window to create the panel from */
  18549     nk_zero(&panel, sizeof(panel));
  18550     panel.bounds = bounds;
  18551     panel.flags = flags;
  18552     panel.scrollbar.x = *x_offset;
  18553     panel.scrollbar.y = *y_offset;
  18554     panel.buffer = win->buffer;
  18555     panel.layout = (struct nk_panel*)nk_create_panel(ctx);
  18556     ctx->current = &panel;
  18557     nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
  18558 
  18559     win->buffer = panel.buffer;
  18560     win->buffer.clip = panel.layout->clip;
  18561     panel.layout->offset_x = x_offset;
  18562     panel.layout->offset_y = y_offset;
  18563     panel.layout->parent = win->layout;
  18564     win->layout = panel.layout;
  18565 
  18566     ctx->current = win;
  18567     if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
  18568         (panel.layout->flags & NK_WINDOW_MINIMIZED))
  18569     {
  18570         nk_flags f = panel.layout->flags;
  18571         nk_group_scrolled_end(ctx);
  18572         if (f & NK_WINDOW_CLOSED)
  18573             return NK_WINDOW_CLOSED;
  18574         if (f & NK_WINDOW_MINIMIZED)
  18575             return NK_WINDOW_MINIMIZED;
  18576     }
  18577     return 1;
  18578 }
  18579 NK_API void
  18580 nk_group_scrolled_end(struct nk_context *ctx)
  18581 {
  18582     struct nk_window *win;
  18583     struct nk_panel *parent;
  18584     struct nk_panel *g;
  18585 
  18586     struct nk_rect clip;
  18587     struct nk_window pan;
  18588     struct nk_vec2 panel_padding;
  18589 
  18590     NK_ASSERT(ctx);
  18591     NK_ASSERT(ctx->current);
  18592     if (!ctx || !ctx->current)
  18593         return;
  18594 
  18595     /* make sure nk_group_begin was called correctly */
  18596     NK_ASSERT(ctx->current);
  18597     win = ctx->current;
  18598     NK_ASSERT(win->layout);
  18599     g = win->layout;
  18600     NK_ASSERT(g->parent);
  18601     parent = g->parent;
  18602 
  18603     /* dummy window */
  18604     nk_zero_struct(pan);
  18605     panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
  18606     pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
  18607     pan.bounds.x = g->bounds.x - panel_padding.x;
  18608     pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
  18609     pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
  18610     if (g->flags & NK_WINDOW_BORDER) {
  18611         pan.bounds.x -= g->border;
  18612         pan.bounds.y -= g->border;
  18613         pan.bounds.w += 2*g->border;
  18614         pan.bounds.h += 2*g->border;
  18615     }
  18616     if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
  18617         pan.bounds.w += ctx->style.window.scrollbar_size.x;
  18618         pan.bounds.h += ctx->style.window.scrollbar_size.y;
  18619     }
  18620     pan.scrollbar.x = *g->offset_x;
  18621     pan.scrollbar.y = *g->offset_y;
  18622     pan.flags = g->flags;
  18623     pan.buffer = win->buffer;
  18624     pan.layout = g;
  18625     pan.parent = win;
  18626     ctx->current = &pan;
  18627 
  18628     /* make sure group has correct clipping rectangle */
  18629     nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
  18630         pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
  18631     nk_push_scissor(&pan.buffer, clip);
  18632     nk_end(ctx);
  18633 
  18634     win->buffer = pan.buffer;
  18635     nk_push_scissor(&win->buffer, parent->clip);
  18636     ctx->current = win;
  18637     win->layout = parent;
  18638     g->bounds = pan.bounds;
  18639     return;
  18640 }
  18641 NK_API int
  18642 nk_group_scrolled_begin(struct nk_context *ctx,
  18643     struct nk_scroll *scroll, const char *title, nk_flags flags)
  18644 {
  18645     return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);
  18646 }
  18647 NK_API int
  18648 nk_group_begin_titled(struct nk_context *ctx, const char *id,
  18649     const char *title, nk_flags flags)
  18650 {
  18651     int id_len;
  18652     nk_hash id_hash;
  18653     struct nk_window *win;
  18654     nk_uint *x_offset;
  18655     nk_uint *y_offset;
  18656 
  18657     NK_ASSERT(ctx);
  18658     NK_ASSERT(id);
  18659     NK_ASSERT(ctx->current);
  18660     NK_ASSERT(ctx->current->layout);
  18661     if (!ctx || !ctx->current || !ctx->current->layout || !id)
  18662         return 0;
  18663 
  18664     /* find persistent group scrollbar value */
  18665     win = ctx->current;
  18666     id_len = (int)nk_strlen(id);
  18667     id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
  18668     x_offset = nk_find_value(win, id_hash);
  18669     if (!x_offset) {
  18670         x_offset = nk_add_value(ctx, win, id_hash, 0);
  18671         y_offset = nk_add_value(ctx, win, id_hash+1, 0);
  18672 
  18673         NK_ASSERT(x_offset);
  18674         NK_ASSERT(y_offset);
  18675         if (!x_offset || !y_offset) return 0;
  18676         *x_offset = *y_offset = 0;
  18677     } else y_offset = nk_find_value(win, id_hash+1);
  18678     return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
  18679 }
  18680 NK_API int
  18681 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
  18682 {
  18683     return nk_group_begin_titled(ctx, title, title, flags);
  18684 }
  18685 NK_API void
  18686 nk_group_end(struct nk_context *ctx)
  18687 {
  18688     nk_group_scrolled_end(ctx);
  18689 }
  18690 
  18691 
  18692 
  18693 
  18694 
  18695 /* ===============================================================
  18696  *
  18697  *                          LIST VIEW
  18698  *
  18699  * ===============================================================*/
  18700 NK_API int
  18701 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
  18702     const char *title, nk_flags flags, int row_height, int row_count)
  18703 {
  18704     int title_len;
  18705     nk_hash title_hash;
  18706     nk_uint *x_offset;
  18707     nk_uint *y_offset;
  18708 
  18709     int result;
  18710     struct nk_window *win;
  18711     struct nk_panel *layout;
  18712     const struct nk_style *style;
  18713     struct nk_vec2 item_spacing;
  18714 
  18715     NK_ASSERT(ctx);
  18716     NK_ASSERT(view);
  18717     NK_ASSERT(title);
  18718     if (!ctx || !view || !title) return 0;
  18719 
  18720     win = ctx->current;
  18721     style = &ctx->style;
  18722     item_spacing = style->window.spacing;
  18723     row_height += NK_MAX(0, (int)item_spacing.y);
  18724 
  18725     /* find persistent list view scrollbar offset */
  18726     title_len = (int)nk_strlen(title);
  18727     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
  18728     x_offset = nk_find_value(win, title_hash);
  18729     if (!x_offset) {
  18730         x_offset = nk_add_value(ctx, win, title_hash, 0);
  18731         y_offset = nk_add_value(ctx, win, title_hash+1, 0);
  18732 
  18733         NK_ASSERT(x_offset);
  18734         NK_ASSERT(y_offset);
  18735         if (!x_offset || !y_offset) return 0;
  18736         *x_offset = *y_offset = 0;
  18737     } else y_offset = nk_find_value(win, title_hash+1);
  18738     view->scroll_value = *y_offset;
  18739     view->scroll_pointer = y_offset;
  18740 
  18741     *y_offset = 0;
  18742     result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
  18743     win = ctx->current;
  18744     layout = win->layout;
  18745 
  18746     view->total_height = row_height * NK_MAX(row_count,1);
  18747     view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
  18748     view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0);
  18749     view->count = NK_MIN(view->count, row_count - view->begin);
  18750     view->end = view->begin + view->count;
  18751     view->ctx = ctx;
  18752     return result;
  18753 }
  18754 NK_API void
  18755 nk_list_view_end(struct nk_list_view *view)
  18756 {
  18757     struct nk_context *ctx;
  18758     struct nk_window *win;
  18759     struct nk_panel *layout;
  18760 
  18761     NK_ASSERT(view);
  18762     NK_ASSERT(view->ctx);
  18763     NK_ASSERT(view->scroll_pointer);
  18764     if (!view || !view->ctx) return;
  18765 
  18766     ctx = view->ctx;
  18767     win = ctx->current;
  18768     layout = win->layout;
  18769     layout->at_y = layout->bounds.y + (float)view->total_height;
  18770     *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
  18771     nk_group_end(view->ctx);
  18772 }
  18773 
  18774 
  18775 
  18776 
  18777 
  18778 /* ===============================================================
  18779  *
  18780  *                              WIDGET
  18781  *
  18782  * ===============================================================*/
  18783 NK_API struct nk_rect
  18784 nk_widget_bounds(struct nk_context *ctx)
  18785 {
  18786     struct nk_rect bounds;
  18787     NK_ASSERT(ctx);
  18788     NK_ASSERT(ctx->current);
  18789     if (!ctx || !ctx->current)
  18790         return nk_rect(0,0,0,0);
  18791     nk_layout_peek(&bounds, ctx);
  18792     return bounds;
  18793 }
  18794 NK_API struct nk_vec2
  18795 nk_widget_position(struct nk_context *ctx)
  18796 {
  18797     struct nk_rect bounds;
  18798     NK_ASSERT(ctx);
  18799     NK_ASSERT(ctx->current);
  18800     if (!ctx || !ctx->current)
  18801         return nk_vec2(0,0);
  18802 
  18803     nk_layout_peek(&bounds, ctx);
  18804     return nk_vec2(bounds.x, bounds.y);
  18805 }
  18806 NK_API struct nk_vec2
  18807 nk_widget_size(struct nk_context *ctx)
  18808 {
  18809     struct nk_rect bounds;
  18810     NK_ASSERT(ctx);
  18811     NK_ASSERT(ctx->current);
  18812     if (!ctx || !ctx->current)
  18813         return nk_vec2(0,0);
  18814 
  18815     nk_layout_peek(&bounds, ctx);
  18816     return nk_vec2(bounds.w, bounds.h);
  18817 }
  18818 NK_API float
  18819 nk_widget_width(struct nk_context *ctx)
  18820 {
  18821     struct nk_rect bounds;
  18822     NK_ASSERT(ctx);
  18823     NK_ASSERT(ctx->current);
  18824     if (!ctx || !ctx->current)
  18825         return 0;
  18826 
  18827     nk_layout_peek(&bounds, ctx);
  18828     return bounds.w;
  18829 }
  18830 NK_API float
  18831 nk_widget_height(struct nk_context *ctx)
  18832 {
  18833     struct nk_rect bounds;
  18834     NK_ASSERT(ctx);
  18835     NK_ASSERT(ctx->current);
  18836     if (!ctx || !ctx->current)
  18837         return 0;
  18838 
  18839     nk_layout_peek(&bounds, ctx);
  18840     return bounds.h;
  18841 }
  18842 NK_API int
  18843 nk_widget_is_hovered(struct nk_context *ctx)
  18844 {
  18845     struct nk_rect c, v;
  18846     struct nk_rect bounds;
  18847     NK_ASSERT(ctx);
  18848     NK_ASSERT(ctx->current);
  18849     if (!ctx || !ctx->current || ctx->active != ctx->current)
  18850         return 0;
  18851 
  18852     c = ctx->current->layout->clip;
  18853     c.x = (float)((int)c.x);
  18854     c.y = (float)((int)c.y);
  18855     c.w = (float)((int)c.w);
  18856     c.h = (float)((int)c.h);
  18857 
  18858     nk_layout_peek(&bounds, ctx);
  18859     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
  18860     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
  18861         return 0;
  18862     return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
  18863 }
  18864 NK_API int
  18865 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
  18866 {
  18867     struct nk_rect c, v;
  18868     struct nk_rect bounds;
  18869     NK_ASSERT(ctx);
  18870     NK_ASSERT(ctx->current);
  18871     if (!ctx || !ctx->current || ctx->active != ctx->current)
  18872         return 0;
  18873 
  18874     c = ctx->current->layout->clip;
  18875     c.x = (float)((int)c.x);
  18876     c.y = (float)((int)c.y);
  18877     c.w = (float)((int)c.w);
  18878     c.h = (float)((int)c.h);
  18879 
  18880     nk_layout_peek(&bounds, ctx);
  18881     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
  18882     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
  18883         return 0;
  18884     return nk_input_mouse_clicked(&ctx->input, btn, bounds);
  18885 }
  18886 NK_API int
  18887 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
  18888 {
  18889     struct nk_rect c, v;
  18890     struct nk_rect bounds;
  18891     NK_ASSERT(ctx);
  18892     NK_ASSERT(ctx->current);
  18893     if (!ctx || !ctx->current || ctx->active != ctx->current)
  18894         return 0;
  18895 
  18896     c = ctx->current->layout->clip;
  18897     c.x = (float)((int)c.x);
  18898     c.y = (float)((int)c.y);
  18899     c.w = (float)((int)c.w);
  18900     c.h = (float)((int)c.h);
  18901 
  18902     nk_layout_peek(&bounds, ctx);
  18903     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
  18904     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
  18905         return 0;
  18906     return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
  18907 }
  18908 NK_API enum nk_widget_layout_states
  18909 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
  18910 {
  18911     struct nk_rect c, v;
  18912     struct nk_window *win;
  18913     struct nk_panel *layout;
  18914     const struct nk_input *in;
  18915 
  18916     NK_ASSERT(ctx);
  18917     NK_ASSERT(ctx->current);
  18918     NK_ASSERT(ctx->current->layout);
  18919     if (!ctx || !ctx->current || !ctx->current->layout)
  18920         return NK_WIDGET_INVALID;
  18921 
  18922     /* allocate space and check if the widget needs to be updated and drawn */
  18923     nk_panel_alloc_space(bounds, ctx);
  18924     win = ctx->current;
  18925     layout = win->layout;
  18926     in = &ctx->input;
  18927     c = layout->clip;
  18928 
  18929     /*  if one of these triggers you forgot to add an `if` condition around either
  18930         a window, group, popup, combobox or contextual menu `begin` and `end` block.
  18931         Example:
  18932             if (nk_begin(...) {...} nk_end(...); or
  18933             if (nk_group_begin(...) { nk_group_end(...);} */
  18934     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
  18935     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
  18936     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
  18937 
  18938     /* need to convert to int here to remove floating point errors */
  18939     bounds->x = (float)((int)bounds->x);
  18940     bounds->y = (float)((int)bounds->y);
  18941     bounds->w = (float)((int)bounds->w);
  18942     bounds->h = (float)((int)bounds->h);
  18943 
  18944     c.x = (float)((int)c.x);
  18945     c.y = (float)((int)c.y);
  18946     c.w = (float)((int)c.w);
  18947     c.h = (float)((int)c.h);
  18948 
  18949     nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
  18950     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
  18951         return NK_WIDGET_INVALID;
  18952     if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
  18953         return NK_WIDGET_ROM;
  18954     return NK_WIDGET_VALID;
  18955 }
  18956 NK_API enum nk_widget_layout_states
  18957 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
  18958     struct nk_vec2 item_padding)
  18959 {
  18960     /* update the bounds to stand without padding  */
  18961     struct nk_window *win;
  18962     struct nk_style *style;
  18963     struct nk_panel *layout;
  18964     enum nk_widget_layout_states state;
  18965     struct nk_vec2 panel_padding;
  18966 
  18967     NK_ASSERT(ctx);
  18968     NK_ASSERT(ctx->current);
  18969     NK_ASSERT(ctx->current->layout);
  18970     if (!ctx || !ctx->current || !ctx->current->layout)
  18971         return NK_WIDGET_INVALID;
  18972 
  18973     win = ctx->current;
  18974     style = &ctx->style;
  18975     layout = win->layout;
  18976     state = nk_widget(bounds, ctx);
  18977 
  18978     panel_padding = nk_panel_get_padding(style, layout->type);
  18979     if (layout->row.index == 1) {
  18980         bounds->w += panel_padding.x;
  18981         bounds->x -= panel_padding.x;
  18982     } else bounds->x -= item_padding.x;
  18983 
  18984     if (layout->row.index == layout->row.columns)
  18985         bounds->w += panel_padding.x;
  18986     else bounds->w += item_padding.x;
  18987     return state;
  18988 }
  18989 NK_API void
  18990 nk_spacing(struct nk_context *ctx, int cols)
  18991 {
  18992     struct nk_window *win;
  18993     struct nk_panel *layout;
  18994     struct nk_rect none;
  18995     int i, index, rows;
  18996 
  18997     NK_ASSERT(ctx);
  18998     NK_ASSERT(ctx->current);
  18999     NK_ASSERT(ctx->current->layout);
  19000     if (!ctx || !ctx->current || !ctx->current->layout)
  19001         return;
  19002 
  19003     /* spacing over row boundaries */
  19004     win = ctx->current;
  19005     layout = win->layout;
  19006     index = (layout->row.index + cols) % layout->row.columns;
  19007     rows = (layout->row.index + cols) / layout->row.columns;
  19008     if (rows) {
  19009         for (i = 0; i < rows; ++i)
  19010             nk_panel_alloc_row(ctx, win);
  19011         cols = index;
  19012     }
  19013     /* non table layout need to allocate space */
  19014     if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
  19015         layout->row.type != NK_LAYOUT_STATIC_FIXED) {
  19016         for (i = 0; i < cols; ++i)
  19017             nk_panel_alloc_space(&none, ctx);
  19018     } layout->row.index = index;
  19019 }
  19020 
  19021 
  19022 
  19023 
  19024 
  19025 /* ===============================================================
  19026  *
  19027  *                              TEXT
  19028  *
  19029  * ===============================================================*/
  19030 NK_LIB void
  19031 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
  19032     const char *string, int len, const struct nk_text *t,
  19033     nk_flags a, const struct nk_user_font *f)
  19034 {
  19035     struct nk_rect label;
  19036     float text_width;
  19037 
  19038     NK_ASSERT(o);
  19039     NK_ASSERT(t);
  19040     if (!o || !t) return;
  19041 
  19042     b.h = NK_MAX(b.h, 2 * t->padding.y);
  19043     label.x = 0; label.w = 0;
  19044     label.y = b.y + t->padding.y;
  19045     label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
  19046 
  19047     text_width = f->width(f->userdata, f->height, (const char*)string, len);
  19048     text_width += (2.0f * t->padding.x);
  19049 
  19050     /* align in x-axis */
  19051     if (a & NK_TEXT_ALIGN_LEFT) {
  19052         label.x = b.x + t->padding.x;
  19053         label.w = NK_MAX(0, b.w - 2 * t->padding.x);
  19054     } else if (a & NK_TEXT_ALIGN_CENTERED) {
  19055         label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
  19056         label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
  19057         label.x = NK_MAX(b.x + t->padding.x, label.x);
  19058         label.w = NK_MIN(b.x + b.w, label.x + label.w);
  19059         if (label.w >= label.x) label.w -= label.x;
  19060     } else if (a & NK_TEXT_ALIGN_RIGHT) {
  19061         label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
  19062         label.w = (float)text_width + 2 * t->padding.x;
  19063     } else return;
  19064 
  19065     /* align in y-axis */
  19066     if (a & NK_TEXT_ALIGN_MIDDLE) {
  19067         label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
  19068         label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
  19069     } else if (a & NK_TEXT_ALIGN_BOTTOM) {
  19070         label.y = b.y + b.h - f->height;
  19071         label.h = f->height;
  19072     }
  19073     nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text);
  19074 }
  19075 NK_LIB void
  19076 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
  19077     const char *string, int len, const struct nk_text *t,
  19078     const struct nk_user_font *f)
  19079 {
  19080     float width;
  19081     int glyphs = 0;
  19082     int fitting = 0;
  19083     int done = 0;
  19084     struct nk_rect line;
  19085     struct nk_text text;
  19086     NK_INTERN nk_rune seperator[] = {' '};
  19087 
  19088     NK_ASSERT(o);
  19089     NK_ASSERT(t);
  19090     if (!o || !t) return;
  19091 
  19092     text.padding = nk_vec2(0,0);
  19093     text.background = t->background;
  19094     text.text = t->text;
  19095 
  19096     b.w = NK_MAX(b.w, 2 * t->padding.x);
  19097     b.h = NK_MAX(b.h, 2 * t->padding.y);
  19098     b.h = b.h - 2 * t->padding.y;
  19099 
  19100     line.x = b.x + t->padding.x;
  19101     line.y = b.y + t->padding.y;
  19102     line.w = b.w - 2 * t->padding.x;
  19103     line.h = 2 * t->padding.y + f->height;
  19104 
  19105     fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
  19106     while (done < len) {
  19107         if (!fitting || line.y + line.h >= (b.y + b.h)) break;
  19108         nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
  19109         done += fitting;
  19110         line.y += f->height + 2 * t->padding.y;
  19111         fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
  19112     }
  19113 }
  19114 NK_API void
  19115 nk_text_colored(struct nk_context *ctx, const char *str, int len,
  19116     nk_flags alignment, struct nk_color color)
  19117 {
  19118     struct nk_window *win;
  19119     const struct nk_style *style;
  19120 
  19121     struct nk_vec2 item_padding;
  19122     struct nk_rect bounds;
  19123     struct nk_text text;
  19124 
  19125     NK_ASSERT(ctx);
  19126     NK_ASSERT(ctx->current);
  19127     NK_ASSERT(ctx->current->layout);
  19128     if (!ctx || !ctx->current || !ctx->current->layout) return;
  19129 
  19130     win = ctx->current;
  19131     style = &ctx->style;
  19132     nk_panel_alloc_space(&bounds, ctx);
  19133     item_padding = style->text.padding;
  19134 
  19135     text.padding.x = item_padding.x;
  19136     text.padding.y = item_padding.y;
  19137     text.background = style->window.background;
  19138     text.text = color;
  19139     nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
  19140 }
  19141 NK_API void
  19142 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
  19143     int len, struct nk_color color)
  19144 {
  19145     struct nk_window *win;
  19146     const struct nk_style *style;
  19147 
  19148     struct nk_vec2 item_padding;
  19149     struct nk_rect bounds;
  19150     struct nk_text text;
  19151 
  19152     NK_ASSERT(ctx);
  19153     NK_ASSERT(ctx->current);
  19154     NK_ASSERT(ctx->current->layout);
  19155     if (!ctx || !ctx->current || !ctx->current->layout) return;
  19156 
  19157     win = ctx->current;
  19158     style = &ctx->style;
  19159     nk_panel_alloc_space(&bounds, ctx);
  19160     item_padding = style->text.padding;
  19161 
  19162     text.padding.x = item_padding.x;
  19163     text.padding.y = item_padding.y;
  19164     text.background = style->window.background;
  19165     text.text = color;
  19166     nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
  19167 }
  19168 #ifdef NK_INCLUDE_STANDARD_VARARGS
  19169 NK_API void
  19170 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
  19171     struct nk_color color, const char *fmt, ...)
  19172 {
  19173     va_list args;
  19174     va_start(args, fmt);
  19175     nk_labelfv_colored(ctx, flags, color, fmt, args);
  19176     va_end(args);
  19177 }
  19178 NK_API void
  19179 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
  19180     const char *fmt, ...)
  19181 {
  19182     va_list args;
  19183     va_start(args, fmt);
  19184     nk_labelfv_colored_wrap(ctx, color, fmt, args);
  19185     va_end(args);
  19186 }
  19187 NK_API void
  19188 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
  19189 {
  19190     va_list args;
  19191     va_start(args, fmt);
  19192     nk_labelfv(ctx, flags, fmt, args);
  19193     va_end(args);
  19194 }
  19195 NK_API void
  19196 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
  19197 {
  19198     va_list args;
  19199     va_start(args, fmt);
  19200     nk_labelfv_wrap(ctx, fmt, args);
  19201     va_end(args);
  19202 }
  19203 NK_API void
  19204 nk_labelfv_colored(struct nk_context *ctx, nk_flags flags,
  19205     struct nk_color color, const char *fmt, va_list args)
  19206 {
  19207     char buf[256];
  19208     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  19209     nk_label_colored(ctx, buf, flags, color);
  19210 }
  19211 
  19212 NK_API void
  19213 nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color,
  19214     const char *fmt, va_list args)
  19215 {
  19216     char buf[256];
  19217     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  19218     nk_label_colored_wrap(ctx, buf, color);
  19219 }
  19220 
  19221 NK_API void
  19222 nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args)
  19223 {
  19224     char buf[256];
  19225     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  19226     nk_label(ctx, buf, flags);
  19227 }
  19228 
  19229 NK_API void
  19230 nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args)
  19231 {
  19232     char buf[256];
  19233     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  19234     nk_label_wrap(ctx, buf);
  19235 }
  19236 
  19237 NK_API void
  19238 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
  19239 {
  19240     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));
  19241 }
  19242 NK_API void
  19243 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
  19244 {
  19245     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);
  19246 }
  19247 NK_API void
  19248 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
  19249 {
  19250     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);
  19251 }
  19252 NK_API void
  19253 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
  19254 {
  19255     double double_value = (double)value;
  19256     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
  19257 }
  19258 NK_API void
  19259 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
  19260 {
  19261     nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);
  19262 }
  19263 NK_API void
  19264 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
  19265 {
  19266     double c[4]; nk_color_dv(c, color);
  19267     nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
  19268         p, c[0], c[1], c[2], c[3]);
  19269 }
  19270 NK_API void
  19271 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
  19272 {
  19273     char hex[16];
  19274     nk_color_hex_rgba(hex, color);
  19275     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
  19276 }
  19277 #endif
  19278 NK_API void
  19279 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
  19280 {
  19281     NK_ASSERT(ctx);
  19282     if (!ctx) return;
  19283     nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
  19284 }
  19285 NK_API void
  19286 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
  19287 {
  19288     NK_ASSERT(ctx);
  19289     if (!ctx) return;
  19290     nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
  19291 }
  19292 NK_API void
  19293 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
  19294 {
  19295     nk_text(ctx, str, nk_strlen(str), alignment);
  19296 }
  19297 NK_API void
  19298 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
  19299     struct nk_color color)
  19300 {
  19301     nk_text_colored(ctx, str, nk_strlen(str), align, color);
  19302 }
  19303 NK_API void
  19304 nk_label_wrap(struct nk_context *ctx, const char *str)
  19305 {
  19306     nk_text_wrap(ctx, str, nk_strlen(str));
  19307 }
  19308 NK_API void
  19309 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
  19310 {
  19311     nk_text_wrap_colored(ctx, str, nk_strlen(str), color);
  19312 }
  19313 
  19314 
  19315 
  19316 
  19317 
  19318 /* ===============================================================
  19319  *
  19320  *                          IMAGE
  19321  *
  19322  * ===============================================================*/
  19323 NK_API nk_handle
  19324 nk_handle_ptr(void *ptr)
  19325 {
  19326     nk_handle handle = {0};
  19327     handle.ptr = ptr;
  19328     return handle;
  19329 }
  19330 NK_API nk_handle
  19331 nk_handle_id(int id)
  19332 {
  19333     nk_handle handle;
  19334     nk_zero_struct(handle);
  19335     handle.id = id;
  19336     return handle;
  19337 }
  19338 NK_API struct nk_image
  19339 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
  19340 {
  19341     struct nk_image s;
  19342     nk_zero(&s, sizeof(s));
  19343     s.handle.ptr = ptr;
  19344     s.w = w; s.h = h;
  19345     s.region[0] = (unsigned short)r.x;
  19346     s.region[1] = (unsigned short)r.y;
  19347     s.region[2] = (unsigned short)r.w;
  19348     s.region[3] = (unsigned short)r.h;
  19349     return s;
  19350 }
  19351 NK_API struct nk_image
  19352 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
  19353 {
  19354     struct nk_image s;
  19355     nk_zero(&s, sizeof(s));
  19356     s.handle.id = id;
  19357     s.w = w; s.h = h;
  19358     s.region[0] = (unsigned short)r.x;
  19359     s.region[1] = (unsigned short)r.y;
  19360     s.region[2] = (unsigned short)r.w;
  19361     s.region[3] = (unsigned short)r.h;
  19362     return s;
  19363 }
  19364 NK_API struct nk_image
  19365 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
  19366     struct nk_rect r)
  19367 {
  19368     struct nk_image s;
  19369     nk_zero(&s, sizeof(s));
  19370     s.handle = handle;
  19371     s.w = w; s.h = h;
  19372     s.region[0] = (unsigned short)r.x;
  19373     s.region[1] = (unsigned short)r.y;
  19374     s.region[2] = (unsigned short)r.w;
  19375     s.region[3] = (unsigned short)r.h;
  19376     return s;
  19377 }
  19378 NK_API struct nk_image
  19379 nk_image_handle(nk_handle handle)
  19380 {
  19381     struct nk_image s;
  19382     nk_zero(&s, sizeof(s));
  19383     s.handle = handle;
  19384     s.w = 0; s.h = 0;
  19385     s.region[0] = 0;
  19386     s.region[1] = 0;
  19387     s.region[2] = 0;
  19388     s.region[3] = 0;
  19389     return s;
  19390 }
  19391 NK_API struct nk_image
  19392 nk_image_ptr(void *ptr)
  19393 {
  19394     struct nk_image s;
  19395     nk_zero(&s, sizeof(s));
  19396     NK_ASSERT(ptr);
  19397     s.handle.ptr = ptr;
  19398     s.w = 0; s.h = 0;
  19399     s.region[0] = 0;
  19400     s.region[1] = 0;
  19401     s.region[2] = 0;
  19402     s.region[3] = 0;
  19403     return s;
  19404 }
  19405 NK_API struct nk_image
  19406 nk_image_id(int id)
  19407 {
  19408     struct nk_image s;
  19409     nk_zero(&s, sizeof(s));
  19410     s.handle.id = id;
  19411     s.w = 0; s.h = 0;
  19412     s.region[0] = 0;
  19413     s.region[1] = 0;
  19414     s.region[2] = 0;
  19415     s.region[3] = 0;
  19416     return s;
  19417 }
  19418 NK_API int
  19419 nk_image_is_subimage(const struct nk_image* img)
  19420 {
  19421     NK_ASSERT(img);
  19422     return !(img->w == 0 && img->h == 0);
  19423 }
  19424 NK_API void
  19425 nk_image(struct nk_context *ctx, struct nk_image img)
  19426 {
  19427     struct nk_window *win;
  19428     struct nk_rect bounds;
  19429 
  19430     NK_ASSERT(ctx);
  19431     NK_ASSERT(ctx->current);
  19432     NK_ASSERT(ctx->current->layout);
  19433     if (!ctx || !ctx->current || !ctx->current->layout) return;
  19434 
  19435     win = ctx->current;
  19436     if (!nk_widget(&bounds, ctx)) return;
  19437     nk_draw_image(&win->buffer, bounds, &img, nk_white);
  19438 }
  19439 NK_API void
  19440 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col)
  19441 {
  19442     struct nk_window *win;
  19443     struct nk_rect bounds;
  19444 
  19445     NK_ASSERT(ctx);
  19446     NK_ASSERT(ctx->current);
  19447     NK_ASSERT(ctx->current->layout);
  19448     if (!ctx || !ctx->current || !ctx->current->layout) return;
  19449 
  19450     win = ctx->current;
  19451     if (!nk_widget(&bounds, ctx)) return;
  19452     nk_draw_image(&win->buffer, bounds, &img, col);
  19453 }
  19454 
  19455 
  19456 
  19457 
  19458 
  19459 /* ==============================================================
  19460  *
  19461  *                          BUTTON
  19462  *
  19463  * ===============================================================*/
  19464 NK_LIB void
  19465 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
  19466     struct nk_rect content, struct nk_color background, struct nk_color foreground,
  19467     float border_width, const struct nk_user_font *font)
  19468 {
  19469     switch (type) {
  19470     case NK_SYMBOL_X:
  19471     case NK_SYMBOL_UNDERSCORE:
  19472     case NK_SYMBOL_PLUS:
  19473     case NK_SYMBOL_MINUS: {
  19474         /* single character text symbol */
  19475         const char *X = (type == NK_SYMBOL_X) ? "x":
  19476             (type == NK_SYMBOL_UNDERSCORE) ? "_":
  19477             (type == NK_SYMBOL_PLUS) ? "+": "-";
  19478         struct nk_text text;
  19479         text.padding = nk_vec2(0,0);
  19480         text.background = background;
  19481         text.text = foreground;
  19482         nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
  19483     } break;
  19484     case NK_SYMBOL_CIRCLE_SOLID:
  19485     case NK_SYMBOL_CIRCLE_OUTLINE:
  19486     case NK_SYMBOL_RECT_SOLID:
  19487     case NK_SYMBOL_RECT_OUTLINE: {
  19488         /* simple empty/filled shapes */
  19489         if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
  19490             nk_fill_rect(out, content,  0, foreground);
  19491             if (type == NK_SYMBOL_RECT_OUTLINE)
  19492                 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
  19493         } else {
  19494             nk_fill_circle(out, content, foreground);
  19495             if (type == NK_SYMBOL_CIRCLE_OUTLINE)
  19496                 nk_fill_circle(out, nk_shrink_rect(content, 1), background);
  19497         }
  19498     } break;
  19499     case NK_SYMBOL_TRIANGLE_UP:
  19500     case NK_SYMBOL_TRIANGLE_DOWN:
  19501     case NK_SYMBOL_TRIANGLE_LEFT:
  19502     case NK_SYMBOL_TRIANGLE_RIGHT: {
  19503         enum nk_heading heading;
  19504         struct nk_vec2 points[3];
  19505         heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
  19506             (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
  19507             (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
  19508         nk_triangle_from_direction(points, content, 0, 0, heading);
  19509         nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
  19510             points[2].x, points[2].y, foreground);
  19511     } break;
  19512     default:
  19513     case NK_SYMBOL_NONE:
  19514     case NK_SYMBOL_MAX: break;
  19515     }
  19516 }
  19517 NK_LIB int
  19518 nk_button_behavior(nk_flags *state, struct nk_rect r,
  19519     const struct nk_input *i, enum nk_button_behavior behavior)
  19520 {
  19521     int ret = 0;
  19522     nk_widget_state_reset(state);
  19523     if (!i) return 0;
  19524     if (nk_input_is_mouse_hovering_rect(i, r)) {
  19525         *state = NK_WIDGET_STATE_HOVERED;
  19526         if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT))
  19527             *state = NK_WIDGET_STATE_ACTIVE;
  19528         if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) {
  19529             ret = (behavior != NK_BUTTON_DEFAULT) ?
  19530                 nk_input_is_mouse_down(i, NK_BUTTON_LEFT):
  19531 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
  19532                 nk_input_is_mouse_released(i, NK_BUTTON_LEFT);
  19533 #else
  19534                 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT);
  19535 #endif
  19536         }
  19537     }
  19538     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r))
  19539         *state |= NK_WIDGET_STATE_ENTERED;
  19540     else if (nk_input_is_mouse_prev_hovering_rect(i, r))
  19541         *state |= NK_WIDGET_STATE_LEFT;
  19542     return ret;
  19543 }
  19544 NK_LIB const struct nk_style_item*
  19545 nk_draw_button(struct nk_command_buffer *out,
  19546     const struct nk_rect *bounds, nk_flags state,
  19547     const struct nk_style_button *style)
  19548 {
  19549     const struct nk_style_item *background;
  19550     if (state & NK_WIDGET_STATE_HOVER)
  19551         background = &style->hover;
  19552     else if (state & NK_WIDGET_STATE_ACTIVED)
  19553         background = &style->active;
  19554     else background = &style->normal;
  19555 
  19556     if (background->type == NK_STYLE_ITEM_IMAGE) {
  19557         nk_draw_image(out, *bounds, &background->data.image, nk_white);
  19558     } else {
  19559         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  19560         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
  19561     }
  19562     return background;
  19563 }
  19564 NK_LIB int
  19565 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
  19566     const struct nk_style_button *style, const struct nk_input *in,
  19567     enum nk_button_behavior behavior, struct nk_rect *content)
  19568 {
  19569     struct nk_rect bounds;
  19570     NK_ASSERT(style);
  19571     NK_ASSERT(state);
  19572     NK_ASSERT(out);
  19573     if (!out || !style)
  19574         return nk_false;
  19575 
  19576     /* calculate button content space */
  19577     content->x = r.x + style->padding.x + style->border + style->rounding;
  19578     content->y = r.y + style->padding.y + style->border + style->rounding;
  19579     content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
  19580     content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
  19581 
  19582     /* execute button behavior */
  19583     bounds.x = r.x - style->touch_padding.x;
  19584     bounds.y = r.y - style->touch_padding.y;
  19585     bounds.w = r.w + 2 * style->touch_padding.x;
  19586     bounds.h = r.h + 2 * style->touch_padding.y;
  19587     return nk_button_behavior(state, bounds, in, behavior);
  19588 }
  19589 NK_LIB void
  19590 nk_draw_button_text(struct nk_command_buffer *out,
  19591     const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
  19592     const struct nk_style_button *style, const char *txt, int len,
  19593     nk_flags text_alignment, const struct nk_user_font *font)
  19594 {
  19595     struct nk_text text;
  19596     const struct nk_style_item *background;
  19597     background = nk_draw_button(out, bounds, state, style);
  19598 
  19599     /* select correct colors/images */
  19600     if (background->type == NK_STYLE_ITEM_COLOR)
  19601         text.background = background->data.color;
  19602     else text.background = style->text_background;
  19603     if (state & NK_WIDGET_STATE_HOVER)
  19604         text.text = style->text_hover;
  19605     else if (state & NK_WIDGET_STATE_ACTIVED)
  19606         text.text = style->text_active;
  19607     else text.text = style->text_normal;
  19608 
  19609     text.padding = nk_vec2(0,0);
  19610     nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
  19611 }
  19612 NK_LIB int
  19613 nk_do_button_text(nk_flags *state,
  19614     struct nk_command_buffer *out, struct nk_rect bounds,
  19615     const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
  19616     const struct nk_style_button *style, const struct nk_input *in,
  19617     const struct nk_user_font *font)
  19618 {
  19619     struct nk_rect content;
  19620     int ret = nk_false;
  19621 
  19622     NK_ASSERT(state);
  19623     NK_ASSERT(style);
  19624     NK_ASSERT(out);
  19625     NK_ASSERT(string);
  19626     NK_ASSERT(font);
  19627     if (!out || !style || !font || !string)
  19628         return nk_false;
  19629 
  19630     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
  19631     if (style->draw_begin) style->draw_begin(out, style->userdata);
  19632     nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
  19633     if (style->draw_end) style->draw_end(out, style->userdata);
  19634     return ret;
  19635 }
  19636 NK_LIB void
  19637 nk_draw_button_symbol(struct nk_command_buffer *out,
  19638     const struct nk_rect *bounds, const struct nk_rect *content,
  19639     nk_flags state, const struct nk_style_button *style,
  19640     enum nk_symbol_type type, const struct nk_user_font *font)
  19641 {
  19642     struct nk_color sym, bg;
  19643     const struct nk_style_item *background;
  19644 
  19645     /* select correct colors/images */
  19646     background = nk_draw_button(out, bounds, state, style);
  19647     if (background->type == NK_STYLE_ITEM_COLOR)
  19648         bg = background->data.color;
  19649     else bg = style->text_background;
  19650 
  19651     if (state & NK_WIDGET_STATE_HOVER)
  19652         sym = style->text_hover;
  19653     else if (state & NK_WIDGET_STATE_ACTIVED)
  19654         sym = style->text_active;
  19655     else sym = style->text_normal;
  19656     nk_draw_symbol(out, type, *content, bg, sym, 1, font);
  19657 }
  19658 NK_LIB int
  19659 nk_do_button_symbol(nk_flags *state,
  19660     struct nk_command_buffer *out, struct nk_rect bounds,
  19661     enum nk_symbol_type symbol, enum nk_button_behavior behavior,
  19662     const struct nk_style_button *style, const struct nk_input *in,
  19663     const struct nk_user_font *font)
  19664 {
  19665     int ret;
  19666     struct nk_rect content;
  19667 
  19668     NK_ASSERT(state);
  19669     NK_ASSERT(style);
  19670     NK_ASSERT(font);
  19671     NK_ASSERT(out);
  19672     if (!out || !style || !font || !state)
  19673         return nk_false;
  19674 
  19675     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
  19676     if (style->draw_begin) style->draw_begin(out, style->userdata);
  19677     nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
  19678     if (style->draw_end) style->draw_end(out, style->userdata);
  19679     return ret;
  19680 }
  19681 NK_LIB void
  19682 nk_draw_button_image(struct nk_command_buffer *out,
  19683     const struct nk_rect *bounds, const struct nk_rect *content,
  19684     nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
  19685 {
  19686     nk_draw_button(out, bounds, state, style);
  19687     nk_draw_image(out, *content, img, nk_white);
  19688 }
  19689 NK_LIB int
  19690 nk_do_button_image(nk_flags *state,
  19691     struct nk_command_buffer *out, struct nk_rect bounds,
  19692     struct nk_image img, enum nk_button_behavior b,
  19693     const struct nk_style_button *style, const struct nk_input *in)
  19694 {
  19695     int ret;
  19696     struct nk_rect content;
  19697 
  19698     NK_ASSERT(state);
  19699     NK_ASSERT(style);
  19700     NK_ASSERT(out);
  19701     if (!out || !style || !state)
  19702         return nk_false;
  19703 
  19704     ret = nk_do_button(state, out, bounds, style, in, b, &content);
  19705     content.x += style->image_padding.x;
  19706     content.y += style->image_padding.y;
  19707     content.w -= 2 * style->image_padding.x;
  19708     content.h -= 2 * style->image_padding.y;
  19709 
  19710     if (style->draw_begin) style->draw_begin(out, style->userdata);
  19711     nk_draw_button_image(out, &bounds, &content, *state, style, &img);
  19712     if (style->draw_end) style->draw_end(out, style->userdata);
  19713     return ret;
  19714 }
  19715 NK_LIB void
  19716 nk_draw_button_text_symbol(struct nk_command_buffer *out,
  19717     const struct nk_rect *bounds, const struct nk_rect *label,
  19718     const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
  19719     const char *str, int len, enum nk_symbol_type type,
  19720     const struct nk_user_font *font)
  19721 {
  19722     struct nk_color sym;
  19723     struct nk_text text;
  19724     const struct nk_style_item *background;
  19725 
  19726     /* select correct background colors/images */
  19727     background = nk_draw_button(out, bounds, state, style);
  19728     if (background->type == NK_STYLE_ITEM_COLOR)
  19729         text.background = background->data.color;
  19730     else text.background = style->text_background;
  19731 
  19732     /* select correct text colors */
  19733     if (state & NK_WIDGET_STATE_HOVER) {
  19734         sym = style->text_hover;
  19735         text.text = style->text_hover;
  19736     } else if (state & NK_WIDGET_STATE_ACTIVED) {
  19737         sym = style->text_active;
  19738         text.text = style->text_active;
  19739     } else {
  19740         sym = style->text_normal;
  19741         text.text = style->text_normal;
  19742     }
  19743 
  19744     text.padding = nk_vec2(0,0);
  19745     nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
  19746     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
  19747 }
  19748 NK_LIB int
  19749 nk_do_button_text_symbol(nk_flags *state,
  19750     struct nk_command_buffer *out, struct nk_rect bounds,
  19751     enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
  19752     enum nk_button_behavior behavior, const struct nk_style_button *style,
  19753     const struct nk_user_font *font, const struct nk_input *in)
  19754 {
  19755     int ret;
  19756     struct nk_rect tri = {0,0,0,0};
  19757     struct nk_rect content;
  19758 
  19759     NK_ASSERT(style);
  19760     NK_ASSERT(out);
  19761     NK_ASSERT(font);
  19762     if (!out || !style || !font)
  19763         return nk_false;
  19764 
  19765     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
  19766     tri.y = content.y + (content.h/2) - font->height/2;
  19767     tri.w = font->height; tri.h = font->height;
  19768     if (align & NK_TEXT_ALIGN_LEFT) {
  19769         tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
  19770         tri.x = NK_MAX(tri.x, 0);
  19771     } else tri.x = content.x + 2 * style->padding.x;
  19772 
  19773     /* draw button */
  19774     if (style->draw_begin) style->draw_begin(out, style->userdata);
  19775     nk_draw_button_text_symbol(out, &bounds, &content, &tri,
  19776         *state, style, str, len, symbol, font);
  19777     if (style->draw_end) style->draw_end(out, style->userdata);
  19778     return ret;
  19779 }
  19780 NK_LIB void
  19781 nk_draw_button_text_image(struct nk_command_buffer *out,
  19782     const struct nk_rect *bounds, const struct nk_rect *label,
  19783     const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
  19784     const char *str, int len, const struct nk_user_font *font,
  19785     const struct nk_image *img)
  19786 {
  19787     struct nk_text text;
  19788     const struct nk_style_item *background;
  19789     background = nk_draw_button(out, bounds, state, style);
  19790 
  19791     /* select correct colors */
  19792     if (background->type == NK_STYLE_ITEM_COLOR)
  19793         text.background = background->data.color;
  19794     else text.background = style->text_background;
  19795     if (state & NK_WIDGET_STATE_HOVER)
  19796         text.text = style->text_hover;
  19797     else if (state & NK_WIDGET_STATE_ACTIVED)
  19798         text.text = style->text_active;
  19799     else text.text = style->text_normal;
  19800 
  19801     text.padding = nk_vec2(0,0);
  19802     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
  19803     nk_draw_image(out, *image, img, nk_white);
  19804 }
  19805 NK_LIB int
  19806 nk_do_button_text_image(nk_flags *state,
  19807     struct nk_command_buffer *out, struct nk_rect bounds,
  19808     struct nk_image img, const char* str, int len, nk_flags align,
  19809     enum nk_button_behavior behavior, const struct nk_style_button *style,
  19810     const struct nk_user_font *font, const struct nk_input *in)
  19811 {
  19812     int ret;
  19813     struct nk_rect icon;
  19814     struct nk_rect content;
  19815 
  19816     NK_ASSERT(style);
  19817     NK_ASSERT(state);
  19818     NK_ASSERT(font);
  19819     NK_ASSERT(out);
  19820     if (!out || !font || !style || !str)
  19821         return nk_false;
  19822 
  19823     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
  19824     icon.y = bounds.y + style->padding.y;
  19825     icon.w = icon.h = bounds.h - 2 * style->padding.y;
  19826     if (align & NK_TEXT_ALIGN_LEFT) {
  19827         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
  19828         icon.x = NK_MAX(icon.x, 0);
  19829     } else icon.x = bounds.x + 2 * style->padding.x;
  19830 
  19831     icon.x += style->image_padding.x;
  19832     icon.y += style->image_padding.y;
  19833     icon.w -= 2 * style->image_padding.x;
  19834     icon.h -= 2 * style->image_padding.y;
  19835 
  19836     if (style->draw_begin) style->draw_begin(out, style->userdata);
  19837     nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
  19838     if (style->draw_end) style->draw_end(out, style->userdata);
  19839     return ret;
  19840 }
  19841 NK_API void
  19842 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
  19843 {
  19844     NK_ASSERT(ctx);
  19845     if (!ctx) return;
  19846     ctx->button_behavior = behavior;
  19847 }
  19848 NK_API int
  19849 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
  19850 {
  19851     struct nk_config_stack_button_behavior *button_stack;
  19852     struct nk_config_stack_button_behavior_element *element;
  19853 
  19854     NK_ASSERT(ctx);
  19855     if (!ctx) return 0;
  19856 
  19857     button_stack = &ctx->stacks.button_behaviors;
  19858     NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
  19859     if (button_stack->head >= (int)NK_LEN(button_stack->elements))
  19860         return 0;
  19861 
  19862     element = &button_stack->elements[button_stack->head++];
  19863     element->address = &ctx->button_behavior;
  19864     element->old_value = ctx->button_behavior;
  19865     ctx->button_behavior = behavior;
  19866     return 1;
  19867 }
  19868 NK_API int
  19869 nk_button_pop_behavior(struct nk_context *ctx)
  19870 {
  19871     struct nk_config_stack_button_behavior *button_stack;
  19872     struct nk_config_stack_button_behavior_element *element;
  19873 
  19874     NK_ASSERT(ctx);
  19875     if (!ctx) return 0;
  19876 
  19877     button_stack = &ctx->stacks.button_behaviors;
  19878     NK_ASSERT(button_stack->head > 0);
  19879     if (button_stack->head < 1)
  19880         return 0;
  19881 
  19882     element = &button_stack->elements[--button_stack->head];
  19883     *element->address = element->old_value;
  19884     return 1;
  19885 }
  19886 NK_API int
  19887 nk_button_text_styled(struct nk_context *ctx,
  19888     const struct nk_style_button *style, const char *title, int len)
  19889 {
  19890     struct nk_window *win;
  19891     struct nk_panel *layout;
  19892     const struct nk_input *in;
  19893 
  19894     struct nk_rect bounds;
  19895     enum nk_widget_layout_states state;
  19896 
  19897     NK_ASSERT(ctx);
  19898     NK_ASSERT(style);
  19899     NK_ASSERT(ctx->current);
  19900     NK_ASSERT(ctx->current->layout);
  19901     if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
  19902 
  19903     win = ctx->current;
  19904     layout = win->layout;
  19905     state = nk_widget(&bounds, ctx);
  19906 
  19907     if (!state) return 0;
  19908     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  19909     return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
  19910                     title, len, style->text_alignment, ctx->button_behavior,
  19911                     style, in, ctx->style.font);
  19912 }
  19913 NK_API int
  19914 nk_button_text(struct nk_context *ctx, const char *title, int len)
  19915 {
  19916     NK_ASSERT(ctx);
  19917     if (!ctx) return 0;
  19918     return nk_button_text_styled(ctx, &ctx->style.button, title, len);
  19919 }
  19920 NK_API int nk_button_label_styled(struct nk_context *ctx,
  19921     const struct nk_style_button *style, const char *title)
  19922 {
  19923     return nk_button_text_styled(ctx, style, title, nk_strlen(title));
  19924 }
  19925 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
  19926 {
  19927     return nk_button_text(ctx, title, nk_strlen(title));
  19928 }
  19929 NK_API int
  19930 nk_button_color(struct nk_context *ctx, struct nk_color color)
  19931 {
  19932     struct nk_window *win;
  19933     struct nk_panel *layout;
  19934     const struct nk_input *in;
  19935     struct nk_style_button button;
  19936 
  19937     int ret = 0;
  19938     struct nk_rect bounds;
  19939     struct nk_rect content;
  19940     enum nk_widget_layout_states state;
  19941 
  19942     NK_ASSERT(ctx);
  19943     NK_ASSERT(ctx->current);
  19944     NK_ASSERT(ctx->current->layout);
  19945     if (!ctx || !ctx->current || !ctx->current->layout)
  19946         return 0;
  19947 
  19948     win = ctx->current;
  19949     layout = win->layout;
  19950 
  19951     state = nk_widget(&bounds, ctx);
  19952     if (!state) return 0;
  19953     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  19954 
  19955     button = ctx->style.button;
  19956     button.normal = nk_style_item_color(color);
  19957     button.hover = nk_style_item_color(color);
  19958     button.active = nk_style_item_color(color);
  19959     ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
  19960                 &button, in, ctx->button_behavior, &content);
  19961     nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
  19962     return ret;
  19963 }
  19964 NK_API int
  19965 nk_button_symbol_styled(struct nk_context *ctx,
  19966     const struct nk_style_button *style, enum nk_symbol_type symbol)
  19967 {
  19968     struct nk_window *win;
  19969     struct nk_panel *layout;
  19970     const struct nk_input *in;
  19971 
  19972     struct nk_rect bounds;
  19973     enum nk_widget_layout_states state;
  19974 
  19975     NK_ASSERT(ctx);
  19976     NK_ASSERT(ctx->current);
  19977     NK_ASSERT(ctx->current->layout);
  19978     if (!ctx || !ctx->current || !ctx->current->layout)
  19979         return 0;
  19980 
  19981     win = ctx->current;
  19982     layout = win->layout;
  19983     state = nk_widget(&bounds, ctx);
  19984     if (!state) return 0;
  19985     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  19986     return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
  19987             symbol, ctx->button_behavior, style, in, ctx->style.font);
  19988 }
  19989 NK_API int
  19990 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
  19991 {
  19992     NK_ASSERT(ctx);
  19993     if (!ctx) return 0;
  19994     return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
  19995 }
  19996 NK_API int
  19997 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
  19998     struct nk_image img)
  19999 {
  20000     struct nk_window *win;
  20001     struct nk_panel *layout;
  20002     const struct nk_input *in;
  20003 
  20004     struct nk_rect bounds;
  20005     enum nk_widget_layout_states state;
  20006 
  20007     NK_ASSERT(ctx);
  20008     NK_ASSERT(ctx->current);
  20009     NK_ASSERT(ctx->current->layout);
  20010     if (!ctx || !ctx->current || !ctx->current->layout)
  20011         return 0;
  20012 
  20013     win = ctx->current;
  20014     layout = win->layout;
  20015 
  20016     state = nk_widget(&bounds, ctx);
  20017     if (!state) return 0;
  20018     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20019     return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
  20020                 img, ctx->button_behavior, style, in);
  20021 }
  20022 NK_API int
  20023 nk_button_image(struct nk_context *ctx, struct nk_image img)
  20024 {
  20025     NK_ASSERT(ctx);
  20026     if (!ctx) return 0;
  20027     return nk_button_image_styled(ctx, &ctx->style.button, img);
  20028 }
  20029 NK_API int
  20030 nk_button_symbol_text_styled(struct nk_context *ctx,
  20031     const struct nk_style_button *style, enum nk_symbol_type symbol,
  20032     const char *text, int len, nk_flags align)
  20033 {
  20034     struct nk_window *win;
  20035     struct nk_panel *layout;
  20036     const struct nk_input *in;
  20037 
  20038     struct nk_rect bounds;
  20039     enum nk_widget_layout_states state;
  20040 
  20041     NK_ASSERT(ctx);
  20042     NK_ASSERT(ctx->current);
  20043     NK_ASSERT(ctx->current->layout);
  20044     if (!ctx || !ctx->current || !ctx->current->layout)
  20045         return 0;
  20046 
  20047     win = ctx->current;
  20048     layout = win->layout;
  20049 
  20050     state = nk_widget(&bounds, ctx);
  20051     if (!state) return 0;
  20052     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20053     return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
  20054                 symbol, text, len, align, ctx->button_behavior,
  20055                 style, ctx->style.font, in);
  20056 }
  20057 NK_API int
  20058 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
  20059     const char* text, int len, nk_flags align)
  20060 {
  20061     NK_ASSERT(ctx);
  20062     if (!ctx) return 0;
  20063     return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
  20064 }
  20065 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
  20066     const char *label, nk_flags align)
  20067 {
  20068     return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);
  20069 }
  20070 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx,
  20071     const struct nk_style_button *style, enum nk_symbol_type symbol,
  20072     const char *title, nk_flags align)
  20073 {
  20074     return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);
  20075 }
  20076 NK_API int
  20077 nk_button_image_text_styled(struct nk_context *ctx,
  20078     const struct nk_style_button *style, struct nk_image img, const char *text,
  20079     int len, nk_flags align)
  20080 {
  20081     struct nk_window *win;
  20082     struct nk_panel *layout;
  20083     const struct nk_input *in;
  20084 
  20085     struct nk_rect bounds;
  20086     enum nk_widget_layout_states state;
  20087 
  20088     NK_ASSERT(ctx);
  20089     NK_ASSERT(ctx->current);
  20090     NK_ASSERT(ctx->current->layout);
  20091     if (!ctx || !ctx->current || !ctx->current->layout)
  20092         return 0;
  20093 
  20094     win = ctx->current;
  20095     layout = win->layout;
  20096 
  20097     state = nk_widget(&bounds, ctx);
  20098     if (!state) return 0;
  20099     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20100     return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
  20101             bounds, img, text, len, align, ctx->button_behavior,
  20102             style, ctx->style.font, in);
  20103 }
  20104 NK_API int
  20105 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
  20106     const char *text, int len, nk_flags align)
  20107 {
  20108     return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);
  20109 }
  20110 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
  20111     const char *label, nk_flags align)
  20112 {
  20113     return nk_button_image_text(ctx, img, label, nk_strlen(label), align);
  20114 }
  20115 NK_API int nk_button_image_label_styled(struct nk_context *ctx,
  20116     const struct nk_style_button *style, struct nk_image img,
  20117     const char *label, nk_flags text_alignment)
  20118 {
  20119     return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);
  20120 }
  20121 
  20122 
  20123 
  20124 
  20125 
  20126 /* ===============================================================
  20127  *
  20128  *                              TOGGLE
  20129  *
  20130  * ===============================================================*/
  20131 NK_LIB int
  20132 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
  20133     nk_flags *state, int active)
  20134 {
  20135     nk_widget_state_reset(state);
  20136     if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
  20137         *state = NK_WIDGET_STATE_ACTIVE;
  20138         active = !active;
  20139     }
  20140     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
  20141         *state |= NK_WIDGET_STATE_ENTERED;
  20142     else if (nk_input_is_mouse_prev_hovering_rect(in, select))
  20143         *state |= NK_WIDGET_STATE_LEFT;
  20144     return active;
  20145 }
  20146 NK_LIB void
  20147 nk_draw_checkbox(struct nk_command_buffer *out,
  20148     nk_flags state, const struct nk_style_toggle *style, int active,
  20149     const struct nk_rect *label, const struct nk_rect *selector,
  20150     const struct nk_rect *cursors, const char *string, int len,
  20151     const struct nk_user_font *font)
  20152 {
  20153     const struct nk_style_item *background;
  20154     const struct nk_style_item *cursor;
  20155     struct nk_text text;
  20156 
  20157     /* select correct colors/images */
  20158     if (state & NK_WIDGET_STATE_HOVER) {
  20159         background = &style->hover;
  20160         cursor = &style->cursor_hover;
  20161         text.text = style->text_hover;
  20162     } else if (state & NK_WIDGET_STATE_ACTIVED) {
  20163         background = &style->hover;
  20164         cursor = &style->cursor_hover;
  20165         text.text = style->text_active;
  20166     } else {
  20167         background = &style->normal;
  20168         cursor = &style->cursor_normal;
  20169         text.text = style->text_normal;
  20170     }
  20171 
  20172     /* draw background and cursor */
  20173     if (background->type == NK_STYLE_ITEM_COLOR) {
  20174         nk_fill_rect(out, *selector, 0, style->border_color);
  20175         nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
  20176     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
  20177     if (active) {
  20178         if (cursor->type == NK_STYLE_ITEM_IMAGE)
  20179             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
  20180         else nk_fill_rect(out, *cursors, 0, cursor->data.color);
  20181     }
  20182 
  20183     text.padding.x = 0;
  20184     text.padding.y = 0;
  20185     text.background = style->text_background;
  20186     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
  20187 }
  20188 NK_LIB void
  20189 nk_draw_option(struct nk_command_buffer *out,
  20190     nk_flags state, const struct nk_style_toggle *style, int active,
  20191     const struct nk_rect *label, const struct nk_rect *selector,
  20192     const struct nk_rect *cursors, const char *string, int len,
  20193     const struct nk_user_font *font)
  20194 {
  20195     const struct nk_style_item *background;
  20196     const struct nk_style_item *cursor;
  20197     struct nk_text text;
  20198 
  20199     /* select correct colors/images */
  20200     if (state & NK_WIDGET_STATE_HOVER) {
  20201         background = &style->hover;
  20202         cursor = &style->cursor_hover;
  20203         text.text = style->text_hover;
  20204     } else if (state & NK_WIDGET_STATE_ACTIVED) {
  20205         background = &style->hover;
  20206         cursor = &style->cursor_hover;
  20207         text.text = style->text_active;
  20208     } else {
  20209         background = &style->normal;
  20210         cursor = &style->cursor_normal;
  20211         text.text = style->text_normal;
  20212     }
  20213 
  20214     /* draw background and cursor */
  20215     if (background->type == NK_STYLE_ITEM_COLOR) {
  20216         nk_fill_circle(out, *selector, style->border_color);
  20217         nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
  20218     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
  20219     if (active) {
  20220         if (cursor->type == NK_STYLE_ITEM_IMAGE)
  20221             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
  20222         else nk_fill_circle(out, *cursors, cursor->data.color);
  20223     }
  20224 
  20225     text.padding.x = 0;
  20226     text.padding.y = 0;
  20227     text.background = style->text_background;
  20228     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
  20229 }
  20230 NK_LIB int
  20231 nk_do_toggle(nk_flags *state,
  20232     struct nk_command_buffer *out, struct nk_rect r,
  20233     int *active, const char *str, int len, enum nk_toggle_type type,
  20234     const struct nk_style_toggle *style, const struct nk_input *in,
  20235     const struct nk_user_font *font)
  20236 {
  20237     int was_active;
  20238     struct nk_rect bounds;
  20239     struct nk_rect select;
  20240     struct nk_rect cursor;
  20241     struct nk_rect label;
  20242 
  20243     NK_ASSERT(style);
  20244     NK_ASSERT(out);
  20245     NK_ASSERT(font);
  20246     if (!out || !style || !font || !active)
  20247         return 0;
  20248 
  20249     r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
  20250     r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
  20251 
  20252     /* add additional touch padding for touch screen devices */
  20253     bounds.x = r.x - style->touch_padding.x;
  20254     bounds.y = r.y - style->touch_padding.y;
  20255     bounds.w = r.w + 2 * style->touch_padding.x;
  20256     bounds.h = r.h + 2 * style->touch_padding.y;
  20257 
  20258     /* calculate the selector space */
  20259     select.w = font->height;
  20260     select.h = select.w;
  20261     select.y = r.y + r.h/2.0f - select.h/2.0f;
  20262     select.x = r.x;
  20263 
  20264     /* calculate the bounds of the cursor inside the selector */
  20265     cursor.x = select.x + style->padding.x + style->border;
  20266     cursor.y = select.y + style->padding.y + style->border;
  20267     cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
  20268     cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
  20269 
  20270     /* label behind the selector */
  20271     label.x = select.x + select.w + style->spacing;
  20272     label.y = select.y;
  20273     label.w = NK_MAX(r.x + r.w, label.x) - label.x;
  20274     label.h = select.w;
  20275 
  20276     /* update selector */
  20277     was_active = *active;
  20278     *active = nk_toggle_behavior(in, bounds, state, *active);
  20279 
  20280     /* draw selector */
  20281     if (style->draw_begin)
  20282         style->draw_begin(out, style->userdata);
  20283     if (type == NK_TOGGLE_CHECK) {
  20284         nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
  20285     } else {
  20286         nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
  20287     }
  20288     if (style->draw_end)
  20289         style->draw_end(out, style->userdata);
  20290     return (was_active != *active);
  20291 }
  20292 /*----------------------------------------------------------------
  20293  *
  20294  *                          CHECKBOX
  20295  *
  20296  * --------------------------------------------------------------*/
  20297 NK_API int
  20298 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
  20299 {
  20300     struct nk_window *win;
  20301     struct nk_panel *layout;
  20302     const struct nk_input *in;
  20303     const struct nk_style *style;
  20304 
  20305     struct nk_rect bounds;
  20306     enum nk_widget_layout_states state;
  20307 
  20308     NK_ASSERT(ctx);
  20309     NK_ASSERT(ctx->current);
  20310     NK_ASSERT(ctx->current->layout);
  20311     if (!ctx || !ctx->current || !ctx->current->layout)
  20312         return active;
  20313 
  20314     win = ctx->current;
  20315     style = &ctx->style;
  20316     layout = win->layout;
  20317 
  20318     state = nk_widget(&bounds, ctx);
  20319     if (!state) return active;
  20320     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20321     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
  20322         text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
  20323     return active;
  20324 }
  20325 NK_API unsigned int
  20326 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
  20327     unsigned int flags, unsigned int value)
  20328 {
  20329     int old_active;
  20330     NK_ASSERT(ctx);
  20331     NK_ASSERT(text);
  20332     if (!ctx || !text) return flags;
  20333     old_active = (int)((flags & value) & value);
  20334     if (nk_check_text(ctx, text, len, old_active))
  20335         flags |= value;
  20336     else flags &= ~value;
  20337     return flags;
  20338 }
  20339 NK_API int
  20340 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
  20341 {
  20342     int old_val;
  20343     NK_ASSERT(ctx);
  20344     NK_ASSERT(text);
  20345     NK_ASSERT(active);
  20346     if (!ctx || !text || !active) return 0;
  20347     old_val = *active;
  20348     *active = nk_check_text(ctx, text, len, *active);
  20349     return old_val != *active;
  20350 }
  20351 NK_API int
  20352 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
  20353     unsigned int *flags, unsigned int value)
  20354 {
  20355     int active;
  20356     NK_ASSERT(ctx);
  20357     NK_ASSERT(text);
  20358     NK_ASSERT(flags);
  20359     if (!ctx || !text || !flags) return 0;
  20360 
  20361     active = (int)((*flags & value) & value);
  20362     if (nk_checkbox_text(ctx, text, len, &active)) {
  20363         if (active) *flags |= value;
  20364         else *flags &= ~value;
  20365         return 1;
  20366     }
  20367     return 0;
  20368 }
  20369 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
  20370 {
  20371     return nk_check_text(ctx, label, nk_strlen(label), active);
  20372 }
  20373 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
  20374     unsigned int flags, unsigned int value)
  20375 {
  20376     return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);
  20377 }
  20378 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
  20379 {
  20380     return nk_checkbox_text(ctx, label, nk_strlen(label), active);
  20381 }
  20382 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
  20383     unsigned int *flags, unsigned int value)
  20384 {
  20385     return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);
  20386 }
  20387 /*----------------------------------------------------------------
  20388  *
  20389  *                          OPTION
  20390  *
  20391  * --------------------------------------------------------------*/
  20392 NK_API int
  20393 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
  20394 {
  20395     struct nk_window *win;
  20396     struct nk_panel *layout;
  20397     const struct nk_input *in;
  20398     const struct nk_style *style;
  20399 
  20400     struct nk_rect bounds;
  20401     enum nk_widget_layout_states state;
  20402 
  20403     NK_ASSERT(ctx);
  20404     NK_ASSERT(ctx->current);
  20405     NK_ASSERT(ctx->current->layout);
  20406     if (!ctx || !ctx->current || !ctx->current->layout)
  20407         return is_active;
  20408 
  20409     win = ctx->current;
  20410     style = &ctx->style;
  20411     layout = win->layout;
  20412 
  20413     state = nk_widget(&bounds, ctx);
  20414     if (!state) return (int)state;
  20415     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20416     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
  20417         text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
  20418     return is_active;
  20419 }
  20420 NK_API int
  20421 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
  20422 {
  20423     int old_value;
  20424     NK_ASSERT(ctx);
  20425     NK_ASSERT(text);
  20426     NK_ASSERT(active);
  20427     if (!ctx || !text || !active) return 0;
  20428     old_value = *active;
  20429     *active = nk_option_text(ctx, text, len, old_value);
  20430     return old_value != *active;
  20431 }
  20432 NK_API int
  20433 nk_option_label(struct nk_context *ctx, const char *label, int active)
  20434 {
  20435     return nk_option_text(ctx, label, nk_strlen(label), active);
  20436 }
  20437 NK_API int
  20438 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
  20439 {
  20440     return nk_radio_text(ctx, label, nk_strlen(label), active);
  20441 }
  20442 
  20443 
  20444 
  20445 
  20446 
  20447 /* ===============================================================
  20448  *
  20449  *                              SELECTABLE
  20450  *
  20451  * ===============================================================*/
  20452 NK_LIB void
  20453 nk_draw_selectable(struct nk_command_buffer *out,
  20454     nk_flags state, const struct nk_style_selectable *style, int active,
  20455     const struct nk_rect *bounds,
  20456     const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym,
  20457     const char *string, int len, nk_flags align, const struct nk_user_font *font)
  20458 {
  20459     const struct nk_style_item *background;
  20460     struct nk_text text;
  20461     text.padding = style->padding;
  20462 
  20463     /* select correct colors/images */
  20464     if (!active) {
  20465         if (state & NK_WIDGET_STATE_ACTIVED) {
  20466             background = &style->pressed;
  20467             text.text = style->text_pressed;
  20468         } else if (state & NK_WIDGET_STATE_HOVER) {
  20469             background = &style->hover;
  20470             text.text = style->text_hover;
  20471         } else {
  20472             background = &style->normal;
  20473             text.text = style->text_normal;
  20474         }
  20475     } else {
  20476         if (state & NK_WIDGET_STATE_ACTIVED) {
  20477             background = &style->pressed_active;
  20478             text.text = style->text_pressed_active;
  20479         } else if (state & NK_WIDGET_STATE_HOVER) {
  20480             background = &style->hover_active;
  20481             text.text = style->text_hover_active;
  20482         } else {
  20483             background = &style->normal_active;
  20484             text.text = style->text_normal_active;
  20485         }
  20486     }
  20487     /* draw selectable background and text */
  20488     if (background->type == NK_STYLE_ITEM_IMAGE) {
  20489         nk_draw_image(out, *bounds, &background->data.image, nk_white);
  20490         text.background = nk_rgba(0,0,0,0);
  20491     } else {
  20492         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  20493         text.background = background->data.color;
  20494     }
  20495     if (icon) {
  20496         if (img) nk_draw_image(out, *icon, img, nk_white);
  20497         else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font);
  20498     }
  20499     nk_widget_text(out, *bounds, string, len, &text, align, font);
  20500 }
  20501 NK_LIB int
  20502 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
  20503     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
  20504     const struct nk_style_selectable *style, const struct nk_input *in,
  20505     const struct nk_user_font *font)
  20506 {
  20507     int old_value;
  20508     struct nk_rect touch;
  20509 
  20510     NK_ASSERT(state);
  20511     NK_ASSERT(out);
  20512     NK_ASSERT(str);
  20513     NK_ASSERT(len);
  20514     NK_ASSERT(value);
  20515     NK_ASSERT(style);
  20516     NK_ASSERT(font);
  20517 
  20518     if (!state || !out || !str || !len || !value || !style || !font) return 0;
  20519     old_value = *value;
  20520 
  20521     /* remove padding */
  20522     touch.x = bounds.x - style->touch_padding.x;
  20523     touch.y = bounds.y - style->touch_padding.y;
  20524     touch.w = bounds.w + style->touch_padding.x * 2;
  20525     touch.h = bounds.h + style->touch_padding.y * 2;
  20526 
  20527     /* update button */
  20528     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
  20529         *value = !(*value);
  20530 
  20531     /* draw selectable */
  20532     if (style->draw_begin) style->draw_begin(out, style->userdata);
  20533     nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font);
  20534     if (style->draw_end) style->draw_end(out, style->userdata);
  20535     return old_value != *value;
  20536 }
  20537 NK_LIB int
  20538 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
  20539     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
  20540     const struct nk_image *img, const struct nk_style_selectable *style,
  20541     const struct nk_input *in, const struct nk_user_font *font)
  20542 {
  20543     int old_value;
  20544     struct nk_rect touch;
  20545     struct nk_rect icon;
  20546 
  20547     NK_ASSERT(state);
  20548     NK_ASSERT(out);
  20549     NK_ASSERT(str);
  20550     NK_ASSERT(len);
  20551     NK_ASSERT(value);
  20552     NK_ASSERT(style);
  20553     NK_ASSERT(font);
  20554 
  20555     if (!state || !out || !str || !len || !value || !style || !font) return 0;
  20556     old_value = *value;
  20557 
  20558     /* toggle behavior */
  20559     touch.x = bounds.x - style->touch_padding.x;
  20560     touch.y = bounds.y - style->touch_padding.y;
  20561     touch.w = bounds.w + style->touch_padding.x * 2;
  20562     touch.h = bounds.h + style->touch_padding.y * 2;
  20563     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
  20564         *value = !(*value);
  20565 
  20566     icon.y = bounds.y + style->padding.y;
  20567     icon.w = icon.h = bounds.h - 2 * style->padding.y;
  20568     if (align & NK_TEXT_ALIGN_LEFT) {
  20569         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
  20570         icon.x = NK_MAX(icon.x, 0);
  20571     } else icon.x = bounds.x + 2 * style->padding.x;
  20572 
  20573     icon.x += style->image_padding.x;
  20574     icon.y += style->image_padding.y;
  20575     icon.w -= 2 * style->image_padding.x;
  20576     icon.h -= 2 * style->image_padding.y;
  20577 
  20578     /* draw selectable */
  20579     if (style->draw_begin) style->draw_begin(out, style->userdata);
  20580     nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font);
  20581     if (style->draw_end) style->draw_end(out, style->userdata);
  20582     return old_value != *value;
  20583 }
  20584 NK_LIB int
  20585 nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out,
  20586     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
  20587     enum nk_symbol_type sym, const struct nk_style_selectable *style,
  20588     const struct nk_input *in, const struct nk_user_font *font)
  20589 {
  20590     int old_value;
  20591     struct nk_rect touch;
  20592     struct nk_rect icon;
  20593 
  20594     NK_ASSERT(state);
  20595     NK_ASSERT(out);
  20596     NK_ASSERT(str);
  20597     NK_ASSERT(len);
  20598     NK_ASSERT(value);
  20599     NK_ASSERT(style);
  20600     NK_ASSERT(font);
  20601 
  20602     if (!state || !out || !str || !len || !value || !style || !font) return 0;
  20603     old_value = *value;
  20604 
  20605     /* toggle behavior */
  20606     touch.x = bounds.x - style->touch_padding.x;
  20607     touch.y = bounds.y - style->touch_padding.y;
  20608     touch.w = bounds.w + style->touch_padding.x * 2;
  20609     touch.h = bounds.h + style->touch_padding.y * 2;
  20610     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
  20611         *value = !(*value);
  20612 
  20613     icon.y = bounds.y + style->padding.y;
  20614     icon.w = icon.h = bounds.h - 2 * style->padding.y;
  20615     if (align & NK_TEXT_ALIGN_LEFT) {
  20616         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
  20617         icon.x = NK_MAX(icon.x, 0);
  20618     } else icon.x = bounds.x + 2 * style->padding.x;
  20619 
  20620     icon.x += style->image_padding.x;
  20621     icon.y += style->image_padding.y;
  20622     icon.w -= 2 * style->image_padding.x;
  20623     icon.h -= 2 * style->image_padding.y;
  20624 
  20625     /* draw selectable */
  20626     if (style->draw_begin) style->draw_begin(out, style->userdata);
  20627     nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font);
  20628     if (style->draw_end) style->draw_end(out, style->userdata);
  20629     return old_value != *value;
  20630 }
  20631 
  20632 NK_API int
  20633 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
  20634     nk_flags align, int *value)
  20635 {
  20636     struct nk_window *win;
  20637     struct nk_panel *layout;
  20638     const struct nk_input *in;
  20639     const struct nk_style *style;
  20640 
  20641     enum nk_widget_layout_states state;
  20642     struct nk_rect bounds;
  20643 
  20644     NK_ASSERT(ctx);
  20645     NK_ASSERT(value);
  20646     NK_ASSERT(ctx->current);
  20647     NK_ASSERT(ctx->current->layout);
  20648     if (!ctx || !ctx->current || !ctx->current->layout || !value)
  20649         return 0;
  20650 
  20651     win = ctx->current;
  20652     layout = win->layout;
  20653     style = &ctx->style;
  20654 
  20655     state = nk_widget(&bounds, ctx);
  20656     if (!state) return 0;
  20657     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20658     return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
  20659                 str, len, align, value, &style->selectable, in, style->font);
  20660 }
  20661 NK_API int
  20662 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
  20663     const char *str, int len, nk_flags align, int *value)
  20664 {
  20665     struct nk_window *win;
  20666     struct nk_panel *layout;
  20667     const struct nk_input *in;
  20668     const struct nk_style *style;
  20669 
  20670     enum nk_widget_layout_states state;
  20671     struct nk_rect bounds;
  20672 
  20673     NK_ASSERT(ctx);
  20674     NK_ASSERT(value);
  20675     NK_ASSERT(ctx->current);
  20676     NK_ASSERT(ctx->current->layout);
  20677     if (!ctx || !ctx->current || !ctx->current->layout || !value)
  20678         return 0;
  20679 
  20680     win = ctx->current;
  20681     layout = win->layout;
  20682     style = &ctx->style;
  20683 
  20684     state = nk_widget(&bounds, ctx);
  20685     if (!state) return 0;
  20686     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20687     return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
  20688                 str, len, align, value, &img, &style->selectable, in, style->font);
  20689 }
  20690 NK_API int
  20691 nk_selectable_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  20692     const char *str, int len, nk_flags align, int *value)
  20693 {
  20694     struct nk_window *win;
  20695     struct nk_panel *layout;
  20696     const struct nk_input *in;
  20697     const struct nk_style *style;
  20698 
  20699     enum nk_widget_layout_states state;
  20700     struct nk_rect bounds;
  20701 
  20702     NK_ASSERT(ctx);
  20703     NK_ASSERT(value);
  20704     NK_ASSERT(ctx->current);
  20705     NK_ASSERT(ctx->current->layout);
  20706     if (!ctx || !ctx->current || !ctx->current->layout || !value)
  20707         return 0;
  20708 
  20709     win = ctx->current;
  20710     layout = win->layout;
  20711     style = &ctx->style;
  20712 
  20713     state = nk_widget(&bounds, ctx);
  20714     if (!state) return 0;
  20715     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20716     return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds,
  20717                 str, len, align, value, sym, &style->selectable, in, style->font);
  20718 }
  20719 NK_API int
  20720 nk_selectable_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  20721     const char *title, nk_flags align, int *value)
  20722 {
  20723     return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
  20724 }
  20725 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
  20726     nk_flags align, int value)
  20727 {
  20728     nk_selectable_text(ctx, str, len, align, &value);return value;
  20729 }
  20730 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
  20731 {
  20732     return nk_selectable_text(ctx, str, nk_strlen(str), align, value);
  20733 }
  20734 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
  20735     const char *str, nk_flags align, int *value)
  20736 {
  20737     return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);
  20738 }
  20739 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
  20740 {
  20741     nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;
  20742 }
  20743 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
  20744     const char *str, nk_flags align, int value)
  20745 {
  20746     nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;
  20747 }
  20748 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
  20749     const char *str, int len, nk_flags align, int value)
  20750 {
  20751     nk_selectable_image_text(ctx, img, str, len, align, &value);return value;
  20752 }
  20753 NK_API int
  20754 nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  20755     const char *title, int title_len, nk_flags align, int value)
  20756 {
  20757     nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value;
  20758 }
  20759 NK_API int
  20760 nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  20761     const char *title, nk_flags align, int value)
  20762 {
  20763     return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
  20764 }
  20765 
  20766 
  20767 
  20768 
  20769 
  20770 /* ===============================================================
  20771  *
  20772  *                              SLIDER
  20773  *
  20774  * ===============================================================*/
  20775 NK_LIB float
  20776 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
  20777     struct nk_rect *visual_cursor, struct nk_input *in,
  20778     struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
  20779     float slider_step, float slider_steps)
  20780 {
  20781     int left_mouse_down;
  20782     int left_mouse_click_in_cursor;
  20783 
  20784     /* check if visual cursor is being dragged */
  20785     nk_widget_state_reset(state);
  20786     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
  20787     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
  20788             NK_BUTTON_LEFT, *visual_cursor, nk_true);
  20789 
  20790     if (left_mouse_down && left_mouse_click_in_cursor) {
  20791         float ratio = 0;
  20792         const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
  20793         const float pxstep = bounds.w / slider_steps;
  20794 
  20795         /* only update value if the next slider step is reached */
  20796         *state = NK_WIDGET_STATE_ACTIVE;
  20797         if (NK_ABS(d) >= pxstep) {
  20798             const float steps = (float)((int)(NK_ABS(d) / pxstep));
  20799             slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
  20800             slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
  20801             ratio = (slider_value - slider_min)/slider_step;
  20802             logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
  20803             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
  20804         }
  20805     }
  20806 
  20807     /* slider widget state */
  20808     if (nk_input_is_mouse_hovering_rect(in, bounds))
  20809         *state = NK_WIDGET_STATE_HOVERED;
  20810     if (*state & NK_WIDGET_STATE_HOVER &&
  20811         !nk_input_is_mouse_prev_hovering_rect(in, bounds))
  20812         *state |= NK_WIDGET_STATE_ENTERED;
  20813     else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
  20814         *state |= NK_WIDGET_STATE_LEFT;
  20815     return slider_value;
  20816 }
  20817 NK_LIB void
  20818 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
  20819     const struct nk_style_slider *style, const struct nk_rect *bounds,
  20820     const struct nk_rect *visual_cursor, float min, float value, float max)
  20821 {
  20822     struct nk_rect fill;
  20823     struct nk_rect bar;
  20824     const struct nk_style_item *background;
  20825 
  20826     /* select correct slider images/colors */
  20827     struct nk_color bar_color;
  20828     const struct nk_style_item *cursor;
  20829 
  20830     NK_UNUSED(min);
  20831     NK_UNUSED(max);
  20832     NK_UNUSED(value);
  20833 
  20834     if (state & NK_WIDGET_STATE_ACTIVED) {
  20835         background = &style->active;
  20836         bar_color = style->bar_active;
  20837         cursor = &style->cursor_active;
  20838     } else if (state & NK_WIDGET_STATE_HOVER) {
  20839         background = &style->hover;
  20840         bar_color = style->bar_hover;
  20841         cursor = &style->cursor_hover;
  20842     } else {
  20843         background = &style->normal;
  20844         bar_color = style->bar_normal;
  20845         cursor = &style->cursor_normal;
  20846     }
  20847     /* calculate slider background bar */
  20848     bar.x = bounds->x;
  20849     bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
  20850     bar.w = bounds->w;
  20851     bar.h = bounds->h/6;
  20852 
  20853     /* filled background bar style */
  20854     fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
  20855     fill.x = bar.x;
  20856     fill.y = bar.y;
  20857     fill.h = bar.h;
  20858 
  20859     /* draw background */
  20860     if (background->type == NK_STYLE_ITEM_IMAGE) {
  20861         nk_draw_image(out, *bounds, &background->data.image, nk_white);
  20862     } else {
  20863         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  20864         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
  20865     }
  20866 
  20867     /* draw slider bar */
  20868     nk_fill_rect(out, bar, style->rounding, bar_color);
  20869     nk_fill_rect(out, fill, style->rounding, style->bar_filled);
  20870 
  20871     /* draw cursor */
  20872     if (cursor->type == NK_STYLE_ITEM_IMAGE)
  20873         nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
  20874     else nk_fill_circle(out, *visual_cursor, cursor->data.color);
  20875 }
  20876 NK_LIB float
  20877 nk_do_slider(nk_flags *state,
  20878     struct nk_command_buffer *out, struct nk_rect bounds,
  20879     float min, float val, float max, float step,
  20880     const struct nk_style_slider *style, struct nk_input *in,
  20881     const struct nk_user_font *font)
  20882 {
  20883     float slider_range;
  20884     float slider_min;
  20885     float slider_max;
  20886     float slider_value;
  20887     float slider_steps;
  20888     float cursor_offset;
  20889 
  20890     struct nk_rect visual_cursor;
  20891     struct nk_rect logical_cursor;
  20892 
  20893     NK_ASSERT(style);
  20894     NK_ASSERT(out);
  20895     if (!out || !style)
  20896         return 0;
  20897 
  20898     /* remove padding from slider bounds */
  20899     bounds.x = bounds.x + style->padding.x;
  20900     bounds.y = bounds.y + style->padding.y;
  20901     bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
  20902     bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
  20903     bounds.w -= 2 * style->padding.x;
  20904     bounds.h -= 2 * style->padding.y;
  20905 
  20906     /* optional buttons */
  20907     if (style->show_buttons) {
  20908         nk_flags ws;
  20909         struct nk_rect button;
  20910         button.y = bounds.y;
  20911         button.w = bounds.h;
  20912         button.h = bounds.h;
  20913 
  20914         /* decrement button */
  20915         button.x = bounds.x;
  20916         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
  20917             &style->dec_button, in, font))
  20918             val -= step;
  20919 
  20920         /* increment button */
  20921         button.x = (bounds.x + bounds.w) - button.w;
  20922         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
  20923             &style->inc_button, in, font))
  20924             val += step;
  20925 
  20926         bounds.x = bounds.x + button.w + style->spacing.x;
  20927         bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
  20928     }
  20929 
  20930     /* remove one cursor size to support visual cursor */
  20931     bounds.x += style->cursor_size.x*0.5f;
  20932     bounds.w -= style->cursor_size.x;
  20933 
  20934     /* make sure the provided values are correct */
  20935     slider_max = NK_MAX(min, max);
  20936     slider_min = NK_MIN(min, max);
  20937     slider_value = NK_CLAMP(slider_min, val, slider_max);
  20938     slider_range = slider_max - slider_min;
  20939     slider_steps = slider_range / step;
  20940     cursor_offset = (slider_value - slider_min) / step;
  20941 
  20942     /* calculate cursor
  20943     Basically you have two cursors. One for visual representation and interaction
  20944     and one for updating the actual cursor value. */
  20945     logical_cursor.h = bounds.h;
  20946     logical_cursor.w = bounds.w / slider_steps;
  20947     logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
  20948     logical_cursor.y = bounds.y;
  20949 
  20950     visual_cursor.h = style->cursor_size.y;
  20951     visual_cursor.w = style->cursor_size.x;
  20952     visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
  20953     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
  20954 
  20955     slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
  20956         in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
  20957     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
  20958 
  20959     /* draw slider */
  20960     if (style->draw_begin) style->draw_begin(out, style->userdata);
  20961     nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
  20962     if (style->draw_end) style->draw_end(out, style->userdata);
  20963     return slider_value;
  20964 }
  20965 NK_API int
  20966 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
  20967     float value_step)
  20968 {
  20969     struct nk_window *win;
  20970     struct nk_panel *layout;
  20971     struct nk_input *in;
  20972     const struct nk_style *style;
  20973 
  20974     int ret = 0;
  20975     float old_value;
  20976     struct nk_rect bounds;
  20977     enum nk_widget_layout_states state;
  20978 
  20979     NK_ASSERT(ctx);
  20980     NK_ASSERT(ctx->current);
  20981     NK_ASSERT(ctx->current->layout);
  20982     NK_ASSERT(value);
  20983     if (!ctx || !ctx->current || !ctx->current->layout || !value)
  20984         return ret;
  20985 
  20986     win = ctx->current;
  20987     style = &ctx->style;
  20988     layout = win->layout;
  20989 
  20990     state = nk_widget(&bounds, ctx);
  20991     if (!state) return ret;
  20992     in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  20993 
  20994     old_value = *value;
  20995     *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
  20996                 old_value, max_value, value_step, &style->slider, in, style->font);
  20997     return (old_value > *value || old_value < *value);
  20998 }
  20999 NK_API float
  21000 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
  21001 {
  21002     nk_slider_float(ctx, min, &val, max, step); return val;
  21003 }
  21004 NK_API int
  21005 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
  21006 {
  21007     float value = (float)val;
  21008     nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
  21009     return (int)value;
  21010 }
  21011 NK_API int
  21012 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
  21013 {
  21014     int ret;
  21015     float value = (float)*val;
  21016     ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
  21017     *val =  (int)value;
  21018     return ret;
  21019 }
  21020 
  21021 
  21022 
  21023 
  21024 
  21025 /* ===============================================================
  21026  *
  21027  *                          PROGRESS
  21028  *
  21029  * ===============================================================*/
  21030 NK_LIB nk_size
  21031 nk_progress_behavior(nk_flags *state, struct nk_input *in,
  21032     struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable)
  21033 {
  21034     int left_mouse_down = 0;
  21035     int left_mouse_click_in_cursor = 0;
  21036 
  21037     nk_widget_state_reset(state);
  21038     if (!in || !modifiable) return value;
  21039     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
  21040     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
  21041             NK_BUTTON_LEFT, cursor, nk_true);
  21042     if (nk_input_is_mouse_hovering_rect(in, r))
  21043         *state = NK_WIDGET_STATE_HOVERED;
  21044 
  21045     if (in && left_mouse_down && left_mouse_click_in_cursor) {
  21046         if (left_mouse_down && left_mouse_click_in_cursor) {
  21047             float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w;
  21048             value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max);
  21049             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f;
  21050             *state |= NK_WIDGET_STATE_ACTIVE;
  21051         }
  21052     }
  21053     /* set progressbar widget state */
  21054     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
  21055         *state |= NK_WIDGET_STATE_ENTERED;
  21056     else if (nk_input_is_mouse_prev_hovering_rect(in, r))
  21057         *state |= NK_WIDGET_STATE_LEFT;
  21058     return value;
  21059 }
  21060 NK_LIB void
  21061 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
  21062     const struct nk_style_progress *style, const struct nk_rect *bounds,
  21063     const struct nk_rect *scursor, nk_size value, nk_size max)
  21064 {
  21065     const struct nk_style_item *background;
  21066     const struct nk_style_item *cursor;
  21067 
  21068     NK_UNUSED(max);
  21069     NK_UNUSED(value);
  21070 
  21071     /* select correct colors/images to draw */
  21072     if (state & NK_WIDGET_STATE_ACTIVED) {
  21073         background = &style->active;
  21074         cursor = &style->cursor_active;
  21075     } else if (state & NK_WIDGET_STATE_HOVER){
  21076         background = &style->hover;
  21077         cursor = &style->cursor_hover;
  21078     } else {
  21079         background = &style->normal;
  21080         cursor = &style->cursor_normal;
  21081     }
  21082 
  21083     /* draw background */
  21084     if (background->type == NK_STYLE_ITEM_COLOR) {
  21085         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  21086         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
  21087     } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
  21088 
  21089     /* draw cursor */
  21090     if (cursor->type == NK_STYLE_ITEM_COLOR) {
  21091         nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
  21092         nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
  21093     } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
  21094 }
  21095 NK_LIB nk_size
  21096 nk_do_progress(nk_flags *state,
  21097     struct nk_command_buffer *out, struct nk_rect bounds,
  21098     nk_size value, nk_size max, int modifiable,
  21099     const struct nk_style_progress *style, struct nk_input *in)
  21100 {
  21101     float prog_scale;
  21102     nk_size prog_value;
  21103     struct nk_rect cursor;
  21104 
  21105     NK_ASSERT(style);
  21106     NK_ASSERT(out);
  21107     if (!out || !style) return 0;
  21108 
  21109     /* calculate progressbar cursor */
  21110     cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
  21111     cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
  21112     cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
  21113     prog_scale = (float)value / (float)max;
  21114 
  21115     /* update progressbar */
  21116     prog_value = NK_MIN(value, max);
  21117     prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable);
  21118     cursor.w = cursor.w * prog_scale;
  21119 
  21120     /* draw progressbar */
  21121     if (style->draw_begin) style->draw_begin(out, style->userdata);
  21122     nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
  21123     if (style->draw_end) style->draw_end(out, style->userdata);
  21124     return prog_value;
  21125 }
  21126 NK_API int
  21127 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
  21128 {
  21129     struct nk_window *win;
  21130     struct nk_panel *layout;
  21131     const struct nk_style *style;
  21132     struct nk_input *in;
  21133 
  21134     struct nk_rect bounds;
  21135     enum nk_widget_layout_states state;
  21136     nk_size old_value;
  21137 
  21138     NK_ASSERT(ctx);
  21139     NK_ASSERT(cur);
  21140     NK_ASSERT(ctx->current);
  21141     NK_ASSERT(ctx->current->layout);
  21142     if (!ctx || !ctx->current || !ctx->current->layout || !cur)
  21143         return 0;
  21144 
  21145     win = ctx->current;
  21146     style = &ctx->style;
  21147     layout = win->layout;
  21148     state = nk_widget(&bounds, ctx);
  21149     if (!state) return 0;
  21150 
  21151     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  21152     old_value = *cur;
  21153     *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
  21154             *cur, max, is_modifyable, &style->progress, in);
  21155     return (*cur != old_value);
  21156 }
  21157 NK_API nk_size
  21158 nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
  21159 {
  21160     nk_progress(ctx, &cur, max, modifyable);
  21161     return cur;
  21162 }
  21163 
  21164 
  21165 
  21166 
  21167 
  21168 /* ===============================================================
  21169  *
  21170  *                              SCROLLBAR
  21171  *
  21172  * ===============================================================*/
  21173 NK_LIB float
  21174 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
  21175     int has_scrolling, const struct nk_rect *scroll,
  21176     const struct nk_rect *cursor, const struct nk_rect *empty0,
  21177     const struct nk_rect *empty1, float scroll_offset,
  21178     float target, float scroll_step, enum nk_orientation o)
  21179 {
  21180     nk_flags ws = 0;
  21181     int left_mouse_down;
  21182     int left_mouse_click_in_cursor;
  21183     float scroll_delta;
  21184 
  21185     nk_widget_state_reset(state);
  21186     if (!in) return scroll_offset;
  21187 
  21188     left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
  21189     left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
  21190         NK_BUTTON_LEFT, *cursor, nk_true);
  21191     if (nk_input_is_mouse_hovering_rect(in, *scroll))
  21192         *state = NK_WIDGET_STATE_HOVERED;
  21193 
  21194     scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
  21195     if (left_mouse_down && left_mouse_click_in_cursor) {
  21196         /* update cursor by mouse dragging */
  21197         float pixel, delta;
  21198         *state = NK_WIDGET_STATE_ACTIVE;
  21199         if (o == NK_VERTICAL) {
  21200             float cursor_y;
  21201             pixel = in->mouse.delta.y;
  21202             delta = (pixel / scroll->h) * target;
  21203             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
  21204             cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
  21205             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
  21206         } else {
  21207             float cursor_x;
  21208             pixel = in->mouse.delta.x;
  21209             delta = (pixel / scroll->w) * target;
  21210             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
  21211             cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
  21212             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
  21213         }
  21214     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
  21215             nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
  21216         /* scroll page up by click on empty space or shortcut */
  21217         if (o == NK_VERTICAL)
  21218             scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
  21219         else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
  21220     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
  21221         nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
  21222         /* scroll page down by click on empty space or shortcut */
  21223         if (o == NK_VERTICAL)
  21224             scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
  21225         else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
  21226     } else if (has_scrolling) {
  21227         if ((scroll_delta < 0 || (scroll_delta > 0))) {
  21228             /* update cursor by mouse scrolling */
  21229             scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
  21230             if (o == NK_VERTICAL)
  21231                 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
  21232             else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
  21233         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
  21234             /* update cursor to the beginning  */
  21235             if (o == NK_VERTICAL) scroll_offset = 0;
  21236         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
  21237             /* update cursor to the end */
  21238             if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
  21239         }
  21240     }
  21241     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
  21242         *state |= NK_WIDGET_STATE_ENTERED;
  21243     else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
  21244         *state |= NK_WIDGET_STATE_LEFT;
  21245     return scroll_offset;
  21246 }
  21247 NK_LIB void
  21248 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
  21249     const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
  21250     const struct nk_rect *scroll)
  21251 {
  21252     const struct nk_style_item *background;
  21253     const struct nk_style_item *cursor;
  21254 
  21255     /* select correct colors/images to draw */
  21256     if (state & NK_WIDGET_STATE_ACTIVED) {
  21257         background = &style->active;
  21258         cursor = &style->cursor_active;
  21259     } else if (state & NK_WIDGET_STATE_HOVER) {
  21260         background = &style->hover;
  21261         cursor = &style->cursor_hover;
  21262     } else {
  21263         background = &style->normal;
  21264         cursor = &style->cursor_normal;
  21265     }
  21266 
  21267     /* draw background */
  21268     if (background->type == NK_STYLE_ITEM_COLOR) {
  21269         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  21270         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
  21271     } else {
  21272         nk_draw_image(out, *bounds, &background->data.image, nk_white);
  21273     }
  21274 
  21275     /* draw cursor */
  21276     if (cursor->type == NK_STYLE_ITEM_COLOR) {
  21277         nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
  21278         nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
  21279     } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
  21280 }
  21281 NK_LIB float
  21282 nk_do_scrollbarv(nk_flags *state,
  21283     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
  21284     float offset, float target, float step, float button_pixel_inc,
  21285     const struct nk_style_scrollbar *style, struct nk_input *in,
  21286     const struct nk_user_font *font)
  21287 {
  21288     struct nk_rect empty_north;
  21289     struct nk_rect empty_south;
  21290     struct nk_rect cursor;
  21291 
  21292     float scroll_step;
  21293     float scroll_offset;
  21294     float scroll_off;
  21295     float scroll_ratio;
  21296 
  21297     NK_ASSERT(out);
  21298     NK_ASSERT(style);
  21299     NK_ASSERT(state);
  21300     if (!out || !style) return 0;
  21301 
  21302     scroll.w = NK_MAX(scroll.w, 1);
  21303     scroll.h = NK_MAX(scroll.h, 0);
  21304     if (target <= scroll.h) return 0;
  21305 
  21306     /* optional scrollbar buttons */
  21307     if (style->show_buttons) {
  21308         nk_flags ws;
  21309         float scroll_h;
  21310         struct nk_rect button;
  21311 
  21312         button.x = scroll.x;
  21313         button.w = scroll.w;
  21314         button.h = scroll.w;
  21315 
  21316         scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
  21317         scroll_step = NK_MIN(step, button_pixel_inc);
  21318 
  21319         /* decrement button */
  21320         button.y = scroll.y;
  21321         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
  21322             NK_BUTTON_REPEATER, &style->dec_button, in, font))
  21323             offset = offset - scroll_step;
  21324 
  21325         /* increment button */
  21326         button.y = scroll.y + scroll.h - button.h;
  21327         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
  21328             NK_BUTTON_REPEATER, &style->inc_button, in, font))
  21329             offset = offset + scroll_step;
  21330 
  21331         scroll.y = scroll.y + button.h;
  21332         scroll.h = scroll_h;
  21333     }
  21334 
  21335     /* calculate scrollbar constants */
  21336     scroll_step = NK_MIN(step, scroll.h);
  21337     scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
  21338     scroll_ratio = scroll.h / target;
  21339     scroll_off = scroll_offset / target;
  21340 
  21341     /* calculate scrollbar cursor bounds */
  21342     cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
  21343     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
  21344     cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
  21345     cursor.x = scroll.x + style->border + style->padding.x;
  21346 
  21347     /* calculate empty space around cursor */
  21348     empty_north.x = scroll.x;
  21349     empty_north.y = scroll.y;
  21350     empty_north.w = scroll.w;
  21351     empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
  21352 
  21353     empty_south.x = scroll.x;
  21354     empty_south.y = cursor.y + cursor.h;
  21355     empty_south.w = scroll.w;
  21356     empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
  21357 
  21358     /* update scrollbar */
  21359     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
  21360         &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
  21361     scroll_off = scroll_offset / target;
  21362     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
  21363 
  21364     /* draw scrollbar */
  21365     if (style->draw_begin) style->draw_begin(out, style->userdata);
  21366     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
  21367     if (style->draw_end) style->draw_end(out, style->userdata);
  21368     return scroll_offset;
  21369 }
  21370 NK_LIB float
  21371 nk_do_scrollbarh(nk_flags *state,
  21372     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
  21373     float offset, float target, float step, float button_pixel_inc,
  21374     const struct nk_style_scrollbar *style, struct nk_input *in,
  21375     const struct nk_user_font *font)
  21376 {
  21377     struct nk_rect cursor;
  21378     struct nk_rect empty_west;
  21379     struct nk_rect empty_east;
  21380 
  21381     float scroll_step;
  21382     float scroll_offset;
  21383     float scroll_off;
  21384     float scroll_ratio;
  21385 
  21386     NK_ASSERT(out);
  21387     NK_ASSERT(style);
  21388     if (!out || !style) return 0;
  21389 
  21390     /* scrollbar background */
  21391     scroll.h = NK_MAX(scroll.h, 1);
  21392     scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
  21393     if (target <= scroll.w) return 0;
  21394 
  21395     /* optional scrollbar buttons */
  21396     if (style->show_buttons) {
  21397         nk_flags ws;
  21398         float scroll_w;
  21399         struct nk_rect button;
  21400         button.y = scroll.y;
  21401         button.w = scroll.h;
  21402         button.h = scroll.h;
  21403 
  21404         scroll_w = scroll.w - 2 * button.w;
  21405         scroll_step = NK_MIN(step, button_pixel_inc);
  21406 
  21407         /* decrement button */
  21408         button.x = scroll.x;
  21409         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
  21410             NK_BUTTON_REPEATER, &style->dec_button, in, font))
  21411             offset = offset - scroll_step;
  21412 
  21413         /* increment button */
  21414         button.x = scroll.x + scroll.w - button.w;
  21415         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
  21416             NK_BUTTON_REPEATER, &style->inc_button, in, font))
  21417             offset = offset + scroll_step;
  21418 
  21419         scroll.x = scroll.x + button.w;
  21420         scroll.w = scroll_w;
  21421     }
  21422 
  21423     /* calculate scrollbar constants */
  21424     scroll_step = NK_MIN(step, scroll.w);
  21425     scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
  21426     scroll_ratio = scroll.w / target;
  21427     scroll_off = scroll_offset / target;
  21428 
  21429     /* calculate cursor bounds */
  21430     cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
  21431     cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
  21432     cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
  21433     cursor.y = scroll.y + style->border + style->padding.y;
  21434 
  21435     /* calculate empty space around cursor */
  21436     empty_west.x = scroll.x;
  21437     empty_west.y = scroll.y;
  21438     empty_west.w = cursor.x - scroll.x;
  21439     empty_west.h = scroll.h;
  21440 
  21441     empty_east.x = cursor.x + cursor.w;
  21442     empty_east.y = scroll.y;
  21443     empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
  21444     empty_east.h = scroll.h;
  21445 
  21446     /* update scrollbar */
  21447     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
  21448         &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
  21449     scroll_off = scroll_offset / target;
  21450     cursor.x = scroll.x + (scroll_off * scroll.w);
  21451 
  21452     /* draw scrollbar */
  21453     if (style->draw_begin) style->draw_begin(out, style->userdata);
  21454     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
  21455     if (style->draw_end) style->draw_end(out, style->userdata);
  21456     return scroll_offset;
  21457 }
  21458 
  21459 
  21460 
  21461 
  21462 
  21463 /* ===============================================================
  21464  *
  21465  *                          TEXT EDITOR
  21466  *
  21467  * ===============================================================*/
  21468 /* stb_textedit.h - v1.8  - public domain - Sean Barrett */
  21469 struct nk_text_find {
  21470    float x,y;    /* position of n'th character */
  21471    float height; /* height of line */
  21472    int first_char, length; /* first char of row, and length */
  21473    int prev_first;  /*_ first char of previous row */
  21474 };
  21475 
  21476 struct nk_text_edit_row {
  21477    float x0,x1;
  21478    /* starting x location, end x location (allows for align=right, etc) */
  21479    float baseline_y_delta;
  21480    /* position of baseline relative to previous row's baseline*/
  21481    float ymin,ymax;
  21482    /* height of row above and below baseline */
  21483    int num_chars;
  21484 };
  21485 
  21486 /* forward declarations */
  21487 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
  21488 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
  21489 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
  21490 #define NK_TEXT_HAS_SELECTION(s)   ((s)->select_start != (s)->select_end)
  21491 
  21492 NK_INTERN float
  21493 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
  21494     const struct nk_user_font *font)
  21495 {
  21496     int len = 0;
  21497     nk_rune unicode = 0;
  21498     const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
  21499     return font->width(font->userdata, font->height, str, len);
  21500 }
  21501 NK_INTERN void
  21502 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
  21503     int line_start_id, float row_height, const struct nk_user_font *font)
  21504 {
  21505     int l;
  21506     int glyphs = 0;
  21507     nk_rune unicode;
  21508     const char *remaining;
  21509     int len = nk_str_len_char(&edit->string);
  21510     const char *end = nk_str_get_const(&edit->string) + len;
  21511     const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
  21512     const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
  21513         text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
  21514 
  21515     r->x0 = 0.0f;
  21516     r->x1 = size.x;
  21517     r->baseline_y_delta = size.y;
  21518     r->ymin = 0.0f;
  21519     r->ymax = size.y;
  21520     r->num_chars = glyphs;
  21521 }
  21522 NK_INTERN int
  21523 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
  21524     const struct nk_user_font *font, float row_height)
  21525 {
  21526     struct nk_text_edit_row r;
  21527     int n = edit->string.len;
  21528     float base_y = 0, prev_x;
  21529     int i=0, k;
  21530 
  21531     r.x0 = r.x1 = 0;
  21532     r.ymin = r.ymax = 0;
  21533     r.num_chars = 0;
  21534 
  21535     /* search rows to find one that straddles 'y' */
  21536     while (i < n) {
  21537         nk_textedit_layout_row(&r, edit, i, row_height, font);
  21538         if (r.num_chars <= 0)
  21539             return n;
  21540 
  21541         if (i==0 && y < base_y + r.ymin)
  21542             return 0;
  21543 
  21544         if (y < base_y + r.ymax)
  21545             break;
  21546 
  21547         i += r.num_chars;
  21548         base_y += r.baseline_y_delta;
  21549     }
  21550 
  21551     /* below all text, return 'after' last character */
  21552     if (i >= n)
  21553         return n;
  21554 
  21555     /* check if it's before the beginning of the line */
  21556     if (x < r.x0)
  21557         return i;
  21558 
  21559     /* check if it's before the end of the line */
  21560     if (x < r.x1) {
  21561         /* search characters in row for one that straddles 'x' */
  21562         k = i;
  21563         prev_x = r.x0;
  21564         for (i=0; i < r.num_chars; ++i) {
  21565             float w = nk_textedit_get_width(edit, k, i, font);
  21566             if (x < prev_x+w) {
  21567                 if (x < prev_x+w/2)
  21568                     return k+i;
  21569                 else return k+i+1;
  21570             }
  21571             prev_x += w;
  21572         }
  21573         /* shouldn't happen, but if it does, fall through to end-of-line case */
  21574     }
  21575 
  21576     /* if the last character is a newline, return that.
  21577      * otherwise return 'after' the last character */
  21578     if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
  21579         return i+r.num_chars-1;
  21580     else return i+r.num_chars;
  21581 }
  21582 NK_LIB void
  21583 nk_textedit_click(struct nk_text_edit *state, float x, float y,
  21584     const struct nk_user_font *font, float row_height)
  21585 {
  21586     /* API click: on mouse down, move the cursor to the clicked location,
  21587      * and reset the selection */
  21588     state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
  21589     state->select_start = state->cursor;
  21590     state->select_end = state->cursor;
  21591     state->has_preferred_x = 0;
  21592 }
  21593 NK_LIB void
  21594 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
  21595     const struct nk_user_font *font, float row_height)
  21596 {
  21597     /* API drag: on mouse drag, move the cursor and selection endpoint
  21598      * to the clicked location */
  21599     int p = nk_textedit_locate_coord(state, x, y, font, row_height);
  21600     if (state->select_start == state->select_end)
  21601         state->select_start = state->cursor;
  21602     state->cursor = state->select_end = p;
  21603 }
  21604 NK_INTERN void
  21605 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
  21606     int n, int single_line, const struct nk_user_font *font, float row_height)
  21607 {
  21608     /* find the x/y location of a character, and remember info about the previous
  21609      * row in case we get a move-up event (for page up, we'll have to rescan) */
  21610     struct nk_text_edit_row r;
  21611     int prev_start = 0;
  21612     int z = state->string.len;
  21613     int i=0, first;
  21614 
  21615     nk_zero_struct(r);
  21616     if (n == z) {
  21617         /* if it's at the end, then find the last line -- simpler than trying to
  21618         explicitly handle this case in the regular code */
  21619         nk_textedit_layout_row(&r, state, 0, row_height, font);
  21620         if (single_line) {
  21621             find->first_char = 0;
  21622             find->length = z;
  21623         } else {
  21624             while (i < z) {
  21625                 prev_start = i;
  21626                 i += r.num_chars;
  21627                 nk_textedit_layout_row(&r, state, i, row_height, font);
  21628             }
  21629 
  21630             find->first_char = i;
  21631             find->length = r.num_chars;
  21632         }
  21633         find->x = r.x1;
  21634         find->y = r.ymin;
  21635         find->height = r.ymax - r.ymin;
  21636         find->prev_first = prev_start;
  21637         return;
  21638     }
  21639 
  21640     /* search rows to find the one that straddles character n */
  21641     find->y = 0;
  21642 
  21643     for(;;) {
  21644         nk_textedit_layout_row(&r, state, i, row_height, font);
  21645         if (n < i + r.num_chars) break;
  21646         prev_start = i;
  21647         i += r.num_chars;
  21648         find->y += r.baseline_y_delta;
  21649     }
  21650 
  21651     find->first_char = first = i;
  21652     find->length = r.num_chars;
  21653     find->height = r.ymax - r.ymin;
  21654     find->prev_first = prev_start;
  21655 
  21656     /* now scan to find xpos */
  21657     find->x = r.x0;
  21658     for (i=0; first+i < n; ++i)
  21659         find->x += nk_textedit_get_width(state, first, i, font);
  21660 }
  21661 NK_INTERN void
  21662 nk_textedit_clamp(struct nk_text_edit *state)
  21663 {
  21664     /* make the selection/cursor state valid if client altered the string */
  21665     int n = state->string.len;
  21666     if (NK_TEXT_HAS_SELECTION(state)) {
  21667         if (state->select_start > n) state->select_start = n;
  21668         if (state->select_end   > n) state->select_end = n;
  21669         /* if clamping forced them to be equal, move the cursor to match */
  21670         if (state->select_start == state->select_end)
  21671             state->cursor = state->select_start;
  21672     }
  21673     if (state->cursor > n) state->cursor = n;
  21674 }
  21675 NK_API void
  21676 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
  21677 {
  21678     /* delete characters while updating undo */
  21679     nk_textedit_makeundo_delete(state, where, len);
  21680     nk_str_delete_runes(&state->string, where, len);
  21681     state->has_preferred_x = 0;
  21682 }
  21683 NK_API void
  21684 nk_textedit_delete_selection(struct nk_text_edit *state)
  21685 {
  21686     /* delete the section */
  21687     nk_textedit_clamp(state);
  21688     if (NK_TEXT_HAS_SELECTION(state)) {
  21689         if (state->select_start < state->select_end) {
  21690             nk_textedit_delete(state, state->select_start,
  21691                 state->select_end - state->select_start);
  21692             state->select_end = state->cursor = state->select_start;
  21693         } else {
  21694             nk_textedit_delete(state, state->select_end,
  21695                 state->select_start - state->select_end);
  21696             state->select_start = state->cursor = state->select_end;
  21697         }
  21698         state->has_preferred_x = 0;
  21699     }
  21700 }
  21701 NK_INTERN void
  21702 nk_textedit_sortselection(struct nk_text_edit *state)
  21703 {
  21704     /* canonicalize the selection so start <= end */
  21705     if (state->select_end < state->select_start) {
  21706         int temp = state->select_end;
  21707         state->select_end = state->select_start;
  21708         state->select_start = temp;
  21709     }
  21710 }
  21711 NK_INTERN void
  21712 nk_textedit_move_to_first(struct nk_text_edit *state)
  21713 {
  21714     /* move cursor to first character of selection */
  21715     if (NK_TEXT_HAS_SELECTION(state)) {
  21716         nk_textedit_sortselection(state);
  21717         state->cursor = state->select_start;
  21718         state->select_end = state->select_start;
  21719         state->has_preferred_x = 0;
  21720     }
  21721 }
  21722 NK_INTERN void
  21723 nk_textedit_move_to_last(struct nk_text_edit *state)
  21724 {
  21725     /* move cursor to last character of selection */
  21726     if (NK_TEXT_HAS_SELECTION(state)) {
  21727         nk_textedit_sortselection(state);
  21728         nk_textedit_clamp(state);
  21729         state->cursor = state->select_end;
  21730         state->select_start = state->select_end;
  21731         state->has_preferred_x = 0;
  21732     }
  21733 }
  21734 NK_INTERN int
  21735 nk_is_word_boundary( struct nk_text_edit *state, int idx)
  21736 {
  21737     int len;
  21738     nk_rune c;
  21739     if (idx <= 0) return 1;
  21740     if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
  21741     return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
  21742             c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
  21743             c == '|');
  21744 }
  21745 NK_INTERN int
  21746 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
  21747 {
  21748    int c = state->cursor - 1;
  21749    while( c >= 0 && !nk_is_word_boundary(state, c))
  21750       --c;
  21751 
  21752    if( c < 0 )
  21753       c = 0;
  21754 
  21755    return c;
  21756 }
  21757 NK_INTERN int
  21758 nk_textedit_move_to_word_next(struct nk_text_edit *state)
  21759 {
  21760    const int len = state->string.len;
  21761    int c = state->cursor+1;
  21762    while( c < len && !nk_is_word_boundary(state, c))
  21763       ++c;
  21764 
  21765    if( c > len )
  21766       c = len;
  21767 
  21768    return c;
  21769 }
  21770 NK_INTERN void
  21771 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
  21772 {
  21773     /* update selection and cursor to match each other */
  21774     if (!NK_TEXT_HAS_SELECTION(state))
  21775         state->select_start = state->select_end = state->cursor;
  21776     else state->cursor = state->select_end;
  21777 }
  21778 NK_API int
  21779 nk_textedit_cut(struct nk_text_edit *state)
  21780 {
  21781     /* API cut: delete selection */
  21782     if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  21783         return 0;
  21784     if (NK_TEXT_HAS_SELECTION(state)) {
  21785         nk_textedit_delete_selection(state); /* implicitly clamps */
  21786         state->has_preferred_x = 0;
  21787         return 1;
  21788     }
  21789    return 0;
  21790 }
  21791 NK_API int
  21792 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
  21793 {
  21794     /* API paste: replace existing selection with passed-in text */
  21795     int glyphs;
  21796     const char *text = (const char *) ctext;
  21797     if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
  21798 
  21799     /* if there's a selection, the paste should delete it */
  21800     nk_textedit_clamp(state);
  21801     nk_textedit_delete_selection(state);
  21802 
  21803     /* try to insert the characters */
  21804     glyphs = nk_utf_len(ctext, len);
  21805     if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
  21806         nk_textedit_makeundo_insert(state, state->cursor, glyphs);
  21807         state->cursor += len;
  21808         state->has_preferred_x = 0;
  21809         return 1;
  21810     }
  21811     /* remove the undo since we didn't actually insert the characters */
  21812     if (state->undo.undo_point)
  21813         --state->undo.undo_point;
  21814     return 0;
  21815 }
  21816 NK_API void
  21817 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
  21818 {
  21819     nk_rune unicode;
  21820     int glyph_len;
  21821     int text_len = 0;
  21822 
  21823     NK_ASSERT(state);
  21824     NK_ASSERT(text);
  21825     if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
  21826 
  21827     glyph_len = nk_utf_decode(text, &unicode, total_len);
  21828     while ((text_len < total_len) && glyph_len)
  21829     {
  21830         /* don't insert a backward delete, just process the event */
  21831         if (unicode == 127) goto next;
  21832         /* can't add newline in single-line mode */
  21833         if (unicode == '\n' && state->single_line) goto next;
  21834         /* filter incoming text */
  21835         if (state->filter && !state->filter(state, unicode)) goto next;
  21836 
  21837         if (!NK_TEXT_HAS_SELECTION(state) &&
  21838             state->cursor < state->string.len)
  21839         {
  21840             if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
  21841                 nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
  21842                 nk_str_delete_runes(&state->string, state->cursor, 1);
  21843             }
  21844             if (nk_str_insert_text_utf8(&state->string, state->cursor,
  21845                                         text+text_len, 1))
  21846             {
  21847                 ++state->cursor;
  21848                 state->has_preferred_x = 0;
  21849             }
  21850         } else {
  21851             nk_textedit_delete_selection(state); /* implicitly clamps */
  21852             if (nk_str_insert_text_utf8(&state->string, state->cursor,
  21853                                         text+text_len, 1))
  21854             {
  21855                 nk_textedit_makeundo_insert(state, state->cursor, 1);
  21856                 ++state->cursor;
  21857                 state->has_preferred_x = 0;
  21858             }
  21859         }
  21860         next:
  21861         text_len += glyph_len;
  21862         glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
  21863     }
  21864 }
  21865 NK_LIB void
  21866 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
  21867     const struct nk_user_font *font, float row_height)
  21868 {
  21869 retry:
  21870     switch (key)
  21871     {
  21872     case NK_KEY_NONE:
  21873     case NK_KEY_CTRL:
  21874     case NK_KEY_ENTER:
  21875     case NK_KEY_SHIFT:
  21876     case NK_KEY_TAB:
  21877     case NK_KEY_COPY:
  21878     case NK_KEY_CUT:
  21879     case NK_KEY_PASTE:
  21880     case NK_KEY_MAX:
  21881     default: break;
  21882     case NK_KEY_TEXT_UNDO:
  21883          nk_textedit_undo(state);
  21884          state->has_preferred_x = 0;
  21885          break;
  21886 
  21887     case NK_KEY_TEXT_REDO:
  21888         nk_textedit_redo(state);
  21889         state->has_preferred_x = 0;
  21890         break;
  21891 
  21892     case NK_KEY_TEXT_SELECT_ALL:
  21893         nk_textedit_select_all(state);
  21894         state->has_preferred_x = 0;
  21895         break;
  21896 
  21897     case NK_KEY_TEXT_INSERT_MODE:
  21898         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  21899             state->mode = NK_TEXT_EDIT_MODE_INSERT;
  21900         break;
  21901     case NK_KEY_TEXT_REPLACE_MODE:
  21902         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  21903             state->mode = NK_TEXT_EDIT_MODE_REPLACE;
  21904         break;
  21905     case NK_KEY_TEXT_RESET_MODE:
  21906         if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
  21907             state->mode == NK_TEXT_EDIT_MODE_REPLACE)
  21908             state->mode = NK_TEXT_EDIT_MODE_VIEW;
  21909         break;
  21910 
  21911     case NK_KEY_LEFT:
  21912         if (shift_mod) {
  21913             nk_textedit_clamp(state);
  21914             nk_textedit_prep_selection_at_cursor(state);
  21915             /* move selection left */
  21916             if (state->select_end > 0)
  21917                 --state->select_end;
  21918             state->cursor = state->select_end;
  21919             state->has_preferred_x = 0;
  21920         } else {
  21921             /* if currently there's a selection,
  21922              * move cursor to start of selection */
  21923             if (NK_TEXT_HAS_SELECTION(state))
  21924                 nk_textedit_move_to_first(state);
  21925             else if (state->cursor > 0)
  21926                --state->cursor;
  21927             state->has_preferred_x = 0;
  21928         } break;
  21929 
  21930     case NK_KEY_RIGHT:
  21931         if (shift_mod) {
  21932             nk_textedit_prep_selection_at_cursor(state);
  21933             /* move selection right */
  21934             ++state->select_end;
  21935             nk_textedit_clamp(state);
  21936             state->cursor = state->select_end;
  21937             state->has_preferred_x = 0;
  21938         } else {
  21939             /* if currently there's a selection,
  21940              * move cursor to end of selection */
  21941             if (NK_TEXT_HAS_SELECTION(state))
  21942                 nk_textedit_move_to_last(state);
  21943             else ++state->cursor;
  21944             nk_textedit_clamp(state);
  21945             state->has_preferred_x = 0;
  21946         } break;
  21947 
  21948     case NK_KEY_TEXT_WORD_LEFT:
  21949         if (shift_mod) {
  21950             if( !NK_TEXT_HAS_SELECTION( state ) )
  21951             nk_textedit_prep_selection_at_cursor(state);
  21952             state->cursor = nk_textedit_move_to_word_previous(state);
  21953             state->select_end = state->cursor;
  21954             nk_textedit_clamp(state );
  21955         } else {
  21956             if (NK_TEXT_HAS_SELECTION(state))
  21957                 nk_textedit_move_to_first(state);
  21958             else {
  21959                 state->cursor = nk_textedit_move_to_word_previous(state);
  21960                 nk_textedit_clamp(state );
  21961             }
  21962         } break;
  21963 
  21964     case NK_KEY_TEXT_WORD_RIGHT:
  21965         if (shift_mod) {
  21966             if( !NK_TEXT_HAS_SELECTION( state ) )
  21967                 nk_textedit_prep_selection_at_cursor(state);
  21968             state->cursor = nk_textedit_move_to_word_next(state);
  21969             state->select_end = state->cursor;
  21970             nk_textedit_clamp(state);
  21971         } else {
  21972             if (NK_TEXT_HAS_SELECTION(state))
  21973                 nk_textedit_move_to_last(state);
  21974             else {
  21975                 state->cursor = nk_textedit_move_to_word_next(state);
  21976                 nk_textedit_clamp(state );
  21977             }
  21978         } break;
  21979 
  21980     case NK_KEY_DOWN: {
  21981         struct nk_text_find find;
  21982         struct nk_text_edit_row row;
  21983         int i, sel = shift_mod;
  21984 
  21985         if (state->single_line) {
  21986             /* on windows, up&down in single-line behave like left&right */
  21987             key = NK_KEY_RIGHT;
  21988             goto retry;
  21989         }
  21990 
  21991         if (sel)
  21992             nk_textedit_prep_selection_at_cursor(state);
  21993         else if (NK_TEXT_HAS_SELECTION(state))
  21994             nk_textedit_move_to_last(state);
  21995 
  21996         /* compute current position of cursor point */
  21997         nk_textedit_clamp(state);
  21998         nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  21999             font, row_height);
  22000 
  22001         /* now find character position down a row */
  22002         if (find.length)
  22003         {
  22004             float x;
  22005             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
  22006             int start = find.first_char + find.length;
  22007 
  22008             state->cursor = start;
  22009             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
  22010             x = row.x0;
  22011 
  22012             for (i=0; i < row.num_chars && x < row.x1; ++i) {
  22013                 float dx = nk_textedit_get_width(state, start, i, font);
  22014                 x += dx;
  22015                 if (x > goal_x)
  22016                     break;
  22017                 ++state->cursor;
  22018             }
  22019             nk_textedit_clamp(state);
  22020 
  22021             state->has_preferred_x = 1;
  22022             state->preferred_x = goal_x;
  22023             if (sel)
  22024                 state->select_end = state->cursor;
  22025         }
  22026     } break;
  22027 
  22028     case NK_KEY_UP: {
  22029         struct nk_text_find find;
  22030         struct nk_text_edit_row row;
  22031         int i, sel = shift_mod;
  22032 
  22033         if (state->single_line) {
  22034             /* on windows, up&down become left&right */
  22035             key = NK_KEY_LEFT;
  22036             goto retry;
  22037         }
  22038 
  22039         if (sel)
  22040             nk_textedit_prep_selection_at_cursor(state);
  22041         else if (NK_TEXT_HAS_SELECTION(state))
  22042             nk_textedit_move_to_first(state);
  22043 
  22044          /* compute current position of cursor point */
  22045          nk_textedit_clamp(state);
  22046          nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  22047                 font, row_height);
  22048 
  22049          /* can only go up if there's a previous row */
  22050          if (find.prev_first != find.first_char) {
  22051             /* now find character position up a row */
  22052             float x;
  22053             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
  22054 
  22055             state->cursor = find.prev_first;
  22056             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
  22057             x = row.x0;
  22058 
  22059             for (i=0; i < row.num_chars && x < row.x1; ++i) {
  22060                 float dx = nk_textedit_get_width(state, find.prev_first, i, font);
  22061                 x += dx;
  22062                 if (x > goal_x)
  22063                     break;
  22064                 ++state->cursor;
  22065             }
  22066             nk_textedit_clamp(state);
  22067 
  22068             state->has_preferred_x = 1;
  22069             state->preferred_x = goal_x;
  22070             if (sel) state->select_end = state->cursor;
  22071          }
  22072       } break;
  22073 
  22074     case NK_KEY_DEL:
  22075         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  22076             break;
  22077         if (NK_TEXT_HAS_SELECTION(state))
  22078             nk_textedit_delete_selection(state);
  22079         else {
  22080             int n = state->string.len;
  22081             if (state->cursor < n)
  22082                 nk_textedit_delete(state, state->cursor, 1);
  22083          }
  22084          state->has_preferred_x = 0;
  22085          break;
  22086 
  22087     case NK_KEY_BACKSPACE:
  22088         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
  22089             break;
  22090         if (NK_TEXT_HAS_SELECTION(state))
  22091             nk_textedit_delete_selection(state);
  22092         else {
  22093             nk_textedit_clamp(state);
  22094             if (state->cursor > 0) {
  22095                 nk_textedit_delete(state, state->cursor-1, 1);
  22096                 --state->cursor;
  22097             }
  22098          }
  22099          state->has_preferred_x = 0;
  22100          break;
  22101 
  22102     case NK_KEY_TEXT_START:
  22103          if (shift_mod) {
  22104             nk_textedit_prep_selection_at_cursor(state);
  22105             state->cursor = state->select_end = 0;
  22106             state->has_preferred_x = 0;
  22107          } else {
  22108             state->cursor = state->select_start = state->select_end = 0;
  22109             state->has_preferred_x = 0;
  22110          }
  22111          break;
  22112 
  22113     case NK_KEY_TEXT_END:
  22114          if (shift_mod) {
  22115             nk_textedit_prep_selection_at_cursor(state);
  22116             state->cursor = state->select_end = state->string.len;
  22117             state->has_preferred_x = 0;
  22118          } else {
  22119             state->cursor = state->string.len;
  22120             state->select_start = state->select_end = 0;
  22121             state->has_preferred_x = 0;
  22122          }
  22123          break;
  22124 
  22125     case NK_KEY_TEXT_LINE_START: {
  22126         if (shift_mod) {
  22127             struct nk_text_find find;
  22128            nk_textedit_clamp(state);
  22129             nk_textedit_prep_selection_at_cursor(state);
  22130             if (state->string.len && state->cursor == state->string.len)
  22131                 --state->cursor;
  22132             nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
  22133                 font, row_height);
  22134             state->cursor = state->select_end = find.first_char;
  22135             state->has_preferred_x = 0;
  22136         } else {
  22137             struct nk_text_find find;
  22138             if (state->string.len && state->cursor == state->string.len)
  22139                 --state->cursor;
  22140             nk_textedit_clamp(state);
  22141             nk_textedit_move_to_first(state);
  22142             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  22143                 font, row_height);
  22144             state->cursor = find.first_char;
  22145             state->has_preferred_x = 0;
  22146         }
  22147       } break;
  22148 
  22149     case NK_KEY_TEXT_LINE_END: {
  22150         if (shift_mod) {
  22151             struct nk_text_find find;
  22152             nk_textedit_clamp(state);
  22153             nk_textedit_prep_selection_at_cursor(state);
  22154             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  22155                 font, row_height);
  22156             state->has_preferred_x = 0;
  22157             state->cursor = find.first_char + find.length;
  22158             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
  22159                 --state->cursor;
  22160             state->select_end = state->cursor;
  22161         } else {
  22162             struct nk_text_find find;
  22163             nk_textedit_clamp(state);
  22164             nk_textedit_move_to_first(state);
  22165             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
  22166                 font, row_height);
  22167 
  22168             state->has_preferred_x = 0;
  22169             state->cursor = find.first_char + find.length;
  22170             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
  22171                 --state->cursor;
  22172         }} break;
  22173     }
  22174 }
  22175 NK_INTERN void
  22176 nk_textedit_flush_redo(struct nk_text_undo_state *state)
  22177 {
  22178     state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
  22179     state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
  22180 }
  22181 NK_INTERN void
  22182 nk_textedit_discard_undo(struct nk_text_undo_state *state)
  22183 {
  22184     /* discard the oldest entry in the undo list */
  22185     if (state->undo_point > 0) {
  22186         /* if the 0th undo state has characters, clean those up */
  22187         if (state->undo_rec[0].char_storage >= 0) {
  22188             int n = state->undo_rec[0].insert_length, i;
  22189             /* delete n characters from all other records */
  22190             state->undo_char_point = (short)(state->undo_char_point - n);
  22191             NK_MEMCPY(state->undo_char, state->undo_char + n,
  22192                 (nk_size)state->undo_char_point*sizeof(nk_rune));
  22193             for (i=0; i < state->undo_point; ++i) {
  22194                 if (state->undo_rec[i].char_storage >= 0)
  22195                 state->undo_rec[i].char_storage = (short)
  22196                     (state->undo_rec[i].char_storage - n);
  22197             }
  22198         }
  22199         --state->undo_point;
  22200         NK_MEMCPY(state->undo_rec, state->undo_rec+1,
  22201             (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
  22202     }
  22203 }
  22204 NK_INTERN void
  22205 nk_textedit_discard_redo(struct nk_text_undo_state *state)
  22206 {
  22207 /*  discard the oldest entry in the redo list--it's bad if this
  22208     ever happens, but because undo & redo have to store the actual
  22209     characters in different cases, the redo character buffer can
  22210     fill up even though the undo buffer didn't */
  22211     nk_size num;
  22212     int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
  22213     if (state->redo_point <= k) {
  22214         /* if the k'th undo state has characters, clean those up */
  22215         if (state->undo_rec[k].char_storage >= 0) {
  22216             int n = state->undo_rec[k].insert_length, i;
  22217             /* delete n characters from all other records */
  22218             state->redo_char_point = (short)(state->redo_char_point + n);
  22219             num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point);
  22220             NK_MEMCPY(state->undo_char + state->redo_char_point,
  22221                 state->undo_char + state->redo_char_point-n, num * sizeof(char));
  22222             for (i = state->redo_point; i < k; ++i) {
  22223                 if (state->undo_rec[i].char_storage >= 0) {
  22224                     state->undo_rec[i].char_storage = (short)
  22225                         (state->undo_rec[i].char_storage + n);
  22226                 }
  22227             }
  22228         }
  22229         ++state->redo_point;
  22230         num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
  22231         if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
  22232             state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
  22233     }
  22234 }
  22235 NK_INTERN struct nk_text_undo_record*
  22236 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
  22237 {
  22238     /* any time we create a new undo record, we discard redo*/
  22239     nk_textedit_flush_redo(state);
  22240 
  22241     /* if we have no free records, we have to make room,
  22242      * by sliding the existing records down */
  22243     if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
  22244         nk_textedit_discard_undo(state);
  22245 
  22246     /* if the characters to store won't possibly fit in the buffer,
  22247      * we can't undo */
  22248     if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
  22249         state->undo_point = 0;
  22250         state->undo_char_point = 0;
  22251         return 0;
  22252     }
  22253 
  22254     /* if we don't have enough free characters in the buffer,
  22255      * we have to make room */
  22256     while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
  22257         nk_textedit_discard_undo(state);
  22258     return &state->undo_rec[state->undo_point++];
  22259 }
  22260 NK_INTERN nk_rune*
  22261 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
  22262     int insert_len, int delete_len)
  22263 {
  22264     struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
  22265     if (r == 0)
  22266         return 0;
  22267 
  22268     r->where = pos;
  22269     r->insert_length = (short) insert_len;
  22270     r->delete_length = (short) delete_len;
  22271 
  22272     if (insert_len == 0) {
  22273         r->char_storage = -1;
  22274         return 0;
  22275     } else {
  22276         r->char_storage = state->undo_char_point;
  22277         state->undo_char_point = (short)(state->undo_char_point +  insert_len);
  22278         return &state->undo_char[r->char_storage];
  22279     }
  22280 }
  22281 NK_API void
  22282 nk_textedit_undo(struct nk_text_edit *state)
  22283 {
  22284     struct nk_text_undo_state *s = &state->undo;
  22285     struct nk_text_undo_record u, *r;
  22286     if (s->undo_point == 0)
  22287         return;
  22288 
  22289     /* we need to do two things: apply the undo record, and create a redo record */
  22290     u = s->undo_rec[s->undo_point-1];
  22291     r = &s->undo_rec[s->redo_point-1];
  22292     r->char_storage = -1;
  22293 
  22294     r->insert_length = u.delete_length;
  22295     r->delete_length = u.insert_length;
  22296     r->where = u.where;
  22297 
  22298     if (u.delete_length)
  22299     {
  22300        /*   if the undo record says to delete characters, then the redo record will
  22301             need to re-insert the characters that get deleted, so we need to store
  22302             them.
  22303             there are three cases:
  22304                 - there's enough room to store the characters
  22305                 - characters stored for *redoing* don't leave room for redo
  22306                 - characters stored for *undoing* don't leave room for redo
  22307             if the last is true, we have to bail */
  22308         if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
  22309             /* the undo records take up too much character space; there's no space
  22310             * to store the redo characters */
  22311             r->insert_length = 0;
  22312         } else {
  22313             int i;
  22314             /* there's definitely room to store the characters eventually */
  22315             while (s->undo_char_point + u.delete_length > s->redo_char_point) {
  22316                 /* there's currently not enough room, so discard a redo record */
  22317                 nk_textedit_discard_redo(s);
  22318                 /* should never happen: */
  22319                 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
  22320                     return;
  22321             }
  22322 
  22323             r = &s->undo_rec[s->redo_point-1];
  22324             r->char_storage = (short)(s->redo_char_point - u.delete_length);
  22325             s->redo_char_point = (short)(s->redo_char_point -  u.delete_length);
  22326 
  22327             /* now save the characters */
  22328             for (i=0; i < u.delete_length; ++i)
  22329                 s->undo_char[r->char_storage + i] =
  22330                     nk_str_rune_at(&state->string, u.where + i);
  22331         }
  22332         /* now we can carry out the deletion */
  22333         nk_str_delete_runes(&state->string, u.where, u.delete_length);
  22334     }
  22335 
  22336     /* check type of recorded action: */
  22337     if (u.insert_length) {
  22338         /* easy case: was a deletion, so we need to insert n characters */
  22339         nk_str_insert_text_runes(&state->string, u.where,
  22340             &s->undo_char[u.char_storage], u.insert_length);
  22341         s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
  22342     }
  22343     state->cursor = (short)(u.where + u.insert_length);
  22344 
  22345     s->undo_point--;
  22346     s->redo_point--;
  22347 }
  22348 NK_API void
  22349 nk_textedit_redo(struct nk_text_edit *state)
  22350 {
  22351     struct nk_text_undo_state *s = &state->undo;
  22352     struct nk_text_undo_record *u, r;
  22353     if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
  22354         return;
  22355 
  22356     /* we need to do two things: apply the redo record, and create an undo record */
  22357     u = &s->undo_rec[s->undo_point];
  22358     r = s->undo_rec[s->redo_point];
  22359 
  22360     /* we KNOW there must be room for the undo record, because the redo record
  22361     was derived from an undo record */
  22362     u->delete_length = r.insert_length;
  22363     u->insert_length = r.delete_length;
  22364     u->where = r.where;
  22365     u->char_storage = -1;
  22366 
  22367     if (r.delete_length) {
  22368         /* the redo record requires us to delete characters, so the undo record
  22369         needs to store the characters */
  22370         if (s->undo_char_point + u->insert_length > s->redo_char_point) {
  22371             u->insert_length = 0;
  22372             u->delete_length = 0;
  22373         } else {
  22374             int i;
  22375             u->char_storage = s->undo_char_point;
  22376             s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
  22377 
  22378             /* now save the characters */
  22379             for (i=0; i < u->insert_length; ++i) {
  22380                 s->undo_char[u->char_storage + i] =
  22381                     nk_str_rune_at(&state->string, u->where + i);
  22382             }
  22383         }
  22384         nk_str_delete_runes(&state->string, r.where, r.delete_length);
  22385     }
  22386 
  22387     if (r.insert_length) {
  22388         /* easy case: need to insert n characters */
  22389         nk_str_insert_text_runes(&state->string, r.where,
  22390             &s->undo_char[r.char_storage], r.insert_length);
  22391     }
  22392     state->cursor = r.where + r.insert_length;
  22393 
  22394     s->undo_point++;
  22395     s->redo_point++;
  22396 }
  22397 NK_INTERN void
  22398 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
  22399 {
  22400     nk_textedit_createundo(&state->undo, where, 0, length);
  22401 }
  22402 NK_INTERN void
  22403 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
  22404 {
  22405     int i;
  22406     nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
  22407     if (p) {
  22408         for (i=0; i < length; ++i)
  22409             p[i] = nk_str_rune_at(&state->string, where+i);
  22410     }
  22411 }
  22412 NK_INTERN void
  22413 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
  22414     int old_length, int new_length)
  22415 {
  22416     int i;
  22417     nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
  22418     if (p) {
  22419         for (i=0; i < old_length; ++i)
  22420             p[i] = nk_str_rune_at(&state->string, where+i);
  22421     }
  22422 }
  22423 NK_LIB void
  22424 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
  22425     nk_plugin_filter filter)
  22426 {
  22427     /* reset the state to default */
  22428    state->undo.undo_point = 0;
  22429    state->undo.undo_char_point = 0;
  22430    state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
  22431    state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
  22432    state->select_end = state->select_start = 0;
  22433    state->cursor = 0;
  22434    state->has_preferred_x = 0;
  22435    state->preferred_x = 0;
  22436    state->cursor_at_end_of_line = 0;
  22437    state->initialized = 1;
  22438    state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
  22439    state->mode = NK_TEXT_EDIT_MODE_VIEW;
  22440    state->filter = filter;
  22441    state->scrollbar = nk_vec2(0,0);
  22442 }
  22443 NK_API void
  22444 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
  22445 {
  22446     NK_ASSERT(state);
  22447     NK_ASSERT(memory);
  22448     if (!state || !memory || !size) return;
  22449     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
  22450     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
  22451     nk_str_init_fixed(&state->string, memory, size);
  22452 }
  22453 NK_API void
  22454 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
  22455 {
  22456     NK_ASSERT(state);
  22457     NK_ASSERT(alloc);
  22458     if (!state || !alloc) return;
  22459     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
  22460     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
  22461     nk_str_init(&state->string, alloc, size);
  22462 }
  22463 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
  22464 NK_API void
  22465 nk_textedit_init_default(struct nk_text_edit *state)
  22466 {
  22467     NK_ASSERT(state);
  22468     if (!state) return;
  22469     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
  22470     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
  22471     nk_str_init_default(&state->string);
  22472 }
  22473 #endif
  22474 NK_API void
  22475 nk_textedit_select_all(struct nk_text_edit *state)
  22476 {
  22477     NK_ASSERT(state);
  22478     state->select_start = 0;
  22479     state->select_end = state->string.len;
  22480 }
  22481 NK_API void
  22482 nk_textedit_free(struct nk_text_edit *state)
  22483 {
  22484     NK_ASSERT(state);
  22485     if (!state) return;
  22486     nk_str_free(&state->string);
  22487 }
  22488 
  22489 
  22490 
  22491 
  22492 
  22493 /* ===============================================================
  22494  *
  22495  *                          FILTER
  22496  *
  22497  * ===============================================================*/
  22498 NK_API int
  22499 nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
  22500 {
  22501     NK_UNUSED(unicode);
  22502     NK_UNUSED(box);
  22503     return nk_true;
  22504 }
  22505 NK_API int
  22506 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
  22507 {
  22508     NK_UNUSED(box);
  22509     if (unicode > 128) return nk_false;
  22510     else return nk_true;
  22511 }
  22512 NK_API int
  22513 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
  22514 {
  22515     NK_UNUSED(box);
  22516     if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
  22517         return nk_false;
  22518     else return nk_true;
  22519 }
  22520 NK_API int
  22521 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
  22522 {
  22523     NK_UNUSED(box);
  22524     if ((unicode < '0' || unicode > '9') && unicode != '-')
  22525         return nk_false;
  22526     else return nk_true;
  22527 }
  22528 NK_API int
  22529 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
  22530 {
  22531     NK_UNUSED(box);
  22532     if ((unicode < '0' || unicode > '9') &&
  22533         (unicode < 'a' || unicode > 'f') &&
  22534         (unicode < 'A' || unicode > 'F'))
  22535         return nk_false;
  22536     else return nk_true;
  22537 }
  22538 NK_API int
  22539 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
  22540 {
  22541     NK_UNUSED(box);
  22542     if (unicode < '0' || unicode > '7')
  22543         return nk_false;
  22544     else return nk_true;
  22545 }
  22546 NK_API int
  22547 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
  22548 {
  22549     NK_UNUSED(box);
  22550     if (unicode != '0' && unicode != '1')
  22551         return nk_false;
  22552     else return nk_true;
  22553 }
  22554 
  22555 /* ===============================================================
  22556  *
  22557  *                          EDIT
  22558  *
  22559  * ===============================================================*/
  22560 NK_LIB void
  22561 nk_edit_draw_text(struct nk_command_buffer *out,
  22562     const struct nk_style_edit *style, float pos_x, float pos_y,
  22563     float x_offset, const char *text, int byte_len, float row_height,
  22564     const struct nk_user_font *font, struct nk_color background,
  22565     struct nk_color foreground, int is_selected)
  22566 {
  22567     NK_ASSERT(out);
  22568     NK_ASSERT(font);
  22569     NK_ASSERT(style);
  22570     if (!text || !byte_len || !out || !style) return;
  22571 
  22572     {int glyph_len = 0;
  22573     nk_rune unicode = 0;
  22574     int text_len = 0;
  22575     float line_width = 0;
  22576     float glyph_width;
  22577     const char *line = text;
  22578     float line_offset = 0;
  22579     int line_count = 0;
  22580 
  22581     struct nk_text txt;
  22582     txt.padding = nk_vec2(0,0);
  22583     txt.background = background;
  22584     txt.text = foreground;
  22585 
  22586     glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
  22587     if (!glyph_len) return;
  22588     while ((text_len < byte_len) && glyph_len)
  22589     {
  22590         if (unicode == '\n') {
  22591             /* new line separator so draw previous line */
  22592             struct nk_rect label;
  22593             label.y = pos_y + line_offset;
  22594             label.h = row_height;
  22595             label.w = line_width;
  22596             label.x = pos_x;
  22597             if (!line_count)
  22598                 label.x += x_offset;
  22599 
  22600             if (is_selected) /* selection needs to draw different background color */
  22601                 nk_fill_rect(out, label, 0, background);
  22602             nk_widget_text(out, label, line, (int)((text + text_len) - line),
  22603                 &txt, NK_TEXT_CENTERED, font);
  22604 
  22605             text_len++;
  22606             line_count++;
  22607             line_width = 0;
  22608             line = text + text_len;
  22609             line_offset += row_height;
  22610             glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
  22611             continue;
  22612         }
  22613         if (unicode == '\r') {
  22614             text_len++;
  22615             glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
  22616             continue;
  22617         }
  22618         glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
  22619         line_width += (float)glyph_width;
  22620         text_len += glyph_len;
  22621         glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
  22622         continue;
  22623     }
  22624     if (line_width > 0) {
  22625         /* draw last line */
  22626         struct nk_rect label;
  22627         label.y = pos_y + line_offset;
  22628         label.h = row_height;
  22629         label.w = line_width;
  22630         label.x = pos_x;
  22631         if (!line_count)
  22632             label.x += x_offset;
  22633 
  22634         if (is_selected)
  22635             nk_fill_rect(out, label, 0, background);
  22636         nk_widget_text(out, label, line, (int)((text + text_len) - line),
  22637             &txt, NK_TEXT_LEFT, font);
  22638     }}
  22639 }
  22640 NK_LIB nk_flags
  22641 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
  22642     struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
  22643     struct nk_text_edit *edit, const struct nk_style_edit *style,
  22644     struct nk_input *in, const struct nk_user_font *font)
  22645 {
  22646     struct nk_rect area;
  22647     nk_flags ret = 0;
  22648     float row_height;
  22649     char prev_state = 0;
  22650     char is_hovered = 0;
  22651     char select_all = 0;
  22652     char cursor_follow = 0;
  22653     struct nk_rect old_clip;
  22654     struct nk_rect clip;
  22655 
  22656     NK_ASSERT(state);
  22657     NK_ASSERT(out);
  22658     NK_ASSERT(style);
  22659     if (!state || !out || !style)
  22660         return ret;
  22661 
  22662     /* visible text area calculation */
  22663     area.x = bounds.x + style->padding.x + style->border;
  22664     area.y = bounds.y + style->padding.y + style->border;
  22665     area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
  22666     area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
  22667     if (flags & NK_EDIT_MULTILINE)
  22668         area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
  22669     row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
  22670 
  22671     /* calculate clipping rectangle */
  22672     old_clip = out->clip;
  22673     nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
  22674 
  22675     /* update edit state */
  22676     prev_state = (char)edit->active;
  22677     is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
  22678     if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) {
  22679         edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
  22680                                 bounds.x, bounds.y, bounds.w, bounds.h);
  22681     }
  22682 
  22683     /* (de)activate text editor */
  22684     if (!prev_state && edit->active) {
  22685         const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
  22686             NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE;
  22687         nk_textedit_clear_state(edit, type, filter);
  22688         if (flags & NK_EDIT_AUTO_SELECT)
  22689             select_all = nk_true;
  22690         if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
  22691             edit->cursor = edit->string.len;
  22692             in = 0;
  22693         }
  22694     } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
  22695     if (flags & NK_EDIT_READ_ONLY)
  22696         edit->mode = NK_TEXT_EDIT_MODE_VIEW;
  22697     else if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
  22698         edit->mode = NK_TEXT_EDIT_MODE_INSERT;
  22699 
  22700     ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
  22701     if (prev_state != edit->active)
  22702         ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
  22703 
  22704     /* handle user input */
  22705     if (edit->active && in)
  22706     {
  22707         int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
  22708         const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
  22709         const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
  22710 
  22711         /* mouse click handler */
  22712         is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
  22713         if (select_all) {
  22714             nk_textedit_select_all(edit);
  22715         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
  22716             in->mouse.buttons[NK_BUTTON_LEFT].clicked) {
  22717             nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
  22718         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
  22719             (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
  22720             nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
  22721             cursor_follow = nk_true;
  22722         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
  22723             in->mouse.buttons[NK_BUTTON_RIGHT].down) {
  22724             nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
  22725             nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
  22726             cursor_follow = nk_true;
  22727         }
  22728 
  22729         {int i; /* keyboard input */
  22730         int old_mode = edit->mode;
  22731         for (i = 0; i < NK_KEY_MAX; ++i) {
  22732             if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
  22733             if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
  22734                 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
  22735                 cursor_follow = nk_true;
  22736             }
  22737         }
  22738         if (old_mode != edit->mode) {
  22739             in->keyboard.text_len = 0;
  22740         }}
  22741 
  22742         /* text input */
  22743         edit->filter = filter;
  22744         if (in->keyboard.text_len) {
  22745             nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
  22746             cursor_follow = nk_true;
  22747             in->keyboard.text_len = 0;
  22748         }
  22749 
  22750         /* enter key handler */
  22751         if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) {
  22752             cursor_follow = nk_true;
  22753             if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
  22754                 nk_textedit_text(edit, "\n", 1);
  22755             else if (flags & NK_EDIT_SIG_ENTER)
  22756                 ret |= NK_EDIT_COMMITED;
  22757             else nk_textedit_text(edit, "\n", 1);
  22758         }
  22759 
  22760         /* cut & copy handler */
  22761         {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
  22762         int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
  22763         if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
  22764         {
  22765             int glyph_len;
  22766             nk_rune unicode;
  22767             const char *text;
  22768             int b = edit->select_start;
  22769             int e = edit->select_end;
  22770 
  22771             int begin = NK_MIN(b, e);
  22772             int end = NK_MAX(b, e);
  22773             text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
  22774             if (edit->clip.copy)
  22775                 edit->clip.copy(edit->clip.userdata, text, end - begin);
  22776             if (cut && !(flags & NK_EDIT_READ_ONLY)){
  22777                 nk_textedit_cut(edit);
  22778                 cursor_follow = nk_true;
  22779             }
  22780         }}
  22781 
  22782         /* paste handler */
  22783         {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
  22784         if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
  22785             edit->clip.paste(edit->clip.userdata, edit);
  22786             cursor_follow = nk_true;
  22787         }}
  22788 
  22789         /* tab handler */
  22790         {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
  22791         if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
  22792             nk_textedit_text(edit, "    ", 4);
  22793             cursor_follow = nk_true;
  22794         }}
  22795     }
  22796 
  22797     /* set widget state */
  22798     if (edit->active)
  22799         *state = NK_WIDGET_STATE_ACTIVE;
  22800     else nk_widget_state_reset(state);
  22801 
  22802     if (is_hovered)
  22803         *state |= NK_WIDGET_STATE_HOVERED;
  22804 
  22805     /* DRAW EDIT */
  22806     {const char *text = nk_str_get_const(&edit->string);
  22807     int len = nk_str_len_char(&edit->string);
  22808 
  22809     {/* select background colors/images  */
  22810     const struct nk_style_item *background;
  22811     if (*state & NK_WIDGET_STATE_ACTIVED)
  22812         background = &style->active;
  22813     else if (*state & NK_WIDGET_STATE_HOVER)
  22814         background = &style->hover;
  22815     else background = &style->normal;
  22816 
  22817     /* draw background frame */
  22818     if (background->type == NK_STYLE_ITEM_COLOR) {
  22819         nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
  22820         nk_fill_rect(out, bounds, style->rounding, background->data.color);
  22821     } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
  22822 
  22823     area.w = NK_MAX(0, area.w - style->cursor_size);
  22824     if (edit->active)
  22825     {
  22826         int total_lines = 1;
  22827         struct nk_vec2 text_size = nk_vec2(0,0);
  22828 
  22829         /* text pointer positions */
  22830         const char *cursor_ptr = 0;
  22831         const char *select_begin_ptr = 0;
  22832         const char *select_end_ptr = 0;
  22833 
  22834         /* 2D pixel positions */
  22835         struct nk_vec2 cursor_pos = nk_vec2(0,0);
  22836         struct nk_vec2 selection_offset_start = nk_vec2(0,0);
  22837         struct nk_vec2 selection_offset_end = nk_vec2(0,0);
  22838 
  22839         int selection_begin = NK_MIN(edit->select_start, edit->select_end);
  22840         int selection_end = NK_MAX(edit->select_start, edit->select_end);
  22841 
  22842         /* calculate total line count + total space + cursor/selection position */
  22843         float line_width = 0.0f;
  22844         if (text && len)
  22845         {
  22846             /* utf8 encoding */
  22847             float glyph_width;
  22848             int glyph_len = 0;
  22849             nk_rune unicode = 0;
  22850             int text_len = 0;
  22851             int glyphs = 0;
  22852             int row_begin = 0;
  22853 
  22854             glyph_len = nk_utf_decode(text, &unicode, len);
  22855             glyph_width = font->width(font->userdata, font->height, text, glyph_len);
  22856             line_width = 0;
  22857 
  22858             /* iterate all lines */
  22859             while ((text_len < len) && glyph_len)
  22860             {
  22861                 /* set cursor 2D position and line */
  22862                 if (!cursor_ptr && glyphs == edit->cursor)
  22863                 {
  22864                     int glyph_offset;
  22865                     struct nk_vec2 out_offset;
  22866                     struct nk_vec2 row_size;
  22867                     const char *remaining;
  22868 
  22869                     /* calculate 2d position */
  22870                     cursor_pos.y = (float)(total_lines-1) * row_height;
  22871                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
  22872                                 text_len-row_begin, row_height, &remaining,
  22873                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
  22874                     cursor_pos.x = row_size.x;
  22875                     cursor_ptr = text + text_len;
  22876                 }
  22877 
  22878                 /* set start selection 2D position and line */
  22879                 if (!select_begin_ptr && edit->select_start != edit->select_end &&
  22880                     glyphs == selection_begin)
  22881                 {
  22882                     int glyph_offset;
  22883                     struct nk_vec2 out_offset;
  22884                     struct nk_vec2 row_size;
  22885                     const char *remaining;
  22886 
  22887                     /* calculate 2d position */
  22888                     selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
  22889                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
  22890                                 text_len-row_begin, row_height, &remaining,
  22891                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
  22892                     selection_offset_start.x = row_size.x;
  22893                     select_begin_ptr = text + text_len;
  22894                 }
  22895 
  22896                 /* set end selection 2D position and line */
  22897                 if (!select_end_ptr && edit->select_start != edit->select_end &&
  22898                     glyphs == selection_end)
  22899                 {
  22900                     int glyph_offset;
  22901                     struct nk_vec2 out_offset;
  22902                     struct nk_vec2 row_size;
  22903                     const char *remaining;
  22904 
  22905                     /* calculate 2d position */
  22906                     selection_offset_end.y = (float)(total_lines-1) * row_height;
  22907                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
  22908                                 text_len-row_begin, row_height, &remaining,
  22909                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
  22910                     selection_offset_end.x = row_size.x;
  22911                     select_end_ptr = text + text_len;
  22912                 }
  22913                 if (unicode == '\n') {
  22914                     text_size.x = NK_MAX(text_size.x, line_width);
  22915                     total_lines++;
  22916                     line_width = 0;
  22917                     text_len++;
  22918                     glyphs++;
  22919                     row_begin = text_len;
  22920                     glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
  22921                     glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
  22922                     continue;
  22923                 }
  22924 
  22925                 glyphs++;
  22926                 text_len += glyph_len;
  22927                 line_width += (float)glyph_width;
  22928 
  22929                 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
  22930                 glyph_width = font->width(font->userdata, font->height,
  22931                     text+text_len, glyph_len);
  22932                 continue;
  22933             }
  22934             text_size.y = (float)total_lines * row_height;
  22935 
  22936             /* handle case when cursor is at end of text buffer */
  22937             if (!cursor_ptr && edit->cursor == edit->string.len) {
  22938                 cursor_pos.x = line_width;
  22939                 cursor_pos.y = text_size.y - row_height;
  22940             }
  22941         }
  22942         {
  22943             /* scrollbar */
  22944             if (cursor_follow)
  22945             {
  22946                 /* update scrollbar to follow cursor */
  22947                 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
  22948                     /* horizontal scroll */
  22949                     const float scroll_increment = area.w * 0.25f;
  22950                     if (cursor_pos.x < edit->scrollbar.x)
  22951                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
  22952                     if (cursor_pos.x >= edit->scrollbar.x + area.w)
  22953                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, edit->scrollbar.x + scroll_increment);
  22954                 } else edit->scrollbar.x = 0;
  22955 
  22956                 if (flags & NK_EDIT_MULTILINE) {
  22957                     /* vertical scroll */
  22958                     if (cursor_pos.y < edit->scrollbar.y)
  22959                         edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
  22960                     if (cursor_pos.y >= edit->scrollbar.y + area.h)
  22961                         edit->scrollbar.y = edit->scrollbar.y + row_height;
  22962                 } else edit->scrollbar.y = 0;
  22963             }
  22964 
  22965             /* scrollbar widget */
  22966             if (flags & NK_EDIT_MULTILINE)
  22967             {
  22968                 nk_flags ws;
  22969                 struct nk_rect scroll;
  22970                 float scroll_target;
  22971                 float scroll_offset;
  22972                 float scroll_step;
  22973                 float scroll_inc;
  22974 
  22975                 scroll = area;
  22976                 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
  22977                 scroll.w = style->scrollbar_size.x;
  22978 
  22979                 scroll_offset = edit->scrollbar.y;
  22980                 scroll_step = scroll.h * 0.10f;
  22981                 scroll_inc = scroll.h * 0.01f;
  22982                 scroll_target = text_size.y;
  22983                 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
  22984                         scroll_offset, scroll_target, scroll_step, scroll_inc,
  22985                         &style->scrollbar, in, font);
  22986             }
  22987         }
  22988 
  22989         /* draw text */
  22990         {struct nk_color background_color;
  22991         struct nk_color text_color;
  22992         struct nk_color sel_background_color;
  22993         struct nk_color sel_text_color;
  22994         struct nk_color cursor_color;
  22995         struct nk_color cursor_text_color;
  22996         const struct nk_style_item *background;
  22997         nk_push_scissor(out, clip);
  22998 
  22999         /* select correct colors to draw */
  23000         if (*state & NK_WIDGET_STATE_ACTIVED) {
  23001             background = &style->active;
  23002             text_color = style->text_active;
  23003             sel_text_color = style->selected_text_hover;
  23004             sel_background_color = style->selected_hover;
  23005             cursor_color = style->cursor_hover;
  23006             cursor_text_color = style->cursor_text_hover;
  23007         } else if (*state & NK_WIDGET_STATE_HOVER) {
  23008             background = &style->hover;
  23009             text_color = style->text_hover;
  23010             sel_text_color = style->selected_text_hover;
  23011             sel_background_color = style->selected_hover;
  23012             cursor_text_color = style->cursor_text_hover;
  23013             cursor_color = style->cursor_hover;
  23014         } else {
  23015             background = &style->normal;
  23016             text_color = style->text_normal;
  23017             sel_text_color = style->selected_text_normal;
  23018             sel_background_color = style->selected_normal;
  23019             cursor_color = style->cursor_normal;
  23020             cursor_text_color = style->cursor_text_normal;
  23021         }
  23022         if (background->type == NK_STYLE_ITEM_IMAGE)
  23023             background_color = nk_rgba(0,0,0,0);
  23024         else background_color = background->data.color;
  23025 
  23026 
  23027         if (edit->select_start == edit->select_end) {
  23028             /* no selection so just draw the complete text */
  23029             const char *begin = nk_str_get_const(&edit->string);
  23030             int l = nk_str_len_char(&edit->string);
  23031             nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
  23032                 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
  23033                 background_color, text_color, nk_false);
  23034         } else {
  23035             /* edit has selection so draw 1-3 text chunks */
  23036             if (edit->select_start != edit->select_end && selection_begin > 0){
  23037                 /* draw unselected text before selection */
  23038                 const char *begin = nk_str_get_const(&edit->string);
  23039                 NK_ASSERT(select_begin_ptr);
  23040                 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
  23041                     area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
  23042                     row_height, font, background_color, text_color, nk_false);
  23043             }
  23044             if (edit->select_start != edit->select_end) {
  23045                 /* draw selected text */
  23046                 NK_ASSERT(select_begin_ptr);
  23047                 if (!select_end_ptr) {
  23048                     const char *begin = nk_str_get_const(&edit->string);
  23049                     select_end_ptr = begin + nk_str_len_char(&edit->string);
  23050                 }
  23051                 nk_edit_draw_text(out, style,
  23052                     area.x - edit->scrollbar.x,
  23053                     area.y + selection_offset_start.y - edit->scrollbar.y,
  23054                     selection_offset_start.x,
  23055                     select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
  23056                     row_height, font, sel_background_color, sel_text_color, nk_true);
  23057             }
  23058             if ((edit->select_start != edit->select_end &&
  23059                 selection_end < edit->string.len))
  23060             {
  23061                 /* draw unselected text after selected text */
  23062                 const char *begin = select_end_ptr;
  23063                 const char *end = nk_str_get_const(&edit->string) +
  23064                                     nk_str_len_char(&edit->string);
  23065                 NK_ASSERT(select_end_ptr);
  23066                 nk_edit_draw_text(out, style,
  23067                     area.x - edit->scrollbar.x,
  23068                     area.y + selection_offset_end.y - edit->scrollbar.y,
  23069                     selection_offset_end.x,
  23070                     begin, (int)(end - begin), row_height, font,
  23071                     background_color, text_color, nk_true);
  23072             }
  23073         }
  23074 
  23075         /* cursor */
  23076         if (edit->select_start == edit->select_end)
  23077         {
  23078             if (edit->cursor >= nk_str_len(&edit->string) ||
  23079                 (cursor_ptr && *cursor_ptr == '\n')) {
  23080                 /* draw cursor at end of line */
  23081                 struct nk_rect cursor;
  23082                 cursor.w = style->cursor_size;
  23083                 cursor.h = font->height;
  23084                 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
  23085                 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
  23086                 cursor.y -= edit->scrollbar.y;
  23087                 nk_fill_rect(out, cursor, 0, cursor_color);
  23088             } else {
  23089                 /* draw cursor inside text */
  23090                 int glyph_len;
  23091                 struct nk_rect label;
  23092                 struct nk_text txt;
  23093 
  23094                 nk_rune unicode;
  23095                 NK_ASSERT(cursor_ptr);
  23096                 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
  23097 
  23098                 label.x = area.x + cursor_pos.x - edit->scrollbar.x;
  23099                 label.y = area.y + cursor_pos.y - edit->scrollbar.y;
  23100                 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
  23101                 label.h = row_height;
  23102 
  23103                 txt.padding = nk_vec2(0,0);
  23104                 txt.background = cursor_color;;
  23105                 txt.text = cursor_text_color;
  23106                 nk_fill_rect(out, label, 0, cursor_color);
  23107                 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
  23108             }
  23109         }}
  23110     } else {
  23111         /* not active so just draw text */
  23112         int l = nk_str_len_char(&edit->string);
  23113         const char *begin = nk_str_get_const(&edit->string);
  23114 
  23115         const struct nk_style_item *background;
  23116         struct nk_color background_color;
  23117         struct nk_color text_color;
  23118         nk_push_scissor(out, clip);
  23119         if (*state & NK_WIDGET_STATE_ACTIVED) {
  23120             background = &style->active;
  23121             text_color = style->text_active;
  23122         } else if (*state & NK_WIDGET_STATE_HOVER) {
  23123             background = &style->hover;
  23124             text_color = style->text_hover;
  23125         } else {
  23126             background = &style->normal;
  23127             text_color = style->text_normal;
  23128         }
  23129         if (background->type == NK_STYLE_ITEM_IMAGE)
  23130             background_color = nk_rgba(0,0,0,0);
  23131         else background_color = background->data.color;
  23132         nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
  23133             area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
  23134             background_color, text_color, nk_false);
  23135     }
  23136     nk_push_scissor(out, old_clip);}
  23137     return ret;
  23138 }
  23139 NK_API void
  23140 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
  23141 {
  23142     nk_hash hash;
  23143     struct nk_window *win;
  23144 
  23145     NK_ASSERT(ctx);
  23146     NK_ASSERT(ctx->current);
  23147     if (!ctx || !ctx->current) return;
  23148 
  23149     win = ctx->current;
  23150     hash = win->edit.seq;
  23151     win->edit.active = nk_true;
  23152     win->edit.name = hash;
  23153     if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
  23154         win->edit.mode = NK_TEXT_EDIT_MODE_INSERT;
  23155 }
  23156 NK_API void
  23157 nk_edit_unfocus(struct nk_context *ctx)
  23158 {
  23159     struct nk_window *win;
  23160     NK_ASSERT(ctx);
  23161     NK_ASSERT(ctx->current);
  23162     if (!ctx || !ctx->current) return;
  23163 
  23164     win = ctx->current;
  23165     win->edit.active = nk_false;
  23166     win->edit.name = 0;
  23167 }
  23168 NK_API nk_flags
  23169 nk_edit_string(struct nk_context *ctx, nk_flags flags,
  23170     char *memory, int *len, int max, nk_plugin_filter filter)
  23171 {
  23172     nk_hash hash;
  23173     nk_flags state;
  23174     struct nk_text_edit *edit;
  23175     struct nk_window *win;
  23176 
  23177     NK_ASSERT(ctx);
  23178     NK_ASSERT(memory);
  23179     NK_ASSERT(len);
  23180     if (!ctx || !memory || !len)
  23181         return 0;
  23182 
  23183     filter = (!filter) ? nk_filter_default: filter;
  23184     win = ctx->current;
  23185     hash = win->edit.seq;
  23186     edit = &ctx->text_edit;
  23187     nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
  23188         NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter);
  23189 
  23190     if (win->edit.active && hash == win->edit.name) {
  23191         if (flags & NK_EDIT_NO_CURSOR)
  23192             edit->cursor = nk_utf_len(memory, *len);
  23193         else edit->cursor = win->edit.cursor;
  23194         if (!(flags & NK_EDIT_SELECTABLE)) {
  23195             edit->select_start = win->edit.cursor;
  23196             edit->select_end = win->edit.cursor;
  23197         } else {
  23198             edit->select_start = win->edit.sel_start;
  23199             edit->select_end = win->edit.sel_end;
  23200         }
  23201         edit->mode = win->edit.mode;
  23202         edit->scrollbar.x = (float)win->edit.scrollbar.x;
  23203         edit->scrollbar.y = (float)win->edit.scrollbar.y;
  23204         edit->active = nk_true;
  23205     } else edit->active = nk_false;
  23206 
  23207     max = NK_MAX(1, max);
  23208     *len = NK_MIN(*len, max-1);
  23209     nk_str_init_fixed(&edit->string, memory, (nk_size)max);
  23210     edit->string.buffer.allocated = (nk_size)*len;
  23211     edit->string.len = nk_utf_len(memory, *len);
  23212     state = nk_edit_buffer(ctx, flags, edit, filter);
  23213     *len = (int)edit->string.buffer.allocated;
  23214 
  23215     if (edit->active) {
  23216         win->edit.cursor = edit->cursor;
  23217         win->edit.sel_start = edit->select_start;
  23218         win->edit.sel_end = edit->select_end;
  23219         win->edit.mode = edit->mode;
  23220         win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x;
  23221         win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y;
  23222     } return state;
  23223 }
  23224 NK_API nk_flags
  23225 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
  23226     struct nk_text_edit *edit, nk_plugin_filter filter)
  23227 {
  23228     struct nk_window *win;
  23229     struct nk_style *style;
  23230     struct nk_input *in;
  23231 
  23232     enum nk_widget_layout_states state;
  23233     struct nk_rect bounds;
  23234 
  23235     nk_flags ret_flags = 0;
  23236     unsigned char prev_state;
  23237     nk_hash hash;
  23238 
  23239     /* make sure correct values */
  23240     NK_ASSERT(ctx);
  23241     NK_ASSERT(edit);
  23242     NK_ASSERT(ctx->current);
  23243     NK_ASSERT(ctx->current->layout);
  23244     if (!ctx || !ctx->current || !ctx->current->layout)
  23245         return 0;
  23246 
  23247     win = ctx->current;
  23248     style = &ctx->style;
  23249     state = nk_widget(&bounds, ctx);
  23250     if (!state) return state;
  23251     in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  23252 
  23253     /* check if edit is currently hot item */
  23254     hash = win->edit.seq++;
  23255     if (win->edit.active && hash == win->edit.name) {
  23256         if (flags & NK_EDIT_NO_CURSOR)
  23257             edit->cursor = edit->string.len;
  23258         if (!(flags & NK_EDIT_SELECTABLE)) {
  23259             edit->select_start = edit->cursor;
  23260             edit->select_end = edit->cursor;
  23261         }
  23262         if (flags & NK_EDIT_CLIPBOARD)
  23263             edit->clip = ctx->clip;
  23264         edit->active = (unsigned char)win->edit.active;
  23265     } else edit->active = nk_false;
  23266     edit->mode = win->edit.mode;
  23267 
  23268     filter = (!filter) ? nk_filter_default: filter;
  23269     prev_state = (unsigned char)edit->active;
  23270     in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
  23271     ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
  23272                     filter, edit, &style->edit, in, style->font);
  23273 
  23274     if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  23275         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT];
  23276     if (edit->active && prev_state != edit->active) {
  23277         /* current edit is now hot */
  23278         win->edit.active = nk_true;
  23279         win->edit.name = hash;
  23280     } else if (prev_state && !edit->active) {
  23281         /* current edit is now cold */
  23282         win->edit.active = nk_false;
  23283     } return ret_flags;
  23284 }
  23285 NK_API nk_flags
  23286 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
  23287     char *buffer, int max, nk_plugin_filter filter)
  23288 {
  23289     nk_flags result;
  23290     int len = nk_strlen(buffer);
  23291     result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
  23292     buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
  23293     return result;
  23294 }
  23295 
  23296 
  23297 
  23298 
  23299 
  23300 /* ===============================================================
  23301  *
  23302  *                              PROPERTY
  23303  *
  23304  * ===============================================================*/
  23305 NK_LIB void
  23306 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
  23307     struct nk_rect drag, struct nk_property_variant *variant,
  23308     float inc_per_pixel)
  23309 {
  23310     int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
  23311     int left_mouse_click_in_cursor = in &&
  23312         nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true);
  23313 
  23314     nk_widget_state_reset(state);
  23315     if (nk_input_is_mouse_hovering_rect(in, drag))
  23316         *state = NK_WIDGET_STATE_HOVERED;
  23317 
  23318     if (left_mouse_down && left_mouse_click_in_cursor) {
  23319         float delta, pixels;
  23320         pixels = in->mouse.delta.x;
  23321         delta = pixels * inc_per_pixel;
  23322         switch (variant->kind) {
  23323         default: break;
  23324         case NK_PROPERTY_INT:
  23325             variant->value.i = variant->value.i + (int)delta;
  23326             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
  23327             break;
  23328         case NK_PROPERTY_FLOAT:
  23329             variant->value.f = variant->value.f + (float)delta;
  23330             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
  23331             break;
  23332         case NK_PROPERTY_DOUBLE:
  23333             variant->value.d = variant->value.d + (double)delta;
  23334             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
  23335             break;
  23336         }
  23337         *state = NK_WIDGET_STATE_ACTIVE;
  23338     }
  23339     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
  23340         *state |= NK_WIDGET_STATE_ENTERED;
  23341     else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
  23342         *state |= NK_WIDGET_STATE_LEFT;
  23343 }
  23344 NK_LIB void
  23345 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
  23346     struct nk_rect property,  struct nk_rect label, struct nk_rect edit,
  23347     struct nk_rect empty, int *state, struct nk_property_variant *variant,
  23348     float inc_per_pixel)
  23349 {
  23350     if (in && *state == NK_PROPERTY_DEFAULT) {
  23351         if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
  23352             *state = NK_PROPERTY_EDIT;
  23353         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true))
  23354             *state = NK_PROPERTY_DRAG;
  23355         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true))
  23356             *state = NK_PROPERTY_DRAG;
  23357     }
  23358     if (*state == NK_PROPERTY_DRAG) {
  23359         nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
  23360         if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
  23361     }
  23362 }
  23363 NK_LIB void
  23364 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
  23365     const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
  23366     const char *name, int len, const struct nk_user_font *font)
  23367 {
  23368     struct nk_text text;
  23369     const struct nk_style_item *background;
  23370 
  23371     /* select correct background and text color */
  23372     if (state & NK_WIDGET_STATE_ACTIVED) {
  23373         background = &style->active;
  23374         text.text = style->label_active;
  23375     } else if (state & NK_WIDGET_STATE_HOVER) {
  23376         background = &style->hover;
  23377         text.text = style->label_hover;
  23378     } else {
  23379         background = &style->normal;
  23380         text.text = style->label_normal;
  23381     }
  23382 
  23383     /* draw background */
  23384     if (background->type == NK_STYLE_ITEM_IMAGE) {
  23385         nk_draw_image(out, *bounds, &background->data.image, nk_white);
  23386         text.background = nk_rgba(0,0,0,0);
  23387     } else {
  23388         text.background = background->data.color;
  23389         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
  23390         nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
  23391     }
  23392 
  23393     /* draw label */
  23394     text.padding = nk_vec2(0,0);
  23395     nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
  23396 }
  23397 NK_LIB void
  23398 nk_do_property(nk_flags *ws,
  23399     struct nk_command_buffer *out, struct nk_rect property,
  23400     const char *name, struct nk_property_variant *variant,
  23401     float inc_per_pixel, char *buffer, int *len,
  23402     int *state, int *cursor, int *select_begin, int *select_end,
  23403     const struct nk_style_property *style,
  23404     enum nk_property_filter filter, struct nk_input *in,
  23405     const struct nk_user_font *font, struct nk_text_edit *text_edit,
  23406     enum nk_button_behavior behavior)
  23407 {
  23408     const nk_plugin_filter filters[] = {
  23409         nk_filter_decimal,
  23410         nk_filter_float
  23411     };
  23412     int active, old;
  23413     int num_len, name_len;
  23414     char string[NK_MAX_NUMBER_BUFFER];
  23415     float size;
  23416 
  23417     char *dst = 0;
  23418     int *length;
  23419 
  23420     struct nk_rect left;
  23421     struct nk_rect right;
  23422     struct nk_rect label;
  23423     struct nk_rect edit;
  23424     struct nk_rect empty;
  23425 
  23426     /* left decrement button */
  23427     left.h = font->height/2;
  23428     left.w = left.h;
  23429     left.x = property.x + style->border + style->padding.x;
  23430     left.y = property.y + style->border + property.h/2.0f - left.h/2;
  23431 
  23432     /* text label */
  23433     name_len = nk_strlen(name);
  23434     size = font->width(font->userdata, font->height, name, name_len);
  23435     label.x = left.x + left.w + style->padding.x;
  23436     label.w = (float)size + 2 * style->padding.x;
  23437     label.y = property.y + style->border + style->padding.y;
  23438     label.h = property.h - (2 * style->border + 2 * style->padding.y);
  23439 
  23440     /* right increment button */
  23441     right.y = left.y;
  23442     right.w = left.w;
  23443     right.h = left.h;
  23444     right.x = property.x + property.w - (right.w + style->padding.x);
  23445 
  23446     /* edit */
  23447     if (*state == NK_PROPERTY_EDIT) {
  23448         size = font->width(font->userdata, font->height, buffer, *len);
  23449         size += style->edit.cursor_size;
  23450         length = len;
  23451         dst = buffer;
  23452     } else {
  23453         switch (variant->kind) {
  23454         default: break;
  23455         case NK_PROPERTY_INT:
  23456             nk_itoa(string, variant->value.i);
  23457             num_len = nk_strlen(string);
  23458             break;
  23459         case NK_PROPERTY_FLOAT:
  23460             NK_DTOA(string, (double)variant->value.f);
  23461             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
  23462             break;
  23463         case NK_PROPERTY_DOUBLE:
  23464             NK_DTOA(string, variant->value.d);
  23465             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
  23466             break;
  23467         }
  23468         size = font->width(font->userdata, font->height, string, num_len);
  23469         dst = string;
  23470         length = &num_len;
  23471     }
  23472 
  23473     edit.w =  (float)size + 2 * style->padding.x;
  23474     edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
  23475     edit.x = right.x - (edit.w + style->padding.x);
  23476     edit.y = property.y + style->border;
  23477     edit.h = property.h - (2 * style->border);
  23478 
  23479     /* empty left space activator */
  23480     empty.w = edit.x - (label.x + label.w);
  23481     empty.x = label.x + label.w;
  23482     empty.y = property.y;
  23483     empty.h = property.h;
  23484 
  23485     /* update property */
  23486     old = (*state == NK_PROPERTY_EDIT);
  23487     nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
  23488 
  23489     /* draw property */
  23490     if (style->draw_begin) style->draw_begin(out, style->userdata);
  23491     nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
  23492     if (style->draw_end) style->draw_end(out, style->userdata);
  23493 
  23494     /* execute right button  */
  23495     if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
  23496         switch (variant->kind) {
  23497         default: break;
  23498         case NK_PROPERTY_INT:
  23499             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
  23500         case NK_PROPERTY_FLOAT:
  23501             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
  23502         case NK_PROPERTY_DOUBLE:
  23503             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
  23504         }
  23505     }
  23506     /* execute left button  */
  23507     if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
  23508         switch (variant->kind) {
  23509         default: break;
  23510         case NK_PROPERTY_INT:
  23511             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
  23512         case NK_PROPERTY_FLOAT:
  23513             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
  23514         case NK_PROPERTY_DOUBLE:
  23515             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
  23516         }
  23517     }
  23518     if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
  23519         /* property has been activated so setup buffer */
  23520         NK_MEMCPY(buffer, dst, (nk_size)*length);
  23521         *cursor = nk_utf_len(buffer, *length);
  23522         *len = *length;
  23523         length = len;
  23524         dst = buffer;
  23525         active = 0;
  23526     } else active = (*state == NK_PROPERTY_EDIT);
  23527 
  23528     /* execute and run text edit field */
  23529     nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
  23530     text_edit->active = (unsigned char)active;
  23531     text_edit->string.len = *length;
  23532     text_edit->cursor = NK_CLAMP(0, *cursor, *length);
  23533     text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
  23534     text_edit->select_end = NK_CLAMP(0,*select_end, *length);
  23535     text_edit->string.buffer.allocated = (nk_size)*length;
  23536     text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER;
  23537     text_edit->string.buffer.memory.ptr = dst;
  23538     text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
  23539     text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
  23540     nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
  23541         filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
  23542 
  23543     *length = text_edit->string.len;
  23544     *cursor = text_edit->cursor;
  23545     *select_begin = text_edit->select_start;
  23546     *select_end = text_edit->select_end;
  23547     if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
  23548         text_edit->active = nk_false;
  23549 
  23550     if (active && !text_edit->active) {
  23551         /* property is now not active so convert edit text to value*/
  23552         *state = NK_PROPERTY_DEFAULT;
  23553         buffer[*len] = '\0';
  23554         switch (variant->kind) {
  23555         default: break;
  23556         case NK_PROPERTY_INT:
  23557             variant->value.i = nk_strtoi(buffer, 0);
  23558             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
  23559             break;
  23560         case NK_PROPERTY_FLOAT:
  23561             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
  23562             variant->value.f = nk_strtof(buffer, 0);
  23563             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
  23564             break;
  23565         case NK_PROPERTY_DOUBLE:
  23566             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
  23567             variant->value.d = nk_strtod(buffer, 0);
  23568             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
  23569             break;
  23570         }
  23571     }
  23572 }
  23573 NK_LIB struct nk_property_variant
  23574 nk_property_variant_int(int value, int min_value, int max_value, int step)
  23575 {
  23576     struct nk_property_variant result;
  23577     result.kind = NK_PROPERTY_INT;
  23578     result.value.i = value;
  23579     result.min_value.i = min_value;
  23580     result.max_value.i = max_value;
  23581     result.step.i = step;
  23582     return result;
  23583 }
  23584 NK_LIB struct nk_property_variant
  23585 nk_property_variant_float(float value, float min_value, float max_value, float step)
  23586 {
  23587     struct nk_property_variant result;
  23588     result.kind = NK_PROPERTY_FLOAT;
  23589     result.value.f = value;
  23590     result.min_value.f = min_value;
  23591     result.max_value.f = max_value;
  23592     result.step.f = step;
  23593     return result;
  23594 }
  23595 NK_LIB struct nk_property_variant
  23596 nk_property_variant_double(double value, double min_value, double max_value,
  23597     double step)
  23598 {
  23599     struct nk_property_variant result;
  23600     result.kind = NK_PROPERTY_DOUBLE;
  23601     result.value.d = value;
  23602     result.min_value.d = min_value;
  23603     result.max_value.d = max_value;
  23604     result.step.d = step;
  23605     return result;
  23606 }
  23607 NK_LIB void
  23608 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
  23609     float inc_per_pixel, const enum nk_property_filter filter)
  23610 {
  23611     struct nk_window *win;
  23612     struct nk_panel *layout;
  23613     struct nk_input *in;
  23614     const struct nk_style *style;
  23615 
  23616     struct nk_rect bounds;
  23617     enum nk_widget_layout_states s;
  23618 
  23619     int *state = 0;
  23620     nk_hash hash = 0;
  23621     char *buffer = 0;
  23622     int *len = 0;
  23623     int *cursor = 0;
  23624     int *select_begin = 0;
  23625     int *select_end = 0;
  23626     int old_state;
  23627 
  23628     char dummy_buffer[NK_MAX_NUMBER_BUFFER];
  23629     int dummy_state = NK_PROPERTY_DEFAULT;
  23630     int dummy_length = 0;
  23631     int dummy_cursor = 0;
  23632     int dummy_select_begin = 0;
  23633     int dummy_select_end = 0;
  23634 
  23635     NK_ASSERT(ctx);
  23636     NK_ASSERT(ctx->current);
  23637     NK_ASSERT(ctx->current->layout);
  23638     if (!ctx || !ctx->current || !ctx->current->layout)
  23639         return;
  23640 
  23641     win = ctx->current;
  23642     layout = win->layout;
  23643     style = &ctx->style;
  23644     s = nk_widget(&bounds, ctx);
  23645     if (!s) return;
  23646 
  23647     /* calculate hash from name */
  23648     if (name[0] == '#') {
  23649         hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
  23650         name++; /* special number hash */
  23651     } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
  23652 
  23653     /* check if property is currently hot item */
  23654     if (win->property.active && hash == win->property.name) {
  23655         buffer = win->property.buffer;
  23656         len = &win->property.length;
  23657         cursor = &win->property.cursor;
  23658         state = &win->property.state;
  23659         select_begin = &win->property.select_start;
  23660         select_end = &win->property.select_end;
  23661     } else {
  23662         buffer = dummy_buffer;
  23663         len = &dummy_length;
  23664         cursor = &dummy_cursor;
  23665         state = &dummy_state;
  23666         select_begin =  &dummy_select_begin;
  23667         select_end = &dummy_select_end;
  23668     }
  23669 
  23670     /* execute property widget */
  23671     old_state = *state;
  23672     ctx->text_edit.clip = ctx->clip;
  23673     in = ((s == NK_WIDGET_ROM && !win->property.active) ||
  23674         layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  23675     nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
  23676         variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
  23677         select_end, &style->property, filter, in, style->font, &ctx->text_edit,
  23678         ctx->button_behavior);
  23679 
  23680     if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
  23681         /* current property is now hot */
  23682         win->property.active = 1;
  23683         NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
  23684         win->property.length = *len;
  23685         win->property.cursor = *cursor;
  23686         win->property.state = *state;
  23687         win->property.name = hash;
  23688         win->property.select_start = *select_begin;
  23689         win->property.select_end = *select_end;
  23690         if (*state == NK_PROPERTY_DRAG) {
  23691             ctx->input.mouse.grab = nk_true;
  23692             ctx->input.mouse.grabbed = nk_true;
  23693         }
  23694     }
  23695     /* check if previously active property is now inactive */
  23696     if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
  23697         if (old_state == NK_PROPERTY_DRAG) {
  23698             ctx->input.mouse.grab = nk_false;
  23699             ctx->input.mouse.grabbed = nk_false;
  23700             ctx->input.mouse.ungrab = nk_true;
  23701         }
  23702         win->property.select_start = 0;
  23703         win->property.select_end = 0;
  23704         win->property.active = 0;
  23705     }
  23706 }
  23707 NK_API void
  23708 nk_property_int(struct nk_context *ctx, const char *name,
  23709     int min, int *val, int max, int step, float inc_per_pixel)
  23710 {
  23711     struct nk_property_variant variant;
  23712     NK_ASSERT(ctx);
  23713     NK_ASSERT(name);
  23714     NK_ASSERT(val);
  23715 
  23716     if (!ctx || !ctx->current || !name || !val) return;
  23717     variant = nk_property_variant_int(*val, min, max, step);
  23718     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
  23719     *val = variant.value.i;
  23720 }
  23721 NK_API void
  23722 nk_property_float(struct nk_context *ctx, const char *name,
  23723     float min, float *val, float max, float step, float inc_per_pixel)
  23724 {
  23725     struct nk_property_variant variant;
  23726     NK_ASSERT(ctx);
  23727     NK_ASSERT(name);
  23728     NK_ASSERT(val);
  23729 
  23730     if (!ctx || !ctx->current || !name || !val) return;
  23731     variant = nk_property_variant_float(*val, min, max, step);
  23732     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
  23733     *val = variant.value.f;
  23734 }
  23735 NK_API void
  23736 nk_property_double(struct nk_context *ctx, const char *name,
  23737     double min, double *val, double max, double step, float inc_per_pixel)
  23738 {
  23739     struct nk_property_variant variant;
  23740     NK_ASSERT(ctx);
  23741     NK_ASSERT(name);
  23742     NK_ASSERT(val);
  23743 
  23744     if (!ctx || !ctx->current || !name || !val) return;
  23745     variant = nk_property_variant_double(*val, min, max, step);
  23746     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
  23747     *val = variant.value.d;
  23748 }
  23749 NK_API int
  23750 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
  23751     int max, int step, float inc_per_pixel)
  23752 {
  23753     struct nk_property_variant variant;
  23754     NK_ASSERT(ctx);
  23755     NK_ASSERT(name);
  23756 
  23757     if (!ctx || !ctx->current || !name) return val;
  23758     variant = nk_property_variant_int(val, min, max, step);
  23759     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
  23760     val = variant.value.i;
  23761     return val;
  23762 }
  23763 NK_API float
  23764 nk_propertyf(struct nk_context *ctx, const char *name, float min,
  23765     float val, float max, float step, float inc_per_pixel)
  23766 {
  23767     struct nk_property_variant variant;
  23768     NK_ASSERT(ctx);
  23769     NK_ASSERT(name);
  23770 
  23771     if (!ctx || !ctx->current || !name) return val;
  23772     variant = nk_property_variant_float(val, min, max, step);
  23773     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
  23774     val = variant.value.f;
  23775     return val;
  23776 }
  23777 NK_API double
  23778 nk_propertyd(struct nk_context *ctx, const char *name, double min,
  23779     double val, double max, double step, float inc_per_pixel)
  23780 {
  23781     struct nk_property_variant variant;
  23782     NK_ASSERT(ctx);
  23783     NK_ASSERT(name);
  23784 
  23785     if (!ctx || !ctx->current || !name) return val;
  23786     variant = nk_property_variant_double(val, min, max, step);
  23787     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
  23788     val = variant.value.d;
  23789     return val;
  23790 }
  23791 
  23792 
  23793 
  23794 
  23795 
  23796 /* ==============================================================
  23797  *
  23798  *                          CHART
  23799  *
  23800  * ===============================================================*/
  23801 NK_API int
  23802 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
  23803     struct nk_color color, struct nk_color highlight,
  23804     int count, float min_value, float max_value)
  23805 {
  23806     struct nk_window *win;
  23807     struct nk_chart *chart;
  23808     const struct nk_style *config;
  23809     const struct nk_style_chart *style;
  23810 
  23811     const struct nk_style_item *background;
  23812     struct nk_rect bounds = {0, 0, 0, 0};
  23813 
  23814     NK_ASSERT(ctx);
  23815     NK_ASSERT(ctx->current);
  23816     NK_ASSERT(ctx->current->layout);
  23817 
  23818     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
  23819     if (!nk_widget(&bounds, ctx)) {
  23820         chart = &ctx->current->layout->chart;
  23821         nk_zero(chart, sizeof(*chart));
  23822         return 0;
  23823     }
  23824 
  23825     win = ctx->current;
  23826     config = &ctx->style;
  23827     chart = &win->layout->chart;
  23828     style = &config->chart;
  23829 
  23830     /* setup basic generic chart  */
  23831     nk_zero(chart, sizeof(*chart));
  23832     chart->x = bounds.x + style->padding.x;
  23833     chart->y = bounds.y + style->padding.y;
  23834     chart->w = bounds.w - 2 * style->padding.x;
  23835     chart->h = bounds.h - 2 * style->padding.y;
  23836     chart->w = NK_MAX(chart->w, 2 * style->padding.x);
  23837     chart->h = NK_MAX(chart->h, 2 * style->padding.y);
  23838 
  23839     /* add first slot into chart */
  23840     {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
  23841     slot->type = type;
  23842     slot->count = count;
  23843     slot->color = color;
  23844     slot->highlight = highlight;
  23845     slot->min = NK_MIN(min_value, max_value);
  23846     slot->max = NK_MAX(min_value, max_value);
  23847     slot->range = slot->max - slot->min;}
  23848 
  23849     /* draw chart background */
  23850     background = &style->background;
  23851     if (background->type == NK_STYLE_ITEM_IMAGE) {
  23852         nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
  23853     } else {
  23854         nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
  23855         nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
  23856             style->rounding, style->background.data.color);
  23857     }
  23858     return 1;
  23859 }
  23860 NK_API int
  23861 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
  23862     int count, float min_value, float max_value)
  23863 {
  23864     return nk_chart_begin_colored(ctx, type, ctx->style.chart.color,
  23865                 ctx->style.chart.selected_color, count, min_value, max_value);
  23866 }
  23867 NK_API void
  23868 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
  23869     struct nk_color color, struct nk_color highlight,
  23870     int count, float min_value, float max_value)
  23871 {
  23872     NK_ASSERT(ctx);
  23873     NK_ASSERT(ctx->current);
  23874     NK_ASSERT(ctx->current->layout);
  23875     NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
  23876     if (!ctx || !ctx->current || !ctx->current->layout) return;
  23877     if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
  23878 
  23879     /* add another slot into the graph */
  23880     {struct nk_chart *chart = &ctx->current->layout->chart;
  23881     struct nk_chart_slot *slot = &chart->slots[chart->slot++];
  23882     slot->type = type;
  23883     slot->count = count;
  23884     slot->color = color;
  23885     slot->highlight = highlight;
  23886     slot->min = NK_MIN(min_value, max_value);
  23887     slot->max = NK_MAX(min_value, max_value);
  23888     slot->range = slot->max - slot->min;}
  23889 }
  23890 NK_API void
  23891 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
  23892     int count, float min_value, float max_value)
  23893 {
  23894     nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color,
  23895         ctx->style.chart.selected_color, count, min_value, max_value);
  23896 }
  23897 NK_INTERN nk_flags
  23898 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
  23899     struct nk_chart *g, float value, int slot)
  23900 {
  23901     struct nk_panel *layout = win->layout;
  23902     const struct nk_input *i = &ctx->input;
  23903     struct nk_command_buffer *out = &win->buffer;
  23904 
  23905     nk_flags ret = 0;
  23906     struct nk_vec2 cur;
  23907     struct nk_rect bounds;
  23908     struct nk_color color;
  23909     float step;
  23910     float range;
  23911     float ratio;
  23912 
  23913     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
  23914     step = g->w / (float)g->slots[slot].count;
  23915     range = g->slots[slot].max - g->slots[slot].min;
  23916     ratio = (value - g->slots[slot].min) / range;
  23917 
  23918     if (g->slots[slot].index == 0) {
  23919         /* first data point does not have a connection */
  23920         g->slots[slot].last.x = g->x;
  23921         g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
  23922 
  23923         bounds.x = g->slots[slot].last.x - 2;
  23924         bounds.y = g->slots[slot].last.y - 2;
  23925         bounds.w = bounds.h = 4;
  23926 
  23927         color = g->slots[slot].color;
  23928         if (!(layout->flags & NK_WINDOW_ROM) &&
  23929             NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
  23930             ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
  23931             ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
  23932                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
  23933             color = g->slots[slot].highlight;
  23934         }
  23935         nk_fill_rect(out, bounds, 0, color);
  23936         g->slots[slot].index += 1;
  23937         return ret;
  23938     }
  23939 
  23940     /* draw a line between the last data point and the new one */
  23941     color = g->slots[slot].color;
  23942     cur.x = g->x + (float)(step * (float)g->slots[slot].index);
  23943     cur.y = (g->y + g->h) - (ratio * (float)g->h);
  23944     nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
  23945 
  23946     bounds.x = cur.x - 3;
  23947     bounds.y = cur.y - 3;
  23948     bounds.w = bounds.h = 6;
  23949 
  23950     /* user selection of current data point */
  23951     if (!(layout->flags & NK_WINDOW_ROM)) {
  23952         if (nk_input_is_mouse_hovering_rect(i, bounds)) {
  23953             ret = NK_CHART_HOVERING;
  23954             ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
  23955                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
  23956             color = g->slots[slot].highlight;
  23957         }
  23958     }
  23959     nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
  23960 
  23961     /* save current data point position */
  23962     g->slots[slot].last.x = cur.x;
  23963     g->slots[slot].last.y = cur.y;
  23964     g->slots[slot].index  += 1;
  23965     return ret;
  23966 }
  23967 NK_INTERN nk_flags
  23968 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
  23969     struct nk_chart *chart, float value, int slot)
  23970 {
  23971     struct nk_command_buffer *out = &win->buffer;
  23972     const struct nk_input *in = &ctx->input;
  23973     struct nk_panel *layout = win->layout;
  23974 
  23975     float ratio;
  23976     nk_flags ret = 0;
  23977     struct nk_color color;
  23978     struct nk_rect item = {0,0,0,0};
  23979 
  23980     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
  23981     if (chart->slots[slot].index  >= chart->slots[slot].count)
  23982         return nk_false;
  23983     if (chart->slots[slot].count) {
  23984         float padding = (float)(chart->slots[slot].count-1);
  23985         item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
  23986     }
  23987 
  23988     /* calculate bounds of current bar chart entry */
  23989     color = chart->slots[slot].color;;
  23990     item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
  23991     if (value >= 0) {
  23992         ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
  23993         item.y = (chart->y + chart->h) - chart->h * ratio;
  23994     } else {
  23995         ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
  23996         item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
  23997     }
  23998     item.x = chart->x + ((float)chart->slots[slot].index * item.w);
  23999     item.x = item.x + ((float)chart->slots[slot].index);
  24000 
  24001     /* user chart bar selection */
  24002     if (!(layout->flags & NK_WINDOW_ROM) &&
  24003         NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
  24004         ret = NK_CHART_HOVERING;
  24005         ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
  24006                 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
  24007         color = chart->slots[slot].highlight;
  24008     }
  24009     nk_fill_rect(out, item, 0, color);
  24010     chart->slots[slot].index += 1;
  24011     return ret;
  24012 }
  24013 NK_API nk_flags
  24014 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
  24015 {
  24016     nk_flags flags;
  24017     struct nk_window *win;
  24018 
  24019     NK_ASSERT(ctx);
  24020     NK_ASSERT(ctx->current);
  24021     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
  24022     NK_ASSERT(slot < ctx->current->layout->chart.slot);
  24023     if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
  24024     if (slot >= ctx->current->layout->chart.slot) return nk_false;
  24025 
  24026     win = ctx->current;
  24027     if (win->layout->chart.slot < slot) return nk_false;
  24028     switch (win->layout->chart.slots[slot].type) {
  24029     case NK_CHART_LINES:
  24030         flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
  24031     case NK_CHART_COLUMN:
  24032         flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
  24033     default:
  24034     case NK_CHART_MAX:
  24035         flags = 0;
  24036     }
  24037     return flags;
  24038 }
  24039 NK_API nk_flags
  24040 nk_chart_push(struct nk_context *ctx, float value)
  24041 {
  24042     return nk_chart_push_slot(ctx, value, 0);
  24043 }
  24044 NK_API void
  24045 nk_chart_end(struct nk_context *ctx)
  24046 {
  24047     struct nk_window *win;
  24048     struct nk_chart *chart;
  24049 
  24050     NK_ASSERT(ctx);
  24051     NK_ASSERT(ctx->current);
  24052     if (!ctx || !ctx->current)
  24053         return;
  24054 
  24055     win = ctx->current;
  24056     chart = &win->layout->chart;
  24057     NK_MEMSET(chart, 0, sizeof(*chart));
  24058     return;
  24059 }
  24060 NK_API void
  24061 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
  24062     int count, int offset)
  24063 {
  24064     int i = 0;
  24065     float min_value;
  24066     float max_value;
  24067 
  24068     NK_ASSERT(ctx);
  24069     NK_ASSERT(values);
  24070     if (!ctx || !values || !count) return;
  24071 
  24072     min_value = values[offset];
  24073     max_value = values[offset];
  24074     for (i = 0; i < count; ++i) {
  24075         min_value = NK_MIN(values[i + offset], min_value);
  24076         max_value = NK_MAX(values[i + offset], max_value);
  24077     }
  24078 
  24079     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
  24080         for (i = 0; i < count; ++i)
  24081             nk_chart_push(ctx, values[i + offset]);
  24082         nk_chart_end(ctx);
  24083     }
  24084 }
  24085 NK_API void
  24086 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
  24087     float(*value_getter)(void* user, int index), int count, int offset)
  24088 {
  24089     int i = 0;
  24090     float min_value;
  24091     float max_value;
  24092 
  24093     NK_ASSERT(ctx);
  24094     NK_ASSERT(value_getter);
  24095     if (!ctx || !value_getter || !count) return;
  24096 
  24097     max_value = min_value = value_getter(userdata, offset);
  24098     for (i = 0; i < count; ++i) {
  24099         float value = value_getter(userdata, i + offset);
  24100         min_value = NK_MIN(value, min_value);
  24101         max_value = NK_MAX(value, max_value);
  24102     }
  24103 
  24104     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
  24105         for (i = 0; i < count; ++i)
  24106             nk_chart_push(ctx, value_getter(userdata, i + offset));
  24107         nk_chart_end(ctx);
  24108     }
  24109 }
  24110 
  24111 
  24112 
  24113 
  24114 
  24115 /* ==============================================================
  24116  *
  24117  *                          COLOR PICKER
  24118  *
  24119  * ===============================================================*/
  24120 NK_LIB int
  24121 nk_color_picker_behavior(nk_flags *state,
  24122     const struct nk_rect *bounds, const struct nk_rect *matrix,
  24123     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
  24124     struct nk_colorf *color, const struct nk_input *in)
  24125 {
  24126     float hsva[4];
  24127     int value_changed = 0;
  24128     int hsv_changed = 0;
  24129 
  24130     NK_ASSERT(state);
  24131     NK_ASSERT(matrix);
  24132     NK_ASSERT(hue_bar);
  24133     NK_ASSERT(color);
  24134 
  24135     /* color matrix */
  24136     nk_colorf_hsva_fv(hsva, *color);
  24137     if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
  24138         hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
  24139         hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
  24140         value_changed = hsv_changed = 1;
  24141     }
  24142     /* hue bar */
  24143     if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
  24144         hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
  24145         value_changed = hsv_changed = 1;
  24146     }
  24147     /* alpha bar */
  24148     if (alpha_bar) {
  24149         if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
  24150             hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
  24151             value_changed = 1;
  24152         }
  24153     }
  24154     nk_widget_state_reset(state);
  24155     if (hsv_changed) {
  24156         *color = nk_hsva_colorfv(hsva);
  24157         *state = NK_WIDGET_STATE_ACTIVE;
  24158     }
  24159     if (value_changed) {
  24160         color->a = hsva[3];
  24161         *state = NK_WIDGET_STATE_ACTIVE;
  24162     }
  24163     /* set color picker widget state */
  24164     if (nk_input_is_mouse_hovering_rect(in, *bounds))
  24165         *state = NK_WIDGET_STATE_HOVERED;
  24166     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
  24167         *state |= NK_WIDGET_STATE_ENTERED;
  24168     else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
  24169         *state |= NK_WIDGET_STATE_LEFT;
  24170     return value_changed;
  24171 }
  24172 NK_LIB void
  24173 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
  24174     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
  24175     struct nk_colorf col)
  24176 {
  24177     NK_STORAGE const struct nk_color black = {0,0,0,255};
  24178     NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
  24179     NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
  24180 
  24181     const float crosshair_size = 7.0f;
  24182     struct nk_color temp;
  24183     float hsva[4];
  24184     float line_y;
  24185     int i;
  24186 
  24187     NK_ASSERT(o);
  24188     NK_ASSERT(matrix);
  24189     NK_ASSERT(hue_bar);
  24190 
  24191     /* draw hue bar */
  24192     nk_colorf_hsva_fv(hsva, col);
  24193     for (i = 0; i < 6; ++i) {
  24194         NK_GLOBAL const struct nk_color hue_colors[] = {
  24195             {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255},
  24196             {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}
  24197         };
  24198         nk_fill_rect_multi_color(o,
  24199             nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
  24200                 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
  24201                 hue_colors[i+1], hue_colors[i+1]);
  24202     }
  24203     line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
  24204     nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
  24205         line_y, 1, nk_rgb(255,255,255));
  24206 
  24207     /* draw alpha bar */
  24208     if (alpha_bar) {
  24209         float alpha = NK_SATURATE(col.a);
  24210         line_y = (float)(int)(alpha_bar->y +  (1.0f - alpha) * matrix->h + 0.5f);
  24211 
  24212         nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
  24213         nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
  24214             line_y, 1, nk_rgb(255,255,255));
  24215     }
  24216 
  24217     /* draw color matrix */
  24218     temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
  24219     nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
  24220     nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
  24221 
  24222     /* draw cross-hair */
  24223     {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
  24224     p.x = (float)(int)(matrix->x + S * matrix->w);
  24225     p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
  24226     nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
  24227     nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
  24228     nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
  24229     nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
  24230 }
  24231 NK_LIB int
  24232 nk_do_color_picker(nk_flags *state,
  24233     struct nk_command_buffer *out, struct nk_colorf *col,
  24234     enum nk_color_format fmt, struct nk_rect bounds,
  24235     struct nk_vec2 padding, const struct nk_input *in,
  24236     const struct nk_user_font *font)
  24237 {
  24238     int ret = 0;
  24239     struct nk_rect matrix;
  24240     struct nk_rect hue_bar;
  24241     struct nk_rect alpha_bar;
  24242     float bar_w;
  24243 
  24244     NK_ASSERT(out);
  24245     NK_ASSERT(col);
  24246     NK_ASSERT(state);
  24247     NK_ASSERT(font);
  24248     if (!out || !col || !state || !font)
  24249         return ret;
  24250 
  24251     bar_w = font->height;
  24252     bounds.x += padding.x;
  24253     bounds.y += padding.x;
  24254     bounds.w -= 2 * padding.x;
  24255     bounds.h -= 2 * padding.y;
  24256 
  24257     matrix.x = bounds.x;
  24258     matrix.y = bounds.y;
  24259     matrix.h = bounds.h;
  24260     matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
  24261 
  24262     hue_bar.w = bar_w;
  24263     hue_bar.y = bounds.y;
  24264     hue_bar.h = matrix.h;
  24265     hue_bar.x = matrix.x + matrix.w + padding.x;
  24266 
  24267     alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
  24268     alpha_bar.y = bounds.y;
  24269     alpha_bar.w = bar_w;
  24270     alpha_bar.h = matrix.h;
  24271 
  24272     ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
  24273         (fmt == NK_RGBA) ? &alpha_bar:0, col, in);
  24274     nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col);
  24275     return ret;
  24276 }
  24277 NK_API int
  24278 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color,
  24279     enum nk_color_format fmt)
  24280 {
  24281     struct nk_window *win;
  24282     struct nk_panel *layout;
  24283     const struct nk_style *config;
  24284     const struct nk_input *in;
  24285 
  24286     enum nk_widget_layout_states state;
  24287     struct nk_rect bounds;
  24288 
  24289     NK_ASSERT(ctx);
  24290     NK_ASSERT(color);
  24291     NK_ASSERT(ctx->current);
  24292     NK_ASSERT(ctx->current->layout);
  24293     if (!ctx || !ctx->current || !ctx->current->layout || !color)
  24294         return 0;
  24295 
  24296     win = ctx->current;
  24297     config = &ctx->style;
  24298     layout = win->layout;
  24299     state = nk_widget(&bounds, ctx);
  24300     if (!state) return 0;
  24301     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
  24302     return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
  24303                 nk_vec2(0,0), in, config->font);
  24304 }
  24305 NK_API struct nk_colorf
  24306 nk_color_picker(struct nk_context *ctx, struct nk_colorf color,
  24307     enum nk_color_format fmt)
  24308 {
  24309     nk_color_pick(ctx, &color, fmt);
  24310     return color;
  24311 }
  24312 
  24313 
  24314 
  24315 
  24316 
  24317 /* ==============================================================
  24318  *
  24319  *                          COMBO
  24320  *
  24321  * ===============================================================*/
  24322 NK_INTERN int
  24323 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
  24324     struct nk_vec2 size, int is_clicked, struct nk_rect header)
  24325 {
  24326     struct nk_window *popup;
  24327     int is_open = 0;
  24328     int is_active = 0;
  24329     struct nk_rect body;
  24330     nk_hash hash;
  24331 
  24332     NK_ASSERT(ctx);
  24333     NK_ASSERT(ctx->current);
  24334     NK_ASSERT(ctx->current->layout);
  24335     if (!ctx || !ctx->current || !ctx->current->layout)
  24336         return 0;
  24337 
  24338     popup = win->popup.win;
  24339     body.x = header.x;
  24340     body.w = size.x;
  24341     body.y = header.y + header.h-ctx->style.window.combo_border;
  24342     body.h = size.y;
  24343 
  24344     hash = win->popup.combo_count++;
  24345     is_open = (popup) ? nk_true:nk_false;
  24346     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
  24347     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
  24348         (!is_open && !is_active && !is_clicked)) return 0;
  24349     if (!nk_nonblock_begin(ctx, 0, body,
  24350         (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
  24351 
  24352     win->popup.type = NK_PANEL_COMBO;
  24353     win->popup.name = hash;
  24354     return 1;
  24355 }
  24356 NK_API int
  24357 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
  24358     struct nk_vec2 size)
  24359 {
  24360     const struct nk_input *in;
  24361     struct nk_window *win;
  24362     struct nk_style *style;
  24363 
  24364     enum nk_widget_layout_states s;
  24365     int is_clicked = nk_false;
  24366     struct nk_rect header;
  24367     const struct nk_style_item *background;
  24368     struct nk_text text;
  24369 
  24370     NK_ASSERT(ctx);
  24371     NK_ASSERT(selected);
  24372     NK_ASSERT(ctx->current);
  24373     NK_ASSERT(ctx->current->layout);
  24374     if (!ctx || !ctx->current || !ctx->current->layout || !selected)
  24375         return 0;
  24376 
  24377     win = ctx->current;
  24378     style = &ctx->style;
  24379     s = nk_widget(&header, ctx);
  24380     if (s == NK_WIDGET_INVALID)
  24381         return 0;
  24382 
  24383     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  24384     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  24385         is_clicked = nk_true;
  24386 
  24387     /* draw combo box header background and border */
  24388     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
  24389         background = &style->combo.active;
  24390         text.text = style->combo.label_active;
  24391     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
  24392         background = &style->combo.hover;
  24393         text.text = style->combo.label_hover;
  24394     } else {
  24395         background = &style->combo.normal;
  24396         text.text = style->combo.label_normal;
  24397     }
  24398     if (background->type == NK_STYLE_ITEM_IMAGE) {
  24399         text.background = nk_rgba(0,0,0,0);
  24400         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  24401     } else {
  24402         text.background = background->data.color;
  24403         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  24404         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  24405     }
  24406     {
  24407         /* print currently selected text item */
  24408         struct nk_rect label;
  24409         struct nk_rect button;
  24410         struct nk_rect content;
  24411 
  24412         enum nk_symbol_type sym;
  24413         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  24414             sym = style->combo.sym_hover;
  24415         else if (is_clicked)
  24416             sym = style->combo.sym_active;
  24417         else sym = style->combo.sym_normal;
  24418 
  24419         /* calculate button */
  24420         button.w = header.h - 2 * style->combo.button_padding.y;
  24421         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
  24422         button.y = header.y + style->combo.button_padding.y;
  24423         button.h = button.w;
  24424 
  24425         content.x = button.x + style->combo.button.padding.x;
  24426         content.y = button.y + style->combo.button.padding.y;
  24427         content.w = button.w - 2 * style->combo.button.padding.x;
  24428         content.h = button.h - 2 * style->combo.button.padding.y;
  24429 
  24430         /* draw selected label */
  24431         text.padding = nk_vec2(0,0);
  24432         label.x = header.x + style->combo.content_padding.x;
  24433         label.y = header.y + style->combo.content_padding.y;
  24434         label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
  24435         label.h = header.h - 2 * style->combo.content_padding.y;
  24436         nk_widget_text(&win->buffer, label, selected, len, &text,
  24437             NK_TEXT_LEFT, ctx->style.font);
  24438 
  24439         /* draw open/close button */
  24440         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
  24441             &ctx->style.combo.button, sym, style->font);
  24442     }
  24443     return nk_combo_begin(ctx, win, size, is_clicked, header);
  24444 }
  24445 NK_API int
  24446 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
  24447 {
  24448     return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);
  24449 }
  24450 NK_API int
  24451 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
  24452 {
  24453     struct nk_window *win;
  24454     struct nk_style *style;
  24455     const struct nk_input *in;
  24456 
  24457     struct nk_rect header;
  24458     int is_clicked = nk_false;
  24459     enum nk_widget_layout_states s;
  24460     const struct nk_style_item *background;
  24461 
  24462     NK_ASSERT(ctx);
  24463     NK_ASSERT(ctx->current);
  24464     NK_ASSERT(ctx->current->layout);
  24465     if (!ctx || !ctx->current || !ctx->current->layout)
  24466         return 0;
  24467 
  24468     win = ctx->current;
  24469     style = &ctx->style;
  24470     s = nk_widget(&header, ctx);
  24471     if (s == NK_WIDGET_INVALID)
  24472         return 0;
  24473 
  24474     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  24475     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  24476         is_clicked = nk_true;
  24477 
  24478     /* draw combo box header background and border */
  24479     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
  24480         background = &style->combo.active;
  24481     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  24482         background = &style->combo.hover;
  24483     else background = &style->combo.normal;
  24484 
  24485     if (background->type == NK_STYLE_ITEM_IMAGE) {
  24486         nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
  24487     } else {
  24488         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  24489         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  24490     }
  24491     {
  24492         struct nk_rect content;
  24493         struct nk_rect button;
  24494         struct nk_rect bounds;
  24495 
  24496         enum nk_symbol_type sym;
  24497         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  24498             sym = style->combo.sym_hover;
  24499         else if (is_clicked)
  24500             sym = style->combo.sym_active;
  24501         else sym = style->combo.sym_normal;
  24502 
  24503         /* calculate button */
  24504         button.w = header.h - 2 * style->combo.button_padding.y;
  24505         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
  24506         button.y = header.y + style->combo.button_padding.y;
  24507         button.h = button.w;
  24508 
  24509         content.x = button.x + style->combo.button.padding.x;
  24510         content.y = button.y + style->combo.button.padding.y;
  24511         content.w = button.w - 2 * style->combo.button.padding.x;
  24512         content.h = button.h - 2 * style->combo.button.padding.y;
  24513 
  24514         /* draw color */
  24515         bounds.h = header.h - 4 * style->combo.content_padding.y;
  24516         bounds.y = header.y + 2 * style->combo.content_padding.y;
  24517         bounds.x = header.x + 2 * style->combo.content_padding.x;
  24518         bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
  24519         nk_fill_rect(&win->buffer, bounds, 0, color);
  24520 
  24521         /* draw open/close button */
  24522         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
  24523             &ctx->style.combo.button, sym, style->font);
  24524     }
  24525     return nk_combo_begin(ctx, win, size, is_clicked, header);
  24526 }
  24527 NK_API int
  24528 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
  24529 {
  24530     struct nk_window *win;
  24531     struct nk_style *style;
  24532     const struct nk_input *in;
  24533 
  24534     struct nk_rect header;
  24535     int is_clicked = nk_false;
  24536     enum nk_widget_layout_states s;
  24537     const struct nk_style_item *background;
  24538     struct nk_color sym_background;
  24539     struct nk_color symbol_color;
  24540 
  24541     NK_ASSERT(ctx);
  24542     NK_ASSERT(ctx->current);
  24543     NK_ASSERT(ctx->current->layout);
  24544     if (!ctx || !ctx->current || !ctx->current->layout)
  24545         return 0;
  24546 
  24547     win = ctx->current;
  24548     style = &ctx->style;
  24549     s = nk_widget(&header, ctx);
  24550     if (s == NK_WIDGET_INVALID)
  24551         return 0;
  24552 
  24553     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  24554     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  24555         is_clicked = nk_true;
  24556 
  24557     /* draw combo box header background and border */
  24558     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
  24559         background = &style->combo.active;
  24560         symbol_color = style->combo.symbol_active;
  24561     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
  24562         background = &style->combo.hover;
  24563         symbol_color = style->combo.symbol_hover;
  24564     } else {
  24565         background = &style->combo.normal;
  24566         symbol_color = style->combo.symbol_hover;
  24567     }
  24568 
  24569     if (background->type == NK_STYLE_ITEM_IMAGE) {
  24570         sym_background = nk_rgba(0,0,0,0);
  24571         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  24572     } else {
  24573         sym_background = background->data.color;
  24574         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  24575         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  24576     }
  24577     {
  24578         struct nk_rect bounds = {0,0,0,0};
  24579         struct nk_rect content;
  24580         struct nk_rect button;
  24581 
  24582         enum nk_symbol_type sym;
  24583         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  24584             sym = style->combo.sym_hover;
  24585         else if (is_clicked)
  24586             sym = style->combo.sym_active;
  24587         else sym = style->combo.sym_normal;
  24588 
  24589         /* calculate button */
  24590         button.w = header.h - 2 * style->combo.button_padding.y;
  24591         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
  24592         button.y = header.y + style->combo.button_padding.y;
  24593         button.h = button.w;
  24594 
  24595         content.x = button.x + style->combo.button.padding.x;
  24596         content.y = button.y + style->combo.button.padding.y;
  24597         content.w = button.w - 2 * style->combo.button.padding.x;
  24598         content.h = button.h - 2 * style->combo.button.padding.y;
  24599 
  24600         /* draw symbol */
  24601         bounds.h = header.h - 2 * style->combo.content_padding.y;
  24602         bounds.y = header.y + style->combo.content_padding.y;
  24603         bounds.x = header.x + style->combo.content_padding.x;
  24604         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
  24605         nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
  24606             1.0f, style->font);
  24607 
  24608         /* draw open/close button */
  24609         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
  24610             &ctx->style.combo.button, sym, style->font);
  24611     }
  24612     return nk_combo_begin(ctx, win, size, is_clicked, header);
  24613 }
  24614 NK_API int
  24615 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
  24616     enum nk_symbol_type symbol, struct nk_vec2 size)
  24617 {
  24618     struct nk_window *win;
  24619     struct nk_style *style;
  24620     struct nk_input *in;
  24621 
  24622     struct nk_rect header;
  24623     int is_clicked = nk_false;
  24624     enum nk_widget_layout_states s;
  24625     const struct nk_style_item *background;
  24626     struct nk_color symbol_color;
  24627     struct nk_text text;
  24628 
  24629     NK_ASSERT(ctx);
  24630     NK_ASSERT(ctx->current);
  24631     NK_ASSERT(ctx->current->layout);
  24632     if (!ctx || !ctx->current || !ctx->current->layout)
  24633         return 0;
  24634 
  24635     win = ctx->current;
  24636     style = &ctx->style;
  24637     s = nk_widget(&header, ctx);
  24638     if (!s) return 0;
  24639 
  24640     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  24641     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  24642         is_clicked = nk_true;
  24643 
  24644     /* draw combo box header background and border */
  24645     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
  24646         background = &style->combo.active;
  24647         symbol_color = style->combo.symbol_active;
  24648         text.text = style->combo.label_active;
  24649     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
  24650         background = &style->combo.hover;
  24651         symbol_color = style->combo.symbol_hover;
  24652         text.text = style->combo.label_hover;
  24653     } else {
  24654         background = &style->combo.normal;
  24655         symbol_color = style->combo.symbol_normal;
  24656         text.text = style->combo.label_normal;
  24657     }
  24658     if (background->type == NK_STYLE_ITEM_IMAGE) {
  24659         text.background = nk_rgba(0,0,0,0);
  24660         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  24661     } else {
  24662         text.background = background->data.color;
  24663         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  24664         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  24665     }
  24666     {
  24667         struct nk_rect content;
  24668         struct nk_rect button;
  24669         struct nk_rect label;
  24670         struct nk_rect image;
  24671 
  24672         enum nk_symbol_type sym;
  24673         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  24674             sym = style->combo.sym_hover;
  24675         else if (is_clicked)
  24676             sym = style->combo.sym_active;
  24677         else sym = style->combo.sym_normal;
  24678 
  24679         /* calculate button */
  24680         button.w = header.h - 2 * style->combo.button_padding.y;
  24681         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
  24682         button.y = header.y + style->combo.button_padding.y;
  24683         button.h = button.w;
  24684 
  24685         content.x = button.x + style->combo.button.padding.x;
  24686         content.y = button.y + style->combo.button.padding.y;
  24687         content.w = button.w - 2 * style->combo.button.padding.x;
  24688         content.h = button.h - 2 * style->combo.button.padding.y;
  24689         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
  24690             &ctx->style.combo.button, sym, style->font);
  24691 
  24692         /* draw symbol */
  24693         image.x = header.x + style->combo.content_padding.x;
  24694         image.y = header.y + style->combo.content_padding.y;
  24695         image.h = header.h - 2 * style->combo.content_padding.y;
  24696         image.w = image.h;
  24697         nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
  24698             1.0f, style->font);
  24699 
  24700         /* draw label */
  24701         text.padding = nk_vec2(0,0);
  24702         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
  24703         label.y = header.y + style->combo.content_padding.y;
  24704         label.w = (button.x - style->combo.content_padding.x) - label.x;
  24705         label.h = header.h - 2 * style->combo.content_padding.y;
  24706         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
  24707     }
  24708     return nk_combo_begin(ctx, win, size, is_clicked, header);
  24709 }
  24710 NK_API int
  24711 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
  24712 {
  24713     struct nk_window *win;
  24714     struct nk_style *style;
  24715     const struct nk_input *in;
  24716 
  24717     struct nk_rect header;
  24718     int is_clicked = nk_false;
  24719     enum nk_widget_layout_states s;
  24720     const struct nk_style_item *background;
  24721 
  24722     NK_ASSERT(ctx);
  24723     NK_ASSERT(ctx->current);
  24724     NK_ASSERT(ctx->current->layout);
  24725     if (!ctx || !ctx->current || !ctx->current->layout)
  24726         return 0;
  24727 
  24728     win = ctx->current;
  24729     style = &ctx->style;
  24730     s = nk_widget(&header, ctx);
  24731     if (s == NK_WIDGET_INVALID)
  24732         return 0;
  24733 
  24734     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  24735     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  24736         is_clicked = nk_true;
  24737 
  24738     /* draw combo box header background and border */
  24739     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
  24740         background = &style->combo.active;
  24741     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  24742         background = &style->combo.hover;
  24743     else background = &style->combo.normal;
  24744 
  24745     if (background->type == NK_STYLE_ITEM_IMAGE) {
  24746         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  24747     } else {
  24748         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  24749         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  24750     }
  24751     {
  24752         struct nk_rect bounds = {0,0,0,0};
  24753         struct nk_rect content;
  24754         struct nk_rect button;
  24755 
  24756         enum nk_symbol_type sym;
  24757         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  24758             sym = style->combo.sym_hover;
  24759         else if (is_clicked)
  24760             sym = style->combo.sym_active;
  24761         else sym = style->combo.sym_normal;
  24762 
  24763         /* calculate button */
  24764         button.w = header.h - 2 * style->combo.button_padding.y;
  24765         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
  24766         button.y = header.y + style->combo.button_padding.y;
  24767         button.h = button.w;
  24768 
  24769         content.x = button.x + style->combo.button.padding.x;
  24770         content.y = button.y + style->combo.button.padding.y;
  24771         content.w = button.w - 2 * style->combo.button.padding.x;
  24772         content.h = button.h - 2 * style->combo.button.padding.y;
  24773 
  24774         /* draw image */
  24775         bounds.h = header.h - 2 * style->combo.content_padding.y;
  24776         bounds.y = header.y + style->combo.content_padding.y;
  24777         bounds.x = header.x + style->combo.content_padding.x;
  24778         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
  24779         nk_draw_image(&win->buffer, bounds, &img, nk_white);
  24780 
  24781         /* draw open/close button */
  24782         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
  24783             &ctx->style.combo.button, sym, style->font);
  24784     }
  24785     return nk_combo_begin(ctx, win, size, is_clicked, header);
  24786 }
  24787 NK_API int
  24788 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
  24789     struct nk_image img, struct nk_vec2 size)
  24790 {
  24791     struct nk_window *win;
  24792     struct nk_style *style;
  24793     struct nk_input *in;
  24794 
  24795     struct nk_rect header;
  24796     int is_clicked = nk_false;
  24797     enum nk_widget_layout_states s;
  24798     const struct nk_style_item *background;
  24799     struct nk_text text;
  24800 
  24801     NK_ASSERT(ctx);
  24802     NK_ASSERT(ctx->current);
  24803     NK_ASSERT(ctx->current->layout);
  24804     if (!ctx || !ctx->current || !ctx->current->layout)
  24805         return 0;
  24806 
  24807     win = ctx->current;
  24808     style = &ctx->style;
  24809     s = nk_widget(&header, ctx);
  24810     if (!s) return 0;
  24811 
  24812     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
  24813     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
  24814         is_clicked = nk_true;
  24815 
  24816     /* draw combo box header background and border */
  24817     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
  24818         background = &style->combo.active;
  24819         text.text = style->combo.label_active;
  24820     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
  24821         background = &style->combo.hover;
  24822         text.text = style->combo.label_hover;
  24823     } else {
  24824         background = &style->combo.normal;
  24825         text.text = style->combo.label_normal;
  24826     }
  24827     if (background->type == NK_STYLE_ITEM_IMAGE) {
  24828         text.background = nk_rgba(0,0,0,0);
  24829         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
  24830     } else {
  24831         text.background = background->data.color;
  24832         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
  24833         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
  24834     }
  24835     {
  24836         struct nk_rect content;
  24837         struct nk_rect button;
  24838         struct nk_rect label;
  24839         struct nk_rect image;
  24840 
  24841         enum nk_symbol_type sym;
  24842         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
  24843             sym = style->combo.sym_hover;
  24844         else if (is_clicked)
  24845             sym = style->combo.sym_active;
  24846         else sym = style->combo.sym_normal;
  24847 
  24848         /* calculate button */
  24849         button.w = header.h - 2 * style->combo.button_padding.y;
  24850         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
  24851         button.y = header.y + style->combo.button_padding.y;
  24852         button.h = button.w;
  24853 
  24854         content.x = button.x + style->combo.button.padding.x;
  24855         content.y = button.y + style->combo.button.padding.y;
  24856         content.w = button.w - 2 * style->combo.button.padding.x;
  24857         content.h = button.h - 2 * style->combo.button.padding.y;
  24858         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
  24859             &ctx->style.combo.button, sym, style->font);
  24860 
  24861         /* draw image */
  24862         image.x = header.x + style->combo.content_padding.x;
  24863         image.y = header.y + style->combo.content_padding.y;
  24864         image.h = header.h - 2 * style->combo.content_padding.y;
  24865         image.w = image.h;
  24866         nk_draw_image(&win->buffer, image, &img, nk_white);
  24867 
  24868         /* draw label */
  24869         text.padding = nk_vec2(0,0);
  24870         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
  24871         label.y = header.y + style->combo.content_padding.y;
  24872         label.w = (button.x - style->combo.content_padding.x) - label.x;
  24873         label.h = header.h - 2 * style->combo.content_padding.y;
  24874         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
  24875     }
  24876     return nk_combo_begin(ctx, win, size, is_clicked, header);
  24877 }
  24878 NK_API int
  24879 nk_combo_begin_symbol_label(struct nk_context *ctx,
  24880     const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
  24881 {
  24882     return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);
  24883 }
  24884 NK_API int
  24885 nk_combo_begin_image_label(struct nk_context *ctx,
  24886     const char *selected, struct nk_image img, struct nk_vec2 size)
  24887 {
  24888     return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);
  24889 }
  24890 NK_API int
  24891 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
  24892 {
  24893     return nk_contextual_item_text(ctx, text, len, align);
  24894 }
  24895 NK_API int
  24896 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
  24897 {
  24898     return nk_contextual_item_label(ctx, label, align);
  24899 }
  24900 NK_API int
  24901 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
  24902     int len, nk_flags alignment)
  24903 {
  24904     return nk_contextual_item_image_text(ctx, img, text, len, alignment);
  24905 }
  24906 NK_API int
  24907 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
  24908     const char *text, nk_flags alignment)
  24909 {
  24910     return nk_contextual_item_image_label(ctx, img, text, alignment);
  24911 }
  24912 NK_API int
  24913 nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
  24914     const char *text, int len, nk_flags alignment)
  24915 {
  24916     return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);
  24917 }
  24918 NK_API int
  24919 nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
  24920     const char *label, nk_flags alignment)
  24921 {
  24922     return nk_contextual_item_symbol_label(ctx, sym, label, alignment);
  24923 }
  24924 NK_API void nk_combo_end(struct nk_context *ctx)
  24925 {
  24926     nk_contextual_end(ctx);
  24927 }
  24928 NK_API void nk_combo_close(struct nk_context *ctx)
  24929 {
  24930     nk_contextual_close(ctx);
  24931 }
  24932 NK_API int
  24933 nk_combo(struct nk_context *ctx, const char **items, int count,
  24934     int selected, int item_height, struct nk_vec2 size)
  24935 {
  24936     int i = 0;
  24937     int max_height;
  24938     struct nk_vec2 item_spacing;
  24939     struct nk_vec2 window_padding;
  24940 
  24941     NK_ASSERT(ctx);
  24942     NK_ASSERT(items);
  24943     NK_ASSERT(ctx->current);
  24944     if (!ctx || !items ||!count)
  24945         return selected;
  24946 
  24947     item_spacing = ctx->style.window.spacing;
  24948     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
  24949     max_height = count * item_height + count * (int)item_spacing.y;
  24950     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
  24951     size.y = NK_MIN(size.y, (float)max_height);
  24952     if (nk_combo_begin_label(ctx, items[selected], size)) {
  24953         nk_layout_row_dynamic(ctx, (float)item_height, 1);
  24954         for (i = 0; i < count; ++i) {
  24955             if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
  24956                 selected = i;
  24957         }
  24958         nk_combo_end(ctx);
  24959     }
  24960     return selected;
  24961 }
  24962 NK_API int
  24963 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
  24964     int separator, int selected, int count, int item_height, struct nk_vec2 size)
  24965 {
  24966     int i;
  24967     int max_height;
  24968     struct nk_vec2 item_spacing;
  24969     struct nk_vec2 window_padding;
  24970     const char *current_item;
  24971     const char *iter;
  24972     int length = 0;
  24973 
  24974     NK_ASSERT(ctx);
  24975     NK_ASSERT(items_separated_by_separator);
  24976     if (!ctx || !items_separated_by_separator)
  24977         return selected;
  24978 
  24979     /* calculate popup window */
  24980     item_spacing = ctx->style.window.spacing;
  24981     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
  24982     max_height = count * item_height + count * (int)item_spacing.y;
  24983     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
  24984     size.y = NK_MIN(size.y, (float)max_height);
  24985 
  24986     /* find selected item */
  24987     current_item = items_separated_by_separator;
  24988     for (i = 0; i < count; ++i) {
  24989         iter = current_item;
  24990         while (*iter && *iter != separator) iter++;
  24991         length = (int)(iter - current_item);
  24992         if (i == selected) break;
  24993         current_item = iter + 1;
  24994     }
  24995 
  24996     if (nk_combo_begin_text(ctx, current_item, length, size)) {
  24997         current_item = items_separated_by_separator;
  24998         nk_layout_row_dynamic(ctx, (float)item_height, 1);
  24999         for (i = 0; i < count; ++i) {
  25000             iter = current_item;
  25001             while (*iter && *iter != separator) iter++;
  25002             length = (int)(iter - current_item);
  25003             if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
  25004                 selected = i;
  25005             current_item = current_item + length + 1;
  25006         }
  25007         nk_combo_end(ctx);
  25008     }
  25009     return selected;
  25010 }
  25011 NK_API int
  25012 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
  25013     int selected, int count, int item_height, struct nk_vec2 size)
  25014 {
  25015     return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);
  25016 }
  25017 NK_API int
  25018 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
  25019     void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
  25020 {
  25021     int i;
  25022     int max_height;
  25023     struct nk_vec2 item_spacing;
  25024     struct nk_vec2 window_padding;
  25025     const char *item;
  25026 
  25027     NK_ASSERT(ctx);
  25028     NK_ASSERT(item_getter);
  25029     if (!ctx || !item_getter)
  25030         return selected;
  25031 
  25032     /* calculate popup window */
  25033     item_spacing = ctx->style.window.spacing;
  25034     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
  25035     max_height = count * item_height + count * (int)item_spacing.y;
  25036     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
  25037     size.y = NK_MIN(size.y, (float)max_height);
  25038 
  25039     item_getter(userdata, selected, &item);
  25040     if (nk_combo_begin_label(ctx, item, size)) {
  25041         nk_layout_row_dynamic(ctx, (float)item_height, 1);
  25042         for (i = 0; i < count; ++i) {
  25043             item_getter(userdata, i, &item);
  25044             if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
  25045                 selected = i;
  25046         }
  25047         nk_combo_end(ctx);
  25048     } return selected;
  25049 }
  25050 NK_API void
  25051 nk_combobox(struct nk_context *ctx, const char **items, int count,
  25052     int *selected, int item_height, struct nk_vec2 size)
  25053 {
  25054     *selected = nk_combo(ctx, items, count, *selected, item_height, size);
  25055 }
  25056 NK_API void
  25057 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
  25058     int *selected, int count, int item_height, struct nk_vec2 size)
  25059 {
  25060     *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);
  25061 }
  25062 NK_API void
  25063 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
  25064     int separator,int *selected, int count, int item_height, struct nk_vec2 size)
  25065 {
  25066     *selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
  25067                                     *selected, count, item_height, size);
  25068 }
  25069 NK_API void
  25070 nk_combobox_callback(struct nk_context *ctx,
  25071     void(*item_getter)(void* data, int id, const char **out_text),
  25072     void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
  25073 {
  25074     *selected = nk_combo_callback(ctx, item_getter, userdata,  *selected, count, item_height, size);
  25075 }
  25076 
  25077 
  25078 
  25079 
  25080 
  25081 /* ===============================================================
  25082  *
  25083  *                              TOOLTIP
  25084  *
  25085  * ===============================================================*/
  25086 NK_API int
  25087 nk_tooltip_begin(struct nk_context *ctx, float width)
  25088 {
  25089     int x,y,w,h;
  25090     struct nk_window *win;
  25091     const struct nk_input *in;
  25092     struct nk_rect bounds;
  25093     int ret;
  25094 
  25095     NK_ASSERT(ctx);
  25096     NK_ASSERT(ctx->current);
  25097     NK_ASSERT(ctx->current->layout);
  25098     if (!ctx || !ctx->current || !ctx->current->layout)
  25099         return 0;
  25100 
  25101     /* make sure that no nonblocking popup is currently active */
  25102     win = ctx->current;
  25103     in = &ctx->input;
  25104     if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
  25105         return 0;
  25106 
  25107     w = nk_iceilf(width);
  25108     h = nk_iceilf(nk_null_rect.h);
  25109     x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x;
  25110     y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y;
  25111 
  25112     bounds.x = (float)x;
  25113     bounds.y = (float)y;
  25114     bounds.w = (float)w;
  25115     bounds.h = (float)h;
  25116 
  25117     ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
  25118         "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
  25119     if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
  25120     win->popup.type = NK_PANEL_TOOLTIP;
  25121     ctx->current->layout->type = NK_PANEL_TOOLTIP;
  25122     return ret;
  25123 }
  25124 
  25125 NK_API void
  25126 nk_tooltip_end(struct nk_context *ctx)
  25127 {
  25128     NK_ASSERT(ctx);
  25129     NK_ASSERT(ctx->current);
  25130     if (!ctx || !ctx->current) return;
  25131     ctx->current->seq--;
  25132     nk_popup_close(ctx);
  25133     nk_popup_end(ctx);
  25134 }
  25135 NK_API void
  25136 nk_tooltip(struct nk_context *ctx, const char *text)
  25137 {
  25138     const struct nk_style *style;
  25139     struct nk_vec2 padding;
  25140 
  25141     int text_len;
  25142     float text_width;
  25143     float text_height;
  25144 
  25145     NK_ASSERT(ctx);
  25146     NK_ASSERT(ctx->current);
  25147     NK_ASSERT(ctx->current->layout);
  25148     NK_ASSERT(text);
  25149     if (!ctx || !ctx->current || !ctx->current->layout || !text)
  25150         return;
  25151 
  25152     /* fetch configuration data */
  25153     style = &ctx->style;
  25154     padding = style->window.padding;
  25155 
  25156     /* calculate size of the text and tooltip */
  25157     text_len = nk_strlen(text);
  25158     text_width = style->font->width(style->font->userdata,
  25159                     style->font->height, text, text_len);
  25160     text_width += (4 * padding.x);
  25161     text_height = (style->font->height + 2 * padding.y);
  25162 
  25163     /* execute tooltip and fill with text */
  25164     if (nk_tooltip_begin(ctx, (float)text_width)) {
  25165         nk_layout_row_dynamic(ctx, (float)text_height, 1);
  25166         nk_text(ctx, text, text_len, NK_TEXT_LEFT);
  25167         nk_tooltip_end(ctx);
  25168     }
  25169 }
  25170 #ifdef NK_INCLUDE_STANDARD_VARARGS
  25171 NK_API void
  25172 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...)
  25173 {
  25174     va_list args;
  25175     va_start(args, fmt);
  25176     nk_tooltipfv(ctx, fmt, args);
  25177     va_end(args);
  25178 }
  25179 NK_API void
  25180 nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
  25181 {
  25182     char buf[256];
  25183     nk_strfmt(buf, NK_LEN(buf), fmt, args);
  25184     nk_tooltip(ctx, buf);
  25185 }
  25186 #endif
  25187 
  25188 
  25189 
  25190 #endif /* NK_IMPLEMENTATION */
  25191 
  25192 /*
  25193 /// ## License
  25194 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
  25195 ///    ------------------------------------------------------------------------------
  25196 ///    This software is available under 2 licenses -- choose whichever you prefer.
  25197 ///    ------------------------------------------------------------------------------
  25198 ///    ALTERNATIVE A - MIT License
  25199 ///    Copyright (c) 2016-2018 Micha Mettke
  25200 ///    Permission is hereby granted, free of charge, to any person obtaining a copy of
  25201 ///    this software and associated documentation files (the "Software"), to deal in
  25202 ///    the Software without restriction, including without limitation the rights to
  25203 ///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  25204 ///    of the Software, and to permit persons to whom the Software is furnished to do
  25205 ///    so, subject to the following conditions:
  25206 ///    The above copyright notice and this permission notice shall be included in all
  25207 ///    copies or substantial portions of the Software.
  25208 ///    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25209 ///    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25210 ///    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25211 ///    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25212 ///    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  25213 ///    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  25214 ///    SOFTWARE.
  25215 ///    ------------------------------------------------------------------------------
  25216 ///    ALTERNATIVE B - Public Domain (www.unlicense.org)
  25217 ///    This is free and unencumbered software released into the public domain.
  25218 ///    Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
  25219 ///    software, either in source code form or as a compiled binary, for any purpose,
  25220 ///    commercial or non-commercial, and by any means.
  25221 ///    In jurisdictions that recognize copyright laws, the author or authors of this
  25222 ///    software dedicate any and all copyright interest in the software to the public
  25223 ///    domain. We make this dedication for the benefit of the public at large and to
  25224 ///    the detriment of our heirs and successors. We intend this dedication to be an
  25225 ///    overt act of relinquishment in perpetuity of all present and future rights to
  25226 ///    this software under copyright law.
  25227 ///    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25228 ///    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25229 ///    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25230 ///    AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  25231 ///    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  25232 ///    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25233 ///    ------------------------------------------------------------------------------
  25234 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25235 
  25236 /// ## Changelog
  25237 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
  25238 /// [date][x.yy.zz]-[description]
  25239 /// -[date]: date on which the change has been pushed
  25240 /// -[x.yy.zz]: Numerical version string representation. Each version number on the right
  25241 ///             resets back to zero if version on the left is incremented.
  25242 ///    - [x]: Major version with API and library breaking changes
  25243 ///    - [yy]: Minor version with non-breaking API and library changes
  25244 ///    - [zz]: Bug fix version with no direct changes to API
  25245 ///
  25246 /// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame
  25247 /// - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to
  25248 ///                         clear provided buffers. So make sure to either free
  25249 ///                         or clear each passed buffer after calling nk_convert.
  25250 /// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior
  25251 /// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process
  25252 /// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype
  25253 /// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug
  25254 /// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separed group identifier and title
  25255 /// - 2018/01/07 (3.00.1) - Started to change documentation style
  25256 /// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken
  25257 ///                        because of conversions between float and byte color representation.
  25258 ///                        Color pickers now use floating point values to represent
  25259 ///                        HSV values. To get back the old behavior I added some additional
  25260 ///                        color conversion functions to cast between nk_color and
  25261 ///                        nk_colorf.
  25262 /// - 2017/12/23 (2.00.7) - Fixed small warning
  25263 /// - 2017/12/23 (2.00.7) - Fixed nk_edit_buffer behavior if activated to allow input
  25264 /// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior
  25265 /// - 2017/12/04 (2.00.6) - Added formated string tooltip widget
  25266 /// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag NK_WINDOW_NO_INPUT
  25267 /// - 2017/11/15 (2.00.4) - Fixed font merging
  25268 /// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions
  25269 /// - 2017/09/14 (2.00.2) - Fixed nk_edit_buffer and nk_edit_focus behavior
  25270 /// - 2017/09/14 (2.00.1) - Fixed window closing behavior
  25271 /// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifing window position and size funtions now
  25272 ///                        require the name of the window and must happen outside the window
  25273 ///                        building process (between function call nk_begin and nk_end).
  25274 /// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last
  25275 /// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows
  25276 /// - 2017/08/27 (1.40.7) - Fixed window background flag
  25277 /// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked
  25278 ///                        query for widgets
  25279 /// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked
  25280 ///                        and filled rectangles
  25281 /// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in
  25282 ///                        process of being destroyed.
  25283 /// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in
  25284 ///                        window instead of directly in table.
  25285 /// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro
  25286 /// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero
  25287 /// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only
  25288 ///                        comes in effect if you pass in zero was row height argument
  25289 /// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change
  25290 ///                        how layouting works. From now there will be an internal minimum
  25291 ///                        row height derived from font height. If you need a row smaller than
  25292 ///                        that you can directly set it by `nk_layout_set_min_row_height` and
  25293 ///                        reset the value back by calling `nk_layout_reset_min_row_height.
  25294 /// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix
  25295 /// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a nk_layout_xxx function
  25296 /// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer
  25297 /// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped
  25298 /// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundries
  25299 /// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space
  25300 /// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size
  25301 /// - 2017/05/06 (1.38.0) - Added platform double-click support
  25302 /// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends
  25303 /// - 2017/04/20 (1.37.0) - Extended properties with selection and clipbard support
  25304 /// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing
  25305 /// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error
  25306 /// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags
  25307 /// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption
  25308 /// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows
  25309 /// - 2017/03/25 (1.35.1) - Fixed windows closing behavior
  25310 /// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377
  25311 /// - 2017/03/18 (1.34.3) - Fixed long window header titles
  25312 /// - 2017/03/04 (1.34.2) - Fixed text edit filtering
  25313 /// - 2017/03/04 (1.34.1) - Fixed group closable flag
  25314 /// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support
  25315 /// - 2017/01/24 (1.33.0) - Added programatic way of remove edit focus
  25316 /// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows
  25317 /// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows
  25318 /// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing
  25319 /// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner
  25320 /// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both
  25321 ///                        dynamic and static widgets.
  25322 /// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit
  25323 /// - 2016/12/31 (1.29.2)- Fixed closing window bug of minimized windows
  25324 /// - 2016/12/03 (1.29.1)- Fixed wrapped text with no seperator and C89 error
  25325 /// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters
  25326 /// - 2016/11/22 (1.28.6)- Fixed window minimized closing bug
  25327 /// - 2016/11/19 (1.28.5)- Fixed abstract combo box closing behavior
  25328 /// - 2016/11/19 (1.28.4)- Fixed tooltip flickering
  25329 /// - 2016/11/19 (1.28.3)- Fixed memory leak caused by popup repeated closing
  25330 /// - 2016/11/18 (1.28.2)- Fixed memory leak caused by popup panel allocation
  25331 /// - 2016/11/10 (1.28.1)- Fixed some warnings and C++ error
  25332 /// - 2016/11/10 (1.28.0)- Added additional `nk_button` versions which allows to directly
  25333 ///                        pass in a style struct to change buttons visual.
  25334 /// - 2016/11/10 (1.27.0)- Added additional 'nk_tree' versions to support external state
  25335 ///                        storage. Just like last the `nk_group` commit the main
  25336 ///                        advantage is that you optionally can minimize nuklears runtime
  25337 ///                        memory consumption or handle hash collisions.
  25338 /// - 2016/11/09 (1.26.0)- Added additional `nk_group` version to support external scrollbar
  25339 ///                        offset storage. Main advantage is that you can externalize
  25340 ///                        the memory management for the offset. It could also be helpful
  25341 ///                        if you have a hash collision in `nk_group_begin` but really
  25342 ///                        want the name. In addition I added `nk_list_view` which allows
  25343 ///                        to draw big lists inside a group without actually having to
  25344 ///                        commit the whole list to nuklear (issue #269).
  25345 /// - 2016/10/30 (1.25.1)- Fixed clipping rectangle bug inside `nk_draw_list`
  25346 /// - 2016/10/29 (1.25.0)- Pulled `nk_panel` memory management into nuklear and out of
  25347 ///                        the hands of the user. From now on users don't have to care
  25348 ///                        about panels unless they care about some information. If you
  25349 ///                        still need the panel just call `nk_window_get_panel`.
  25350 /// - 2016/10/21 (1.24.0)- Changed widget border drawing to stroked rectangle from filled
  25351 ///                        rectangle for less overdraw and widget background transparency.
  25352 /// - 2016/10/18 (1.23.0)- Added `nk_edit_focus` for manually edit widget focus control
  25353 /// - 2016/09/29 (1.22.7)- Fixed deduction of basic type in non `<stdint.h>` compilation
  25354 /// - 2016/09/29 (1.22.6)- Fixed edit widget UTF-8 text cursor drawing bug
  25355 /// - 2016/09/28 (1.22.5)- Fixed edit widget UTF-8 text appending/inserting/removing
  25356 /// - 2016/09/28 (1.22.4)- Fixed drawing bug inside edit widgets which offset all text
  25357 ///                        text in every edit widget if one of them is scrolled.
  25358 /// - 2016/09/28 (1.22.3)- Fixed small bug in edit widgets if not active. The wrong
  25359 ///                        text length is passed. It should have been in bytes but
  25360 ///                        was passed as glyphes.
  25361 /// - 2016/09/20 (1.22.2)- Fixed color button size calculation
  25362 /// - 2016/09/20 (1.22.1)- Fixed some `nk_vsnprintf` behavior bugs and removed
  25363 ///                        `<stdio.h>` again from `NK_INCLUDE_STANDARD_VARARGS`.
  25364 /// - 2016/09/18 (1.22.0)- C89 does not support vsnprintf only C99 and newer as well
  25365 ///                        as C++11 and newer. In addition to use vsnprintf you have
  25366 ///                        to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS`
  25367 ///                        is not enough. That behavior is now fixed. By default if
  25368 ///                        both varargs as well as stdio is selected I try to use
  25369 ///                        vsnprintf if not possible I will revert to vsprintf. If
  25370 ///                        varargs but not stdio was defined I will use my own function.
  25371 /// - 2016/09/15 (1.21.2)- Fixed panel `close` behavior for deeper panel levels
  25372 /// - 2016/09/15 (1.21.1)- Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`
  25373 /// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo,
  25374 ///                        and contextual which prevented closing in y-direction if
  25375 ///                        popup did not reach max height.
  25376 ///                        In addition the height parameter was changed into vec2
  25377 ///                        for width and height to have more control over the popup size.
  25378 /// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection
  25379 /// - 2016/09/13 (1.20.2)- Fixed slider behavior hopefully for the last time. This time
  25380 ///                        all calculation are correct so no more hackery.
  25381 /// - 2016/09/13 (1.20.1)- Internal change to divide window/panel flags into panel flags and types.
  25382 ///                        Suprisinly spend years in C and still happened to confuse types
  25383 ///                        with flags. Probably something to take note.
  25384 /// - 2016/09/08 (1.20.0)- Added additional helper function to make it easier to just
  25385 ///                        take the produced buffers from `nk_convert` and unplug the
  25386 ///                        iteration process from `nk_context`. So now you can
  25387 ///                        just use the vertex,element and command buffer + two pointer
  25388 ///                        inside the command buffer retrieved by calls `nk__draw_begin`
  25389 ///                        and `nk__draw_end` and macro `nk_draw_foreach_bounded`.
  25390 /// - 2016/09/08 (1.19.0)- Added additional asserts to make sure every `nk_xxx_begin` call
  25391 ///                        for windows, popups, combobox, menu and contextual is guarded by
  25392 ///                        `if` condition and does not produce false drawing output.
  25393 /// - 2016/09/08 (1.18.0)- Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT`
  25394 ///                        to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and
  25395 ///                        `NK_SYMBOL_RECT_OUTLINE`.
  25396 /// - 2016/09/08 (1.17.0)- Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE`
  25397 ///                        to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and
  25398 ///                        `NK_SYMBOL_CIRCLE_OUTLINE`.
  25399 /// - 2016/09/08 (1.16.0)- Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES`
  25400 ///                        is not defined by supporting the biggest compiler GCC, clang and MSVC.
  25401 /// - 2016/09/07 (1.15.3)- Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error
  25402 /// - 2016/09/04 (1.15.2)- Fixed wrong combobox height calculation
  25403 /// - 2016/09/03 (1.15.1)- Fixed gaps inside combo boxes in OpenGL
  25404 /// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and
  25405 ///                        instead made it user provided. The range of types to convert
  25406 ///                        to is quite limited at the moment, but I would be more than
  25407 ///                        happy to accept PRs to add additional.
  25408 /// - 2016/08/30 (1.14.2) - Removed unused variables
  25409 /// - 2016/08/30 (1.14.1) - Fixed C++ build errors
  25410 /// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly
  25411 /// - 2016/08/30 (1.13.4) - Tweaked some default styling variables
  25412 /// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would
  25413 ///                        refrain from using slider with a big number of steps.
  25414 /// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the
  25415 ///                        window was in Read Only Mode.
  25416 /// - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just
  25417 ///                        a hack for combo box and menu.
  25418 /// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since
  25419 ///                        it is bugged and causes issues in window selection.
  25420 /// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now
  25421 ///                        determined by the scrollbar size
  25422 /// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11
  25423 /// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection
  25424 /// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code
  25425 ///                        handling panel padding and panel border.
  25426 /// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`
  25427 /// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups
  25428 /// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes
  25429 /// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for
  25430 ///                        hash collisions. Currently limited to NK_WINDOW_MAX_NAME
  25431 ///                        which in term can be redefined if not big enough.
  25432 /// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code
  25433 /// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released'
  25434 ///                        to account for key press and release happening in one frame.
  25435 /// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate
  25436 /// - 2016/08/17 (1.09.6)- Removed invalid check for value zero in nk_propertyx
  25437 /// - 2016/08/16 (1.09.5)- Fixed ROM mode for deeper levels of popup windows parents.
  25438 /// - 2016/08/15 (1.09.4)- Editbox are now still active if enter was pressed with flag
  25439 ///                        `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep
  25440 ///                        typing after commiting.
  25441 /// - 2016/08/15 (1.09.4)- Removed redundant code
  25442 /// - 2016/08/15 (1.09.4)- Fixed negative numbers in `nk_strtoi` and remove unused variable
  25443 /// - 2016/08/15 (1.09.3)- Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background
  25444 ///                        window only as selected by hovering and not by clicking.
  25445 /// - 2016/08/14 (1.09.2)- Fixed a bug in font atlas which caused wrong loading
  25446 ///                        of glyphes for font with multiple ranges.
  25447 /// - 2016/08/12 (1.09.1)- Added additional function to check if window is currently
  25448 ///                        hidden and therefore not visible.
  25449 /// - 2016/08/12 (1.09.1)- nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED`
  25450 ///                        instead of the old flag `NK_WINDOW_HIDDEN`
  25451 /// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed
  25452 ///                        the underlying implementation to not cast to float and instead
  25453 ///                        work directly on the given values.
  25454 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
  25455 ///                        floating pointer number to string conversion for additional
  25456 ///                        precision.
  25457 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
  25458 ///                        string to floating point number conversion for additional
  25459 ///                        precision.
  25460 /// - 2016/08/08 (1.07.2)- Fixed compiling error without define NK_INCLUDE_FIXED_TYPE
  25461 /// - 2016/08/08 (1.07.1)- Fixed possible floating point error inside `nk_widget` leading
  25462 ///                        to wrong wiget width calculation which results in widgets falsly
  25463 ///                        becomming tagged as not inside window and cannot be accessed.
  25464 /// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and
  25465 ///                        closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown
  25466 ///                        by using `nk_window_show` and closed by either clicking the close
  25467 ///                        icon in a window or by calling `nk_window_close`. Only closed
  25468 ///                        windows get removed at the end of the frame while hidden windows
  25469 ///                        remain.
  25470 /// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to
  25471 ///                        `nk_edit_string` which takes, edits and outputs a '\0' terminated string.
  25472 /// - 2016/08/08 (1.05.4)- Fixed scrollbar auto hiding behavior
  25473 /// - 2016/08/08 (1.05.3)- Fixed wrong panel padding selection in `nk_layout_widget_space`
  25474 /// - 2016/08/07 (1.05.2)- Fixed old bug in dynamic immediate mode layout API, calculating
  25475 ///                        wrong item spacing and panel width.
  25476 ///- 2016/08/07 (1.05.1)- Hopefully finally fixed combobox popup drawing bug
  25477 ///- 2016/08/07 (1.05.0) - Split varargs away from NK_INCLUDE_STANDARD_IO into own
  25478 ///                        define NK_INCLUDE_STANDARD_VARARGS to allow more fine
  25479 ///                        grained controlled over library includes.
  25480 /// - 2016/08/06 (1.04.5)- Changed memset calls to NK_MEMSET
  25481 /// - 2016/08/04 (1.04.4)- Fixed fast window scaling behavior
  25482 /// - 2016/08/04 (1.04.3)- Fixed window scaling, movement bug which appears if you
  25483 ///                        move/scale a window and another window is behind it.
  25484 ///                        If you are fast enough then the window behind gets activated
  25485 ///                        and the operation is blocked. I now require activating
  25486 ///                        by hovering only if mouse is not pressed.
  25487 /// - 2016/08/04 (1.04.2)- Fixed changing fonts
  25488 /// - 2016/08/03 (1.04.1)- Fixed `NK_WINDOW_BACKGROUND` behavior
  25489 /// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`
  25490 /// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for
  25491 ///                        sub windows (combo, menu, ...)
  25492 /// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor
  25493 /// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window
  25494 ///                        to be always in the background of the screen
  25495 /// - 2016/08/03 (1.03.2)- Removed invalid assert macro for NK_RGB color picker
  25496 /// - 2016/08/01 (1.03.1)- Added helper macros into header include guard
  25497 /// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to
  25498 ///                        simplify memory management by removing the need to
  25499 ///                        allocate the pool.
  25500 /// - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled
  25501 ///                        will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT
  25502 ///                        seconds without window interaction. To make it work
  25503 ///                        you have to also set a delta time inside the `nk_context`.
  25504 /// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs
  25505 /// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`
  25506 /// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument
  25507 /// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified
  25508 ///                        font atlas memory management by converting pointer
  25509 ///                        arrays for fonts and font configurations to lists.
  25510 /// - 2016/07/15 (1.00.0) - Changed button API to use context dependend button
  25511 ///                        behavior instead of passing it for every function call.
  25512 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25513 
  25514 /// ## Gallery
  25515 /// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png)
  25516 /// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png)
  25517 /// ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png)
  25518 /// ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png)
  25519 /// ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png)
  25520 /// ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png)
  25521 /// ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif)
  25522 /// ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png)
  25523 /// ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png)
  25524 ///
  25525 /// ## Credits
  25526 /// Developed by Micha Mettke and every direct or indirect github contributor. <br /><br />
  25527 ///
  25528 /// 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 />
  25529 /// Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from r-lyeh@github.com for documentation generation <br /><br />
  25530 /// Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br />
  25531 ///
  25532 /// Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and
  25533 /// giving me the inspiration for this library, Casey Muratori for handmade hero
  25534 /// and his original immediate mode graphical user interface idea and Sean
  25535 /// Barret for his amazing single header libraries which restored my faith
  25536 /// in libraries and brought me to create some of my own. Finally Apoorva Joshi
  25537 /// for his single header file packer.
  25538 */
  25539