1 /*/// # Nuklear
2 /// ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif)
3 ///
4 /// ## Contents
5 /// 1. About section
6 /// 2. Highlights section
7 /// 3. Features section
8 /// 4. Usage section
9 ///     1. Flags section
10 ///     2. Constants section
11 ///     3. Dependencies section
12 /// 5. Example section
13 /// 6. API section
14 ///     1. Context section
15 ///     2. Input section
16 ///     3. Drawing section
17 ///     4. Window section
18 ///     5. Layouting section
19 ///     6. Groups section
20 ///     7. Tree section
21 ///     8. Properties section
22 /// 7. License section
23 /// 8. Changelog section
24 /// 9. Gallery section
25 /// 10. Credits section
26 ///
27 /// ## About
28 /// This is a minimal state immediate mode graphical user interface toolkit
29 /// written in ANSI C and licensed under public domain. It was designed as a simple
30 /// embeddable user interface for application and does not have any dependencies,
31 /// a default renderbackend or OS window and input handling but instead provides a very modular
32 /// library approach by using simple input state for input and draw
33 /// commands describing primitive shapes as output. So instead of providing a
34 /// layered library that tries to abstract over a number of platform and
35 /// render backends it only focuses on the actual UI.
36 ///
37 /// ## Highlights
38 /// - Graphical user interface toolkit
39 /// - Single header library
40 /// - Written in C89 (a.k.a. ANSI C or ISO C90)
41 /// - Small codebase (~18kLOC)
42 /// - Focus on portability, efficiency and simplicity
43 /// - No dependencies (not even the standard library if not wanted)
44 /// - Fully skinnable and customizable
45 /// - Low memory footprint with total memory control if needed or wanted
46 /// - UTF-8 support
47 /// - No global or hidden state
48 /// - Customizable library modules (you can compile and use only what you need)
49 /// - Optional font baker and vertex buffer output
50 ///
51 /// ## Features
52 /// - Absolutely no platform dependent code
53 /// - Memory management control ranging from/to
54 ///     - Ease of use by allocating everything from standard library
55 ///     - Control every byte of memory inside the library
56 /// - Font handling control ranging from/to
57 ///     - Use your own font implementation for everything
58 ///     - Use this libraries internal font baking and handling API
59 /// - Drawing output control ranging from/to
60 ///     - Simple shapes for more high level APIs which already have drawing capabilities
61 ///     - Hardware accessible anti-aliased vertex buffer output
62 /// - Customizable colors and properties ranging from/to
63 ///     - Simple changes to color by filling a simple color table
64 ///     - Complete control with ability to use skinning to decorate widgets
65 /// - Bendable UI library with widget ranging from/to
66 ///     - Basic widgets like buttons, checkboxes, slider, ...
67 ///     - Advanced widget like abstract comboboxes, contextual menus,...
68 /// - Compile time configuration to only compile what you need
69 ///     - Subset which can be used if you do not want to link or use the standard library
70 /// - Can be easily modified to only update on user input instead of frame updates
71 ///
72 /// ## Usage
73 /// This library is self contained in one single header file and can be used either
74 /// in header only mode or in implementation mode. The header only mode is used
75 /// by default when included and allows including this header in other headers
76 /// and does not contain the actual implementation. <br /><br />
77 ///
78 /// The implementation mode requires to define  the preprocessor macro
79 /// NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.:
80 ///
81 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C
82 ///     #define NK_IMPLEMENTATION
83 ///     #include "nuklear.h"
84 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
85 ///
86 /// Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
87 /// below in header and implementation mode if you want to use additional functionality
88 /// or need more control over the library.
89 ///
90 /// !!! WARNING
91 ///     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.
92 ///
93 /// ### Flags
94 /// Flag                            | Description
95 /// --------------------------------|------------------------------------------
96 /// NK_PRIVATE                      | If defined declares all functions as static, so they can only be accessed inside the file that contains the implementation
97 /// 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.
98 /// 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.
99 /// NK_INCLUDE_STANDARD_IO          | If defined it will include header `<stdio.h>` and provide additional functions depending on file loading.
100 /// NK_INCLUDE_STANDARD_VARARGS     | If defined it will include header <stdio.h> and provide additional functions depending on file loading.
101 /// 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,...
102 /// 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.
103 /// 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
104 /// 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.
105 /// 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.
106 /// 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.
107 ///
108 /// !!! WARNING
109 ///     The following flags will pull in the standard C library:
110 ///     - NK_INCLUDE_DEFAULT_ALLOCATOR
111 ///     - NK_INCLUDE_STANDARD_IO
112 ///     - NK_INCLUDE_STANDARD_VARARGS
113 ///
114 /// !!! WARNING
115 ///     The following flags if defined need to be defined for both header and implementation:
116 ///     - NK_INCLUDE_FIXED_TYPES
117 ///     - NK_INCLUDE_DEFAULT_ALLOCATOR
118 ///     - NK_INCLUDE_STANDARD_VARARGS
119 ///     - NK_INCLUDE_VERTEX_BUFFER_OUTPUT
120 ///     - NK_INCLUDE_FONT_BAKING
121 ///     - NK_INCLUDE_DEFAULT_FONT
122 ///     - NK_INCLUDE_STANDARD_VARARGS
123 ///     - NK_INCLUDE_COMMAND_USERDATA
124 ///
125 /// ### Constants
126 /// Define                          | Description
127 /// --------------------------------|---------------------------------------
128 /// 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.
129 /// NK_MAX_NUMBER_BUFFER            | Maximum buffer size for the conversion buffer between float and string Under normal circumstances this should be more than sufficient.
130 /// 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.
131 ///
132 /// !!! WARNING
133 ///     The following constants if defined need to be defined for both header and implementation:
134 ///     - NK_MAX_NUMBER_BUFFER
135 ///     - NK_BUFFER_DEFAULT_INITIAL_SIZE
136 ///     - NK_INPUT_MAX
137 ///
138 /// ### Dependencies
139 /// Function    | Description
140 /// ------------|---------------------------------------------------------------
141 /// NK_ASSERT   | If you don't define this, nuklear will use <assert.h> with assert().
142 /// NK_MEMSET   | You can define this to 'memset' or your own memset implementation replacement. If not nuklear will use its own version.
143 /// NK_MEMCPY   | You can define this to 'memcpy' or your own memcpy implementation replacement. If not nuklear will use its own version.
144 /// 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.
145 /// NK_SIN      | You can define this to 'sinf' or your own sine implementation replacement. If not nuklear will use its own approximation implementation.
146 /// NK_COS      | You can define this to 'cosf' or your own cosine implementation replacement. If not nuklear will use its own approximation implementation.
147 /// 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!).
148 /// 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!).
149 /// 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.
150 ///
151 /// !!! WARNING
152 ///     The following dependencies will pull in the standard C library if not redefined:
153 ///     - NK_ASSERT
154 ///
155 /// !!! WARNING
156 ///     The following dependencies if defined need to be defined for both header and implementation:
157 ///     - NK_ASSERT
158 ///
159 /// !!! WARNING
160 ///     The following dependencies if defined need to be defined only for the implementation part:
161 ///     - NK_MEMSET
162 ///     - NK_MEMCPY
163 ///     - NK_SQRT
164 ///     - NK_SIN
165 ///     - NK_COS
166 ///     - NK_STRTOD
167 ///     - NK_DTOA
168 ///     - NK_VSNPRINTF
169 ///
170 /// ## Example
171 ///
172 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
173 /// // init gui state
174 /// enum {EASY, HARD};
175 /// static int op = EASY;
176 /// static float value = 0.6f;
177 /// static int i =  20;
178 /// struct nk_context ctx;
179 ///
180 /// nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);
181 /// if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220),
182 ///     NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
183 ///     // fixed widget pixel width
184 ///     nk_layout_row_static(&ctx, 30, 80, 1);
185 ///     if (nk_button_label(&ctx, "button")) {
186 ///         // event handling
187 ///     }
188 ///
189 ///     // fixed widget window ratio width
190 ///     nk_layout_row_dynamic(&ctx, 30, 2);
191 ///     if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY;
192 ///     if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD;
193 ///
194 ///     // custom widget pixel width
195 ///     nk_layout_row_begin(&ctx, NK_STATIC, 30, 2);
196 ///     {
197 ///         nk_layout_row_push(&ctx, 50);
198 ///         nk_label(&ctx, "Volume:", NK_TEXT_LEFT);
199 ///         nk_layout_row_push(&ctx, 110);
200 ///         nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
201 ///     }
202 ///     nk_layout_row_end(&ctx);
203 /// }
204 /// nk_end(&ctx);
205 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
206 ///
207 /// ![](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png)
208 ///
209 /// ## API
210 ///
211 */
212 #ifndef NK_NUKLEAR_H_
213 #define NK_NUKLEAR_H_
214 
215 #ifdef __cplusplus
216 extern "C" {
217 #endif
218 /*
219  * ==============================================================
220  *
221  *                          CONSTANTS
222  *
223  * ===============================================================
224  */
225 #define NK_UNDEFINED (-1.0f)
226 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
227 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
228 #ifndef NK_INPUT_MAX
229   #define NK_INPUT_MAX 16
230 #endif
231 #ifndef NK_MAX_NUMBER_BUFFER
232   #define NK_MAX_NUMBER_BUFFER 64
233 #endif
234 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
235   #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
236 #endif
237 /*
238  * ==============================================================
239  *
240  *                          HELPER
241  *
242  * ===============================================================
243  */
244 #ifndef NK_API
245   #ifdef NK_PRIVATE
246     #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
247       #define NK_API static inline
248     #elif defined(__cplusplus)
249       #define NK_API static inline
250     #else
251       #define NK_API static
252     #endif
253   #else
254     #define NK_API extern
255   #endif
256 #endif
257 
258 #define NK_INTERN static
259 #define NK_STORAGE static
260 #define NK_GLOBAL static
261 
262 #define NK_FLAG(x) (1 << (x))
263 #define NK_STRINGIFY(x) #x
264 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
265 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
266 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
267 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
268 
269 #ifdef _MSC_VER
270   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
271 #else
272   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
273 #endif
274 
275 #ifndef NK_STATIC_ASSERT
276   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
277 #endif
278 
279 #ifndef NK_FILE_LINE
280 #ifdef _MSC_VER
281   #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
282 #else
283   #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
284 #endif
285 #endif
286 
287 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
288 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
289 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
290 
291 #ifdef NK_INCLUDE_STANDARD_VARARGS
292   #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
293     #include <sal.h>
294     #define NK_PRINTF_FORMAT_STRING _Printf_format_string_
295   #else
296     #define NK_PRINTF_FORMAT_STRING
297   #endif
298   #if defined(__GNUC__)
299     #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1)))
300   #else
301     #define NK_PRINTF_VARARG_FUNC(fmtargnumber)
302   #endif
303 #endif
304 
305 /*
306  * ===============================================================
307  *
308  *                          BASIC
309  *
310  * ===============================================================
311  */
312 #ifdef NK_INCLUDE_FIXED_TYPES
313  #include <stdint.h>
314  #define NK_INT8 int8_t
315  #define NK_UINT8 uint8_t
316  #define NK_INT16 int16_t
317  #define NK_UINT16 uint16_t
318  #define NK_INT32 int32_t
319  #define NK_UINT32 uint32_t
320  #define NK_SIZE_TYPE uintptr_t
321  #define NK_POINTER_TYPE uintptr_t
322 #else
323   #ifndef NK_INT8
324     #define NK_INT8 char
325   #endif
326   #ifndef NK_UINT8
327     #define NK_UINT8 unsigned char
328   #endif
329   #ifndef NK_INT16
330     #define NK_INT16 signed short
331   #endif
332   #ifndef NK_UINT16
333     #define NK_UINT16 unsigned short
334   #endif
335   #ifndef NK_INT32
336     #if defined(_MSC_VER)
337       #define NK_INT32 __int32
338     #else
339       #define NK_INT32 signed int
340     #endif
341   #endif
342   #ifndef NK_UINT32
343     #if defined(_MSC_VER)
344       #define NK_UINT32 unsigned __int32
345     #else
346       #define NK_UINT32 unsigned int
347     #endif
348   #endif
349   #ifndef NK_SIZE_TYPE
350     #if defined(_WIN64) && defined(_MSC_VER)
351       #define NK_SIZE_TYPE unsigned __int64
352     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
353       #define NK_SIZE_TYPE unsigned __int32
354     #elif defined(__GNUC__) || defined(__clang__)
355       #if defined(__x86_64__) || defined(__ppc64__)
356         #define NK_SIZE_TYPE unsigned long
357       #else
358         #define NK_SIZE_TYPE unsigned int
359       #endif
360     #else
361       #define NK_SIZE_TYPE unsigned long
362     #endif
363   #endif
364   #ifndef NK_POINTER_TYPE
365     #if defined(_WIN64) && defined(_MSC_VER)
366       #define NK_POINTER_TYPE unsigned __int64
367     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
368       #define NK_POINTER_TYPE unsigned __int32
369     #elif defined(__GNUC__) || defined(__clang__)
370       #if defined(__x86_64__) || defined(__ppc64__)
371         #define NK_POINTER_TYPE unsigned long
372       #else
373         #define NK_POINTER_TYPE unsigned int
374       #endif
375     #else
376       #define NK_POINTER_TYPE unsigned long
377     #endif
378   #endif
379 #endif
380 
381 typedef NK_INT8 nk_char;
382 typedef NK_UINT8 nk_uchar;
383 typedef NK_UINT8 nk_byte;
384 typedef NK_INT16 nk_short;
385 typedef NK_UINT16 nk_ushort;
386 typedef NK_INT32 nk_int;
387 typedef NK_UINT32 nk_uint;
388 typedef NK_SIZE_TYPE nk_size;
389 typedef NK_POINTER_TYPE nk_ptr;
390 
391 typedef nk_uint nk_hash;
392 typedef nk_uint nk_flags;
393 typedef nk_uint nk_rune;
394 
395 /* Make sure correct type size:
396  * This will fire with a negative subscript error if the type sizes
397  * are set incorrectly by the compiler, and compile out if not */
398 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
399 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
400 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
401 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
402 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
403 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
404 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
405 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
406 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
407 
408 /* ============================================================================
409  *
410  *                                  API
411  *
412  * =========================================================================== */
413 struct nk_buffer;
414 struct nk_allocator;
415 struct nk_command_buffer;
416 struct nk_draw_command;
417 struct nk_convert_config;
418 struct nk_style_item;
419 struct nk_text_edit;
420 struct nk_draw_list;
421 struct nk_user_font;
422 struct nk_panel;
423 struct nk_context;
424 struct nk_draw_vertex_layout_element;
425 struct nk_style_button;
426 struct nk_style_toggle;
427 struct nk_style_selectable;
428 struct nk_style_slide;
429 struct nk_style_progress;
430 struct nk_style_scrollbar;
431 struct nk_style_edit;
432 struct nk_style_property;
433 struct nk_style_chart;
434 struct nk_style_combo;
435 struct nk_style_tab;
436 struct nk_style_window_header;
437 struct nk_style_window;
438 
439 enum {nk_false, nk_true};
440 struct nk_color {nk_byte r,g,b,a;};
441 struct nk_colorf {float r,g,b,a;};
442 struct nk_vec2 {float x,y;};
443 struct nk_vec2i {short x, y;};
444 struct nk_rect {float x,y,w,h;};
445 struct nk_recti {short x,y,w,h;};
446 typedef char nk_glyph[NK_UTF_SIZE];
447 typedef union {void *ptr; int id;} nk_handle;
448 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
449 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
450 struct nk_scroll {nk_uint x, y;};
451 
452 enum nk_heading         {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
453 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
454 enum nk_modify          {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
455 enum nk_orientation     {NK_VERTICAL, NK_HORIZONTAL};
456 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true};
457 enum nk_show_states     {NK_HIDDEN = nk_false, NK_SHOWN = nk_true};
458 enum nk_chart_type      {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX};
459 enum nk_chart_event     {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02};
460 enum nk_color_format    {NK_RGB, NK_RGBA};
461 enum nk_popup_type      {NK_POPUP_STATIC, NK_POPUP_DYNAMIC};
462 enum nk_layout_format   {NK_DYNAMIC, NK_STATIC};
463 enum nk_tree_type       {NK_TREE_NODE, NK_TREE_TAB};
464 
465 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
466 typedef void (*nk_plugin_free)(nk_handle, void *old);
467 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
468 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
469 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
470 
471 struct nk_allocator {
472     nk_handle userdata;
473     nk_plugin_alloc alloc;
474     nk_plugin_free free;
475 };
476 enum nk_symbol_type {
477     NK_SYMBOL_NONE,
478     NK_SYMBOL_X,
479     NK_SYMBOL_UNDERSCORE,
480     NK_SYMBOL_CIRCLE_SOLID,
481     NK_SYMBOL_CIRCLE_OUTLINE,
482     NK_SYMBOL_RECT_SOLID,
483     NK_SYMBOL_RECT_OUTLINE,
484     NK_SYMBOL_TRIANGLE_UP,
485     NK_SYMBOL_TRIANGLE_DOWN,
486     NK_SYMBOL_TRIANGLE_LEFT,
487     NK_SYMBOL_TRIANGLE_RIGHT,
488     NK_SYMBOL_PLUS,
489     NK_SYMBOL_MINUS,
490     NK_SYMBOL_MAX
491 };
492 /* =============================================================================
493  *
494  *                                  CONTEXT
495  *
496  * =============================================================================*/
497 /*/// ### Context
498 /// Contexts are the main entry point and the majestro of nuklear and contain all required state.
499 /// They are used for window, memory, input, style, stack, commands and time management and need
500 /// to be passed into all nuklear GUI specific functions.
501 ///
502 /// #### Usage
503 /// To use a context it first has to be initialized which can be achieved by calling
504 /// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
505 /// Each takes in a font handle and a specific way of handling memory. Memory control
506 /// hereby ranges from standard library to just specifying a fixed sized block of memory
507 /// which nuklear has to manage itself from.
508 ///
509 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
510 /// struct nk_context ctx;
511 /// nk_init_xxx(&ctx, ...);
512 /// while (1) {
513 ///     // [...]
514 ///     nk_clear(&ctx);
515 /// }
516 /// nk_free(&ctx);
517 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
518 ///
519 /// #### Reference
520 /// Function            | Description
521 /// --------------------|-------------------------------------------------------
522 /// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free)
523 /// __nk_init_fixed__   | Initializes context from single fixed size memory block
524 /// __nk_init__         | Initializes context with memory allocator callbacks for alloc and free
525 /// __nk_init_custom__  | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
526 /// __nk_clear__        | Called at the end of the frame to reset and prepare the context for the next frame
527 /// __nk_free__         | Shutdown and free all memory allocated inside the context
528 /// __nk_set_user_data__| Utility function to pass user data to draw command
529  */
530 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
531 /*/// #### nk_init_default
532 /// Initializes a `nk_context` struct with a default standard library allocator.
533 /// Should be used if you don't want to be bothered with memory management in nuklear.
534 ///
535 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
536 /// int nk_init_default(struct nk_context *ctx, const struct nk_user_font *font);
537 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
538 ///
539 /// Parameter   | Description
540 /// ------------|---------------------------------------------------------------
541 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
542 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
543 ///
544 /// Returns either `false(0)` on failure or `true(1)` on success.
545 ///
546 */
547 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
548 #endif
549 /*/// #### nk_init_fixed
550 /// Initializes a `nk_context` struct from single fixed size memory block
551 /// Should be used if you want complete control over nuklear's memory management.
552 /// Especially recommended for system with little memory or systems with virtual memory.
553 /// For the later case you can just allocate for example 16MB of virtual memory
554 /// and only the required amount of memory will actually be committed.
555 ///
556 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
557 /// int nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font);
558 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
559 ///
560 /// !!! Warning
561 ///     make sure the passed memory block is aligned correctly for `nk_draw_commands`.
562 ///
563 /// Parameter   | Description
564 /// ------------|--------------------------------------------------------------
565 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
566 /// __memory__  | Must point to a previously allocated memory block
567 /// __size__    | Must contain the total size of __memory__
568 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
569 ///
570 /// Returns either `false(0)` on failure or `true(1)` on success.
571 */
572 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
573 /*/// #### nk_init
574 /// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
575 /// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
576 /// interface to nuklear. Can be useful for cases like monitoring memory consumption.
577 ///
578 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
579 /// int nk_init(struct nk_context *ctx, struct nk_allocator *alloc, const struct nk_user_font *font);
580 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
581 ///
582 /// Parameter   | Description
583 /// ------------|---------------------------------------------------------------
584 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
585 /// __alloc__   | Must point to a previously allocated memory allocator
586 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
587 ///
588 /// Returns either `false(0)` on failure or `true(1)` on success.
589 */
590 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
591 /*/// #### nk_init_custom
592 /// Initializes a `nk_context` struct from two different either fixed or growing
593 /// buffers. The first buffer is for allocating draw commands while the second buffer is
594 /// used for allocating windows, panels and state tables.
595 ///
596 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
597 /// int nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font);
598 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
599 ///
600 /// Parameter   | Description
601 /// ------------|---------------------------------------------------------------
602 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
603 /// __cmds__    | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
604 /// __pool__    | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
605 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
606 ///
607 /// Returns either `false(0)` on failure or `true(1)` on success.
608 */
609 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
610 /*/// #### nk_clear
611 /// Resets the context state at the end of the frame. This includes mostly
612 /// garbage collector tasks like removing windows or table not called and therefore
613 /// used anymore.
614 ///
615 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
616 /// void nk_clear(struct nk_context *ctx);
617 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
618 ///
619 /// Parameter   | Description
620 /// ------------|-----------------------------------------------------------
621 /// __ctx__     | Must point to a previously initialized `nk_context` struct
622 */
623 NK_API void nk_clear(struct nk_context*);
624 /*/// #### nk_free
625 /// Frees all memory allocated by nuklear. Not needed if context was
626 /// initialized with `nk_init_fixed`.
627 ///
628 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
629 /// void nk_free(struct nk_context *ctx);
630 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
631 ///
632 /// Parameter   | Description
633 /// ------------|-----------------------------------------------------------
634 /// __ctx__     | Must point to a previously initialized `nk_context` struct
635 */
636 NK_API void nk_free(struct nk_context*);
637 #ifdef NK_INCLUDE_COMMAND_USERDATA
638 /*/// #### nk_set_user_data
639 /// Sets the currently passed userdata passed down into each draw command.
640 ///
641 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
642 /// void nk_set_user_data(struct nk_context *ctx, nk_handle data);
643 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
644 ///
645 /// Parameter   | Description
646 /// ------------|--------------------------------------------------------------
647 /// __ctx__     | Must point to a previously initialized `nk_context` struct
648 /// __data__    | Handle with either pointer or index to be passed into every draw commands
649 */
650 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
651 #endif
652 /* =============================================================================
653  *
654  *                                  INPUT
655  *
656  * =============================================================================*/
657 /*/// ### Input
658 /// The input API is responsible for holding the current input state composed of
659 /// mouse, key and text input states.
660 /// It is worth noting that no direct os or window handling is done in nuklear.
661 /// Instead all input state has to be provided by platform specific code. This in one hand
662 /// expects more work from the user and complicates usage but on the other hand
663 /// provides simple abstraction over a big number of platforms, libraries and other
664 /// already provided functionality.
665 ///
666 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
667 /// nk_input_begin(&ctx);
668 /// while (GetEvent(&evt)) {
669 ///     if (evt.type == MOUSE_MOVE)
670 ///         nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
671 ///     else if (evt.type == [...]) {
672 ///         // [...]
673 ///     }
674 /// } nk_input_end(&ctx);
675 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
676 ///
677 /// #### Usage
678 /// Input state needs to be provided to nuklear by first calling `nk_input_begin`
679 /// which resets internal state like delta mouse position and button transistions.
680 /// After `nk_input_begin` all current input state needs to be provided. This includes
681 /// mouse motion, button and key pressed and released, text input and scrolling.
682 /// Both event- or state-based input handling are supported by this API
683 /// and should work without problems. Finally after all input state has been
684 /// mirrored `nk_input_end` needs to be called to finish input process.
685 ///
686 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
687 /// struct nk_context ctx;
688 /// nk_init_xxx(&ctx, ...);
689 /// while (1) {
690 ///     Event evt;
691 ///     nk_input_begin(&ctx);
692 ///     while (GetEvent(&evt)) {
693 ///         if (evt.type == MOUSE_MOVE)
694 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
695 ///         else if (evt.type == [...]) {
696 ///             // [...]
697 ///         }
698 ///     }
699 ///     nk_input_end(&ctx);
700 ///     // [...]
701 ///     nk_clear(&ctx);
702 /// } nk_free(&ctx);
703 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
704 ///
705 /// #### Reference
706 /// Function            | Description
707 /// --------------------|-------------------------------------------------------
708 /// __nk_input_begin__  | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
709 /// __nk_input_motion__ | Mirrors mouse cursor position
710 /// __nk_input_key__    | Mirrors key state with either pressed or released
711 /// __nk_input_button__ | Mirrors mouse button state with either pressed or released
712 /// __nk_input_scroll__ | Mirrors mouse scroll values
713 /// __nk_input_char__   | Adds a single ASCII text character into an internal text buffer
714 /// __nk_input_glyph__  | Adds a single multi-byte UTF-8 character into an internal text buffer
715 /// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer
716 /// __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
717 */
718 enum nk_keys {
719     NK_KEY_NONE,
720     NK_KEY_SHIFT,
721     NK_KEY_CTRL,
722     NK_KEY_DEL,
723     NK_KEY_ENTER,
724     NK_KEY_TAB,
725     NK_KEY_BACKSPACE,
726     NK_KEY_COPY,
727     NK_KEY_CUT,
728     NK_KEY_PASTE,
729     NK_KEY_UP,
730     NK_KEY_DOWN,
731     NK_KEY_LEFT,
732     NK_KEY_RIGHT,
733     /* Shortcuts: text field */
734     NK_KEY_TEXT_INSERT_MODE,
735     NK_KEY_TEXT_REPLACE_MODE,
736     NK_KEY_TEXT_RESET_MODE,
737     NK_KEY_TEXT_LINE_START,
738     NK_KEY_TEXT_LINE_END,
739     NK_KEY_TEXT_START,
740     NK_KEY_TEXT_END,
741     NK_KEY_TEXT_UNDO,
742     NK_KEY_TEXT_REDO,
743     NK_KEY_TEXT_SELECT_ALL,
744     NK_KEY_TEXT_WORD_LEFT,
745     NK_KEY_TEXT_WORD_RIGHT,
746     /* Shortcuts: scrollbar */
747     NK_KEY_SCROLL_START,
748     NK_KEY_SCROLL_END,
749     NK_KEY_SCROLL_DOWN,
750     NK_KEY_SCROLL_UP,
751     NK_KEY_MAX
752 };
753 enum nk_buttons {
754     NK_BUTTON_LEFT,
755     NK_BUTTON_MIDDLE,
756     NK_BUTTON_RIGHT,
757     NK_BUTTON_DOUBLE,
758     NK_BUTTON_MAX
759 };
760 /*/// #### nk_input_begin
761 /// Begins the input mirroring process by resetting text, scroll
762 /// mouse previous mouse position and movement as well as key state transitions,
763 ///
764 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
765 /// void nk_input_begin(struct nk_context*);
766 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
767 ///
768 /// Parameter   | Description
769 /// ------------|-----------------------------------------------------------
770 /// __ctx__     | Must point to a previously initialized `nk_context` struct
771 */
772 NK_API void nk_input_begin(struct nk_context*);
773 /*/// #### nk_input_motion
774 /// Mirrors current mouse position to nuklear
775 ///
776 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
777 /// void nk_input_motion(struct nk_context *ctx, int x, int y);
778 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
779 ///
780 /// Parameter   | Description
781 /// ------------|-----------------------------------------------------------
782 /// __ctx__     | Must point to a previously initialized `nk_context` struct
783 /// __x__       | Must hold an integer describing the current mouse cursor x-position
784 /// __y__       | Must hold an integer describing the current mouse cursor y-position
785 */
786 NK_API void nk_input_motion(struct nk_context*, int x, int y);
787 /*/// #### nk_input_key
788 /// Mirrors state of a specific key to nuklear
789 ///
790 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
791 /// void nk_input_key(struct nk_context*, enum nk_keys key, int down);
792 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
793 ///
794 /// Parameter   | Description
795 /// ------------|-----------------------------------------------------------
796 /// __ctx__     | Must point to a previously initialized `nk_context` struct
797 /// __key__     | Must be any value specified in enum `nk_keys` that needs to be mirrored
798 /// __down__    | Must be 0 for key is up and 1 for key is down
799 */
800 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
801 /*/// #### nk_input_button
802 /// Mirrors the state of a specific mouse button to nuklear
803 ///
804 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
805 /// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, int down);
806 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
807 ///
808 /// Parameter   | Description
809 /// ------------|-----------------------------------------------------------
810 /// __ctx__     | Must point to a previously initialized `nk_context` struct
811 /// __btn__     | Must be any value specified in enum `nk_buttons` that needs to be mirrored
812 /// __x__       | Must contain an integer describing mouse cursor x-position on click up/down
813 /// __y__       | Must contain an integer describing mouse cursor y-position on click up/down
814 /// __down__    | Must be 0 for key is up and 1 for key is down
815 */
816 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
817 /*/// #### nk_input_scroll
818 /// Copies the last mouse scroll value to nuklear. Is generally
819 /// a scroll value. So does not have to come from mouse and could also originate
820 ///
821 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
822 /// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val);
823 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
824 ///
825 /// Parameter   | Description
826 /// ------------|-----------------------------------------------------------
827 /// __ctx__     | Must point to a previously initialized `nk_context` struct
828 /// __val__     | vector with both X- as well as Y-scroll value
829 */
830 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
831 /*/// #### nk_input_char
832 /// Copies a single ASCII character into an internal text buffer
833 /// This is basically a helper function to quickly push ASCII characters into
834 /// nuklear.
835 ///
836 /// !!! Note
837 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
838 ///
839 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
840 /// void nk_input_char(struct nk_context *ctx, char c);
841 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
842 ///
843 /// Parameter   | Description
844 /// ------------|-----------------------------------------------------------
845 /// __ctx__     | Must point to a previously initialized `nk_context` struct
846 /// __c__       | Must be a single ASCII character preferable one that can be printed
847 */
848 NK_API void nk_input_char(struct nk_context*, char);
849 /*/// #### nk_input_glyph
850 /// Converts an encoded unicode rune into UTF-8 and copies the result into an
851 /// internal text buffer.
852 ///
853 /// !!! Note
854 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
855 ///
856 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
857 /// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g);
858 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
859 ///
860 /// Parameter   | Description
861 /// ------------|-----------------------------------------------------------
862 /// __ctx__     | Must point to a previously initialized `nk_context` struct
863 /// __g__       | UTF-32 unicode codepoint
864 */
865 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
866 /*/// #### nk_input_unicode
867 /// Converts a unicode rune into UTF-8 and copies the result
868 /// into an internal text buffer.
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_unicode(struct nk_context*, nk_rune rune);
874 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
875 ///
876 /// Parameter   | Description
877 /// ------------|-----------------------------------------------------------
878 /// __ctx__     | Must point to a previously initialized `nk_context` struct
879 /// __rune__    | UTF-32 unicode codepoint
880 */
881 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
882 /*/// #### nk_input_end
883 /// End the input mirroring process by resetting mouse grabbing
884 /// state to ensure the mouse cursor is not grabbed indefinitely.///
885 ///
886 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
887 /// void nk_input_end(struct nk_context *ctx);
888 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
889 ///
890 /// Parameter   | Description
891 /// ------------|-----------------------------------------------------------
892 /// __ctx__     | Must point to a previously initialized `nk_context` struct
893 */
894 NK_API void nk_input_end(struct nk_context*);
895 /* =============================================================================
896  *
897  *                                  DRAWING
898  *
899  * =============================================================================*/
900 /*/// ### Drawing
901 /// This library was designed to be render backend agnostic so it does
902 /// not draw anything to screen directly. Instead all drawn shapes, widgets
903 /// are made of, are buffered into memory and make up a command queue.
904 /// Each frame therefore fills the command buffer with draw commands
905 /// that then need to be executed by the user and his own render backend.
906 /// After that the command buffer needs to be cleared and a new frame can be
907 /// started. It is probably important to note that the command buffer is the main
908 /// drawing API and the optional vertex buffer API only takes this format and
909 /// converts it into a hardware accessible format.
910 ///
911 /// #### Usage
912 /// To draw all draw commands accumulated over a frame you need your own render
913 /// backend able to draw a number of 2D primitives. This includes at least
914 /// filled and stroked rectangles, circles, text, lines, triangles and scissors.
915 /// As soon as this criterion is met you can iterate over each draw command
916 /// and execute each draw command in a interpreter like fashion:
917 ///
918 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
919 /// const struct nk_command *cmd = 0;
920 /// nk_foreach(cmd, &ctx) {
921 ///     switch (cmd->type) {
922 ///     case NK_COMMAND_LINE:
923 ///         your_draw_line_function(...)
924 ///         break;
925 ///     case NK_COMMAND_RECT
926 ///         your_draw_rect_function(...)
927 ///         break;
928 ///     case //...:
929 ///         //[...]
930 ///     }
931 /// }
932 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
933 ///
934 /// In program flow context draw commands need to be executed after input has been
935 /// gathered and the complete UI with windows and their contained widgets have
936 /// been executed and before calling `nk_clear` which frees all previously
937 /// allocated draw commands.
938 ///
939 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
940 /// struct nk_context ctx;
941 /// nk_init_xxx(&ctx, ...);
942 /// while (1) {
943 ///     Event evt;
944 ///     nk_input_begin(&ctx);
945 ///     while (GetEvent(&evt)) {
946 ///         if (evt.type == MOUSE_MOVE)
947 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
948 ///         else if (evt.type == [...]) {
949 ///             [...]
950 ///         }
951 ///     }
952 ///     nk_input_end(&ctx);
953 ///     //
954 ///     // [...]
955 ///     //
956 ///     const struct nk_command *cmd = 0;
957 ///     nk_foreach(cmd, &ctx) {
958 ///     switch (cmd->type) {
959 ///     case NK_COMMAND_LINE:
960 ///         your_draw_line_function(...)
961 ///         break;
962 ///     case NK_COMMAND_RECT
963 ///         your_draw_rect_function(...)
964 ///         break;
965 ///     case ...:
966 ///         // [...]
967 ///     }
968 ///     nk_clear(&ctx);
969 /// }
970 /// nk_free(&ctx);
971 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
972 ///
973 /// You probably noticed that you have to draw all of the UI each frame which is
974 /// quite wasteful. While the actual UI updating loop is quite fast rendering
975 /// without actually needing it is not. So there are multiple things you could do.
976 ///
977 /// First is only update on input. This of course is only an option if your
978 /// application only depends on the UI and does not require any outside calculations.
979 /// If you actually only update on input make sure to update the UI two times each
980 /// frame and call `nk_clear` directly after the first pass and only draw in
981 /// the second pass. In addition it is recommended to also add additional timers
982 /// to make sure the UI is not drawn more than a fixed number of frames per second.
983 ///
984 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
985 /// struct nk_context ctx;
986 /// nk_init_xxx(&ctx, ...);
987 /// while (1) {
988 ///     // [...wait for input ]
989 ///     // [...do two UI passes ...]
990 ///     do_ui(...)
991 ///     nk_clear(&ctx);
992 ///     do_ui(...)
993 ///     //
994 ///     // draw
995 ///     const struct nk_command *cmd = 0;
996 ///     nk_foreach(cmd, &ctx) {
997 ///     switch (cmd->type) {
998 ///     case NK_COMMAND_LINE:
999 ///         your_draw_line_function(...)
1000 ///         break;
1001 ///     case NK_COMMAND_RECT
1002 ///         your_draw_rect_function(...)
1003 ///         break;
1004 ///     case ...:
1005 ///         //[...]
1006 ///     }
1007 ///     nk_clear(&ctx);
1008 /// }
1009 /// nk_free(&ctx);
1010 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1011 ///
1012 /// The second probably more applicable trick is to only draw if anything changed.
1013 /// It is not really useful for applications with continuous draw loop but
1014 /// quite useful for desktop applications. To actually get nuklear to only
1015 /// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
1016 /// allocate a memory buffer that will store each unique drawing output.
1017 /// After each frame you compare the draw command memory inside the library
1018 /// with your allocated buffer by memcmp. If memcmp detects differences
1019 /// you have to copy the command buffer into the allocated buffer
1020 /// and then draw like usual (this example uses fixed memory but you could
1021 /// use dynamically allocated memory).
1022 ///
1023 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1024 /// //[... other defines ...]
1025 /// #define NK_ZERO_COMMAND_MEMORY
1026 /// #include "nuklear.h"
1027 /// //
1028 /// // setup context
1029 /// struct nk_context ctx;
1030 /// void *last = calloc(1,64*1024);
1031 /// void *buf = calloc(1,64*1024);
1032 /// nk_init_fixed(&ctx, buf, 64*1024);
1033 /// //
1034 /// // loop
1035 /// while (1) {
1036 ///     // [...input...]
1037 ///     // [...ui...]
1038 ///     void *cmds = nk_buffer_memory(&ctx.memory);
1039 ///     if (memcmp(cmds, last, ctx.memory.allocated)) {
1040 ///         memcpy(last,cmds,ctx.memory.allocated);
1041 ///         const struct nk_command *cmd = 0;
1042 ///         nk_foreach(cmd, &ctx) {
1043 ///             switch (cmd->type) {
1044 ///             case NK_COMMAND_LINE:
1045 ///                 your_draw_line_function(...)
1046 ///                 break;
1047 ///             case NK_COMMAND_RECT
1048 ///                 your_draw_rect_function(...)
1049 ///                 break;
1050 ///             case ...:
1051 ///                 // [...]
1052 ///             }
1053 ///         }
1054 ///     }
1055 ///     nk_clear(&ctx);
1056 /// }
1057 /// nk_free(&ctx);
1058 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1059 ///
1060 /// Finally while using draw commands makes sense for higher abstracted platforms like
1061 /// X11 and Win32 or drawing libraries it is often desirable to use graphics
1062 /// hardware directly. Therefore it is possible to just define
1063 /// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
1064 /// To access the vertex output you first have to convert all draw commands into
1065 /// vertexes by calling `nk_convert` which takes in your preferred vertex format.
1066 /// After successfully converting all draw commands just iterate over and execute all
1067 /// vertex draw commands:
1068 ///
1069 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1070 /// // fill configuration
1071 /// struct nk_convert_config cfg = {};
1072 /// static const struct nk_draw_vertex_layout_element vertex_layout[] = {
1073 ///     {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
1074 ///     {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
1075 ///     {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
1076 ///     {NK_VERTEX_LAYOUT_END}
1077 /// };
1078 /// cfg.shape_AA = NK_ANTI_ALIASING_ON;
1079 /// cfg.line_AA = NK_ANTI_ALIASING_ON;
1080 /// cfg.vertex_layout = vertex_layout;
1081 /// cfg.vertex_size = sizeof(struct your_vertex);
1082 /// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
1083 /// cfg.circle_segment_count = 22;
1084 /// cfg.curve_segment_count = 22;
1085 /// cfg.arc_segment_count = 22;
1086 /// cfg.global_alpha = 1.0f;
1087 /// cfg.null = dev->null;
1088 /// //
1089 /// // setup buffers and convert
1090 /// struct nk_buffer cmds, verts, idx;
1091 /// nk_buffer_init_default(&cmds);
1092 /// nk_buffer_init_default(&verts);
1093 /// nk_buffer_init_default(&idx);
1094 /// nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
1095 /// //
1096 /// // draw
1097 /// nk_draw_foreach(cmd, &ctx, &cmds) {
1098 /// if (!cmd->elem_count) continue;
1099 ///     //[...]
1100 /// }
1101 /// nk_buffer_free(&cms);
1102 /// nk_buffer_free(&verts);
1103 /// nk_buffer_free(&idx);
1104 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1105 ///
1106 /// #### Reference
1107 /// Function            | Description
1108 /// --------------------|-------------------------------------------------------
1109 /// __nk__begin__       | Returns the first draw command in the context draw command list to be drawn
1110 /// __nk__next__        | Increments the draw command iterator to the next command inside the context draw command list
1111 /// __nk_foreach__      | Iterates over each draw command inside the context draw command list
1112 /// __nk_convert__      | Converts from the abstract draw commands list into a hardware accessible vertex format
1113 /// __nk_draw_begin__   | Returns the first vertex command in the context vertex draw list to be executed
1114 /// __nk__draw_next__   | Increments the vertex command iterator to the next command inside the context vertex command list
1115 /// __nk__draw_end__    | Returns the end of the vertex draw list
1116 /// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list
1117 */
1118 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON};
1119 enum nk_convert_result {
1120     NK_CONVERT_SUCCESS = 0,
1121     NK_CONVERT_INVALID_PARAM = 1,
1122     NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1),
1123     NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2),
1124     NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3)
1125 };
1126 struct nk_draw_null_texture {
1127     nk_handle texture; /* texture handle to a texture with a white pixel */
1128     struct nk_vec2 uv; /* coordinates to a white pixel in the texture  */
1129 };
1130 struct nk_convert_config {
1131     float global_alpha; /* global alpha value */
1132     enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
1133     enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
1134     unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
1135     unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
1136     unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
1137     struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
1138     const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
1139     nk_size vertex_size; /* sizeof one vertex for vertex packing */
1140     nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
1141 };
1142 /*/// #### nk__begin
1143 /// Returns a draw command list iterator to iterate all draw
1144 /// commands accumulated over one frame.
1145 ///
1146 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1147 /// const struct nk_command* nk__begin(struct nk_context*);
1148 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1149 ///
1150 /// Parameter   | Description
1151 /// ------------|-----------------------------------------------------------
1152 /// __ctx__     | must point to an previously initialized `nk_context` struct at the end of a frame
1153 ///
1154 /// Returns draw command pointer pointing to the first command inside the draw command list
1155 */
1156 NK_API const struct nk_command* nk__begin(struct nk_context*);
1157 /*/// #### nk__next
1158 /// Returns a draw command list iterator to iterate all draw
1159 ///
1160 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1161 /// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1162 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1163 ///
1164 /// Parameter   | Description
1165 /// ------------|-----------------------------------------------------------
1166 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1167 /// __cmd__     | Must point to an previously a draw command either returned by `nk__begin` or `nk__next`
1168 ///
1169 /// Returns draw command pointer pointing to the next command inside the draw command list
1170 */
1171 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1172 /*/// #### nk_foreach
1173 /// Iterates over each draw command inside the context draw command list
1174 ///
1175 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1176 /// #define nk_foreach(c, ctx)
1177 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1178 ///
1179 /// Parameter   | Description
1180 /// ------------|-----------------------------------------------------------
1181 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1182 /// __cmd__     | Command pointer initialized to NULL
1183 ///
1184 /// Returns draw command pointer pointing to the next command inside the draw command list
1185 */
1186 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1187 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1188 /*/// #### nk_convert
1189 /// Converts all internal draw commands into vertex draw commands and fills
1190 /// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format
1191 /// as well as some other configuration values have to be configured by filling out a
1192 /// `nk_convert_config` struct.
1193 ///
1194 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1195 /// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
1196 //      struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1197 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1198 ///
1199 /// Parameter   | Description
1200 /// ------------|-----------------------------------------------------------
1201 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1202 /// __cmds__    | Must point to a previously initialized buffer to hold converted vertex draw commands
1203 /// __vertices__| Must point to a previously initialized buffer to hold all produced vertices
1204 /// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices
1205 /// __config__  | Must point to a filled out `nk_config` struct to configure the conversion process
1206 ///
1207 /// Returns one of enum nk_convert_result error codes
1208 ///
1209 /// Parameter                       | Description
1210 /// --------------------------------|-----------------------------------------------------------
1211 /// NK_CONVERT_SUCCESS              | Signals a successful draw command to vertex buffer conversion
1212 /// NK_CONVERT_INVALID_PARAM        | An invalid argument was passed in the function call
1213 /// NK_CONVERT_COMMAND_BUFFER_FULL  | The provided buffer for storing draw commands is full or failed to allocate more memory
1214 /// NK_CONVERT_VERTEX_BUFFER_FULL   | The provided buffer for storing vertices is full or failed to allocate more memory
1215 /// NK_CONVERT_ELEMENT_BUFFER_FULL  | The provided buffer for storing indicies is full or failed to allocate more memory
1216 */
1217 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*);
1218 /*/// #### nk__draw_begin
1219 /// Returns a draw vertex command buffer iterator to iterate each the vertex draw command buffer
1220 ///
1221 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1222 /// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1223 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1224 ///
1225 /// Parameter   | Description
1226 /// ------------|-----------------------------------------------------------
1227 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1228 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
1229 ///
1230 /// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer
1231 */
1232 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1233 /*/// #### nk__draw_end
1234 /// Returns the vertex draw command at the end of the vertex draw command buffer
1235 ///
1236 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1237 /// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf);
1238 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1239 ///
1240 /// Parameter   | Description
1241 /// ------------|-----------------------------------------------------------
1242 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1243 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
1244 ///
1245 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
1246 */
1247 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1248 /*/// #### nk__draw_next
1249 /// Increments the vertex draw command buffer iterator
1250 ///
1251 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1252 /// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1253 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1254 ///
1255 /// Parameter   | Description
1256 /// ------------|-----------------------------------------------------------
1257 /// __cmd__     | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
1258 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
1259 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
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_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1264 /*/// #### nk_draw_foreach
1265 /// Iterates over each vertex draw command inside a vertex draw command buffer
1266 ///
1267 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1268 /// #define nk_draw_foreach(cmd,ctx, b)
1269 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1270 ///
1271 /// Parameter   | Description
1272 /// ------------|-----------------------------------------------------------
1273 /// __cmd__     | `nk_draw_command`iterator set to NULL
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 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1278 #endif
1279 /* =============================================================================
1280  *
1281  *                                  WINDOW
1282  *
1283  * =============================================================================
1284 /// ### Window
1285 /// Windows are the main persistent state used inside nuklear and are life time
1286 /// controlled by simply "retouching" (i.e. calling) each window each frame.
1287 /// All widgets inside nuklear can only be added inside function pair `nk_begin_xxx`
1288 /// and `nk_end`. Calling any widgets outside these two functions will result in an
1289 /// assert in debug or no state change in release mode.<br /><br />
1290 ///
1291 /// Each window holds frame persistent state like position, size, flags, state tables,
1292 /// and some garbage collected internal persistent widget state. Each window
1293 /// is linked into a window stack list which determines the drawing and overlapping
1294 /// order. The topmost window thereby is the currently active window.<br /><br />
1295 ///
1296 /// To change window position inside the stack occurs either automatically by
1297 /// user input by being clicked on or programmatically by calling `nk_window_focus`.
1298 /// Windows by default are visible unless explicitly being defined with flag
1299 /// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
1300 /// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
1301 /// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.<br /><br />
1302 ///
1303 /// #### Usage
1304 /// To create and keep a window you have to call one of the two `nk_begin_xxx`
1305 /// functions to start window declarations and `nk_end` at the end. Furthermore it
1306 /// is recommended to check the return value of `nk_begin_xxx` and only process
1307 /// widgets inside the window if the value is not 0. Either way you have to call
1308 /// `nk_end` at the end of window declarations. Furthermore, do not attempt to
1309 /// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
1310 /// in a segmentation fault.
1311 ///
1312 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1313 /// if (nk_begin_xxx(...) {
1314 ///     // [... widgets ...]
1315 /// }
1316 /// nk_end(ctx);
1317 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1318 ///
1319 /// In the grand concept window and widget declarations need to occur after input
1320 /// handling and before drawing to screen. Not doing so can result in higher
1321 /// latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
1322 /// is called at the end of the frame. While nuklear's default platform backends
1323 /// already call `nk_clear` for you if you write your own backend not calling
1324 /// `nk_clear` can cause asserts or even worse undefined behavior.
1325 ///
1326 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1327 /// struct nk_context ctx;
1328 /// nk_init_xxx(&ctx, ...);
1329 /// while (1) {
1330 ///     Event evt;
1331 ///     nk_input_begin(&ctx);
1332 ///     while (GetEvent(&evt)) {
1333 ///         if (evt.type == MOUSE_MOVE)
1334 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
1335 ///         else if (evt.type == [...]) {
1336 ///             nk_input_xxx(...);
1337 ///         }
1338 ///     }
1339 ///     nk_input_end(&ctx);
1340 ///
1341 ///     if (nk_begin_xxx(...) {
1342 ///         //[...]
1343 ///     }
1344 ///     nk_end(ctx);
1345 ///
1346 ///     const struct nk_command *cmd = 0;
1347 ///     nk_foreach(cmd, &ctx) {
1348 ///     case NK_COMMAND_LINE:
1349 ///         your_draw_line_function(...)
1350 ///         break;
1351 ///     case NK_COMMAND_RECT
1352 ///         your_draw_rect_function(...)
1353 ///         break;
1354 ///     case //...:
1355 ///         //[...]
1356 ///     }
1357 ///     nk_clear(&ctx);
1358 /// }
1359 /// nk_free(&ctx);
1360 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1361 ///
1362 /// #### Reference
1363 /// Function                            | Description
1364 /// ------------------------------------|----------------------------------------
1365 /// nk_begin                            | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1366 /// nk_begin_titled                     | Extended window start with separated title and identifier to allow multiple windows with same name but not title
1367 /// nk_end                              | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
1368 //
1369 /// nk_window_find                      | Finds and returns the window with give name
1370 /// nk_window_get_bounds                | Returns a rectangle with screen position and size of the currently processed window.
1371 /// nk_window_get_position              | Returns the position of the currently processed window
1372 /// nk_window_get_size                  | Returns the size with width and height of the currently processed window
1373 /// nk_window_get_width                 | Returns the width of the currently processed window
1374 /// nk_window_get_height                | Returns the height of the currently processed window
1375 /// nk_window_get_panel                 | Returns the underlying panel which contains all processing state of the current window
1376 /// nk_window_get_content_region        | Returns the position and size of the currently visible and non-clipped space inside the currently processed window
1377 /// nk_window_get_content_region_min    | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1378 /// nk_window_get_content_region_max    | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1379 /// nk_window_get_content_region_size   | Returns the size of the currently visible and non-clipped space inside the currently processed window
1380 /// nk_window_get_canvas                | Returns the draw command buffer. Can be used to draw custom widgets
1381 /// nk_window_has_focus                 | Returns if the currently processed window is currently active
1382 /// nk_window_is_collapsed              | Returns if the window with given name is currently minimized/collapsed
1383 /// nk_window_is_closed                 | Returns if the currently processed window was closed
1384 /// nk_window_is_hidden                 | Returns if the currently processed window was hidden
1385 /// nk_window_is_active                 | Same as nk_window_has_focus for some reason
1386 /// nk_window_is_hovered                | Returns if the currently processed window is currently being hovered by mouse
1387 /// nk_window_is_any_hovered            | Return if any window currently hovered
1388 /// nk_item_is_any_active               | Returns if any window or widgets is currently hovered or active
1389 //
1390 /// nk_window_set_bounds                | Updates position and size of the currently processed window
1391 /// nk_window_set_position              | Updates position of the currently process window
1392 /// nk_window_set_size                  | Updates the size of the currently processed window
1393 /// nk_window_set_focus                 | Set the currently processed window as active window
1394 //
1395 /// nk_window_close                     | Closes the window with given window name which deletes the window at the end of the frame
1396 /// nk_window_collapse                  | Collapses the window with given window name
1397 /// nk_window_collapse_if               | Collapses the window with given window name if the given condition was met
1398 /// nk_window_show                      | Hides a visible or reshows a hidden window
1399 /// nk_window_show_if                   | Hides/shows a window depending on condition
1400 */
1401 /*
1402 /// #### nk_panel_flags
1403 /// Flag                        | Description
1404 /// ----------------------------|----------------------------------------
1405 /// NK_WINDOW_BORDER            | Draws a border around the window to visually separate window from the background
1406 /// NK_WINDOW_MOVABLE           | The movable flag indicates that a window can be moved by user input or by dragging the window header
1407 /// 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
1408 /// NK_WINDOW_CLOSABLE          | Adds a closable icon into the header
1409 /// NK_WINDOW_MINIMIZABLE       | Adds a minimize icon into the header
1410 /// NK_WINDOW_NO_SCROLLBAR      | Removes the scrollbar from the window
1411 /// NK_WINDOW_TITLE             | Forces a header at the top at the window showing the title
1412 /// 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
1413 /// NK_WINDOW_BACKGROUND        | Always keep window in the background
1414 /// NK_WINDOW_SCALE_LEFT        | Puts window scaler in the left-ottom corner instead right-bottom
1415 /// NK_WINDOW_NO_INPUT          | Prevents window of scaling, moving or getting focus
1416 ///
1417 /// #### nk_collapse_states
1418 /// State           | Description
1419 /// ----------------|-----------------------------------------------------------
1420 /// __NK_MINIMIZED__| UI section is collased and not visibile until maximized
1421 /// __NK_MAXIMIZED__| UI section is extended and visibile until minimized
1422 /// <br /><br />
1423 */
1424 enum nk_panel_flags {
1425     NK_WINDOW_BORDER            = NK_FLAG(0),
1426     NK_WINDOW_MOVABLE           = NK_FLAG(1),
1427     NK_WINDOW_SCALABLE          = NK_FLAG(2),
1428     NK_WINDOW_CLOSABLE          = NK_FLAG(3),
1429     NK_WINDOW_MINIMIZABLE       = NK_FLAG(4),
1430     NK_WINDOW_NO_SCROLLBAR      = NK_FLAG(5),
1431     NK_WINDOW_TITLE             = NK_FLAG(6),
1432     NK_WINDOW_SCROLL_AUTO_HIDE  = NK_FLAG(7),
1433     NK_WINDOW_BACKGROUND        = NK_FLAG(8),
1434     NK_WINDOW_SCALE_LEFT        = NK_FLAG(9),
1435     NK_WINDOW_NO_INPUT          = NK_FLAG(10)
1436 };
1437 /*/// #### nk_begin
1438 /// Starts a new window; needs to be called every frame for every
1439 /// window (unless hidden) or otherwise the window gets removed
1440 ///
1441 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1442 /// int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1443 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1444 ///
1445 /// Parameter   | Description
1446 /// ------------|-----------------------------------------------------------
1447 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1448 /// __title__   | Window title and identifier. Needs to be persistent over frames to identify the window
1449 /// __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
1450 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different window behaviors
1451 ///
1452 /// Returns `true(1)` if the window can be filled up with widgets from this point
1453 /// until `nk_end` or `false(0)` otherwise for example if minimized
1454 */
1455 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1456 /*/// #### nk_begin_titled
1457 /// Extended window start with separated title and identifier to allow multiple
1458 /// windows with same name but not title
1459 ///
1460 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1461 /// int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1462 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1463 ///
1464 /// Parameter   | Description
1465 /// ------------|-----------------------------------------------------------
1466 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1467 /// __name__    | Window identifier. Needs to be persistent over frames to identify the window
1468 /// __title__   | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
1469 /// __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
1470 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different window behaviors
1471 ///
1472 /// Returns `true(1)` if the window can be filled up with widgets from this point
1473 /// until `nk_end` or `false(0)` otherwise for example if minimized
1474 */
1475 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1476 /*/// #### nk_end
1477 /// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
1478 /// All widget calls after this functions will result in asserts or no state changes
1479 ///
1480 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1481 /// void nk_end(struct nk_context *ctx);
1482 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1483 ///
1484 /// Parameter   | Description
1485 /// ------------|-----------------------------------------------------------
1486 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1487 */
1488 NK_API void nk_end(struct nk_context *ctx);
1489 /*/// #### nk_window_find
1490 /// Finds and returns a window from passed name
1491 ///
1492 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1493 /// void nk_end(struct nk_context *ctx);
1494 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1495 ///
1496 /// Parameter   | Description
1497 /// ------------|-----------------------------------------------------------
1498 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1499 /// __name__    | Window identifier
1500 ///
1501 /// Returns a `nk_window` struct pointing to the identified window or NULL if
1502 /// no window with given name was found
1503 */
1504 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1505 /*/// #### nk_window_get_bounds
1506 ///
1507 /// Returns a rectangle with screen position and size of the currently processed window
1508 /// !!! WARNING
1509 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1510 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1511 /// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
1512 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1513 ///
1514 /// Parameter   | Description
1515 /// ------------|-----------------------------------------------------------
1516 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1517 ///
1518 /// Returns a `nk_rect` struct with window upper left window position and size
1519 */
1520 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
1521 /*/// #### nk_window_get_bounds
1522 ///
1523 /// Returns the position of the currently processed window.
1524 /// !!! WARNING
1525 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1526 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1527 /// struct nk_vec2 nk_window_get_position(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_vec2` struct with window upper left position
1535 */
1536 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
1537 /*/// #### nk_window_get_size
1538 ///
1539 /// Returns the size with width and height of the currently processed window.
1540 /// !!! WARNING
1541 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1542 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1543 /// struct nk_vec2 nk_window_get_size(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 width and height
1551 */
1552 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*);
1553 /*/// #### nk_window_get_width
1554 ///
1555 /// Returns the width of the currently processed window.
1556 /// !!! WARNING
1557 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1558 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1559 /// float nk_window_get_width(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 the current window width
1567 */
1568 NK_API float nk_window_get_width(const struct nk_context*);
1569 /*/// #### nk_window_get_height
1570 ///
1571 /// Returns the height of the currently processed window.
1572 /// !!! WARNING
1573 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1575 /// float nk_window_get_height(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 height
1583 */
1584 NK_API float nk_window_get_height(const struct nk_context*);
1585 /*/// #### nk_window_get_panel
1586 ///
1587 /// Returns the underlying panel which contains all processing state of the current window.
1588 /// !!! WARNING
1589 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1590 /// !!! WARNING
1591 ///     Do not keep the returned panel pointer around it is only valid until `nk_end`
1592 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1593 /// struct nk_panel* nk_window_get_panel(struct nk_context *ctx);
1594 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1595 ///
1596 /// Parameter   | Description
1597 /// ------------|-----------------------------------------------------------
1598 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1599 ///
1600 /// Returns a pointer to window internal `nk_panel` state.
1601 */
1602 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*);
1603 /*/// #### nk_window_get_content_region
1604 ///
1605 /// Returns the position and size of the currently visible and non-clipped space
1606 /// inside the currently processed window.
1607 /// !!! WARNING
1608 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1609 ///
1610 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1611 /// struct nk_rect nk_window_get_content_region(struct nk_context *ctx);
1612 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1613 ///
1614 /// Parameter   | Description
1615 /// ------------|-----------------------------------------------------------
1616 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1617 ///
1618 /// Returns `nk_rect` struct with screen position and size (no scrollbar offset)
1619 /// of the visible space inside the current window
1620 */
1621 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*);
1622 /*/// #### nk_window_get_content_region_min
1623 ///
1624 /// Returns the upper left position of the currently visible and non-clipped
1625 /// space inside the currently processed window.
1626 /// !!! WARNING
1627 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1628 ///
1629 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1630 /// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx);
1631 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1632 ///
1633 /// Parameter   | Description
1634 /// ------------|-----------------------------------------------------------
1635 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1636 ///
1637 /// returns `nk_vec2` struct with  upper left screen position (no scrollbar offset)
1638 /// of the visible space inside the current window
1639 */
1640 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*);
1641 /*/// #### nk_window_get_content_region_max
1642 ///
1643 /// Returns the lower right screen position of the currently visible and
1644 /// non-clipped space inside the currently processed window.
1645 /// !!! WARNING
1646 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1647 ///
1648 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1649 /// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx);
1650 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1651 ///
1652 /// Parameter   | Description
1653 /// ------------|-----------------------------------------------------------
1654 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1655 ///
1656 /// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset)
1657 /// of the visible space inside the current window
1658 */
1659 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*);
1660 /*/// #### nk_window_get_content_region_size
1661 ///
1662 /// Returns the size of the currently visible and non-clipped space inside the
1663 /// currently processed window
1664 /// !!! WARNING
1665 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1666 ///
1667 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1668 /// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx);
1669 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1670 ///
1671 /// Parameter   | Description
1672 /// ------------|-----------------------------------------------------------
1673 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1674 ///
1675 /// Returns `nk_vec2` struct with size the visible space inside the current window
1676 */
1677 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*);
1678 /*/// #### nk_window_get_canvas
1679 /// Returns the draw command buffer. Can be used to draw custom widgets
1680 /// !!! WARNING
1681 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1682 /// !!! WARNING
1683 ///     Do not keep the returned command buffer pointer around it is only valid until `nk_end`
1684 ///
1685 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1686 /// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx);
1687 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1688 ///
1689 /// Parameter   | Description
1690 /// ------------|-----------------------------------------------------------
1691 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1692 ///
1693 /// Returns a pointer to window internal `nk_command_buffer` struct used as
1694 /// drawing canvas. Can be used to do custom drawing.
1695 */
1696 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*);
1697 /*/// #### nk_window_has_focus
1698 /// Returns if the currently processed window is currently active
1699 /// !!! WARNING
1700 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1701 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1702 /// int nk_window_has_focus(const struct nk_context *ctx);
1703 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1704 ///
1705 /// Parameter   | Description
1706 /// ------------|-----------------------------------------------------------
1707 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1708 ///
1709 /// Returns `false(0)` if current window is not active or `true(1)` if it is
1710 */
1711 NK_API int nk_window_has_focus(const struct nk_context*);
1712 /*/// #### nk_window_is_hovered
1713 /// Return if the current window is being hovered
1714 /// !!! WARNING
1715 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1716 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1717 /// int nk_window_is_hovered(struct nk_context *ctx);
1718 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1719 ///
1720 /// Parameter   | Description
1721 /// ------------|-----------------------------------------------------------
1722 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1723 ///
1724 /// Returns `true(1)` if current window is hovered or `false(0)` otherwise
1725 */
1726 NK_API int nk_window_is_hovered(struct nk_context*);
1727 /*/// #### nk_window_is_collapsed
1728 /// Returns if the window with given name is currently minimized/collapsed
1729 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1730 /// int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1732 ///
1733 /// Parameter   | Description
1734 /// ------------|-----------------------------------------------------------
1735 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1736 /// __name__    | Identifier of window you want to check if it is collapsed
1737 ///
1738 /// Returns `true(1)` if current window is minimized and `false(0)` if window not
1739 /// found or is not minimized
1740 */
1741 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1742 /*/// #### nk_window_is_closed
1743 /// Returns if the window with given name was closed by calling `nk_close`
1744 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1745 /// int nk_window_is_closed(struct nk_context *ctx, const char *name);
1746 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1747 ///
1748 /// Parameter   | Description
1749 /// ------------|-----------------------------------------------------------
1750 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1751 /// __name__    | Identifier of window you want to check if it is closed
1752 ///
1753 /// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed
1754 */
1755 NK_API int nk_window_is_closed(struct nk_context*, const char*);
1756 /*/// #### nk_window_is_hidden
1757 /// Returns if the window with given name is hidden
1758 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1759 /// int nk_window_is_hidden(struct nk_context *ctx, const char *name);
1760 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1761 ///
1762 /// Parameter   | Description
1763 /// ------------|-----------------------------------------------------------
1764 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1765 /// __name__    | Identifier of window you want to check if it is hidden
1766 ///
1767 /// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible
1768 */
1769 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1770 /*/// #### nk_window_is_active
1771 /// Same as nk_window_has_focus for some reason
1772 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1773 /// int nk_window_is_active(struct nk_context *ctx, const char *name);
1774 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1775 ///
1776 /// Parameter   | Description
1777 /// ------------|-----------------------------------------------------------
1778 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1779 /// __name__    | Identifier of window you want to check if it is active
1780 ///
1781 /// Returns `true(1)` if current window is active or `false(0)` window not found or not active
1782 */
1783 NK_API int nk_window_is_active(struct nk_context*, const char*);
1784 /*/// #### nk_window_is_any_hovered
1785 /// Returns if the any window is being hovered
1786 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1787 /// int nk_window_is_any_hovered(struct nk_context*);
1788 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1789 ///
1790 /// Parameter   | Description
1791 /// ------------|-----------------------------------------------------------
1792 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1793 ///
1794 /// Returns `true(1)` if any window is hovered or `false(0)` otherwise
1795 */
1796 NK_API int nk_window_is_any_hovered(struct nk_context*);
1797 /*/// #### nk_item_is_any_active
1798 /// Returns if the any window is being hovered or any widget is currently active.
1799 /// Can be used to decide if input should be processed by UI or your specific input handling.
1800 /// Example could be UI and 3D camera to move inside a 3D space.
1801 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1802 /// int nk_item_is_any_active(struct nk_context*);
1803 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1804 ///
1805 /// Parameter   | Description
1806 /// ------------|-----------------------------------------------------------
1807 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1808 ///
1809 /// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise
1810 */
1811 NK_API int nk_item_is_any_active(struct nk_context*);
1812 /*/// #### nk_window_set_bounds
1813 /// Updates position and size of window with passed in name
1814 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1815 /// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
1816 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1817 ///
1818 /// Parameter   | Description
1819 /// ------------|-----------------------------------------------------------
1820 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1821 /// __name__    | Identifier of the window to modify both position and size
1822 /// __bounds__  | Must point to a `nk_rect` struct with the new position and size
1823 */
1824 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
1825 /*/// #### nk_window_set_position
1826 /// Updates position of window with passed name
1827 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1828 /// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
1829 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1830 ///
1831 /// Parameter   | Description
1832 /// ------------|-----------------------------------------------------------
1833 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1834 /// __name__    | Identifier of the window to modify both position
1835 /// __pos__     | Must point to a `nk_vec2` struct with the new position
1836 */
1837 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
1838 /*/// #### nk_window_set_size
1839 /// Updates size of window with passed in name
1840 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1841 /// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
1842 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1843 ///
1844 /// Parameter   | Description
1845 /// ------------|-----------------------------------------------------------
1846 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1847 /// __name__    | Identifier of the window to modify both window size
1848 /// __size__    | Must point to a `nk_vec2` struct with new window size
1849 */
1850 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
1851 /*/// #### nk_window_set_focus
1852 /// Sets the window with given name as active
1853 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1854 /// void nk_window_set_focus(struct nk_context*, const char *name);
1855 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1856 ///
1857 /// Parameter   | Description
1858 /// ------------|-----------------------------------------------------------
1859 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1860 /// __name__    | Identifier of the window to set focus on
1861 */
1862 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1863 /*/// #### nk_window_close
1864 /// Closes a window and marks it for being freed at the end of the frame
1865 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1866 /// void nk_window_close(struct nk_context *ctx, const char *name);
1867 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1868 ///
1869 /// Parameter   | Description
1870 /// ------------|-----------------------------------------------------------
1871 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1872 /// __name__    | Identifier of the window to close
1873 */
1874 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1875 /*/// #### nk_window_collapse
1876 /// Updates collapse state of a window with given name
1877 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1878 /// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1879 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1880 ///
1881 /// Parameter   | Description
1882 /// ------------|-----------------------------------------------------------
1883 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1884 /// __name__    | Identifier of the window to close
1885 /// __state__   | value out of nk_collapse_states section
1886 */
1887 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1888 /*/// #### nk_window_collapse_if
1889 /// Updates collapse state of a window with given name if given condition is met
1890 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1891 /// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1892 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1893 ///
1894 /// Parameter   | Description
1895 /// ------------|-----------------------------------------------------------
1896 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1897 /// __name__    | Identifier of the window to either collapse or maximize
1898 /// __state__   | value out of nk_collapse_states section the window should be put into
1899 /// __cond__    | condition that has to be met to actually commit the collapse state change
1900 */
1901 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1902 /*/// #### nk_window_show
1903 /// updates visibility state of a window with given name
1904 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1905 /// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1906 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1907 ///
1908 /// Parameter   | Description
1909 /// ------------|-----------------------------------------------------------
1910 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1911 /// __name__    | Identifier of the window to either collapse or maximize
1912 /// __state__   | state with either visible or hidden to modify the window with
1913 */
1914 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1915 /*/// #### nk_window_show_if
1916 /// Updates visibility state of a window with given name if a given condition is met
1917 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1918 /// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1919 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1920 ///
1921 /// Parameter   | Description
1922 /// ------------|-----------------------------------------------------------
1923 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1924 /// __name__    | Identifier of the window to either hide or show
1925 /// __state__   | state with either visible or hidden to modify the window with
1926 /// __cond__    | condition that has to be met to actually commit the visbility state change
1927 */
1928 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1929 /* =============================================================================
1930  *
1931  *                                  LAYOUT
1932  *
1933  * =============================================================================
1934 /// ### Layouting
1935 /// Layouting in general describes placing widget inside a window with position and size.
1936 /// While in this particular implementation there are five different APIs for layouting
1937 /// each with different trade offs between control and ease of use. <br /><br />
1938 ///
1939 /// All layouting methods in this library are based around the concept of a row.
1940 /// A row has a height the window content grows by and a number of columns and each
1941 /// layouting method specifies how each widget is placed inside the row.
1942 /// After a row has been allocated by calling a layouting functions and then
1943 /// filled with widgets will advance an internal pointer over the allocated row. <br /><br />
1944 ///
1945 /// To actually define a layout you just call the appropriate layouting function
1946 /// and each subsequent widget call will place the widget as specified. Important
1947 /// here is that if you define more widgets then columns defined inside the layout
1948 /// functions it will allocate the next row without you having to make another layouting <br /><br />
1949 /// call.
1950 ///
1951 /// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
1952 /// is that you have to define the row height for each. However the row height
1953 /// often depends on the height of the font. <br /><br />
1954 ///
1955 /// To fix that internally nuklear uses a minimum row height that is set to the
1956 /// height plus padding of currently active font and overwrites the row height
1957 /// value if zero. <br /><br />
1958 ///
1959 /// If you manually want to change the minimum row height then
1960 /// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to
1961 /// reset it back to be derived from font height. <br /><br />
1962 ///
1963 /// Also if you change the font in nuklear it will automatically change the minimum
1964 /// row height for you and. This means if you change the font but still want
1965 /// a minimum row height smaller than the font you have to repush your value. <br /><br />
1966 ///
1967 /// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
1968 /// layouting method in combination with a cassowary constraint solver (there are
1969 /// some versions on github with permissive license model) to take over all control over widget
1970 /// layouting yourself. However for quick and dirty layouting using all the other layouting
1971 /// functions should be fine.
1972 ///
1973 /// #### Usage
1974 /// 1.  __nk_layout_row_dynamic__<br /><br />
1975 ///     The easiest layouting function is `nk_layout_row_dynamic`. It provides each
1976 ///     widgets with same horizontal space inside the row and dynamically grows
1977 ///     if the owning window grows in width. So the number of columns dictates
1978 ///     the size of each widget dynamically by formula:
1979 ///
1980 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1981 ///     widget_width = (window_width - padding - spacing) * (1/colum_count)
1982 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1983 ///
1984 ///     Just like all other layouting APIs if you define more widget than columns this
1985 ///     library will allocate a new row and keep all layouting parameters previously
1986 ///     defined.
1987 ///
1988 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1989 ///     if (nk_begin_xxx(...) {
1990 ///         // first row with height: 30 composed of two widgets
1991 ///         nk_layout_row_dynamic(&ctx, 30, 2);
1992 ///         nk_widget(...);
1993 ///         nk_widget(...);
1994 ///         //
1995 ///         // second row with same parameter as defined above
1996 ///         nk_widget(...);
1997 ///         nk_widget(...);
1998 ///         //
1999 ///         // third row uses 0 for height which will use auto layouting
2000 ///         nk_layout_row_dynamic(&ctx, 0, 2);
2001 ///         nk_widget(...);
2002 ///         nk_widget(...);
2003 ///     }
2004 ///     nk_end(...);
2005 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2006 ///
2007 /// 2.  __nk_layout_row_static__<br /><br />
2008 ///     Another easy layouting function is `nk_layout_row_static`. It provides each
2009 ///     widget with same horizontal pixel width inside the row and does not grow
2010 ///     if the owning window scales smaller or bigger.
2011 ///
2012 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2013 ///     if (nk_begin_xxx(...) {
2014 ///         // first row with height: 30 composed of two widgets with width: 80
2015 ///         nk_layout_row_static(&ctx, 30, 80, 2);
2016 ///         nk_widget(...);
2017 ///         nk_widget(...);
2018 ///         //
2019 ///         // second row with same parameter as defined above
2020 ///         nk_widget(...);
2021 ///         nk_widget(...);
2022 ///         //
2023 ///         // third row uses 0 for height which will use auto layouting
2024 ///         nk_layout_row_static(&ctx, 0, 80, 2);
2025 ///         nk_widget(...);
2026 ///         nk_widget(...);
2027 ///     }
2028 ///     nk_end(...);
2029 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2030 ///
2031 /// 3.  __nk_layout_row_xxx__<br /><br />
2032 ///     A little bit more advanced layouting API are functions `nk_layout_row_begin`,
2033 ///     `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
2034 ///     specify each column pixel or window ratio in a row. It supports either
2035 ///     directly setting per column pixel width or widget window ratio but not
2036 ///     both. Furthermore it is a immediate mode API so each value is directly
2037 ///     pushed before calling a widget. Therefore the layout is not automatically
2038 ///     repeating like the last two layouting functions.
2039 ///
2040 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2041 ///     if (nk_begin_xxx(...) {
2042 ///         // first row with height: 25 composed of two widgets with width 60 and 40
2043 ///         nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
2044 ///         nk_layout_row_push(ctx, 60);
2045 ///         nk_widget(...);
2046 ///         nk_layout_row_push(ctx, 40);
2047 ///         nk_widget(...);
2048 ///         nk_layout_row_end(ctx);
2049 ///         //
2050 ///         // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
2051 ///         nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
2052 ///         nk_layout_row_push(ctx, 0.25f);
2053 ///         nk_widget(...);
2054 ///         nk_layout_row_push(ctx, 0.75f);
2055 ///         nk_widget(...);
2056 ///         nk_layout_row_end(ctx);
2057 ///         //
2058 ///         // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75
2059 ///         nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
2060 ///         nk_layout_row_push(ctx, 0.25f);
2061 ///         nk_widget(...);
2062 ///         nk_layout_row_push(ctx, 0.75f);
2063 ///         nk_widget(...);
2064 ///         nk_layout_row_end(ctx);
2065 ///     }
2066 ///     nk_end(...);
2067 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2068 ///
2069 /// 4.  __nk_layout_row__<br /><br />
2070 ///     The array counterpart to API nk_layout_row_xxx is the single nk_layout_row
2071 ///     functions. Instead of pushing either pixel or window ratio for every widget
2072 ///     it allows to define it by array. The trade of for less control is that
2073 ///     `nk_layout_row` is automatically repeating. Otherwise the behavior is the
2074 ///     same.
2075 ///
2076 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2077 ///     if (nk_begin_xxx(...) {
2078 ///         // two rows with height: 30 composed of two widgets with width 60 and 40
2079 ///         const float size[] = {60,40};
2080 ///         nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
2081 ///         nk_widget(...);
2082 ///         nk_widget(...);
2083 ///         nk_widget(...);
2084 ///         nk_widget(...);
2085 ///         //
2086 ///         // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
2087 ///         const float ratio[] = {0.25, 0.75};
2088 ///         nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
2089 ///         nk_widget(...);
2090 ///         nk_widget(...);
2091 ///         nk_widget(...);
2092 ///         nk_widget(...);
2093 ///         //
2094 ///         // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75
2095 ///         const float ratio[] = {0.25, 0.75};
2096 ///         nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
2097 ///         nk_widget(...);
2098 ///         nk_widget(...);
2099 ///         nk_widget(...);
2100 ///         nk_widget(...);
2101 ///     }
2102 ///     nk_end(...);
2103 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2104 ///
2105 /// 5.  __nk_layout_row_template_xxx__<br /><br />
2106 ///     The most complex and second most flexible API is a simplified flexbox version without
2107 ///     line wrapping and weights for dynamic widgets. It is an immediate mode API but
2108 ///     unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
2109 ///     before calling the templated widgets.
2110 ///     The row template layout has three different per widget size specifier. The first
2111 ///     one is the `nk_layout_row_template_push_static`  with fixed widget pixel width.
2112 ///     They do not grow if the row grows and will always stay the same.
2113 ///     The second size specifier is `nk_layout_row_template_push_variable`
2114 ///     which defines a minimum widget size but it also can grow if more space is available
2115 ///     not taken by other widgets.
2116 ///     Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic`
2117 ///     which are completely flexible and unlike variable widgets can even shrink
2118 ///     to zero if not enough space is provided.
2119 ///
2120 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2121 ///     if (nk_begin_xxx(...) {
2122 ///         // two rows with height: 30 composed of three widgets
2123 ///         nk_layout_row_template_begin(ctx, 30);
2124 ///         nk_layout_row_template_push_dynamic(ctx);
2125 ///         nk_layout_row_template_push_variable(ctx, 80);
2126 ///         nk_layout_row_template_push_static(ctx, 80);
2127 ///         nk_layout_row_template_end(ctx);
2128 ///         //
2129 ///         // first row
2130 ///         nk_widget(...); // dynamic widget can go to zero if not enough space
2131 ///         nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
2132 ///         nk_widget(...); // static widget with fixed 80 pixel width
2133 ///         //
2134 ///         // second row same layout
2135 ///         nk_widget(...);
2136 ///         nk_widget(...);
2137 ///         nk_widget(...);
2138 ///     }
2139 ///     nk_end(...);
2140 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2141 ///
2142 /// 6.  __nk_layout_space_xxx__<br /><br />
2143 ///     Finally the most flexible API directly allows you to place widgets inside the
2144 ///     window. The space layout API is an immediate mode API which does not support
2145 ///     row auto repeat and directly sets position and size of a widget. Position
2146 ///     and size hereby can be either specified as ratio of allocated space or
2147 ///     allocated space local position and pixel size. Since this API is quite
2148 ///     powerful there are a number of utility functions to get the available space
2149 ///     and convert between local allocated space and screen space.
2150 ///
2151 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2152 ///     if (nk_begin_xxx(...) {
2153 ///         // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
2154 ///         nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
2155 ///         nk_layout_space_push(ctx, nk_rect(0,0,150,200));
2156 ///         nk_widget(...);
2157 ///         nk_layout_space_push(ctx, nk_rect(200,200,100,200));
2158 ///         nk_widget(...);
2159 ///         nk_layout_space_end(ctx);
2160 ///         //
2161 ///         // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
2162 ///         nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
2163 ///         nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
2164 ///         nk_widget(...);
2165 ///         nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
2166 ///         nk_widget(...);
2167 ///     }
2168 ///     nk_end(...);
2169 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2170 ///
2171 /// #### Reference
2172 /// Function                                | Description
2173 /// ----------------------------------------|------------------------------------
2174 /// nk_layout_set_min_row_height            | Set the currently used minimum row height to a specified value
2175 /// nk_layout_reset_min_row_height          | Resets the currently used minimum row height to font height
2176 /// nk_layout_widget_bounds                 | Calculates current width a static layout row can fit inside a window
2177 /// nk_layout_ratio_from_pixel              | Utility functions to calculate window ratio from pixel size
2178 //
2179 /// nk_layout_row_dynamic                   | Current layout is divided into n same sized growing columns
2180 /// nk_layout_row_static                    | Current layout is divided into n same fixed sized columns
2181 /// nk_layout_row_begin                     | Starts a new row with given height and number of columns
2182 /// nk_layout_row_push                      | Pushes another column with given size or window ratio
2183 /// nk_layout_row_end                       | Finished previously started row
2184 /// nk_layout_row                           | Specifies row columns in array as either window ratio or size
2185 //
2186 /// nk_layout_row_template_begin            | Begins the row template declaration
2187 /// nk_layout_row_template_push_dynamic     | Adds a dynamic column that dynamically grows and can go to zero if not enough space
2188 /// nk_layout_row_template_push_variable    | Adds a variable column that dynamically grows but does not shrink below specified pixel width
2189 /// nk_layout_row_template_push_static      | Adds a static column that does not grow and will always have the same size
2190 /// nk_layout_row_template_end              | Marks the end of the row template
2191 //
2192 /// nk_layout_space_begin                   | Begins a new layouting space that allows to specify each widgets position and size
2193 /// nk_layout_space_push                    | Pushes position and size of the next widget in own coordinate space either as pixel or ratio
2194 /// nk_layout_space_end                     | Marks the end of the layouting space
2195 //
2196 /// nk_layout_space_bounds                  | Callable after nk_layout_space_begin and returns total space allocated
2197 /// nk_layout_space_to_screen               | Converts vector from nk_layout_space coordinate space into screen space
2198 /// nk_layout_space_to_local                | Converts vector from screen space into nk_layout_space coordinates
2199 /// nk_layout_space_rect_to_screen          | Converts rectangle from nk_layout_space coordinate space into screen space
2200 /// nk_layout_space_rect_to_local           | Converts rectangle from screen space into nk_layout_space coordinates
2201 */
2202 /*/// #### nk_layout_set_min_row_height
2203 /// Sets the currently used minimum row height.
2204 /// !!! WARNING
2205 ///     The passed height needs to include both your preferred row height
2206 ///     as well as padding. No internal padding is added.
2207 ///
2208 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2209 /// void nk_layout_set_min_row_height(struct nk_context*, float height);
2210 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2211 ///
2212 /// Parameter   | Description
2213 /// ------------|-----------------------------------------------------------
2214 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2215 /// __height__  | New minimum row height to be used for auto generating the row height
2216 */
2217 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height);
2218 /*/// #### nk_layout_reset_min_row_height
2219 /// Reset the currently used minimum row height back to `font_height + text_padding + padding`
2220 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2221 /// void nk_layout_reset_min_row_height(struct nk_context*);
2222 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2223 ///
2224 /// Parameter   | Description
2225 /// ------------|-----------------------------------------------------------
2226 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2227 */
2228 NK_API void nk_layout_reset_min_row_height(struct nk_context*);
2229 /*/// #### nk_layout_widget_bounds
2230 /// Returns the width of the next row allocate by one of the layouting functions
2231 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2232 /// struct nk_rect nk_layout_widget_bounds(struct nk_context*);
2233 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2234 ///
2235 /// Parameter   | Description
2236 /// ------------|-----------------------------------------------------------
2237 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2238 ///
2239 /// Return `nk_rect` with both position and size of the next row
2240 */
2241 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*);
2242 /*/// #### nk_layout_ratio_from_pixel
2243 /// Utility functions to calculate window ratio from pixel size
2244 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2245 /// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
2246 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2247 ///
2248 /// Parameter   | Description
2249 /// ------------|-----------------------------------------------------------
2250 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2251 /// __pixel__   | Pixel_width to convert to window ratio
2252 ///
2253 /// Returns `nk_rect` with both position and size of the next row
2254 */
2255 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
2256 /*/// #### nk_layout_row_dynamic
2257 /// Sets current row layout to share horizontal space
2258 /// between @cols number of widgets evenly. Once called all subsequent widget
2259 /// calls greater than @cols will allocate a new row with same layout.
2260 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2261 /// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
2262 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2263 ///
2264 /// Parameter   | Description
2265 /// ------------|-----------------------------------------------------------
2266 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2267 /// __height__  | Holds height of each widget in row or zero for auto layouting
2268 /// __columns__ | Number of widget inside row
2269 */
2270 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
2271 /*/// #### nk_layout_row_dynamic
2272 /// Sets current row layout to fill @cols number of widgets
2273 /// in row with same @item_width horizontal size. Once called all subsequent widget
2274 /// calls greater than @cols will allocate a new row with same layout.
2275 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2276 /// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
2277 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2278 ///
2279 /// Parameter   | Description
2280 /// ------------|-----------------------------------------------------------
2281 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2282 /// __height__  | Holds height of each widget in row or zero for auto layouting
2283 /// __width__   | Holds pixel width of each widget in the row
2284 /// __columns__ | Number of widget inside row
2285 */
2286 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
2287 /*/// #### nk_layout_row_begin
2288 /// Starts a new dynamic or fixed row with given height and columns.
2289 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2290 /// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
2291 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2292 ///
2293 /// Parameter   | Description
2294 /// ------------|-----------------------------------------------------------
2295 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2296 /// __fmt__     | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
2297 /// __height__  | holds height of each widget in row or zero for auto layouting
2298 /// __columns__ | Number of widget inside row
2299 */
2300 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
2301 /*/// #### nk_layout_row_push
2302 /// Specifies either window ratio or width of a single column
2303 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2304 /// void nk_layout_row_push(struct nk_context*, float value);
2305 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2306 ///
2307 /// Parameter   | Description
2308 /// ------------|-----------------------------------------------------------
2309 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2310 /// __value__   | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call
2311 */
2312 NK_API void nk_layout_row_push(struct nk_context*, float value);
2313 /*/// #### nk_layout_row_end
2314 /// Finished previously started row
2315 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2316 /// void nk_layout_row_end(struct nk_context*);
2317 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2318 ///
2319 /// Parameter   | Description
2320 /// ------------|-----------------------------------------------------------
2321 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2322 */
2323 NK_API void nk_layout_row_end(struct nk_context*);
2324 /*/// #### nk_layout_row
2325 /// Specifies row columns in array as either window ratio or size
2326 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2327 /// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
2328 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2329 ///
2330 /// Parameter   | Description
2331 /// ------------|-----------------------------------------------------------
2332 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2333 /// __fmt__     | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
2334 /// __height__  | Holds height of each widget in row or zero for auto layouting
2335 /// __columns__ | Number of widget inside row
2336 */
2337 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
2338 /*/// #### nk_layout_row_template_begin
2339 /// Begins the row template declaration
2340 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2341 /// void nk_layout_row_template_begin(struct nk_context*, float row_height);
2342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2343 ///
2344 /// Parameter   | Description
2345 /// ------------|-----------------------------------------------------------
2346 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2347 /// __height__  | Holds height of each widget in row or zero for auto layouting
2348 */
2349 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
2350 /*/// #### nk_layout_row_template_push_dynamic
2351 /// Adds a dynamic column that dynamically grows and can go to zero if not enough space
2352 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2353 /// void nk_layout_row_template_push_dynamic(struct nk_context*);
2354 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2355 ///
2356 /// Parameter   | Description
2357 /// ------------|-----------------------------------------------------------
2358 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2359 /// __height__  | Holds height of each widget in row or zero for auto layouting
2360 */
2361 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*);
2362 /*/// #### nk_layout_row_template_push_variable
2363 /// Adds a variable column that dynamically grows but does not shrink below specified pixel width
2364 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2365 /// void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
2366 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2367 ///
2368 /// Parameter   | Description
2369 /// ------------|-----------------------------------------------------------
2370 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2371 /// __width__   | Holds the minimum pixel width the next column must always be
2372 */
2373 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
2374 /*/// #### nk_layout_row_template_push_static
2375 /// Adds a static column that does not grow and will always have the same size
2376 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2377 /// void nk_layout_row_template_push_static(struct nk_context*, float width);
2378 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2379 ///
2380 /// Parameter   | Description
2381 /// ------------|-----------------------------------------------------------
2382 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2383 /// __width__   | Holds the absolute pixel width value the next column must be
2384 */
2385 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
2386 /*/// #### nk_layout_row_template_end
2387 /// Marks the end of the row template
2388 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2389 /// void nk_layout_row_template_end(struct nk_context*);
2390 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2391 ///
2392 /// Parameter   | Description
2393 /// ------------|-----------------------------------------------------------
2394 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2395 */
2396 NK_API void nk_layout_row_template_end(struct nk_context*);
2397 /*/// #### nk_layout_space_begin
2398 /// Begins a new layouting space that allows to specify each widgets position and size.
2399 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2400 /// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
2401 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2402 ///
2403 /// Parameter   | Description
2404 /// ------------|-----------------------------------------------------------
2405 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2406 /// __fmt__     | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
2407 /// __height__  | Holds height of each widget in row or zero for auto layouting
2408 /// __columns__ | Number of widgets inside row
2409 */
2410 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
2411 /*/// #### nk_layout_space_push
2412 /// Pushes position and size of the next widget in own coordinate space either as pixel or ratio
2413 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2414 /// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds);
2415 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2416 ///
2417 /// Parameter   | Description
2418 /// ------------|-----------------------------------------------------------
2419 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2420 /// __bounds__  | Position and size in laoyut space local coordinates
2421 */
2422 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds);
2423 /*/// #### nk_layout_space_end
2424 /// Marks the end of the layout space
2425 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2426 /// void nk_layout_space_end(struct nk_context*);
2427 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2428 ///
2429 /// Parameter   | Description
2430 /// ------------|-----------------------------------------------------------
2431 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2432 */
2433 NK_API void nk_layout_space_end(struct nk_context*);
2434 /*/// #### nk_layout_space_bounds
2435 /// Utility function to calculate total space allocated for `nk_layout_space`
2436 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2437 /// struct nk_rect nk_layout_space_bounds(struct nk_context*);
2438 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2439 ///
2440 /// Parameter   | Description
2441 /// ------------|-----------------------------------------------------------
2442 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2443 ///
2444 /// Returns `nk_rect` holding the total space allocated
2445 */
2446 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*);
2447 /*/// #### nk_layout_space_to_screen
2448 /// Converts vector from nk_layout_space coordinate space into screen space
2449 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2450 /// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
2451 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2452 ///
2453 /// Parameter   | Description
2454 /// ------------|-----------------------------------------------------------
2455 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2456 /// __vec__     | Position to convert from layout space into screen coordinate space
2457 ///
2458 /// Returns transformed `nk_vec2` in screen space coordinates
2459 */
2460 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
2461 /*/// #### nk_layout_space_to_screen
2462 /// Converts vector from layout space into screen space
2463 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2464 /// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
2465 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2466 ///
2467 /// Parameter   | Description
2468 /// ------------|-----------------------------------------------------------
2469 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2470 /// __vec__     | Position to convert from screen space into layout coordinate space
2471 ///
2472 /// Returns transformed `nk_vec2` in layout space coordinates
2473 */
2474 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
2475 /*/// #### nk_layout_space_rect_to_screen
2476 /// Converts rectangle from screen space into layout space
2477 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2478 /// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
2479 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2480 ///
2481 /// Parameter   | Description
2482 /// ------------|-----------------------------------------------------------
2483 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2484 /// __bounds__  | Rectangle to convert from layout space into screen space
2485 ///
2486 /// Returns transformed `nk_rect` in screen space coordinates
2487 */
2488 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
2489 /*/// #### nk_layout_space_rect_to_local
2490 /// Converts rectangle from layout space into screen space
2491 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2492 /// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
2493 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2494 ///
2495 /// Parameter   | Description
2496 /// ------------|-----------------------------------------------------------
2497 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2498 /// __bounds__  | Rectangle to convert from layout space into screen space
2499 ///
2500 /// Returns transformed `nk_rect` in layout space coordinates
2501 */
2502 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
2503 /* =============================================================================
2504  *
2505  *                                  GROUP
2506  *
2507  * =============================================================================
2508 /// ### Groups
2509 /// Groups are basically windows inside windows. They allow to subdivide space
2510 /// in a window to layout widgets as a group. Almost all more complex widget
2511 /// layouting requirements can be solved using groups and basic layouting
2512 /// fuctionality. Groups just like windows are identified by an unique name and
2513 /// internally keep track of scrollbar offsets by default. However additional
2514 /// versions are provided to directly manage the scrollbar.
2515 ///
2516 /// #### Usage
2517 /// To create a group you have to call one of the three `nk_group_begin_xxx`
2518 /// functions to start group declarations and `nk_group_end` at the end. Furthermore it
2519 /// is required to check the return value of `nk_group_begin_xxx` and only process
2520 /// widgets inside the window if the value is not 0.
2521 /// Nesting groups is possible and even encouraged since many layouting schemes
2522 /// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end`
2523 /// to be only called if the corosponding `nk_group_begin_xxx` call does not return 0:
2524 ///
2525 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2526 /// if (nk_group_begin_xxx(ctx, ...) {
2527 ///     // [... widgets ...]
2528 ///     nk_group_end(ctx);
2529 /// }
2530 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2531 ///
2532 /// In the grand concept groups can be called after starting a window
2533 /// with `nk_begin_xxx` and before calling `nk_end`:
2534 ///
2535 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2536 /// struct nk_context ctx;
2537 /// nk_init_xxx(&ctx, ...);
2538 /// while (1) {
2539 ///     // Input
2540 ///     Event evt;
2541 ///     nk_input_begin(&ctx);
2542 ///     while (GetEvent(&evt)) {
2543 ///         if (evt.type == MOUSE_MOVE)
2544 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
2545 ///         else if (evt.type == [...]) {
2546 ///             nk_input_xxx(...);
2547 ///         }
2548 ///     }
2549 ///     nk_input_end(&ctx);
2550 ///     //
2551 ///     // Window
2552 ///     if (nk_begin_xxx(...) {
2553 ///         // [...widgets...]
2554 ///         nk_layout_row_dynamic(...);
2555 ///         if (nk_group_begin_xxx(ctx, ...) {
2556 ///             //[... widgets ...]
2557 ///             nk_group_end(ctx);
2558 ///         }
2559 ///     }
2560 ///     nk_end(ctx);
2561 ///     //
2562 ///     // Draw
2563 ///     const struct nk_command *cmd = 0;
2564 ///     nk_foreach(cmd, &ctx) {
2565 ///     switch (cmd->type) {
2566 ///     case NK_COMMAND_LINE:
2567 ///         your_draw_line_function(...)
2568 ///         break;
2569 ///     case NK_COMMAND_RECT
2570 ///         your_draw_rect_function(...)
2571 ///         break;
2572 ///     case ...:
2573 ///         // [...]
2574 ///     }
2575 //      nk_clear(&ctx);
2576 /// }
2577 /// nk_free(&ctx);
2578 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2579 /// #### Reference
2580 /// Function                        | Description
2581 /// --------------------------------|-------------------------------------------
2582 /// nk_group_begin                  | Start a new group with internal scrollbar handling
2583 /// nk_group_begin_titled           | Start a new group with separeted name and title and internal scrollbar handling
2584 /// nk_group_end                    | Ends a group. Should only be called if nk_group_begin returned non-zero
2585 /// nk_group_scrolled_offset_begin  | Start a new group with manual separated handling of scrollbar x- and y-offset
2586 /// nk_group_scrolled_begin         | Start a new group with manual scrollbar handling
2587 /// nk_group_scrolled_end           | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero
2588 */
2589 /*/// #### nk_group_begin
2590 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
2591 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2592 /// int nk_group_begin(struct nk_context*, const char *title, nk_flags);
2593 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2594 ///
2595 /// Parameter   | Description
2596 /// ------------|-----------------------------------------------------------
2597 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2598 /// __title__   | Must be an unique identifier for this group that is also used for the group header
2599 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different group behaviors
2600 ///
2601 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2602 */
2603 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
2604 /*/// #### nk_group_begin_titled
2605 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
2606 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2607 /// int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
2608 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2609 ///
2610 /// Parameter   | Description
2611 /// ------------|-----------------------------------------------------------
2612 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2613 /// __id__      | Must be an unique identifier for this group
2614 /// __title__   | Group header title
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_titled(struct nk_context*, const char *name, const char *title, nk_flags);
2620 /*/// #### nk_group_end
2621 /// Ends a widget group
2622 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2623 /// void nk_group_end(struct nk_context*);
2624 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2625 ///
2626 /// Parameter   | Description
2627 /// ------------|-----------------------------------------------------------
2628 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2629 */
2630 NK_API void nk_group_end(struct nk_context*);
2631 /*/// #### nk_group_scrolled_offset_begin
2632 /// starts a new widget group. requires a previous layouting function to specify
2633 /// a size. Does not keep track of scrollbar.
2634 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2635 /// int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
2636 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2637 ///
2638 /// Parameter   | Description
2639 /// ------------|-----------------------------------------------------------
2640 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2641 /// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally.
2642 /// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically
2643 /// __title__   | Window unique group title used to both identify and display in the group header
2644 /// __flags__   | Window flags from the nk_panel_flags section
2645 ///
2646 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2647 */
2648 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);
2649 /*/// #### nk_group_scrolled_begin
2650 /// Starts a new widget group. requires a previous
2651 /// layouting function to specify a size. Does not keep track of scrollbar.
2652 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2653 /// int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
2654 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2655 ///
2656 /// Parameter   | Description
2657 /// ------------|-----------------------------------------------------------
2658 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2659 /// __off__     | Both x- and y- scroll offset. Allows for manual scrollbar control
2660 /// __title__   | Window unique group title used to both identify and display in the group header
2661 /// __flags__   | Window flags from nk_panel_flags section
2662 ///
2663 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2664 */
2665 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
2666 /*/// #### nk_group_scrolled_end
2667 /// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin.
2668 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2669 /// void nk_group_scrolled_end(struct nk_context*);
2670 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2671 ///
2672 /// Parameter   | Description
2673 /// ------------|-----------------------------------------------------------
2674 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2675 */
2676 NK_API void nk_group_scrolled_end(struct nk_context*);
2677 /* =============================================================================
2678  *
2679  *                                  TREE
2680  *
2681  * =============================================================================
2682 /// ### Tree
2683 /// Trees represent two different concept. First the concept of a collapsable
2684 /// UI section that can be either in a hidden or visibile state. They allow the UI
2685 /// user to selectively minimize the current set of visible UI to comprehend.
2686 /// The second concept are tree widgets for visual UI representation of trees.<br /><br />
2687 ///
2688 /// Trees thereby can be nested for tree representations and multiple nested
2689 /// collapsable UI sections. All trees are started by calling of the
2690 /// `nk_tree_xxx_push_tree` functions and ended by calling one of the
2691 /// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label
2692 /// and optionally an image to be displayed and the initial collapse state from
2693 /// the nk_collapse_states section.<br /><br />
2694 ///
2695 /// The runtime state of the tree is either stored outside the library by the caller
2696 /// or inside which requires a unique ID. The unique ID can either be generated
2697 /// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`,
2698 /// by `__FILE__` and a user provided ID generated for example by loop index with
2699 /// function `nk_tree_push_id` or completely provided from outside by user with
2700 /// function `nk_tree_push_hashed`.
2701 ///
2702 /// #### Usage
2703 /// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx`
2704 /// functions to start a collapsable UI section and `nk_tree_xxx_pop` to mark the
2705 /// end.
2706 /// Each starting function will either return `false(0)` if the tree is collapsed
2707 /// or hidden and therefore does not need to be filled with content or `true(1)`
2708 /// if visible and required to be filled.
2709 ///
2710 /// !!! Note
2711 ///     The tree header does not require and layouting function and instead
2712 ///     calculates a auto height based on the currently used font size
2713 ///
2714 /// The tree ending functions only need to be called if the tree content is
2715 /// actually visible. So make sure the tree push function is guarded by `if`
2716 /// and the pop call is only taken if the tree is visible.
2717 ///
2718 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2719 /// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) {
2720 ///     nk_layout_row_dynamic(...);
2721 ///     nk_widget(...);
2722 ///     nk_tree_pop(ctx);
2723 /// }
2724 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2725 ///
2726 /// #### Reference
2727 /// Function                    | Description
2728 /// ----------------------------|-------------------------------------------
2729 /// nk_tree_push                | Start a collapsable UI section with internal state management
2730 /// nk_tree_push_id             | Start a collapsable UI section with internal state management callable in a look
2731 /// nk_tree_push_hashed         | Start a collapsable UI section with internal state management with full control over internal unique ID use to store state
2732 /// nk_tree_image_push          | Start a collapsable UI section with image and label header
2733 /// nk_tree_image_push_id       | Start a collapsable UI section with image and label header and internal state management callable in a look
2734 /// 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
2735 /// nk_tree_pop                 | Ends a collapsable UI section
2736 //
2737 /// nk_tree_state_push          | Start a collapsable UI section with external state management
2738 /// nk_tree_state_image_push    | Start a collapsable UI section with image and label header and external state management
2739 /// nk_tree_state_pop           | Ends a collapsabale UI section
2740 ///
2741 /// #### nk_tree_type
2742 /// Flag            | Description
2743 /// ----------------|----------------------------------------
2744 /// NK_TREE_NODE    | Highlighted tree header to mark a collapsable UI section
2745 /// NK_TREE_TAB     | Non-highighted tree header closer to tree representations
2746 */
2747 /*/// #### nk_tree_push
2748 /// Starts a collapsable UI section with internal state management
2749 /// !!! WARNING
2750 ///     To keep track of the runtime tree collapsable state this function uses
2751 ///     defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
2752 ///     to call this function in a loop please use `nk_tree_push_id` or
2753 ///     `nk_tree_push_hashed` instead.
2754 ///
2755 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2756 /// #define nk_tree_push(ctx, type, title, state)
2757 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2758 ///
2759 /// Parameter   | Description
2760 /// ------------|-----------------------------------------------------------
2761 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2762 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2763 /// __title__   | Label printed in the tree header
2764 /// __state__   | Initial tree state value out of nk_collapse_states
2765 ///
2766 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2767 */
2768 #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__)
2769 /*/// #### nk_tree_push_id
2770 /// Starts a collapsable UI section with internal state management callable in a look
2771 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2772 /// #define nk_tree_push_id(ctx, type, title, state, id)
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 /// __id__      | Loop counter index if this function is called in a loop
2782 ///
2783 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2784 */
2785 #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)
2786 /*/// #### nk_tree_push_hashed
2787 /// Start a collapsable UI section with internal state management with full
2788 /// control over internal unique ID used to store state
2789 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2790 /// 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);
2791 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2792 ///
2793 /// Parameter   | Description
2794 /// ------------|-----------------------------------------------------------
2795 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2796 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2797 /// __title__   | Label printed in the tree header
2798 /// __state__   | Initial tree state value out of nk_collapse_states
2799 /// __hash__    | Memory block or string to generate the ID from
2800 /// __len__     | Size of passed memory block or string in __hash__
2801 /// __seed__    | Seeding value if this function is called in a loop or default to `0`
2802 ///
2803 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2804 */
2805 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);
2806 /*/// #### nk_tree_image_push
2807 /// Start a collapsable UI section with image and label header
2808 /// !!! WARNING
2809 ///     To keep track of the runtime tree collapsable state this function uses
2810 ///     defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
2811 ///     to call this function in a loop please use `nk_tree_image_push_id` or
2812 ///     `nk_tree_image_push_hashed` instead.
2813 ///
2814 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2815 /// #define nk_tree_image_push(ctx, type, img, title, state)
2816 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2817 //
2818 /// Parameter   | Description
2819 /// ------------|-----------------------------------------------------------
2820 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2821 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2822 /// __img__     | Image to display inside the header on the left of the label
2823 /// __title__   | Label printed in the tree header
2824 /// __state__   | Initial tree state value out of nk_collapse_states
2825 ///
2826 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2827 */
2828 #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__)
2829 /*/// #### nk_tree_image_push_id
2830 /// Start a collapsable UI section with image and label header and internal state
2831 /// management callable in a look
2832 ///
2833 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2834 /// #define nk_tree_image_push_id(ctx, type, img, title, state, id)
2835 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2836 ///
2837 /// Parameter   | Description
2838 /// ------------|-----------------------------------------------------------
2839 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2840 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2841 /// __img__     | Image to display inside the header on the left of the label
2842 /// __title__   | Label printed in the tree header
2843 /// __state__   | Initial tree state value out of nk_collapse_states
2844 /// __id__      | Loop counter index if this function is called in a loop
2845 ///
2846 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2847 */
2848 #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)
2849 /*/// #### nk_tree_image_push_hashed
2850 /// Start a collapsable UI section with internal state management with full
2851 /// control over internal unique ID used to store state
2852 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2853 /// 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);
2854 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2855 ///
2856 /// Parameter   | Description
2857 /// ------------|-----------------------------------------------------------
2858 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2859 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2860 /// __img__     | Image to display inside the header on the left of the label
2861 /// __title__   | Label printed in the tree header
2862 /// __state__   | Initial tree state value out of nk_collapse_states
2863 /// __hash__    | Memory block or string to generate the ID from
2864 /// __len__     | Size of passed memory block or string in __hash__
2865 /// __seed__    | Seeding value if this function is called in a loop or default to `0`
2866 ///
2867 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2868 */
2869 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);
2870 /*/// #### nk_tree_pop
2871 /// Ends a collapsabale UI section
2872 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2873 /// void nk_tree_pop(struct nk_context*);
2874 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2875 ///
2876 /// Parameter   | Description
2877 /// ------------|-----------------------------------------------------------
2878 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
2879 */
2880 NK_API void nk_tree_pop(struct nk_context*);
2881 /*/// #### nk_tree_state_push
2882 /// Start a collapsable UI section with external state management
2883 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2884 /// int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
2885 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2886 ///
2887 /// Parameter   | Description
2888 /// ------------|-----------------------------------------------------------
2889 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
2890 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2891 /// __title__   | Label printed in the tree header
2892 /// __state__   | Persistent state to update
2893 ///
2894 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2895 */
2896 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
2897 /*/// #### nk_tree_state_image_push
2898 /// Start a collapsable UI section with image and label header and external state management
2899 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2900 /// int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, 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 /// __img__     | Image to display inside the header on the left of the label
2907 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2908 /// __title__   | Label printed in the tree header
2909 /// __state__   | Persistent state to update
2910 ///
2911 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2912 */
2913 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);
2914 /*/// #### nk_tree_state_pop
2915 /// Ends a collapsabale UI section
2916 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2917 /// void nk_tree_state_pop(struct nk_context*);
2918 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2919 ///
2920 /// Parameter   | Description
2921 /// ------------|-----------------------------------------------------------
2922 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
2923 */
2924 NK_API void nk_tree_state_pop(struct nk_context*);
2925 /* =============================================================================
2926  *
2927  *                                  LIST VIEW
2928  *
2929  * ============================================================================= */
2930 struct nk_list_view {
2931 /* public: */
2932     int begin, end, count;
2933 /* private: */
2934     int total_height;
2935     struct nk_context *ctx;
2936     nk_uint *scroll_pointer;
2937     nk_uint scroll_value;
2938 };
2939 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);
2940 NK_API void nk_list_view_end(struct nk_list_view*);
2941 /* =============================================================================
2942  *
2943  *                                  WIDGET
2944  *
2945  * ============================================================================= */
2946 enum nk_widget_layout_states {
2947     NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
2948     NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
2949     NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
2950 };
2951 enum nk_widget_states {
2952     NK_WIDGET_STATE_MODIFIED    = NK_FLAG(1),
2953     NK_WIDGET_STATE_INACTIVE    = NK_FLAG(2), /* widget is neither active nor hovered */
2954     NK_WIDGET_STATE_ENTERED     = NK_FLAG(3), /* widget has been hovered on the current frame */
2955     NK_WIDGET_STATE_HOVER       = NK_FLAG(4), /* widget is being hovered */
2956     NK_WIDGET_STATE_ACTIVED     = NK_FLAG(5),/* widget is currently activated */
2957     NK_WIDGET_STATE_LEFT        = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
2958     NK_WIDGET_STATE_HOVERED     = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */
2959     NK_WIDGET_STATE_ACTIVE      = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */
2960 };
2961 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
2962 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2);
2963 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
2964 NK_API struct nk_vec2 nk_widget_position(struct nk_context*);
2965 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
2966 NK_API float nk_widget_width(struct nk_context*);
2967 NK_API float nk_widget_height(struct nk_context*);
2968 NK_API int nk_widget_is_hovered(struct nk_context*);
2969 NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons);
2970 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
2971 NK_API void nk_spacing(struct nk_context*, int cols);
2972 /* =============================================================================
2973  *
2974  *                                  TEXT
2975  *
2976  * ============================================================================= */
2977 enum nk_text_align {
2978     NK_TEXT_ALIGN_LEFT        = 0x01,
2979     NK_TEXT_ALIGN_CENTERED    = 0x02,
2980     NK_TEXT_ALIGN_RIGHT       = 0x04,
2981     NK_TEXT_ALIGN_TOP         = 0x08,
2982     NK_TEXT_ALIGN_MIDDLE      = 0x10,
2983     NK_TEXT_ALIGN_BOTTOM      = 0x20
2984 };
2985 enum nk_text_alignment {
2986     NK_TEXT_LEFT        = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT,
2987     NK_TEXT_CENTERED    = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED,
2988     NK_TEXT_RIGHT       = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT
2989 };
2990 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
2991 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
2992 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
2993 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
2994 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
2995 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
2996 NK_API void nk_label_wrap(struct nk_context*, const char*);
2997 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
2998 NK_API void nk_image(struct nk_context*, struct nk_image);
2999 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color);
3000 #ifdef NK_INCLUDE_STANDARD_VARARGS
3001 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3);
3002 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);
3003 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2);
3004 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3);
3005 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
3006 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
3007 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
3008 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
3009 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
3010 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
3011 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
3012 #endif
3013 /* =============================================================================
3014  *
3015  *                                  BUTTON
3016  *
3017  * ============================================================================= */
3018 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
3019 NK_API int nk_button_label(struct nk_context*, const char *title);
3020 NK_API int nk_button_color(struct nk_context*, struct nk_color);
3021 NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type);
3022 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
3023 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
3024 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3025 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
3026 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
3027 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
3028 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
3029 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
3030 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
3031 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);
3032 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);
3033 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);
3034 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);
3035 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior);
3036 NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior);
3037 NK_API int nk_button_pop_behavior(struct nk_context*);
3038 /* =============================================================================
3039  *
3040  *                                  CHECKBOX
3041  *
3042  * ============================================================================= */
3043 NK_API int nk_check_label(struct nk_context*, const char*, int active);
3044 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
3045 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
3046 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
3047 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
3048 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
3049 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
3050 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
3051 /* =============================================================================
3052  *
3053  *                                  RADIO BUTTON
3054  *
3055  * ============================================================================= */
3056 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
3057 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
3058 NK_API int nk_option_label(struct nk_context*, const char*, int active);
3059 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
3060 /* =============================================================================
3061  *
3062  *                                  SELECTABLE
3063  *
3064  * ============================================================================= */
3065 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
3066 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
3067 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image,  const char*, nk_flags align, int *value);
3068 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
3069 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
3070 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
3071 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
3072 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
3073 /* =============================================================================
3074  *
3075  *                                  SLIDER
3076  *
3077  * ============================================================================= */
3078 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
3079 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
3080 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
3081 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
3082 /* =============================================================================
3083  *
3084  *                                  PROGRESSBAR
3085  *
3086  * ============================================================================= */
3087 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
3088 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
3089 
3090 /* =============================================================================
3091  *
3092  *                                  COLOR PICKER
3093  *
3094  * ============================================================================= */
3095 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format);
3096 NK_API int nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format);
3097 /* =============================================================================
3098  *
3099  *                                  PROPERTIES
3100  *
3101  * =============================================================================
3102 /// ### Properties
3103 /// Properties are the main value modification widgets in Nuklear. Changing a value
3104 /// can be achieved by dragging, adding/removing incremental steps on button click
3105 /// or by directly typing a number.
3106 ///
3107 /// #### Usage
3108 /// Each property requires a unique name for identifaction that is also used for
3109 /// displaying a label. If you want to use the same name multiple times make sure
3110 /// add a '#' before your name. The '#' will not be shown but will generate a
3111 /// unique ID. Each propery also takes in a minimum and maximum value. If you want
3112 /// to make use of the complete number range of a type just use the provided
3113 /// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for
3114 /// `nk_property_int` and `nk_propertyi`. In additional each property takes in
3115 /// a increment value that will be added or subtracted if either the increment
3116 /// decrement button is clicked. Finally there is a value for increment per pixel
3117 /// dragged that is added or subtracted from the value.
3118 ///
3119 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3120 /// int value = 0;
3121 /// struct nk_context ctx;
3122 /// nk_init_xxx(&ctx, ...);
3123 /// while (1) {
3124 ///     // Input
3125 ///     Event evt;
3126 ///     nk_input_begin(&ctx);
3127 ///     while (GetEvent(&evt)) {
3128 ///         if (evt.type == MOUSE_MOVE)
3129 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
3130 ///         else if (evt.type == [...]) {
3131 ///             nk_input_xxx(...);
3132 ///         }
3133 ///     }
3134 ///     nk_input_end(&ctx);
3135 ///     //
3136 ///     // Window
3137 ///     if (nk_begin_xxx(...) {
3138 ///         // Property
3139 ///         nk_layout_row_dynamic(...);
3140 ///         nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1);
3141 ///     }
3142 ///     nk_end(ctx);
3143 ///     //
3144 ///     // Draw
3145 ///     const struct nk_command *cmd = 0;
3146 ///     nk_foreach(cmd, &ctx) {
3147 ///     switch (cmd->type) {
3148 ///     case NK_COMMAND_LINE:
3149 ///         your_draw_line_function(...)
3150 ///         break;
3151 ///     case NK_COMMAND_RECT
3152 ///         your_draw_rect_function(...)
3153 ///         break;
3154 ///     case ...:
3155 ///         // [...]
3156 ///     }
3157 //      nk_clear(&ctx);
3158 /// }
3159 /// nk_free(&ctx);
3160 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3161 ///
3162 /// #### Reference
3163 /// Function            | Description
3164 /// --------------------|-------------------------------------------
3165 /// nk_property_int     | Integer property directly modifing a passed in value
3166 /// nk_property_float   | Float property directly modifing a passed in value
3167 /// nk_property_double  | Double property directly modifing a passed in value
3168 /// nk_propertyi        | Integer property returning the modified int value
3169 /// nk_propertyf        | Float property returning the modified float value
3170 /// nk_propertyd        | Double property returning the modified double value
3171 ///
3172 */
3173 /*/// #### nk_property_int
3174 /// Integer property directly modifing a passed in value
3175 /// !!! WARNING
3176 ///     To generate a unique property ID using the same label make sure to insert
3177 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3178 ///
3179 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3180 /// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
3181 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3182 ///
3183 /// Parameter           | Description
3184 /// --------------------|-----------------------------------------------------------
3185 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3186 /// __name__            | String used both as a label as well as a unique identifier
3187 /// __min__             | Minimum value not allowed to be underflown
3188 /// __val__             | Integer pointer to be modified
3189 /// __max__             | Maximum value not allowed to be overflown
3190 /// __step__            | Increment added and subtracted on increment and decrement button
3191 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3192 */
3193 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
3194 /*/// #### nk_property_float
3195 /// Float property directly modifing a passed in value
3196 /// !!! WARNING
3197 ///     To generate a unique property ID using the same label make sure to insert
3198 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3199 ///
3200 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3201 /// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
3202 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3203 ///
3204 /// Parameter           | Description
3205 /// --------------------|-----------------------------------------------------------
3206 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3207 /// __name__            | String used both as a label as well as a unique identifier
3208 /// __min__             | Minimum value not allowed to be underflown
3209 /// __val__             | Float pointer to be modified
3210 /// __max__             | Maximum value not allowed to be overflown
3211 /// __step__            | Increment added and subtracted on increment and decrement button
3212 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3213 */
3214 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
3215 /*/// #### nk_property_double
3216 /// Double property directly modifing a passed in value
3217 /// !!! WARNING
3218 ///     To generate a unique property ID using the same label make sure to insert
3219 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3220 ///
3221 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3222 /// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel);
3223 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3224 ///
3225 /// Parameter           | Description
3226 /// --------------------|-----------------------------------------------------------
3227 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3228 /// __name__            | String used both as a label as well as a unique identifier
3229 /// __min__             | Minimum value not allowed to be underflown
3230 /// __val__             | Double pointer to be modified
3231 /// __max__             | Maximum value not allowed to be overflown
3232 /// __step__            | Increment added and subtracted on increment and decrement button
3233 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3234 */
3235 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
3236 /*/// #### nk_propertyi
3237 /// Integer property modifing a passed in value and returning the new value
3238 /// !!! WARNING
3239 ///     To generate a unique property ID using the same label make sure to insert
3240 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3241 ///
3242 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3243 /// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel);
3244 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3245 ///
3246 /// Parameter           | Description
3247 /// --------------------|-----------------------------------------------------------
3248 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3249 /// __name__            | String used both as a label as well as a unique identifier
3250 /// __min__             | Minimum value not allowed to be underflown
3251 /// __val__             | Current integer value to be modified and returned
3252 /// __max__             | Maximum value not allowed to be overflown
3253 /// __step__            | Increment added and subtracted on increment and decrement button
3254 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3255 ///
3256 /// Returns the new modified integer value
3257 */
3258 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
3259 /*/// #### nk_propertyf
3260 /// Float property modifing a passed in value and returning the new value
3261 /// !!! WARNING
3262 ///     To generate a unique property ID using the same label make sure to insert
3263 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3264 ///
3265 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3266 /// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel);
3267 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3268 ///
3269 /// Parameter           | Description
3270 /// --------------------|-----------------------------------------------------------
3271 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3272 /// __name__            | String used both as a label as well as a unique identifier
3273 /// __min__             | Minimum value not allowed to be underflown
3274 /// __val__             | Current float value to be modified and returned
3275 /// __max__             | Maximum value not allowed to be overflown
3276 /// __step__            | Increment added and subtracted on increment and decrement button
3277 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3278 ///
3279 /// Returns the new modified float value
3280 */
3281 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
3282 /*/// #### nk_propertyd
3283 /// Float property modifing a passed in value and returning the new value
3284 /// !!! WARNING
3285 ///     To generate a unique property ID using the same label make sure to insert
3286 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3287 ///
3288 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3289 /// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel);
3290 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3291 ///
3292 /// Parameter           | Description
3293 /// --------------------|-----------------------------------------------------------
3294 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3295 /// __name__            | String used both as a label as well as a unique identifier
3296 /// __min__             | Minimum value not allowed to be underflown
3297 /// __val__             | Current double value to be modified and returned
3298 /// __max__             | Maximum value not allowed to be overflown
3299 /// __step__            | Increment added and subtracted on increment and decrement button
3300 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3301 ///
3302 /// Returns the new modified double value
3303 */
3304 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
3305 /* =============================================================================
3306  *
3307  *                                  TEXT EDIT
3308  *
3309  * ============================================================================= */
3310 enum nk_edit_flags {
3311     NK_EDIT_DEFAULT                 = 0,
3312     NK_EDIT_READ_ONLY               = NK_FLAG(0),
3313     NK_EDIT_AUTO_SELECT             = NK_FLAG(1),
3314     NK_EDIT_SIG_ENTER               = NK_FLAG(2),
3315     NK_EDIT_ALLOW_TAB               = NK_FLAG(3),
3316     NK_EDIT_NO_CURSOR               = NK_FLAG(4),
3317     NK_EDIT_SELECTABLE              = NK_FLAG(5),
3318     NK_EDIT_CLIPBOARD               = NK_FLAG(6),
3319     NK_EDIT_CTRL_ENTER_NEWLINE      = NK_FLAG(7),
3320     NK_EDIT_NO_HORIZONTAL_SCROLL    = NK_FLAG(8),
3321     NK_EDIT_ALWAYS_INSERT_MODE      = NK_FLAG(9),
3322     NK_EDIT_MULTILINE               = NK_FLAG(10),
3323     NK_EDIT_GOTO_END_ON_ACTIVATE    = NK_FLAG(11)
3324 };
3325 enum nk_edit_types {
3326     NK_EDIT_SIMPLE  = NK_EDIT_ALWAYS_INSERT_MODE,
3327     NK_EDIT_FIELD   = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD,
3328     NK_EDIT_BOX     = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD,
3329     NK_EDIT_EDITOR  = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD
3330 };
3331 enum nk_edit_events {
3332     NK_EDIT_ACTIVE      = NK_FLAG(0), /* edit widget is currently being modified */
3333     NK_EDIT_INACTIVE    = NK_FLAG(1), /* edit widget is not active and is not being modified */
3334     NK_EDIT_ACTIVATED   = NK_FLAG(2), /* edit widget went from state inactive to state active */
3335     NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
3336     NK_EDIT_COMMITED    = NK_FLAG(4) /* edit widget has received an enter and lost focus */
3337 };
3338 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
3339 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
3340 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
3341 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
3342 NK_API void nk_edit_unfocus(struct nk_context*);
3343 /* =============================================================================
3344  *
3345  *                                  CHART
3346  *
3347  * ============================================================================= */
3348 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
3349 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);
3350 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
3351 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);
3352 NK_API nk_flags nk_chart_push(struct nk_context*, float);
3353 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
3354 NK_API void nk_chart_end(struct nk_context*);
3355 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
3356 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);
3357 /* =============================================================================
3358  *
3359  *                                  POPUP
3360  *
3361  * ============================================================================= */
3362 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
3363 NK_API void nk_popup_close(struct nk_context*);
3364 NK_API void nk_popup_end(struct nk_context*);
3365 /* =============================================================================
3366  *
3367  *                                  COMBOBOX
3368  *
3369  * ============================================================================= */
3370 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
3371 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);
3372 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);
3373 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);
3374 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
3375 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);
3376 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);
3377 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);
3378 /* =============================================================================
3379  *
3380  *                                  ABSTRACT COMBOBOX
3381  *
3382  * ============================================================================= */
3383 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
3384 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
3385 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
3386 NK_API int nk_combo_begin_symbol(struct nk_context*,  enum nk_symbol_type,  struct nk_vec2 size);
3387 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
3388 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
3389 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img,  struct nk_vec2 size);
3390 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
3391 NK_API int nk_combo_begin_image_text(struct nk_context*,  const char *selected, int, struct nk_image, struct nk_vec2 size);
3392 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
3393 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
3394 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3395 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
3396 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3397 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3398 NK_API void nk_combo_close(struct nk_context*);
3399 NK_API void nk_combo_end(struct nk_context*);
3400 /* =============================================================================
3401  *
3402  *                                  CONTEXTUAL
3403  *
3404  * ============================================================================= */
3405 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
3406 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
3407 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
3408 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3409 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3410 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3411 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3412 NK_API void nk_contextual_close(struct nk_context*);
3413 NK_API void nk_contextual_end(struct nk_context*);
3414 /* =============================================================================
3415  *
3416  *                                  TOOLTIP
3417  *
3418  * ============================================================================= */
3419 NK_API void nk_tooltip(struct nk_context*, const char*);
3420 #ifdef NK_INCLUDE_STANDARD_VARARGS
3421 NK_API void nk_tooltipf(struct nk_context*, const char*, ...);
3422 #endif
3423 NK_API int nk_tooltip_begin(struct nk_context*, float width);
3424 NK_API void nk_tooltip_end(struct nk_context*);
3425 /* =============================================================================
3426  *
3427  *                                  MENU
3428  *
3429  * ============================================================================= */
3430 NK_API void nk_menubar_begin(struct nk_context*);
3431 NK_API void nk_menubar_end(struct nk_context*);
3432 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
3433 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
3434 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
3435 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
3436 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
3437 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
3438 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);
3439 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
3440 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
3441 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
3442 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3443 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3444 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3445 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3446 NK_API void nk_menu_close(struct nk_context*);
3447 NK_API void nk_menu_end(struct nk_context*);
3448 /* =============================================================================
3449  *
3450  *                                  STYLE
3451  *
3452  * ============================================================================= */
3453 enum nk_style_colors {
3454     NK_COLOR_TEXT,
3455     NK_COLOR_WINDOW,
3456     NK_COLOR_HEADER,
3457     NK_COLOR_BORDER,
3458     NK_COLOR_BUTTON,
3459     NK_COLOR_BUTTON_HOVER,
3460     NK_COLOR_BUTTON_ACTIVE,
3461     NK_COLOR_TOGGLE,
3462     NK_COLOR_TOGGLE_HOVER,
3463     NK_COLOR_TOGGLE_CURSOR,
3464     NK_COLOR_SELECT,
3465     NK_COLOR_SELECT_ACTIVE,
3466     NK_COLOR_SLIDER,
3467     NK_COLOR_SLIDER_CURSOR,
3468     NK_COLOR_SLIDER_CURSOR_HOVER,
3469     NK_COLOR_SLIDER_CURSOR_ACTIVE,
3470     NK_COLOR_PROPERTY,
3471     NK_COLOR_EDIT,
3472     NK_COLOR_EDIT_CURSOR,
3473     NK_COLOR_COMBO,
3474     NK_COLOR_CHART,
3475     NK_COLOR_CHART_COLOR,
3476     NK_COLOR_CHART_COLOR_HIGHLIGHT,
3477     NK_COLOR_SCROLLBAR,
3478     NK_COLOR_SCROLLBAR_CURSOR,
3479     NK_COLOR_SCROLLBAR_CURSOR_HOVER,
3480     NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,
3481     NK_COLOR_TAB_HEADER,
3482     NK_COLOR_COUNT
3483 };
3484 enum nk_style_cursor {
3485     NK_CURSOR_ARROW,
3486     NK_CURSOR_TEXT,
3487     NK_CURSOR_MOVE,
3488     NK_CURSOR_RESIZE_VERTICAL,
3489     NK_CURSOR_RESIZE_HORIZONTAL,
3490     NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT,
3491     NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT,
3492     NK_CURSOR_COUNT
3493 };
3494 NK_API void nk_style_default(struct nk_context*);
3495 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
3496 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
3497 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
3498 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors);
3499 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
3500 NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor);
3501 NK_API void nk_style_show_cursor(struct nk_context*);
3502 NK_API void nk_style_hide_cursor(struct nk_context*);
3503 
3504 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*);
3505 NK_API int nk_style_push_float(struct nk_context*, float*, float);
3506 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
3507 NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item);
3508 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
3509 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
3510 
3511 NK_API int nk_style_pop_font(struct nk_context*);
3512 NK_API int nk_style_pop_float(struct nk_context*);
3513 NK_API int nk_style_pop_vec2(struct nk_context*);
3514 NK_API int nk_style_pop_style_item(struct nk_context*);
3515 NK_API int nk_style_pop_flags(struct nk_context*);
3516 NK_API int nk_style_pop_color(struct nk_context*);
3517 /* =============================================================================
3518  *
3519  *                                  COLOR
3520  *
3521  * ============================================================================= */
3522 NK_API struct nk_color nk_rgb(int r, int g, int b);
3523 NK_API struct nk_color nk_rgb_iv(const int *rgb);
3524 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
3525 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
3526 NK_API struct nk_color nk_rgb_fv(const float *rgb);
3527 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c);
3528 NK_API struct nk_color nk_rgb_hex(const char *rgb);
3529 
3530 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
3531 NK_API struct nk_color nk_rgba_u32(nk_uint);
3532 NK_API struct nk_color nk_rgba_iv(const int *rgba);
3533 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
3534 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
3535 NK_API struct nk_color nk_rgba_fv(const float *rgba);
3536 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c);
3537 NK_API struct nk_color nk_rgba_hex(const char *rgb);
3538 
3539 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a);
3540 NK_API struct nk_colorf nk_hsva_colorfv(float *c);
3541 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in);
3542 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in);
3543 
3544 NK_API struct nk_color nk_hsv(int h, int s, int v);
3545 NK_API struct nk_color nk_hsv_iv(const int *hsv);
3546 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
3547 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
3548 NK_API struct nk_color nk_hsv_fv(const float *hsv);
3549 
3550 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
3551 NK_API struct nk_color nk_hsva_iv(const int *hsva);
3552 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
3553 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
3554 NK_API struct nk_color nk_hsva_fv(const float *hsva);
3555 
3556 /* color (conversion nuklear --> user) */
3557 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
3558 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
3559 NK_API struct nk_colorf nk_color_cf(struct nk_color);
3560 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
3561 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
3562 
3563 NK_API nk_uint nk_color_u32(struct nk_color);
3564 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
3565 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
3566 
3567 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
3568 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
3569 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
3570 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
3571 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
3572 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
3573 
3574 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
3575 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
3576 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
3577 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
3578 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
3579 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
3580 /* =============================================================================
3581  *
3582  *                                  IMAGE
3583  *
3584  * ============================================================================= */
3585 NK_API nk_handle nk_handle_ptr(void*);
3586 NK_API nk_handle nk_handle_id(int);
3587 NK_API struct nk_image nk_image_handle(nk_handle);
3588 NK_API struct nk_image nk_image_ptr(void*);
3589 NK_API struct nk_image nk_image_id(int);
3590 NK_API int nk_image_is_subimage(const struct nk_image* img);
3591 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
3592 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
3593 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
3594 /* =============================================================================
3595  *
3596  *                                  MATH
3597  *
3598  * ============================================================================= */
3599 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
3600 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
3601 
3602 NK_API struct nk_vec2 nk_vec2(float x, float y);
3603 NK_API struct nk_vec2 nk_vec2i(int x, int y);
3604 NK_API struct nk_vec2 nk_vec2v(const float *xy);
3605 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
3606 
3607 NK_API struct nk_rect nk_get_null_rect(void);
3608 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
3609 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
3610 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
3611 NK_API struct nk_rect nk_rectv(const float *xywh);
3612 NK_API struct nk_rect nk_rectiv(const int *xywh);
3613 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
3614 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
3615 /* =============================================================================
3616  *
3617  *                                  STRING
3618  *
3619  * ============================================================================= */
3620 NK_API int nk_strlen(const char *str);
3621 NK_API int nk_stricmp(const char *s1, const char *s2);
3622 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
3623 NK_API int nk_strtoi(const char *str, const char **endptr);
3624 NK_API float nk_strtof(const char *str, const char **endptr);
3625 NK_API double nk_strtod(const char *str, const char **endptr);
3626 NK_API int nk_strfilter(const char *text, const char *regexp);
3627 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
3628 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
3629 /* =============================================================================
3630  *
3631  *                                  UTF-8
3632  *
3633  * ============================================================================= */
3634 NK_API int nk_utf_decode(const char*, nk_rune*, int);
3635 NK_API int nk_utf_encode(nk_rune, char*, int);
3636 NK_API int nk_utf_len(const char*, int byte_len);
3637 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
3638 /* ===============================================================
3639  *
3640  *                          FONT
3641  *
3642  * ===============================================================*/
3643 /*  Font handling in this library was designed to be quite customizable and lets
3644     you decide what you want to use and what you want to provide. There are three
3645     different ways to use the font atlas. The first two will use your font
3646     handling scheme and only requires essential data to run nuklear. The next
3647     slightly more advanced features is font handling with vertex buffer output.
3648     Finally the most complex API wise is using nuklear's font baking API.
3649 
3650     1.) Using your own implementation without vertex buffer output
3651     --------------------------------------------------------------
3652     So first up the easiest way to do font handling is by just providing a
3653     `nk_user_font` struct which only requires the height in pixel of the used
3654     font and a callback to calculate the width of a string. This way of handling
3655     fonts is best fitted for using the normal draw shape command API where you
3656     do all the text drawing yourself and the library does not require any kind
3657     of deeper knowledge about which font handling mechanism you use.
3658     IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
3659     over the complete life time! I know this sucks but it is currently the only
3660     way to switch between fonts.
3661 
3662         float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
3663         {
3664             your_font_type *type = handle.ptr;
3665             float text_width = ...;
3666             return text_width;
3667         }
3668 
3669         struct nk_user_font font;
3670         font.userdata.ptr = &your_font_class_or_struct;
3671         font.height = your_font_height;
3672         font.width = your_text_width_calculation;
3673 
3674         struct nk_context ctx;
3675         nk_init_default(&ctx, &font);
3676 
3677     2.) Using your own implementation with vertex buffer output
3678     --------------------------------------------------------------
3679     While the first approach works fine if you don't want to use the optional
3680     vertex buffer output it is not enough if you do. To get font handling working
3681     for these cases you have to provide two additional parameters inside the
3682     `nk_user_font`. First a texture atlas handle used to draw text as subimages
3683     of a bigger font atlas texture and a callback to query a character's glyph
3684     information (offset, size, ...). So it is still possible to provide your own
3685     font and use the vertex buffer output.
3686 
3687         float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
3688         {
3689             your_font_type *type = handle.ptr;
3690             float text_width = ...;
3691             return text_width;
3692         }
3693         void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
3694         {
3695             your_font_type *type = handle.ptr;
3696             glyph.width = ...;
3697             glyph.height = ...;
3698             glyph.xadvance = ...;
3699             glyph.uv[0].x = ...;
3700             glyph.uv[0].y = ...;
3701             glyph.uv[1].x = ...;
3702             glyph.uv[1].y = ...;
3703             glyph.offset.x = ...;
3704             glyph.offset.y = ...;
3705         }
3706 
3707         struct nk_user_font font;
3708         font.userdata.ptr = &your_font_class_or_struct;
3709         font.height = your_font_height;
3710         font.width = your_text_width_calculation;
3711         font.query = query_your_font_glyph;
3712         font.texture.id = your_font_texture;
3713 
3714         struct nk_context ctx;
3715         nk_init_default(&ctx, &font);
3716 
3717     3.) Nuklear font baker
3718     ------------------------------------
3719     The final approach if you do not have a font handling functionality or don't
3720     want to use it in this library is by using the optional font baker.
3721     The font baker APIs can be used to create a font plus font atlas texture
3722     and can be used with or without the vertex buffer output.
3723 
3724     It still uses the `nk_user_font` struct and the two different approaches
3725     previously stated still work. The font baker is not located inside
3726     `nk_context` like all other systems since it can be understood as more of
3727     an extension to nuklear and does not really depend on any `nk_context` state.
3728 
3729     Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
3730     functions. If you don't care about memory just call the default version
3731     `nk_font_atlas_init_default` which will allocate all memory from the standard library.
3732     If you want to control memory allocation but you don't care if the allocated
3733     memory is temporary and therefore can be freed directly after the baking process
3734     is over or permanent you can call `nk_font_atlas_init`.
3735 
3736     After successfully initializing the font baker you can add Truetype(.ttf) fonts from
3737     different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
3738     functions. Adding font will permanently store each font, font config and ttf memory block(!)
3739     inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
3740     the font baker by for example adding additional fonts you can call
3741     `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
3742 
3743     As soon as you added all fonts you wanted you can now start the baking process
3744     for every selected glyph to image by calling `nk_font_atlas_bake`.
3745     The baking process returns image memory, width and height which can be used to
3746     either create your own image object or upload it to any graphics library.
3747     No matter which case you finally have to call `nk_font_atlas_end` which
3748     will free all temporary memory including the font atlas image so make sure
3749     you created our texture beforehand. `nk_font_atlas_end` requires a handle
3750     to your font texture or object and optionally fills a `struct nk_draw_null_texture`
3751     which can be used for the optional vertex output. If you don't want it just
3752     set the argument to `NULL`.
3753 
3754     At this point you are done and if you don't want to reuse the font atlas you
3755     can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
3756     memory. Finally if you don't use the font atlas and any of it's fonts anymore
3757     you need to call `nk_font_atlas_clear` to free all memory still being used.
3758 
3759         struct nk_font_atlas atlas;
3760         nk_font_atlas_init_default(&atlas);
3761         nk_font_atlas_begin(&atlas);
3762         nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
3763         nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
3764         const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
3765         nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
3766 
3767         struct nk_context ctx;
3768         nk_init_default(&ctx, &font->handle);
3769         while (1) {
3770 
3771         }
3772         nk_font_atlas_clear(&atlas);
3773 
3774     The font baker API is probably the most complex API inside this library and
3775     I would suggest reading some of my examples `example/` to get a grip on how
3776     to use the font atlas. There are a number of details I left out. For example
3777     how to merge fonts, configure a font with `nk_font_config` to use other languages,
3778     use another texture coordinate format and a lot more:
3779 
3780         struct nk_font_config cfg = nk_font_config(font_pixel_height);
3781         cfg.merge_mode = nk_false or nk_true;
3782         cfg.range = nk_font_korean_glyph_ranges();
3783         cfg.coord_type = NK_COORD_PIXEL;
3784         nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
3785 
3786 */
3787 struct nk_user_font_glyph;
3788 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
3789 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
3790                                     struct nk_user_font_glyph *glyph,
3791                                     nk_rune codepoint, nk_rune next_codepoint);
3792 
3793 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT)
3794 struct nk_user_font_glyph {
3795     struct nk_vec2 uv[2];
3796     /* texture coordinates */
3797     struct nk_vec2 offset;
3798     /* offset between top left and glyph */
3799     float width, height;
3800     /* size of the glyph  */
3801     float xadvance;
3802     /* offset to the next glyph */
3803 };
3804 #endif
3805 
3806 struct nk_user_font {
3807     nk_handle userdata;
3808     /* user provided font handle */
3809     float height;
3810     /* max height of the font */
3811     nk_text_width_f width;
3812     /* font string width in pixel callback */
3813 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3814     nk_query_font_glyph_f query;
3815     /* font glyph callback to query drawing info */
3816     nk_handle texture;
3817     /* texture handle to the used font atlas or texture */
3818 #endif
3819 };
3820 
3821 #ifdef NK_INCLUDE_FONT_BAKING
3822 enum nk_font_coord_type {
3823     NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
3824     NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
3825 };
3826 
3827 struct nk_font;
3828 struct nk_baked_font {
3829     float height;
3830     /* height of the font  */
3831     float ascent, descent;
3832     /* font glyphs ascent and descent  */
3833     nk_rune glyph_offset;
3834     /* glyph array offset inside the font glyph baking output array  */
3835     nk_rune glyph_count;
3836     /* number of glyphs of this font inside the glyph baking array output */
3837     const nk_rune *ranges;
3838     /* font codepoint ranges as pairs of (from/to) and 0 as last element */
3839 };
3840 
3841 struct nk_font_config {
3842     struct nk_font_config *next;
3843     /* NOTE: only used internally */
3844     void *ttf_blob;
3845     /* pointer to loaded TTF file memory block.
3846      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
3847     nk_size ttf_size;
3848     /* size of the loaded TTF file memory block
3849      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
3850 
3851     unsigned char ttf_data_owned_by_atlas;
3852     /* used inside font atlas: default to: 0*/
3853     unsigned char merge_mode;
3854     /* merges this font into the last font */
3855     unsigned char pixel_snap;
3856     /* align every character to pixel boundary (if true set oversample (1,1)) */
3857     unsigned char oversample_v, oversample_h;
3858     /* rasterize at hight quality for sub-pixel position */
3859     unsigned char padding[3];
3860 
3861     float size;
3862     /* baked pixel height of the font */
3863     enum nk_font_coord_type coord_type;
3864     /* texture coordinate format with either pixel or UV coordinates */
3865     struct nk_vec2 spacing;
3866     /* extra pixel spacing between glyphs  */
3867     const nk_rune *range;
3868     /* list of unicode ranges (2 values per range, zero terminated) */
3869     struct nk_baked_font *font;
3870     /* font to setup in the baking process: NOTE: not needed for font atlas */
3871     nk_rune fallback_glyph;
3872     /* fallback glyph to use if a given rune is not found */
3873     struct nk_font_config *n;
3874     struct nk_font_config *p;
3875 };
3876 
3877 struct nk_font_glyph {
3878     nk_rune codepoint;
3879     float xadvance;
3880     float x0, y0, x1, y1, w, h;
3881     float u0, v0, u1, v1;
3882 };
3883 
3884 struct nk_font {
3885     struct nk_font *next;
3886     struct nk_user_font handle;
3887     struct nk_baked_font info;
3888     float scale;
3889     struct nk_font_glyph *glyphs;
3890     const struct nk_font_glyph *fallback;
3891     nk_rune fallback_codepoint;
3892     nk_handle texture;
3893     struct nk_font_config *config;
3894 };
3895 
3896 enum nk_font_atlas_format {
3897     NK_FONT_ATLAS_ALPHA8,
3898     NK_FONT_ATLAS_RGBA32
3899 };
3900 
3901 struct nk_font_atlas {
3902     void *pixel;
3903     int tex_width;
3904     int tex_height;
3905 
3906     struct nk_allocator permanent;
3907     struct nk_allocator temporary;
3908 
3909     struct nk_recti custom;
3910     struct nk_cursor cursors[NK_CURSOR_COUNT];
3911 
3912     int glyph_count;
3913     struct nk_font_glyph *glyphs;
3914     struct nk_font *default_font;
3915     struct nk_font *fonts;
3916     struct nk_font_config *config;
3917     int font_num;
3918 };
3919 
3920 /* some language glyph codepoint ranges */
3921 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
3922 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
3923 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
3924 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
3925 
3926 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
3927 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
3928 #endif
3929 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
3930 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
3931 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
3932 NK_API struct nk_font_config nk_font_config(float pixel_height);
3933 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
3934 #ifdef NK_INCLUDE_DEFAULT_FONT
3935 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
3936 #endif
3937 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);
3938 #ifdef NK_INCLUDE_STANDARD_IO
3939 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*);
3940 #endif
3941 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*);
3942 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);
3943 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
3944 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
3945 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
3946 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
3947 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
3948 
3949 #endif
3950 
3951 /* ==============================================================
3952  *
3953  *                          MEMORY BUFFER
3954  *
3955  * ===============================================================*/
3956 /*  A basic (double)-buffer with linear allocation and resetting as only
3957     freeing policy. The buffer's main purpose is to control all memory management
3958     inside the GUI toolkit and still leave memory control as much as possible in
3959     the hand of the user while also making sure the library is easy to use if
3960     not as much control is needed.
3961     In general all memory inside this library can be provided from the user in
3962     three different ways.
3963 
3964     The first way and the one providing most control is by just passing a fixed
3965     size memory block. In this case all control lies in the hand of the user
3966     since he can exactly control where the memory comes from and how much memory
3967     the library should consume. Of course using the fixed size API removes the
3968     ability to automatically resize a buffer if not enough memory is provided so
3969     you have to take over the resizing. While being a fixed sized buffer sounds
3970     quite limiting, it is very effective in this library since the actual memory
3971     consumption is quite stable and has a fixed upper bound for a lot of cases.
3972 
3973     If you don't want to think about how much memory the library should allocate
3974     at all time or have a very dynamic UI with unpredictable memory consumption
3975     habits but still want control over memory allocation you can use the dynamic
3976     allocator based API. The allocator consists of two callbacks for allocating
3977     and freeing memory and optional userdata so you can plugin your own allocator.
3978 
3979     The final and easiest way can be used by defining
3980     NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
3981     allocation functions malloc and free and takes over complete control over
3982     memory in this library.
3983 */
3984 struct nk_memory_status {
3985     void *memory;
3986     unsigned int type;
3987     nk_size size;
3988     nk_size allocated;
3989     nk_size needed;
3990     nk_size calls;
3991 };
3992 
3993 enum nk_allocation_type {
3994     NK_BUFFER_FIXED,
3995     NK_BUFFER_DYNAMIC
3996 };
3997 
3998 enum nk_buffer_allocation_type {
3999     NK_BUFFER_FRONT,
4000     NK_BUFFER_BACK,
4001     NK_BUFFER_MAX
4002 };
4003 
4004 struct nk_buffer_marker {
4005     int active;
4006     nk_size offset;
4007 };
4008 
4009 struct nk_memory {void *ptr;nk_size size;};
4010 struct nk_buffer {
4011     struct nk_buffer_marker marker[NK_BUFFER_MAX];
4012     /* buffer marker to free a buffer to a certain offset */
4013     struct nk_allocator pool;
4014     /* allocator callback for dynamic buffers */
4015     enum nk_allocation_type type;
4016     /* memory management type */
4017     struct nk_memory memory;
4018     /* memory and size of the current memory block */
4019     float grow_factor;
4020     /* growing factor for dynamic memory management */
4021     nk_size allocated;
4022     /* total amount of memory allocated */
4023     nk_size needed;
4024     /* totally consumed memory given that enough memory is present */
4025     nk_size calls;
4026     /* number of allocation calls */
4027     nk_size size;
4028     /* current size of the buffer */
4029 };
4030 
4031 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4032 NK_API void nk_buffer_init_default(struct nk_buffer*);
4033 #endif
4034 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
4035 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
4036 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
4037 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
4038 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
4039 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type);
4040 NK_API void nk_buffer_clear(struct nk_buffer*);
4041 NK_API void nk_buffer_free(struct nk_buffer*);
4042 NK_API void *nk_buffer_memory(struct nk_buffer*);
4043 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
4044 NK_API nk_size nk_buffer_total(struct nk_buffer*);
4045 
4046 /* ==============================================================
4047  *
4048  *                          STRING
4049  *
4050  * ===============================================================*/
4051 /*  Basic string buffer which is only used in context with the text editor
4052  *  to manage and manipulate dynamic or fixed size string content. This is _NOT_
4053  *  the default string handling method. The only instance you should have any contact
4054  *  with this API is if you interact with an `nk_text_edit` object inside one of the
4055  *  copy and paste functions and even there only for more advanced cases. */
4056 struct nk_str {
4057     struct nk_buffer buffer;
4058     int len; /* in codepoints/runes/glyphs */
4059 };
4060 
4061 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4062 NK_API void nk_str_init_default(struct nk_str*);
4063 #endif
4064 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
4065 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
4066 NK_API void nk_str_clear(struct nk_str*);
4067 NK_API void nk_str_free(struct nk_str*);
4068 
4069 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
4070 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
4071 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
4072 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
4073 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
4074 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
4075 
4076 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
4077 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
4078 
4079 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
4080 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
4081 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
4082 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
4083 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
4084 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
4085 
4086 NK_API void nk_str_remove_chars(struct nk_str*, int len);
4087 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
4088 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
4089 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
4090 
4091 NK_API char *nk_str_at_char(struct nk_str*, int pos);
4092 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
4093 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
4094 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
4095 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
4096 
4097 NK_API char *nk_str_get(struct nk_str*);
4098 NK_API const char *nk_str_get_const(const struct nk_str*);
4099 NK_API int nk_str_len(struct nk_str*);
4100 NK_API int nk_str_len_char(struct nk_str*);
4101 
4102 /*===============================================================
4103  *
4104  *                      TEXT EDITOR
4105  *
4106  * ===============================================================*/
4107 /* Editing text in this library is handled by either `nk_edit_string` or
4108  * `nk_edit_buffer`. But like almost everything in this library there are multiple
4109  * ways of doing it and a balance between control and ease of use with memory
4110  * as well as functionality controlled by flags.
4111  *
4112  * This library generally allows three different levels of memory control:
4113  * First of is the most basic way of just providing a simple char array with
4114  * string length. This method is probably the easiest way of handling simple
4115  * user text input. Main upside is complete control over memory while the biggest
4116  * downside in comparison with the other two approaches is missing undo/redo.
4117  *
4118  * For UIs that require undo/redo the second way was created. It is based on
4119  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
4120  * This is mainly useful if you want something more like a text editor but don't want
4121  * to have a dynamically growing buffer.
4122  *
4123  * The final way is using a dynamically growing nk_text_edit struct, which
4124  * has both a default version if you don't care where memory comes from and an
4125  * allocator version if you do. While the text editor is quite powerful for its
4126  * complexity I would not recommend editing gigabytes of data with it.
4127  * It is rather designed for uses cases which make sense for a GUI library not for
4128  * an full blown text editor.
4129  */
4130 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
4131 #define NK_TEXTEDIT_UNDOSTATECOUNT     99
4132 #endif
4133 
4134 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
4135 #define NK_TEXTEDIT_UNDOCHARCOUNT      999
4136 #endif
4137 
4138 struct nk_text_edit;
4139 struct nk_clipboard {
4140     nk_handle userdata;
4141     nk_plugin_paste paste;
4142     nk_plugin_copy copy;
4143 };
4144 
4145 struct nk_text_undo_record {
4146    int where;
4147    short insert_length;
4148    short delete_length;
4149    short char_storage;
4150 };
4151 
4152 struct nk_text_undo_state {
4153    struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT];
4154    nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT];
4155    short undo_point;
4156    short redo_point;
4157    short undo_char_point;
4158    short redo_char_point;
4159 };
4160 
4161 enum nk_text_edit_type {
4162     NK_TEXT_EDIT_SINGLE_LINE,
4163     NK_TEXT_EDIT_MULTI_LINE
4164 };
4165 
4166 enum nk_text_edit_mode {
4167     NK_TEXT_EDIT_MODE_VIEW,
4168     NK_TEXT_EDIT_MODE_INSERT,
4169     NK_TEXT_EDIT_MODE_REPLACE
4170 };
4171 
4172 struct nk_token {
4173 	struct nk_color color;
4174 	int offset;
4175 };
4176 
4177 struct nk_lexer {
4178 	struct nk_token *tokens;
4179 	struct nk_token *(*lex)(void *data, const char *buf, int size);
4180 	void *data;
4181 	int needs_refresh;
4182 };
4183 
4184 struct nk_text_edit {
4185     struct nk_clipboard clip;
4186     struct nk_str string;
4187     nk_plugin_filter filter;
4188     struct nk_vec2 scrollbar;
4189 
4190     int cursor;
4191     int select_start;
4192     int select_end;
4193     unsigned char mode;
4194     unsigned char cursor_at_end_of_line;
4195     unsigned char initialized;
4196     unsigned char has_preferred_x;
4197     unsigned char single_line;
4198     unsigned char active;
4199     unsigned char padding1;
4200     float preferred_x;
4201     struct nk_text_undo_state undo;
4202 		struct nk_lexer lexer;
4203 };
4204 
4205 /* filter function */
4206 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
4207 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
4208 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
4209 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
4210 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
4211 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
4212 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
4213 
4214 /* text editor */
4215 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4216 NK_API void nk_textedit_init_default(struct nk_text_edit*);
4217 #endif
4218 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
4219 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
4220 NK_API void nk_textedit_free(struct nk_text_edit*);
4221 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
4222 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
4223 NK_API void nk_textedit_delete_selection(struct nk_text_edit*);
4224 NK_API void nk_textedit_select_all(struct nk_text_edit*);
4225 NK_API int nk_textedit_cut(struct nk_text_edit*);
4226 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
4227 NK_API void nk_textedit_undo(struct nk_text_edit*);
4228 NK_API void nk_textedit_redo(struct nk_text_edit*);
4229 
4230 /* ===============================================================
4231  *
4232  *                          DRAWING
4233  *
4234  * ===============================================================*/
4235 /*  This library was designed to be render backend agnostic so it does
4236     not draw anything to screen. Instead all drawn shapes, widgets
4237     are made of, are buffered into memory and make up a command queue.
4238     Each frame therefore fills the command buffer with draw commands
4239     that then need to be executed by the user and his own render backend.
4240     After that the command buffer needs to be cleared and a new frame can be
4241     started. It is probably important to note that the command buffer is the main
4242     drawing API and the optional vertex buffer API only takes this format and
4243     converts it into a hardware accessible format.
4244 
4245     To use the command queue to draw your own widgets you can access the
4246     command buffer of each window by calling `nk_window_get_canvas` after
4247     previously having called `nk_begin`:
4248 
4249         void draw_red_rectangle_widget(struct nk_context *ctx)
4250         {
4251             struct nk_command_buffer *canvas;
4252             struct nk_input *input = &ctx->input;
4253             canvas = nk_window_get_canvas(ctx);
4254 
4255             struct nk_rect space;
4256             enum nk_widget_layout_states state;
4257             state = nk_widget(&space, ctx);
4258             if (!state) return;
4259 
4260             if (state != NK_WIDGET_ROM)
4261                 update_your_widget_by_user_input(...);
4262             nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
4263         }
4264 
4265         if (nk_begin(...)) {
4266             nk_layout_row_dynamic(ctx, 25, 1);
4267             draw_red_rectangle_widget(ctx);
4268         }
4269         nk_end(..)
4270 
4271     Important to know if you want to create your own widgets is the `nk_widget`
4272     call. It allocates space on the panel reserved for this widget to be used,
4273     but also returns the state of the widget space. If your widget is not seen and does
4274     not have to be updated it is '0' and you can just return. If it only has
4275     to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
4276     update and draw your widget. The reason for separating is to only draw and
4277     update what is actually necessary which is crucial for performance.
4278 */
4279 enum nk_command_type {
4280     NK_COMMAND_NOP,
4281     NK_COMMAND_SCISSOR,
4282     NK_COMMAND_LINE,
4283     NK_COMMAND_CURVE,
4284     NK_COMMAND_RECT,
4285     NK_COMMAND_RECT_FILLED,
4286     NK_COMMAND_RECT_MULTI_COLOR,
4287     NK_COMMAND_CIRCLE,
4288     NK_COMMAND_CIRCLE_FILLED,
4289     NK_COMMAND_ARC,
4290     NK_COMMAND_ARC_FILLED,
4291     NK_COMMAND_TRIANGLE,
4292     NK_COMMAND_TRIANGLE_FILLED,
4293     NK_COMMAND_POLYGON,
4294     NK_COMMAND_POLYGON_FILLED,
4295     NK_COMMAND_POLYLINE,
4296     NK_COMMAND_TEXT,
4297     NK_COMMAND_IMAGE,
4298     NK_COMMAND_CUSTOM
4299 };
4300 
4301 /* command base and header of every command inside the buffer */
4302 struct nk_command {
4303     enum nk_command_type type;
4304     nk_size next;
4305 #ifdef NK_INCLUDE_COMMAND_USERDATA
4306     nk_handle userdata;
4307 #endif
4308 };
4309 
4310 struct nk_command_scissor {
4311     struct nk_command header;
4312     short x, y;
4313     unsigned short w, h;
4314 };
4315 
4316 struct nk_command_line {
4317     struct nk_command header;
4318     unsigned short line_thickness;
4319     struct nk_vec2i begin;
4320     struct nk_vec2i end;
4321     struct nk_color color;
4322 };
4323 
4324 struct nk_command_curve {
4325     struct nk_command header;
4326     unsigned short line_thickness;
4327     struct nk_vec2i begin;
4328     struct nk_vec2i end;
4329     struct nk_vec2i ctrl[2];
4330     struct nk_color color;
4331 };
4332 
4333 struct nk_command_rect {
4334     struct nk_command header;
4335     unsigned short rounding;
4336     unsigned short line_thickness;
4337     short x, y;
4338     unsigned short w, h;
4339     struct nk_color color;
4340 };
4341 
4342 struct nk_command_rect_filled {
4343     struct nk_command header;
4344     unsigned short rounding;
4345     short x, y;
4346     unsigned short w, h;
4347     struct nk_color color;
4348 };
4349 
4350 struct nk_command_rect_multi_color {
4351     struct nk_command header;
4352     short x, y;
4353     unsigned short w, h;
4354     struct nk_color left;
4355     struct nk_color top;
4356     struct nk_color bottom;
4357     struct nk_color right;
4358 };
4359 
4360 struct nk_command_triangle {
4361     struct nk_command header;
4362     unsigned short line_thickness;
4363     struct nk_vec2i a;
4364     struct nk_vec2i b;
4365     struct nk_vec2i c;
4366     struct nk_color color;
4367 };
4368 
4369 struct nk_command_triangle_filled {
4370     struct nk_command header;
4371     struct nk_vec2i a;
4372     struct nk_vec2i b;
4373     struct nk_vec2i c;
4374     struct nk_color color;
4375 };
4376 
4377 struct nk_command_circle {
4378     struct nk_command header;
4379     short x, y;
4380     unsigned short line_thickness;
4381     unsigned short w, h;
4382     struct nk_color color;
4383 };
4384 
4385 struct nk_command_circle_filled {
4386     struct nk_command header;
4387     short x, y;
4388     unsigned short w, h;
4389     struct nk_color color;
4390 };
4391 
4392 struct nk_command_arc {
4393     struct nk_command header;
4394     short cx, cy;
4395     unsigned short r;
4396     unsigned short line_thickness;
4397     float a[2];
4398     struct nk_color color;
4399 };
4400 
4401 struct nk_command_arc_filled {
4402     struct nk_command header;
4403     short cx, cy;
4404     unsigned short r;
4405     float a[2];
4406     struct nk_color color;
4407 };
4408 
4409 struct nk_command_polygon {
4410     struct nk_command header;
4411     struct nk_color color;
4412     unsigned short line_thickness;
4413     unsigned short point_count;
4414     struct nk_vec2i points[1];
4415 };
4416 
4417 struct nk_command_polygon_filled {
4418     struct nk_command header;
4419     struct nk_color color;
4420     unsigned short point_count;
4421     struct nk_vec2i points[1];
4422 };
4423 
4424 struct nk_command_polyline {
4425     struct nk_command header;
4426     struct nk_color color;
4427     unsigned short line_thickness;
4428     unsigned short point_count;
4429     struct nk_vec2i points[1];
4430 };
4431 
4432 struct nk_command_image {
4433     struct nk_command header;
4434     short x, y;
4435     unsigned short w, h;
4436     struct nk_image img;
4437     struct nk_color col;
4438 };
4439 
4440 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
4441     unsigned short w, unsigned short h, nk_handle callback_data);
4442 struct nk_command_custom {
4443     struct nk_command header;
4444     short x, y;
4445     unsigned short w, h;
4446     nk_handle callback_data;
4447     nk_command_custom_callback callback;
4448 };
4449 
4450 struct nk_command_text {
4451     struct nk_command header;
4452     const struct nk_user_font *font;
4453     struct nk_color background;
4454     struct nk_color foreground;
4455     short x, y;
4456     unsigned short w, h;
4457     float height;
4458     int length;
4459     char string[1];
4460 };
4461 
4462 enum nk_command_clipping {
4463     NK_CLIPPING_OFF = nk_false,
4464     NK_CLIPPING_ON = nk_true
4465 };
4466 
4467 struct nk_command_buffer {
4468     struct nk_buffer *base;
4469     struct nk_rect clip;
4470     int use_clipping;
4471     nk_handle userdata;
4472     nk_size begin, end, last;
4473 };
4474 
4475 /* shape outlines */
4476 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);
4477 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
4478 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
4479 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
4480 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);
4481 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
4482 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
4483 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
4484 
4485 /* filled shades */
4486 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
4487 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);
4488 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
4489 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);
4490 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);
4491 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
4492 
4493 /* misc */
4494 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
4495 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);
4496 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
4497 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
4498 
4499 /* ===============================================================
4500  *
4501  *                          INPUT
4502  *
4503  * ===============================================================*/
4504 struct nk_mouse_button {
4505     int down;
4506     unsigned int clicked;
4507     struct nk_vec2 clicked_pos;
4508 };
4509 struct nk_mouse {
4510     struct nk_mouse_button buttons[NK_BUTTON_MAX];
4511     struct nk_vec2 pos;
4512     struct nk_vec2 prev;
4513     struct nk_vec2 delta;
4514     struct nk_vec2 scroll_delta;
4515     unsigned char grab;
4516     unsigned char grabbed;
4517     unsigned char ungrab;
4518 };
4519 
4520 struct nk_key {
4521     int down;
4522     unsigned int clicked;
4523 };
4524 struct nk_keyboard {
4525     struct nk_key keys[NK_KEY_MAX];
4526     char text[NK_INPUT_MAX];
4527     int text_len;
4528 };
4529 
4530 struct nk_input {
4531     struct nk_keyboard keyboard;
4532     struct nk_mouse mouse;
4533 };
4534 
4535 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
4536 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4537 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
4538 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4539 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);
4540 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
4541 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
4542 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
4543 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
4544 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
4545 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
4546 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
4547 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
4548 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
4549 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
4550 
4551 /* ===============================================================
4552  *
4553  *                          DRAW LIST
4554  *
4555  * ===============================================================*/
4556 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4557 /*  The optional vertex buffer draw list provides a 2D drawing context
4558     with antialiasing functionality which takes basic filled or outlined shapes
4559     or a path and outputs vertexes, elements and draw commands.
4560     The actual draw list API is not required to be used directly while using this
4561     library since converting the default library draw command output is done by
4562     just calling `nk_convert` but I decided to still make this library accessible
4563     since it can be useful.
4564 
4565     The draw list is based on a path buffering and polygon and polyline
4566     rendering API which allows a lot of ways to draw 2D content to screen.
4567     In fact it is probably more powerful than needed but allows even more crazy
4568     things than this library provides by default.
4569 */
4570 typedef nk_ushort nk_draw_index;
4571 enum nk_draw_list_stroke {
4572     NK_STROKE_OPEN = nk_false,
4573     /* build up path has no connection back to the beginning */
4574     NK_STROKE_CLOSED = nk_true
4575     /* build up path has a connection back to the beginning */
4576 };
4577 
4578 enum nk_draw_vertex_layout_attribute {
4579     NK_VERTEX_POSITION,
4580     NK_VERTEX_COLOR,
4581     NK_VERTEX_TEXCOORD,
4582     NK_VERTEX_ATTRIBUTE_COUNT
4583 };
4584 
4585 enum nk_draw_vertex_layout_format {
4586     NK_FORMAT_SCHAR,
4587     NK_FORMAT_SSHORT,
4588     NK_FORMAT_SINT,
4589     NK_FORMAT_UCHAR,
4590     NK_FORMAT_USHORT,
4591     NK_FORMAT_UINT,
4592     NK_FORMAT_FLOAT,
4593     NK_FORMAT_DOUBLE,
4594 
4595 NK_FORMAT_COLOR_BEGIN,
4596     NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
4597     NK_FORMAT_R16G15B16,
4598     NK_FORMAT_R32G32B32,
4599 
4600     NK_FORMAT_R8G8B8A8,
4601     NK_FORMAT_B8G8R8A8,
4602     NK_FORMAT_R16G15B16A16,
4603     NK_FORMAT_R32G32B32A32,
4604     NK_FORMAT_R32G32B32A32_FLOAT,
4605     NK_FORMAT_R32G32B32A32_DOUBLE,
4606 
4607     NK_FORMAT_RGB32,
4608     NK_FORMAT_RGBA32,
4609 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
4610     NK_FORMAT_COUNT
4611 };
4612 
4613 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
4614 struct nk_draw_vertex_layout_element {
4615     enum nk_draw_vertex_layout_attribute attribute;
4616     enum nk_draw_vertex_layout_format format;
4617     nk_size offset;
4618 };
4619 
4620 struct nk_draw_command {
4621     unsigned int elem_count;
4622     /* number of elements in the current draw batch */
4623     struct nk_rect clip_rect;
4624     /* current screen clipping rectangle */
4625     nk_handle texture;
4626     /* current texture to set */
4627 #ifdef NK_INCLUDE_COMMAND_USERDATA
4628     nk_handle userdata;
4629 #endif
4630 };
4631 
4632 struct nk_draw_list {
4633     struct nk_rect clip_rect;
4634     struct nk_vec2 circle_vtx[12];
4635     struct nk_convert_config config;
4636 
4637     struct nk_buffer *buffer;
4638     struct nk_buffer *vertices;
4639     struct nk_buffer *elements;
4640 
4641     unsigned int element_count;
4642     unsigned int vertex_count;
4643     unsigned int cmd_count;
4644     nk_size cmd_offset;
4645 
4646     unsigned int path_count;
4647     unsigned int path_offset;
4648 
4649     enum nk_anti_aliasing line_AA;
4650     enum nk_anti_aliasing shape_AA;
4651 
4652 #ifdef NK_INCLUDE_COMMAND_USERDATA
4653     nk_handle userdata;
4654 #endif
4655 };
4656 
4657 /* draw list */
4658 NK_API void nk_draw_list_init(struct nk_draw_list*);
4659 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);
4660 NK_API void nk_draw_list_clear(struct nk_draw_list*);
4661 
4662 /* drawing */
4663 #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))
4664 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
4665 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*);
4666 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
4667 
4668 /* path */
4669 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
4670 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
4671 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);
4672 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);
4673 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
4674 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);
4675 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
4676 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
4677 
4678 /* stroke */
4679 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);
4680 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
4681 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);
4682 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);
4683 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);
4684 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);
4685 
4686 /* fill */
4687 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
4688 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);
4689 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);
4690 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);
4691 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);
4692 
4693 /* misc */
4694 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
4695 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);
4696 #ifdef NK_INCLUDE_COMMAND_USERDATA
4697 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
4698 #endif
4699 
4700 #endif
4701 
4702 /* ===============================================================
4703  *
4704  *                          GUI
4705  *
4706  * ===============================================================*/
4707 enum nk_style_item_type {
4708     NK_STYLE_ITEM_COLOR,
4709     NK_STYLE_ITEM_IMAGE
4710 };
4711 
4712 union nk_style_item_data {
4713     struct nk_image image;
4714     struct nk_color color;
4715 };
4716 
4717 struct nk_style_item {
4718     enum nk_style_item_type type;
4719     union nk_style_item_data data;
4720 };
4721 
4722 struct nk_style_text {
4723     struct nk_color color;
4724     struct nk_vec2 padding;
4725 };
4726 
4727 struct nk_style_button {
4728     /* background */
4729     struct nk_style_item normal;
4730     struct nk_style_item hover;
4731     struct nk_style_item active;
4732     struct nk_color border_color;
4733 
4734     /* text */
4735     struct nk_color text_background;
4736     struct nk_color text_normal;
4737     struct nk_color text_hover;
4738     struct nk_color text_active;
4739     nk_flags text_alignment;
4740 
4741     /* properties */
4742     float border;
4743     float rounding;
4744     struct nk_vec2 padding;
4745     struct nk_vec2 image_padding;
4746     struct nk_vec2 touch_padding;
4747 
4748     /* optional user callbacks */
4749     nk_handle userdata;
4750     void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata);
4751     void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
4752 };
4753 
4754 struct nk_style_toggle {
4755     /* background */
4756     struct nk_style_item normal;
4757     struct nk_style_item hover;
4758     struct nk_style_item active;
4759     struct nk_color border_color;
4760 
4761     /* cursor */
4762     struct nk_style_item cursor_normal;
4763     struct nk_style_item cursor_hover;
4764 
4765     /* text */
4766     struct nk_color text_normal;
4767     struct nk_color text_hover;
4768     struct nk_color text_active;
4769     struct nk_color text_background;
4770     nk_flags text_alignment;
4771 
4772     /* properties */
4773     struct nk_vec2 padding;
4774     struct nk_vec2 touch_padding;
4775     float spacing;
4776     float border;
4777 
4778     /* optional user callbacks */
4779     nk_handle userdata;
4780     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4781     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4782 };
4783 
4784 struct nk_style_selectable {
4785     /* background (inactive) */
4786     struct nk_style_item normal;
4787     struct nk_style_item hover;
4788     struct nk_style_item pressed;
4789 
4790     /* background (active) */
4791     struct nk_style_item normal_active;
4792     struct nk_style_item hover_active;
4793     struct nk_style_item pressed_active;
4794 
4795     /* text color (inactive) */
4796     struct nk_color text_normal;
4797     struct nk_color text_hover;
4798     struct nk_color text_pressed;
4799 
4800     /* text color (active) */
4801     struct nk_color text_normal_active;
4802     struct nk_color text_hover_active;
4803     struct nk_color text_pressed_active;
4804     struct nk_color text_background;
4805     nk_flags text_alignment;
4806 
4807     /* properties */
4808     float rounding;
4809     struct nk_vec2 padding;
4810     struct nk_vec2 touch_padding;
4811     struct nk_vec2 image_padding;
4812 
4813     /* optional user callbacks */
4814     nk_handle userdata;
4815     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4816     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4817 };
4818 
4819 struct nk_style_slider {
4820     /* background */
4821     struct nk_style_item normal;
4822     struct nk_style_item hover;
4823     struct nk_style_item active;
4824     struct nk_color border_color;
4825 
4826     /* background bar */
4827     struct nk_color bar_normal;
4828     struct nk_color bar_hover;
4829     struct nk_color bar_active;
4830     struct nk_color bar_filled;
4831 
4832     /* cursor */
4833     struct nk_style_item cursor_normal;
4834     struct nk_style_item cursor_hover;
4835     struct nk_style_item cursor_active;
4836 
4837     /* properties */
4838     float border;
4839     float rounding;
4840     float bar_height;
4841     struct nk_vec2 padding;
4842     struct nk_vec2 spacing;
4843     struct nk_vec2 cursor_size;
4844 
4845     /* optional buttons */
4846     int show_buttons;
4847     struct nk_style_button inc_button;
4848     struct nk_style_button dec_button;
4849     enum nk_symbol_type inc_symbol;
4850     enum nk_symbol_type dec_symbol;
4851 
4852     /* optional user callbacks */
4853     nk_handle userdata;
4854     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4855     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4856 };
4857 
4858 struct nk_style_progress {
4859     /* background */
4860     struct nk_style_item normal;
4861     struct nk_style_item hover;
4862     struct nk_style_item active;
4863     struct nk_color border_color;
4864 
4865     /* cursor */
4866     struct nk_style_item cursor_normal;
4867     struct nk_style_item cursor_hover;
4868     struct nk_style_item cursor_active;
4869     struct nk_color cursor_border_color;
4870 
4871     /* properties */
4872     float rounding;
4873     float border;
4874     float cursor_border;
4875     float cursor_rounding;
4876     struct nk_vec2 padding;
4877 
4878     /* optional user callbacks */
4879     nk_handle userdata;
4880     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4881     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4882 };
4883 
4884 struct nk_style_scrollbar {
4885     /* background */
4886     struct nk_style_item normal;
4887     struct nk_style_item hover;
4888     struct nk_style_item active;
4889     struct nk_color border_color;
4890 
4891     /* cursor */
4892     struct nk_style_item cursor_normal;
4893     struct nk_style_item cursor_hover;
4894     struct nk_style_item cursor_active;
4895     struct nk_color cursor_border_color;
4896 
4897     /* properties */
4898     float border;
4899     float rounding;
4900     float border_cursor;
4901     float rounding_cursor;
4902     struct nk_vec2 padding;
4903 
4904     /* optional buttons */
4905     int show_buttons;
4906     struct nk_style_button inc_button;
4907     struct nk_style_button dec_button;
4908     enum nk_symbol_type inc_symbol;
4909     enum nk_symbol_type dec_symbol;
4910 
4911     /* optional user callbacks */
4912     nk_handle userdata;
4913     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4914     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4915 };
4916 
4917 struct nk_style_edit {
4918     /* background */
4919     struct nk_style_item normal;
4920     struct nk_style_item hover;
4921     struct nk_style_item active;
4922     struct nk_color border_color;
4923     struct nk_style_scrollbar scrollbar;
4924 
4925     /* cursor  */
4926     struct nk_color cursor_normal;
4927     struct nk_color cursor_hover;
4928     struct nk_color cursor_text_normal;
4929     struct nk_color cursor_text_hover;
4930 
4931     /* text (unselected) */
4932     struct nk_color text_normal;
4933     struct nk_color text_hover;
4934     struct nk_color text_active;
4935 
4936     /* text (selected) */
4937     struct nk_color selected_normal;
4938     struct nk_color selected_hover;
4939     struct nk_color selected_text_normal;
4940     struct nk_color selected_text_hover;
4941 
4942     /* properties */
4943     float border;
4944     float rounding;
4945     float cursor_size;
4946     struct nk_vec2 scrollbar_size;
4947     struct nk_vec2 padding;
4948     float row_padding;
4949 };
4950 
4951 struct nk_style_property {
4952     /* background */
4953     struct nk_style_item normal;
4954     struct nk_style_item hover;
4955     struct nk_style_item active;
4956     struct nk_color border_color;
4957 
4958     /* text */
4959     struct nk_color label_normal;
4960     struct nk_color label_hover;
4961     struct nk_color label_active;
4962 
4963     /* symbols */
4964     enum nk_symbol_type sym_left;
4965     enum nk_symbol_type sym_right;
4966 
4967     /* properties */
4968     float border;
4969     float rounding;
4970     struct nk_vec2 padding;
4971 
4972     struct nk_style_edit edit;
4973     struct nk_style_button inc_button;
4974     struct nk_style_button dec_button;
4975 
4976     /* optional user callbacks */
4977     nk_handle userdata;
4978     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4979     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4980 };
4981 
4982 struct nk_style_chart {
4983     /* colors */
4984     struct nk_style_item background;
4985     struct nk_color border_color;
4986     struct nk_color selected_color;
4987     struct nk_color color;
4988 
4989     /* properties */
4990     float border;
4991     float rounding;
4992     struct nk_vec2 padding;
4993 };
4994 
4995 struct nk_style_combo {
4996     /* background */
4997     struct nk_style_item normal;
4998     struct nk_style_item hover;
4999     struct nk_style_item active;
5000     struct nk_color border_color;
5001 
5002     /* label */
5003     struct nk_color label_normal;
5004     struct nk_color label_hover;
5005     struct nk_color label_active;
5006 
5007     /* symbol */
5008     struct nk_color symbol_normal;
5009     struct nk_color symbol_hover;
5010     struct nk_color symbol_active;
5011 
5012     /* button */
5013     struct nk_style_button button;
5014     enum nk_symbol_type sym_normal;
5015     enum nk_symbol_type sym_hover;
5016     enum nk_symbol_type sym_active;
5017 
5018     /* properties */
5019     float border;
5020     float rounding;
5021     struct nk_vec2 content_padding;
5022     struct nk_vec2 button_padding;
5023     struct nk_vec2 spacing;
5024 };
5025 
5026 struct nk_style_tab {
5027     /* background */
5028     struct nk_style_item background;
5029     struct nk_color border_color;
5030     struct nk_color text;
5031 
5032     /* button */
5033     struct nk_style_button tab_maximize_button;
5034     struct nk_style_button tab_minimize_button;
5035     struct nk_style_button node_maximize_button;
5036     struct nk_style_button node_minimize_button;
5037     enum nk_symbol_type sym_minimize;
5038     enum nk_symbol_type sym_maximize;
5039 
5040     /* properties */
5041     float border;
5042     float rounding;
5043     float indent;
5044     struct nk_vec2 padding;
5045     struct nk_vec2 spacing;
5046 };
5047 
5048 enum nk_style_header_align {
5049     NK_HEADER_LEFT,
5050     NK_HEADER_RIGHT
5051 };
5052 struct nk_style_window_header {
5053     /* background */
5054     struct nk_style_item normal;
5055     struct nk_style_item hover;
5056     struct nk_style_item active;
5057 
5058     /* button */
5059     struct nk_style_button close_button;
5060     struct nk_style_button minimize_button;
5061     enum nk_symbol_type close_symbol;
5062     enum nk_symbol_type minimize_symbol;
5063     enum nk_symbol_type maximize_symbol;
5064 
5065     /* title */
5066     struct nk_color label_normal;
5067     struct nk_color label_hover;
5068     struct nk_color label_active;
5069 
5070     /* properties */
5071     enum nk_style_header_align align;
5072     struct nk_vec2 padding;
5073     struct nk_vec2 label_padding;
5074     struct nk_vec2 spacing;
5075 };
5076 
5077 struct nk_style_window {
5078     struct nk_style_window_header header;
5079     struct nk_style_item fixed_background;
5080     struct nk_color background;
5081 
5082     struct nk_color border_color;
5083     struct nk_color popup_border_color;
5084     struct nk_color combo_border_color;
5085     struct nk_color contextual_border_color;
5086     struct nk_color menu_border_color;
5087     struct nk_color group_border_color;
5088     struct nk_color tooltip_border_color;
5089     struct nk_style_item scaler;
5090 
5091     float border;
5092     float combo_border;
5093     float contextual_border;
5094     float menu_border;
5095     float group_border;
5096     float tooltip_border;
5097     float popup_border;
5098     float min_row_height_padding;
5099 
5100     float rounding;
5101     struct nk_vec2 spacing;
5102     struct nk_vec2 scrollbar_size;
5103     struct nk_vec2 min_size;
5104 
5105     struct nk_vec2 padding;
5106     struct nk_vec2 group_padding;
5107     struct nk_vec2 popup_padding;
5108     struct nk_vec2 combo_padding;
5109     struct nk_vec2 contextual_padding;
5110     struct nk_vec2 menu_padding;
5111     struct nk_vec2 tooltip_padding;
5112 };
5113 
5114 struct nk_style {
5115     const struct nk_user_font *font;
5116     const struct nk_cursor *cursors[NK_CURSOR_COUNT];
5117     const struct nk_cursor *cursor_active;
5118     struct nk_cursor *cursor_last;
5119     int cursor_visible;
5120 
5121     struct nk_style_text text;
5122     struct nk_style_button button;
5123     struct nk_style_button contextual_button;
5124     struct nk_style_button menu_button;
5125     struct nk_style_toggle option;
5126     struct nk_style_toggle checkbox;
5127     struct nk_style_selectable selectable;
5128     struct nk_style_slider slider;
5129     struct nk_style_progress progress;
5130     struct nk_style_property property;
5131     struct nk_style_edit edit;
5132     struct nk_style_chart chart;
5133     struct nk_style_scrollbar scrollh;
5134     struct nk_style_scrollbar scrollv;
5135     struct nk_style_tab tab;
5136     struct nk_style_combo combo;
5137     struct nk_style_window window;
5138 };
5139 
5140 NK_API struct nk_style_item nk_style_item_image(struct nk_image img);
5141 NK_API struct nk_style_item nk_style_item_color(struct nk_color);
5142 NK_API struct nk_style_item nk_style_item_hide(void);
5143 
5144 /*==============================================================
5145  *                          PANEL
5146  * =============================================================*/
5147 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
5148 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
5149 #endif
5150 #ifndef NK_CHART_MAX_SLOT
5151 #define NK_CHART_MAX_SLOT 4
5152 #endif
5153 
5154 enum nk_panel_type {
5155     NK_PANEL_WINDOW     = NK_FLAG(0),
5156     NK_PANEL_GROUP      = NK_FLAG(1),
5157     NK_PANEL_POPUP      = NK_FLAG(2),
5158     NK_PANEL_CONTEXTUAL = NK_FLAG(4),
5159     NK_PANEL_COMBO      = NK_FLAG(5),
5160     NK_PANEL_MENU       = NK_FLAG(6),
5161     NK_PANEL_TOOLTIP    = NK_FLAG(7)
5162 };
5163 enum nk_panel_set {
5164     NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP,
5165     NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP,
5166     NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP
5167 };
5168 
5169 struct nk_chart_slot {
5170     enum nk_chart_type type;
5171     struct nk_color color;
5172     struct nk_color highlight;
5173     float min, max, range;
5174     int count;
5175     struct nk_vec2 last;
5176     int index;
5177 };
5178 
5179 struct nk_chart {
5180     int slot;
5181     float x, y, w, h;
5182     struct nk_chart_slot slots[NK_CHART_MAX_SLOT];
5183 };
5184 
5185 enum nk_panel_row_layout_type {
5186     NK_LAYOUT_DYNAMIC_FIXED = 0,
5187     NK_LAYOUT_DYNAMIC_ROW,
5188     NK_LAYOUT_DYNAMIC_FREE,
5189     NK_LAYOUT_DYNAMIC,
5190     NK_LAYOUT_STATIC_FIXED,
5191     NK_LAYOUT_STATIC_ROW,
5192     NK_LAYOUT_STATIC_FREE,
5193     NK_LAYOUT_STATIC,
5194     NK_LAYOUT_TEMPLATE,
5195     NK_LAYOUT_COUNT
5196 };
5197 struct nk_row_layout {
5198     enum nk_panel_row_layout_type type;
5199     int index;
5200     float height;
5201     float min_height;
5202     int columns;
5203     const float *ratio;
5204     float item_width;
5205     float item_height;
5206     float item_offset;
5207     float filled;
5208     struct nk_rect item;
5209     int tree_depth;
5210     float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS];
5211 };
5212 
5213 struct nk_popup_buffer {
5214     nk_size begin;
5215     nk_size parent;
5216     nk_size last;
5217     nk_size end;
5218     int active;
5219 };
5220 
5221 struct nk_menu_state {
5222     float x, y, w, h;
5223     struct nk_scroll offset;
5224 };
5225 
5226 struct nk_panel {
5227     enum nk_panel_type type;
5228     nk_flags flags;
5229     struct nk_rect bounds;
5230     nk_uint *offset_x;
5231     nk_uint *offset_y;
5232     float at_x, at_y, max_x;
5233     float footer_height;
5234     float header_height;
5235     float border;
5236     unsigned int has_scrolling;
5237     struct nk_rect clip;
5238     struct nk_menu_state menu;
5239     struct nk_row_layout row;
5240     struct nk_chart chart;
5241     struct nk_command_buffer *buffer;
5242     struct nk_panel *parent;
5243 };
5244 
5245 /*==============================================================
5246  *                          WINDOW
5247  * =============================================================*/
5248 #ifndef NK_WINDOW_MAX_NAME
5249 #define NK_WINDOW_MAX_NAME 64
5250 #endif
5251 
5252 struct nk_table;
5253 enum nk_window_flags {
5254     NK_WINDOW_PRIVATE       = NK_FLAG(11),
5255     NK_WINDOW_DYNAMIC       = NK_WINDOW_PRIVATE,
5256     /* special window type growing up in height while being filled to a certain maximum height */
5257     NK_WINDOW_ROM           = NK_FLAG(12),
5258     /* sets window widgets into a read only mode and does not allow input changes */
5259     NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT,
5260     /* prevents all interaction caused by input to either window or widgets inside */
5261     NK_WINDOW_HIDDEN        = NK_FLAG(13),
5262     /* Hides window and stops any window interaction and drawing */
5263     NK_WINDOW_CLOSED        = NK_FLAG(14),
5264     /* Directly closes and frees the window at the end of the frame */
5265     NK_WINDOW_MINIMIZED     = NK_FLAG(15),
5266     /* marks the window as minimized */
5267     NK_WINDOW_REMOVE_ROM    = NK_FLAG(16)
5268     /* Removes read only mode at the end of the window */
5269 };
5270 
5271 struct nk_popup_state {
5272     struct nk_window *win;
5273     enum nk_panel_type type;
5274     struct nk_popup_buffer buf;
5275     nk_hash name;
5276     int active;
5277     unsigned combo_count;
5278     unsigned con_count, con_old;
5279     unsigned active_con;
5280     struct nk_rect header;
5281 };
5282 
5283 struct nk_edit_state {
5284     nk_hash name;
5285     unsigned int seq;
5286     unsigned int old;
5287     int active, prev;
5288     int cursor;
5289     int sel_start;
5290     int sel_end;
5291     struct nk_scroll scrollbar;
5292     unsigned char mode;
5293     unsigned char single_line;
5294 };
5295 
5296 struct nk_property_state {
5297     int active, prev;
5298     char buffer[NK_MAX_NUMBER_BUFFER];
5299     int length;
5300     int cursor;
5301     int select_start;
5302     int select_end;
5303     nk_hash name;
5304     unsigned int seq;
5305     unsigned int old;
5306     int state;
5307 };
5308 
5309 struct nk_window {
5310     unsigned int seq;
5311     nk_hash name;
5312     char name_string[NK_WINDOW_MAX_NAME];
5313     nk_flags flags;
5314 
5315     struct nk_rect bounds;
5316     struct nk_scroll scrollbar;
5317     struct nk_command_buffer buffer;
5318     struct nk_panel *layout;
5319     float scrollbar_hiding_timer;
5320 
5321     /* persistent widget state */
5322     struct nk_property_state property;
5323     struct nk_popup_state popup;
5324     struct nk_edit_state edit;
5325     unsigned int scrolled;
5326 
5327     struct nk_table *tables;
5328     unsigned int table_count;
5329 
5330     /* window list hooks */
5331     struct nk_window *next;
5332     struct nk_window *prev;
5333     struct nk_window *parent;
5334 };
5335 
5336 /*==============================================================
5337  *                          STACK
5338  * =============================================================*/
5339 /* The style modifier stack can be used to temporarily change a
5340  * property inside `nk_style`. For example if you want a special
5341  * red button you can temporarily push the old button color onto a stack
5342  * draw the button with a red color and then you just pop the old color
5343  * back from the stack:
5344  *
5345  *      nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
5346  *      nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
5347  *      nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
5348  *      nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
5349  *
5350  *      nk_button(...);
5351  *
5352  *      nk_style_pop_style_item(ctx);
5353  *      nk_style_pop_style_item(ctx);
5354  *      nk_style_pop_style_item(ctx);
5355  *      nk_style_pop_vec2(ctx);
5356  *
5357  * Nuklear has a stack for style_items, float properties, vector properties,
5358  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
5359  * which can be changed at compile time.
5360  */
5361 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
5362 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
5363 #endif
5364 
5365 #ifndef NK_FONT_STACK_SIZE
5366 #define NK_FONT_STACK_SIZE 8
5367 #endif
5368 
5369 #ifndef NK_STYLE_ITEM_STACK_SIZE
5370 #define NK_STYLE_ITEM_STACK_SIZE 16
5371 #endif
5372 
5373 #ifndef NK_FLOAT_STACK_SIZE
5374 #define NK_FLOAT_STACK_SIZE 32
5375 #endif
5376 
5377 #ifndef NK_VECTOR_STACK_SIZE
5378 #define NK_VECTOR_STACK_SIZE 16
5379 #endif
5380 
5381 #ifndef NK_FLAGS_STACK_SIZE
5382 #define NK_FLAGS_STACK_SIZE 32
5383 #endif
5384 
5385 #ifndef NK_COLOR_STACK_SIZE
5386 #define NK_COLOR_STACK_SIZE 32
5387 #endif
5388 
5389 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
5390     struct nk_config_stack_##name##_element {\
5391         prefix##_##type *address;\
5392         prefix##_##type old_value;\
5393     }
5394 #define NK_CONFIG_STACK(type,size)\
5395     struct nk_config_stack_##type {\
5396         int head;\
5397         struct nk_config_stack_##type##_element elements[size];\
5398     }
5399 
5400 #define nk_float float
5401 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
5402 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
5403 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
5404 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags);
5405 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
5406 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
5407 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
5408 
5409 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE);
5410 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE);
5411 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE);
5412 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE);
5413 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE);
5414 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE);
5415 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE);
5416 
5417 struct nk_configuration_stacks {
5418     struct nk_config_stack_style_item style_items;
5419     struct nk_config_stack_float floats;
5420     struct nk_config_stack_vec2 vectors;
5421     struct nk_config_stack_flags flags;
5422     struct nk_config_stack_color colors;
5423     struct nk_config_stack_user_font fonts;
5424     struct nk_config_stack_button_behavior button_behaviors;
5425 };
5426 
5427 /*==============================================================
5428  *                          CONTEXT
5429  * =============================================================*/
5430 #define NK_VALUE_PAGE_CAPACITY \
5431     (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
5432 
5433 struct nk_table {
5434     unsigned int seq;
5435     unsigned int size;
5436     nk_hash keys[NK_VALUE_PAGE_CAPACITY];
5437     nk_uint values[NK_VALUE_PAGE_CAPACITY];
5438     struct nk_table *next, *prev;
5439 };
5440 
5441 union nk_page_data {
5442     struct nk_table tbl;
5443     struct nk_panel pan;
5444     struct nk_window win;
5445 };
5446 
5447 struct nk_page_element {
5448     union nk_page_data data;
5449     struct nk_page_element *next;
5450     struct nk_page_element *prev;
5451 };
5452 
5453 struct nk_page {
5454     unsigned int size;
5455     struct nk_page *next;
5456     struct nk_page_element win[1];
5457 };
5458 
5459 struct nk_pool {
5460     struct nk_allocator alloc;
5461     enum nk_allocation_type type;
5462     unsigned int page_count;
5463     struct nk_page *pages;
5464     struct nk_page_element *freelist;
5465     unsigned capacity;
5466     nk_size size;
5467     nk_size cap;
5468 };
5469 
5470 struct nk_context {
5471 /* public: can be accessed freely */
5472     struct nk_input input;
5473     struct nk_style style;
5474     struct nk_buffer memory;
5475     struct nk_clipboard clip;
5476     nk_flags last_widget_state;
5477     enum nk_button_behavior button_behavior;
5478     struct nk_configuration_stacks stacks;
5479     float delta_time_seconds;
5480 
5481 /* private:
5482     should only be accessed if you
5483     know what you are doing */
5484 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
5485     struct nk_draw_list draw_list;
5486 #endif
5487 #ifdef NK_INCLUDE_COMMAND_USERDATA
5488     nk_handle userdata;
5489 #endif
5490     /* text editor objects are quite big because of an internal
5491      * undo/redo stack. Therefore it does not make sense to have one for
5492      * each window for temporary use cases, so I only provide *one* instance
5493      * for all windows. This works because the content is cleared anyway */
5494     struct nk_text_edit text_edit;
5495     /* draw buffer used for overlay drawing operation like cursor */
5496     struct nk_command_buffer overlay;
5497 
5498     /* windows */
5499     int build;
5500     int use_pool;
5501     struct nk_pool pool;
5502     struct nk_window *begin;
5503     struct nk_window *end;
5504     struct nk_window *active;
5505     struct nk_window *current;
5506     struct nk_page_element *freelist;
5507     unsigned int count;
5508     unsigned int seq;
5509 };
5510 
5511 /* ==============================================================
5512  *                          MATH
5513  * =============================================================== */
5514 #define NK_PI 3.141592654f
5515 #define NK_UTF_INVALID 0xFFFD
5516 #define NK_MAX_FLOAT_PRECISION 2
5517 
5518 #define NK_UNUSED(x) ((void)(x))
5519 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
5520 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
5521 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
5522 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
5523 #define NK_INBOX(px, py, x, y, w, h)\
5524     (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
5525 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
5526     (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
5527 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
5528     (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
5529 
5530 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
5531 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
5532 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
5533 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
5534 
5535 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
5536 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
5537 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
5538 
5539 /* ==============================================================
5540  *                          ALIGNMENT
5541  * =============================================================== */
5542 /* Pointer to Integer type conversion for pointer alignment */
5543 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
5544 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
5545 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
5546 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
5547 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
5548 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
5549 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
5550 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
5551 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
5552 #else /* generates warning but works */
5553 # define NK_UINT_TO_PTR(x) ((void*)(x))
5554 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
5555 #endif
5556 
5557 #define NK_ALIGN_PTR(x, mask)\
5558     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
5559 #define NK_ALIGN_PTR_BACK(x, mask)\
5560     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
5561 
5562 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
5563 #define NK_CONTAINER_OF(ptr,type,member)\
5564     (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
5565 
5566 #ifdef __cplusplus
5567 }
5568 #endif
5569 
5570 #ifdef __cplusplus
5571 template<typename T> struct nk_alignof;
5572 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
5573 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
5574 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
5575     diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
5576 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
5577 #elif defined(_MSC_VER)
5578 #define NK_ALIGNOF(t) (__alignof(t))
5579 #else
5580 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
5581 #endif
5582 
5583 #endif /* NK_NUKLEAR_H_ */
5584 /*
5585  * ==============================================================
5586  *
5587  *                          IMPLEMENTATION
5588  *
5589  * ===============================================================
5590  */
5591 #ifdef NK_IMPLEMENTATION
5592 
5593 #ifndef NK_POOL_DEFAULT_CAPACITY
5594 #define NK_POOL_DEFAULT_CAPACITY 16
5595 #endif
5596 
5597 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
5598 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
5599 #endif
5600 
5601 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
5602 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
5603 #endif
5604 
5605 /* standard library headers */
5606 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5607 #include <stdlib.h> /* malloc, free */
5608 #endif
5609 #ifdef NK_INCLUDE_STANDARD_IO
5610 #include <stdio.h> /* fopen, fclose,... */
5611 #endif
5612 #ifdef NK_INCLUDE_STANDARD_VARARGS
5613 #include <stdarg.h> /* valist, va_start, va_end, ... */
5614 #endif
5615 #ifndef NK_ASSERT
5616 #include <assert.h>
5617 #define NK_ASSERT(expr) assert(expr)
5618 #endif
5619 
5620 #ifndef NK_MEMSET
5621 #define NK_MEMSET nk_memset
5622 #endif
5623 #ifndef NK_MEMCPY
5624 #define NK_MEMCPY nk_memcopy
5625 #endif
5626 #ifndef NK_SQRT
5627 #define NK_SQRT nk_sqrt
5628 #endif
5629 #ifndef NK_SIN
5630 #define NK_SIN nk_sin
5631 #endif
5632 #ifndef NK_COS
5633 #define NK_COS nk_cos
5634 #endif
5635 #ifndef NK_STRTOD
5636 #define NK_STRTOD nk_strtod
5637 #endif
5638 #ifndef NK_DTOA
5639 #define NK_DTOA nk_dtoa
5640 #endif
5641 
5642 #define NK_DEFAULT (-1)
5643 
5644 #ifndef NK_VSNPRINTF
5645 /* If your compiler does support `vsnprintf` I would highly recommend
5646  * defining this to vsnprintf instead since `vsprintf` is basically
5647  * unbelievable unsafe and should *NEVER* be used. But I have to support
5648  * it since C89 only provides this unsafe version. */
5649   #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
5650       (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
5651       (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
5652       (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
5653        defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
5654       #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
5655   #else
5656     #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
5657   #endif
5658 #endif
5659 
5660 #define NK_SCHAR_MIN (-127)
5661 #define NK_SCHAR_MAX 127
5662 #define NK_UCHAR_MIN 0
5663 #define NK_UCHAR_MAX 256
5664 #define NK_SSHORT_MIN (-32767)
5665 #define NK_SSHORT_MAX 32767
5666 #define NK_USHORT_MIN 0
5667 #define NK_USHORT_MAX 65535
5668 #define NK_SINT_MIN (-2147483647)
5669 #define NK_SINT_MAX 2147483647
5670 #define NK_UINT_MIN 0
5671 #define NK_UINT_MAX 4294967295u
5672 
5673 /* Make sure correct type size:
5674  * This will fire with a negative subscript error if the type sizes
5675  * are set incorrectly by the compiler, and compile out if not */
5676 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
5677 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
5678 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
5679 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
5680 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
5681 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
5682 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
5683 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
5684 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
5685 
5686 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
5687 #define NK_FLOAT_PRECISION 0.00000000000001
5688 
5689 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
5690 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
5691 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
5692 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
5693 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
5694 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
5695 
5696 /*
5697  * ==============================================================
5698  *
5699  *                          MATH
5700  *
5701  * ===============================================================
5702  */
5703 /*  Since nuklear is supposed to work on all systems providing floating point
5704     math without any dependencies I also had to implement my own math functions
5705     for sqrt, sin and cos. Since the actual highly accurate implementations for
5706     the standard library functions are quite complex and I do not need high
5707     precision for my use cases I use approximations.
5708 
5709     Sqrt
5710     ----
5711     For square root nuklear uses the famous fast inverse square root:
5712     https://en.wikipedia.org/wiki/Fast_inverse_square_root with
5713     slightly tweaked magic constant. While on today's hardware it is
5714     probably not faster it is still fast and accurate enough for
5715     nuklear's use cases. IMPORTANT: this requires float format IEEE 754
5716 
5717     Sine/Cosine
5718     -----------
5719     All constants inside both function are generated Remez's minimax
5720     approximations for value range 0...2*PI. The reason why I decided to
5721     approximate exactly that range is that nuklear only needs sine and
5722     cosine to generate circles which only requires that exact range.
5723     In addition I used Remez instead of Taylor for additional precision:
5724     www.lolengine.net/blog/2011/12/21/better-function-approximations.
5725 
5726     The tool I used to generate constants for both sine and cosine
5727     (it can actually approximate a lot more functions) can be
5728     found here: www.lolengine.net/wiki/oss/lolremez
5729 */
5730 NK_INTERN float
5731 nk_inv_sqrt(float number)
5732 {
5733     float x2;
5734     const float threehalfs = 1.5f;
5735     union {nk_uint i; float f;} conv = {0};
5736     conv.f = number;
5737     x2 = number * 0.5f;
5738     conv.i = 0x5f375A84 - (conv.i >> 1);
5739     conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
5740     return conv.f;
5741 }
5742 
5743 NK_INTERN float
5744 nk_sqrt(float x)
5745 {
5746     return x * nk_inv_sqrt(x);
5747 }
5748 
5749 NK_INTERN float
5750 nk_sin(float x)
5751 {
5752     NK_STORAGE const float a0 = +1.91059300966915117e-31f;
5753     NK_STORAGE const float a1 = +1.00086760103908896f;
5754     NK_STORAGE const float a2 = -1.21276126894734565e-2f;
5755     NK_STORAGE const float a3 = -1.38078780785773762e-1f;
5756     NK_STORAGE const float a4 = -2.67353392911981221e-2f;
5757     NK_STORAGE const float a5 = +2.08026600266304389e-2f;
5758     NK_STORAGE const float a6 = -3.03996055049204407e-3f;
5759     NK_STORAGE const float a7 = +1.38235642404333740e-4f;
5760     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
5761 }
5762 
5763 NK_INTERN float
5764 nk_cos(float x)
5765 {
5766     NK_STORAGE const float a0 = +1.00238601909309722f;
5767     NK_STORAGE const float a1 = -3.81919947353040024e-2f;
5768     NK_STORAGE const float a2 = -3.94382342128062756e-1f;
5769     NK_STORAGE const float a3 = -1.18134036025221444e-1f;
5770     NK_STORAGE const float a4 = +1.07123798512170878e-1f;
5771     NK_STORAGE const float a5 = -1.86637164165180873e-2f;
5772     NK_STORAGE const float a6 = +9.90140908664079833e-4f;
5773     NK_STORAGE const float a7 = -5.23022132118824778e-14f;
5774     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
5775 }
5776 
5777 NK_INTERN nk_uint
5778 nk_round_up_pow2(nk_uint v)
5779 {
5780     v--;
5781     v |= v >> 1;
5782     v |= v >> 2;
5783     v |= v >> 4;
5784     v |= v >> 8;
5785     v |= v >> 16;
5786     v++;
5787     return v;
5788 }
5789 
5790 NK_API struct nk_rect
5791 nk_get_null_rect(void)
5792 {
5793     return nk_null_rect;
5794 }
5795 
5796 NK_API struct nk_rect
5797 nk_rect(float x, float y, float w, float h)
5798 {
5799     struct nk_rect r;
5800     r.x = x; r.y = y;
5801     r.w = w; r.h = h;
5802     return r;
5803 }
5804 
5805 NK_API struct nk_rect
5806 nk_recti(int x, int y, int w, int h)
5807 {
5808     struct nk_rect r;
5809     r.x = (float)x;
5810     r.y = (float)y;
5811     r.w = (float)w;
5812     r.h = (float)h;
5813     return r;
5814 }
5815 
5816 NK_API struct nk_rect
5817 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
5818 {
5819     return nk_rect(pos.x, pos.y, size.x, size.y);
5820 }
5821 
5822 NK_API struct nk_rect
5823 nk_rectv(const float *r)
5824 {
5825     return nk_rect(r[0], r[1], r[2], r[3]);
5826 }
5827 
5828 NK_API struct nk_rect
5829 nk_rectiv(const int *r)
5830 {
5831     return nk_recti(r[0], r[1], r[2], r[3]);
5832 }
5833 
5834 NK_API struct nk_vec2
5835 nk_rect_pos(struct nk_rect r)
5836 {
5837     struct nk_vec2 ret;
5838     ret.x = r.x; ret.y = r.y;
5839     return ret;
5840 }
5841 
5842 NK_API struct nk_vec2
5843 nk_rect_size(struct nk_rect r)
5844 {
5845     struct nk_vec2 ret;
5846     ret.x = r.w; ret.y = r.h;
5847     return ret;
5848 }
5849 
5850 NK_INTERN struct nk_rect
5851 nk_shrink_rect(struct nk_rect r, float amount)
5852 {
5853     struct nk_rect res;
5854     r.w = NK_MAX(r.w, 2 * amount);
5855     r.h = NK_MAX(r.h, 2 * amount);
5856     res.x = r.x + amount;
5857     res.y = r.y + amount;
5858     res.w = r.w - 2 * amount;
5859     res.h = r.h - 2 * amount;
5860     return res;
5861 }
5862 
5863 NK_INTERN struct nk_rect
5864 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
5865 {
5866     r.w = NK_MAX(r.w, 2 * pad.x);
5867     r.h = NK_MAX(r.h, 2 * pad.y);
5868     r.x += pad.x; r.y += pad.y;
5869     r.w -= 2 * pad.x;
5870     r.h -= 2 * pad.y;
5871     return r;
5872 }
5873 
5874 NK_API struct nk_vec2
5875 nk_vec2(float x, float y)
5876 {
5877     struct nk_vec2 ret;
5878     ret.x = x; ret.y = y;
5879     return ret;
5880 }
5881 
5882 NK_API struct nk_vec2
5883 nk_vec2i(int x, int y)
5884 {
5885     struct nk_vec2 ret;
5886     ret.x = (float)x;
5887     ret.y = (float)y;
5888     return ret;
5889 }
5890 
5891 NK_API struct nk_vec2
5892 nk_vec2v(const float *v)
5893 {
5894     return nk_vec2(v[0], v[1]);
5895 }
5896 
5897 NK_API struct nk_vec2
5898 nk_vec2iv(const int *v)
5899 {
5900     return nk_vec2i(v[0], v[1]);
5901 }
5902 
5903 /*
5904  * ==============================================================
5905  *
5906  *                          UTIL
5907  *
5908  * ===============================================================
5909  */
5910 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
5911 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
5912 NK_INTERN int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
5913 NK_INTERN int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
5914 NK_INTERN int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
5915 NK_INTERN int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
5916 
5917 NK_INTERN void*
5918 nk_memcopy(void *dst0, const void *src0, nk_size length)
5919 {
5920     nk_ptr t;
5921     char *dst = (char*)dst0;
5922     const char *src = (const char*)src0;
5923     if (length == 0 || dst == src)
5924         goto done;
5925 
5926     #define nk_word int
5927     #define nk_wsize sizeof(nk_word)
5928     #define nk_wmask (nk_wsize-1)
5929     #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
5930     #define NK_TLOOP1(s) do { s; } while (--t)
5931 
5932     if (dst < src) {
5933         t = (nk_ptr)src; /* only need low bits */
5934         if ((t | (nk_ptr)dst) & nk_wmask) {
5935             if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
5936                 t = length;
5937             else
5938                 t = nk_wsize - (t & nk_wmask);
5939             length -= t;
5940             NK_TLOOP1(*dst++ = *src++);
5941         }
5942         t = length / nk_wsize;
5943         NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
5944             src += nk_wsize; dst += nk_wsize);
5945         t = length & nk_wmask;
5946         NK_TLOOP(*dst++ = *src++);
5947     } else {
5948         src += length;
5949         dst += length;
5950         t = (nk_ptr)src;
5951         if ((t | (nk_ptr)dst) & nk_wmask) {
5952             if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
5953                 t = length;
5954             else
5955                 t &= nk_wmask;
5956             length -= t;
5957             NK_TLOOP1(*--dst = *--src);
5958         }
5959         t = length / nk_wsize;
5960         NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
5961             *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
5962         t = length & nk_wmask;
5963         NK_TLOOP(*--dst = *--src);
5964     }
5965     #undef nk_word
5966     #undef nk_wsize
5967     #undef nk_wmask
5968     #undef NK_TLOOP
5969     #undef NK_TLOOP1
5970 done:
5971     return (dst0);
5972 }
5973 
5974 NK_INTERN void
5975 nk_memset(void *ptr, int c0, nk_size size)
5976 {
5977     #define nk_word unsigned
5978     #define nk_wsize sizeof(nk_word)
5979     #define nk_wmask (nk_wsize - 1)
5980     nk_byte *dst = (nk_byte*)ptr;
5981     unsigned c = 0;
5982     nk_size t = 0;
5983 
5984     if ((c = (nk_byte)c0) != 0) {
5985         c = (c << 8) | c; /* at least 16-bits  */
5986         if (sizeof(unsigned int) > 2)
5987             c = (c << 16) | c; /* at least 32-bits*/
5988     }
5989 
5990     /* too small of a word count */
5991     dst = (nk_byte*)ptr;
5992     if (size < 3 * nk_wsize) {
5993         while (size--) *dst++ = (nk_byte)c0;
5994         return;
5995     }
5996 
5997     /* align destination */
5998     if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
5999         t = nk_wsize -t;
6000         size -= t;
6001         do {
6002             *dst++ = (nk_byte)c0;
6003         } while (--t != 0);
6004     }
6005 
6006     /* fill word */
6007     t = size / nk_wsize;
6008     do {
6009         *(nk_word*)((void*)dst) = c;
6010         dst += nk_wsize;
6011     } while (--t != 0);
6012 
6013     /* fill trailing bytes */
6014     t = (size & nk_wmask);
6015     if (t != 0) {
6016         do {
6017             *dst++ = (nk_byte)c0;
6018         } while (--t != 0);
6019     }
6020 
6021     #undef nk_word
6022     #undef nk_wsize
6023     #undef nk_wmask
6024 }
6025 
6026 NK_INTERN void
6027 nk_zero(void *ptr, nk_size size)
6028 {
6029     NK_ASSERT(ptr);
6030     NK_MEMSET(ptr, 0, size);
6031 }
6032 
6033 NK_API int
6034 nk_strlen(const char *str)
6035 {
6036     int siz = 0;
6037     NK_ASSERT(str);
6038     while (str && *str++ != '\0') siz++;
6039     return siz;
6040 }
6041 
6042 NK_API int
6043 nk_strtoi(const char *str, const char **endptr)
6044 {
6045     int neg = 1;
6046     const char *p = str;
6047     int value = 0;
6048 
6049     NK_ASSERT(str);
6050     if (!str) return 0;
6051 
6052     /* skip whitespace */
6053     while (*p == ' ') p++;
6054     if (*p == '-') {
6055         neg = -1;
6056         p++;
6057     }
6058     while (*p && *p >= '0' && *p <= '9') {
6059         value = value * 10 + (int) (*p - '0');
6060         p++;
6061     }
6062     if (endptr)
6063         *endptr = p;
6064     return neg*value;
6065 }
6066 
6067 NK_API double
6068 nk_strtod(const char *str, const char **endptr)
6069 {
6070     double m;
6071     double neg = 1.0;
6072     const char *p = str;
6073     double value = 0;
6074     double number = 0;
6075 
6076     NK_ASSERT(str);
6077     if (!str) return 0;
6078 
6079     /* skip whitespace */
6080     while (*p == ' ') p++;
6081     if (*p == '-') {
6082         neg = -1.0;
6083         p++;
6084     }
6085 
6086     while (*p && *p != '.' && *p != 'e') {
6087         value = value * 10.0 + (double) (*p - '0');
6088         p++;
6089     }
6090 
6091     if (*p == '.') {
6092         p++;
6093         for(m = 0.1; *p && *p != 'e'; p++ ) {
6094             value = value + (double) (*p - '0') * m;
6095             m *= 0.1;
6096         }
6097     }
6098     if (*p == 'e') {
6099         int i, pow, div;
6100         p++;
6101         if (*p == '-') {
6102             div = nk_true;
6103             p++;
6104         } else if (*p == '+') {
6105             div = nk_false;
6106             p++;
6107         } else div = nk_false;
6108 
6109         for (pow = 0; *p; p++)
6110             pow = pow * 10 + (int) (*p - '0');
6111 
6112         for (m = 1.0, i = 0; i < pow; i++)
6113             m *= 10.0;
6114 
6115         if (div)
6116             value /= m;
6117         else value *= m;
6118     }
6119     number = value * neg;
6120     if (endptr)
6121         *endptr = p;
6122     return number;
6123 }
6124 
6125 NK_API float
6126 nk_strtof(const char *str, const char **endptr)
6127 {
6128     float float_value;
6129     double double_value;
6130     double_value = NK_STRTOD(str, endptr);
6131     float_value = (float)double_value;
6132     return float_value;
6133 }
6134 
6135 NK_API int
6136 nk_stricmp(const char *s1, const char *s2)
6137 {
6138     nk_int c1,c2,d;
6139     do {
6140         c1 = *s1++;
6141         c2 = *s2++;
6142         d = c1 - c2;
6143         while (d) {
6144             if (c1 <= 'Z' && c1 >= 'A') {
6145                 d += ('a' - 'A');
6146                 if (!d) break;
6147             }
6148             if (c2 <= 'Z' && c2 >= 'A') {
6149                 d -= ('a' - 'A');
6150                 if (!d) break;
6151             }
6152             return ((d >= 0) << 1) - 1;
6153         }
6154     } while (c1);
6155     return 0;
6156 }
6157 
6158 NK_API int
6159 nk_stricmpn(const char *s1, const char *s2, int n)
6160 {
6161     int c1,c2,d;
6162     NK_ASSERT(n >= 0);
6163     do {
6164         c1 = *s1++;
6165         c2 = *s2++;
6166         if (!n--) return 0;
6167 
6168         d = c1 - c2;
6169         while (d) {
6170             if (c1 <= 'Z' && c1 >= 'A') {
6171                 d += ('a' - 'A');
6172                 if (!d) break;
6173             }
6174             if (c2 <= 'Z' && c2 >= 'A') {
6175                 d -= ('a' - 'A');
6176                 if (!d) break;
6177             }
6178             return ((d >= 0) << 1) - 1;
6179         }
6180     } while (c1);
6181     return 0;
6182 }
6183 
6184 NK_INTERN int
6185 nk_str_match_here(const char *regexp, const char *text)
6186 {
6187     if (regexp[0] == '\0')
6188         return 1;
6189     if (regexp[1] == '*')
6190         return nk_str_match_star(regexp[0], regexp+2, text);
6191     if (regexp[0] == '$' && regexp[1] == '\0')
6192         return *text == '\0';
6193     if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
6194         return nk_str_match_here(regexp+1, text+1);
6195     return 0;
6196 }
6197 
6198 NK_INTERN int
6199 nk_str_match_star(int c, const char *regexp, const char *text)
6200 {
6201     do {/* a '* matches zero or more instances */
6202         if (nk_str_match_here(regexp, text))
6203             return 1;
6204     } while (*text != '\0' && (*text++ == c || c == '.'));
6205     return 0;
6206 }
6207 
6208 NK_API int
6209 nk_strfilter(const char *text, const char *regexp)
6210 {
6211     /*
6212     c    matches any literal character c
6213     .    matches any single character
6214     ^    matches the beginning of the input string
6215     $    matches the end of the input string
6216     *    matches zero or more occurrences of the previous character*/
6217     if (regexp[0] == '^')
6218         return nk_str_match_here(regexp+1, text);
6219     do {    /* must look even if string is empty */
6220         if (nk_str_match_here(regexp, text))
6221             return 1;
6222     } while (*text++ != '\0');
6223     return 0;
6224 }
6225 
6226 NK_API int
6227 nk_strmatch_fuzzy_text(const char *str, int str_len,
6228     const char *pattern, int *out_score)
6229 {
6230     /* Returns true if each character in pattern is found sequentially within str
6231      * if found then out_score is also set. Score value has no intrinsic meaning.
6232      * Range varies with pattern. Can only compare scores with same search pattern. */
6233 
6234     /* bonus for adjacent matches */
6235     #define NK_ADJACENCY_BONUS 5
6236     /* bonus if match occurs after a separator */
6237     #define NK_SEPARATOR_BONUS 10
6238     /* bonus if match is uppercase and prev is lower */
6239     #define NK_CAMEL_BONUS 10
6240     /* penalty applied for every letter in str before the first match */
6241     #define NK_LEADING_LETTER_PENALTY (-3)
6242     /* maximum penalty for leading letters */
6243     #define NK_MAX_LEADING_LETTER_PENALTY (-9)
6244     /* penalty for every letter that doesn't matter */
6245     #define NK_UNMATCHED_LETTER_PENALTY (-1)
6246 
6247     /* loop variables */
6248     int score = 0;
6249     char const * pattern_iter = pattern;
6250     int str_iter = 0;
6251     int prev_matched = nk_false;
6252     int prev_lower = nk_false;
6253     /* true so if first letter match gets separator bonus*/
6254     int prev_separator = nk_true;
6255 
6256     /* use "best" matched letter if multiple string letters match the pattern */
6257     char const * best_letter = 0;
6258     int best_letter_score = 0;
6259 
6260     /* loop over strings */
6261     NK_ASSERT(str);
6262     NK_ASSERT(pattern);
6263     if (!str || !str_len || !pattern) return 0;
6264     while (str_iter < str_len)
6265     {
6266         const char pattern_letter = *pattern_iter;
6267         const char str_letter = str[str_iter];
6268 
6269         int next_match = *pattern_iter != '\0' &&
6270             nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
6271         int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
6272 
6273         int advanced = next_match && best_letter;
6274         int pattern_repeat = best_letter && *pattern_iter != '\0';
6275         pattern_repeat = pattern_repeat &&
6276             nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
6277 
6278         if (advanced || pattern_repeat) {
6279             score += best_letter_score;
6280             best_letter = 0;
6281             best_letter_score = 0;
6282         }
6283 
6284         if (next_match || rematch)
6285         {
6286             int new_score = 0;
6287             /* Apply penalty for each letter before the first pattern match */
6288             if (pattern_iter == pattern) {
6289                 int count = (int)(&str[str_iter] - str);
6290                 int penalty = NK_LEADING_LETTER_PENALTY * count;
6291                 if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
6292                     penalty = NK_MAX_LEADING_LETTER_PENALTY;
6293 
6294                 score += penalty;
6295             }
6296 
6297             /* apply bonus for consecutive bonuses */
6298             if (prev_matched)
6299                 new_score += NK_ADJACENCY_BONUS;
6300 
6301             /* apply bonus for matches after a separator */
6302             if (prev_separator)
6303                 new_score += NK_SEPARATOR_BONUS;
6304 
6305             /* apply bonus across camel case boundaries */
6306             if (prev_lower && nk_is_upper(str_letter))
6307                 new_score += NK_CAMEL_BONUS;
6308 
6309             /* update pattern iter IFF the next pattern letter was matched */
6310             if (next_match)
6311                 ++pattern_iter;
6312 
6313             /* update best letter in str which may be for a "next" letter or a rematch */
6314             if (new_score >= best_letter_score) {
6315                 /* apply penalty for now skipped letter */
6316                 if (best_letter != 0)
6317                     score += NK_UNMATCHED_LETTER_PENALTY;
6318 
6319                 best_letter = &str[str_iter];
6320                 best_letter_score = new_score;
6321             }
6322             prev_matched = nk_true;
6323         } else {
6324             score += NK_UNMATCHED_LETTER_PENALTY;
6325             prev_matched = nk_false;
6326         }
6327 
6328         /* separators should be more easily defined */
6329         prev_lower = nk_is_lower(str_letter) != 0;
6330         prev_separator = str_letter == '_' || str_letter == ' ';
6331 
6332         ++str_iter;
6333     }
6334 
6335     /* apply score for last match */
6336     if (best_letter)
6337         score += best_letter_score;
6338 
6339     /* did not match full pattern */
6340     if (*pattern_iter != '\0')
6341         return nk_false;
6342 
6343     if (out_score)
6344         *out_score = score;
6345     return nk_true;
6346 }
6347 
6348 NK_API int
6349 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
6350 {return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);}
6351 
6352 NK_INTERN int
6353 nk_string_float_limit(char *string, int prec)
6354 {
6355     int dot = 0;
6356     char *c = string;
6357     while (*c) {
6358         if (*c == '.') {
6359             dot = 1;
6360             c++;
6361             continue;
6362         }
6363         if (dot == (prec+1)) {
6364             *c = 0;
6365             break;
6366         }
6367         if (dot > 0) dot++;
6368         c++;
6369     }
6370     return (int)(c - string);
6371 }
6372 
6373 NK_INTERN double
6374 nk_pow(double x, int n)
6375 {
6376     /*  check the sign of n */
6377     double r = 1;
6378     int plus = n >= 0;
6379     n = (plus) ? n : -n;
6380     while (n > 0) {
6381         if ((n & 1) == 1)
6382             r *= x;
6383         n /= 2;
6384         x *= x;
6385     }
6386     return plus ? r : 1.0 / r;
6387 }
6388 
6389 NK_INTERN int
6390 nk_ifloord(double x)
6391 {
6392     x = (double)((int)x - ((x < 0.0) ? 1 : 0));
6393     return (int)x;
6394 }
6395 
6396 NK_INTERN int
6397 nk_ifloorf(float x)
6398 {
6399     x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
6400     return (int)x;
6401 }
6402 
6403 NK_INTERN int
6404 nk_iceilf(float x)
6405 {
6406     if (x >= 0) {
6407         int i = (int)x;
6408         return (x > i) ? i+1: i;
6409     } else {
6410         int t = (int)x;
6411         float r = x - (float)t;
6412         return (r > 0.0f) ? t+1: t;
6413     }
6414 }
6415 
6416 NK_INTERN int
6417 nk_log10(double n)
6418 {
6419     int neg;
6420     int ret;
6421     int exp = 0;
6422 
6423     neg = (n < 0) ? 1 : 0;
6424     ret = (neg) ? (int)-n : (int)n;
6425     while ((ret / 10) > 0) {
6426         ret /= 10;
6427         exp++;
6428     }
6429     if (neg) exp = -exp;
6430     return exp;
6431 }
6432 
6433 NK_INTERN void
6434 nk_strrev_ascii(char *s)
6435 {
6436     int len = nk_strlen(s);
6437     int end = len / 2;
6438     int i = 0;
6439     char t;
6440     for (; i < end; ++i) {
6441         t = s[i];
6442         s[i] = s[len - 1 - i];
6443         s[len -1 - i] = t;
6444     }
6445 }
6446 
6447 NK_INTERN char*
6448 nk_itoa(char *s, long n)
6449 {
6450     long i = 0;
6451     if (n == 0) {
6452         s[i++] = '0';
6453         s[i] = 0;
6454         return s;
6455     }
6456     if (n < 0) {
6457         s[i++] = '-';
6458         n = -n;
6459     }
6460     while (n > 0) {
6461         s[i++] = (char)('0' + (n % 10));
6462         n /= 10;
6463     }
6464     s[i] = 0;
6465     if (s[0] == '-')
6466         ++s;
6467 
6468     nk_strrev_ascii(s);
6469     return s;
6470 }
6471 
6472 NK_INTERN char*
6473 nk_dtoa(char *s, double n)
6474 {
6475     int useExp = 0;
6476     int digit = 0, m = 0, m1 = 0;
6477     char *c = s;
6478     int neg = 0;
6479 
6480     NK_ASSERT(s);
6481     if (!s) return 0;
6482 
6483     if (n == 0.0) {
6484         s[0] = '0'; s[1] = '\0';
6485         return s;
6486     }
6487 
6488     neg = (n < 0);
6489     if (neg) n = -n;
6490 
6491     /* calculate magnitude */
6492     m = nk_log10(n);
6493     useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
6494     if (neg) *(c++) = '-';
6495 
6496     /* set up for scientific notation */
6497     if (useExp) {
6498         if (m < 0)
6499            m -= 1;
6500         n = n / (double)nk_pow(10.0, m);
6501         m1 = m;
6502         m = 0;
6503     }
6504     if (m < 1.0) {
6505         m = 0;
6506     }
6507 
6508     /* convert the number */
6509     while (n > NK_FLOAT_PRECISION || m >= 0) {
6510         double weight = nk_pow(10.0, m);
6511         if (weight > 0) {
6512             double t = (double)n / weight;
6513             digit = nk_ifloord(t);
6514             n -= ((double)digit * weight);
6515             *(c++) = (char)('0' + (char)digit);
6516         }
6517         if (m == 0 && n > 0)
6518             *(c++) = '.';
6519         m--;
6520     }
6521 
6522     if (useExp) {
6523         /* convert the exponent */
6524         int i, j;
6525         *(c++) = 'e';
6526         if (m1 > 0) {
6527             *(c++) = '+';
6528         } else {
6529             *(c++) = '-';
6530             m1 = -m1;
6531         }
6532         m = 0;
6533         while (m1 > 0) {
6534             *(c++) = (char)('0' + (char)(m1 % 10));
6535             m1 /= 10;
6536             m++;
6537         }
6538         c -= m;
6539         for (i = 0, j = m-1; i<j; i++, j--) {
6540             /* swap without temporary */
6541             c[i] ^= c[j];
6542             c[j] ^= c[i];
6543             c[i] ^= c[j];
6544         }
6545         c += m;
6546     }
6547     *(c) = '\0';
6548     return s;
6549 }
6550 
6551 #ifdef NK_INCLUDE_STANDARD_VARARGS
6552 #ifndef NK_INCLUDE_STANDARD_IO
6553 static int
6554 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
6555 {
6556     enum nk_arg_type {
6557         NK_ARG_TYPE_CHAR,
6558         NK_ARG_TYPE_SHORT,
6559         NK_ARG_TYPE_DEFAULT,
6560         NK_ARG_TYPE_LONG
6561     };
6562     enum nk_arg_flags {
6563         NK_ARG_FLAG_LEFT = 0x01,
6564         NK_ARG_FLAG_PLUS = 0x02,
6565         NK_ARG_FLAG_SPACE = 0x04,
6566         NK_ARG_FLAG_NUM = 0x10,
6567         NK_ARG_FLAG_ZERO = 0x20
6568     };
6569 
6570     char number_buffer[NK_MAX_NUMBER_BUFFER];
6571     enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
6572     int precision = NK_DEFAULT;
6573     int width = NK_DEFAULT;
6574     nk_flags flag = 0;
6575 
6576     int len = 0;
6577     int result = -1;
6578     const char *iter = fmt;
6579 
6580     NK_ASSERT(buf);
6581     NK_ASSERT(buf_size);
6582     if (!buf || !buf_size || !fmt) return 0;
6583     for (iter = fmt; *iter && len < buf_size; iter++) {
6584         /* copy all non-format characters */
6585         while (*iter && (*iter != '%') && (len < buf_size))
6586             buf[len++] = *iter++;
6587         if (!(*iter) || len >= buf_size) break;
6588         iter++;
6589 
6590         /* flag arguments */
6591         while (*iter) {
6592             if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
6593             else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
6594             else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
6595             else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
6596             else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
6597             else break;
6598             iter++;
6599         }
6600 
6601         /* width argument */
6602         width = NK_DEFAULT;
6603         if (*iter >= '1' && *iter <= '9') {
6604             const char *end;
6605             width = nk_strtoi(iter, &end);
6606             if (end == iter)
6607                 width = -1;
6608             else iter = end;
6609         } else if (*iter == '*') {
6610             width = va_arg(args, int);
6611             iter++;
6612         }
6613 
6614         /* precision argument */
6615         precision = NK_DEFAULT;
6616         if (*iter == '.') {
6617             iter++;
6618             if (*iter == '*') {
6619                 precision = va_arg(args, int);
6620                 iter++;
6621             } else {
6622                 const char *end;
6623                 precision = nk_strtoi(iter, &end);
6624                 if (end == iter)
6625                     precision = -1;
6626                 else iter = end;
6627             }
6628         }
6629 
6630         /* length modifier */
6631         if (*iter == 'h') {
6632             if (*(iter+1) == 'h') {
6633                 arg_type = NK_ARG_TYPE_CHAR;
6634                 iter++;
6635             } else arg_type = NK_ARG_TYPE_SHORT;
6636             iter++;
6637         } else if (*iter == 'l') {
6638             arg_type = NK_ARG_TYPE_LONG;
6639             iter++;
6640         } else arg_type = NK_ARG_TYPE_DEFAULT;
6641 
6642         /* specifier */
6643         if (*iter == '%') {
6644             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6645             NK_ASSERT(precision == NK_DEFAULT);
6646             NK_ASSERT(width == NK_DEFAULT);
6647             if (len < buf_size)
6648                 buf[len++] = '%';
6649         } else if (*iter == 's') {
6650             /* string  */
6651             const char *str = va_arg(args, const char*);
6652             NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
6653             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6654             NK_ASSERT(precision == NK_DEFAULT);
6655             NK_ASSERT(width == NK_DEFAULT);
6656             if (str == buf) return -1;
6657             while (str && *str && len < buf_size)
6658                 buf[len++] = *str++;
6659         } else if (*iter == 'n') {
6660             /* current length callback */
6661             signed int *n = va_arg(args, int*);
6662             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6663             NK_ASSERT(precision == NK_DEFAULT);
6664             NK_ASSERT(width == NK_DEFAULT);
6665             if (n) *n = len;
6666         } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
6667             /* signed integer */
6668             long value = 0;
6669             const char *num_iter;
6670             int num_len, num_print, padding;
6671             int cur_precision = NK_MAX(precision, 1);
6672             int cur_width = NK_MAX(width, 0);
6673 
6674             /* retrieve correct value type */
6675             if (arg_type == NK_ARG_TYPE_CHAR)
6676                 value = (signed char)va_arg(args, int);
6677             else if (arg_type == NK_ARG_TYPE_SHORT)
6678                 value = (signed short)va_arg(args, int);
6679             else if (arg_type == NK_ARG_TYPE_LONG)
6680                 value = va_arg(args, signed long);
6681             else if (*iter == 'c')
6682                 value = (unsigned char)va_arg(args, int);
6683             else value = va_arg(args, signed int);
6684 
6685             /* convert number to string */
6686             nk_itoa(number_buffer, value);
6687             num_len = nk_strlen(number_buffer);
6688             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
6689             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
6690                 padding = NK_MAX(padding-1, 0);
6691 
6692             /* fill left padding up to a total of `width` characters */
6693             if (!(flag & NK_ARG_FLAG_LEFT)) {
6694                 while (padding-- > 0 && (len < buf_size)) {
6695                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
6696                         buf[len++] = '0';
6697                     else buf[len++] = ' ';
6698                 }
6699             }
6700 
6701             /* copy string value representation into buffer */
6702             if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
6703                 buf[len++] = '+';
6704             else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
6705                 buf[len++] = ' ';
6706 
6707             /* fill up to precision number of digits with '0' */
6708             num_print = NK_MAX(cur_precision, num_len);
6709             while (precision && (num_print > num_len) && (len < buf_size)) {
6710                 buf[len++] = '0';
6711                 num_print--;
6712             }
6713 
6714             /* copy string value representation into buffer */
6715             num_iter = number_buffer;
6716             while (precision && *num_iter && len < buf_size)
6717                 buf[len++] = *num_iter++;
6718 
6719             /* fill right padding up to width characters */
6720             if (flag & NK_ARG_FLAG_LEFT) {
6721                 while ((padding-- > 0) && (len < buf_size))
6722                     buf[len++] = ' ';
6723             }
6724         } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
6725             /* unsigned integer */
6726             unsigned long value = 0;
6727             int num_len = 0, num_print, padding = 0;
6728             int cur_precision = NK_MAX(precision, 1);
6729             int cur_width = NK_MAX(width, 0);
6730             unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
6731 
6732             /* print oct/hex/dec value */
6733             const char *upper_output_format = "0123456789ABCDEF";
6734             const char *lower_output_format = "0123456789abcdef";
6735             const char *output_format = (*iter == 'x') ?
6736                 lower_output_format: upper_output_format;
6737 
6738             /* retrieve correct value type */
6739             if (arg_type == NK_ARG_TYPE_CHAR)
6740                 value = (unsigned char)va_arg(args, int);
6741             else if (arg_type == NK_ARG_TYPE_SHORT)
6742                 value = (unsigned short)va_arg(args, int);
6743             else if (arg_type == NK_ARG_TYPE_LONG)
6744                 value = va_arg(args, unsigned long);
6745             else value = va_arg(args, unsigned int);
6746 
6747             do {
6748                 /* convert decimal number into hex/oct number */
6749                 int digit = output_format[value % base];
6750                 if (num_len < NK_MAX_NUMBER_BUFFER)
6751                     number_buffer[num_len++] = (char)digit;
6752                 value /= base;
6753             } while (value > 0);
6754 
6755             num_print = NK_MAX(cur_precision, num_len);
6756             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
6757             if (flag & NK_ARG_FLAG_NUM)
6758                 padding = NK_MAX(padding-1, 0);
6759 
6760             /* fill left padding up to a total of `width` characters */
6761             if (!(flag & NK_ARG_FLAG_LEFT)) {
6762                 while ((padding-- > 0) && (len < buf_size)) {
6763                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
6764                         buf[len++] = '0';
6765                     else buf[len++] = ' ';
6766                 }
6767             }
6768 
6769             /* fill up to precision number of digits */
6770             if (num_print && (flag & NK_ARG_FLAG_NUM)) {
6771                 if ((*iter == 'o') && (len < buf_size)) {
6772                     buf[len++] = '0';
6773                 } else if ((*iter == 'x') && ((len+1) < buf_size)) {
6774                     buf[len++] = '0';
6775                     buf[len++] = 'x';
6776                 } else if ((*iter == 'X') && ((len+1) < buf_size)) {
6777                     buf[len++] = '0';
6778                     buf[len++] = 'X';
6779                 }
6780             }
6781             while (precision && (num_print > num_len) && (len < buf_size)) {
6782                 buf[len++] = '0';
6783                 num_print--;
6784             }
6785 
6786             /* reverse number direction */
6787             while (num_len > 0) {
6788                 if (precision && (len < buf_size))
6789                     buf[len++] = number_buffer[num_len-1];
6790                 num_len--;
6791             }
6792 
6793             /* fill right padding up to width characters */
6794             if (flag & NK_ARG_FLAG_LEFT) {
6795                 while ((padding-- > 0) && (len < buf_size))
6796                     buf[len++] = ' ';
6797             }
6798         } else if (*iter == 'f') {
6799             /* floating point */
6800             const char *num_iter;
6801             int cur_precision = (precision < 0) ? 6: precision;
6802             int prefix, cur_width = NK_MAX(width, 0);
6803             double value = va_arg(args, double);
6804             int num_len = 0, frac_len = 0, dot = 0;
6805             int padding = 0;
6806 
6807             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6808             NK_DTOA(number_buffer, value);
6809             num_len = nk_strlen(number_buffer);
6810 
6811             /* calculate padding */
6812             num_iter = number_buffer;
6813             while (*num_iter && *num_iter != '.')
6814                 num_iter++;
6815 
6816             prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
6817             padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
6818             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
6819                 padding = NK_MAX(padding-1, 0);
6820 
6821             /* fill left padding up to a total of `width` characters */
6822             if (!(flag & NK_ARG_FLAG_LEFT)) {
6823                 while (padding-- > 0 && (len < buf_size)) {
6824                     if (flag & NK_ARG_FLAG_ZERO)
6825                         buf[len++] = '0';
6826                     else buf[len++] = ' ';
6827                 }
6828             }
6829 
6830             /* copy string value representation into buffer */
6831             num_iter = number_buffer;
6832             if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
6833                 buf[len++] = '+';
6834             else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
6835                 buf[len++] = ' ';
6836             while (*num_iter) {
6837                 if (dot) frac_len++;
6838                 if (len < buf_size)
6839                     buf[len++] = *num_iter;
6840                 if (*num_iter == '.') dot = 1;
6841                 if (frac_len >= cur_precision) break;
6842                 num_iter++;
6843             }
6844 
6845             /* fill number up to precision */
6846             while (frac_len < cur_precision) {
6847                 if (!dot && len < buf_size) {
6848                     buf[len++] = '.';
6849                     dot = 1;
6850                 }
6851                 if (len < buf_size)
6852                     buf[len++] = '0';
6853                 frac_len++;
6854             }
6855 
6856             /* fill right padding up to width characters */
6857             if (flag & NK_ARG_FLAG_LEFT) {
6858                 while ((padding-- > 0) && (len < buf_size))
6859                     buf[len++] = ' ';
6860             }
6861         } else {
6862             /* Specifier not supported: g,G,e,E,p,z */
6863             NK_ASSERT(0 && "specifier is not supported!");
6864             return result;
6865         }
6866     }
6867     buf[(len >= buf_size)?(buf_size-1):len] = 0;
6868     result = (len >= buf_size)?-1:len;
6869     return result;
6870 }
6871 #endif
6872 
6873 NK_INTERN int
6874 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
6875 {
6876     int result = -1;
6877     NK_ASSERT(buf);
6878     NK_ASSERT(buf_size);
6879     if (!buf || !buf_size || !fmt) return 0;
6880 #ifdef NK_INCLUDE_STANDARD_IO
6881     result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
6882     result = (result >= buf_size) ? -1: result;
6883     buf[buf_size-1] = 0;
6884 #else
6885     result = nk_vsnprintf(buf, buf_size, fmt, args);
6886 #endif
6887     return result;
6888 }
6889 #endif
6890 
6891 NK_API nk_hash
6892 nk_murmur_hash(const void * key, int len, nk_hash seed)
6893 {
6894     /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
6895     #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
6896     union {const nk_uint *i; const nk_byte *b;} conv = {0};
6897     const nk_byte *data = (const nk_byte*)key;
6898     const int nblocks = len/4;
6899     nk_uint h1 = seed;
6900     const nk_uint c1 = 0xcc9e2d51;
6901     const nk_uint c2 = 0x1b873593;
6902     const nk_byte *tail;
6903     const nk_uint *blocks;
6904     nk_uint k1;
6905     int i;
6906 
6907     /* body */
6908     if (!key) return 0;
6909     conv.b = (data + nblocks*4);
6910     blocks = (const nk_uint*)conv.i;
6911     for (i = -nblocks; i; ++i) {
6912         k1 = blocks[i];
6913         k1 *= c1;
6914         k1 = NK_ROTL(k1,15);
6915         k1 *= c2;
6916 
6917         h1 ^= k1;
6918         h1 = NK_ROTL(h1,13);
6919         h1 = h1*5+0xe6546b64;
6920     }
6921 
6922     /* tail */
6923     tail = (const nk_byte*)(data + nblocks*4);
6924     k1 = 0;
6925     switch (len & 3) {
6926     case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
6927     case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
6928     case 1: k1 ^= tail[0];
6929             k1 *= c1;
6930             k1 = NK_ROTL(k1,15);
6931             k1 *= c2;
6932             h1 ^= k1;
6933             break;
6934     default: break;
6935     }
6936 
6937     /* finalization */
6938     h1 ^= (nk_uint)len;
6939     /* fmix32 */
6940     h1 ^= h1 >> 16;
6941     h1 *= 0x85ebca6b;
6942     h1 ^= h1 >> 13;
6943     h1 *= 0xc2b2ae35;
6944     h1 ^= h1 >> 16;
6945 
6946     #undef NK_ROTL
6947     return h1;
6948 }
6949 
6950 #ifdef NK_INCLUDE_STANDARD_IO
6951 NK_INTERN char*
6952 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
6953 {
6954     char *buf;
6955     FILE *fd;
6956     long ret;
6957 
6958     NK_ASSERT(path);
6959     NK_ASSERT(siz);
6960     NK_ASSERT(alloc);
6961     if (!path || !siz || !alloc)
6962         return 0;
6963 
6964     fd = fopen(path, "rb");
6965     if (!fd) return 0;
6966     fseek(fd, 0, SEEK_END);
6967     ret = ftell(fd);
6968     if (ret < 0) {
6969         fclose(fd);
6970         return 0;
6971     }
6972     *siz = (nk_size)ret;
6973     fseek(fd, 0, SEEK_SET);
6974     buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
6975     NK_ASSERT(buf);
6976     if (!buf) {
6977         fclose(fd);
6978         return 0;
6979     }
6980     *siz = (nk_size)fread(buf, 1,*siz, fd);
6981     fclose(fd);
6982     return buf;
6983 }
6984 #endif
6985 
6986 /*
6987  * ==============================================================
6988  *
6989  *                          COLOR
6990  *
6991  * ===============================================================
6992  */
6993 NK_INTERN int
6994 nk_parse_hex(const char *p, int length)
6995 {
6996     int i = 0;
6997     int len = 0;
6998     while (len < length) {
6999         i <<= 4;
7000         if (p[len] >= 'a' && p[len] <= 'f')
7001             i += ((p[len] - 'a') + 10);
7002         else if (p[len] >= 'A' && p[len] <= 'F')
7003             i += ((p[len] - 'A') + 10);
7004         else i += (p[len] - '0');
7005         len++;
7006     }
7007     return i;
7008 }
7009 
7010 NK_API struct nk_color
7011 nk_rgba(int r, int g, int b, int a)
7012 {
7013     struct nk_color ret;
7014     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
7015     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
7016     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
7017     ret.a = (nk_byte)NK_CLAMP(0, a, 255);
7018     return ret;
7019 }
7020 
7021 NK_API struct nk_color
7022 nk_rgb_hex(const char *rgb)
7023 {
7024     struct nk_color col;
7025     const char *c = rgb;
7026     if (*c == '#') c++;
7027     col.r = (nk_byte)nk_parse_hex(c, 2);
7028     col.g = (nk_byte)nk_parse_hex(c+2, 2);
7029     col.b = (nk_byte)nk_parse_hex(c+4, 2);
7030     col.a = 255;
7031     return col;
7032 }
7033 
7034 NK_API struct nk_color
7035 nk_rgba_hex(const char *rgb)
7036 {
7037     struct nk_color col;
7038     const char *c = rgb;
7039     if (*c == '#') c++;
7040     col.r = (nk_byte)nk_parse_hex(c, 2);
7041     col.g = (nk_byte)nk_parse_hex(c+2, 2);
7042     col.b = (nk_byte)nk_parse_hex(c+4, 2);
7043     col.a = (nk_byte)nk_parse_hex(c+6, 2);
7044     return col;
7045 }
7046 
7047 NK_API void
7048 nk_color_hex_rgba(char *output, struct nk_color col)
7049 {
7050     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
7051     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
7052     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
7053     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
7054     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
7055     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
7056     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
7057     output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
7058     output[7] = (char)NK_TO_HEX((col.a & 0x0F));
7059     output[8] = '\0';
7060     #undef NK_TO_HEX
7061 }
7062 
7063 NK_API void
7064 nk_color_hex_rgb(char *output, struct nk_color col)
7065 {
7066     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
7067     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
7068     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
7069     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
7070     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
7071     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
7072     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
7073     output[6] = '\0';
7074     #undef NK_TO_HEX
7075 }
7076 
7077 NK_API struct nk_color
7078 nk_rgba_iv(const int *c)
7079 {
7080     return nk_rgba(c[0], c[1], c[2], c[3]);
7081 }
7082 
7083 NK_API struct nk_color
7084 nk_rgba_bv(const nk_byte *c)
7085 {
7086     return nk_rgba(c[0], c[1], c[2], c[3]);
7087 }
7088 
7089 NK_API struct nk_color
7090 nk_rgb(int r, int g, int b)
7091 {
7092     struct nk_color ret;
7093     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
7094     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
7095     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
7096     ret.a = (nk_byte)255;
7097     return ret;
7098 }
7099 
7100 NK_API struct nk_color
7101 nk_rgb_iv(const int *c)
7102 {
7103     return nk_rgb(c[0], c[1], c[2]);
7104 }
7105 
7106 NK_API struct nk_color
7107 nk_rgb_bv(const nk_byte* c)
7108 {
7109     return nk_rgb(c[0], c[1], c[2]);
7110 }
7111 
7112 NK_API struct nk_color
7113 nk_rgba_u32(nk_uint in)
7114 {
7115     struct nk_color ret;
7116     ret.r = (in & 0xFF);
7117     ret.g = ((in >> 8) & 0xFF);
7118     ret.b = ((in >> 16) & 0xFF);
7119     ret.a = (nk_byte)((in >> 24) & 0xFF);
7120     return ret;
7121 }
7122 
7123 NK_API struct nk_color
7124 nk_rgba_f(float r, float g, float b, float a)
7125 {
7126     struct nk_color ret;
7127     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
7128     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
7129     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
7130     ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
7131     return ret;
7132 }
7133 
7134 NK_API struct nk_color
7135 nk_rgba_fv(const float *c)
7136 {
7137     return nk_rgba_f(c[0], c[1], c[2], c[3]);
7138 }
7139 
7140 NK_API struct nk_color
7141 nk_rgba_cf(struct nk_colorf c)
7142 {
7143     return nk_rgba_f(c.r, c.g, c.b, c.a);
7144 }
7145 
7146 NK_API struct nk_color
7147 nk_rgb_f(float r, float g, float b)
7148 {
7149     struct nk_color ret;
7150     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
7151     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
7152     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
7153     ret.a = 255;
7154     return ret;
7155 }
7156 
7157 NK_API struct nk_color
7158 nk_rgb_fv(const float *c)
7159 {
7160     return nk_rgb_f(c[0], c[1], c[2]);
7161 }
7162 
7163 NK_API struct nk_color
7164 nk_rgb_cf(struct nk_colorf c)
7165 {
7166     return nk_rgb_f(c.r, c.g, c.b);
7167 }
7168 
7169 NK_API struct nk_color
7170 nk_hsv(int h, int s, int v)
7171 {
7172     return nk_hsva(h, s, v, 255);
7173 }
7174 
7175 NK_API struct nk_color
7176 nk_hsv_iv(const int *c)
7177 {
7178     return nk_hsv(c[0], c[1], c[2]);
7179 }
7180 
7181 NK_API struct nk_color
7182 nk_hsv_bv(const nk_byte *c)
7183 {
7184     return nk_hsv(c[0], c[1], c[2]);
7185 }
7186 
7187 NK_API struct nk_color
7188 nk_hsv_f(float h, float s, float v)
7189 {
7190     return nk_hsva_f(h, s, v, 1.0f);
7191 }
7192 
7193 NK_API struct nk_color
7194 nk_hsv_fv(const float *c)
7195 {
7196     return nk_hsv_f(c[0], c[1], c[2]);
7197 }
7198 
7199 NK_API struct nk_color
7200 nk_hsva(int h, int s, int v, int a)
7201 {
7202     float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
7203     float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
7204     float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
7205     float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
7206     return nk_hsva_f(hf, sf, vf, af);
7207 }
7208 
7209 NK_API struct nk_color
7210 nk_hsva_iv(const int *c)
7211 {
7212     return nk_hsva(c[0], c[1], c[2], c[3]);
7213 }
7214 
7215 NK_API struct nk_color
7216 nk_hsva_bv(const nk_byte *c)
7217 {
7218     return nk_hsva(c[0], c[1], c[2], c[3]);
7219 }
7220 
7221 NK_API struct nk_colorf
7222 nk_hsva_colorf(float h, float s, float v, float a)
7223 {
7224     int i;
7225     float p, q, t, f;
7226     struct nk_colorf out = {0,0,0,0};
7227     if (s <= 0.0f) {
7228         out.r = v; out.g = v; out.b = v; out.a = a;
7229         return out;
7230     }
7231     h = h / (60.0f/360.0f);
7232     i = (int)h;
7233     f = h - (float)i;
7234     p = v * (1.0f - s);
7235     q = v * (1.0f - (s * f));
7236     t = v * (1.0f - s * (1.0f - f));
7237 
7238     switch (i) {
7239     case 0: default: out.r = v; out.g = t; out.b = p; break;
7240     case 1: out.r = q; out.g = v; out.b = p; break;
7241     case 2: out.r = p; out.g = v; out.b = t; break;
7242     case 3: out.r = p; out.g = q; out.b = v; break;
7243     case 4: out.r = t; out.g = p; out.b = v; break;
7244     case 5: out.r = v; out.g = p; out.b = q; break;}
7245     out.a = a;
7246     return out;
7247 }
7248 
7249 NK_API struct nk_colorf
7250 nk_hsva_colorfv(float *c)
7251 {
7252     return nk_hsva_colorf(c[0], c[1], c[2], c[3]);
7253 }
7254 
7255 NK_API struct nk_color
7256 nk_hsva_f(float h, float s, float v, float a)
7257 {
7258     struct nk_colorf c = nk_hsva_colorf(h, s, v, a);
7259     return nk_rgba_f(c.r, c.g, c.b, c.a);
7260 }
7261 
7262 NK_API struct nk_color
7263 nk_hsva_fv(const float *c)
7264 {
7265     return nk_hsva_f(c[0], c[1], c[2], c[3]);
7266 }
7267 
7268 NK_API nk_uint
7269 nk_color_u32(struct nk_color in)
7270 {
7271     nk_uint out = (nk_uint)in.r;
7272     out |= ((nk_uint)in.g << 8);
7273     out |= ((nk_uint)in.b << 16);
7274     out |= ((nk_uint)in.a << 24);
7275     return out;
7276 }
7277 
7278 NK_API void
7279 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
7280 {
7281     NK_STORAGE const float s = 1.0f/255.0f;
7282     *r = (float)in.r * s;
7283     *g = (float)in.g * s;
7284     *b = (float)in.b * s;
7285     *a = (float)in.a * s;
7286 }
7287 
7288 NK_API void
7289 nk_color_fv(float *c, struct nk_color in)
7290 {
7291     nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
7292 }
7293 
7294 NK_API struct nk_colorf
7295 nk_color_cf(struct nk_color in)
7296 {
7297     struct nk_colorf o;
7298     nk_color_f(&o.r, &o.g, &o.b, &o.a, in);
7299     return o;
7300 }
7301 
7302 NK_API void
7303 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
7304 {
7305     NK_STORAGE const double s = 1.0/255.0;
7306     *r = (double)in.r * s;
7307     *g = (double)in.g * s;
7308     *b = (double)in.b * s;
7309     *a = (double)in.a * s;
7310 }
7311 
7312 NK_API void
7313 nk_color_dv(double *c, struct nk_color in)
7314 {
7315     nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
7316 }
7317 
7318 NK_API void
7319 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
7320 {
7321     float a;
7322     nk_color_hsva_f(out_h, out_s, out_v, &a, in);
7323 }
7324 
7325 NK_API void
7326 nk_color_hsv_fv(float *out, struct nk_color in)
7327 {
7328     float a;
7329     nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
7330 }
7331 
7332 NK_API void
7333 nk_colorf_hsva_f(float *out_h, float *out_s,
7334     float *out_v, float *out_a, struct nk_colorf in)
7335 {
7336     float chroma;
7337     float K = 0.0f;
7338     if (in.g < in.b) {
7339         const float t = in.g; in.g = in.b; in.b = t;
7340         K = -1.f;
7341     }
7342     if (in.r < in.g) {
7343         const float t = in.r; in.r = in.g; in.g = t;
7344         K = -2.f/6.0f - K;
7345     }
7346     chroma = in.r - ((in.g < in.b) ? in.g: in.b);
7347     *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f));
7348     *out_s = chroma / (in.r + 1e-20f);
7349     *out_v = in.r;
7350     *out_a = in.a;
7351 
7352 }
7353 
7354 NK_API void
7355 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
7356 {
7357     nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in);
7358 }
7359 NK_API void
7360 nk_color_hsva_f(float *out_h, float *out_s,
7361     float *out_v, float *out_a, struct nk_color in)
7362 {
7363     struct nk_colorf col;
7364     nk_color_f(&col.r,&col.g,&col.b,&col.a, in);
7365     nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col);
7366 }
7367 
7368 NK_API void
7369 nk_color_hsva_fv(float *out, struct nk_color in)
7370 {
7371     nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
7372 }
7373 
7374 NK_API void
7375 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
7376                 int *out_a, struct nk_color in)
7377 {
7378     float h,s,v,a;
7379     nk_color_hsva_f(&h, &s, &v, &a, in);
7380     *out_h = (nk_byte)(h * 255.0f);
7381     *out_s = (nk_byte)(s * 255.0f);
7382     *out_v = (nk_byte)(v * 255.0f);
7383     *out_a = (nk_byte)(a * 255.0f);
7384 }
7385 
7386 NK_API void
7387 nk_color_hsva_iv(int *out, struct nk_color in)
7388 {
7389     nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
7390 }
7391 
7392 NK_API void
7393 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
7394 {
7395     int tmp[4];
7396     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7397     out[0] = (nk_byte)tmp[0];
7398     out[1] = (nk_byte)tmp[1];
7399     out[2] = (nk_byte)tmp[2];
7400     out[3] = (nk_byte)tmp[3];
7401 }
7402 
7403 NK_API void
7404 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
7405 {
7406     int tmp[4];
7407     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7408     *h = (nk_byte)tmp[0];
7409     *s = (nk_byte)tmp[1];
7410     *v = (nk_byte)tmp[2];
7411     *a = (nk_byte)tmp[3];
7412 }
7413 
7414 NK_API void
7415 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
7416 {
7417     int a;
7418     nk_color_hsva_i(out_h, out_s, out_v, &a, in);
7419 }
7420 
7421 NK_API void
7422 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
7423 {
7424     int tmp[4];
7425     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7426     *out_h = (nk_byte)tmp[0];
7427     *out_s = (nk_byte)tmp[1];
7428     *out_v = (nk_byte)tmp[2];
7429 }
7430 
7431 NK_API void
7432 nk_color_hsv_iv(int *out, struct nk_color in)
7433 {
7434     nk_color_hsv_i(&out[0], &out[1], &out[2], in);
7435 }
7436 
7437 NK_API void
7438 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
7439 {
7440     int tmp[4];
7441     nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
7442     out[0] = (nk_byte)tmp[0];
7443     out[1] = (nk_byte)tmp[1];
7444     out[2] = (nk_byte)tmp[2];
7445 }
7446 /*
7447  * ==============================================================
7448  *
7449  *                          IMAGE
7450  *
7451  * ===============================================================
7452  */
7453 NK_API nk_handle
7454 nk_handle_ptr(void *ptr)
7455 {
7456     nk_handle handle = {0};
7457     handle.ptr = ptr;
7458     return handle;
7459 }
7460 
7461 NK_API nk_handle
7462 nk_handle_id(int id)
7463 {
7464     nk_handle handle;
7465     nk_zero_struct(handle);
7466     handle.id = id;
7467     return handle;
7468 }
7469 
7470 NK_API struct nk_image
7471 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
7472 {
7473     struct nk_image s;
7474     nk_zero(&s, sizeof(s));
7475     s.handle.ptr = ptr;
7476     s.w = w; s.h = h;
7477     s.region[0] = (unsigned short)r.x;
7478     s.region[1] = (unsigned short)r.y;
7479     s.region[2] = (unsigned short)r.w;
7480     s.region[3] = (unsigned short)r.h;
7481     return s;
7482 }
7483 
7484 NK_API struct nk_image
7485 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
7486 {
7487     struct nk_image s;
7488     nk_zero(&s, sizeof(s));
7489     s.handle.id = id;
7490     s.w = w; s.h = h;
7491     s.region[0] = (unsigned short)r.x;
7492     s.region[1] = (unsigned short)r.y;
7493     s.region[2] = (unsigned short)r.w;
7494     s.region[3] = (unsigned short)r.h;
7495     return s;
7496 }
7497 
7498 NK_API struct nk_image
7499 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
7500     struct nk_rect r)
7501 {
7502     struct nk_image s;
7503     nk_zero(&s, sizeof(s));
7504     s.handle = handle;
7505     s.w = w; s.h = h;
7506     s.region[0] = (unsigned short)r.x;
7507     s.region[1] = (unsigned short)r.y;
7508     s.region[2] = (unsigned short)r.w;
7509     s.region[3] = (unsigned short)r.h;
7510     return s;
7511 }
7512 
7513 NK_API struct nk_image
7514 nk_image_handle(nk_handle handle)
7515 {
7516     struct nk_image s;
7517     nk_zero(&s, sizeof(s));
7518     s.handle = handle;
7519     s.w = 0; s.h = 0;
7520     s.region[0] = 0;
7521     s.region[1] = 0;
7522     s.region[2] = 0;
7523     s.region[3] = 0;
7524     return s;
7525 }
7526 
7527 NK_API struct nk_image
7528 nk_image_ptr(void *ptr)
7529 {
7530     struct nk_image s;
7531     nk_zero(&s, sizeof(s));
7532     NK_ASSERT(ptr);
7533     s.handle.ptr = ptr;
7534     s.w = 0; s.h = 0;
7535     s.region[0] = 0;
7536     s.region[1] = 0;
7537     s.region[2] = 0;
7538     s.region[3] = 0;
7539     return s;
7540 }
7541 
7542 NK_API struct nk_image
7543 nk_image_id(int id)
7544 {
7545     struct nk_image s;
7546     nk_zero(&s, sizeof(s));
7547     s.handle.id = id;
7548     s.w = 0; s.h = 0;
7549     s.region[0] = 0;
7550     s.region[1] = 0;
7551     s.region[2] = 0;
7552     s.region[3] = 0;
7553     return s;
7554 }
7555 
7556 NK_API int
7557 nk_image_is_subimage(const struct nk_image* img)
7558 {
7559     NK_ASSERT(img);
7560     return !(img->w == 0 && img->h == 0);
7561 }
7562 
7563 NK_INTERN void
7564 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
7565     float x1, float y1)
7566 {
7567     NK_ASSERT(a);
7568     NK_ASSERT(clip);
7569     clip->x = NK_MAX(a->x, x0);
7570     clip->y = NK_MAX(a->y, y0);
7571     clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
7572     clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
7573     clip->w = NK_MAX(0, clip->w);
7574     clip->h = NK_MAX(0, clip->h);
7575 }
7576 
7577 NK_API void
7578 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
7579     float pad_x, float pad_y, enum nk_heading direction)
7580 {
7581     float w_half, h_half;
7582     NK_ASSERT(result);
7583 
7584     r.w = NK_MAX(2 * pad_x, r.w);
7585     r.h = NK_MAX(2 * pad_y, r.h);
7586     r.w = r.w - 2 * pad_x;
7587     r.h = r.h - 2 * pad_y;
7588 
7589     r.x = r.x + pad_x;
7590     r.y = r.y + pad_y;
7591 
7592     w_half = r.w / 2.0f;
7593     h_half = r.h / 2.0f;
7594 
7595     if (direction == NK_UP) {
7596         result[0] = nk_vec2(r.x + w_half, r.y);
7597         result[1] = nk_vec2(r.x + r.w, r.y + r.h);
7598         result[2] = nk_vec2(r.x, r.y + r.h);
7599     } else if (direction == NK_RIGHT) {
7600         result[0] = nk_vec2(r.x, r.y);
7601         result[1] = nk_vec2(r.x + r.w, r.y + h_half);
7602         result[2] = nk_vec2(r.x, r.y + r.h);
7603     } else if (direction == NK_DOWN) {
7604         result[0] = nk_vec2(r.x, r.y);
7605         result[1] = nk_vec2(r.x + r.w, r.y);
7606         result[2] = nk_vec2(r.x + w_half, r.y + r.h);
7607     } else {
7608         result[0] = nk_vec2(r.x, r.y + h_half);
7609         result[1] = nk_vec2(r.x + r.w, r.y);
7610         result[2] = nk_vec2(r.x + r.w, r.y + r.h);
7611     }
7612 }
7613 
7614 NK_INTERN int
7615 nk_text_clamp(const struct nk_user_font *font, const char *text,
7616     int text_len, float space, int *glyphs, float *text_width,
7617     nk_rune *sep_list, int sep_count)
7618 {
7619     int i = 0;
7620     int glyph_len = 0;
7621     float last_width = 0;
7622     nk_rune unicode = 0;
7623     float width = 0;
7624     int len = 0;
7625     int g = 0;
7626     float s;
7627 
7628     int sep_len = 0;
7629     int sep_g = 0;
7630     float sep_width = 0;
7631     sep_count = NK_MAX(sep_count,0);
7632 
7633     glyph_len = nk_utf_decode(text, &unicode, text_len);
7634     while (glyph_len && (width < space) && (len < text_len)) {
7635         len += glyph_len;
7636         s = font->width(font->userdata, font->height, text, len);
7637         for (i = 0; i < sep_count; ++i) {
7638             if (unicode != sep_list[i]) continue;
7639             sep_width = last_width = width;
7640             sep_g = g+1;
7641             sep_len = len;
7642             break;
7643         }
7644         if (i == sep_count){
7645             last_width = sep_width = width;
7646             sep_g = g+1;
7647         }
7648         width = s;
7649         glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
7650         g++;
7651     }
7652     if (len >= text_len) {
7653         *glyphs = g;
7654         *text_width = last_width;
7655         return len;
7656     } else {
7657         *glyphs = sep_g;
7658         *text_width = sep_width;
7659         return (!sep_len) ? len: sep_len;
7660     }
7661 }
7662 
7663 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
7664 NK_INTERN struct nk_vec2
7665 nk_text_calculate_text_bounds(const struct nk_user_font *font,
7666     const char *begin, int byte_len, float row_height, const char **remaining,
7667     struct nk_vec2 *out_offset, int *glyphs, int op)
7668 {
7669     float line_height = row_height;
7670     struct nk_vec2 text_size = nk_vec2(0,0);
7671     float line_width = 0.0f;
7672 
7673     float glyph_width;
7674     int glyph_len = 0;
7675     nk_rune unicode = 0;
7676     int text_len = 0;
7677     if (!begin || byte_len <= 0 || !font)
7678         return nk_vec2(0,row_height);
7679 
7680     glyph_len = nk_utf_decode(begin, &unicode, byte_len);
7681     if (!glyph_len) return text_size;
7682     glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
7683 
7684     *glyphs = 0;
7685     while ((text_len < byte_len) && glyph_len) {
7686         if (unicode == '\n') {
7687             text_size.x = NK_MAX(text_size.x, line_width);
7688             text_size.y += line_height;
7689             line_width = 0;
7690             *glyphs+=1;
7691             if (op == NK_STOP_ON_NEW_LINE)
7692                 break;
7693 
7694             text_len++;
7695             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7696             continue;
7697         }
7698 
7699         if (unicode == '\r') {
7700             text_len++;
7701             *glyphs+=1;
7702             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7703             continue;
7704         }
7705 
7706         *glyphs = *glyphs + 1;
7707         text_len += glyph_len;
7708         line_width += (float)glyph_width;
7709         glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7710         glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
7711         continue;
7712     }
7713 
7714     if (text_size.x < line_width)
7715         text_size.x = line_width;
7716     if (out_offset)
7717         *out_offset = nk_vec2(line_width, text_size.y + line_height);
7718     if (line_width > 0 || text_size.y == 0.0f)
7719         text_size.y += line_height;
7720     if (remaining)
7721         *remaining = begin+text_len;
7722     return text_size;
7723 }
7724 
7725 /* ==============================================================
7726  *
7727  *                          UTF-8
7728  *
7729  * ===============================================================*/
7730 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
7731 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
7732 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
7733 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
7734 
7735 NK_INTERN int
7736 nk_utf_validate(nk_rune *u, int i)
7737 {
7738     NK_ASSERT(u);
7739     if (!u) return 0;
7740     if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
7741          NK_BETWEEN(*u, 0xD800, 0xDFFF))
7742             *u = NK_UTF_INVALID;
7743     for (i = 1; *u > nk_utfmax[i]; ++i);
7744     return i;
7745 }
7746 
7747 NK_INTERN nk_rune
7748 nk_utf_decode_byte(char c, int *i)
7749 {
7750     NK_ASSERT(i);
7751     if (!i) return 0;
7752     for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
7753         if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
7754             return (nk_byte)(c & ~nk_utfmask[*i]);
7755     }
7756     return 0;
7757 }
7758 
7759 NK_API int
7760 nk_utf_decode(const char *c, nk_rune *u, int clen)
7761 {
7762     int i, j, len, type=0;
7763     nk_rune udecoded;
7764 
7765     NK_ASSERT(c);
7766     NK_ASSERT(u);
7767 
7768     if (!c || !u) return 0;
7769     if (!clen) return 0;
7770     *u = NK_UTF_INVALID;
7771 
7772     udecoded = nk_utf_decode_byte(c[0], &len);
7773     if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
7774         return 1;
7775 
7776     for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
7777         udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
7778         if (type != 0)
7779             return j;
7780     }
7781     if (j < len)
7782         return 0;
7783     *u = udecoded;
7784     nk_utf_validate(u, len);
7785     return len;
7786 }
7787 
7788 NK_INTERN char
7789 nk_utf_encode_byte(nk_rune u, int i)
7790 {
7791     return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
7792 }
7793 
7794 NK_API int
7795 nk_utf_encode(nk_rune u, char *c, int clen)
7796 {
7797     int len, i;
7798     len = nk_utf_validate(&u, 0);
7799     if (clen < len || !len || len > NK_UTF_SIZE)
7800         return 0;
7801 
7802     for (i = len - 1; i != 0; --i) {
7803         c[i] = nk_utf_encode_byte(u, 0);
7804         u >>= 6;
7805     }
7806     c[0] = nk_utf_encode_byte(u, len);
7807     return len;
7808 }
7809 
7810 NK_API int
7811 nk_utf_len(const char *str, int len)
7812 {
7813     const char *text;
7814     int glyphs = 0;
7815     int text_len;
7816     int glyph_len;
7817     int src_len = 0;
7818     nk_rune unicode;
7819 
7820     NK_ASSERT(str);
7821     if (!str || !len) return 0;
7822 
7823     text = str;
7824     text_len = len;
7825     glyph_len = nk_utf_decode(text, &unicode, text_len);
7826     while (glyph_len && src_len < len) {
7827         glyphs++;
7828         src_len = src_len + glyph_len;
7829         glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
7830     }
7831     return glyphs;
7832 }
7833 
7834 NK_API const char*
7835 nk_utf_at(const char *buffer, int length, int index,
7836     nk_rune *unicode, int *len)
7837 {
7838     int i = 0;
7839     int src_len = 0;
7840     int glyph_len = 0;
7841     const char *text;
7842     int text_len;
7843 
7844     NK_ASSERT(buffer);
7845     NK_ASSERT(unicode);
7846     NK_ASSERT(len);
7847 
7848     if (!buffer || !unicode || !len) return 0;
7849     if (index < 0) {
7850         *unicode = NK_UTF_INVALID;
7851         *len = 0;
7852         return 0;
7853     }
7854 
7855     text = buffer;
7856     text_len = length;
7857     glyph_len = nk_utf_decode(text, unicode, text_len);
7858     while (glyph_len) {
7859         if (i == index) {
7860             *len = glyph_len;
7861             break;
7862         }
7863 
7864         i++;
7865         src_len = src_len + glyph_len;
7866         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7867     }
7868     if (i != index) return 0;
7869     return buffer + src_len;
7870 }
7871 
7872 /* ==============================================================
7873  *
7874  *                          BUFFER
7875  *
7876  * ===============================================================*/
7877 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
7878 NK_INTERN void* nk_malloc(nk_handle unused, void *old,nk_size size)
7879 {NK_UNUSED(unused); NK_UNUSED(old); return malloc(size);}
7880 NK_INTERN void nk_mfree(nk_handle unused, void *ptr)
7881 {NK_UNUSED(unused); free(ptr);}
7882 
7883 NK_API void
7884 nk_buffer_init_default(struct nk_buffer *buffer)
7885 {
7886     struct nk_allocator alloc;
7887     alloc.userdata.ptr = 0;
7888     alloc.alloc = nk_malloc;
7889     alloc.free = nk_mfree;
7890     nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
7891 }
7892 #endif
7893 
7894 NK_API void
7895 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
7896     nk_size initial_size)
7897 {
7898     NK_ASSERT(b);
7899     NK_ASSERT(a);
7900     NK_ASSERT(initial_size);
7901     if (!b || !a || !initial_size) return;
7902 
7903     nk_zero(b, sizeof(*b));
7904     b->type = NK_BUFFER_DYNAMIC;
7905     b->memory.ptr = a->alloc(a->userdata,0, initial_size);
7906     b->memory.size = initial_size;
7907     b->size = initial_size;
7908     b->grow_factor = 2.0f;
7909     b->pool = *a;
7910 }
7911 
7912 NK_API void
7913 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
7914 {
7915     NK_ASSERT(b);
7916     NK_ASSERT(m);
7917     NK_ASSERT(size);
7918     if (!b || !m || !size) return;
7919 
7920     nk_zero(b, sizeof(*b));
7921     b->type = NK_BUFFER_FIXED;
7922     b->memory.ptr = m;
7923     b->memory.size = size;
7924     b->size = size;
7925 }
7926 
7927 NK_INTERN void*
7928 nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment,
7929     enum nk_buffer_allocation_type type)
7930 {
7931     void *memory = 0;
7932     switch (type) {
7933     default:
7934     case NK_BUFFER_MAX:
7935     case NK_BUFFER_FRONT:
7936         if (align) {
7937             memory = NK_ALIGN_PTR(unaligned, align);
7938             *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
7939         } else {
7940             memory = unaligned;
7941             *alignment = 0;
7942         }
7943         break;
7944     case NK_BUFFER_BACK:
7945         if (align) {
7946             memory = NK_ALIGN_PTR_BACK(unaligned, align);
7947             *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
7948         } else {
7949             memory = unaligned;
7950             *alignment = 0;
7951         }
7952         break;
7953     }
7954     return memory;
7955 }
7956 
7957 NK_INTERN void*
7958 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
7959 {
7960     void *temp;
7961     nk_size buffer_size;
7962 
7963     NK_ASSERT(b);
7964     NK_ASSERT(size);
7965     if (!b || !size || !b->pool.alloc || !b->pool.free)
7966         return 0;
7967 
7968     buffer_size = b->memory.size;
7969     temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
7970     NK_ASSERT(temp);
7971     if (!temp) return 0;
7972 
7973     *size = capacity;
7974     if (temp != b->memory.ptr) {
7975         NK_MEMCPY(temp, b->memory.ptr, buffer_size);
7976         b->pool.free(b->pool.userdata, b->memory.ptr);
7977     }
7978 
7979     if (b->size == buffer_size) {
7980         /* no back buffer so just set correct size */
7981         b->size = capacity;
7982         return temp;
7983     } else {
7984         /* copy back buffer to the end of the new buffer */
7985         void *dst, *src;
7986         nk_size back_size;
7987         back_size = buffer_size - b->size;
7988         dst = nk_ptr_add(void, temp, capacity - back_size);
7989         src = nk_ptr_add(void, temp, b->size);
7990         NK_MEMCPY(dst, src, back_size);
7991         b->size = capacity - back_size;
7992     }
7993     return temp;
7994 }
7995 
7996 NK_INTERN void*
7997 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
7998     nk_size size, nk_size align)
7999 {
8000     int full;
8001     nk_size alignment;
8002     void *unaligned;
8003     void *memory;
8004 
8005     NK_ASSERT(b);
8006     NK_ASSERT(size);
8007     if (!b || !size) return 0;
8008     b->needed += size;
8009 
8010     /* calculate total size with needed alignment + size */
8011     if (type == NK_BUFFER_FRONT)
8012         unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
8013     else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
8014     memory = nk_buffer_align(unaligned, align, &alignment, type);
8015 
8016     /* check if buffer has enough memory*/
8017     if (type == NK_BUFFER_FRONT)
8018         full = ((b->allocated + size + alignment) > b->size);
8019     else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
8020 
8021     if (full) {
8022         nk_size capacity;
8023         if (b->type != NK_BUFFER_DYNAMIC)
8024             return 0;
8025         NK_ASSERT(b->pool.alloc && b->pool.free);
8026         if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
8027             return 0;
8028 
8029         /* buffer is full so allocate bigger buffer if dynamic */
8030         capacity = (nk_size)((float)b->memory.size * b->grow_factor);
8031         capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
8032         b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
8033         if (!b->memory.ptr) return 0;
8034 
8035         /* align newly allocated pointer */
8036         if (type == NK_BUFFER_FRONT)
8037             unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
8038         else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
8039         memory = nk_buffer_align(unaligned, align, &alignment, type);
8040     }
8041     if (type == NK_BUFFER_FRONT)
8042         b->allocated += size + alignment;
8043     else b->size -= (size + alignment);
8044     b->needed += alignment;
8045     b->calls++;
8046     return memory;
8047 }
8048 
8049 NK_API void
8050 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type,
8051     const void *memory, nk_size size, nk_size align)
8052 {
8053     void *mem = nk_buffer_alloc(b, type, size, align);
8054     if (!mem) return;
8055     NK_MEMCPY(mem, memory, size);
8056 }
8057 
8058 NK_API void
8059 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
8060 {
8061     NK_ASSERT(buffer);
8062     if (!buffer) return;
8063     buffer->marker[type].active = nk_true;
8064     if (type == NK_BUFFER_BACK)
8065         buffer->marker[type].offset = buffer->size;
8066     else buffer->marker[type].offset = buffer->allocated;
8067 }
8068 
8069 NK_API void
8070 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
8071 {
8072     NK_ASSERT(buffer);
8073     if (!buffer) return;
8074     if (type == NK_BUFFER_BACK) {
8075         /* reset back buffer either back to marker or empty */
8076         buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
8077         if (buffer->marker[type].active)
8078             buffer->size = buffer->marker[type].offset;
8079         else buffer->size = buffer->memory.size;
8080         buffer->marker[type].active = nk_false;
8081     } else {
8082         /* reset front buffer either back to back marker or empty */
8083         buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
8084         if (buffer->marker[type].active)
8085             buffer->allocated = buffer->marker[type].offset;
8086         else buffer->allocated = 0;
8087         buffer->marker[type].active = nk_false;
8088     }
8089 }
8090 
8091 NK_API void
8092 nk_buffer_clear(struct nk_buffer *b)
8093 {
8094     NK_ASSERT(b);
8095     if (!b) return;
8096     b->allocated = 0;
8097     b->size = b->memory.size;
8098     b->calls = 0;
8099     b->needed = 0;
8100 }
8101 
8102 NK_API void
8103 nk_buffer_free(struct nk_buffer *b)
8104 {
8105     NK_ASSERT(b);
8106     if (!b || !b->memory.ptr) return;
8107     if (b->type == NK_BUFFER_FIXED) return;
8108     if (!b->pool.free) return;
8109     NK_ASSERT(b->pool.free);
8110     b->pool.free(b->pool.userdata, b->memory.ptr);
8111 }
8112 
8113 NK_API void
8114 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
8115 {
8116     NK_ASSERT(b);
8117     NK_ASSERT(s);
8118     if (!s || !b) return;
8119     s->allocated = b->allocated;
8120     s->size =  b->memory.size;
8121     s->needed = b->needed;
8122     s->memory = b->memory.ptr;
8123     s->calls = b->calls;
8124 }
8125 
8126 NK_API void*
8127 nk_buffer_memory(struct nk_buffer *buffer)
8128 {
8129     NK_ASSERT(buffer);
8130     if (!buffer) return 0;
8131     return buffer->memory.ptr;
8132 }
8133 
8134 NK_API const void*
8135 nk_buffer_memory_const(const struct nk_buffer *buffer)
8136 {
8137     NK_ASSERT(buffer);
8138     if (!buffer) return 0;
8139     return buffer->memory.ptr;
8140 }
8141 
8142 NK_API nk_size
8143 nk_buffer_total(struct nk_buffer *buffer)
8144 {
8145     NK_ASSERT(buffer);
8146     if (!buffer) return 0;
8147     return buffer->memory.size;
8148 }
8149 
8150 /*
8151  * ==============================================================
8152  *
8153  *                          STRING
8154  *
8155  * ===============================================================
8156  */
8157 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
8158 NK_API void
8159 nk_str_init_default(struct nk_str *str)
8160 {
8161     struct nk_allocator alloc;
8162     alloc.userdata.ptr = 0;
8163     alloc.alloc = nk_malloc;
8164     alloc.free = nk_mfree;
8165     nk_buffer_init(&str->buffer, &alloc, 32);
8166     str->len = 0;
8167 }
8168 #endif
8169 
8170 NK_API void
8171 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
8172 {
8173     nk_buffer_init(&str->buffer, alloc, size);
8174     str->len = 0;
8175 }
8176 
8177 NK_API void
8178 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
8179 {
8180     nk_buffer_init_fixed(&str->buffer, memory, size);
8181     str->len = 0;
8182 }
8183 
8184 NK_API int
8185 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
8186 {
8187     char *mem;
8188     NK_ASSERT(s);
8189     NK_ASSERT(str);
8190     if (!s || !str || !len) return 0;
8191     mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
8192     if (!mem) return 0;
8193     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
8194     s->len += nk_utf_len(str, len);
8195     return len;
8196 }
8197 
8198 NK_API int
8199 nk_str_append_str_char(struct nk_str *s, const char *str)
8200 {
8201     return nk_str_append_text_char(s, str, nk_strlen(str));
8202 }
8203 
8204 NK_API int
8205 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
8206 {
8207     int i = 0;
8208     int byte_len = 0;
8209     nk_rune unicode;
8210     if (!str || !text || !len) return 0;
8211     for (i = 0; i < len; ++i)
8212         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
8213     nk_str_append_text_char(str, text, byte_len);
8214     return len;
8215 }
8216 
8217 NK_API int
8218 nk_str_append_str_utf8(struct nk_str *str, const char *text)
8219 {
8220     int runes = 0;
8221     int byte_len = 0;
8222     int num_runes = 0;
8223     int glyph_len = 0;
8224     nk_rune unicode;
8225     if (!str || !text) return 0;
8226 
8227     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
8228     while (unicode != '\0' && glyph_len) {
8229         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
8230         byte_len += glyph_len;
8231         num_runes++;
8232     }
8233     nk_str_append_text_char(str, text, byte_len);
8234     return runes;
8235 }
8236 
8237 NK_API int
8238 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
8239 {
8240     int i = 0;
8241     int byte_len = 0;
8242     nk_glyph glyph;
8243 
8244     NK_ASSERT(str);
8245     if (!str || !text || !len) return 0;
8246     for (i = 0; i < len; ++i) {
8247         byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
8248         if (!byte_len) break;
8249         nk_str_append_text_char(str, glyph, byte_len);
8250     }
8251     return len;
8252 }
8253 
8254 NK_API int
8255 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
8256 {
8257     int i = 0;
8258     nk_glyph glyph;
8259     int byte_len;
8260     NK_ASSERT(str);
8261     if (!str || !runes) return 0;
8262     while (runes[i] != '\0') {
8263         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8264         nk_str_append_text_char(str, glyph, byte_len);
8265         i++;
8266     }
8267     return i;
8268 }
8269 
8270 NK_API int
8271 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
8272 {
8273     int i;
8274     void *mem;
8275     char *src;
8276     char *dst;
8277 
8278     int copylen;
8279     NK_ASSERT(s);
8280     NK_ASSERT(str);
8281     NK_ASSERT(len >= 0);
8282     if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
8283     if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
8284         (s->buffer.type == NK_BUFFER_FIXED)) return 0;
8285 
8286     copylen = (int)s->buffer.allocated - pos;
8287     if (!copylen) {
8288         nk_str_append_text_char(s, str, len);
8289         return 1;
8290     }
8291     mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
8292     if (!mem) return 0;
8293 
8294     /* memmove */
8295     NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
8296     NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
8297     dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
8298     src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
8299     for (i = 0; i < copylen; ++i) *dst-- = *src--;
8300     mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
8301     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
8302     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8303     return 1;
8304 }
8305 
8306 NK_API int
8307 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
8308 {
8309     int glyph_len;
8310     nk_rune unicode;
8311     const char *begin;
8312     const char *buffer;
8313 
8314     NK_ASSERT(str);
8315     NK_ASSERT(cstr);
8316     NK_ASSERT(len);
8317     if (!str || !cstr || !len) return 0;
8318     begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
8319     if (!str->len)
8320         return nk_str_append_text_char(str, cstr, len);
8321     buffer = nk_str_get_const(str);
8322     if (!begin) return 0;
8323     return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
8324 }
8325 
8326 NK_API int
8327 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
8328 {
8329     return nk_str_insert_text_utf8(str, pos, text, len);
8330 }
8331 
8332 NK_API int
8333 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
8334 {
8335     return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
8336 }
8337 
8338 NK_API int
8339 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
8340 {
8341     int i = 0;
8342     int byte_len = 0;
8343     nk_rune unicode;
8344 
8345     NK_ASSERT(str);
8346     NK_ASSERT(text);
8347     if (!str || !text || !len) return 0;
8348     for (i = 0; i < len; ++i)
8349         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
8350     nk_str_insert_at_rune(str, pos, text, byte_len);
8351     return len;
8352 }
8353 
8354 NK_API int
8355 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
8356 {
8357     int runes = 0;
8358     int byte_len = 0;
8359     int num_runes = 0;
8360     int glyph_len = 0;
8361     nk_rune unicode;
8362     if (!str || !text) return 0;
8363 
8364     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
8365     while (unicode != '\0' && glyph_len) {
8366         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
8367         byte_len += glyph_len;
8368         num_runes++;
8369     }
8370     nk_str_insert_at_rune(str, pos, text, byte_len);
8371     return runes;
8372 }
8373 
8374 NK_API int
8375 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
8376 {
8377     int i = 0;
8378     int byte_len = 0;
8379     nk_glyph glyph;
8380 
8381     NK_ASSERT(str);
8382     if (!str || !runes || !len) return 0;
8383     for (i = 0; i < len; ++i) {
8384         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8385         if (!byte_len) break;
8386         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
8387     }
8388     return len;
8389 }
8390 
8391 NK_API int
8392 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
8393 {
8394     int i = 0;
8395     nk_glyph glyph;
8396     int byte_len;
8397     NK_ASSERT(str);
8398     if (!str || !runes) return 0;
8399     while (runes[i] != '\0') {
8400         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8401         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
8402         i++;
8403     }
8404     return i;
8405 }
8406 
8407 NK_API void
8408 nk_str_remove_chars(struct nk_str *s, int len)
8409 {
8410     NK_ASSERT(s);
8411     NK_ASSERT(len >= 0);
8412     if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
8413     NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
8414     s->buffer.allocated -= (nk_size)len;
8415     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8416 }
8417 
8418 NK_API void
8419 nk_str_remove_runes(struct nk_str *str, int len)
8420 {
8421     int index;
8422     const char *begin;
8423     const char *end;
8424     nk_rune unicode;
8425 
8426     NK_ASSERT(str);
8427     NK_ASSERT(len >= 0);
8428     if (!str || len < 0) return;
8429     if (len >= str->len) {
8430         str->len = 0;
8431         return;
8432     }
8433 
8434     index = str->len - len;
8435     begin = nk_str_at_rune(str, index, &unicode, &len);
8436     end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
8437     nk_str_remove_chars(str, (int)(end-begin)+1);
8438 }
8439 
8440 NK_API void
8441 nk_str_delete_chars(struct nk_str *s, int pos, int len)
8442 {
8443     NK_ASSERT(s);
8444     if (!s || !len || (nk_size)pos > s->buffer.allocated ||
8445         (nk_size)(pos + len) > s->buffer.allocated) return;
8446 
8447     if ((nk_size)(pos + len) < s->buffer.allocated) {
8448         /* memmove */
8449         char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
8450         char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
8451         NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
8452         NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
8453         s->buffer.allocated -= (nk_size)len;
8454     } else nk_str_remove_chars(s, len);
8455     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8456 }
8457 
8458 NK_API void
8459 nk_str_delete_runes(struct nk_str *s, int pos, int len)
8460 {
8461     char *temp;
8462     nk_rune unicode;
8463     char *begin;
8464     char *end;
8465     int unused;
8466 
8467     NK_ASSERT(s);
8468     NK_ASSERT(s->len >= pos + len);
8469     if (s->len < pos + len)
8470         len = NK_CLAMP(0, (s->len - pos), s->len);
8471     if (!len) return;
8472 
8473     temp = (char *)s->buffer.memory.ptr;
8474     begin = nk_str_at_rune(s, pos, &unicode, &unused);
8475     if (!begin) return;
8476     s->buffer.memory.ptr = begin;
8477     end = nk_str_at_rune(s, len, &unicode, &unused);
8478     s->buffer.memory.ptr = temp;
8479     if (!end) return;
8480     nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
8481 }
8482 
8483 NK_API char*
8484 nk_str_at_char(struct nk_str *s, int pos)
8485 {
8486     NK_ASSERT(s);
8487     if (!s || pos > (int)s->buffer.allocated) return 0;
8488     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
8489 }
8490 
8491 NK_API char*
8492 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
8493 {
8494     int i = 0;
8495     int src_len = 0;
8496     int glyph_len = 0;
8497     char *text;
8498     int text_len;
8499 
8500     NK_ASSERT(str);
8501     NK_ASSERT(unicode);
8502     NK_ASSERT(len);
8503 
8504     if (!str || !unicode || !len) return 0;
8505     if (pos < 0) {
8506         *unicode = 0;
8507         *len = 0;
8508         return 0;
8509     }
8510 
8511     text = (char*)str->buffer.memory.ptr;
8512     text_len = (int)str->buffer.allocated;
8513     glyph_len = nk_utf_decode(text, unicode, text_len);
8514     while (glyph_len) {
8515         if (i == pos) {
8516             *len = glyph_len;
8517             break;
8518         }
8519 
8520         i++;
8521         src_len = src_len + glyph_len;
8522         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
8523     }
8524     if (i != pos) return 0;
8525     return text + src_len;
8526 }
8527 
8528 NK_API const char*
8529 nk_str_at_char_const(const struct nk_str *s, int pos)
8530 {
8531     NK_ASSERT(s);
8532     if (!s || pos > (int)s->buffer.allocated) return 0;
8533     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
8534 }
8535 
8536 NK_API const char*
8537 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
8538 {
8539     int i = 0;
8540     int src_len = 0;
8541     int glyph_len = 0;
8542     char *text;
8543     int text_len;
8544 
8545     NK_ASSERT(str);
8546     NK_ASSERT(unicode);
8547     NK_ASSERT(len);
8548 
8549     if (!str || !unicode || !len) return 0;
8550     if (pos < 0) {
8551         *unicode = 0;
8552         *len = 0;
8553         return 0;
8554     }
8555 
8556     text = (char*)str->buffer.memory.ptr;
8557     text_len = (int)str->buffer.allocated;
8558     glyph_len = nk_utf_decode(text, unicode, text_len);
8559     while (glyph_len) {
8560         if (i == pos) {
8561             *len = glyph_len;
8562             break;
8563         }
8564 
8565         i++;
8566         src_len = src_len + glyph_len;
8567         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
8568     }
8569     if (i != pos) return 0;
8570     return text + src_len;
8571 }
8572 
8573 NK_API nk_rune
8574 nk_str_rune_at(const struct nk_str *str, int pos)
8575 {
8576     int len;
8577     nk_rune unicode = 0;
8578     nk_str_at_const(str, pos, &unicode, &len);
8579     return unicode;
8580 }
8581 
8582 NK_API char*
8583 nk_str_get(struct nk_str *s)
8584 {
8585     NK_ASSERT(s);
8586     if (!s || !s->len || !s->buffer.allocated) return 0;
8587     return (char*)s->buffer.memory.ptr;
8588 }
8589 
8590 NK_API const char*
8591 nk_str_get_const(const struct nk_str *s)
8592 {
8593     NK_ASSERT(s);
8594     if (!s || !s->len || !s->buffer.allocated) return 0;
8595     return (const char*)s->buffer.memory.ptr;
8596 }
8597 
8598 NK_API int
8599 nk_str_len(struct nk_str *s)
8600 {
8601     NK_ASSERT(s);
8602     if (!s || !s->len || !s->buffer.allocated) return 0;
8603     return s->len;
8604 }
8605 
8606 NK_API int
8607 nk_str_len_char(struct nk_str *s)
8608 {
8609     NK_ASSERT(s);
8610     if (!s || !s->len || !s->buffer.allocated) return 0;
8611     return (int)s->buffer.allocated;
8612 }
8613 
8614 NK_API void
8615 nk_str_clear(struct nk_str *str)
8616 {
8617     NK_ASSERT(str);
8618     nk_buffer_clear(&str->buffer);
8619     str->len = 0;
8620 }
8621 
8622 NK_API void
8623 nk_str_free(struct nk_str *str)
8624 {
8625     NK_ASSERT(str);
8626     nk_buffer_free(&str->buffer);
8627     str->len = 0;
8628 }
8629 
8630 /*
8631  * ==============================================================
8632  *
8633  *                      Command buffer
8634  *
8635  * ===============================================================
8636 */
8637 NK_INTERN void
8638 nk_command_buffer_init(struct nk_command_buffer *cmdbuf,
8639     struct nk_buffer *buffer, enum nk_command_clipping clip)
8640 {
8641     NK_ASSERT(cmdbuf);
8642     NK_ASSERT(buffer);
8643     if (!cmdbuf || !buffer) return;
8644     cmdbuf->base = buffer;
8645     cmdbuf->use_clipping = clip;
8646     cmdbuf->begin = buffer->allocated;
8647     cmdbuf->end = buffer->allocated;
8648     cmdbuf->last = buffer->allocated;
8649 }
8650 
8651 NK_INTERN void
8652 nk_command_buffer_reset(struct nk_command_buffer *buffer)
8653 {
8654     NK_ASSERT(buffer);
8655     if (!buffer) return;
8656     buffer->begin = 0;
8657     buffer->end = 0;
8658     buffer->last = 0;
8659     buffer->clip = nk_null_rect;
8660 #ifdef NK_INCLUDE_COMMAND_USERDATA
8661     buffer->userdata.ptr = 0;
8662 #endif
8663 }
8664 
8665 NK_INTERN void*
8666 nk_command_buffer_push(struct nk_command_buffer* b,
8667     enum nk_command_type t, nk_size size)
8668 {
8669     NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
8670     struct nk_command *cmd;
8671     nk_size alignment;
8672     void *unaligned;
8673     void *memory;
8674 
8675     NK_ASSERT(b);
8676     NK_ASSERT(b->base);
8677     if (!b) return 0;
8678     cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
8679     if (!cmd) return 0;
8680 
8681     /* make sure the offset to the next command is aligned */
8682     b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
8683     unaligned = (nk_byte*)cmd + size;
8684     memory = NK_ALIGN_PTR(unaligned, align);
8685     alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
8686 #ifdef NK_ZERO_COMMAND_MEMORY
8687     NK_MEMSET(cmd, 0, size + alignment);
8688 #endif
8689 
8690     cmd->type = t;
8691     cmd->next = b->base->allocated + alignment;
8692 #ifdef NK_INCLUDE_COMMAND_USERDATA
8693     cmd->userdata = b->userdata;
8694 #endif
8695     b->end = cmd->next;
8696     return cmd;
8697 }
8698 
8699 NK_API void
8700 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
8701 {
8702     struct nk_command_scissor *cmd;
8703     NK_ASSERT(b);
8704     if (!b) return;
8705 
8706     b->clip.x = r.x;
8707     b->clip.y = r.y;
8708     b->clip.w = r.w;
8709     b->clip.h = r.h;
8710     cmd = (struct nk_command_scissor*)
8711         nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
8712 
8713     if (!cmd) return;
8714     cmd->x = (short)r.x;
8715     cmd->y = (short)r.y;
8716     cmd->w = (unsigned short)NK_MAX(0, r.w);
8717     cmd->h = (unsigned short)NK_MAX(0, r.h);
8718 }
8719 
8720 NK_API void
8721 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
8722     float x1, float y1, float line_thickness, struct nk_color c)
8723 {
8724     struct nk_command_line *cmd;
8725     NK_ASSERT(b);
8726     if (!b || line_thickness <= 0) return;
8727     cmd = (struct nk_command_line*)
8728         nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
8729     if (!cmd) return;
8730     cmd->line_thickness = (unsigned short)line_thickness;
8731     cmd->begin.x = (short)x0;
8732     cmd->begin.y = (short)y0;
8733     cmd->end.x = (short)x1;
8734     cmd->end.y = (short)y1;
8735     cmd->color = c;
8736 }
8737 
8738 NK_API void
8739 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
8740     float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
8741     float bx, float by, float line_thickness, struct nk_color col)
8742 {
8743     struct nk_command_curve *cmd;
8744     NK_ASSERT(b);
8745     if (!b || col.a == 0 || line_thickness <= 0) return;
8746 
8747     cmd = (struct nk_command_curve*)
8748         nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
8749     if (!cmd) return;
8750     cmd->line_thickness = (unsigned short)line_thickness;
8751     cmd->begin.x = (short)ax;
8752     cmd->begin.y = (short)ay;
8753     cmd->ctrl[0].x = (short)ctrl0x;
8754     cmd->ctrl[0].y = (short)ctrl0y;
8755     cmd->ctrl[1].x = (short)ctrl1x;
8756     cmd->ctrl[1].y = (short)ctrl1y;
8757     cmd->end.x = (short)bx;
8758     cmd->end.y = (short)by;
8759     cmd->color = col;
8760 }
8761 
8762 NK_API void
8763 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
8764     float rounding, float line_thickness, struct nk_color c)
8765 {
8766     struct nk_command_rect *cmd;
8767     NK_ASSERT(b);
8768     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
8769     if (b->use_clipping) {
8770         const struct nk_rect *clip = &b->clip;
8771         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8772             clip->x, clip->y, clip->w, clip->h)) return;
8773     }
8774     cmd = (struct nk_command_rect*)
8775         nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
8776     if (!cmd) return;
8777     cmd->rounding = (unsigned short)rounding;
8778     cmd->line_thickness = (unsigned short)line_thickness;
8779     cmd->x = (short)rect.x;
8780     cmd->y = (short)rect.y;
8781     cmd->w = (unsigned short)NK_MAX(0, rect.w);
8782     cmd->h = (unsigned short)NK_MAX(0, rect.h);
8783     cmd->color = c;
8784 }
8785 
8786 NK_API void
8787 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
8788     float rounding, struct nk_color c)
8789 {
8790     struct nk_command_rect_filled *cmd;
8791     NK_ASSERT(b);
8792     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
8793     if (b->use_clipping) {
8794         const struct nk_rect *clip = &b->clip;
8795         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8796             clip->x, clip->y, clip->w, clip->h)) return;
8797     }
8798 
8799     cmd = (struct nk_command_rect_filled*)
8800         nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
8801     if (!cmd) return;
8802     cmd->rounding = (unsigned short)rounding;
8803     cmd->x = (short)rect.x;
8804     cmd->y = (short)rect.y;
8805     cmd->w = (unsigned short)NK_MAX(0, rect.w);
8806     cmd->h = (unsigned short)NK_MAX(0, rect.h);
8807     cmd->color = c;
8808 }
8809 
8810 NK_API void
8811 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
8812     struct nk_color left, struct nk_color top, struct nk_color right,
8813     struct nk_color bottom)
8814 {
8815     struct nk_command_rect_multi_color *cmd;
8816     NK_ASSERT(b);
8817     if (!b || rect.w == 0 || rect.h == 0) return;
8818     if (b->use_clipping) {
8819         const struct nk_rect *clip = &b->clip;
8820         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8821             clip->x, clip->y, clip->w, clip->h)) return;
8822     }
8823 
8824     cmd = (struct nk_command_rect_multi_color*)
8825         nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
8826     if (!cmd) return;
8827     cmd->x = (short)rect.x;
8828     cmd->y = (short)rect.y;
8829     cmd->w = (unsigned short)NK_MAX(0, rect.w);
8830     cmd->h = (unsigned short)NK_MAX(0, rect.h);
8831     cmd->left = left;
8832     cmd->top = top;
8833     cmd->right = right;
8834     cmd->bottom = bottom;
8835 }
8836 
8837 NK_API void
8838 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
8839     float line_thickness, struct nk_color c)
8840 {
8841     struct nk_command_circle *cmd;
8842     if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
8843     if (b->use_clipping) {
8844         const struct nk_rect *clip = &b->clip;
8845         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
8846             return;
8847     }
8848 
8849     cmd = (struct nk_command_circle*)
8850         nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
8851     if (!cmd) return;
8852     cmd->line_thickness = (unsigned short)line_thickness;
8853     cmd->x = (short)r.x;
8854     cmd->y = (short)r.y;
8855     cmd->w = (unsigned short)NK_MAX(r.w, 0);
8856     cmd->h = (unsigned short)NK_MAX(r.h, 0);
8857     cmd->color = c;
8858 }
8859 
8860 NK_API void
8861 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
8862 {
8863     struct nk_command_circle_filled *cmd;
8864     NK_ASSERT(b);
8865     if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
8866     if (b->use_clipping) {
8867         const struct nk_rect *clip = &b->clip;
8868         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
8869             return;
8870     }
8871 
8872     cmd = (struct nk_command_circle_filled*)
8873         nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
8874     if (!cmd) return;
8875     cmd->x = (short)r.x;
8876     cmd->y = (short)r.y;
8877     cmd->w = (unsigned short)NK_MAX(r.w, 0);
8878     cmd->h = (unsigned short)NK_MAX(r.h, 0);
8879     cmd->color = c;
8880 }
8881 
8882 NK_API void
8883 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
8884     float a_min, float a_max, float line_thickness, struct nk_color c)
8885 {
8886     struct nk_command_arc *cmd;
8887     if (!b || c.a == 0 || line_thickness <= 0) return;
8888     cmd = (struct nk_command_arc*)
8889         nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
8890     if (!cmd) return;
8891     cmd->line_thickness = (unsigned short)line_thickness;
8892     cmd->cx = (short)cx;
8893     cmd->cy = (short)cy;
8894     cmd->r = (unsigned short)radius;
8895     cmd->a[0] = a_min;
8896     cmd->a[1] = a_max;
8897     cmd->color = c;
8898 }
8899 
8900 NK_API void
8901 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
8902     float a_min, float a_max, struct nk_color c)
8903 {
8904     struct nk_command_arc_filled *cmd;
8905     NK_ASSERT(b);
8906     if (!b || c.a == 0) return;
8907     cmd = (struct nk_command_arc_filled*)
8908         nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
8909     if (!cmd) return;
8910     cmd->cx = (short)cx;
8911     cmd->cy = (short)cy;
8912     cmd->r = (unsigned short)radius;
8913     cmd->a[0] = a_min;
8914     cmd->a[1] = a_max;
8915     cmd->color = c;
8916 }
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 
8946 NK_API void
8947 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
8948     float y1, float x2, float y2, struct nk_color c)
8949 {
8950     struct nk_command_triangle_filled *cmd;
8951     NK_ASSERT(b);
8952     if (!b || c.a == 0) return;
8953     if (!b) return;
8954     if (b->use_clipping) {
8955         const struct nk_rect *clip = &b->clip;
8956         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
8957             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
8958             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
8959             return;
8960     }
8961 
8962     cmd = (struct nk_command_triangle_filled*)
8963         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
8964     if (!cmd) return;
8965     cmd->a.x = (short)x0;
8966     cmd->a.y = (short)y0;
8967     cmd->b.x = (short)x1;
8968     cmd->b.y = (short)y1;
8969     cmd->c.x = (short)x2;
8970     cmd->c.y = (short)y2;
8971     cmd->color = c;
8972 }
8973 
8974 NK_API void
8975 nk_stroke_polygon(struct nk_command_buffer *b,  float *points, int point_count,
8976     float line_thickness, struct nk_color col)
8977 {
8978     int i;
8979     nk_size size = 0;
8980     struct nk_command_polygon *cmd;
8981 
8982     NK_ASSERT(b);
8983     if (!b || col.a == 0 || line_thickness <= 0) return;
8984     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
8985     cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
8986     if (!cmd) return;
8987     cmd->color = col;
8988     cmd->line_thickness = (unsigned short)line_thickness;
8989     cmd->point_count = (unsigned short)point_count;
8990     for (i = 0; i < point_count; ++i) {
8991         cmd->points[i].x = (short)points[i*2];
8992         cmd->points[i].y = (short)points[i*2+1];
8993     }
8994 }
8995 
8996 NK_API void
8997 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
8998     struct nk_color col)
8999 {
9000     int i;
9001     nk_size size = 0;
9002     struct nk_command_polygon_filled *cmd;
9003 
9004     NK_ASSERT(b);
9005     if (!b || col.a == 0) return;
9006     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
9007     cmd = (struct nk_command_polygon_filled*)
9008         nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
9009     if (!cmd) return;
9010     cmd->color = col;
9011     cmd->point_count = (unsigned short)point_count;
9012     for (i = 0; i < point_count; ++i) {
9013         cmd->points[i].x = (short)points[i*2+0];
9014         cmd->points[i].y = (short)points[i*2+1];
9015     }
9016 }
9017 
9018 NK_API void
9019 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count,
9020     float line_thickness, struct nk_color col)
9021 {
9022     int i;
9023     nk_size size = 0;
9024     struct nk_command_polyline *cmd;
9025 
9026     NK_ASSERT(b);
9027     if (!b || col.a == 0 || line_thickness <= 0) return;
9028     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
9029     cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
9030     if (!cmd) return;
9031     cmd->color = col;
9032     cmd->point_count = (unsigned short)point_count;
9033     cmd->line_thickness = (unsigned short)line_thickness;
9034     for (i = 0; i < point_count; ++i) {
9035         cmd->points[i].x = (short)points[i*2];
9036         cmd->points[i].y = (short)points[i*2+1];
9037     }
9038 }
9039 
9040 NK_API void
9041 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
9042     const struct nk_image *img, struct nk_color col)
9043 {
9044     struct nk_command_image *cmd;
9045     NK_ASSERT(b);
9046     if (!b) return;
9047     if (b->use_clipping) {
9048         const struct nk_rect *c = &b->clip;
9049         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))
9050             return;
9051     }
9052 
9053     cmd = (struct nk_command_image*)
9054         nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
9055     if (!cmd) return;
9056     cmd->x = (short)r.x;
9057     cmd->y = (short)r.y;
9058     cmd->w = (unsigned short)NK_MAX(0, r.w);
9059     cmd->h = (unsigned short)NK_MAX(0, r.h);
9060     cmd->img = *img;
9061     cmd->col = col;
9062 }
9063 
9064 NK_API void
9065 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
9066     nk_command_custom_callback cb, nk_handle usr)
9067 {
9068     struct nk_command_custom *cmd;
9069     NK_ASSERT(b);
9070     if (!b) return;
9071     if (b->use_clipping) {
9072         const struct nk_rect *c = &b->clip;
9073         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))
9074             return;
9075     }
9076 
9077     cmd = (struct nk_command_custom*)
9078         nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
9079     if (!cmd) return;
9080     cmd->x = (short)r.x;
9081     cmd->y = (short)r.y;
9082     cmd->w = (unsigned short)NK_MAX(0, r.w);
9083     cmd->h = (unsigned short)NK_MAX(0, r.h);
9084     cmd->callback_data = usr;
9085     cmd->callback = cb;
9086 }
9087 
9088 NK_API void
9089 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
9090     const char *string, int length, const struct nk_user_font *font,
9091     struct nk_color bg, struct nk_color fg)
9092 {
9093     float text_width = 0;
9094     struct nk_command_text *cmd;
9095 
9096     NK_ASSERT(b);
9097     NK_ASSERT(font);
9098     if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
9099     if (b->use_clipping) {
9100         const struct nk_rect *c = &b->clip;
9101         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))
9102             return;
9103     }
9104 
9105     /* make sure text fits inside bounds */
9106     text_width = font->width(font->userdata, font->height, string, length);
9107     if (text_width > r.w){
9108         int glyphs = 0;
9109         float txt_width = (float)text_width;
9110         length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
9111     }
9112 
9113     if (!length) return;
9114     cmd = (struct nk_command_text*)
9115         nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
9116     if (!cmd) return;
9117     cmd->x = (short)r.x;
9118     cmd->y = (short)r.y;
9119     cmd->w = (unsigned short)r.w;
9120     cmd->h = (unsigned short)r.h;
9121     cmd->background = bg;
9122     cmd->foreground = fg;
9123     cmd->font = font;
9124     cmd->length = length;
9125     cmd->height = font->height;
9126     NK_MEMCPY(cmd->string, string, (nk_size)length);
9127     cmd->string[length] = '\0';
9128 }
9129 
9130 /* ==============================================================
9131  *
9132  *                          DRAW LIST
9133  *
9134  * ===============================================================*/
9135 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
9136 NK_API void
9137 nk_draw_list_init(struct nk_draw_list *list)
9138 {
9139     nk_size i = 0;
9140     NK_ASSERT(list);
9141     if (!list) return;
9142     nk_zero(list, sizeof(*list));
9143     for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
9144         const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
9145         list->circle_vtx[i].x = (float)NK_COS(a);
9146         list->circle_vtx[i].y = (float)NK_SIN(a);
9147     }
9148 }
9149 
9150 NK_API void
9151 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
9152     struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
9153     enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
9154 {
9155     NK_ASSERT(canvas);
9156     NK_ASSERT(config);
9157     NK_ASSERT(cmds);
9158     NK_ASSERT(vertices);
9159     NK_ASSERT(elements);
9160     if (!canvas || !config || !cmds || !vertices || !elements)
9161         return;
9162 
9163     canvas->buffer = cmds;
9164     canvas->config = *config;
9165     canvas->elements = elements;
9166     canvas->vertices = vertices;
9167     canvas->line_AA = line_aa;
9168     canvas->shape_AA = shape_aa;
9169     canvas->clip_rect = nk_null_rect;
9170 }
9171 
9172 NK_API const struct nk_draw_command*
9173 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
9174 {
9175     nk_byte *memory;
9176     nk_size offset;
9177     const struct nk_draw_command *cmd;
9178 
9179     NK_ASSERT(buffer);
9180     if (!buffer || !buffer->size || !canvas->cmd_count)
9181         return 0;
9182 
9183     memory = (nk_byte*)buffer->memory.ptr;
9184     offset = buffer->memory.size - canvas->cmd_offset;
9185     cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
9186     return cmd;
9187 }
9188 
9189 NK_API const struct nk_draw_command*
9190 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
9191 {
9192     nk_size size;
9193     nk_size offset;
9194     nk_byte *memory;
9195     const struct nk_draw_command *end;
9196 
9197     NK_ASSERT(buffer);
9198     NK_ASSERT(canvas);
9199     if (!buffer || !canvas)
9200         return 0;
9201 
9202     memory = (nk_byte*)buffer->memory.ptr;
9203     size = buffer->memory.size;
9204     offset = size - canvas->cmd_offset;
9205     end = nk_ptr_add(const struct nk_draw_command, memory, offset);
9206     end -= (canvas->cmd_count-1);
9207     return end;
9208 }
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 
9225 NK_API void
9226 nk_draw_list_clear(struct nk_draw_list *list)
9227 {
9228     NK_ASSERT(list);
9229     if (!list) return;
9230     if (list->buffer)
9231         nk_buffer_clear(list->buffer);
9232     if (list->vertices)
9233         nk_buffer_clear(list->vertices);
9234     if (list->elements)
9235         nk_buffer_clear(list->elements);
9236 
9237     list->element_count = 0;
9238     list->vertex_count = 0;
9239     list->cmd_offset = 0;
9240     list->cmd_count = 0;
9241     list->path_count = 0;
9242     list->vertices = 0;
9243     list->elements = 0;
9244     list->clip_rect = nk_null_rect;
9245 }
9246 
9247 NK_INTERN struct nk_vec2*
9248 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
9249 {
9250     struct nk_vec2 *points;
9251     NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
9252     NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
9253     points = (struct nk_vec2*)
9254         nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
9255                         point_size * (nk_size)count, point_align);
9256 
9257     if (!points) return 0;
9258     if (!list->path_offset) {
9259         void *memory = nk_buffer_memory(list->buffer);
9260         list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
9261     }
9262     list->path_count += (unsigned int)count;
9263     return points;
9264 }
9265 
9266 NK_INTERN struct nk_vec2
9267 nk_draw_list_path_last(struct nk_draw_list *list)
9268 {
9269     void *memory;
9270     struct nk_vec2 *point;
9271     NK_ASSERT(list->path_count);
9272     memory = nk_buffer_memory(list->buffer);
9273     point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
9274     point += (list->path_count-1);
9275     return *point;
9276 }
9277 
9278 NK_INTERN struct nk_draw_command*
9279 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
9280     nk_handle texture)
9281 {
9282     NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
9283     NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
9284     struct nk_draw_command *cmd;
9285 
9286     NK_ASSERT(list);
9287     cmd = (struct nk_draw_command*)
9288         nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
9289 
9290     if (!cmd) return 0;
9291     if (!list->cmd_count) {
9292         nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
9293         nk_size total = nk_buffer_total(list->buffer);
9294         memory = nk_ptr_add(nk_byte, memory, total);
9295         list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
9296     }
9297 
9298     cmd->elem_count = 0;
9299     cmd->clip_rect = clip;
9300     cmd->texture = texture;
9301 #ifdef NK_INCLUDE_COMMAND_USERDATA
9302     cmd->userdata = list->userdata;
9303 #endif
9304 
9305     list->cmd_count++;
9306     list->clip_rect = clip;
9307     return cmd;
9308 }
9309 
9310 NK_INTERN struct nk_draw_command*
9311 nk_draw_list_command_last(struct nk_draw_list *list)
9312 {
9313     void *memory;
9314     nk_size size;
9315     struct nk_draw_command *cmd;
9316     NK_ASSERT(list->cmd_count);
9317 
9318     memory = nk_buffer_memory(list->buffer);
9319     size = nk_buffer_total(list->buffer);
9320     cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
9321     return (cmd - (list->cmd_count-1));
9322 }
9323 
9324 NK_INTERN void
9325 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
9326 {
9327     NK_ASSERT(list);
9328     if (!list) return;
9329     if (!list->cmd_count) {
9330         nk_draw_list_push_command(list, rect, list->config.null.texture);
9331     } else {
9332         struct nk_draw_command *prev = nk_draw_list_command_last(list);
9333         if (prev->elem_count == 0)
9334             prev->clip_rect = rect;
9335         nk_draw_list_push_command(list, rect, prev->texture);
9336     }
9337 }
9338 
9339 NK_INTERN void
9340 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
9341 {
9342     NK_ASSERT(list);
9343     if (!list) return;
9344     if (!list->cmd_count) {
9345         nk_draw_list_push_command(list, nk_null_rect, texture);
9346     } else {
9347         struct nk_draw_command *prev = nk_draw_list_command_last(list);
9348         if (prev->elem_count == 0) {
9349             prev->texture = texture;
9350         #ifdef NK_INCLUDE_COMMAND_USERDATA
9351             prev->userdata = list->userdata;
9352         #endif
9353     } else if (prev->texture.id != texture.id
9354         #ifdef NK_INCLUDE_COMMAND_USERDATA
9355             || prev->userdata.id != list->userdata.id
9356         #endif
9357         ) nk_draw_list_push_command(list, prev->clip_rect, texture);
9358     }
9359 }
9360 
9361 #ifdef NK_INCLUDE_COMMAND_USERDATA
9362 NK_API void
9363 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
9364 {
9365     list->userdata = userdata;
9366 }
9367 #endif
9368 
9369 NK_INTERN void*
9370 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
9371 {
9372     void *vtx;
9373     NK_ASSERT(list);
9374     if (!list) return 0;
9375     vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
9376         list->config.vertex_size*count, list->config.vertex_alignment);
9377     if (!vtx) return 0;
9378     list->vertex_count += (unsigned int)count;
9379     return vtx;
9380 }
9381 
9382 NK_INTERN nk_draw_index*
9383 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
9384 {
9385     nk_draw_index *ids;
9386     struct nk_draw_command *cmd;
9387     NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
9388     NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
9389     NK_ASSERT(list);
9390     if (!list) return 0;
9391 
9392     ids = (nk_draw_index*)
9393         nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
9394     if (!ids) return 0;
9395     cmd = nk_draw_list_command_last(list);
9396     list->element_count += (unsigned int)count;
9397     cmd->elem_count += (unsigned int)count;
9398     return ids;
9399 }
9400 
9401 NK_INTERN int
9402 nk_draw_vertex_layout_element_is_end_of_layout(
9403     const struct nk_draw_vertex_layout_element *element)
9404 {
9405     return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
9406             element->format == NK_FORMAT_COUNT);
9407 }
9408 
9409 NK_INTERN void
9410 nk_draw_vertex_color(void *attr, const float *vals,
9411     enum nk_draw_vertex_layout_format format)
9412 {
9413     /* if this triggers you tried to provide a value format for a color */
9414     float val[4];
9415     NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
9416     NK_ASSERT(format <= NK_FORMAT_COLOR_END);
9417     if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
9418 
9419     val[0] = NK_SATURATE(vals[0]);
9420     val[1] = NK_SATURATE(vals[1]);
9421     val[2] = NK_SATURATE(vals[2]);
9422     val[3] = NK_SATURATE(vals[3]);
9423 
9424     switch (format) {
9425     default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
9426     case NK_FORMAT_R8G8B8A8:
9427     case NK_FORMAT_R8G8B8: {
9428         struct nk_color col = nk_rgba_fv(val);
9429         NK_MEMCPY(attr, &col.r, sizeof(col));
9430     } break;
9431     case NK_FORMAT_B8G8R8A8: {
9432         struct nk_color col = nk_rgba_fv(val);
9433         struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
9434         NK_MEMCPY(attr, &bgra, sizeof(bgra));
9435     } break;
9436     case NK_FORMAT_R16G15B16: {
9437         nk_ushort col[3];
9438         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
9439         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
9440         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
9441         NK_MEMCPY(attr, col, sizeof(col));
9442     } break;
9443     case NK_FORMAT_R16G15B16A16: {
9444         nk_ushort col[4];
9445         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
9446         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
9447         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
9448         col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX);
9449         NK_MEMCPY(attr, col, sizeof(col));
9450     } break;
9451     case NK_FORMAT_R32G32B32: {
9452         nk_uint col[3];
9453         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
9454         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
9455         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
9456         NK_MEMCPY(attr, col, sizeof(col));
9457     } break;
9458     case NK_FORMAT_R32G32B32A32: {
9459         nk_uint col[4];
9460         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
9461         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
9462         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
9463         col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX);
9464         NK_MEMCPY(attr, col, sizeof(col));
9465     } break;
9466     case NK_FORMAT_R32G32B32A32_FLOAT:
9467         NK_MEMCPY(attr, val, sizeof(float)*4);
9468         break;
9469     case NK_FORMAT_R32G32B32A32_DOUBLE: {
9470         double col[4];
9471         col[0] = (double)val[0];
9472         col[1] = (double)val[1];
9473         col[2] = (double)val[2];
9474         col[3] = (double)val[3];
9475         NK_MEMCPY(attr, col, sizeof(col));
9476     } break;
9477     case NK_FORMAT_RGB32:
9478     case NK_FORMAT_RGBA32: {
9479         struct nk_color col = nk_rgba_fv(val);
9480         nk_uint color = nk_color_u32(col);
9481         NK_MEMCPY(attr, &color, sizeof(color));
9482     } break; }
9483 }
9484 
9485 NK_INTERN void
9486 nk_draw_vertex_element(void *dst, const float *values, int value_count,
9487     enum nk_draw_vertex_layout_format format)
9488 {
9489     int value_index;
9490     void *attribute = dst;
9491     /* if this triggers you tried to provide a color format for a value */
9492     NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
9493     if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
9494     for (value_index = 0; value_index < value_count; ++value_index) {
9495         switch (format) {
9496         default: NK_ASSERT(0 && "invalid vertex layout format"); break;
9497         case NK_FORMAT_SCHAR: {
9498             char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX);
9499             NK_MEMCPY(attribute, &value, sizeof(value));
9500             attribute = (void*)((char*)attribute + sizeof(char));
9501         } break;
9502         case NK_FORMAT_SSHORT: {
9503             nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX);
9504             NK_MEMCPY(attribute, &value, sizeof(value));
9505             attribute = (void*)((char*)attribute + sizeof(value));
9506         } break;
9507         case NK_FORMAT_SINT: {
9508             nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX);
9509             NK_MEMCPY(attribute, &value, sizeof(value));
9510             attribute = (void*)((char*)attribute + sizeof(nk_int));
9511         } break;
9512         case NK_FORMAT_UCHAR: {
9513             unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX);
9514             NK_MEMCPY(attribute, &value, sizeof(value));
9515             attribute = (void*)((char*)attribute + sizeof(unsigned char));
9516         } break;
9517         case NK_FORMAT_USHORT: {
9518             nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX);
9519             NK_MEMCPY(attribute, &value, sizeof(value));
9520             attribute = (void*)((char*)attribute + sizeof(value));
9521             } break;
9522         case NK_FORMAT_UINT: {
9523             nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX);
9524             NK_MEMCPY(attribute, &value, sizeof(value));
9525             attribute = (void*)((char*)attribute + sizeof(nk_uint));
9526         } break;
9527         case NK_FORMAT_FLOAT:
9528             NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
9529             attribute = (void*)((char*)attribute + sizeof(float));
9530             break;
9531         case NK_FORMAT_DOUBLE: {
9532             double value = (double)values[value_index];
9533             NK_MEMCPY(attribute, &value, sizeof(value));
9534             attribute = (void*)((char*)attribute + sizeof(double));
9535             } break;
9536         }
9537     }
9538 }
9539 
9540 NK_INTERN void*
9541 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
9542     struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
9543 {
9544     void *result = (void*)((char*)dst + config->vertex_size);
9545     const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
9546     while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
9547         void *address = (void*)((char*)dst + elem_iter->offset);
9548         switch (elem_iter->attribute) {
9549         case NK_VERTEX_ATTRIBUTE_COUNT:
9550         default: NK_ASSERT(0 && "wrong element attribute"); break;
9551         case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
9552         case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
9553         case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
9554         }
9555         elem_iter++;
9556     }
9557     return result;
9558 }
9559 
9560 NK_API void
9561 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
9562     const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
9563     float thickness, enum nk_anti_aliasing aliasing)
9564 {
9565     nk_size count;
9566     int thick_line;
9567     struct nk_colorf col;
9568     struct nk_colorf col_trans;
9569     NK_ASSERT(list);
9570     if (!list || points_count < 2) return;
9571 
9572     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9573     count = points_count;
9574     if (!closed) count = points_count-1;
9575     thick_line = thickness > 1.0f;
9576 
9577 #ifdef NK_INCLUDE_COMMAND_USERDATA
9578     nk_draw_list_push_userdata(list, list->userdata);
9579 #endif
9580 
9581     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9582     nk_color_fv(&col.r, color);
9583     col_trans = col;
9584     col_trans.a = 0;
9585 
9586     if (aliasing == NK_ANTI_ALIASING_ON) {
9587         /* ANTI-ALIASED STROKE */
9588         const float AA_SIZE = 1.0f;
9589         NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
9590         NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
9591 
9592         /* allocate vertices and elements  */
9593         nk_size i1 = 0;
9594         nk_size vertex_offset;
9595         nk_size index = list->vertex_count;
9596 
9597         const nk_size idx_count = (thick_line) ?  (count * 18) : (count * 12);
9598         const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
9599 
9600         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9601         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9602 
9603         nk_size size;
9604         struct nk_vec2 *normals, *temp;
9605         if (!vtx || !ids) return;
9606 
9607         /* temporary allocate normals + points */
9608         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
9609         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
9610         size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
9611         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
9612         NK_ASSERT(normals);
9613         if (!normals) return;
9614         temp = normals + points_count;
9615 
9616         /* make sure vertex pointer is still correct */
9617         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
9618 
9619         /* calculate normals */
9620         for (i1 = 0; i1 < count; ++i1) {
9621             const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
9622             struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
9623             float len;
9624 
9625             /* vec2 inverted length  */
9626             len = nk_vec2_len_sqr(diff);
9627             if (len != 0.0f)
9628                 len = nk_inv_sqrt(len);
9629             else len = 1.0f;
9630 
9631             diff = nk_vec2_muls(diff, len);
9632             normals[i1].x = diff.y;
9633             normals[i1].y = -diff.x;
9634         }
9635 
9636         if (!closed)
9637             normals[points_count-1] = normals[points_count-2];
9638 
9639         if (!thick_line) {
9640             nk_size idx1, i;
9641             if (!closed) {
9642                 struct nk_vec2 d;
9643                 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
9644                 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
9645                 d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
9646                 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
9647                 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
9648             }
9649 
9650             /* fill elements */
9651             idx1 = index;
9652             for (i1 = 0; i1 < count; i1++) {
9653                 struct nk_vec2 dm;
9654                 float dmr2;
9655                 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
9656                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
9657 
9658                 /* average normals */
9659                 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
9660                 dmr2 = dm.x * dm.x + dm.y* dm.y;
9661                 if (dmr2 > 0.000001f) {
9662                     float scale = 1.0f/dmr2;
9663                     scale = NK_MIN(100.0f, scale);
9664                     dm = nk_vec2_muls(dm, scale);
9665                 }
9666 
9667                 dm = nk_vec2_muls(dm, AA_SIZE);
9668                 temp[i2*2+0] = nk_vec2_add(points[i2], dm);
9669                 temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
9670 
9671                 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
9672                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
9673                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
9674                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
9675                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
9676                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
9677                 ids += 12;
9678                 idx1 = idx2;
9679             }
9680 
9681             /* fill vertices */
9682             for (i = 0; i < points_count; ++i) {
9683                 const struct nk_vec2 uv = list->config.null.uv;
9684                 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
9685                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
9686                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
9687             }
9688         } else {
9689             nk_size idx1, i;
9690             const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
9691             if (!closed) {
9692                 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
9693                 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
9694 
9695                 temp[0] = nk_vec2_add(points[0], d1);
9696                 temp[1] = nk_vec2_add(points[0], d2);
9697                 temp[2] = nk_vec2_sub(points[0], d2);
9698                 temp[3] = nk_vec2_sub(points[0], d1);
9699 
9700                 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
9701                 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
9702 
9703                 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
9704                 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
9705                 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
9706                 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
9707             }
9708 
9709             /* add all elements */
9710             idx1 = index;
9711             for (i1 = 0; i1 < count; ++i1) {
9712                 struct nk_vec2 dm_out, dm_in;
9713                 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
9714                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
9715 
9716                 /* average normals */
9717                 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
9718                 float dmr2 = dm.x * dm.x + dm.y* dm.y;
9719                 if (dmr2 > 0.000001f) {
9720                     float scale = 1.0f/dmr2;
9721                     scale = NK_MIN(100.0f, scale);
9722                     dm = nk_vec2_muls(dm, scale);
9723                 }
9724 
9725                 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
9726                 dm_in = nk_vec2_muls(dm, half_inner_thickness);
9727                 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
9728                 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
9729                 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
9730                 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
9731 
9732                 /* add indexes */
9733                 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
9734                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
9735                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
9736                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
9737                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
9738                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
9739                 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
9740                 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
9741                 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
9742                 ids += 18;
9743                 idx1 = idx2;
9744             }
9745 
9746             /* add vertices */
9747             for (i = 0; i < points_count; ++i) {
9748                 const struct nk_vec2 uv = list->config.null.uv;
9749                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
9750                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
9751                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
9752                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
9753             }
9754         }
9755         /* free temporary normals + points */
9756         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
9757     } else {
9758         /* NON ANTI-ALIASED STROKE */
9759         nk_size i1 = 0;
9760         nk_size idx = list->vertex_count;
9761         const nk_size idx_count = count * 6;
9762         const nk_size vtx_count = count * 4;
9763         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9764         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9765         if (!vtx || !ids) return;
9766 
9767         for (i1 = 0; i1 < count; ++i1) {
9768             float dx, dy;
9769             const struct nk_vec2 uv = list->config.null.uv;
9770             const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
9771             const struct nk_vec2 p1 = points[i1];
9772             const struct nk_vec2 p2 = points[i2];
9773             struct nk_vec2 diff = nk_vec2_sub(p2, p1);
9774             float len;
9775 
9776             /* vec2 inverted length  */
9777             len = nk_vec2_len_sqr(diff);
9778             if (len != 0.0f)
9779                 len = nk_inv_sqrt(len);
9780             else len = 1.0f;
9781             diff = nk_vec2_muls(diff, len);
9782 
9783             /* add vertices */
9784             dx = diff.x * (thickness * 0.5f);
9785             dy = diff.y * (thickness * 0.5f);
9786 
9787             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
9788             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
9789             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
9790             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
9791 
9792             ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
9793             ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
9794             ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
9795 
9796             ids += 6;
9797             idx += 4;
9798         }
9799     }
9800 }
9801 
9802 NK_API void
9803 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
9804     const struct nk_vec2 *points, const unsigned int points_count,
9805     struct nk_color color, enum nk_anti_aliasing aliasing)
9806 {
9807     struct nk_colorf col;
9808     struct nk_colorf col_trans;
9809 
9810     NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
9811     NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
9812     NK_ASSERT(list);
9813     if (!list || points_count < 3) return;
9814 
9815 #ifdef NK_INCLUDE_COMMAND_USERDATA
9816     nk_draw_list_push_userdata(list, list->userdata);
9817 #endif
9818 
9819     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9820     nk_color_fv(&col.r, color);
9821     col_trans = col;
9822     col_trans.a = 0;
9823 
9824     if (aliasing == NK_ANTI_ALIASING_ON) {
9825         nk_size i = 0;
9826         nk_size i0 = 0;
9827         nk_size i1 = 0;
9828 
9829         const float AA_SIZE = 1.0f;
9830         nk_size vertex_offset = 0;
9831         nk_size index = list->vertex_count;
9832 
9833         const nk_size idx_count = (points_count-2)*3 + points_count*6;
9834         const nk_size vtx_count = (points_count*2);
9835 
9836         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9837         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9838 
9839         nk_size size = 0;
9840         struct nk_vec2 *normals = 0;
9841         unsigned int vtx_inner_idx = (unsigned int)(index + 0);
9842         unsigned int vtx_outer_idx = (unsigned int)(index + 1);
9843         if (!vtx || !ids) return;
9844 
9845         /* temporary allocate normals */
9846         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
9847         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
9848         size = pnt_size * points_count;
9849         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
9850         NK_ASSERT(normals);
9851         if (!normals) return;
9852         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
9853 
9854         /* add elements */
9855         for (i = 2; i < points_count; i++) {
9856             ids[0] = (nk_draw_index)(vtx_inner_idx);
9857             ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
9858             ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
9859             ids += 3;
9860         }
9861 
9862         /* compute normals */
9863         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
9864             struct nk_vec2 p0 = points[i0];
9865             struct nk_vec2 p1 = points[i1];
9866             struct nk_vec2 diff = nk_vec2_sub(p1, p0);
9867 
9868             /* vec2 inverted length  */
9869             float len = nk_vec2_len_sqr(diff);
9870             if (len != 0.0f)
9871                 len = nk_inv_sqrt(len);
9872             else len = 1.0f;
9873             diff = nk_vec2_muls(diff, len);
9874 
9875             normals[i0].x = diff.y;
9876             normals[i0].y = -diff.x;
9877         }
9878 
9879         /* add vertices + indexes */
9880         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
9881             const struct nk_vec2 uv = list->config.null.uv;
9882             struct nk_vec2 n0 = normals[i0];
9883             struct nk_vec2 n1 = normals[i1];
9884             struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
9885             float dmr2 = dm.x*dm.x + dm.y*dm.y;
9886             if (dmr2 > 0.000001f) {
9887                 float scale = 1.0f / dmr2;
9888                 scale = NK_MIN(scale, 100.0f);
9889                 dm = nk_vec2_muls(dm, scale);
9890             }
9891             dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
9892 
9893             /* add vertices */
9894             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
9895             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
9896 
9897             /* add indexes */
9898             ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
9899             ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
9900             ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
9901             ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
9902             ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
9903             ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
9904             ids += 6;
9905         }
9906         /* free temporary normals + points */
9907         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
9908     } else {
9909         nk_size i = 0;
9910         nk_size index = list->vertex_count;
9911         const nk_size idx_count = (points_count-2)*3;
9912         const nk_size vtx_count = points_count;
9913         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9914         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9915 
9916         if (!vtx || !ids) return;
9917         for (i = 0; i < vtx_count; ++i)
9918             vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
9919         for (i = 2; i < points_count; ++i) {
9920             ids[0] = (nk_draw_index)index;
9921             ids[1] = (nk_draw_index)(index+ i - 1);
9922             ids[2] = (nk_draw_index)(index+i);
9923             ids += 3;
9924         }
9925     }
9926 }
9927 
9928 NK_API void
9929 nk_draw_list_path_clear(struct nk_draw_list *list)
9930 {
9931     NK_ASSERT(list);
9932     if (!list) return;
9933     nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
9934     list->path_count = 0;
9935     list->path_offset = 0;
9936 }
9937 
9938 NK_API void
9939 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
9940 {
9941     struct nk_vec2 *points = 0;
9942     struct nk_draw_command *cmd = 0;
9943     NK_ASSERT(list);
9944     if (!list) return;
9945     if (!list->cmd_count)
9946         nk_draw_list_add_clip(list, nk_null_rect);
9947 
9948     cmd = nk_draw_list_command_last(list);
9949     if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
9950         nk_draw_list_push_image(list, list->config.null.texture);
9951 
9952     points = nk_draw_list_alloc_path(list, 1);
9953     if (!points) return;
9954     points[0] = pos;
9955 }
9956 
9957 NK_API void
9958 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
9959     float radius, int a_min, int a_max)
9960 {
9961     int a = 0;
9962     NK_ASSERT(list);
9963     if (!list) return;
9964     if (a_min <= a_max) {
9965         for (a = a_min; a <= a_max; a++) {
9966             const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
9967             const float x = center.x + c.x * radius;
9968             const float y = center.y + c.y * radius;
9969             nk_draw_list_path_line_to(list, nk_vec2(x, y));
9970         }
9971     }
9972 }
9973 
9974 NK_API void
9975 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
9976     float radius, float a_min, float a_max, unsigned int segments)
9977 {
9978     unsigned int i = 0;
9979     NK_ASSERT(list);
9980     if (!list) return;
9981     if (radius == 0.0f) return;
9982 
9983     /*  This algorithm for arc drawing relies on these two trigonometric identities[1]:
9984             sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
9985             cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
9986 
9987         Two coordinates (x, y) of a point on a circle centered on
9988         the origin can be written in polar form as:
9989             x = r * cos(a)
9990             y = r * sin(a)
9991         where r is the radius of the circle,
9992             a is the angle between (x, y) and the origin.
9993 
9994         This allows us to rotate the coordinates around the
9995         origin by an angle b using the following transformation:
9996             x' = r * cos(a + b) = x * cos(b) - y * sin(b)
9997             y' = r * sin(a + b) = y * cos(b) + x * sin(b)
9998 
9999         [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
10000     */
10001     {const float d_angle = (a_max - a_min) / (float)segments;
10002     const float sin_d = (float)NK_SIN(d_angle);
10003     const float cos_d = (float)NK_COS(d_angle);
10004 
10005     float cx = (float)NK_COS(a_min) * radius;
10006     float cy = (float)NK_SIN(a_min) * radius;
10007     for(i = 0; i <= segments; ++i) {
10008         float new_cx, new_cy;
10009         const float x = center.x + cx;
10010         const float y = center.y + cy;
10011         nk_draw_list_path_line_to(list, nk_vec2(x, y));
10012 
10013         new_cx = cx * cos_d - cy * sin_d;
10014         new_cy = cy * cos_d + cx * sin_d;
10015         cx = new_cx;
10016         cy = new_cy;
10017     }}
10018 }
10019 
10020 NK_API void
10021 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
10022     struct nk_vec2 b, float rounding)
10023 {
10024     float r;
10025     NK_ASSERT(list);
10026     if (!list) return;
10027     r = rounding;
10028     r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
10029     r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
10030 
10031     if (r == 0.0f) {
10032         nk_draw_list_path_line_to(list, a);
10033         nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
10034         nk_draw_list_path_line_to(list, b);
10035         nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
10036     } else {
10037         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
10038         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
10039         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
10040         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
10041     }
10042 }
10043 
10044 NK_API void
10045 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
10046     struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
10047 {
10048     float t_step;
10049     unsigned int i_step;
10050     struct nk_vec2 p1;
10051 
10052     NK_ASSERT(list);
10053     NK_ASSERT(list->path_count);
10054     if (!list || !list->path_count) return;
10055     num_segments = NK_MAX(num_segments, 1);
10056 
10057     p1 = nk_draw_list_path_last(list);
10058     t_step = 1.0f/(float)num_segments;
10059     for (i_step = 1; i_step <= num_segments; ++i_step) {
10060         float t = t_step * (float)i_step;
10061         float u = 1.0f - t;
10062         float w1 = u*u*u;
10063         float w2 = 3*u*u*t;
10064         float w3 = 3*u*t*t;
10065         float w4 = t * t *t;
10066         float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
10067         float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
10068         nk_draw_list_path_line_to(list, nk_vec2(x,y));
10069     }
10070 }
10071 
10072 NK_API void
10073 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
10074 {
10075     struct nk_vec2 *points;
10076     NK_ASSERT(list);
10077     if (!list) return;
10078     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
10079     nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
10080     nk_draw_list_path_clear(list);
10081 }
10082 
10083 NK_API void
10084 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
10085     enum nk_draw_list_stroke closed, float thickness)
10086 {
10087     struct nk_vec2 *points;
10088     NK_ASSERT(list);
10089     if (!list) return;
10090     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
10091     nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
10092         closed, thickness, list->config.line_AA);
10093     nk_draw_list_path_clear(list);
10094 }
10095 
10096 NK_API void
10097 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
10098     struct nk_vec2 b, struct nk_color col, float thickness)
10099 {
10100     NK_ASSERT(list);
10101     if (!list || !col.a) return;
10102     if (list->line_AA == NK_ANTI_ALIASING_ON) {
10103         nk_draw_list_path_line_to(list, a);
10104         nk_draw_list_path_line_to(list, b);
10105     } else {
10106         nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
10107         nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
10108     }
10109     nk_draw_list_path_stroke(list,  col, NK_STROKE_OPEN, thickness);
10110 }
10111 
10112 NK_API void
10113 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
10114     struct nk_color col, float rounding)
10115 {
10116     NK_ASSERT(list);
10117     if (!list || !col.a) return;
10118 
10119     if (list->line_AA == NK_ANTI_ALIASING_ON) {
10120         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
10121             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10122     } else {
10123         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
10124             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10125     } nk_draw_list_path_fill(list,  col);
10126 }
10127 
10128 NK_API void
10129 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
10130     struct nk_color col, float rounding, float thickness)
10131 {
10132     NK_ASSERT(list);
10133     if (!list || !col.a) return;
10134     if (list->line_AA == NK_ANTI_ALIASING_ON) {
10135         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
10136             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10137     } else {
10138         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
10139             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10140     } nk_draw_list_path_stroke(list,  col, NK_STROKE_CLOSED, thickness);
10141 }
10142 
10143 NK_API void
10144 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
10145     struct nk_color left, struct nk_color top, struct nk_color right,
10146     struct nk_color bottom)
10147 {
10148     void *vtx;
10149     struct nk_colorf col_left, col_top;
10150     struct nk_colorf col_right, col_bottom;
10151     nk_draw_index *idx;
10152     nk_draw_index index;
10153 
10154     nk_color_fv(&col_left.r, left);
10155     nk_color_fv(&col_right.r, right);
10156     nk_color_fv(&col_top.r, top);
10157     nk_color_fv(&col_bottom.r, bottom);
10158 
10159     NK_ASSERT(list);
10160     if (!list) return;
10161 
10162     nk_draw_list_push_image(list, list->config.null.texture);
10163     index = (nk_draw_index)list->vertex_count;
10164     vtx = nk_draw_list_alloc_vertices(list, 4);
10165     idx = nk_draw_list_alloc_elements(list, 6);
10166     if (!vtx || !idx) return;
10167 
10168     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
10169     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
10170     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
10171 
10172     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
10173     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
10174     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
10175     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
10176 }
10177 
10178 NK_API void
10179 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
10180     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
10181 {
10182     NK_ASSERT(list);
10183     if (!list || !col.a) return;
10184     nk_draw_list_path_line_to(list, a);
10185     nk_draw_list_path_line_to(list, b);
10186     nk_draw_list_path_line_to(list, c);
10187     nk_draw_list_path_fill(list, col);
10188 }
10189 
10190 NK_API void
10191 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
10192     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
10193 {
10194     NK_ASSERT(list);
10195     if (!list || !col.a) return;
10196     nk_draw_list_path_line_to(list, a);
10197     nk_draw_list_path_line_to(list, b);
10198     nk_draw_list_path_line_to(list, c);
10199     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10200 }
10201 
10202 NK_API void
10203 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
10204     float radius, struct nk_color col, unsigned int segs)
10205 {
10206     float a_max;
10207     NK_ASSERT(list);
10208     if (!list || !col.a) return;
10209     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
10210     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
10211     nk_draw_list_path_fill(list, col);
10212 }
10213 
10214 NK_API void
10215 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
10216     float radius, struct nk_color col, unsigned int segs, float thickness)
10217 {
10218     float a_max;
10219     NK_ASSERT(list);
10220     if (!list || !col.a) return;
10221     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
10222     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
10223     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10224 }
10225 
10226 NK_API void
10227 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
10228     struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
10229     struct nk_color col, unsigned int segments, float thickness)
10230 {
10231     NK_ASSERT(list);
10232     if (!list || !col.a) return;
10233     nk_draw_list_path_line_to(list, p0);
10234     nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
10235     nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
10236 }
10237 
10238 NK_INTERN void
10239 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
10240     struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
10241     struct nk_color color)
10242 {
10243     void *vtx;
10244     struct nk_vec2 uvb;
10245     struct nk_vec2 uvd;
10246     struct nk_vec2 b;
10247     struct nk_vec2 d;
10248 
10249     struct nk_colorf col;
10250     nk_draw_index *idx;
10251     nk_draw_index index;
10252     NK_ASSERT(list);
10253     if (!list) return;
10254 
10255     nk_color_fv(&col.r, color);
10256     uvb = nk_vec2(uvc.x, uva.y);
10257     uvd = nk_vec2(uva.x, uvc.y);
10258     b = nk_vec2(c.x, a.y);
10259     d = nk_vec2(a.x, c.y);
10260 
10261     index = (nk_draw_index)list->vertex_count;
10262     vtx = nk_draw_list_alloc_vertices(list, 4);
10263     idx = nk_draw_list_alloc_elements(list, 6);
10264     if (!vtx || !idx) return;
10265 
10266     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
10267     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
10268     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
10269 
10270     vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
10271     vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
10272     vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
10273     vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
10274 }
10275 
10276 NK_API void
10277 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
10278     struct nk_rect rect, struct nk_color color)
10279 {
10280     NK_ASSERT(list);
10281     if (!list) return;
10282     /* push new command with given texture */
10283     nk_draw_list_push_image(list, texture.handle);
10284     if (nk_image_is_subimage(&texture)) {
10285         /* add region inside of the texture  */
10286         struct nk_vec2 uv[2];
10287         uv[0].x = (float)texture.region[0]/(float)texture.w;
10288         uv[0].y = (float)texture.region[1]/(float)texture.h;
10289         uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
10290         uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
10291         nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
10292             nk_vec2(rect.x + rect.w, rect.y + rect.h),  uv[0], uv[1], color);
10293     } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
10294             nk_vec2(rect.x + rect.w, rect.y + rect.h),
10295             nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
10296 }
10297 
10298 NK_API void
10299 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
10300     struct nk_rect rect, const char *text, int len, float font_height,
10301     struct nk_color fg)
10302 {
10303     float x = 0;
10304     int text_len = 0;
10305     nk_rune unicode = 0;
10306     nk_rune next = 0;
10307     int glyph_len = 0;
10308     int next_glyph_len = 0;
10309     struct nk_user_font_glyph g;
10310 
10311     NK_ASSERT(list);
10312     if (!list || !len || !text) return;
10313     if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
10314         list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
10315 
10316     nk_draw_list_push_image(list, font->texture);
10317     x = rect.x;
10318     glyph_len = nk_utf_decode(text, &unicode, len);
10319     if (!glyph_len) return;
10320 
10321     /* draw every glyph image */
10322     fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
10323     while (text_len < len && glyph_len) {
10324         float gx, gy, gh, gw;
10325         float char_width = 0;
10326         if (unicode == NK_UTF_INVALID) break;
10327 
10328         /* query currently drawn glyph information */
10329         next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
10330         font->query(font->userdata, font_height, &g, unicode,
10331                     (next == NK_UTF_INVALID) ? '\0' : next);
10332 
10333         /* calculate and draw glyph drawing rectangle and image */
10334         gx = x + g.offset.x;
10335         gy = rect.y + g.offset.y;
10336         gw = g.width; gh = g.height;
10337         char_width = g.xadvance;
10338         nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
10339             g.uv[0], g.uv[1], fg);
10340 
10341         /* offset next glyph */
10342         text_len += glyph_len;
10343         x += char_width;
10344         glyph_len = next_glyph_len;
10345         unicode = next;
10346     }
10347 }
10348 
10349 NK_API nk_flags
10350 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
10351     struct nk_buffer *vertices, struct nk_buffer *elements,
10352     const struct nk_convert_config *config)
10353 {
10354     nk_flags res = NK_CONVERT_SUCCESS;
10355     const struct nk_command *cmd;
10356     NK_ASSERT(ctx);
10357     NK_ASSERT(cmds);
10358     NK_ASSERT(vertices);
10359     NK_ASSERT(elements);
10360     NK_ASSERT(config);
10361     NK_ASSERT(config->vertex_layout);
10362     NK_ASSERT(config->vertex_size);
10363     if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
10364         return NK_CONVERT_INVALID_PARAM;
10365 
10366     nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
10367         config->line_AA, config->shape_AA);
10368     nk_foreach(cmd, ctx)
10369     {
10370 #ifdef NK_INCLUDE_COMMAND_USERDATA
10371         ctx->draw_list.userdata = cmd->userdata;
10372 #endif
10373         switch (cmd->type) {
10374         case NK_COMMAND_NOP: break;
10375         case NK_COMMAND_SCISSOR: {
10376             const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
10377             nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
10378         } break;
10379         case NK_COMMAND_LINE: {
10380             const struct nk_command_line *l = (const struct nk_command_line*)cmd;
10381             nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
10382                 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
10383         } break;
10384         case NK_COMMAND_CURVE: {
10385             const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
10386             nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
10387                 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
10388                 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
10389                 config->curve_segment_count, q->line_thickness);
10390         } break;
10391         case NK_COMMAND_RECT: {
10392             const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
10393             nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10394                 r->color, (float)r->rounding, r->line_thickness);
10395         } break;
10396         case NK_COMMAND_RECT_FILLED: {
10397             const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
10398             nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10399                 r->color, (float)r->rounding);
10400         } break;
10401         case NK_COMMAND_RECT_MULTI_COLOR: {
10402             const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
10403             nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10404                 r->left, r->top, r->right, r->bottom);
10405         } break;
10406         case NK_COMMAND_CIRCLE: {
10407             const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
10408             nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
10409                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
10410                 config->circle_segment_count, c->line_thickness);
10411         } break;
10412         case NK_COMMAND_CIRCLE_FILLED: {
10413             const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
10414             nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
10415                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
10416                 config->circle_segment_count);
10417         } break;
10418         case NK_COMMAND_ARC: {
10419             const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
10420             //nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
10421             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
10422                 c->a[0], c->a[1], config->arc_segment_count);
10423             //nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
10424             nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_OPEN, c->line_thickness);
10425         } break;
10426         case NK_COMMAND_ARC_FILLED: {
10427             const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
10428             //nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
10429             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
10430                 c->a[0], c->a[1], config->arc_segment_count);
10431             nk_draw_list_path_fill(&ctx->draw_list, c->color);
10432         } break;
10433         case NK_COMMAND_TRIANGLE: {
10434             const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
10435             nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
10436                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
10437                 t->line_thickness);
10438         } break;
10439         case NK_COMMAND_TRIANGLE_FILLED: {
10440             const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
10441             nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
10442                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
10443         } break;
10444         case NK_COMMAND_POLYGON: {
10445             int i;
10446             const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
10447             for (i = 0; i < p->point_count; ++i) {
10448                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10449                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10450             }
10451             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
10452         } break;
10453         case NK_COMMAND_POLYGON_FILLED: {
10454             int i;
10455             const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
10456             for (i = 0; i < p->point_count; ++i) {
10457                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10458                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10459             }
10460             nk_draw_list_path_fill(&ctx->draw_list, p->color);
10461         } break;
10462         case NK_COMMAND_POLYLINE: {
10463             int i;
10464             const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
10465             for (i = 0; i < p->point_count; ++i) {
10466                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10467                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10468             }
10469             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
10470         } break;
10471         case NK_COMMAND_TEXT: {
10472             const struct nk_command_text *t = (const struct nk_command_text*)cmd;
10473             nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
10474                 t->string, t->length, t->height, t->foreground);
10475         } break;
10476         case NK_COMMAND_IMAGE: {
10477             const struct nk_command_image *i = (const struct nk_command_image*)cmd;
10478             nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
10479         } break;
10480         case NK_COMMAND_CUSTOM: {
10481             const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
10482             c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
10483         } break;
10484         default: break;
10485         }
10486     }
10487     res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
10488     res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
10489     res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
10490     return res;
10491 }
10492 NK_API const struct nk_draw_command*
10493 nk__draw_begin(const struct nk_context *ctx,
10494     const struct nk_buffer *buffer)
10495 {return nk__draw_list_begin(&ctx->draw_list, buffer);}
10496 
10497 NK_API const struct nk_draw_command*
10498 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
10499 {return nk__draw_list_end(&ctx->draw_list, buffer);}
10500 
10501 NK_API const struct nk_draw_command*
10502 nk__draw_next(const struct nk_draw_command *cmd,
10503     const struct nk_buffer *buffer, const struct nk_context *ctx)
10504 {return nk__draw_list_next(cmd, buffer, &ctx->draw_list);}
10505 
10506 #endif
10507 
10508 /*
10509  * ==============================================================
10510  *
10511  *                          FONT HANDLING
10512  *
10513  * ===============================================================
10514  */
10515 #ifdef NK_INCLUDE_FONT_BAKING
10516 /* -------------------------------------------------------------
10517  *
10518  *                          RECT PACK
10519  *
10520  * --------------------------------------------------------------*/
10521 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
10522 /* Sean Barrett 2014 */
10523 #define NK_RP__MAXVAL  0xffff
10524 typedef unsigned short nk_rp_coord;
10525 
10526 struct nk_rp_rect {
10527     /* reserved for your use: */
10528     int id;
10529     /* input: */
10530     nk_rp_coord w, h;
10531     /* output: */
10532     nk_rp_coord x, y;
10533     int was_packed;
10534     /* non-zero if valid packing */
10535 }; /* 16 bytes, nominally */
10536 
10537 struct nk_rp_node {
10538     nk_rp_coord  x,y;
10539     struct nk_rp_node  *next;
10540 };
10541 
10542 struct nk_rp_context {
10543     int width;
10544     int height;
10545     int align;
10546     int init_mode;
10547     int heuristic;
10548     int num_nodes;
10549     struct nk_rp_node *active_head;
10550     struct nk_rp_node *free_head;
10551     struct nk_rp_node extra[2];
10552     /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
10553 };
10554 
10555 struct nk_rp__findresult {
10556     int x,y;
10557     struct nk_rp_node **prev_link;
10558 };
10559 
10560 enum NK_RP_HEURISTIC {
10561     NK_RP_HEURISTIC_Skyline_default=0,
10562     NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
10563     NK_RP_HEURISTIC_Skyline_BF_sortHeight
10564 };
10565 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
10566 
10567 NK_INTERN void
10568 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
10569 {
10570     if (allow_out_of_mem)
10571         /* if it's ok to run out of memory, then don't bother aligning them; */
10572         /* this gives better packing, but may fail due to OOM (even though */
10573         /* the rectangles easily fit). @TODO a smarter approach would be to only */
10574         /* quantize once we've hit OOM, then we could get rid of this parameter. */
10575         context->align = 1;
10576     else {
10577         /* if it's not ok to run out of memory, then quantize the widths */
10578         /* so that num_nodes is always enough nodes. */
10579         /* */
10580         /* I.e. num_nodes * align >= width */
10581         /*                  align >= width / num_nodes */
10582         /*                  align = ceil(width/num_nodes) */
10583         context->align = (context->width + context->num_nodes-1) / context->num_nodes;
10584     }
10585 }
10586 
10587 NK_INTERN void
10588 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
10589     struct nk_rp_node *nodes, int num_nodes)
10590 {
10591     int i;
10592 #ifndef STBRP_LARGE_RECTS
10593     NK_ASSERT(width <= 0xffff && height <= 0xffff);
10594 #endif
10595 
10596     for (i=0; i < num_nodes-1; ++i)
10597         nodes[i].next = &nodes[i+1];
10598     nodes[i].next = 0;
10599     context->init_mode = NK_RP__INIT_skyline;
10600     context->heuristic = NK_RP_HEURISTIC_Skyline_default;
10601     context->free_head = &nodes[0];
10602     context->active_head = &context->extra[0];
10603     context->width = width;
10604     context->height = height;
10605     context->num_nodes = num_nodes;
10606     nk_rp_setup_allow_out_of_mem(context, 0);
10607 
10608     /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
10609     context->extra[0].x = 0;
10610     context->extra[0].y = 0;
10611     context->extra[0].next = &context->extra[1];
10612     context->extra[1].x = (nk_rp_coord) width;
10613     context->extra[1].y = 65535;
10614     context->extra[1].next = 0;
10615 }
10616 
10617 /* find minimum y position if it starts at x1 */
10618 NK_INTERN int
10619 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
10620     int x0, int width, int *pwaste)
10621 {
10622     struct nk_rp_node *node = first;
10623     int x1 = x0 + width;
10624     int min_y, visited_width, waste_area;
10625     NK_ASSERT(first->x <= x0);
10626     NK_UNUSED(c);
10627 
10628     NK_ASSERT(node->next->x > x0);
10629     /* we ended up handling this in the caller for efficiency */
10630     NK_ASSERT(node->x <= x0);
10631 
10632     min_y = 0;
10633     waste_area = 0;
10634     visited_width = 0;
10635     while (node->x < x1)
10636     {
10637         if (node->y > min_y) {
10638             /* raise min_y higher. */
10639             /* we've accounted for all waste up to min_y, */
10640             /* but we'll now add more waste for everything we've visited */
10641             waste_area += visited_width * (node->y - min_y);
10642             min_y = node->y;
10643             /* the first time through, visited_width might be reduced */
10644             if (node->x < x0)
10645             visited_width += node->next->x - x0;
10646             else
10647             visited_width += node->next->x - node->x;
10648         } else {
10649             /* add waste area */
10650             int under_width = node->next->x - node->x;
10651             if (under_width + visited_width > width)
10652             under_width = width - visited_width;
10653             waste_area += under_width * (min_y - node->y);
10654             visited_width += under_width;
10655         }
10656         node = node->next;
10657     }
10658     *pwaste = waste_area;
10659     return min_y;
10660 }
10661 
10662 NK_INTERN struct nk_rp__findresult
10663 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
10664 {
10665     int best_waste = (1<<30), best_x, best_y = (1 << 30);
10666     struct nk_rp__findresult fr;
10667     struct nk_rp_node **prev, *node, *tail, **best = 0;
10668 
10669     /* align to multiple of c->align */
10670     width = (width + c->align - 1);
10671     width -= width % c->align;
10672     NK_ASSERT(width % c->align == 0);
10673 
10674     node = c->active_head;
10675     prev = &c->active_head;
10676     while (node->x + width <= c->width) {
10677         int y,waste;
10678         y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
10679         /* actually just want to test BL */
10680         if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
10681             /* bottom left */
10682             if (y < best_y) {
10683             best_y = y;
10684             best = prev;
10685             }
10686         } else {
10687             /* best-fit */
10688             if (y + height <= c->height) {
10689                 /* can only use it if it first vertically */
10690                 if (y < best_y || (y == best_y && waste < best_waste)) {
10691                     best_y = y;
10692                     best_waste = waste;
10693                     best = prev;
10694                 }
10695             }
10696         }
10697         prev = &node->next;
10698         node = node->next;
10699     }
10700     best_x = (best == 0) ? 0 : (*best)->x;
10701 
10702     /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
10703     /* */
10704     /* e.g, if fitting */
10705     /* */
10706     /*     ____________________ */
10707     /*    |____________________| */
10708     /* */
10709     /*            into */
10710     /* */
10711     /*   |                         | */
10712     /*   |             ____________| */
10713     /*   |____________| */
10714     /* */
10715     /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
10716     /* */
10717     /* This makes BF take about 2x the time */
10718     if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
10719     {
10720         tail = c->active_head;
10721         node = c->active_head;
10722         prev = &c->active_head;
10723         /* find first node that's admissible */
10724         while (tail->x < width)
10725             tail = tail->next;
10726         while (tail)
10727         {
10728             int xpos = tail->x - width;
10729             int y,waste;
10730             NK_ASSERT(xpos >= 0);
10731             /* find the left position that matches this */
10732             while (node->next->x <= xpos) {
10733                 prev = &node->next;
10734                 node = node->next;
10735             }
10736             NK_ASSERT(node->next->x > xpos && node->x <= xpos);
10737             y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
10738             if (y + height < c->height) {
10739                 if (y <= best_y) {
10740                     if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
10741                         best_x = xpos;
10742                         NK_ASSERT(y <= best_y);
10743                         best_y = y;
10744                         best_waste = waste;
10745                         best = prev;
10746                     }
10747                 }
10748             }
10749             tail = tail->next;
10750         }
10751     }
10752     fr.prev_link = best;
10753     fr.x = best_x;
10754     fr.y = best_y;
10755     return fr;
10756 }
10757 
10758 NK_INTERN struct nk_rp__findresult
10759 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
10760 {
10761     /* find best position according to heuristic */
10762     struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
10763     struct nk_rp_node *node, *cur;
10764 
10765     /* bail if: */
10766     /*    1. it failed */
10767     /*    2. the best node doesn't fit (we don't always check this) */
10768     /*    3. we're out of memory */
10769     if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
10770         res.prev_link = 0;
10771         return res;
10772     }
10773 
10774     /* on success, create new node */
10775     node = context->free_head;
10776     node->x = (nk_rp_coord) res.x;
10777     node->y = (nk_rp_coord) (res.y + height);
10778 
10779     context->free_head = node->next;
10780 
10781     /* insert the new node into the right starting point, and */
10782     /* let 'cur' point to the remaining nodes needing to be */
10783     /* stitched back in */
10784     cur = *res.prev_link;
10785     if (cur->x < res.x) {
10786         /* preserve the existing one, so start testing with the next one */
10787         struct nk_rp_node *next = cur->next;
10788         cur->next = node;
10789         cur = next;
10790     } else {
10791         *res.prev_link = node;
10792     }
10793 
10794     /* from here, traverse cur and free the nodes, until we get to one */
10795     /* that shouldn't be freed */
10796     while (cur->next && cur->next->x <= res.x + width) {
10797         struct nk_rp_node *next = cur->next;
10798         /* move the current node to the free list */
10799         cur->next = context->free_head;
10800         context->free_head = cur;
10801         cur = next;
10802     }
10803     /* stitch the list back in */
10804     node->next = cur;
10805 
10806     if (cur->x < res.x + width)
10807         cur->x = (nk_rp_coord) (res.x + width);
10808     return res;
10809 }
10810 
10811 NK_INTERN int
10812 nk_rect_height_compare(const void *a, const void *b)
10813 {
10814     const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
10815     const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
10816     if (p->h > q->h)
10817         return -1;
10818     if (p->h < q->h)
10819         return  1;
10820     return (p->w > q->w) ? -1 : (p->w < q->w);
10821 }
10822 
10823 NK_INTERN int
10824 nk_rect_original_order(const void *a, const void *b)
10825 {
10826     const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
10827     const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
10828     return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
10829 }
10830 
10831 NK_INTERN void
10832 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
10833 {
10834     /* iterative quick sort */
10835     #define NK_MAX_SORT_STACK 64
10836     unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
10837     unsigned seed = len/2 * 69069+1;
10838     for (;;) {
10839         for (; left+1 < len; len++) {
10840             struct nk_rp_rect pivot, tmp;
10841             if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
10842             pivot = array[left+seed%(len-left)];
10843             seed = seed * 69069 + 1;
10844             stack[pos++] = len;
10845             for (right = left-1;;) {
10846                 while (cmp(&array[++right], &pivot) < 0);
10847                 while (cmp(&pivot, &array[--len]) < 0);
10848                 if (right >= len) break;
10849                 tmp = array[right];
10850                 array[right] = array[len];
10851                 array[len] = tmp;
10852             }
10853         }
10854         if (pos == 0) break;
10855         left = len;
10856         len = stack[--pos];
10857     }
10858     #undef NK_MAX_SORT_STACK
10859 }
10860 
10861 NK_INTERN void
10862 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
10863 {
10864     int i;
10865     /* we use the 'was_packed' field internally to allow sorting/unsorting */
10866     for (i=0; i < num_rects; ++i) {
10867         rects[i].was_packed = i;
10868     }
10869 
10870     /* sort according to heuristic */
10871     nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
10872 
10873     for (i=0; i < num_rects; ++i) {
10874         struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
10875         if (fr.prev_link) {
10876             rects[i].x = (nk_rp_coord) fr.x;
10877             rects[i].y = (nk_rp_coord) fr.y;
10878         } else {
10879             rects[i].x = rects[i].y = NK_RP__MAXVAL;
10880         }
10881     }
10882 
10883     /* unsort */
10884     nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
10885 
10886     /* set was_packed flags */
10887     for (i=0; i < num_rects; ++i)
10888         rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
10889 }
10890 
10891 /*
10892  * ==============================================================
10893  *
10894  *                          TRUETYPE
10895  *
10896  * ===============================================================
10897  */
10898 /* stb_truetype.h - v1.07 - public domain */
10899 #define NK_TT_MAX_OVERSAMPLE   8
10900 #define NK_TT__OVER_MASK  (NK_TT_MAX_OVERSAMPLE-1)
10901 
10902 struct nk_tt_bakedchar {
10903     unsigned short x0,y0,x1,y1;
10904     /* coordinates of bbox in bitmap */
10905     float xoff,yoff,xadvance;
10906 };
10907 
10908 struct nk_tt_aligned_quad{
10909     float x0,y0,s0,t0; /* top-left */
10910     float x1,y1,s1,t1; /* bottom-right */
10911 };
10912 
10913 struct nk_tt_packedchar {
10914     unsigned short x0,y0,x1,y1;
10915     /* coordinates of bbox in bitmap */
10916     float xoff,yoff,xadvance;
10917     float xoff2,yoff2;
10918 };
10919 
10920 struct nk_tt_pack_range {
10921     float font_size;
10922     int first_unicode_codepoint_in_range;
10923     /* if non-zero, then the chars are continuous, and this is the first codepoint */
10924     int *array_of_unicode_codepoints;
10925     /* if non-zero, then this is an array of unicode codepoints */
10926     int num_chars;
10927     struct nk_tt_packedchar *chardata_for_range; /* output */
10928     unsigned char h_oversample, v_oversample;
10929     /* don't set these, they're used internally */
10930 };
10931 
10932 struct nk_tt_pack_context {
10933     void *pack_info;
10934     int   width;
10935     int   height;
10936     int   stride_in_bytes;
10937     int   padding;
10938     unsigned int   h_oversample, v_oversample;
10939     unsigned char *pixels;
10940     void  *nodes;
10941 };
10942 
10943 struct nk_tt_fontinfo {
10944     const unsigned char* data; /* pointer to .ttf file */
10945     int fontstart;/* offset of start of font */
10946     int numGlyphs;/* number of glyphs, needed for range checking */
10947     int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
10948     int index_map; /* a cmap mapping for our chosen character encoding */
10949     int indexToLocFormat; /* format needed to map from glyph index to glyph */
10950 };
10951 
10952 enum {
10953   NK_TT_vmove=1,
10954   NK_TT_vline,
10955   NK_TT_vcurve
10956 };
10957 
10958 struct nk_tt_vertex {
10959     short x,y,cx,cy;
10960     unsigned char type,padding;
10961 };
10962 
10963 struct nk_tt__bitmap{
10964    int w,h,stride;
10965    unsigned char *pixels;
10966 };
10967 
10968 struct nk_tt__hheap_chunk {
10969     struct nk_tt__hheap_chunk *next;
10970 };
10971 struct nk_tt__hheap {
10972     struct nk_allocator alloc;
10973     struct nk_tt__hheap_chunk *head;
10974     void   *first_free;
10975     int    num_remaining_in_head_chunk;
10976 };
10977 
10978 struct nk_tt__edge {
10979     float x0,y0, x1,y1;
10980     int invert;
10981 };
10982 
10983 struct nk_tt__active_edge {
10984     struct nk_tt__active_edge *next;
10985     float fx,fdx,fdy;
10986     float direction;
10987     float sy;
10988     float ey;
10989 };
10990 struct nk_tt__point {float x,y;};
10991 
10992 #define NK_TT_MACSTYLE_DONTCARE     0
10993 #define NK_TT_MACSTYLE_BOLD         1
10994 #define NK_TT_MACSTYLE_ITALIC       2
10995 #define NK_TT_MACSTYLE_UNDERSCORE   4
10996 #define NK_TT_MACSTYLE_NONE         8
10997 /* <= not same as 0, this makes us check the bitfield is 0 */
10998 
10999 enum { /* platformID */
11000    NK_TT_PLATFORM_ID_UNICODE   =0,
11001    NK_TT_PLATFORM_ID_MAC       =1,
11002    NK_TT_PLATFORM_ID_ISO       =2,
11003    NK_TT_PLATFORM_ID_MICROSOFT =3
11004 };
11005 
11006 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
11007    NK_TT_UNICODE_EID_UNICODE_1_0    =0,
11008    NK_TT_UNICODE_EID_UNICODE_1_1    =1,
11009    NK_TT_UNICODE_EID_ISO_10646      =2,
11010    NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
11011    NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
11012 };
11013 
11014 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
11015    NK_TT_MS_EID_SYMBOL        =0,
11016    NK_TT_MS_EID_UNICODE_BMP   =1,
11017    NK_TT_MS_EID_SHIFTJIS      =2,
11018    NK_TT_MS_EID_UNICODE_FULL  =10
11019 };
11020 
11021 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
11022    NK_TT_MAC_EID_ROMAN        =0,   NK_TT_MAC_EID_ARABIC       =4,
11023    NK_TT_MAC_EID_JAPANESE     =1,   NK_TT_MAC_EID_HEBREW       =5,
11024    NK_TT_MAC_EID_CHINESE_TRAD =2,   NK_TT_MAC_EID_GREEK        =6,
11025    NK_TT_MAC_EID_KOREAN       =3,   NK_TT_MAC_EID_RUSSIAN      =7
11026 };
11027 
11028 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
11029        /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
11030    NK_TT_MS_LANG_ENGLISH     =0x0409,   NK_TT_MS_LANG_ITALIAN     =0x0410,
11031    NK_TT_MS_LANG_CHINESE     =0x0804,   NK_TT_MS_LANG_JAPANESE    =0x0411,
11032    NK_TT_MS_LANG_DUTCH       =0x0413,   NK_TT_MS_LANG_KOREAN      =0x0412,
11033    NK_TT_MS_LANG_FRENCH      =0x040c,   NK_TT_MS_LANG_RUSSIAN     =0x0419,
11034    NK_TT_MS_LANG_GERMAN      =0x0407,   NK_TT_MS_LANG_SPANISH     =0x0409,
11035    NK_TT_MS_LANG_HEBREW      =0x040d,   NK_TT_MS_LANG_SWEDISH     =0x041D
11036 };
11037 
11038 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
11039    NK_TT_MAC_LANG_ENGLISH      =0 ,   NK_TT_MAC_LANG_JAPANESE     =11,
11040    NK_TT_MAC_LANG_ARABIC       =12,   NK_TT_MAC_LANG_KOREAN       =23,
11041    NK_TT_MAC_LANG_DUTCH        =4 ,   NK_TT_MAC_LANG_RUSSIAN      =32,
11042    NK_TT_MAC_LANG_FRENCH       =1 ,   NK_TT_MAC_LANG_SPANISH      =6 ,
11043    NK_TT_MAC_LANG_GERMAN       =2 ,   NK_TT_MAC_LANG_SWEDISH      =5 ,
11044    NK_TT_MAC_LANG_HEBREW       =10,   NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
11045    NK_TT_MAC_LANG_ITALIAN      =3 ,   NK_TT_MAC_LANG_CHINESE_TRAD =19
11046 };
11047 
11048 #define nk_ttBYTE(p)     (* (const nk_byte *) (p))
11049 #define nk_ttCHAR(p)     (* (const char *) (p))
11050 
11051 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
11052    #define nk_ttUSHORT(p)   (* (nk_ushort *) (p))
11053    #define nk_ttSHORT(p)    (* (nk_short *) (p))
11054    #define nk_ttULONG(p)    (* (nk_uint *) (p))
11055    #define nk_ttLONG(p)     (* (nk_int *) (p))
11056 #else
11057     static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
11058     static nk_short nk_ttSHORT(const nk_byte *p)   { return (nk_short)(p[0]*256 + p[1]); }
11059     static nk_uint nk_ttULONG(const nk_byte *p)  { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
11060 #endif
11061 
11062 #define nk_tt_tag4(p,c0,c1,c2,c3)\
11063     ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
11064 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
11065 
11066 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
11067                                 int glyph_index, struct nk_tt_vertex **pvertices);
11068 
11069 NK_INTERN nk_uint
11070 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
11071 {
11072     /* @OPTIMIZE: binary search */
11073     nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
11074     nk_uint tabledir = fontstart + 12;
11075     nk_int i;
11076     for (i = 0; i < num_tables; ++i) {
11077         nk_uint loc = tabledir + (nk_uint)(16*i);
11078         if (nk_tt_tag(data+loc+0, tag))
11079             return nk_ttULONG(data+loc+8);
11080     }
11081     return 0;
11082 }
11083 
11084 NK_INTERN int
11085 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
11086 {
11087     nk_uint cmap, t;
11088     nk_int i,numTables;
11089     const nk_byte *data = (const nk_byte *) data2;
11090 
11091     info->data = data;
11092     info->fontstart = fontstart;
11093 
11094     cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap");       /* required */
11095     info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
11096     info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
11097     info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
11098     info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
11099     info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
11100     info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
11101     if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
11102         return 0;
11103 
11104     t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
11105     if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
11106     else info->numGlyphs = 0xffff;
11107 
11108     /* find a cmap encoding table we understand *now* to avoid searching */
11109     /* later. (todo: could make this installable) */
11110     /* the same regardless of glyph. */
11111     numTables = nk_ttUSHORT(data + cmap + 2);
11112     info->index_map = 0;
11113     for (i=0; i < numTables; ++i)
11114     {
11115         nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
11116         /* find an encoding we understand: */
11117         switch(nk_ttUSHORT(data+encoding_record)) {
11118         case NK_TT_PLATFORM_ID_MICROSOFT:
11119             switch (nk_ttUSHORT(data+encoding_record+2)) {
11120             case NK_TT_MS_EID_UNICODE_BMP:
11121             case NK_TT_MS_EID_UNICODE_FULL:
11122                 /* MS/Unicode */
11123                 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
11124                 break;
11125             default: break;
11126             } break;
11127         case NK_TT_PLATFORM_ID_UNICODE:
11128             /* Mac/iOS has these */
11129             /* all the encodingIDs are unicode, so we don't bother to check it */
11130             info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
11131             break;
11132         default: break;
11133         }
11134     }
11135     if (info->index_map == 0)
11136         return 0;
11137     info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
11138     return 1;
11139 }
11140 
11141 NK_INTERN int
11142 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
11143 {
11144     const nk_byte *data = info->data;
11145     nk_uint index_map = (nk_uint)info->index_map;
11146 
11147     nk_ushort format = nk_ttUSHORT(data + index_map + 0);
11148     if (format == 0) { /* apple byte encoding */
11149         nk_int bytes = nk_ttUSHORT(data + index_map + 2);
11150         if (unicode_codepoint < bytes-6)
11151             return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
11152         return 0;
11153     } else if (format == 6) {
11154         nk_uint first = nk_ttUSHORT(data + index_map + 6);
11155         nk_uint count = nk_ttUSHORT(data + index_map + 8);
11156         if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
11157             return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
11158         return 0;
11159     } else if (format == 2) {
11160         NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
11161         return 0;
11162     } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
11163         nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
11164         nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
11165         nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
11166         nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
11167 
11168         /* do a binary search of the segments */
11169         nk_uint endCount = index_map + 14;
11170         nk_uint search = endCount;
11171 
11172         if (unicode_codepoint > 0xffff)
11173             return 0;
11174 
11175         /* they lie from endCount .. endCount + segCount */
11176         /* but searchRange is the nearest power of two, so... */
11177         if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
11178             search += (nk_uint)(rangeShift*2);
11179 
11180         /* now decrement to bias correctly to find smallest */
11181         search -= 2;
11182         while (entrySelector) {
11183             nk_ushort end;
11184             searchRange >>= 1;
11185             end = nk_ttUSHORT(data + search + searchRange*2);
11186             if (unicode_codepoint > end)
11187                 search += (nk_uint)(searchRange*2);
11188             --entrySelector;
11189         }
11190         search += 2;
11191 
11192       {
11193          nk_ushort offset, start;
11194          nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
11195 
11196          NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
11197          start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
11198          if (unicode_codepoint < start)
11199             return 0;
11200 
11201          offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
11202          if (offset == 0)
11203             return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
11204 
11205          return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
11206       }
11207    } else if (format == 12 || format == 13) {
11208         nk_uint ngroups = nk_ttULONG(data+index_map+12);
11209         nk_int low,high;
11210         low = 0; high = (nk_int)ngroups;
11211         /* Binary search the right group. */
11212         while (low < high) {
11213             nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
11214             nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
11215             nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
11216             if ((nk_uint) unicode_codepoint < start_char)
11217                 high = mid;
11218             else if ((nk_uint) unicode_codepoint > end_char)
11219                 low = mid+1;
11220             else {
11221                 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
11222                 if (format == 12)
11223                     return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
11224                 else /* format == 13 */
11225                     return (int)start_glyph;
11226             }
11227         }
11228         return 0; /* not found */
11229     }
11230     /* @TODO */
11231     NK_ASSERT(0);
11232     return 0;
11233 }
11234 
11235 NK_INTERN void
11236 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
11237 {
11238     v->type = type;
11239     v->x = (nk_short) x;
11240     v->y = (nk_short) y;
11241     v->cx = (nk_short) cx;
11242     v->cy = (nk_short) cy;
11243 }
11244 
11245 NK_INTERN int
11246 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
11247 {
11248     int g1,g2;
11249     if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
11250     if (info->indexToLocFormat >= 2)    return -1; /* unknown index->glyph map format */
11251 
11252     if (info->indexToLocFormat == 0) {
11253         g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
11254         g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
11255     } else {
11256         g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
11257         g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
11258     }
11259     return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
11260 }
11261 
11262 NK_INTERN int
11263 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
11264     int *x0, int *y0, int *x1, int *y1)
11265 {
11266     int g = nk_tt__GetGlyfOffset(info, glyph_index);
11267     if (g < 0) return 0;
11268 
11269     if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
11270     if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
11271     if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
11272     if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
11273     return 1;
11274 }
11275 
11276 NK_INTERN int
11277 nk_tt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
11278     int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
11279 {
11280    if (start_off) {
11281       if (was_off)
11282          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
11283       nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
11284    } else {
11285       if (was_off)
11286          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
11287       else
11288          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
11289    }
11290    return num_vertices;
11291 }
11292 
11293 NK_INTERN int
11294 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
11295     int glyph_index, struct nk_tt_vertex **pvertices)
11296 {
11297     nk_short numberOfContours;
11298     const nk_byte *endPtsOfContours;
11299     const nk_byte *data = info->data;
11300     struct nk_tt_vertex *vertices=0;
11301     int num_vertices=0;
11302     int g = nk_tt__GetGlyfOffset(info, glyph_index);
11303     *pvertices = 0;
11304 
11305     if (g < 0) return 0;
11306     numberOfContours = nk_ttSHORT(data + g);
11307     if (numberOfContours > 0) {
11308         nk_byte flags=0,flagcount;
11309         nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
11310         nk_int x,y,cx,cy,sx,sy, scx,scy;
11311         const nk_byte *points;
11312         endPtsOfContours = (data + g + 10);
11313         ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
11314         points = data + g + 10 + numberOfContours * 2 + 2 + ins;
11315 
11316         n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
11317         m = n + 2*numberOfContours;  /* a loose bound on how many vertices we might need */
11318         vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
11319         if (vertices == 0)
11320             return 0;
11321 
11322         next_move = 0;
11323         flagcount=0;
11324 
11325         /* in first pass, we load uninterpreted data into the allocated array */
11326         /* above, shifted to the end of the array so we won't overwrite it when */
11327         /* we create our final data starting from the front */
11328         off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
11329 
11330         /* first load flags */
11331         for (i=0; i < n; ++i) {
11332             if (flagcount == 0) {
11333                 flags = *points++;
11334                 if (flags & 8)
11335                     flagcount = *points++;
11336             } else --flagcount;
11337             vertices[off+i].type = flags;
11338         }
11339 
11340         /* now load x coordinates */
11341         x=0;
11342         for (i=0; i < n; ++i) {
11343             flags = vertices[off+i].type;
11344             if (flags & 2) {
11345                 nk_short dx = *points++;
11346                 x += (flags & 16) ? dx : -dx; /* ??? */
11347             } else {
11348                 if (!(flags & 16)) {
11349                     x = x + (nk_short) (points[0]*256 + points[1]);
11350                     points += 2;
11351                 }
11352             }
11353             vertices[off+i].x = (nk_short) x;
11354         }
11355 
11356         /* now load y coordinates */
11357         y=0;
11358         for (i=0; i < n; ++i) {
11359             flags = vertices[off+i].type;
11360             if (flags & 4) {
11361                 nk_short dy = *points++;
11362                 y += (flags & 32) ? dy : -dy; /* ??? */
11363             } else {
11364                 if (!(flags & 32)) {
11365                     y = y + (nk_short) (points[0]*256 + points[1]);
11366                     points += 2;
11367                 }
11368             }
11369             vertices[off+i].y = (nk_short) y;
11370         }
11371 
11372         /* now convert them to our format */
11373         num_vertices=0;
11374         sx = sy = cx = cy = scx = scy = 0;
11375         for (i=0; i < n; ++i)
11376         {
11377             flags = vertices[off+i].type;
11378             x     = (nk_short) vertices[off+i].x;
11379             y     = (nk_short) vertices[off+i].y;
11380 
11381             if (next_move == i) {
11382                 if (i != 0)
11383                     num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
11384 
11385                 /* now start the new one                */
11386                 start_off = !(flags & 1);
11387                 if (start_off) {
11388                     /* if we start off with an off-curve point, then when we need to find a point on the curve */
11389                     /* where we can start, and we need to save some state for when we wraparound. */
11390                     scx = x;
11391                     scy = y;
11392                     if (!(vertices[off+i+1].type & 1)) {
11393                         /* next point is also a curve point, so interpolate an on-point curve */
11394                         sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
11395                         sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
11396                     } else {
11397                         /* otherwise just use the next point as our start point */
11398                         sx = (nk_int) vertices[off+i+1].x;
11399                         sy = (nk_int) vertices[off+i+1].y;
11400                         ++i; /* we're using point i+1 as the starting point, so skip it */
11401                     }
11402                 } else {
11403                     sx = x;
11404                     sy = y;
11405                 }
11406                 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
11407                 was_off = 0;
11408                 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
11409                 ++j;
11410             } else {
11411                 if (!(flags & 1))
11412                 { /* if it's a curve */
11413                     if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
11414                         nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
11415                     cx = x;
11416                     cy = y;
11417                     was_off = 1;
11418                 } else {
11419                     if (was_off)
11420                         nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
11421                     else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
11422                     was_off = 0;
11423                 }
11424             }
11425         }
11426         num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
11427     } else if (numberOfContours == -1) {
11428         /* Compound shapes. */
11429         int more = 1;
11430         const nk_byte *comp = data + g + 10;
11431         num_vertices = 0;
11432         vertices = 0;
11433 
11434         while (more)
11435         {
11436             nk_ushort flags, gidx;
11437             int comp_num_verts = 0, i;
11438             struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
11439             float mtx[6] = {1,0,0,1,0,0}, m, n;
11440 
11441             flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
11442             gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
11443 
11444             if (flags & 2) { /* XY values */
11445                 if (flags & 1) { /* shorts */
11446                     mtx[4] = nk_ttSHORT(comp); comp+=2;
11447                     mtx[5] = nk_ttSHORT(comp); comp+=2;
11448                 } else {
11449                     mtx[4] = nk_ttCHAR(comp); comp+=1;
11450                     mtx[5] = nk_ttCHAR(comp); comp+=1;
11451                 }
11452             } else {
11453                 /* @TODO handle matching point */
11454                 NK_ASSERT(0);
11455             }
11456             if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
11457                 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11458                 mtx[1] = mtx[2] = 0;
11459             } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
11460                 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11461                 mtx[1] = mtx[2] = 0;
11462                 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11463             } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
11464                 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11465                 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11466                 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11467                 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11468             }
11469 
11470              /* Find transformation scales. */
11471             m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
11472             n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
11473 
11474              /* Get indexed glyph. */
11475             comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
11476             if (comp_num_verts > 0)
11477             {
11478                 /* Transform vertices. */
11479                 for (i = 0; i < comp_num_verts; ++i) {
11480                     struct nk_tt_vertex* v = &comp_verts[i];
11481                     short x,y;
11482                     x=v->x; y=v->y;
11483                     v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
11484                     v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
11485                     x=v->cx; y=v->cy;
11486                     v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
11487                     v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
11488                 }
11489                 /* Append vertices. */
11490                 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
11491                     (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
11492                 if (!tmp) {
11493                     if (vertices) alloc->free(alloc->userdata, vertices);
11494                     if (comp_verts) alloc->free(alloc->userdata, comp_verts);
11495                     return 0;
11496                 }
11497                 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
11498                 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
11499                 if (vertices) alloc->free(alloc->userdata,vertices);
11500                 vertices = tmp;
11501                 alloc->free(alloc->userdata,comp_verts);
11502                 num_vertices += comp_num_verts;
11503             }
11504             /* More components ? */
11505             more = flags & (1<<5);
11506         }
11507     } else if (numberOfContours < 0) {
11508         /* @TODO other compound variations? */
11509         NK_ASSERT(0);
11510     } else {
11511         /* numberOfCounters == 0, do nothing */
11512     }
11513     *pvertices = vertices;
11514     return num_vertices;
11515 }
11516 
11517 NK_INTERN void
11518 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
11519     int *advanceWidth, int *leftSideBearing)
11520 {
11521     nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
11522     if (glyph_index < numOfLongHorMetrics) {
11523         if (advanceWidth)
11524             *advanceWidth    = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
11525         if (leftSideBearing)
11526             *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
11527     } else {
11528         if (advanceWidth)
11529             *advanceWidth    = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
11530         if (leftSideBearing)
11531             *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
11532     }
11533 }
11534 
11535 NK_INTERN void
11536 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
11537     int *ascent, int *descent, int *lineGap)
11538 {
11539    if (ascent ) *ascent  = nk_ttSHORT(info->data+info->hhea + 4);
11540    if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
11541    if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
11542 }
11543 
11544 NK_INTERN float
11545 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
11546 {
11547    int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
11548    return (float) height / (float)fheight;
11549 }
11550 
11551 NK_INTERN float
11552 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
11553 {
11554    int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
11555    return pixels / (float)unitsPerEm;
11556 }
11557 
11558 /*-------------------------------------------------------------
11559  *            antialiasing software rasterizer
11560  * --------------------------------------------------------------*/
11561 NK_INTERN void
11562 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
11563     int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
11564     int *ix0, int *iy0, int *ix1, int *iy1)
11565 {
11566     int x0,y0,x1,y1;
11567     if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
11568         /* e.g. space character */
11569         if (ix0) *ix0 = 0;
11570         if (iy0) *iy0 = 0;
11571         if (ix1) *ix1 = 0;
11572         if (iy1) *iy1 = 0;
11573     } else {
11574         /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
11575         if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
11576         if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
11577         if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
11578         if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
11579     }
11580 }
11581 
11582 NK_INTERN void
11583 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
11584     float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
11585 {
11586    nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
11587 }
11588 
11589 /*-------------------------------------------------------------
11590  *                          Rasterizer
11591  * --------------------------------------------------------------*/
11592 NK_INTERN void*
11593 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
11594 {
11595     if (hh->first_free) {
11596         void *p = hh->first_free;
11597         hh->first_free = * (void **) p;
11598         return p;
11599     } else {
11600         if (hh->num_remaining_in_head_chunk == 0) {
11601             int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
11602             struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
11603                 hh->alloc.alloc(hh->alloc.userdata, 0,
11604                 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
11605             if (c == 0) return 0;
11606             c->next = hh->head;
11607             hh->head = c;
11608             hh->num_remaining_in_head_chunk = count;
11609         }
11610         --hh->num_remaining_in_head_chunk;
11611         return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
11612     }
11613 }
11614 
11615 NK_INTERN void
11616 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
11617 {
11618     *(void **) p = hh->first_free;
11619     hh->first_free = p;
11620 }
11621 
11622 NK_INTERN void
11623 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
11624 {
11625     struct nk_tt__hheap_chunk *c = hh->head;
11626     while (c) {
11627         struct nk_tt__hheap_chunk *n = c->next;
11628         hh->alloc.free(hh->alloc.userdata, c);
11629         c = n;
11630     }
11631 }
11632 
11633 NK_INTERN struct nk_tt__active_edge*
11634 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
11635     int off_x, float start_point)
11636 {
11637     struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
11638         nk_tt__hheap_alloc(hh, sizeof(*z));
11639     float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
11640     /*STBTT_assert(e->y0 <= start_point); */
11641     if (!z) return z;
11642     z->fdx = dxdy;
11643     z->fdy = (dxdy != 0) ? (1/dxdy): 0;
11644     z->fx = e->x0 + dxdy * (start_point - e->y0);
11645     z->fx -= (float)off_x;
11646     z->direction = e->invert ? 1.0f : -1.0f;
11647     z->sy = e->y0;
11648     z->ey = e->y1;
11649     z->next = 0;
11650     return z;
11651 }
11652 
11653 NK_INTERN void
11654 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
11655     float x0, float y0, float x1, float y1)
11656 {
11657     if (y0 == y1) return;
11658     NK_ASSERT(y0 < y1);
11659     NK_ASSERT(e->sy <= e->ey);
11660     if (y0 > e->ey) return;
11661     if (y1 < e->sy) return;
11662     if (y0 < e->sy) {
11663         x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
11664         y0 = e->sy;
11665     }
11666     if (y1 > e->ey) {
11667         x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
11668         y1 = e->ey;
11669     }
11670 
11671     if (x0 == x) NK_ASSERT(x1 <= x+1);
11672     else if (x0 == x+1) NK_ASSERT(x1 >= x);
11673     else if (x0 <= x) NK_ASSERT(x1 <= x);
11674     else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
11675     else NK_ASSERT(x1 >= x && x1 <= x+1);
11676 
11677     if (x0 <= x && x1 <= x)
11678         scanline[x] += e->direction * (y1-y0);
11679     else if (x0 >= x+1 && x1 >= x+1);
11680     else {
11681         NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
11682         /* coverage = 1 - average x position */
11683         scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
11684     }
11685 }
11686 
11687 NK_INTERN void
11688 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
11689     struct nk_tt__active_edge *e, float y_top)
11690 {
11691     float y_bottom = y_top+1;
11692     while (e)
11693     {
11694         /* brute force every pixel */
11695         /* compute intersection points with top & bottom */
11696         NK_ASSERT(e->ey >= y_top);
11697         if (e->fdx == 0) {
11698             float x0 = e->fx;
11699             if (x0 < len) {
11700                 if (x0 >= 0) {
11701                     nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
11702                     nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
11703                 } else {
11704                     nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
11705                 }
11706             }
11707         } else {
11708             float x0 = e->fx;
11709             float dx = e->fdx;
11710             float xb = x0 + dx;
11711             float x_top, x_bottom;
11712             float y0,y1;
11713             float dy = e->fdy;
11714             NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
11715 
11716             /* compute endpoints of line segment clipped to this scanline (if the */
11717             /* line segment starts on this scanline. x0 is the intersection of the */
11718             /* line with y_top, but that may be off the line segment. */
11719             if (e->sy > y_top) {
11720                 x_top = x0 + dx * (e->sy - y_top);
11721                 y0 = e->sy;
11722             } else {
11723                 x_top = x0;
11724                 y0 = y_top;
11725             }
11726 
11727             if (e->ey < y_bottom) {
11728                 x_bottom = x0 + dx * (e->ey - y_top);
11729                 y1 = e->ey;
11730             } else {
11731                 x_bottom = xb;
11732                 y1 = y_bottom;
11733             }
11734 
11735             if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
11736             {
11737                 /* from here on, we don't have to range check x values */
11738                 if ((int) x_top == (int) x_bottom) {
11739                     float height;
11740                     /* simple case, only spans one pixel */
11741                     int x = (int) x_top;
11742                     height = y1 - y0;
11743                     NK_ASSERT(x >= 0 && x < len);
11744                     scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f)  * (float)height;
11745                     scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
11746                 } else {
11747                     int x,x1,x2;
11748                     float y_crossing, step, sign, area;
11749                     /* covers 2+ pixels */
11750                     if (x_top > x_bottom)
11751                     {
11752                         /* flip scanline vertically; signed area is the same */
11753                         float t;
11754                         y0 = y_bottom - (y0 - y_top);
11755                         y1 = y_bottom - (y1 - y_top);
11756                         t = y0; y0 = y1; y1 = t;
11757                         t = x_bottom; x_bottom = x_top; x_top = t;
11758                         dx = -dx;
11759                         dy = -dy;
11760                         t = x0; x0 = xb; xb = t;
11761                     }
11762 
11763                     x1 = (int) x_top;
11764                     x2 = (int) x_bottom;
11765                     /* compute intersection with y axis at x1+1 */
11766                     y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
11767 
11768                     sign = e->direction;
11769                     /* area of the rectangle covered from y0..y_crossing */
11770                     area = sign * (y_crossing-y0);
11771                     /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
11772                     scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
11773 
11774                     step = sign * dy;
11775                     for (x = x1+1; x < x2; ++x) {
11776                         scanline[x] += area + step/2;
11777                         area += step;
11778                     }
11779                     y_crossing += (float)dy * (float)(x2 - (x1+1));
11780 
11781                     scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
11782                     scanline_fill[x2] += sign * (y1-y0);
11783                 }
11784             }
11785             else
11786             {
11787                 /* if edge goes outside of box we're drawing, we require */
11788                 /* clipping logic. since this does not match the intended use */
11789                 /* of this library, we use a different, very slow brute */
11790                 /* force implementation */
11791                 int x;
11792                 for (x=0; x < len; ++x)
11793                 {
11794                     /* cases: */
11795                     /* */
11796                     /* there can be up to two intersections with the pixel. any intersection */
11797                     /* with left or right edges can be handled by splitting into two (or three) */
11798                     /* regions. intersections with top & bottom do not necessitate case-wise logic. */
11799                     /* */
11800                     /* the old way of doing this found the intersections with the left & right edges, */
11801                     /* then used some simple logic to produce up to three segments in sorted order */
11802                     /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
11803                     /* across the x border, then the corresponding y position might not be distinct */
11804                     /* from the other y segment, and it might ignored as an empty segment. to avoid */
11805                     /* that, we need to explicitly produce segments based on x positions. */
11806 
11807                     /* rename variables to clear pairs */
11808                     float ya = y_top;
11809                     float x1 = (float) (x);
11810                     float x2 = (float) (x+1);
11811                     float x3 = xb;
11812                     float y3 = y_bottom;
11813                     float yb,y2;
11814 
11815                     yb = ((float)x - x0) / dx + y_top;
11816                     y2 = ((float)x+1 - x0) / dx + y_top;
11817 
11818                     if (x0 < x1 && x3 > x2) {         /* three segments descending down-right */
11819                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11820                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
11821                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11822                     } else if (x3 < x1 && x0 > x2) {  /* three segments descending down-left */
11823                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11824                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
11825                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11826                     } else if (x0 < x1 && x3 > x1) {  /* two segments across x, down-right */
11827                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11828                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11829                     } else if (x3 < x1 && x0 > x1) {  /* two segments across x, down-left */
11830                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11831                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11832                     } else if (x0 < x2 && x3 > x2) {  /* two segments across x+1, down-right */
11833                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11834                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11835                     } else if (x3 < x2 && x0 > x2) {  /* two segments across x+1, down-left */
11836                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11837                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11838                     } else {  /* one segment */
11839                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
11840                     }
11841                 }
11842             }
11843         }
11844         e = e->next;
11845     }
11846 }
11847 
11848 /* directly AA rasterize edges w/o supersampling */
11849 NK_INTERN void
11850 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
11851     int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
11852 {
11853     struct nk_tt__hheap hh;
11854     struct nk_tt__active_edge *active = 0;
11855     int y,j=0, i;
11856     float scanline_data[129], *scanline, *scanline2;
11857 
11858     NK_UNUSED(vsubsample);
11859     nk_zero_struct(hh);
11860     hh.alloc = *alloc;
11861 
11862     if (result->w > 64)
11863         scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
11864     else scanline = scanline_data;
11865 
11866     scanline2 = scanline + result->w;
11867     y = off_y;
11868     e[n].y0 = (float) (off_y + result->h) + 1;
11869 
11870     while (j < result->h)
11871     {
11872         /* find center of pixel for this scanline */
11873         float scan_y_top    = (float)y + 0.0f;
11874         float scan_y_bottom = (float)y + 1.0f;
11875         struct nk_tt__active_edge **step = &active;
11876 
11877         NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
11878         NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
11879 
11880         /* update all active edges; */
11881         /* remove all active edges that terminate before the top of this scanline */
11882         while (*step) {
11883             struct nk_tt__active_edge * z = *step;
11884             if (z->ey <= scan_y_top) {
11885                 *step = z->next; /* delete from list */
11886                 NK_ASSERT(z->direction);
11887                 z->direction = 0;
11888                 nk_tt__hheap_free(&hh, z);
11889             } else {
11890                 step = &((*step)->next); /* advance through list */
11891             }
11892         }
11893 
11894         /* insert all edges that start before the bottom of this scanline */
11895         while (e->y0 <= scan_y_bottom) {
11896             if (e->y0 != e->y1) {
11897                 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
11898                 if (z != 0) {
11899                     NK_ASSERT(z->ey >= scan_y_top);
11900                     /* insert at front */
11901                     z->next = active;
11902                     active = z;
11903                 }
11904             }
11905             ++e;
11906         }
11907 
11908         /* now process all active edges */
11909         if (active)
11910             nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
11911 
11912         {
11913             float sum = 0;
11914             for (i=0; i < result->w; ++i) {
11915                 float k;
11916                 int m;
11917                 sum += scanline2[i];
11918                 k = scanline[i] + sum;
11919                 k = (float) NK_ABS(k) * 255.0f + 0.5f;
11920                 m = (int) k;
11921                 if (m > 255) m = 255;
11922                 result->pixels[j*result->stride + i] = (unsigned char) m;
11923             }
11924         }
11925         /* advance all the edges */
11926         step = &active;
11927         while (*step) {
11928             struct nk_tt__active_edge *z = *step;
11929             z->fx += z->fdx; /* advance to position for current scanline */
11930             step = &((*step)->next); /* advance through list */
11931         }
11932         ++y;
11933         ++j;
11934     }
11935     nk_tt__hheap_cleanup(&hh);
11936     if (scanline != scanline_data)
11937         alloc->free(alloc->userdata, scanline);
11938 }
11939 
11940 #define NK_TT__COMPARE(a,b)  ((a)->y0 < (b)->y0)
11941 NK_INTERN void
11942 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
11943 {
11944     int i,j;
11945     for (i=1; i < n; ++i) {
11946         struct nk_tt__edge t = p[i], *a = &t;
11947         j = i;
11948         while (j > 0) {
11949             struct nk_tt__edge *b = &p[j-1];
11950             int c = NK_TT__COMPARE(a,b);
11951             if (!c) break;
11952             p[j] = p[j-1];
11953             --j;
11954         }
11955         if (i != j)
11956             p[j] = t;
11957     }
11958 }
11959 
11960 NK_INTERN void
11961 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
11962 {
11963     /* threshold for transitioning to insertion sort */
11964     while (n > 12) {
11965         struct nk_tt__edge t;
11966         int c01,c12,c,m,i,j;
11967 
11968         /* compute median of three */
11969         m = n >> 1;
11970         c01 = NK_TT__COMPARE(&p[0],&p[m]);
11971         c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
11972 
11973         /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
11974         if (c01 != c12) {
11975             /* otherwise, we'll need to swap something else to middle */
11976             int z;
11977             c = NK_TT__COMPARE(&p[0],&p[n-1]);
11978             /* 0>mid && mid<n:  0>n => n; 0<n => 0 */
11979             /* 0<mid && mid>n:  0>n => 0; 0<n => n */
11980             z = (c == c12) ? 0 : n-1;
11981             t = p[z];
11982             p[z] = p[m];
11983             p[m] = t;
11984         }
11985 
11986         /* now p[m] is the median-of-three */
11987         /* swap it to the beginning so it won't move around */
11988         t = p[0];
11989         p[0] = p[m];
11990         p[m] = t;
11991 
11992         /* partition loop */
11993         i=1;
11994         j=n-1;
11995         for(;;) {
11996             /* handling of equality is crucial here */
11997             /* for sentinels & efficiency with duplicates */
11998             for (;;++i) {
11999                 if (!NK_TT__COMPARE(&p[i], &p[0])) break;
12000             }
12001             for (;;--j) {
12002                 if (!NK_TT__COMPARE(&p[0], &p[j])) break;
12003             }
12004 
12005             /* make sure we haven't crossed */
12006              if (i >= j) break;
12007              t = p[i];
12008              p[i] = p[j];
12009              p[j] = t;
12010 
12011             ++i;
12012             --j;
12013 
12014         }
12015 
12016         /* recurse on smaller side, iterate on larger */
12017         if (j < (n-i)) {
12018             nk_tt__sort_edges_quicksort(p,j);
12019             p = p+i;
12020             n = n-i;
12021         } else {
12022             nk_tt__sort_edges_quicksort(p+i, n-i);
12023             n = j;
12024         }
12025     }
12026 }
12027 
12028 NK_INTERN void
12029 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
12030 {
12031    nk_tt__sort_edges_quicksort(p, n);
12032    nk_tt__sort_edges_ins_sort(p, n);
12033 }
12034 
12035 NK_INTERN void
12036 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
12037     int *wcount, int windings, float scale_x, float scale_y,
12038     float shift_x, float shift_y, int off_x, int off_y, int invert,
12039     struct nk_allocator *alloc)
12040 {
12041     float y_scale_inv = invert ? -scale_y : scale_y;
12042     struct nk_tt__edge *e;
12043     int n,i,j,k,m;
12044     int vsubsample = 1;
12045     /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
12046 
12047     /* now we have to blow out the windings into explicit edge lists */
12048     n = 0;
12049     for (i=0; i < windings; ++i)
12050         n += wcount[i];
12051 
12052     e = (struct nk_tt__edge*)
12053        alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
12054     if (e == 0) return;
12055     n = 0;
12056 
12057     m=0;
12058     for (i=0; i < windings; ++i)
12059     {
12060         struct nk_tt__point *p = pts + m;
12061         m += wcount[i];
12062         j = wcount[i]-1;
12063         for (k=0; k < wcount[i]; j=k++) {
12064             int a=k,b=j;
12065             /* skip the edge if horizontal */
12066             if (p[j].y == p[k].y)
12067                 continue;
12068 
12069             /* add edge from j to k to the list */
12070             e[n].invert = 0;
12071             if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
12072                 e[n].invert = 1;
12073                 a=j,b=k;
12074             }
12075             e[n].x0 = p[a].x * scale_x + shift_x;
12076             e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
12077             e[n].x1 = p[b].x * scale_x + shift_x;
12078             e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
12079             ++n;
12080         }
12081     }
12082 
12083     /* now sort the edges by their highest point (should snap to integer, and then by x) */
12084     /*STBTT_sort(e, n, sizeof(e[0]), nk_tt__edge_compare); */
12085     nk_tt__sort_edges(e, n);
12086     /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
12087     nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
12088     alloc->free(alloc->userdata, e);
12089 }
12090 
12091 NK_INTERN void
12092 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
12093 {
12094     if (!points) return; /* during first pass, it's unallocated */
12095     points[n].x = x;
12096     points[n].y = y;
12097 }
12098 
12099 NK_INTERN int
12100 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
12101     float x0, float y0, float x1, float y1, float x2, float y2,
12102     float objspace_flatness_squared, int n)
12103 {
12104     /* tesselate until threshold p is happy...
12105      * @TODO warped to compensate for non-linear stretching */
12106     /* midpoint */
12107     float mx = (x0 + 2*x1 + x2)/4;
12108     float my = (y0 + 2*y1 + y2)/4;
12109     /* versus directly drawn line */
12110     float dx = (x0+x2)/2 - mx;
12111     float dy = (y0+y2)/2 - my;
12112     if (n > 16) /* 65536 segments on one curve better be enough! */
12113         return 1;
12114 
12115     /* half-pixel error allowed... need to be smaller if AA */
12116     if (dx*dx+dy*dy > objspace_flatness_squared) {
12117         nk_tt__tesselate_curve(points, num_points, x0,y0,
12118             (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
12119         nk_tt__tesselate_curve(points, num_points, mx,my,
12120             (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
12121     } else {
12122         nk_tt__add_point(points, *num_points,x2,y2);
12123         *num_points = *num_points+1;
12124     }
12125     return 1;
12126 }
12127 
12128 /* returns number of contours */
12129 NK_INTERN struct nk_tt__point*
12130 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
12131     float objspace_flatness, int **contour_lengths, int *num_contours,
12132     struct nk_allocator *alloc)
12133 {
12134     struct nk_tt__point *points=0;
12135     int num_points=0;
12136     float objspace_flatness_squared = objspace_flatness * objspace_flatness;
12137     int i;
12138     int n=0;
12139     int start=0;
12140     int pass;
12141 
12142     /* count how many "moves" there are to get the contour count */
12143     for (i=0; i < num_verts; ++i)
12144         if (vertices[i].type == NK_TT_vmove) ++n;
12145 
12146     *num_contours = n;
12147     if (n == 0) return 0;
12148 
12149     *contour_lengths = (int *)
12150         alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
12151     if (*contour_lengths == 0) {
12152         *num_contours = 0;
12153         return 0;
12154     }
12155 
12156     /* make two passes through the points so we don't need to realloc */
12157     for (pass=0; pass < 2; ++pass)
12158     {
12159         float x=0,y=0;
12160         if (pass == 1) {
12161             points = (struct nk_tt__point *)
12162                 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
12163             if (points == 0) goto error;
12164         }
12165         num_points = 0;
12166         n= -1;
12167 
12168         for (i=0; i < num_verts; ++i)
12169         {
12170             switch (vertices[i].type) {
12171             case NK_TT_vmove:
12172                 /* start the next contour */
12173                 if (n >= 0)
12174                 (*contour_lengths)[n] = num_points - start;
12175                 ++n;
12176                 start = num_points;
12177 
12178                 x = vertices[i].x, y = vertices[i].y;
12179                 nk_tt__add_point(points, num_points++, x,y);
12180                 break;
12181             case NK_TT_vline:
12182                x = vertices[i].x, y = vertices[i].y;
12183                nk_tt__add_point(points, num_points++, x, y);
12184                break;
12185             case NK_TT_vcurve:
12186                nk_tt__tesselate_curve(points, &num_points, x,y,
12187                                         vertices[i].cx, vertices[i].cy,
12188                                         vertices[i].x,  vertices[i].y,
12189                                         objspace_flatness_squared, 0);
12190                x = vertices[i].x, y = vertices[i].y;
12191                break;
12192             default: break;
12193          }
12194       }
12195       (*contour_lengths)[n] = num_points - start;
12196    }
12197    return points;
12198 
12199 error:
12200    alloc->free(alloc->userdata, points);
12201    alloc->free(alloc->userdata, *contour_lengths);
12202    *contour_lengths = 0;
12203    *num_contours = 0;
12204    return 0;
12205 }
12206 
12207 NK_INTERN void
12208 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
12209     struct nk_tt_vertex *vertices, int num_verts,
12210     float scale_x, float scale_y, float shift_x, float shift_y,
12211     int x_off, int y_off, int invert, struct nk_allocator *alloc)
12212 {
12213     float scale = scale_x > scale_y ? scale_y : scale_x;
12214     int winding_count, *winding_lengths;
12215     struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
12216         flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
12217 
12218     NK_ASSERT(alloc);
12219     if (windings) {
12220         nk_tt__rasterize(result, windings, winding_lengths, winding_count,
12221             scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
12222         alloc->free(alloc->userdata, winding_lengths);
12223         alloc->free(alloc->userdata, windings);
12224     }
12225 }
12226 
12227 NK_INTERN void
12228 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
12229     int out_w, int out_h, int out_stride, float scale_x, float scale_y,
12230     float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
12231 {
12232     int ix0,iy0;
12233     struct nk_tt_vertex *vertices;
12234     int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
12235     struct nk_tt__bitmap gbm;
12236 
12237     nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
12238         shift_y, &ix0,&iy0,0,0);
12239     gbm.pixels = output;
12240     gbm.w = out_w;
12241     gbm.h = out_h;
12242     gbm.stride = out_stride;
12243 
12244     if (gbm.w && gbm.h)
12245         nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
12246             shift_x, shift_y, ix0,iy0, 1, alloc);
12247     alloc->free(alloc->userdata, vertices);
12248 }
12249 
12250 /*-------------------------------------------------------------
12251  *                          Bitmap baking
12252  * --------------------------------------------------------------*/
12253 NK_INTERN int
12254 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
12255     int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
12256 {
12257     int num_nodes = pw - padding;
12258     struct nk_rp_context *context = (struct nk_rp_context *)
12259         alloc->alloc(alloc->userdata,0, sizeof(*context));
12260     struct nk_rp_node *nodes = (struct nk_rp_node*)
12261         alloc->alloc(alloc->userdata,0, (sizeof(*nodes  ) * (nk_size)num_nodes));
12262 
12263     if (context == 0 || nodes == 0) {
12264         if (context != 0) alloc->free(alloc->userdata, context);
12265         if (nodes   != 0) alloc->free(alloc->userdata, nodes);
12266         return 0;
12267     }
12268 
12269     spc->width = pw;
12270     spc->height = ph;
12271     spc->pixels = pixels;
12272     spc->pack_info = context;
12273     spc->nodes = nodes;
12274     spc->padding = padding;
12275     spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
12276     spc->h_oversample = 1;
12277     spc->v_oversample = 1;
12278 
12279     nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
12280     if (pixels)
12281         NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
12282     return 1;
12283 }
12284 
12285 NK_INTERN void
12286 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
12287 {
12288     alloc->free(alloc->userdata, spc->nodes);
12289     alloc->free(alloc->userdata, spc->pack_info);
12290 }
12291 
12292 NK_INTERN void
12293 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
12294     unsigned int h_oversample, unsigned int v_oversample)
12295 {
12296    NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
12297    NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
12298    if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
12299       spc->h_oversample = h_oversample;
12300    if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
12301       spc->v_oversample = v_oversample;
12302 }
12303 
12304 NK_INTERN void
12305 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
12306     int kernel_width)
12307 {
12308     unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
12309     int safe_w = w - kernel_width;
12310     int j;
12311 
12312     for (j=0; j < h; ++j)
12313     {
12314         int i;
12315         unsigned int total;
12316         NK_MEMSET(buffer, 0, (nk_size)kernel_width);
12317 
12318         total = 0;
12319 
12320         /* make kernel_width a constant in common cases so compiler can optimize out the divide */
12321         switch (kernel_width) {
12322         case 2:
12323             for (i=0; i <= safe_w; ++i) {
12324                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12325                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12326                 pixels[i] = (unsigned char) (total / 2);
12327             }
12328             break;
12329         case 3:
12330             for (i=0; i <= safe_w; ++i) {
12331                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12332                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12333                 pixels[i] = (unsigned char) (total / 3);
12334             }
12335             break;
12336         case 4:
12337             for (i=0; i <= safe_w; ++i) {
12338                 total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
12339                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12340                 pixels[i] = (unsigned char) (total / 4);
12341             }
12342             break;
12343         case 5:
12344             for (i=0; i <= safe_w; ++i) {
12345                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12346                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12347                 pixels[i] = (unsigned char) (total / 5);
12348             }
12349             break;
12350         default:
12351             for (i=0; i <= safe_w; ++i) {
12352                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
12353                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
12354                 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
12355             }
12356             break;
12357         }
12358 
12359         for (; i < w; ++i) {
12360             NK_ASSERT(pixels[i] == 0);
12361             total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
12362             pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
12363         }
12364         pixels += stride_in_bytes;
12365     }
12366 }
12367 
12368 NK_INTERN void
12369 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
12370     int kernel_width)
12371 {
12372     unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
12373     int safe_h = h - kernel_width;
12374     int j;
12375 
12376     for (j=0; j < w; ++j)
12377     {
12378         int i;
12379         unsigned int total;
12380         NK_MEMSET(buffer, 0, (nk_size)kernel_width);
12381 
12382         total = 0;
12383 
12384         /* make kernel_width a constant in common cases so compiler can optimize out the divide */
12385         switch (kernel_width) {
12386         case 2:
12387             for (i=0; i <= safe_h; ++i) {
12388                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12389                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12390                 pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
12391             }
12392             break;
12393          case 3:
12394             for (i=0; i <= safe_h; ++i) {
12395                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12396                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12397                 pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
12398             }
12399             break;
12400          case 4:
12401             for (i=0; i <= safe_h; ++i) {
12402                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12403                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12404                 pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
12405             }
12406             break;
12407          case 5:
12408             for (i=0; i <= safe_h; ++i) {
12409                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12410                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12411                 pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
12412             }
12413             break;
12414          default:
12415             for (i=0; i <= safe_h; ++i) {
12416                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12417                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12418                 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
12419             }
12420             break;
12421         }
12422 
12423         for (; i < h; ++i) {
12424             NK_ASSERT(pixels[i*stride_in_bytes] == 0);
12425             total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
12426             pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
12427         }
12428         pixels += 1;
12429     }
12430 }
12431 
12432 NK_INTERN float
12433 nk_tt__oversample_shift(int oversample)
12434 {
12435     if (!oversample)
12436         return 0.0f;
12437 
12438     /* The prefilter is a box filter of width "oversample", */
12439     /* which shifts phase by (oversample - 1)/2 pixels in */
12440     /* oversampled space. We want to shift in the opposite */
12441     /* direction to counter this. */
12442     return (float)-(oversample - 1) / (2.0f * (float)oversample);
12443 }
12444 
12445 /* rects array must be big enough to accommodate all characters in the given ranges */
12446 NK_INTERN int
12447 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
12448     struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
12449     int num_ranges, struct nk_rp_rect *rects)
12450 {
12451     int i,j,k;
12452     k = 0;
12453 
12454     for (i=0; i < num_ranges; ++i) {
12455         float fh = ranges[i].font_size;
12456         float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
12457             nk_tt_ScaleForMappingEmToPixels(info, -fh);
12458         ranges[i].h_oversample = (unsigned char) spc->h_oversample;
12459         ranges[i].v_oversample = (unsigned char) spc->v_oversample;
12460         for (j=0; j < ranges[i].num_chars; ++j) {
12461             int x0,y0,x1,y1;
12462             int codepoint = ranges[i].first_unicode_codepoint_in_range ?
12463                 ranges[i].first_unicode_codepoint_in_range + j :
12464                 ranges[i].array_of_unicode_codepoints[j];
12465 
12466             int glyph = nk_tt_FindGlyphIndex(info, codepoint);
12467             nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
12468                 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
12469             rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
12470             rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
12471             ++k;
12472         }
12473     }
12474     return k;
12475 }
12476 
12477 NK_INTERN int
12478 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
12479     struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
12480     int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
12481 {
12482     int i,j,k, return_value = 1;
12483     /* save current values */
12484     int old_h_over = (int)spc->h_oversample;
12485     int old_v_over = (int)spc->v_oversample;
12486     /* rects array must be big enough to accommodate all characters in the given ranges */
12487 
12488     k = 0;
12489     for (i=0; i < num_ranges; ++i)
12490     {
12491         float fh = ranges[i].font_size;
12492         float recip_h,recip_v,sub_x,sub_y;
12493         float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
12494             nk_tt_ScaleForMappingEmToPixels(info, -fh);
12495 
12496         spc->h_oversample = ranges[i].h_oversample;
12497         spc->v_oversample = ranges[i].v_oversample;
12498 
12499         recip_h = 1.0f / (float)spc->h_oversample;
12500         recip_v = 1.0f / (float)spc->v_oversample;
12501 
12502         sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
12503         sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
12504 
12505         for (j=0; j < ranges[i].num_chars; ++j)
12506         {
12507             struct nk_rp_rect *r = &rects[k];
12508             if (r->was_packed)
12509             {
12510                 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
12511                 int advance, lsb, x0,y0,x1,y1;
12512                 int codepoint = ranges[i].first_unicode_codepoint_in_range ?
12513                     ranges[i].first_unicode_codepoint_in_range + j :
12514                     ranges[i].array_of_unicode_codepoints[j];
12515                 int glyph = nk_tt_FindGlyphIndex(info, codepoint);
12516                 nk_rp_coord pad = (nk_rp_coord) spc->padding;
12517 
12518                 /* pad on left and top */
12519                 r->x = (nk_rp_coord)((int)r->x + (int)pad);
12520                 r->y = (nk_rp_coord)((int)r->y + (int)pad);
12521                 r->w = (nk_rp_coord)((int)r->w - (int)pad);
12522                 r->h = (nk_rp_coord)((int)r->h - (int)pad);
12523 
12524                 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
12525                 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
12526                         (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
12527                 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
12528                     (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
12529                     spc->stride_in_bytes, scale * (float)spc->h_oversample,
12530                     scale * (float)spc->v_oversample, 0,0, glyph, alloc);
12531 
12532                 if (spc->h_oversample > 1)
12533                    nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
12534                         r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
12535 
12536                 if (spc->v_oversample > 1)
12537                    nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
12538                         r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
12539 
12540                 bc->x0       = (nk_ushort)  r->x;
12541                 bc->y0       = (nk_ushort)  r->y;
12542                 bc->x1       = (nk_ushort) (r->x + r->w);
12543                 bc->y1       = (nk_ushort) (r->y + r->h);
12544                 bc->xadvance = scale * (float)advance;
12545                 bc->xoff     = (float)  x0 * recip_h + sub_x;
12546                 bc->yoff     = (float)  y0 * recip_v + sub_y;
12547                 bc->xoff2    = ((float)x0 + r->w) * recip_h + sub_x;
12548                 bc->yoff2    = ((float)y0 + r->h) * recip_v + sub_y;
12549             } else {
12550                 return_value = 0; /* if any fail, report failure */
12551             }
12552             ++k;
12553         }
12554     }
12555     /* restore original values */
12556     spc->h_oversample = (unsigned int)old_h_over;
12557     spc->v_oversample = (unsigned int)old_v_over;
12558     return return_value;
12559 }
12560 
12561 NK_INTERN void
12562 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
12563     int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
12564     int align_to_integer)
12565 {
12566     float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
12567     struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
12568     if (align_to_integer) {
12569         int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
12570         int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
12571 
12572         float x = (float)tx;
12573         float y = (float)ty;
12574 
12575         q->x0 = x;
12576         q->y0 = y;
12577         q->x1 = x + b->xoff2 - b->xoff;
12578         q->y1 = y + b->yoff2 - b->yoff;
12579     } else {
12580         q->x0 = *xpos + b->xoff;
12581         q->y0 = *ypos + b->yoff;
12582         q->x1 = *xpos + b->xoff2;
12583         q->y1 = *ypos + b->yoff2;
12584     }
12585     q->s0 = b->x0 * ipw;
12586     q->t0 = b->y0 * iph;
12587     q->s1 = b->x1 * ipw;
12588     q->t1 = b->y1 * iph;
12589     *xpos += b->xadvance;
12590 }
12591 
12592 /* -------------------------------------------------------------
12593  *
12594  *                          FONT BAKING
12595  *
12596  * --------------------------------------------------------------*/
12597 struct nk_font_bake_data {
12598     struct nk_tt_fontinfo info;
12599     struct nk_rp_rect *rects;
12600     struct nk_tt_pack_range *ranges;
12601     nk_rune range_count;
12602 };
12603 
12604 struct nk_font_baker {
12605     struct nk_allocator alloc;
12606     struct nk_tt_pack_context spc;
12607     struct nk_font_bake_data *build;
12608     struct nk_tt_packedchar *packed_chars;
12609     struct nk_rp_rect *rects;
12610     struct nk_tt_pack_range *ranges;
12611 };
12612 
12613 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
12614 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
12615 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
12616 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
12617 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
12618 
12619 NK_INTERN int
12620 nk_range_count(const nk_rune *range)
12621 {
12622     const nk_rune *iter = range;
12623     NK_ASSERT(range);
12624     if (!range) return 0;
12625     while (*(iter++) != 0);
12626     return (iter == range) ? 0 : (int)((iter - range)/2);
12627 }
12628 
12629 NK_INTERN int
12630 nk_range_glyph_count(const nk_rune *range, int count)
12631 {
12632     int i = 0;
12633     int total_glyphs = 0;
12634     for (i = 0; i < count; ++i) {
12635         int diff;
12636         nk_rune f = range[(i*2)+0];
12637         nk_rune t = range[(i*2)+1];
12638         NK_ASSERT(t >= f);
12639         diff = (int)((t - f) + 1);
12640         total_glyphs += diff;
12641     }
12642     return total_glyphs;
12643 }
12644 
12645 NK_API const nk_rune*
12646 nk_font_default_glyph_ranges(void)
12647 {
12648     NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
12649     return ranges;
12650 }
12651 
12652 NK_API const nk_rune*
12653 nk_font_chinese_glyph_ranges(void)
12654 {
12655     NK_STORAGE const nk_rune ranges[] = {
12656         0x0020, 0x00FF,
12657         0x3000, 0x30FF,
12658         0x31F0, 0x31FF,
12659         0xFF00, 0xFFEF,
12660         0x4e00, 0x9FAF,
12661         0
12662     };
12663     return ranges;
12664 }
12665 
12666 NK_API const nk_rune*
12667 nk_font_cyrillic_glyph_ranges(void)
12668 {
12669     NK_STORAGE const nk_rune ranges[] = {
12670         0x0020, 0x00FF,
12671         0x0400, 0x052F,
12672         0x2DE0, 0x2DFF,
12673         0xA640, 0xA69F,
12674         0
12675     };
12676     return ranges;
12677 }
12678 
12679 NK_API const nk_rune*
12680 nk_font_korean_glyph_ranges(void)
12681 {
12682     NK_STORAGE const nk_rune ranges[] = {
12683         0x0020, 0x00FF,
12684         0x3131, 0x3163,
12685         0xAC00, 0xD79D,
12686         0
12687     };
12688     return ranges;
12689 }
12690 
12691 NK_INTERN void
12692 nk_font_baker_memory(nk_size *temp, int *glyph_count,
12693     struct nk_font_config *config_list, int count)
12694 {
12695     int range_count = 0;
12696     int total_range_count = 0;
12697     struct nk_font_config *iter, *i;
12698 
12699     NK_ASSERT(config_list);
12700     NK_ASSERT(glyph_count);
12701     if (!config_list) {
12702         *temp = 0;
12703         *glyph_count = 0;
12704         return;
12705     }
12706     *glyph_count = 0;
12707     for (iter = config_list; iter; iter = iter->next) {
12708         i = iter;
12709         do {if (!i->range) iter->range = nk_font_default_glyph_ranges();
12710             range_count = nk_range_count(i->range);
12711             total_range_count += range_count;
12712             *glyph_count += nk_range_glyph_count(i->range, range_count);
12713         } while ((i = i->n) != iter);
12714     }
12715     *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
12716     *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
12717     *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
12718     *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
12719     *temp += sizeof(struct nk_font_baker);
12720     *temp += nk_rect_align + nk_range_align + nk_char_align;
12721     *temp += nk_build_align + nk_baker_align;
12722 }
12723 
12724 NK_INTERN struct nk_font_baker*
12725 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
12726 {
12727     struct nk_font_baker *baker;
12728     if (!memory) return 0;
12729     /* setup baker inside a memory block  */
12730     baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
12731     baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
12732     baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
12733     baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
12734     baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
12735     baker->alloc = *alloc;
12736     return baker;
12737 }
12738 
12739 NK_INTERN int
12740 nk_font_bake_pack(struct nk_font_baker *baker,
12741     nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
12742     const struct nk_font_config *config_list, int count,
12743     struct nk_allocator *alloc)
12744 {
12745     NK_STORAGE const nk_size max_height = 1024 * 32;
12746     const struct nk_font_config *config_iter, *it;
12747     int total_glyph_count = 0;
12748     int total_range_count = 0;
12749     int range_count = 0;
12750     int i = 0;
12751 
12752     NK_ASSERT(image_memory);
12753     NK_ASSERT(width);
12754     NK_ASSERT(height);
12755     NK_ASSERT(config_list);
12756     NK_ASSERT(count);
12757     NK_ASSERT(alloc);
12758 
12759     if (!image_memory || !width || !height || !config_list || !count) return nk_false;
12760     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
12761         it = config_iter;
12762         do {range_count = nk_range_count(it->range);
12763             total_range_count += range_count;
12764             total_glyph_count += nk_range_glyph_count(it->range, range_count);
12765         } while ((it = it->n) != config_iter);
12766     }
12767     /* setup font baker from temporary memory */
12768     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
12769         it = config_iter;
12770         do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0))
12771             return nk_false;
12772         } while ((it = it->n) != config_iter);
12773     }
12774     *height = 0;
12775     *width = (total_glyph_count > 1000) ? 1024 : 512;
12776     nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
12777     {
12778         int input_i = 0;
12779         int range_n = 0;
12780         int rect_n = 0;
12781         int char_n = 0;
12782 
12783         if (custom) {
12784             /* pack custom user data first so it will be in the upper left corner*/
12785             struct nk_rp_rect custom_space;
12786             nk_zero(&custom_space, sizeof(custom_space));
12787             custom_space.w = (nk_rp_coord)(custom->w);
12788             custom_space.h = (nk_rp_coord)(custom->h);
12789 
12790             nk_tt_PackSetOversampling(&baker->spc, 1, 1);
12791             nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
12792             *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
12793 
12794             custom->x = (short)custom_space.x;
12795             custom->y = (short)custom_space.y;
12796             custom->w = (short)custom_space.w;
12797             custom->h = (short)custom_space.h;
12798         }
12799 
12800         /* first font pass: pack all glyphs */
12801         for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
12802             config_iter = config_iter->next) {
12803             it = config_iter;
12804             do {int n = 0;
12805                 int glyph_count;
12806                 const nk_rune *in_range;
12807                 const struct nk_font_config *cfg = it;
12808                 struct nk_font_bake_data *tmp = &baker->build[input_i++];
12809 
12810                 /* count glyphs + ranges in current font */
12811                 glyph_count = 0; range_count = 0;
12812                 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
12813                     glyph_count += (int)(in_range[1] - in_range[0]) + 1;
12814                     range_count++;
12815                 }
12816 
12817                 /* setup ranges  */
12818                 tmp->ranges = baker->ranges + range_n;
12819                 tmp->range_count = (nk_rune)range_count;
12820                 range_n += range_count;
12821                 for (i = 0; i < range_count; ++i) {
12822                     in_range = &cfg->range[i * 2];
12823                     tmp->ranges[i].font_size = cfg->size;
12824                     tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
12825                     tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
12826                     tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
12827                     char_n += tmp->ranges[i].num_chars;
12828                 }
12829 
12830                 /* pack */
12831                 tmp->rects = baker->rects + rect_n;
12832                 rect_n += glyph_count;
12833                 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
12834                 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
12835                     tmp->ranges, (int)tmp->range_count, tmp->rects);
12836                 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
12837 
12838                 /* texture height */
12839                 for (i = 0; i < n; ++i) {
12840                     if (tmp->rects[i].was_packed)
12841                         *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
12842                 }
12843             } while ((it = it->n) != config_iter);
12844         }
12845         NK_ASSERT(rect_n == total_glyph_count);
12846         NK_ASSERT(char_n == total_glyph_count);
12847         NK_ASSERT(range_n == total_range_count);
12848     }
12849     *height = (int)nk_round_up_pow2((nk_uint)*height);
12850     *image_memory = (nk_size)(*width) * (nk_size)(*height);
12851     return nk_true;
12852 }
12853 
12854 NK_INTERN void
12855 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
12856     struct nk_font_glyph *glyphs, int glyphs_count,
12857     const struct nk_font_config *config_list, int font_count)
12858 {
12859     int input_i = 0;
12860     nk_rune glyph_n = 0;
12861     const struct nk_font_config *config_iter;
12862     const struct nk_font_config *it;
12863 
12864     NK_ASSERT(image_memory);
12865     NK_ASSERT(width);
12866     NK_ASSERT(height);
12867     NK_ASSERT(config_list);
12868     NK_ASSERT(baker);
12869     NK_ASSERT(font_count);
12870     NK_ASSERT(glyphs_count);
12871     if (!image_memory || !width || !height || !config_list ||
12872         !font_count || !glyphs || !glyphs_count)
12873         return;
12874 
12875     /* second font pass: render glyphs */
12876     nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
12877     baker->spc.pixels = (unsigned char*)image_memory;
12878     baker->spc.height = (int)height;
12879     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
12880         config_iter = config_iter->next) {
12881         it = config_iter;
12882         do {const struct nk_font_config *cfg = it;
12883             struct nk_font_bake_data *tmp = &baker->build[input_i++];
12884             nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
12885             nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
12886                 (int)tmp->range_count, tmp->rects, &baker->alloc);
12887         } while ((it = it->n) != config_iter);
12888     } nk_tt_PackEnd(&baker->spc, &baker->alloc);
12889 
12890     /* third pass: setup font and glyphs */
12891     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
12892         config_iter = config_iter->next) {
12893         it = config_iter;
12894         do {nk_size i = 0;
12895             int char_idx = 0;
12896             nk_rune glyph_count = 0;
12897             const struct nk_font_config *cfg = it;
12898             struct nk_font_bake_data *tmp = &baker->build[input_i++];
12899             struct nk_baked_font *dst_font = cfg->font;
12900 
12901             float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
12902             int unscaled_ascent, unscaled_descent, unscaled_line_gap;
12903             nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
12904                                     &unscaled_line_gap);
12905 
12906             /* fill baked font */
12907             if (!cfg->merge_mode) {
12908                 dst_font->ranges = cfg->range;
12909                 dst_font->height = cfg->size;
12910                 dst_font->ascent = ((float)unscaled_ascent * font_scale);
12911                 dst_font->descent = ((float)unscaled_descent * font_scale);
12912                 dst_font->glyph_offset = glyph_n;
12913             }
12914 
12915             /* fill own baked font glyph array */
12916             for (i = 0; i < tmp->range_count; ++i) {
12917                 struct nk_tt_pack_range *range = &tmp->ranges[i];
12918                 for (char_idx = 0; char_idx < range->num_chars; char_idx++)
12919                 {
12920                     nk_rune codepoint = 0;
12921                     float dummy_x = 0, dummy_y = 0;
12922                     struct nk_tt_aligned_quad q;
12923                     struct nk_font_glyph *glyph;
12924 
12925                     /* query glyph bounds from stb_truetype */
12926                     const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
12927                     if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
12928                     codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
12929                     nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
12930                         (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
12931 
12932                     /* fill own glyph type with data */
12933                     glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count];
12934                     glyph->codepoint = codepoint;
12935                     glyph->x0 = q.x0; glyph->y0 = q.y0;
12936                     glyph->x1 = q.x1; glyph->y1 = q.y1;
12937                     glyph->y0 += (dst_font->ascent + 0.5f);
12938                     glyph->y1 += (dst_font->ascent + 0.5f);
12939                     glyph->w = glyph->x1 - glyph->x0 + 0.5f;
12940                     glyph->h = glyph->y1 - glyph->y0;
12941 
12942                     if (cfg->coord_type == NK_COORD_PIXEL) {
12943                         glyph->u0 = q.s0 * (float)width;
12944                         glyph->v0 = q.t0 * (float)height;
12945                         glyph->u1 = q.s1 * (float)width;
12946                         glyph->v1 = q.t1 * (float)height;
12947                     } else {
12948                         glyph->u0 = q.s0;
12949                         glyph->v0 = q.t0;
12950                         glyph->u1 = q.s1;
12951                         glyph->v1 = q.t1;
12952                     }
12953                     glyph->xadvance = (pc->xadvance + cfg->spacing.x);
12954                     if (cfg->pixel_snap)
12955                         glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
12956                     glyph_count++;
12957                 }
12958             }
12959             dst_font->glyph_count += glyph_count;
12960             glyph_n += glyph_count;
12961         } while ((it = it->n) != config_iter);
12962     }
12963 }
12964 
12965 NK_INTERN void
12966 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
12967     struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
12968     int tex_height, char white, char black)
12969 {
12970     nk_byte *pixels;
12971     int y = 0;
12972     int x = 0;
12973     int n = 0;
12974 
12975     NK_ASSERT(img_memory);
12976     NK_ASSERT(img_width);
12977     NK_ASSERT(img_height);
12978     NK_ASSERT(texture_data_mask);
12979     NK_UNUSED(tex_height);
12980     if (!img_memory || !img_width || !img_height || !texture_data_mask)
12981         return;
12982 
12983     pixels = (nk_byte*)img_memory;
12984     for (y = 0, n = 0; y < tex_height; ++y) {
12985         for (x = 0; x < tex_width; ++x, ++n) {
12986             const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
12987             const int off1 = off0 + 1 + tex_width;
12988             pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
12989             pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
12990         }
12991     }
12992 }
12993 
12994 NK_INTERN void
12995 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
12996     const void *in_memory)
12997 {
12998     int n = 0;
12999     nk_rune *dst;
13000     const nk_byte *src;
13001 
13002     NK_ASSERT(out_memory);
13003     NK_ASSERT(in_memory);
13004     NK_ASSERT(img_width);
13005     NK_ASSERT(img_height);
13006     if (!out_memory || !in_memory || !img_height || !img_width) return;
13007 
13008     dst = (nk_rune*)out_memory;
13009     src = (const nk_byte*)in_memory;
13010     for (n = (int)(img_width * img_height); n > 0; n--)
13011         *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
13012 }
13013 
13014 /* -------------------------------------------------------------
13015  *
13016  *                          FONT
13017  *
13018  * --------------------------------------------------------------*/
13019 NK_INTERN float
13020 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
13021 {
13022     nk_rune unicode;
13023     int text_len  = 0;
13024     float text_width = 0;
13025     int glyph_len = 0;
13026     float scale = 0;
13027 
13028     struct nk_font *font = (struct nk_font*)handle.ptr;
13029     NK_ASSERT(font);
13030     NK_ASSERT(font->glyphs);
13031     if (!font || !text || !len)
13032         return 0;
13033 
13034     scale = height/font->info.height;
13035     glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
13036     if (!glyph_len) return 0;
13037     while (text_len <= (int)len && glyph_len) {
13038         const struct nk_font_glyph *g;
13039         if (unicode == NK_UTF_INVALID) break;
13040 
13041         /* query currently drawn glyph information */
13042         g = nk_font_find_glyph(font, unicode);
13043         text_width += g->xadvance * scale;
13044 
13045         /* offset next glyph */
13046         glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
13047         text_len += glyph_len;
13048     }
13049     return text_width;
13050 }
13051 
13052 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13053 NK_INTERN void
13054 nk_font_query_font_glyph(nk_handle handle, float height,
13055     struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
13056 {
13057     float scale;
13058     const struct nk_font_glyph *g;
13059     struct nk_font *font;
13060 
13061     NK_ASSERT(glyph);
13062     NK_UNUSED(next_codepoint);
13063 
13064     font = (struct nk_font*)handle.ptr;
13065     NK_ASSERT(font);
13066     NK_ASSERT(font->glyphs);
13067     if (!font || !glyph)
13068         return;
13069 
13070     scale = height/font->info.height;
13071     g = nk_font_find_glyph(font, codepoint);
13072     glyph->width = (g->x1 - g->x0) * scale;
13073     glyph->height = (g->y1 - g->y0) * scale;
13074     glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
13075     glyph->xadvance = (g->xadvance * scale);
13076     glyph->uv[0] = nk_vec2(g->u0, g->v0);
13077     glyph->uv[1] = nk_vec2(g->u1, g->v1);
13078 }
13079 #endif
13080 
13081 NK_API const struct nk_font_glyph*
13082 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
13083 {
13084     int i = 0;
13085     int count;
13086     int total_glyphs = 0;
13087     const struct nk_font_glyph *glyph = 0;
13088     const struct nk_font_config *iter = 0;
13089 
13090     NK_ASSERT(font);
13091     NK_ASSERT(font->glyphs);
13092     NK_ASSERT(font->info.ranges);
13093     if (!font || !font->glyphs) return 0;
13094 
13095     glyph = font->fallback;
13096     iter = font->config;
13097     do {count = nk_range_count(iter->range);
13098         for (i = 0; i < count; ++i) {
13099             nk_rune f = iter->range[(i*2)+0];
13100             nk_rune t = iter->range[(i*2)+1];
13101             int diff = (int)((t - f) + 1);
13102             if (unicode >= f && unicode <= t)
13103                 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
13104             total_glyphs += diff;
13105         }
13106     } while ((iter = iter->n) != font->config);
13107     return glyph;
13108 }
13109 
13110 NK_INTERN void
13111 nk_font_init(struct nk_font *font, float pixel_height,
13112     nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
13113     const struct nk_baked_font *baked_font, nk_handle atlas)
13114 {
13115     struct nk_baked_font baked;
13116     NK_ASSERT(font);
13117     NK_ASSERT(glyphs);
13118     NK_ASSERT(baked_font);
13119     if (!font || !glyphs || !baked_font)
13120         return;
13121 
13122     baked = *baked_font;
13123     font->fallback = 0;
13124     font->info = baked;
13125     font->scale = (float)pixel_height / (float)font->info.height;
13126     font->glyphs = &glyphs[baked_font->glyph_offset];
13127     font->texture = atlas;
13128     font->fallback_codepoint = fallback_codepoint;
13129     font->fallback = nk_font_find_glyph(font, fallback_codepoint);
13130 
13131     font->handle.height = font->info.height * font->scale;
13132     font->handle.width = nk_font_text_width;
13133     font->handle.userdata.ptr = font;
13134 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13135     font->handle.query = nk_font_query_font_glyph;
13136     font->handle.texture = font->texture;
13137 #endif
13138 }
13139 
13140 /* ---------------------------------------------------------------------------
13141  *
13142  *                          DEFAULT FONT
13143  *
13144  * ProggyClean.ttf
13145  * Copyright (c) 2004, 2005 Tristan Grimmer
13146  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
13147  * Download and more information at http://upperbounds.net
13148  *-----------------------------------------------------------------------------*/
13149 #ifdef NK_INCLUDE_DEFAULT_FONT
13150 
13151  #ifdef __clang__
13152 #pragma clang diagnostic push
13153 
13154 #pragma clang diagnostic ignored "-Woverlength-strings"
13155 #elif defined(__GNUC__) || defined(__GNUG__)
13156 #pragma GCC diagnostic push
13157 #pragma GCC diagnostic ignored "-Woverlength-strings"
13158 #endif
13159 
13160 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
13161     "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
13162     "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#"
13163     "`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"
13164     "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"
13165     "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"
13166     "*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)"
13167     "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"
13168     "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."
13169     "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"
13170     "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(,)"
13171     "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#"
13172     "'/###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"
13173     "_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"
13174     "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/"
13175     "/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"
13176     "%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&#"
13177     "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)("
13178     "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"
13179     "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"
13180     "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^-"
13181     "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-"
13182     "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"
13183     "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%"
13184     "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]"
13185     "%(?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"
13186     "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:"
13187     "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("
13188     "$/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<"
13189     "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'?"
13190     "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/;"
13191     ")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"
13192     "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("
13193     "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"
13194     "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
13195     "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<-"
13196     "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"
13197     "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"
13198     ".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@@"
13199     "$&)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*"
13200     "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"
13201     "@-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&#"
13202     "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#"
13203     "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"
13204     "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"
13205     "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&#"
13206     "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"
13207     ":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+"
13208     "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*"
13209     "$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"
13210     ":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"
13211     "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"
13212     "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"
13213     "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"
13214     ":^#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@&]>"
13215     "_>@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%"
13216     "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;"
13217     "^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:"
13218     "+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%"
13219     "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-"
13220     "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*"
13221     "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"
13222     "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
13223     "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`"
13224     "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]%/"
13225     "+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"
13226     "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"
13227     "?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"
13228     "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"
13229     ">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'>"
13230     "[%$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"
13231     "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#"
13232     "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$"
13233     "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,)"
13234     "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"
13235     "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"
13236     "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"
13237     "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(#"
13238     ";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&>"
13239     "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#"
13240     "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"
13241     "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#"
13242     "/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-#"
13243     "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#"
13244     "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
13245     "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
13246     "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
13247 #endif /* NK_INCLUDE_DEFAULT_FONT */
13248 
13249 #define NK_CURSOR_DATA_W 90
13250 #define NK_CURSOR_DATA_H 27
13251 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
13252 {
13253     "..-         -XXXXXXX-    X    -           X           -XXXXXXX          -          XXXXXXX"
13254     "..-         -X.....X-   X.X   -          X.X          -X.....X          -          X.....X"
13255     "---         -XXX.XXX-  X...X  -         X...X         -X....X           -           X....X"
13256     "X           -  X.X  - X.....X -        X.....X        -X...X            -            X...X"
13257     "XX          -  X.X  -X.......X-       X.......X       -X..X.X           -           X.X..X"
13258     "X.X         -  X.X  -XXXX.XXXX-       XXXX.XXXX       -X.X X.X          -          X.X X.X"
13259     "X..X        -  X.X  -   X.X   -          X.X          -XX   X.X         -         X.X   XX"
13260     "X...X       -  X.X  -   X.X   -    XX    X.X    XX    -      X.X        -        X.X      "
13261     "X....X      -  X.X  -   X.X   -   X.X    X.X    X.X   -       X.X       -       X.X       "
13262     "X.....X     -  X.X  -   X.X   -  X..X    X.X    X..X  -        X.X      -      X.X        "
13263     "X......X    -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -         X.X   XX-XX   X.X         "
13264     "X.......X   -  X.X  -   X.X   -X.....................X-          X.X X.X-X.X X.X          "
13265     "X........X  -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -           X.X..X-X..X.X           "
13266     "X.........X -XXX.XXX-   X.X   -  X..X    X.X    X..X  -            X...X-X...X            "
13267     "X..........X-X.....X-   X.X   -   X.X    X.X    X.X   -           X....X-X....X           "
13268     "X......XXXXX-XXXXXXX-   X.X   -    XX    X.X    XX    -          X.....X-X.....X          "
13269     "X...X..X    ---------   X.X   -          X.X          -          XXXXXXX-XXXXXXX          "
13270     "X..X X..X   -       -XXXX.XXXX-       XXXX.XXXX       ------------------------------------"
13271     "X.X  X..X   -       -X.......X-       X.......X       -    XX           XX    -           "
13272     "XX    X..X  -       - X.....X -        X.....X        -   X.X           X.X   -           "
13273     "      X..X          -  X...X  -         X...X         -  X..X           X..X  -           "
13274     "       XX           -   X.X   -          X.X          - X...XXXXXXXXXXXXX...X -           "
13275     "------------        -    X    -           X           -X.....................X-           "
13276     "                    ----------------------------------- X...XXXXXXXXXXXXX...X -           "
13277     "                                                      -  X..X           X..X  -           "
13278     "                                                      -   X.X           X.X   -           "
13279     "                                                      -    XX           XX    -           "
13280 };
13281 
13282 #ifdef __clang__
13283 #pragma clang diagnostic pop
13284 #elif defined(__GNUC__) || defined(__GNUG__)
13285 #pragma GCC diagnostic pop
13286 #endif
13287 
13288 NK_INTERN unsigned int
13289 nk_decompress_length(unsigned char *input)
13290 {
13291     return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
13292 }
13293 
13294 NK_GLOBAL unsigned char *nk__barrier;
13295 NK_GLOBAL unsigned char *nk__barrier2;
13296 NK_GLOBAL unsigned char *nk__barrier3;
13297 NK_GLOBAL unsigned char *nk__barrier4;
13298 NK_GLOBAL unsigned char *nk__dout;
13299 
13300 NK_INTERN void
13301 nk__match(unsigned char *data, unsigned int length)
13302 {
13303     /* INVERSE of memmove... write each byte before copying the next...*/
13304     NK_ASSERT (nk__dout + length <= nk__barrier);
13305     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
13306     if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
13307     while (length--) *nk__dout++ = *data++;
13308 }
13309 
13310 NK_INTERN void
13311 nk__lit(unsigned char *data, unsigned int length)
13312 {
13313     NK_ASSERT (nk__dout + length <= nk__barrier);
13314     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
13315     if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
13316     NK_MEMCPY(nk__dout, data, length);
13317     nk__dout += length;
13318 }
13319 
13320 #define nk__in2(x)   ((i[x] << 8) + i[(x)+1])
13321 #define nk__in3(x)   ((i[x] << 16) + nk__in2((x)+1))
13322 #define nk__in4(x)   ((i[x] << 24) + nk__in3((x)+1))
13323 
13324 NK_INTERN unsigned char*
13325 nk_decompress_token(unsigned char *i)
13326 {
13327     if (*i >= 0x20) { /* use fewer if's for cases that expand small */
13328         if (*i >= 0x80)       nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
13329         else if (*i >= 0x40)  nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
13330         else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
13331     } else { /* more ifs for cases that expand large, since overhead is amortized */
13332         if (*i >= 0x18)       nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
13333         else if (*i >= 0x10)  nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
13334         else if (*i >= 0x08)  nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
13335         else if (*i == 0x07)  nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
13336         else if (*i == 0x06)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
13337         else if (*i == 0x04)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
13338     }
13339     return i;
13340 }
13341 
13342 NK_INTERN unsigned int
13343 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
13344 {
13345     const unsigned long ADLER_MOD = 65521;
13346     unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
13347     unsigned long blocklen, i;
13348 
13349     blocklen = buflen % 5552;
13350     while (buflen) {
13351         for (i=0; i + 7 < blocklen; i += 8) {
13352             s1 += buffer[0]; s2 += s1;
13353             s1 += buffer[1]; s2 += s1;
13354             s1 += buffer[2]; s2 += s1;
13355             s1 += buffer[3]; s2 += s1;
13356             s1 += buffer[4]; s2 += s1;
13357             s1 += buffer[5]; s2 += s1;
13358             s1 += buffer[6]; s2 += s1;
13359             s1 += buffer[7]; s2 += s1;
13360             buffer += 8;
13361         }
13362         for (; i < blocklen; ++i) {
13363             s1 += *buffer++; s2 += s1;
13364         }
13365 
13366         s1 %= ADLER_MOD; s2 %= ADLER_MOD;
13367         buflen -= (unsigned int)blocklen;
13368         blocklen = 5552;
13369     }
13370     return (unsigned int)(s2 << 16) + (unsigned int)s1;
13371 }
13372 
13373 NK_INTERN unsigned int
13374 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
13375 {
13376     unsigned int olen;
13377     if (nk__in4(0) != 0x57bC0000) return 0;
13378     if (nk__in4(4) != 0)          return 0; /* error! stream is > 4GB */
13379     olen = nk_decompress_length(i);
13380     nk__barrier2 = i;
13381     nk__barrier3 = i+length;
13382     nk__barrier = output + olen;
13383     nk__barrier4 = output;
13384     i += 16;
13385 
13386     nk__dout = output;
13387     for (;;) {
13388         unsigned char *old_i = i;
13389         i = nk_decompress_token(i);
13390         if (i == old_i) {
13391             if (*i == 0x05 && i[1] == 0xfa) {
13392                 NK_ASSERT(nk__dout == output + olen);
13393                 if (nk__dout != output + olen) return 0;
13394                 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
13395                     return 0;
13396                 return olen;
13397             } else {
13398                 NK_ASSERT(0); /* NOTREACHED */
13399                 return 0;
13400             }
13401         }
13402         NK_ASSERT(nk__dout <= output + olen);
13403         if (nk__dout > output + olen)
13404             return 0;
13405     }
13406 }
13407 
13408 NK_INTERN unsigned int
13409 nk_decode_85_byte(char c)
13410 { return (unsigned int)((c >= '\\') ? c-36 : c-35); }
13411 
13412 NK_INTERN void
13413 nk_decode_85(unsigned char* dst, const unsigned char* src)
13414 {
13415     while (*src)
13416     {
13417         unsigned int tmp =
13418             nk_decode_85_byte((char)src[0]) +
13419             85 * (nk_decode_85_byte((char)src[1]) +
13420             85 * (nk_decode_85_byte((char)src[2]) +
13421             85 * (nk_decode_85_byte((char)src[3]) +
13422             85 * nk_decode_85_byte((char)src[4]))));
13423 
13424         /* we can't assume little-endianess. */
13425         dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
13426         dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
13427         dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
13428         dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
13429 
13430         src += 5;
13431         dst += 4;
13432     }
13433 }
13434 
13435 /* -------------------------------------------------------------
13436  *
13437  *                          FONT ATLAS
13438  *
13439  * --------------------------------------------------------------*/
13440 NK_API struct nk_font_config
13441 nk_font_config(float pixel_height)
13442 {
13443     struct nk_font_config cfg;
13444     nk_zero_struct(cfg);
13445     cfg.ttf_blob = 0;
13446     cfg.ttf_size = 0;
13447     cfg.ttf_data_owned_by_atlas = 0;
13448     cfg.size = pixel_height;
13449     cfg.oversample_h = 3;
13450     cfg.oversample_v = 1;
13451     cfg.pixel_snap = 0;
13452     cfg.coord_type = NK_COORD_UV;
13453     cfg.spacing = nk_vec2(0,0);
13454     cfg.range = nk_font_default_glyph_ranges();
13455     cfg.merge_mode = 0;
13456     cfg.fallback_glyph = '?';
13457     cfg.font = 0;
13458     cfg.n = 0;
13459     return cfg;
13460 }
13461 
13462 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13463 NK_API void
13464 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
13465 {
13466     NK_ASSERT(atlas);
13467     if (!atlas) return;
13468     nk_zero_struct(*atlas);
13469     atlas->temporary.userdata.ptr = 0;
13470     atlas->temporary.alloc = nk_malloc;
13471     atlas->temporary.free = nk_mfree;
13472     atlas->permanent.userdata.ptr = 0;
13473     atlas->permanent.alloc = nk_malloc;
13474     atlas->permanent.free = nk_mfree;
13475 }
13476 #endif
13477 
13478 NK_API void
13479 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
13480 {
13481     NK_ASSERT(atlas);
13482     NK_ASSERT(alloc);
13483     if (!atlas || !alloc) return;
13484     nk_zero_struct(*atlas);
13485     atlas->permanent = *alloc;
13486     atlas->temporary = *alloc;
13487 }
13488 
13489 NK_API void
13490 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
13491     struct nk_allocator *permanent, struct nk_allocator *temporary)
13492 {
13493     NK_ASSERT(atlas);
13494     NK_ASSERT(permanent);
13495     NK_ASSERT(temporary);
13496     if (!atlas || !permanent || !temporary) return;
13497     nk_zero_struct(*atlas);
13498     atlas->permanent = *permanent;
13499     atlas->temporary = *temporary;
13500 }
13501 
13502 NK_API void
13503 nk_font_atlas_begin(struct nk_font_atlas *atlas)
13504 {
13505     NK_ASSERT(atlas);
13506     NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
13507     NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
13508     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
13509         !atlas->temporary.alloc || !atlas->temporary.free) return;
13510     if (atlas->glyphs) {
13511         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13512         atlas->glyphs = 0;
13513     }
13514     if (atlas->pixel) {
13515         atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
13516         atlas->pixel = 0;
13517     }
13518 }
13519 
13520 NK_API struct nk_font*
13521 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
13522 {
13523     struct nk_font *font = 0;
13524     struct nk_font_config *cfg;
13525 
13526     NK_ASSERT(atlas);
13527     NK_ASSERT(atlas->permanent.alloc);
13528     NK_ASSERT(atlas->permanent.free);
13529     NK_ASSERT(atlas->temporary.alloc);
13530     NK_ASSERT(atlas->temporary.free);
13531 
13532     NK_ASSERT(config);
13533     NK_ASSERT(config->ttf_blob);
13534     NK_ASSERT(config->ttf_size);
13535     NK_ASSERT(config->size > 0.0f);
13536 
13537     if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
13538         !atlas->permanent.alloc || !atlas->permanent.free ||
13539         !atlas->temporary.alloc || !atlas->temporary.free)
13540         return 0;
13541 
13542     /* allocate font config  */
13543     cfg = (struct nk_font_config*)
13544         atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
13545     NK_MEMCPY(cfg, config, sizeof(*config));
13546     cfg->n = cfg;
13547     cfg->p = cfg;
13548 
13549     if (!config->merge_mode) {
13550         /* insert font config into list */
13551         if (!atlas->config) {
13552             atlas->config = cfg;
13553             cfg->next = 0;
13554         } else {
13555             struct nk_font_config *i = atlas->config;
13556             while (i->next) i = i->next;
13557             i->next = cfg;
13558             cfg->next = 0;
13559         }
13560         /* allocate new font */
13561         font = (struct nk_font*)
13562             atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
13563         NK_ASSERT(font);
13564         nk_zero(font, sizeof(*font));
13565         if (!font) return 0;
13566         font->config = cfg;
13567 
13568         /* insert font into list */
13569         if (!atlas->fonts) {
13570             atlas->fonts = font;
13571             font->next = 0;
13572         } else {
13573             struct nk_font *i = atlas->fonts;
13574             while (i->next) i = i->next;
13575             i->next = font;
13576             font->next = 0;
13577         }
13578         cfg->font = &font->info;
13579     } else {
13580         /* extend previously added font */
13581         struct nk_font *f = 0;
13582         struct nk_font_config *c = 0;
13583         NK_ASSERT(atlas->font_num);
13584         f = atlas->fonts;
13585         c = f->config;
13586         cfg->font = &f->info;
13587 
13588         cfg->n = c;
13589         cfg->p = c->p;
13590         c->p->n = cfg;
13591         c->p = cfg;
13592     }
13593     /* create own copy of .TTF font blob */
13594     if (!config->ttf_data_owned_by_atlas) {
13595         cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
13596         NK_ASSERT(cfg->ttf_blob);
13597         if (!cfg->ttf_blob) {
13598             atlas->font_num++;
13599             return 0;
13600         }
13601         NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
13602         cfg->ttf_data_owned_by_atlas = 1;
13603     }
13604     atlas->font_num++;
13605     return font;
13606 }
13607 
13608 NK_API struct nk_font*
13609 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
13610     nk_size size, float height, const struct nk_font_config *config)
13611 {
13612     struct nk_font_config cfg;
13613     NK_ASSERT(memory);
13614     NK_ASSERT(size);
13615 
13616     NK_ASSERT(atlas);
13617     NK_ASSERT(atlas->temporary.alloc);
13618     NK_ASSERT(atlas->temporary.free);
13619     NK_ASSERT(atlas->permanent.alloc);
13620     NK_ASSERT(atlas->permanent.free);
13621     if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
13622         !atlas->permanent.alloc || !atlas->permanent.free)
13623         return 0;
13624 
13625     cfg = (config) ? *config: nk_font_config(height);
13626     cfg.ttf_blob = memory;
13627     cfg.ttf_size = size;
13628     cfg.size = height;
13629     cfg.ttf_data_owned_by_atlas = 0;
13630     return nk_font_atlas_add(atlas, &cfg);
13631 }
13632 
13633 #ifdef NK_INCLUDE_STANDARD_IO
13634 NK_API struct nk_font*
13635 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
13636     float height, const struct nk_font_config *config)
13637 {
13638     nk_size size;
13639     char *memory;
13640     struct nk_font_config cfg;
13641 
13642     NK_ASSERT(atlas);
13643     NK_ASSERT(atlas->temporary.alloc);
13644     NK_ASSERT(atlas->temporary.free);
13645     NK_ASSERT(atlas->permanent.alloc);
13646     NK_ASSERT(atlas->permanent.free);
13647 
13648     if (!atlas || !file_path) return 0;
13649     memory = nk_file_load(file_path, &size, &atlas->permanent);
13650     if (!memory) return 0;
13651 
13652     cfg = (config) ? *config: nk_font_config(height);
13653     cfg.ttf_blob = memory;
13654     cfg.ttf_size = size;
13655     cfg.size = height;
13656     cfg.ttf_data_owned_by_atlas = 1;
13657     return nk_font_atlas_add(atlas, &cfg);
13658 }
13659 #endif
13660 
13661 NK_API struct nk_font*
13662 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
13663     void *compressed_data, nk_size compressed_size, float height,
13664     const struct nk_font_config *config)
13665 {
13666     unsigned int decompressed_size;
13667     void *decompressed_data;
13668     struct nk_font_config cfg;
13669 
13670     NK_ASSERT(atlas);
13671     NK_ASSERT(atlas->temporary.alloc);
13672     NK_ASSERT(atlas->temporary.free);
13673     NK_ASSERT(atlas->permanent.alloc);
13674     NK_ASSERT(atlas->permanent.free);
13675 
13676     NK_ASSERT(compressed_data);
13677     NK_ASSERT(compressed_size);
13678     if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
13679         !atlas->permanent.alloc || !atlas->permanent.free)
13680         return 0;
13681 
13682     decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
13683     decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
13684     NK_ASSERT(decompressed_data);
13685     if (!decompressed_data) return 0;
13686     nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
13687         (unsigned int)compressed_size);
13688 
13689     cfg = (config) ? *config: nk_font_config(height);
13690     cfg.ttf_blob = decompressed_data;
13691     cfg.ttf_size = decompressed_size;
13692     cfg.size = height;
13693     cfg.ttf_data_owned_by_atlas = 1;
13694     return nk_font_atlas_add(atlas, &cfg);
13695 }
13696 
13697 NK_API struct nk_font*
13698 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
13699     const char *data_base85, float height, const struct nk_font_config *config)
13700 {
13701     int compressed_size;
13702     void *compressed_data;
13703     struct nk_font *font;
13704 
13705     NK_ASSERT(atlas);
13706     NK_ASSERT(atlas->temporary.alloc);
13707     NK_ASSERT(atlas->temporary.free);
13708     NK_ASSERT(atlas->permanent.alloc);
13709     NK_ASSERT(atlas->permanent.free);
13710 
13711     NK_ASSERT(data_base85);
13712     if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
13713         !atlas->permanent.alloc || !atlas->permanent.free)
13714         return 0;
13715 
13716     compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
13717     compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
13718     NK_ASSERT(compressed_data);
13719     if (!compressed_data) return 0;
13720     nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
13721     font = nk_font_atlas_add_compressed(atlas, compressed_data,
13722                     (nk_size)compressed_size, height, config);
13723     atlas->temporary.free(atlas->temporary.userdata, compressed_data);
13724     return font;
13725 }
13726 
13727 #ifdef NK_INCLUDE_DEFAULT_FONT
13728 NK_API struct nk_font*
13729 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
13730     float pixel_height, const struct nk_font_config *config)
13731 {
13732     NK_ASSERT(atlas);
13733     NK_ASSERT(atlas->temporary.alloc);
13734     NK_ASSERT(atlas->temporary.free);
13735     NK_ASSERT(atlas->permanent.alloc);
13736     NK_ASSERT(atlas->permanent.free);
13737     return nk_font_atlas_add_compressed_base85(atlas,
13738         nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
13739 }
13740 #endif
13741 
13742 NK_API const void*
13743 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
13744     enum nk_font_atlas_format fmt)
13745 {
13746     int i = 0;
13747     void *tmp = 0;
13748     nk_size tmp_size, img_size;
13749     struct nk_font *font_iter;
13750     struct nk_font_baker *baker;
13751 
13752     NK_ASSERT(atlas);
13753     NK_ASSERT(atlas->temporary.alloc);
13754     NK_ASSERT(atlas->temporary.free);
13755     NK_ASSERT(atlas->permanent.alloc);
13756     NK_ASSERT(atlas->permanent.free);
13757 
13758     NK_ASSERT(width);
13759     NK_ASSERT(height);
13760     if (!atlas || !width || !height ||
13761         !atlas->temporary.alloc || !atlas->temporary.free ||
13762         !atlas->permanent.alloc || !atlas->permanent.free)
13763         return 0;
13764 
13765 #ifdef NK_INCLUDE_DEFAULT_FONT
13766     /* no font added so just use default font */
13767     if (!atlas->font_num)
13768         atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
13769 #endif
13770     NK_ASSERT(atlas->font_num);
13771     if (!atlas->font_num) return 0;
13772 
13773     /* allocate temporary baker memory required for the baking process */
13774     nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
13775     tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
13776     NK_ASSERT(tmp);
13777     if (!tmp) goto failed;
13778 
13779     /* allocate glyph memory for all fonts */
13780     baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
13781     atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
13782         atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
13783     NK_ASSERT(atlas->glyphs);
13784     if (!atlas->glyphs)
13785         goto failed;
13786 
13787     /* pack all glyphs into a tight fit space */
13788     atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
13789     atlas->custom.h = NK_CURSOR_DATA_H + 1;
13790     if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
13791         atlas->config, atlas->font_num, &atlas->temporary))
13792         goto failed;
13793 
13794     /* allocate memory for the baked image font atlas */
13795     atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
13796     NK_ASSERT(atlas->pixel);
13797     if (!atlas->pixel)
13798         goto failed;
13799 
13800     /* bake glyphs and custom white pixel into image */
13801     nk_font_bake(baker, atlas->pixel, *width, *height,
13802         atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
13803     nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
13804             nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
13805 
13806     if (fmt == NK_FONT_ATLAS_RGBA32) {
13807         /* convert alpha8 image into rgba32 image */
13808         void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
13809                             (nk_size)(*width * *height * 4));
13810         NK_ASSERT(img_rgba);
13811         if (!img_rgba) goto failed;
13812         nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
13813         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13814         atlas->pixel = img_rgba;
13815     }
13816     atlas->tex_width = *width;
13817     atlas->tex_height = *height;
13818 
13819     /* initialize each font */
13820     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
13821         struct nk_font *font = font_iter;
13822         struct nk_font_config *config = font->config;
13823         nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
13824             config->font, nk_handle_ptr(0));
13825     }
13826 
13827     /* initialize each cursor */
13828     {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
13829         /* Pos      Size        Offset */
13830         {{ 0, 3},   {12,19},    { 0, 0}},
13831         {{13, 0},   { 7,16},    { 4, 8}},
13832         {{31, 0},   {23,23},    {11,11}},
13833         {{21, 0},   { 9, 23},   { 5,11}},
13834         {{55,18},   {23, 9},    {11, 5}},
13835         {{73, 0},   {17,17},    { 9, 9}},
13836         {{55, 0},   {17,17},    { 9, 9}}
13837     };
13838     for (i = 0; i < NK_CURSOR_COUNT; ++i) {
13839         struct nk_cursor *cursor = &atlas->cursors[i];
13840         cursor->img.w = (unsigned short)*width;
13841         cursor->img.h = (unsigned short)*height;
13842         cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
13843         cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
13844         cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
13845         cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
13846         cursor->size = nk_cursor_data[i][1];
13847         cursor->offset = nk_cursor_data[i][2];
13848     }}
13849     /* free temporary memory */
13850     atlas->temporary.free(atlas->temporary.userdata, tmp);
13851     return atlas->pixel;
13852 
13853 failed:
13854     /* error so cleanup all memory */
13855     if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
13856     if (atlas->glyphs) {
13857         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13858         atlas->glyphs = 0;
13859     }
13860     if (atlas->pixel) {
13861         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13862         atlas->pixel = 0;
13863     }
13864     return 0;
13865 }
13866 
13867 NK_API void
13868 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
13869     struct nk_draw_null_texture *null)
13870 {
13871     int i = 0;
13872     struct nk_font *font_iter;
13873     NK_ASSERT(atlas);
13874     if (!atlas) {
13875         if (!null) return;
13876         null->texture = texture;
13877         null->uv = nk_vec2(0.5f,0.5f);
13878     }
13879     if (null) {
13880         null->texture = texture;
13881         null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
13882         null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
13883     }
13884     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
13885         font_iter->texture = texture;
13886 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13887         font_iter->handle.texture = texture;
13888 #endif
13889     }
13890     for (i = 0; i < NK_CURSOR_COUNT; ++i)
13891         atlas->cursors[i].img.handle = texture;
13892 
13893     atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13894     atlas->pixel = 0;
13895     atlas->tex_width = 0;
13896     atlas->tex_height = 0;
13897     atlas->custom.x = 0;
13898     atlas->custom.y = 0;
13899     atlas->custom.w = 0;
13900     atlas->custom.h = 0;
13901 }
13902 
13903 NK_API void
13904 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
13905 {
13906     NK_ASSERT(atlas);
13907     NK_ASSERT(atlas->temporary.alloc);
13908     NK_ASSERT(atlas->temporary.free);
13909     NK_ASSERT(atlas->permanent.alloc);
13910     NK_ASSERT(atlas->permanent.free);
13911     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
13912     if (atlas->config) {
13913         struct nk_font_config *iter;
13914         for (iter = atlas->config; iter; iter = iter->next) {
13915             struct nk_font_config *i;
13916             for (i = iter->n; i != iter; i = i->n) {
13917                 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
13918                 i->ttf_blob = 0;
13919             }
13920             atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
13921             iter->ttf_blob = 0;
13922         }
13923     }
13924 }
13925 
13926 NK_API void
13927 nk_font_atlas_clear(struct nk_font_atlas *atlas)
13928 {
13929     NK_ASSERT(atlas);
13930     NK_ASSERT(atlas->temporary.alloc);
13931     NK_ASSERT(atlas->temporary.free);
13932     NK_ASSERT(atlas->permanent.alloc);
13933     NK_ASSERT(atlas->permanent.free);
13934     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
13935 
13936     if (atlas->config) {
13937         struct nk_font_config *iter, *next;
13938         for (iter = atlas->config; iter; iter = next) {
13939             struct nk_font_config *i, *n;
13940             for (i = iter->n; i != iter; i = n) {
13941                 n = i->n;
13942                 if (i->ttf_blob)
13943                     atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
13944                 atlas->permanent.free(atlas->permanent.userdata, i);
13945             }
13946             next = iter->next;
13947             if (i->ttf_blob)
13948                 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
13949             atlas->permanent.free(atlas->permanent.userdata, iter);
13950         }
13951         atlas->config = 0;
13952     }
13953     if (atlas->fonts) {
13954         struct nk_font *iter, *next;
13955         for (iter = atlas->fonts; iter; iter = next) {
13956             next = iter->next;
13957             atlas->permanent.free(atlas->permanent.userdata, iter);
13958         }
13959         atlas->fonts = 0;
13960     }
13961     if (atlas->glyphs)
13962         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13963     nk_zero_struct(*atlas);
13964 }
13965 #endif
13966 /* ==============================================================
13967  *
13968  *                          INPUT
13969  *
13970  * ===============================================================*/
13971 NK_API void
13972 nk_input_begin(struct nk_context *ctx)
13973 {
13974     int i;
13975     struct nk_input *in;
13976     NK_ASSERT(ctx);
13977     if (!ctx) return;
13978     in = &ctx->input;
13979     for (i = 0; i < NK_BUTTON_MAX; ++i)
13980         in->mouse.buttons[i].clicked = 0;
13981 
13982     in->keyboard.text_len = 0;
13983     in->mouse.scroll_delta = nk_vec2(0,0);
13984     in->mouse.prev.x = in->mouse.pos.x;
13985     in->mouse.prev.y = in->mouse.pos.y;
13986     in->mouse.delta.x = 0;
13987     in->mouse.delta.y = 0;
13988     for (i = 0; i < NK_KEY_MAX; i++)
13989         in->keyboard.keys[i].clicked = 0;
13990 }
13991 
13992 NK_API void
13993 nk_input_end(struct nk_context *ctx)
13994 {
13995     struct nk_input *in;
13996     NK_ASSERT(ctx);
13997     if (!ctx) return;
13998     in = &ctx->input;
13999     if (in->mouse.grab)
14000         in->mouse.grab = 0;
14001     if (in->mouse.ungrab) {
14002         in->mouse.grabbed = 0;
14003         in->mouse.ungrab = 0;
14004         in->mouse.grab = 0;
14005     }
14006 }
14007 
14008 NK_API void
14009 nk_input_motion(struct nk_context *ctx, int x, int y)
14010 {
14011     struct nk_input *in;
14012     NK_ASSERT(ctx);
14013     if (!ctx) return;
14014     in = &ctx->input;
14015     in->mouse.pos.x = (float)x;
14016     in->mouse.pos.y = (float)y;
14017     in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
14018     in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
14019 }
14020 
14021 NK_API void
14022 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
14023 {
14024     struct nk_input *in;
14025     NK_ASSERT(ctx);
14026     if (!ctx) return;
14027     in = &ctx->input;
14028     if (in->keyboard.keys[key].down != down)
14029         in->keyboard.keys[key].clicked++;
14030     in->keyboard.keys[key].down = down;
14031 }
14032 
14033 NK_API void
14034 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
14035 {
14036     struct nk_mouse_button *btn;
14037     struct nk_input *in;
14038     NK_ASSERT(ctx);
14039     if (!ctx) return;
14040     in = &ctx->input;
14041     if (in->mouse.buttons[id].down == down) return;
14042 
14043     btn = &in->mouse.buttons[id];
14044     btn->clicked_pos.x = (float)x;
14045     btn->clicked_pos.y = (float)y;
14046     btn->down = down;
14047     btn->clicked++;
14048 }
14049 
14050 NK_API void
14051 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
14052 {
14053     NK_ASSERT(ctx);
14054     if (!ctx) return;
14055     ctx->input.mouse.scroll_delta.x += val.x;
14056     ctx->input.mouse.scroll_delta.y += val.y;
14057 }
14058 
14059 NK_API void
14060 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
14061 {
14062     int len = 0;
14063     nk_rune unicode;
14064     struct nk_input *in;
14065 
14066     NK_ASSERT(ctx);
14067     if (!ctx) return;
14068     in = &ctx->input;
14069 
14070     len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
14071     if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
14072         nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
14073             NK_INPUT_MAX - in->keyboard.text_len);
14074         in->keyboard.text_len += len;
14075     }
14076 }
14077 
14078 NK_API void
14079 nk_input_char(struct nk_context *ctx, char c)
14080 {
14081     nk_glyph glyph;
14082     NK_ASSERT(ctx);
14083     if (!ctx) return;
14084     glyph[0] = c;
14085     nk_input_glyph(ctx, glyph);
14086 }
14087 
14088 NK_API void
14089 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
14090 {
14091     nk_glyph rune;
14092     NK_ASSERT(ctx);
14093     if (!ctx) return;
14094     nk_utf_encode(unicode, rune, NK_UTF_SIZE);
14095     nk_input_glyph(ctx, rune);
14096 }
14097 
14098 NK_API int
14099 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
14100 {
14101     const struct nk_mouse_button *btn;
14102     if (!i) return nk_false;
14103     btn = &i->mouse.buttons[id];
14104     return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
14105 }
14106 
14107 NK_API int
14108 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
14109     struct nk_rect b)
14110 {
14111     const struct nk_mouse_button *btn;
14112     if (!i) return nk_false;
14113     btn = &i->mouse.buttons[id];
14114     if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
14115         return nk_false;
14116     return nk_true;
14117 }
14118 
14119 NK_API int
14120 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
14121     struct nk_rect b, int down)
14122 {
14123     const struct nk_mouse_button *btn;
14124     if (!i) return nk_false;
14125     btn = &i->mouse.buttons[id];
14126     return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
14127 }
14128 
14129 NK_API int
14130 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
14131     struct nk_rect b)
14132 {
14133     const struct nk_mouse_button *btn;
14134     if (!i) return nk_false;
14135     btn = &i->mouse.buttons[id];
14136     return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
14137             btn->clicked) ? nk_true : nk_false;
14138 }
14139 
14140 NK_API int
14141 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
14142     struct nk_rect b, int down)
14143 {
14144     const struct nk_mouse_button *btn;
14145     if (!i) return nk_false;
14146     btn = &i->mouse.buttons[id];
14147     return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
14148             btn->clicked) ? nk_true : nk_false;
14149 }
14150 
14151 NK_API int
14152 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
14153 {
14154     int i, down = 0;
14155     for (i = 0; i < NK_BUTTON_MAX; ++i)
14156         down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
14157     return down;
14158 }
14159 
14160 NK_API int
14161 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
14162 {
14163     if (!i) return nk_false;
14164     return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
14165 }
14166 
14167 NK_API int
14168 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
14169 {
14170     if (!i) return nk_false;
14171     return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
14172 }
14173 
14174 NK_API int
14175 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
14176 {
14177     if (!i) return nk_false;
14178     if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
14179     return nk_input_is_mouse_click_in_rect(i, id, rect);
14180 }
14181 
14182 NK_API int
14183 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
14184 {
14185     if (!i) return nk_false;
14186     return i->mouse.buttons[id].down;
14187 }
14188 
14189 NK_API int
14190 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
14191 {
14192     const struct nk_mouse_button *b;
14193     if (!i) return nk_false;
14194     b = &i->mouse.buttons[id];
14195     if (b->down && b->clicked)
14196         return nk_true;
14197     return nk_false;
14198 }
14199 
14200 NK_API int
14201 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
14202 {
14203     if (!i) return nk_false;
14204     return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
14205 }
14206 
14207 NK_API int
14208 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
14209 {
14210     const struct nk_key *k;
14211     if (!i) return nk_false;
14212     k = &i->keyboard.keys[key];
14213     if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
14214         return nk_true;
14215     return nk_false;
14216 }
14217 
14218 NK_API int
14219 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
14220 {
14221     const struct nk_key *k;
14222     if (!i) return nk_false;
14223     k = &i->keyboard.keys[key];
14224     if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
14225         return nk_true;
14226     return nk_false;
14227 }
14228 
14229 NK_API int
14230 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
14231 {
14232     const struct nk_key *k;
14233     if (!i) return nk_false;
14234     k = &i->keyboard.keys[key];
14235     if (k->down) return nk_true;
14236     return nk_false;
14237 }
14238 
14239 /*
14240  * ==============================================================
14241  *
14242  *                          TEXT EDITOR
14243  *
14244  * ===============================================================
14245  */
14246 /* stb_textedit.h - v1.8  - public domain - Sean Barrett */
14247 struct nk_text_find {
14248    float x,y;    /* position of n'th character */
14249    float height; /* height of line */
14250    int first_char, length; /* first char of row, and length */
14251    int prev_first;  /*_ first char of previous row */
14252 };
14253 
14254 struct nk_text_edit_row {
14255    float x0,x1;
14256    /* starting x location, end x location (allows for align=right, etc) */
14257    float baseline_y_delta;
14258    /* position of baseline relative to previous row's baseline*/
14259    float ymin,ymax;
14260    /* height of row above and below baseline */
14261    int num_chars;
14262 };
14263 
14264 /* forward declarations */
14265 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
14266 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
14267 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
14268 #define NK_TEXT_HAS_SELECTION(s)   ((s)->select_start != (s)->select_end)
14269 
14270 NK_INTERN float
14271 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
14272     const struct nk_user_font *font)
14273 {
14274     int len = 0;
14275     nk_rune unicode = 0;
14276     const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
14277     return font->width(font->userdata, font->height, str, len);
14278 }
14279 
14280 NK_INTERN void
14281 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
14282     int line_start_id, float row_height, const struct nk_user_font *font)
14283 {
14284     int l;
14285     int glyphs = 0;
14286     nk_rune unicode;
14287     const char *remaining;
14288     int len = nk_str_len_char(&edit->string);
14289     const char *end = nk_str_get_const(&edit->string) + len;
14290     const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
14291     const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
14292         text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
14293 
14294     r->x0 = 0.0f;
14295     r->x1 = size.x;
14296     r->baseline_y_delta = size.y;
14297     r->ymin = 0.0f;
14298     r->ymax = size.y;
14299     r->num_chars = glyphs;
14300 }
14301 
14302 NK_INTERN int
14303 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
14304     const struct nk_user_font *font, float row_height)
14305 {
14306     struct nk_text_edit_row r;
14307     int n = edit->string.len;
14308     float base_y = 0, prev_x;
14309     int i=0, k;
14310 
14311     r.x0 = r.x1 = 0;
14312     r.ymin = r.ymax = 0;
14313     r.num_chars = 0;
14314 
14315     /* search rows to find one that straddles 'y' */
14316     while (i < n) {
14317         nk_textedit_layout_row(&r, edit, i, row_height, font);
14318         if (r.num_chars <= 0)
14319             return n;
14320 
14321         if (i==0 && y < base_y + r.ymin)
14322             return 0;
14323 
14324         if (y < base_y + r.ymax)
14325             break;
14326 
14327         i += r.num_chars;
14328         base_y += r.baseline_y_delta;
14329     }
14330 
14331     /* below all text, return 'after' last character */
14332     if (i >= n)
14333         return n;
14334 
14335     /* check if it's before the beginning of the line */
14336     if (x < r.x0)
14337         return i;
14338 
14339     /* check if it's before the end of the line */
14340     if (x < r.x1) {
14341         /* search characters in row for one that straddles 'x' */
14342         k = i;
14343         prev_x = r.x0;
14344         for (i=0; i < r.num_chars; ++i) {
14345             float w = nk_textedit_get_width(edit, k, i, font);
14346             if (x < prev_x+w) {
14347                 if (x < prev_x+w/2)
14348                     return k+i;
14349                 else return k+i+1;
14350             }
14351             prev_x += w;
14352         }
14353         /* shouldn't happen, but if it does, fall through to end-of-line case */
14354     }
14355 
14356     /* if the last character is a newline, return that.
14357      * otherwise return 'after' the last character */
14358     if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
14359         return i+r.num_chars-1;
14360     else return i+r.num_chars;
14361 }
14362 
14363 NK_INTERN void
14364 nk_textedit_click(struct nk_text_edit *state, float x, float y,
14365     const struct nk_user_font *font, float row_height)
14366 {
14367     /* API click: on mouse down, move the cursor to the clicked location,
14368      * and reset the selection */
14369     state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
14370     state->select_start = state->cursor;
14371     state->select_end = state->cursor;
14372     state->has_preferred_x = 0;
14373 }
14374 
14375 NK_INTERN void
14376 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
14377     const struct nk_user_font *font, float row_height)
14378 {
14379     /* API drag: on mouse drag, move the cursor and selection endpoint
14380      * to the clicked location */
14381     int p = nk_textedit_locate_coord(state, x, y, font, row_height);
14382     if (state->select_start == state->select_end)
14383         state->select_start = state->cursor;
14384     state->cursor = state->select_end = p;
14385 }
14386 
14387 NK_INTERN void
14388 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
14389     int n, int single_line, const struct nk_user_font *font, float row_height)
14390 {
14391     /* find the x/y location of a character, and remember info about the previous
14392      * row in case we get a move-up event (for page up, we'll have to rescan) */
14393     struct nk_text_edit_row r;
14394     int prev_start = 0;
14395     int z = state->string.len;
14396     int i=0, first;
14397 
14398     nk_zero_struct(r);
14399     if (n == z) {
14400         /* if it's at the end, then find the last line -- simpler than trying to
14401         explicitly handle this case in the regular code */
14402         nk_textedit_layout_row(&r, state, 0, row_height, font);
14403         if (single_line) {
14404             find->first_char = 0;
14405             find->length = z;
14406         } else {
14407             while (i < z) {
14408                 prev_start = i;
14409                 i += r.num_chars;
14410                 nk_textedit_layout_row(&r, state, i, row_height, font);
14411             }
14412 
14413             find->first_char = i;
14414             find->length = r.num_chars;
14415         }
14416         find->x = r.x1;
14417         find->y = r.ymin;
14418         find->height = r.ymax - r.ymin;
14419         find->prev_first = prev_start;
14420         return;
14421     }
14422 
14423     /* search rows to find the one that straddles character n */
14424     find->y = 0;
14425 
14426     for(;;) {
14427         nk_textedit_layout_row(&r, state, i, row_height, font);
14428         if (n < i + r.num_chars) break;
14429         prev_start = i;
14430         i += r.num_chars;
14431         find->y += r.baseline_y_delta;
14432     }
14433 
14434     find->first_char = first = i;
14435     find->length = r.num_chars;
14436     find->height = r.ymax - r.ymin;
14437     find->prev_first = prev_start;
14438 
14439     /* now scan to find xpos */
14440     find->x = r.x0;
14441     for (i=0; first+i < n; ++i)
14442         find->x += nk_textedit_get_width(state, first, i, font);
14443 }
14444 
14445 NK_INTERN void
14446 nk_textedit_clamp(struct nk_text_edit *state)
14447 {
14448     /* make the selection/cursor state valid if client altered the string */
14449     int n = state->string.len;
14450     if (NK_TEXT_HAS_SELECTION(state)) {
14451         if (state->select_start > n) state->select_start = n;
14452         if (state->select_end   > n) state->select_end = n;
14453         /* if clamping forced them to be equal, move the cursor to match */
14454         if (state->select_start == state->select_end)
14455             state->cursor = state->select_start;
14456     }
14457     if (state->cursor > n) state->cursor = n;
14458 }
14459 
14460 NK_API void
14461 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
14462 {
14463     /* delete characters while updating undo */
14464     nk_textedit_makeundo_delete(state, where, len);
14465     nk_str_delete_runes(&state->string, where, len);
14466     state->has_preferred_x = 0;
14467 }
14468 
14469 NK_API void
14470 nk_textedit_delete_selection(struct nk_text_edit *state)
14471 {
14472     /* delete the section */
14473     nk_textedit_clamp(state);
14474     if (NK_TEXT_HAS_SELECTION(state)) {
14475         if (state->select_start < state->select_end) {
14476             nk_textedit_delete(state, state->select_start,
14477                 state->select_end - state->select_start);
14478             state->select_end = state->cursor = state->select_start;
14479         } else {
14480             nk_textedit_delete(state, state->select_end,
14481                 state->select_start - state->select_end);
14482             state->select_start = state->cursor = state->select_end;
14483         }
14484         state->has_preferred_x = 0;
14485     }
14486 }
14487 
14488 NK_INTERN void
14489 nk_textedit_sortselection(struct nk_text_edit *state)
14490 {
14491     /* canonicalize the selection so start <= end */
14492     if (state->select_end < state->select_start) {
14493         int temp = state->select_end;
14494         state->select_end = state->select_start;
14495         state->select_start = temp;
14496     }
14497 }
14498 
14499 NK_INTERN void
14500 nk_textedit_move_to_first(struct nk_text_edit *state)
14501 {
14502     /* move cursor to first character of selection */
14503     if (NK_TEXT_HAS_SELECTION(state)) {
14504         nk_textedit_sortselection(state);
14505         state->cursor = state->select_start;
14506         state->select_end = state->select_start;
14507         state->has_preferred_x = 0;
14508     }
14509 }
14510 
14511 NK_INTERN void
14512 nk_textedit_move_to_last(struct nk_text_edit *state)
14513 {
14514     /* move cursor to last character of selection */
14515     if (NK_TEXT_HAS_SELECTION(state)) {
14516         nk_textedit_sortselection(state);
14517         nk_textedit_clamp(state);
14518         state->cursor = state->select_end;
14519         state->select_start = state->select_end;
14520         state->has_preferred_x = 0;
14521     }
14522 }
14523 
14524 NK_INTERN int
14525 nk_is_word_boundary( struct nk_text_edit *state, int idx)
14526 {
14527     int len;
14528     nk_rune c;
14529     if (idx <= 0) return 1;
14530     if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
14531     return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
14532             c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
14533             c == '|');
14534 }
14535 
14536 NK_INTERN int
14537 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
14538 {
14539    int c = state->cursor - 1;
14540    while( c >= 0 && !nk_is_word_boundary(state, c))
14541       --c;
14542 
14543    if( c < 0 )
14544       c = 0;
14545 
14546    return c;
14547 }
14548 
14549 NK_INTERN int
14550 nk_textedit_move_to_word_next(struct nk_text_edit *state)
14551 {
14552    const int len = state->string.len;
14553    int c = state->cursor+1;
14554    while( c < len && !nk_is_word_boundary(state, c))
14555       ++c;
14556 
14557    if( c > len )
14558       c = len;
14559 
14560    return c;
14561 }
14562 
14563 NK_INTERN void
14564 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
14565 {
14566     /* update selection and cursor to match each other */
14567     if (!NK_TEXT_HAS_SELECTION(state))
14568         state->select_start = state->select_end = state->cursor;
14569     else state->cursor = state->select_end;
14570 }
14571 
14572 NK_API int
14573 nk_textedit_cut(struct nk_text_edit *state)
14574 {
14575     /* API cut: delete selection */
14576     if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
14577         return 0;
14578     if (NK_TEXT_HAS_SELECTION(state)) {
14579         nk_textedit_delete_selection(state); /* implicitly clamps */
14580         state->has_preferred_x = 0;
14581         return 1;
14582     }
14583    return 0;
14584 }
14585 
14586 NK_API int
14587 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
14588 {
14589     /* API paste: replace existing selection with passed-in text */
14590     int glyphs;
14591     const char *text = (const char *) ctext;
14592     if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
14593 
14594     /* if there's a selection, the paste should delete it */
14595     nk_textedit_clamp(state);
14596     nk_textedit_delete_selection(state);
14597 
14598     /* try to insert the characters */
14599     glyphs = nk_utf_len(ctext, len);
14600     if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
14601         nk_textedit_makeundo_insert(state, state->cursor, glyphs);
14602         state->cursor += len;
14603         state->has_preferred_x = 0;
14604         return 1;
14605     }
14606     /* remove the undo since we didn't actually insert the characters */
14607     if (state->undo.undo_point)
14608         --state->undo.undo_point;
14609     return 0;
14610 }
14611 
14612 NK_API void
14613 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
14614 {
14615     nk_rune unicode;
14616     int glyph_len;
14617     int text_len = 0;
14618 
14619     NK_ASSERT(state);
14620     NK_ASSERT(text);
14621     if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
14622 
14623     glyph_len = nk_utf_decode(text, &unicode, total_len);
14624     while ((text_len < total_len) && glyph_len)
14625     {
14626         /* don't insert a backward delete, just process the event */
14627         if (unicode == 127) goto next;
14628         /* can't add newline in single-line mode */
14629         if (unicode == '\n' && state->single_line) goto next;
14630         /* filter incoming text */
14631         if (state->filter && !state->filter(state, unicode)) goto next;
14632 
14633         if (!NK_TEXT_HAS_SELECTION(state) &&
14634             state->cursor < state->string.len)
14635         {
14636             if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
14637                 nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
14638                 nk_str_delete_runes(&state->string, state->cursor, 1);
14639             }
14640             if (nk_str_insert_text_utf8(&state->string, state->cursor,
14641                                         text+text_len, 1))
14642             {
14643                 ++state->cursor;
14644                 state->has_preferred_x = 0;
14645             }
14646         } else {
14647             nk_textedit_delete_selection(state); /* implicitly clamps */
14648             if (nk_str_insert_text_utf8(&state->string, state->cursor,
14649                                         text+text_len, 1))
14650             {
14651                 nk_textedit_makeundo_insert(state, state->cursor, 1);
14652                 ++state->cursor;
14653                 state->has_preferred_x = 0;
14654             }
14655         }
14656         next:
14657         text_len += glyph_len;
14658         glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
14659     }
14660 
14661 		state->lexer.needs_refresh = 1;
14662 }
14663 
14664 NK_INTERN void
14665 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
14666     const struct nk_user_font *font, float row_height)
14667 {
14668 retry:
14669     switch (key)
14670     {
14671     case NK_KEY_NONE:
14672     case NK_KEY_CTRL:
14673     case NK_KEY_ENTER:
14674     case NK_KEY_SHIFT:
14675     case NK_KEY_TAB:
14676     case NK_KEY_COPY:
14677     case NK_KEY_CUT:
14678     case NK_KEY_PASTE:
14679     case NK_KEY_MAX:
14680     default: break;
14681     case NK_KEY_TEXT_UNDO:
14682          nk_textedit_undo(state);
14683          state->has_preferred_x = 0;
14684          break;
14685 
14686     case NK_KEY_TEXT_REDO:
14687         nk_textedit_redo(state);
14688         state->has_preferred_x = 0;
14689         break;
14690 
14691     case NK_KEY_TEXT_SELECT_ALL:
14692         nk_textedit_select_all(state);
14693         state->has_preferred_x = 0;
14694         break;
14695 
14696     case NK_KEY_TEXT_INSERT_MODE:
14697         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
14698             state->mode = NK_TEXT_EDIT_MODE_INSERT;
14699         break;
14700     case NK_KEY_TEXT_REPLACE_MODE:
14701         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
14702             state->mode = NK_TEXT_EDIT_MODE_REPLACE;
14703         break;
14704     case NK_KEY_TEXT_RESET_MODE:
14705         if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
14706             state->mode == NK_TEXT_EDIT_MODE_REPLACE)
14707             state->mode = NK_TEXT_EDIT_MODE_VIEW;
14708         break;
14709 
14710     case NK_KEY_LEFT:
14711         if (shift_mod) {
14712             nk_textedit_clamp(state);
14713             nk_textedit_prep_selection_at_cursor(state);
14714             /* move selection left */
14715             if (state->select_end > 0)
14716                 --state->select_end;
14717             state->cursor = state->select_end;
14718             state->has_preferred_x = 0;
14719         } else {
14720             /* if currently there's a selection,
14721              * move cursor to start of selection */
14722             if (NK_TEXT_HAS_SELECTION(state))
14723                 nk_textedit_move_to_first(state);
14724             else if (state->cursor > 0)
14725                --state->cursor;
14726             state->has_preferred_x = 0;
14727         } break;
14728 
14729     case NK_KEY_RIGHT:
14730         if (shift_mod) {
14731             nk_textedit_prep_selection_at_cursor(state);
14732             /* move selection right */
14733             ++state->select_end;
14734             nk_textedit_clamp(state);
14735             state->cursor = state->select_end;
14736             state->has_preferred_x = 0;
14737         } else {
14738             /* if currently there's a selection,
14739              * move cursor to end of selection */
14740             if (NK_TEXT_HAS_SELECTION(state))
14741                 nk_textedit_move_to_last(state);
14742             else ++state->cursor;
14743             nk_textedit_clamp(state);
14744             state->has_preferred_x = 0;
14745         } break;
14746 
14747     case NK_KEY_TEXT_WORD_LEFT:
14748         if (shift_mod) {
14749             if( !NK_TEXT_HAS_SELECTION( state ) )
14750             nk_textedit_prep_selection_at_cursor(state);
14751             state->cursor = nk_textedit_move_to_word_previous(state);
14752             state->select_end = state->cursor;
14753             nk_textedit_clamp(state );
14754         } else {
14755             if (NK_TEXT_HAS_SELECTION(state))
14756                 nk_textedit_move_to_first(state);
14757             else {
14758                 state->cursor = nk_textedit_move_to_word_previous(state);
14759                 nk_textedit_clamp(state );
14760             }
14761         } break;
14762 
14763     case NK_KEY_TEXT_WORD_RIGHT:
14764         if (shift_mod) {
14765             if( !NK_TEXT_HAS_SELECTION( state ) )
14766                 nk_textedit_prep_selection_at_cursor(state);
14767             state->cursor = nk_textedit_move_to_word_next(state);
14768             state->select_end = state->cursor;
14769             nk_textedit_clamp(state);
14770         } else {
14771             if (NK_TEXT_HAS_SELECTION(state))
14772                 nk_textedit_move_to_last(state);
14773             else {
14774                 state->cursor = nk_textedit_move_to_word_next(state);
14775                 nk_textedit_clamp(state );
14776             }
14777         } break;
14778 
14779     case NK_KEY_DOWN: {
14780         struct nk_text_find find;
14781         struct nk_text_edit_row row;
14782         int i, sel = shift_mod;
14783 
14784         if (state->single_line) {
14785             /* on windows, up&down in single-line behave like left&right */
14786             key = NK_KEY_RIGHT;
14787             goto retry;
14788         }
14789 
14790         if (sel)
14791             nk_textedit_prep_selection_at_cursor(state);
14792         else if (NK_TEXT_HAS_SELECTION(state))
14793             nk_textedit_move_to_last(state);
14794 
14795         /* compute current position of cursor point */
14796         nk_textedit_clamp(state);
14797         nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
14798             font, row_height);
14799 
14800         /* now find character position down a row */
14801         if (find.length)
14802         {
14803             float x;
14804             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
14805             int start = find.first_char + find.length;
14806 
14807             state->cursor = start;
14808             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
14809             x = row.x0;
14810 
14811             for (i=0; i < row.num_chars && x < row.x1; ++i) {
14812                 float dx = nk_textedit_get_width(state, start, i, font);
14813                 x += dx;
14814                 if (x > goal_x)
14815                     break;
14816                 ++state->cursor;
14817             }
14818             nk_textedit_clamp(state);
14819 
14820             state->has_preferred_x = 1;
14821             state->preferred_x = goal_x;
14822             if (sel)
14823                 state->select_end = state->cursor;
14824         }
14825     } break;
14826 
14827     case NK_KEY_UP: {
14828         struct nk_text_find find;
14829         struct nk_text_edit_row row;
14830         int i, sel = shift_mod;
14831 
14832         if (state->single_line) {
14833             /* on windows, up&down become left&right */
14834             key = NK_KEY_LEFT;
14835             goto retry;
14836         }
14837 
14838         if (sel)
14839             nk_textedit_prep_selection_at_cursor(state);
14840         else if (NK_TEXT_HAS_SELECTION(state))
14841             nk_textedit_move_to_first(state);
14842 
14843          /* compute current position of cursor point */
14844          nk_textedit_clamp(state);
14845          nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
14846                 font, row_height);
14847 
14848          /* can only go up if there's a previous row */
14849          if (find.prev_first != find.first_char) {
14850             /* now find character position up a row */
14851             float x;
14852             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
14853 
14854             state->cursor = find.prev_first;
14855             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
14856             x = row.x0;
14857 
14858             for (i=0; i < row.num_chars && x < row.x1; ++i) {
14859                 float dx = nk_textedit_get_width(state, find.prev_first, i, font);
14860                 x += dx;
14861                 if (x > goal_x)
14862                     break;
14863                 ++state->cursor;
14864             }
14865             nk_textedit_clamp(state);
14866 
14867             state->has_preferred_x = 1;
14868             state->preferred_x = goal_x;
14869             if (sel) state->select_end = state->cursor;
14870          }
14871       } break;
14872 
14873     case NK_KEY_DEL:
14874         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
14875             break;
14876         if (NK_TEXT_HAS_SELECTION(state))
14877             nk_textedit_delete_selection(state);
14878         else {
14879             int n = state->string.len;
14880             if (state->cursor < n)
14881                 nk_textedit_delete(state, state->cursor, 1);
14882          }
14883          state->has_preferred_x = 0;
14884          break;
14885 
14886     case NK_KEY_BACKSPACE:
14887         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
14888             break;
14889         if (NK_TEXT_HAS_SELECTION(state))
14890             nk_textedit_delete_selection(state);
14891         else {
14892             nk_textedit_clamp(state);
14893             if (state->cursor > 0) {
14894                 nk_textedit_delete(state, state->cursor-1, 1);
14895                 --state->cursor;
14896             }
14897          }
14898          state->has_preferred_x = 0;
14899          break;
14900 
14901     case NK_KEY_TEXT_START:
14902          if (shift_mod) {
14903             nk_textedit_prep_selection_at_cursor(state);
14904             state->cursor = state->select_end = 0;
14905             state->has_preferred_x = 0;
14906          } else {
14907             state->cursor = state->select_start = state->select_end = 0;
14908             state->has_preferred_x = 0;
14909          }
14910          break;
14911 
14912     case NK_KEY_TEXT_END:
14913          if (shift_mod) {
14914             nk_textedit_prep_selection_at_cursor(state);
14915             state->cursor = state->select_end = state->string.len;
14916             state->has_preferred_x = 0;
14917          } else {
14918             state->cursor = state->string.len;
14919             state->select_start = state->select_end = 0;
14920             state->has_preferred_x = 0;
14921          }
14922          break;
14923 
14924     case NK_KEY_TEXT_LINE_START: {
14925         if (shift_mod) {
14926             struct nk_text_find find;
14927            nk_textedit_clamp(state);
14928             nk_textedit_prep_selection_at_cursor(state);
14929             if (state->string.len && state->cursor == state->string.len)
14930                 --state->cursor;
14931             nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
14932                 font, row_height);
14933             state->cursor = state->select_end = find.first_char;
14934             state->has_preferred_x = 0;
14935         } else {
14936             struct nk_text_find find;
14937             if (state->string.len && state->cursor == state->string.len)
14938                 --state->cursor;
14939             nk_textedit_clamp(state);
14940             nk_textedit_move_to_first(state);
14941             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
14942                 font, row_height);
14943             state->cursor = find.first_char;
14944             state->has_preferred_x = 0;
14945         }
14946       } break;
14947 
14948     case NK_KEY_TEXT_LINE_END: {
14949         if (shift_mod) {
14950             struct nk_text_find find;
14951             nk_textedit_clamp(state);
14952             nk_textedit_prep_selection_at_cursor(state);
14953             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
14954                 font, row_height);
14955             state->has_preferred_x = 0;
14956             state->cursor = find.first_char + find.length;
14957             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
14958                 --state->cursor;
14959             state->select_end = state->cursor;
14960         } else {
14961             struct nk_text_find find;
14962             nk_textedit_clamp(state);
14963             nk_textedit_move_to_first(state);
14964             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
14965                 font, row_height);
14966 
14967             state->has_preferred_x = 0;
14968             state->cursor = find.first_char + find.length;
14969             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
14970                 --state->cursor;
14971         }} break;
14972     }
14973 
14974 		state->lexer.needs_refresh = 1;
14975 }
14976 
14977 NK_INTERN void
14978 nk_textedit_flush_redo(struct nk_text_undo_state *state)
14979 {
14980     state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
14981     state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
14982 }
14983 
14984 NK_INTERN void
14985 nk_textedit_discard_undo(struct nk_text_undo_state *state)
14986 {
14987     /* discard the oldest entry in the undo list */
14988     if (state->undo_point > 0) {
14989         /* if the 0th undo state has characters, clean those up */
14990         if (state->undo_rec[0].char_storage >= 0) {
14991             int n = state->undo_rec[0].insert_length, i;
14992             /* delete n characters from all other records */
14993             state->undo_char_point = (short)(state->undo_char_point - n);
14994             NK_MEMCPY(state->undo_char, state->undo_char + n,
14995                 (nk_size)state->undo_char_point*sizeof(nk_rune));
14996             for (i=0; i < state->undo_point; ++i) {
14997                 if (state->undo_rec[i].char_storage >= 0)
14998                 state->undo_rec[i].char_storage = (short)
14999                     (state->undo_rec[i].char_storage - n);
15000             }
15001         }
15002         --state->undo_point;
15003         NK_MEMCPY(state->undo_rec, state->undo_rec+1,
15004             (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
15005     }
15006 }
15007 
15008 NK_INTERN void
15009 nk_textedit_discard_redo(struct nk_text_undo_state *state)
15010 {
15011 /*  discard the oldest entry in the redo list--it's bad if this
15012     ever happens, but because undo & redo have to store the actual
15013     characters in different cases, the redo character buffer can
15014     fill up even though the undo buffer didn't */
15015     nk_size num;
15016     int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
15017     if (state->redo_point <= k) {
15018         /* if the k'th undo state has characters, clean those up */
15019         if (state->undo_rec[k].char_storage >= 0) {
15020             int n = state->undo_rec[k].insert_length, i;
15021             /* delete n characters from all other records */
15022             state->redo_char_point = (short)(state->redo_char_point + n);
15023             num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point);
15024             NK_MEMCPY(state->undo_char + state->redo_char_point,
15025                 state->undo_char + state->redo_char_point-n, num * sizeof(char));
15026             for (i = state->redo_point; i < k; ++i) {
15027                 if (state->undo_rec[i].char_storage >= 0) {
15028                     state->undo_rec[i].char_storage = (short)
15029                         (state->undo_rec[i].char_storage + n);
15030                 }
15031             }
15032         }
15033         ++state->redo_point;
15034         num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
15035         if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
15036             state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
15037     }
15038 }
15039 
15040 NK_INTERN struct nk_text_undo_record*
15041 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
15042 {
15043     /* any time we create a new undo record, we discard redo*/
15044     nk_textedit_flush_redo(state);
15045 
15046     /* if we have no free records, we have to make room,
15047      * by sliding the existing records down */
15048     if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
15049         nk_textedit_discard_undo(state);
15050 
15051     /* if the characters to store won't possibly fit in the buffer,
15052      * we can't undo */
15053     if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
15054         state->undo_point = 0;
15055         state->undo_char_point = 0;
15056         return 0;
15057     }
15058 
15059     /* if we don't have enough free characters in the buffer,
15060      * we have to make room */
15061     while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
15062         nk_textedit_discard_undo(state);
15063     return &state->undo_rec[state->undo_point++];
15064 }
15065 
15066 NK_INTERN nk_rune*
15067 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
15068     int insert_len, int delete_len)
15069 {
15070     struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
15071     if (r == 0)
15072         return 0;
15073 
15074     r->where = pos;
15075     r->insert_length = (short) insert_len;
15076     r->delete_length = (short) delete_len;
15077 
15078     if (insert_len == 0) {
15079         r->char_storage = -1;
15080         return 0;
15081     } else {
15082         r->char_storage = state->undo_char_point;
15083         state->undo_char_point = (short)(state->undo_char_point +  insert_len);
15084         return &state->undo_char[r->char_storage];
15085     }
15086 }
15087 
15088 NK_API void
15089 nk_textedit_undo(struct nk_text_edit *state)
15090 {
15091     struct nk_text_undo_state *s = &state->undo;
15092     struct nk_text_undo_record u, *r;
15093     if (s->undo_point == 0)
15094         return;
15095 
15096     /* we need to do two things: apply the undo record, and create a redo record */
15097     u = s->undo_rec[s->undo_point-1];
15098     r = &s->undo_rec[s->redo_point-1];
15099     r->char_storage = -1;
15100 
15101     r->insert_length = u.delete_length;
15102     r->delete_length = u.insert_length;
15103     r->where = u.where;
15104 
15105     if (u.delete_length)
15106     {
15107        /*   if the undo record says to delete characters, then the redo record will
15108             need to re-insert the characters that get deleted, so we need to store
15109             them.
15110             there are three cases:
15111                 - there's enough room to store the characters
15112                 - characters stored for *redoing* don't leave room for redo
15113                 - characters stored for *undoing* don't leave room for redo
15114             if the last is true, we have to bail */
15115         if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
15116             /* the undo records take up too much character space; there's no space
15117             * to store the redo characters */
15118             r->insert_length = 0;
15119         } else {
15120             int i;
15121             /* there's definitely room to store the characters eventually */
15122             while (s->undo_char_point + u.delete_length > s->redo_char_point) {
15123                 /* there's currently not enough room, so discard a redo record */
15124                 nk_textedit_discard_redo(s);
15125                 /* should never happen: */
15126                 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
15127                     return;
15128             }
15129 
15130             r = &s->undo_rec[s->redo_point-1];
15131             r->char_storage = (short)(s->redo_char_point - u.delete_length);
15132             s->redo_char_point = (short)(s->redo_char_point -  u.delete_length);
15133 
15134             /* now save the characters */
15135             for (i=0; i < u.delete_length; ++i)
15136                 s->undo_char[r->char_storage + i] =
15137                     nk_str_rune_at(&state->string, u.where + i);
15138         }
15139         /* now we can carry out the deletion */
15140         nk_str_delete_runes(&state->string, u.where, u.delete_length);
15141     }
15142 
15143     /* check type of recorded action: */
15144     if (u.insert_length) {
15145         /* easy case: was a deletion, so we need to insert n characters */
15146         nk_str_insert_text_runes(&state->string, u.where,
15147             &s->undo_char[u.char_storage], u.insert_length);
15148         s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
15149     }
15150     state->cursor = (short)(u.where + u.insert_length);
15151 
15152     s->undo_point--;
15153     s->redo_point--;
15154 }
15155 
15156 NK_API void
15157 nk_textedit_redo(struct nk_text_edit *state)
15158 {
15159     struct nk_text_undo_state *s = &state->undo;
15160     struct nk_text_undo_record *u, r;
15161     if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
15162         return;
15163 
15164     /* we need to do two things: apply the redo record, and create an undo record */
15165     u = &s->undo_rec[s->undo_point];
15166     r = s->undo_rec[s->redo_point];
15167 
15168     /* we KNOW there must be room for the undo record, because the redo record
15169     was derived from an undo record */
15170     u->delete_length = r.insert_length;
15171     u->insert_length = r.delete_length;
15172     u->where = r.where;
15173     u->char_storage = -1;
15174 
15175     if (r.delete_length) {
15176         /* the redo record requires us to delete characters, so the undo record
15177         needs to store the characters */
15178         if (s->undo_char_point + u->insert_length > s->redo_char_point) {
15179             u->insert_length = 0;
15180             u->delete_length = 0;
15181         } else {
15182             int i;
15183             u->char_storage = s->undo_char_point;
15184             s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
15185 
15186             /* now save the characters */
15187             for (i=0; i < u->insert_length; ++i) {
15188                 s->undo_char[u->char_storage + i] =
15189                     nk_str_rune_at(&state->string, u->where + i);
15190             }
15191         }
15192         nk_str_delete_runes(&state->string, r.where, r.delete_length);
15193     }
15194 
15195     if (r.insert_length) {
15196         /* easy case: need to insert n characters */
15197         nk_str_insert_text_runes(&state->string, r.where,
15198             &s->undo_char[r.char_storage], r.insert_length);
15199     }
15200     state->cursor = r.where + r.insert_length;
15201 
15202     s->undo_point++;
15203     s->redo_point++;
15204 }
15205 
15206 NK_INTERN void
15207 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
15208 {
15209     nk_textedit_createundo(&state->undo, where, 0, length);
15210 }
15211 
15212 NK_INTERN void
15213 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
15214 {
15215     int i;
15216     nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
15217     if (p) {
15218         for (i=0; i < length; ++i)
15219             p[i] = nk_str_rune_at(&state->string, where+i);
15220     }
15221 }
15222 
15223 NK_INTERN void
15224 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
15225     int old_length, int new_length)
15226 {
15227     int i;
15228     nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
15229     if (p) {
15230         for (i=0; i < old_length; ++i)
15231             p[i] = nk_str_rune_at(&state->string, where+i);
15232     }
15233 }
15234 
15235 NK_INTERN void
15236 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
15237     nk_plugin_filter filter)
15238 {
15239     /* reset the state to default */
15240    state->undo.undo_point = 0;
15241    state->undo.undo_char_point = 0;
15242    state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
15243    state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
15244    state->select_end = state->select_start = 0;
15245    state->cursor = 0;
15246    state->has_preferred_x = 0;
15247    state->preferred_x = 0;
15248    state->cursor_at_end_of_line = 0;
15249    state->initialized = 1;
15250    state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
15251    state->mode = NK_TEXT_EDIT_MODE_VIEW;
15252    state->filter = filter;
15253    state->scrollbar = nk_vec2(0,0);
15254 }
15255 
15256 NK_INTERN void
15257 nk_textedit_reset_state(struct nk_text_edit *state, enum nk_text_edit_type type,
15258     nk_plugin_filter filter)
15259 {
15260     /* reset the state to default */
15261    state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
15262    state->mode = NK_TEXT_EDIT_MODE_VIEW;
15263    state->filter = filter;
15264 }
15265 
15266 NK_API void
15267 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
15268 {
15269     NK_ASSERT(state);
15270     NK_ASSERT(memory);
15271     if (!state || !memory || !size) return;
15272     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
15273     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
15274     nk_str_init_fixed(&state->string, memory, size);
15275 }
15276 
15277 NK_API void
15278 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
15279 {
15280     NK_ASSERT(state);
15281     NK_ASSERT(alloc);
15282     if (!state || !alloc) return;
15283     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
15284     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
15285     nk_str_init(&state->string, alloc, size);
15286 }
15287 
15288 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
15289 NK_API void
15290 nk_textedit_init_default(struct nk_text_edit *state)
15291 {
15292     NK_ASSERT(state);
15293     if (!state) return;
15294     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
15295     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
15296     nk_str_init_default(&state->string);
15297 }
15298 #endif
15299 
15300 NK_API void
15301 nk_textedit_select_all(struct nk_text_edit *state)
15302 {
15303     NK_ASSERT(state);
15304     state->select_start = 0;
15305     state->select_end = state->string.len;
15306 }
15307 
15308 NK_API void
15309 nk_textedit_free(struct nk_text_edit *state)
15310 {
15311     NK_ASSERT(state);
15312     if (!state) return;
15313     nk_str_free(&state->string);
15314 }
15315 
15316 /* ===============================================================
15317  *
15318  *                          TEXT WIDGET
15319  *
15320  * ===============================================================*/
15321 #define nk_widget_state_reset(s)\
15322     if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
15323         (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
15324     else (*(s)) = NK_WIDGET_STATE_INACTIVE;
15325 
15326 struct nk_text {
15327     struct nk_vec2 padding;
15328     struct nk_color background;
15329     struct nk_color text;
15330 };
15331 
15332 NK_INTERN void
15333 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
15334     const char *string, int len, const struct nk_text *t,
15335     nk_flags a, const struct nk_user_font *f)
15336 {
15337     struct nk_rect label;
15338     float text_width;
15339 
15340     NK_ASSERT(o);
15341     NK_ASSERT(t);
15342     if (!o || !t) return;
15343 
15344     b.h = NK_MAX(b.h, 2 * t->padding.y);
15345     label.x = 0; label.w = 0;
15346     label.y = b.y + t->padding.y;
15347     label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
15348 
15349     text_width = f->width(f->userdata, f->height, (const char*)string, len);
15350     text_width += (2.0f * t->padding.x);
15351 
15352     /* align in x-axis */
15353     if (a & NK_TEXT_ALIGN_LEFT) {
15354         label.x = b.x + t->padding.x;
15355         label.w = NK_MAX(0, b.w - 2 * t->padding.x);
15356     } else if (a & NK_TEXT_ALIGN_CENTERED) {
15357         label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
15358         label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
15359         label.x = NK_MAX(b.x + t->padding.x, label.x);
15360         label.w = NK_MIN(b.x + b.w, label.x + label.w);
15361         if (label.w >= label.x) label.w -= label.x;
15362     } else if (a & NK_TEXT_ALIGN_RIGHT) {
15363         label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
15364         label.w = (float)text_width + 2 * t->padding.x;
15365     } else return;
15366 
15367     /* align in y-axis */
15368     if (a & NK_TEXT_ALIGN_MIDDLE) {
15369         label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
15370         label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
15371     } else if (a & NK_TEXT_ALIGN_BOTTOM) {
15372         label.y = b.y + b.h - f->height;
15373         label.h = f->height;
15374     }
15375     nk_draw_text(o, label, (const char*)string,
15376         len, f, t->background, t->text);
15377 }
15378 
15379 NK_INTERN void
15380 nk_widget_text_lexed(struct nk_command_buffer *o, struct nk_rect b,
15381     const char *string, int len, const struct nk_text *t,
15382     nk_flags a, const struct nk_user_font *f, struct nk_token *tokens,
15383 		int offset)
15384 {
15385     struct nk_rect label;
15386     float text_width;
15387 		struct nk_token *token = tokens;
15388 
15389     NK_ASSERT(o);
15390     NK_ASSERT(t);
15391     if (!o || !t) return;
15392 
15393     b.h = NK_MAX(b.h, 2 * t->padding.y);
15394     label.x = 0; label.w = 0;
15395     label.y = b.y + t->padding.y;
15396     label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
15397 
15398     text_width = f->width(f->userdata, f->height, (const char*)string, len);
15399     text_width += (2.0f * t->padding.x);
15400 
15401     /* align in x-axis */
15402     if (a & NK_TEXT_ALIGN_LEFT) {
15403         label.x = b.x + t->padding.x;
15404         label.w = NK_MAX(0, b.w - 2 * t->padding.x);
15405     } else if (a & NK_TEXT_ALIGN_CENTERED) {
15406         label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
15407         label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
15408         label.x = NK_MAX(b.x + t->padding.x, label.x);
15409         label.w = NK_MIN(b.x + b.w, label.x + label.w);
15410         if (label.w >= label.x) label.w -= label.x;
15411     } else if (a & NK_TEXT_ALIGN_RIGHT) {
15412         label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
15413         label.w = (float)text_width + 2 * t->padding.x;
15414     } else return;
15415 
15416     /* align in y-axis */
15417     if (a & NK_TEXT_ALIGN_MIDDLE) {
15418         label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
15419         label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
15420     } else if (a & NK_TEXT_ALIGN_BOTTOM) {
15421         label.y = b.y + b.h - f->height;
15422         label.h = f->height;
15423     }
15424 
15425 		//FIXME do this chunk-wise instead of character-wise
15426 		const int glyph_max = nk_utf_len(string, len);
15427 		const float dd = text_width/glyph_max;
15428 		for(int i = 0, u = 0; i < len; u++)
15429 		{
15430 			nk_rune unicode;
15431 			const int glyph_len = nk_utf_decode(string + i, &unicode, len - i);
15432 
15433 			const struct nk_rect dst = {
15434 				.x = label.x + u*dd,
15435 				.y = label.y,
15436 				.w = text_width,
15437 				.h = label.h
15438 			};
15439 
15440 			struct nk_color bg = t->background;
15441 			struct nk_color fg = t->text;
15442 
15443 			while(offset + i >= token->offset)
15444 				token++;
15445 
15446 			fg = token->color;
15447 			nk_draw_text(o, dst, string + i, glyph_len, f, bg, fg);
15448 			i += glyph_len;
15449 		}
15450 }
15451 
15452 NK_INTERN void
15453 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
15454     const char *string, int len, const struct nk_text *t,
15455     const struct nk_user_font *f)
15456 {
15457     float width;
15458     int glyphs = 0;
15459     int fitting = 0;
15460     int done = 0;
15461     struct nk_rect line;
15462     struct nk_text text;
15463     NK_INTERN nk_rune seperator[] = {' '};
15464 
15465     NK_ASSERT(o);
15466     NK_ASSERT(t);
15467     if (!o || !t) return;
15468 
15469     text.padding = nk_vec2(0,0);
15470     text.background = t->background;
15471     text.text = t->text;
15472 
15473     b.w = NK_MAX(b.w, 2 * t->padding.x);
15474     b.h = NK_MAX(b.h, 2 * t->padding.y);
15475     b.h = b.h - 2 * t->padding.y;
15476 
15477     line.x = b.x + t->padding.x;
15478     line.y = b.y + t->padding.y;
15479     line.w = b.w - 2 * t->padding.x;
15480     line.h = 2 * t->padding.y + f->height;
15481 
15482     fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
15483     while (done < len) {
15484         if (!fitting || line.y + line.h >= (b.y + b.h)) break;
15485         nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
15486         done += fitting;
15487         line.y += f->height + 2 * t->padding.y;
15488         fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
15489     }
15490 }
15491 
15492 /* ===============================================================
15493  *
15494  *                          BUTTON
15495  *
15496  * ===============================================================*/
15497 NK_INTERN void
15498 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
15499     struct nk_rect content, struct nk_color background, struct nk_color foreground,
15500     float border_width, const struct nk_user_font *font)
15501 {
15502     switch (type) {
15503     case NK_SYMBOL_X:
15504     case NK_SYMBOL_UNDERSCORE:
15505     case NK_SYMBOL_PLUS:
15506     case NK_SYMBOL_MINUS: {
15507         /* single character text symbol */
15508         const char *X = (type == NK_SYMBOL_X) ? "x":
15509             (type == NK_SYMBOL_UNDERSCORE) ? "_":
15510             (type == NK_SYMBOL_PLUS) ? "+": "-";
15511         struct nk_text text;
15512         text.padding = nk_vec2(0,0);
15513         text.background = background;
15514         text.text = foreground;
15515         nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
15516     } break;
15517     case NK_SYMBOL_CIRCLE_SOLID:
15518     case NK_SYMBOL_CIRCLE_OUTLINE:
15519     case NK_SYMBOL_RECT_SOLID:
15520     case NK_SYMBOL_RECT_OUTLINE: {
15521         /* simple empty/filled shapes */
15522         if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
15523             nk_fill_rect(out, content,  0, foreground);
15524             if (type == NK_SYMBOL_RECT_OUTLINE)
15525                 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
15526         } else {
15527             nk_fill_circle(out, content, foreground);
15528             if (type == NK_SYMBOL_CIRCLE_OUTLINE)
15529                 nk_fill_circle(out, nk_shrink_rect(content, 1), background);
15530         }
15531     } break;
15532     case NK_SYMBOL_TRIANGLE_UP:
15533     case NK_SYMBOL_TRIANGLE_DOWN:
15534     case NK_SYMBOL_TRIANGLE_LEFT:
15535     case NK_SYMBOL_TRIANGLE_RIGHT: {
15536         enum nk_heading heading;
15537         struct nk_vec2 points[3];
15538         heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
15539             (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
15540             (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
15541         nk_triangle_from_direction(points, content, 0, 0, heading);
15542         nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
15543             points[2].x, points[2].y, foreground);
15544     } break;
15545     default:
15546     case NK_SYMBOL_NONE:
15547     case NK_SYMBOL_MAX: break;
15548     }
15549 }
15550 
15551 NK_INTERN int
15552 nk_button_behavior(nk_flags *state, struct nk_rect r,
15553     const struct nk_input *i, enum nk_button_behavior behavior)
15554 {
15555     int ret = 0;
15556     nk_widget_state_reset(state);
15557     if (!i) return 0;
15558     if (nk_input_is_mouse_hovering_rect(i, r)) {
15559         *state = NK_WIDGET_STATE_HOVERED;
15560         if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT))
15561             *state = NK_WIDGET_STATE_ACTIVE;
15562         if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) {
15563             ret = (behavior != NK_BUTTON_DEFAULT) ?
15564                 nk_input_is_mouse_down(i, NK_BUTTON_LEFT):
15565 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
15566                 nk_input_is_mouse_released(i, NK_BUTTON_LEFT);
15567 #else
15568                 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT);
15569 #endif
15570         }
15571     }
15572     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r))
15573         *state |= NK_WIDGET_STATE_ENTERED;
15574     else if (nk_input_is_mouse_prev_hovering_rect(i, r))
15575         *state |= NK_WIDGET_STATE_LEFT;
15576     return ret;
15577 }
15578 
15579 NK_INTERN const struct nk_style_item*
15580 nk_draw_button(struct nk_command_buffer *out,
15581     const struct nk_rect *bounds, nk_flags state,
15582     const struct nk_style_button *style)
15583 {
15584     const struct nk_style_item *background;
15585     if (state & NK_WIDGET_STATE_HOVER)
15586         background = &style->hover;
15587     else if (state & NK_WIDGET_STATE_ACTIVED)
15588         background = &style->active;
15589     else background = &style->normal;
15590 
15591     if (background->type == NK_STYLE_ITEM_IMAGE) {
15592         nk_draw_image(out, *bounds, &background->data.image, nk_white);
15593     } else {
15594         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
15595         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
15596     }
15597     return background;
15598 }
15599 
15600 NK_INTERN int
15601 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
15602     const struct nk_style_button *style, const struct nk_input *in,
15603     enum nk_button_behavior behavior, struct nk_rect *content)
15604 {
15605     struct nk_rect bounds;
15606     NK_ASSERT(style);
15607     NK_ASSERT(state);
15608     NK_ASSERT(out);
15609     if (!out || !style)
15610         return nk_false;
15611 
15612     /* calculate button content space */
15613     content->x = r.x + style->padding.x + style->border + style->rounding;
15614     content->y = r.y + style->padding.y + style->border + style->rounding;
15615     content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
15616     content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
15617 
15618     /* execute button behavior */
15619     bounds.x = r.x - style->touch_padding.x;
15620     bounds.y = r.y - style->touch_padding.y;
15621     bounds.w = r.w + 2 * style->touch_padding.x;
15622     bounds.h = r.h + 2 * style->touch_padding.y;
15623     return nk_button_behavior(state, bounds, in, behavior);
15624 }
15625 
15626 NK_INTERN void
15627 nk_draw_button_text(struct nk_command_buffer *out,
15628     const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
15629     const struct nk_style_button *style, const char *txt, int len,
15630     nk_flags text_alignment, const struct nk_user_font *font)
15631 {
15632     struct nk_text text;
15633     const struct nk_style_item *background;
15634     background = nk_draw_button(out, bounds, state, style);
15635 
15636     /* select correct colors/images */
15637     if (background->type == NK_STYLE_ITEM_COLOR)
15638         text.background = background->data.color;
15639     else text.background = style->text_background;
15640     if (state & NK_WIDGET_STATE_HOVER)
15641         text.text = style->text_hover;
15642     else if (state & NK_WIDGET_STATE_ACTIVED)
15643         text.text = style->text_active;
15644     else text.text = style->text_normal;
15645 
15646     text.padding = nk_vec2(0,0);
15647     nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
15648 }
15649 
15650 NK_INTERN int
15651 nk_do_button_text(nk_flags *state,
15652     struct nk_command_buffer *out, struct nk_rect bounds,
15653     const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
15654     const struct nk_style_button *style, const struct nk_input *in,
15655     const struct nk_user_font *font)
15656 {
15657     struct nk_rect content;
15658     int ret = nk_false;
15659 
15660     NK_ASSERT(state);
15661     NK_ASSERT(style);
15662     NK_ASSERT(out);
15663     NK_ASSERT(string);
15664     NK_ASSERT(font);
15665     if (!out || !style || !font || !string)
15666         return nk_false;
15667 
15668     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
15669     if (style->draw_begin) style->draw_begin(out, style->userdata);
15670     nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
15671     if (style->draw_end) style->draw_end(out, style->userdata);
15672     return ret;
15673 }
15674 
15675 NK_INTERN void
15676 nk_draw_button_symbol(struct nk_command_buffer *out,
15677     const struct nk_rect *bounds, const struct nk_rect *content,
15678     nk_flags state, const struct nk_style_button *style,
15679     enum nk_symbol_type type, const struct nk_user_font *font)
15680 {
15681     struct nk_color sym, bg;
15682     const struct nk_style_item *background;
15683 
15684     /* select correct colors/images */
15685     background = nk_draw_button(out, bounds, state, style);
15686     if (background->type == NK_STYLE_ITEM_COLOR)
15687         bg = background->data.color;
15688     else bg = style->text_background;
15689 
15690     if (state & NK_WIDGET_STATE_HOVER)
15691         sym = style->text_hover;
15692     else if (state & NK_WIDGET_STATE_ACTIVED)
15693         sym = style->text_active;
15694     else sym = style->text_normal;
15695     nk_draw_symbol(out, type, *content, bg, sym, 1, font);
15696 }
15697 
15698 NK_INTERN int
15699 nk_do_button_symbol(nk_flags *state,
15700     struct nk_command_buffer *out, struct nk_rect bounds,
15701     enum nk_symbol_type symbol, enum nk_button_behavior behavior,
15702     const struct nk_style_button *style, const struct nk_input *in,
15703     const struct nk_user_font *font)
15704 {
15705     int ret;
15706     struct nk_rect content;
15707 
15708     NK_ASSERT(state);
15709     NK_ASSERT(style);
15710     NK_ASSERT(font);
15711     NK_ASSERT(out);
15712     if (!out || !style || !font || !state)
15713         return nk_false;
15714 
15715     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
15716     if (style->draw_begin) style->draw_begin(out, style->userdata);
15717     nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
15718     if (style->draw_end) style->draw_end(out, style->userdata);
15719     return ret;
15720 }
15721 
15722 NK_INTERN void
15723 nk_draw_button_image(struct nk_command_buffer *out,
15724     const struct nk_rect *bounds, const struct nk_rect *content,
15725     nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
15726 {
15727     nk_draw_button(out, bounds, state, style);
15728     nk_draw_image(out, *content, img, nk_white);
15729 }
15730 
15731 NK_INTERN int
15732 nk_do_button_image(nk_flags *state,
15733     struct nk_command_buffer *out, struct nk_rect bounds,
15734     struct nk_image img, enum nk_button_behavior b,
15735     const struct nk_style_button *style, const struct nk_input *in)
15736 {
15737     int ret;
15738     struct nk_rect content;
15739 
15740     NK_ASSERT(state);
15741     NK_ASSERT(style);
15742     NK_ASSERT(out);
15743     if (!out || !style || !state)
15744         return nk_false;
15745 
15746     ret = nk_do_button(state, out, bounds, style, in, b, &content);
15747     content.x += style->image_padding.x;
15748     content.y += style->image_padding.y;
15749     content.w -= 2 * style->image_padding.x;
15750     content.h -= 2 * style->image_padding.y;
15751 
15752     if (style->draw_begin) style->draw_begin(out, style->userdata);
15753     nk_draw_button_image(out, &bounds, &content, *state, style, &img);
15754     if (style->draw_end) style->draw_end(out, style->userdata);
15755     return ret;
15756 }
15757 
15758 NK_INTERN void
15759 nk_draw_button_text_symbol(struct nk_command_buffer *out,
15760     const struct nk_rect *bounds, const struct nk_rect *label,
15761     const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
15762     const char *str, int len, enum nk_symbol_type type,
15763     const struct nk_user_font *font)
15764 {
15765     struct nk_color sym;
15766     struct nk_text text;
15767     const struct nk_style_item *background;
15768 
15769     /* select correct background colors/images */
15770     background = nk_draw_button(out, bounds, state, style);
15771     if (background->type == NK_STYLE_ITEM_COLOR)
15772         text.background = background->data.color;
15773     else text.background = style->text_background;
15774 
15775     /* select correct text colors */
15776     if (state & NK_WIDGET_STATE_HOVER) {
15777         sym = style->text_hover;
15778         text.text = style->text_hover;
15779     } else if (state & NK_WIDGET_STATE_ACTIVED) {
15780         sym = style->text_active;
15781         text.text = style->text_active;
15782     } else {
15783         sym = style->text_normal;
15784         text.text = style->text_normal;
15785     }
15786 
15787     text.padding = nk_vec2(0,0);
15788     nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
15789     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
15790 }
15791 
15792 NK_INTERN int
15793 nk_do_button_text_symbol(nk_flags *state,
15794     struct nk_command_buffer *out, struct nk_rect bounds,
15795     enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
15796     enum nk_button_behavior behavior, const struct nk_style_button *style,
15797     const struct nk_user_font *font, const struct nk_input *in)
15798 {
15799     int ret;
15800     struct nk_rect tri = {0,0,0,0};
15801     struct nk_rect content;
15802 
15803     NK_ASSERT(style);
15804     NK_ASSERT(out);
15805     NK_ASSERT(font);
15806     if (!out || !style || !font)
15807         return nk_false;
15808 
15809     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
15810     tri.y = content.y + (content.h/2) - font->height/2;
15811     tri.w = font->height; tri.h = font->height;
15812     if (align & NK_TEXT_ALIGN_LEFT) {
15813         tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
15814         tri.x = NK_MAX(tri.x, 0);
15815     } else tri.x = content.x + 2 * style->padding.x;
15816 
15817     /* draw button */
15818     if (style->draw_begin) style->draw_begin(out, style->userdata);
15819     nk_draw_button_text_symbol(out, &bounds, &content, &tri,
15820         *state, style, str, len, symbol, font);
15821     if (style->draw_end) style->draw_end(out, style->userdata);
15822     return ret;
15823 }
15824 
15825 NK_INTERN void
15826 nk_draw_button_text_image(struct nk_command_buffer *out,
15827     const struct nk_rect *bounds, const struct nk_rect *label,
15828     const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
15829     const char *str, int len, const struct nk_user_font *font,
15830     const struct nk_image *img)
15831 {
15832     struct nk_text text;
15833     const struct nk_style_item *background;
15834     background = nk_draw_button(out, bounds, state, style);
15835 
15836     /* select correct colors */
15837     if (background->type == NK_STYLE_ITEM_COLOR)
15838         text.background = background->data.color;
15839     else text.background = style->text_background;
15840     if (state & NK_WIDGET_STATE_HOVER)
15841         text.text = style->text_hover;
15842     else if (state & NK_WIDGET_STATE_ACTIVED)
15843         text.text = style->text_active;
15844     else text.text = style->text_normal;
15845 
15846     text.padding = nk_vec2(0,0);
15847     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
15848     nk_draw_image(out, *image, img, nk_white);
15849 }
15850 
15851 NK_INTERN int
15852 nk_do_button_text_image(nk_flags *state,
15853     struct nk_command_buffer *out, struct nk_rect bounds,
15854     struct nk_image img, const char* str, int len, nk_flags align,
15855     enum nk_button_behavior behavior, const struct nk_style_button *style,
15856     const struct nk_user_font *font, const struct nk_input *in)
15857 {
15858     int ret;
15859     struct nk_rect icon;
15860     struct nk_rect content;
15861 
15862     NK_ASSERT(style);
15863     NK_ASSERT(state);
15864     NK_ASSERT(font);
15865     NK_ASSERT(out);
15866     if (!out || !font || !style || !str)
15867         return nk_false;
15868 
15869     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
15870     icon.y = bounds.y + style->padding.y;
15871     icon.w = icon.h = bounds.h - 2 * style->padding.y;
15872     if (align & NK_TEXT_ALIGN_LEFT) {
15873         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
15874         icon.x = NK_MAX(icon.x, 0);
15875     } else icon.x = bounds.x + 2 * style->padding.x;
15876 
15877     icon.x += style->image_padding.x;
15878     icon.y += style->image_padding.y;
15879     icon.w -= 2 * style->image_padding.x;
15880     icon.h -= 2 * style->image_padding.y;
15881 
15882     if (style->draw_begin) style->draw_begin(out, style->userdata);
15883     nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
15884     if (style->draw_end) style->draw_end(out, style->userdata);
15885     return ret;
15886 }
15887 
15888 /* ===============================================================
15889  *
15890  *                          TOGGLE
15891  *
15892  * ===============================================================*/
15893 enum nk_toggle_type {
15894     NK_TOGGLE_CHECK,
15895     NK_TOGGLE_OPTION
15896 };
15897 
15898 NK_INTERN int
15899 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
15900     nk_flags *state, int active)
15901 {
15902     nk_widget_state_reset(state);
15903     if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
15904         *state = NK_WIDGET_STATE_ACTIVE;
15905         active = !active;
15906     }
15907     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
15908         *state |= NK_WIDGET_STATE_ENTERED;
15909     else if (nk_input_is_mouse_prev_hovering_rect(in, select))
15910         *state |= NK_WIDGET_STATE_LEFT;
15911     return active;
15912 }
15913 
15914 NK_INTERN void
15915 nk_draw_checkbox(struct nk_command_buffer *out,
15916     nk_flags state, const struct nk_style_toggle *style, int active,
15917     const struct nk_rect *label, const struct nk_rect *selector,
15918     const struct nk_rect *cursors, const char *string, int len,
15919     const struct nk_user_font *font)
15920 {
15921     const struct nk_style_item *background;
15922     const struct nk_style_item *cursor;
15923     struct nk_text text;
15924 
15925     /* select correct colors/images */
15926     if (state & NK_WIDGET_STATE_HOVER) {
15927         background = &style->hover;
15928         cursor = &style->cursor_hover;
15929         text.text = style->text_hover;
15930     } else if (state & NK_WIDGET_STATE_ACTIVED) {
15931         background = &style->hover;
15932         cursor = &style->cursor_hover;
15933         text.text = style->text_active;
15934     } else {
15935         background = &style->normal;
15936         cursor = &style->cursor_normal;
15937         text.text = style->text_normal;
15938     }
15939 
15940     /* draw background and cursor */
15941     if (background->type == NK_STYLE_ITEM_COLOR) {
15942         nk_fill_rect(out, *selector, 0, style->border_color);
15943         nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
15944     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
15945     if (active) {
15946         if (cursor->type == NK_STYLE_ITEM_IMAGE)
15947             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
15948         else nk_fill_rect(out, *cursors, 0, cursor->data.color);
15949     }
15950 
15951     text.padding.x = 0;
15952     text.padding.y = 0;
15953     text.background = style->text_background;
15954     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
15955 }
15956 
15957 NK_INTERN void
15958 nk_draw_option(struct nk_command_buffer *out,
15959     nk_flags state, const struct nk_style_toggle *style, int active,
15960     const struct nk_rect *label, const struct nk_rect *selector,
15961     const struct nk_rect *cursors, const char *string, int len,
15962     const struct nk_user_font *font)
15963 {
15964     const struct nk_style_item *background;
15965     const struct nk_style_item *cursor;
15966     struct nk_text text;
15967 
15968     /* select correct colors/images */
15969     if (state & NK_WIDGET_STATE_HOVER) {
15970         background = &style->hover;
15971         cursor = &style->cursor_hover;
15972         text.text = style->text_hover;
15973     } else if (state & NK_WIDGET_STATE_ACTIVED) {
15974         background = &style->hover;
15975         cursor = &style->cursor_hover;
15976         text.text = style->text_active;
15977     } else {
15978         background = &style->normal;
15979         cursor = &style->cursor_normal;
15980         text.text = style->text_normal;
15981     }
15982 
15983     /* draw background and cursor */
15984     if (background->type == NK_STYLE_ITEM_COLOR) {
15985         nk_fill_circle(out, *selector, style->border_color);
15986         nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
15987     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
15988     if (active) {
15989         if (cursor->type == NK_STYLE_ITEM_IMAGE)
15990             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
15991         else nk_fill_circle(out, *cursors, cursor->data.color);
15992     }
15993 
15994     text.padding.x = 0;
15995     text.padding.y = 0;
15996     text.background = style->text_background;
15997     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
15998 }
15999 
16000 NK_INTERN int
16001 nk_do_toggle(nk_flags *state,
16002     struct nk_command_buffer *out, struct nk_rect r,
16003     int *active, const char *str, int len, enum nk_toggle_type type,
16004     const struct nk_style_toggle *style, const struct nk_input *in,
16005     const struct nk_user_font *font)
16006 {
16007     int was_active;
16008     struct nk_rect bounds;
16009     struct nk_rect select;
16010     struct nk_rect cursor;
16011     struct nk_rect label;
16012 
16013     NK_ASSERT(style);
16014     NK_ASSERT(out);
16015     NK_ASSERT(font);
16016     if (!out || !style || !font || !active)
16017         return 0;
16018 
16019     r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
16020     r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
16021 
16022     /* add additional touch padding for touch screen devices */
16023     bounds.x = r.x - style->touch_padding.x;
16024     bounds.y = r.y - style->touch_padding.y;
16025     bounds.w = r.w + 2 * style->touch_padding.x;
16026     bounds.h = r.h + 2 * style->touch_padding.y;
16027 
16028     /* calculate the selector space */
16029     select.w = font->height;
16030     select.h = select.w;
16031     select.y = r.y + r.h/2.0f - select.h/2.0f;
16032     select.x = r.x;
16033 
16034     /* calculate the bounds of the cursor inside the selector */
16035     cursor.x = select.x + style->padding.x + style->border;
16036     cursor.y = select.y + style->padding.y + style->border;
16037     cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
16038     cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
16039 
16040     /* label behind the selector */
16041     label.x = select.x + select.w + style->spacing;
16042     label.y = select.y;
16043     label.w = NK_MAX(r.x + r.w, label.x) - label.x;
16044     label.h = select.w;
16045 
16046     /* update selector */
16047     was_active = *active;
16048     *active = nk_toggle_behavior(in, bounds, state, *active);
16049 
16050     /* draw selector */
16051     if (style->draw_begin)
16052         style->draw_begin(out, style->userdata);
16053     if (type == NK_TOGGLE_CHECK) {
16054         nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
16055     } else {
16056         nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
16057     }
16058     if (style->draw_end)
16059         style->draw_end(out, style->userdata);
16060     return (was_active != *active);
16061 }
16062 
16063 /* ===============================================================
16064  *
16065  *                          SELECTABLE
16066  *
16067  * ===============================================================*/
16068 NK_INTERN void
16069 nk_draw_selectable(struct nk_command_buffer *out,
16070     nk_flags state, const struct nk_style_selectable *style, int active,
16071     const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img,
16072     const char *string, int len, nk_flags align, const struct nk_user_font *font)
16073 {
16074     const struct nk_style_item *background;
16075     struct nk_text text;
16076     text.padding = style->padding;
16077 
16078     /* select correct colors/images */
16079     if (!active) {
16080         if (state & NK_WIDGET_STATE_ACTIVED) {
16081             background = &style->pressed;
16082             text.text = style->text_pressed;
16083         } else if (state & NK_WIDGET_STATE_HOVER) {
16084             background = &style->hover;
16085             text.text = style->text_hover;
16086         } else {
16087             background = &style->normal;
16088             text.text = style->text_normal;
16089         }
16090     } else {
16091         if (state & NK_WIDGET_STATE_ACTIVED) {
16092             background = &style->pressed_active;
16093             text.text = style->text_pressed_active;
16094         } else if (state & NK_WIDGET_STATE_HOVER) {
16095             background = &style->hover_active;
16096             text.text = style->text_hover_active;
16097         } else {
16098             background = &style->normal_active;
16099             text.text = style->text_normal_active;
16100         }
16101     }
16102 
16103 
16104     /* draw selectable background and text */
16105     if (background->type == NK_STYLE_ITEM_IMAGE) {
16106         nk_draw_image(out, *bounds, &background->data.image, nk_white);
16107         text.background = nk_rgba(0,0,0,0);
16108     } else {
16109         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
16110         text.background = background->data.color;
16111     }
16112     if (img && icon) nk_draw_image(out, *icon, img, nk_white);
16113     nk_widget_text(out, *bounds, string, len, &text, align, font);
16114 }
16115 
16116 NK_INTERN int
16117 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
16118     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
16119     const struct nk_style_selectable *style, const struct nk_input *in,
16120     const struct nk_user_font *font)
16121 {
16122     int old_value;
16123     struct nk_rect touch;
16124 
16125     NK_ASSERT(state);
16126     NK_ASSERT(out);
16127     NK_ASSERT(str);
16128     NK_ASSERT(len);
16129     NK_ASSERT(value);
16130     NK_ASSERT(style);
16131     NK_ASSERT(font);
16132 
16133     if (!state || !out || !str || !len || !value || !style || !font) return 0;
16134     old_value = *value;
16135 
16136     /* remove padding */
16137     touch.x = bounds.x - style->touch_padding.x;
16138     touch.y = bounds.y - style->touch_padding.y;
16139     touch.w = bounds.w + style->touch_padding.x * 2;
16140     touch.h = bounds.h + style->touch_padding.y * 2;
16141 
16142     /* update button */
16143     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
16144         *value = !(*value);
16145 
16146     /* draw selectable */
16147     if (style->draw_begin) style->draw_begin(out, style->userdata);
16148     nk_draw_selectable(out, *state, style, *value, &bounds, 0,0, str, len, align, font);
16149     if (style->draw_end) style->draw_end(out, style->userdata);
16150     return old_value != *value;
16151 }
16152 
16153 NK_INTERN int
16154 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
16155     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
16156     const struct nk_image *img, const struct nk_style_selectable *style,
16157     const struct nk_input *in, const struct nk_user_font *font)
16158 {
16159     int old_value;
16160     struct nk_rect touch;
16161     struct nk_rect icon;
16162 
16163     NK_ASSERT(state);
16164     NK_ASSERT(out);
16165     NK_ASSERT(str);
16166     NK_ASSERT(len);
16167     NK_ASSERT(value);
16168     NK_ASSERT(style);
16169     NK_ASSERT(font);
16170 
16171     if (!state || !out || !str || !len || !value || !style || !font) return 0;
16172     old_value = *value;
16173 
16174     /* toggle behavior */
16175     touch.x = bounds.x - style->touch_padding.x;
16176     touch.y = bounds.y - style->touch_padding.y;
16177     touch.w = bounds.w + style->touch_padding.x * 2;
16178     touch.h = bounds.h + style->touch_padding.y * 2;
16179     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
16180         *value = !(*value);
16181 
16182     icon.y = bounds.y + style->padding.y;
16183     icon.w = icon.h = bounds.h - 2 * style->padding.y;
16184     if (align & NK_TEXT_ALIGN_LEFT) {
16185         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
16186         icon.x = NK_MAX(icon.x, 0);
16187     } else icon.x = bounds.x + 2 * style->padding.x;
16188 
16189     icon.x += style->image_padding.x;
16190     icon.y += style->image_padding.y;
16191     icon.w -= 2 * style->image_padding.x;
16192     icon.h -= 2 * style->image_padding.y;
16193 
16194     /* draw selectable */
16195     if (style->draw_begin) style->draw_begin(out, style->userdata);
16196     nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, str, len, align, font);
16197     if (style->draw_end) style->draw_end(out, style->userdata);
16198     return old_value != *value;
16199 }
16200 
16201 
16202 /* ===============================================================
16203  *
16204  *                          SLIDER
16205  *
16206  * ===============================================================*/
16207 NK_INTERN float
16208 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
16209     struct nk_rect *visual_cursor, struct nk_input *in,
16210     struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
16211     float slider_step, float slider_steps)
16212 {
16213     int left_mouse_down;
16214     int left_mouse_click_in_cursor;
16215 
16216     /* check if visual cursor is being dragged */
16217     nk_widget_state_reset(state);
16218     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
16219     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
16220             NK_BUTTON_LEFT, *visual_cursor, nk_true);
16221 
16222     if (left_mouse_down && left_mouse_click_in_cursor) {
16223         float ratio = 0;
16224         const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
16225         const float pxstep = bounds.w / slider_steps;
16226 
16227         /* only update value if the next slider step is reached */
16228         *state = NK_WIDGET_STATE_ACTIVE;
16229         if (NK_ABS(d) >= pxstep) {
16230             const float steps = (float)((int)(NK_ABS(d) / pxstep));
16231             slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
16232             slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
16233             ratio = (slider_value - slider_min)/slider_step;
16234             logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
16235             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
16236         }
16237     }
16238 
16239     /* slider widget state */
16240     if (nk_input_is_mouse_hovering_rect(in, bounds))
16241         *state = NK_WIDGET_STATE_HOVERED;
16242     if (*state & NK_WIDGET_STATE_HOVER &&
16243         !nk_input_is_mouse_prev_hovering_rect(in, bounds))
16244         *state |= NK_WIDGET_STATE_ENTERED;
16245     else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
16246         *state |= NK_WIDGET_STATE_LEFT;
16247     return slider_value;
16248 }
16249 
16250 NK_INTERN void
16251 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
16252     const struct nk_style_slider *style, const struct nk_rect *bounds,
16253     const struct nk_rect *visual_cursor, float min, float value, float max)
16254 {
16255     struct nk_rect fill;
16256     struct nk_rect bar;
16257     const struct nk_style_item *background;
16258 
16259     /* select correct slider images/colors */
16260     struct nk_color bar_color;
16261     const struct nk_style_item *cursor;
16262 
16263     NK_UNUSED(min);
16264     NK_UNUSED(max);
16265     NK_UNUSED(value);
16266 
16267     if (state & NK_WIDGET_STATE_ACTIVED) {
16268         background = &style->active;
16269         bar_color = style->bar_active;
16270         cursor = &style->cursor_active;
16271     } else if (state & NK_WIDGET_STATE_HOVER) {
16272         background = &style->hover;
16273         bar_color = style->bar_hover;
16274         cursor = &style->cursor_hover;
16275     } else {
16276         background = &style->normal;
16277         bar_color = style->bar_normal;
16278         cursor = &style->cursor_normal;
16279     }
16280 
16281     /* calculate slider background bar */
16282     bar.x = bounds->x;
16283     bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
16284     bar.w = bounds->w;
16285     bar.h = bounds->h/6;
16286 
16287     /* filled background bar style */
16288     fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
16289     fill.x = bar.x;
16290     fill.y = bar.y;
16291     fill.h = bar.h;
16292 
16293     /* draw background */
16294     if (background->type == NK_STYLE_ITEM_IMAGE) {
16295         nk_draw_image(out, *bounds, &background->data.image, nk_white);
16296     } else {
16297         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
16298         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
16299     }
16300 
16301     /* draw slider bar */
16302     nk_fill_rect(out, bar, style->rounding, bar_color);
16303     nk_fill_rect(out, fill, style->rounding, style->bar_filled);
16304 
16305     /* draw cursor */
16306     if (cursor->type == NK_STYLE_ITEM_IMAGE)
16307         nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
16308     else nk_fill_circle(out, *visual_cursor, cursor->data.color);
16309 }
16310 
16311 NK_INTERN float
16312 nk_do_slider(nk_flags *state,
16313     struct nk_command_buffer *out, struct nk_rect bounds,
16314     float min, float val, float max, float step,
16315     const struct nk_style_slider *style, struct nk_input *in,
16316     const struct nk_user_font *font)
16317 {
16318     float slider_range;
16319     float slider_min;
16320     float slider_max;
16321     float slider_value;
16322     float slider_steps;
16323     float cursor_offset;
16324 
16325     struct nk_rect visual_cursor;
16326     struct nk_rect logical_cursor;
16327 
16328     NK_ASSERT(style);
16329     NK_ASSERT(out);
16330     if (!out || !style)
16331         return 0;
16332 
16333     /* remove padding from slider bounds */
16334     bounds.x = bounds.x + style->padding.x;
16335     bounds.y = bounds.y + style->padding.y;
16336     bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
16337     bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
16338     bounds.w -= 2 * style->padding.x;
16339     bounds.h -= 2 * style->padding.y;
16340 
16341     /* optional buttons */
16342     if (style->show_buttons) {
16343         nk_flags ws;
16344         struct nk_rect button;
16345         button.y = bounds.y;
16346         button.w = bounds.h;
16347         button.h = bounds.h;
16348 
16349         /* decrement button */
16350         button.x = bounds.x;
16351         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
16352             &style->dec_button, in, font))
16353             val -= step;
16354 
16355         /* increment button */
16356         button.x = (bounds.x + bounds.w) - button.w;
16357         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
16358             &style->inc_button, in, font))
16359             val += step;
16360 
16361         bounds.x = bounds.x + button.w + style->spacing.x;
16362         bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
16363     }
16364 
16365     /* remove one cursor size to support visual cursor */
16366     bounds.x += style->cursor_size.x*0.5f;
16367     bounds.w -= style->cursor_size.x;
16368 
16369     /* make sure the provided values are correct */
16370     slider_max = NK_MAX(min, max);
16371     slider_min = NK_MIN(min, max);
16372     slider_value = NK_CLAMP(slider_min, val, slider_max);
16373     slider_range = slider_max - slider_min;
16374     slider_steps = slider_range / step;
16375     cursor_offset = (slider_value - slider_min) / step;
16376 
16377     /* calculate cursor
16378     Basically you have two cursors. One for visual representation and interaction
16379     and one for updating the actual cursor value. */
16380     logical_cursor.h = bounds.h;
16381     logical_cursor.w = bounds.w / slider_steps;
16382     logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
16383     logical_cursor.y = bounds.y;
16384 
16385     visual_cursor.h = style->cursor_size.y;
16386     visual_cursor.w = style->cursor_size.x;
16387     visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
16388     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
16389 
16390     slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
16391         in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
16392     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
16393 
16394     /* draw slider */
16395     if (style->draw_begin) style->draw_begin(out, style->userdata);
16396     nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
16397     if (style->draw_end) style->draw_end(out, style->userdata);
16398     return slider_value;
16399 }
16400 
16401 /* ===============================================================
16402  *
16403  *                          PROGRESSBAR
16404  *
16405  * ===============================================================*/
16406 NK_INTERN nk_size
16407 nk_progress_behavior(nk_flags *state, struct nk_input *in,
16408     struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable)
16409 {
16410     int left_mouse_down = 0;
16411     int left_mouse_click_in_cursor = 0;
16412 
16413     nk_widget_state_reset(state);
16414     if (!in || !modifiable) return value;
16415     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
16416     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
16417             NK_BUTTON_LEFT, cursor, nk_true);
16418     if (nk_input_is_mouse_hovering_rect(in, r))
16419         *state = NK_WIDGET_STATE_HOVERED;
16420 
16421     if (in && left_mouse_down && left_mouse_click_in_cursor) {
16422         if (left_mouse_down && left_mouse_click_in_cursor) {
16423             float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w;
16424             value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max);
16425             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f;
16426             *state |= NK_WIDGET_STATE_ACTIVE;
16427         }
16428     }
16429     /* set progressbar widget state */
16430     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
16431         *state |= NK_WIDGET_STATE_ENTERED;
16432     else if (nk_input_is_mouse_prev_hovering_rect(in, r))
16433         *state |= NK_WIDGET_STATE_LEFT;
16434     return value;
16435 }
16436 
16437 NK_INTERN void
16438 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
16439     const struct nk_style_progress *style, const struct nk_rect *bounds,
16440     const struct nk_rect *scursor, nk_size value, nk_size max)
16441 {
16442     const struct nk_style_item *background;
16443     const struct nk_style_item *cursor;
16444 
16445     NK_UNUSED(max);
16446     NK_UNUSED(value);
16447 
16448     /* select correct colors/images to draw */
16449     if (state & NK_WIDGET_STATE_ACTIVED) {
16450         background = &style->active;
16451         cursor = &style->cursor_active;
16452     } else if (state & NK_WIDGET_STATE_HOVER){
16453         background = &style->hover;
16454         cursor = &style->cursor_hover;
16455     } else {
16456         background = &style->normal;
16457         cursor = &style->cursor_normal;
16458     }
16459 
16460     /* draw background */
16461     if (background->type == NK_STYLE_ITEM_COLOR) {
16462         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
16463         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
16464     } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
16465 
16466     /* draw cursor */
16467     if (cursor->type == NK_STYLE_ITEM_COLOR) {
16468         nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
16469         nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
16470     } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
16471 }
16472 
16473 NK_INTERN nk_size
16474 nk_do_progress(nk_flags *state,
16475     struct nk_command_buffer *out, struct nk_rect bounds,
16476     nk_size value, nk_size max, int modifiable,
16477     const struct nk_style_progress *style, struct nk_input *in)
16478 {
16479     float prog_scale;
16480     nk_size prog_value;
16481     struct nk_rect cursor;
16482 
16483     NK_ASSERT(style);
16484     NK_ASSERT(out);
16485     if (!out || !style) return 0;
16486 
16487     /* calculate progressbar cursor */
16488     cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
16489     cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
16490     cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
16491     prog_scale = (float)value / (float)max;
16492 
16493     /* update progressbar */
16494     prog_value = NK_MIN(value, max);
16495     prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable);
16496     cursor.w = cursor.w * prog_scale;
16497 
16498     /* draw progressbar */
16499     if (style->draw_begin) style->draw_begin(out, style->userdata);
16500     nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
16501     if (style->draw_end) style->draw_end(out, style->userdata);
16502     return prog_value;
16503 }
16504 
16505 /* ===============================================================
16506  *
16507  *                          SCROLLBAR
16508  *
16509  * ===============================================================*/
16510 NK_INTERN float
16511 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
16512     int has_scrolling, const struct nk_rect *scroll,
16513     const struct nk_rect *cursor, const struct nk_rect *empty0,
16514     const struct nk_rect *empty1, float scroll_offset,
16515     float target, float scroll_step, enum nk_orientation o)
16516 {
16517     nk_flags ws = 0;
16518     int left_mouse_down;
16519     int left_mouse_click_in_cursor;
16520     float scroll_delta;
16521 
16522     nk_widget_state_reset(state);
16523     if (!in) return scroll_offset;
16524 
16525     left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
16526     left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
16527         NK_BUTTON_LEFT, *cursor, nk_true);
16528     if (nk_input_is_mouse_hovering_rect(in, *scroll))
16529         *state = NK_WIDGET_STATE_HOVERED;
16530 
16531     scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
16532     if (left_mouse_down && left_mouse_click_in_cursor) {
16533         /* update cursor by mouse dragging */
16534         float pixel, delta;
16535         *state = NK_WIDGET_STATE_ACTIVE;
16536         if (o == NK_VERTICAL) {
16537             float cursor_y;
16538             pixel = in->mouse.delta.y;
16539             delta = (pixel / scroll->h) * target;
16540             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
16541             cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
16542             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
16543         } else {
16544             float cursor_x;
16545             pixel = in->mouse.delta.x;
16546             delta = (pixel / scroll->w) * target;
16547             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
16548             cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
16549             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
16550         }
16551     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
16552             nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
16553         /* scroll page up by click on empty space or shortcut */
16554         if (o == NK_VERTICAL)
16555             scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
16556         else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
16557     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
16558         nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
16559         /* scroll page down by click on empty space or shortcut */
16560         if (o == NK_VERTICAL)
16561             scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
16562         else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
16563     } else if (has_scrolling) {
16564         if ((scroll_delta < 0 || (scroll_delta > 0))) {
16565             /* update cursor by mouse scrolling */
16566             scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
16567             if (o == NK_VERTICAL)
16568                 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
16569             else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
16570         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
16571             /* update cursor to the beginning  */
16572             if (o == NK_VERTICAL) scroll_offset = 0;
16573         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
16574             /* update cursor to the end */
16575             if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
16576         }
16577     }
16578     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
16579         *state |= NK_WIDGET_STATE_ENTERED;
16580     else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
16581         *state |= NK_WIDGET_STATE_LEFT;
16582     return scroll_offset;
16583 }
16584 
16585 NK_INTERN void
16586 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
16587     const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
16588     const struct nk_rect *scroll)
16589 {
16590     const struct nk_style_item *background;
16591     const struct nk_style_item *cursor;
16592 
16593     /* select correct colors/images to draw */
16594     if (state & NK_WIDGET_STATE_ACTIVED) {
16595         background = &style->active;
16596         cursor = &style->cursor_active;
16597     } else if (state & NK_WIDGET_STATE_HOVER) {
16598         background = &style->hover;
16599         cursor = &style->cursor_hover;
16600     } else {
16601         background = &style->normal;
16602         cursor = &style->cursor_normal;
16603     }
16604 
16605     /* draw background */
16606     if (background->type == NK_STYLE_ITEM_COLOR) {
16607         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
16608         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
16609     } else {
16610         nk_draw_image(out, *bounds, &background->data.image, nk_white);
16611     }
16612 
16613     /* draw cursor */
16614     if (background->type == NK_STYLE_ITEM_COLOR) {
16615         nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
16616         nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
16617     } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
16618 }
16619 
16620 NK_INTERN float
16621 nk_do_scrollbarv(nk_flags *state,
16622     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
16623     float offset, float target, float step, float button_pixel_inc,
16624     const struct nk_style_scrollbar *style, struct nk_input *in,
16625     const struct nk_user_font *font)
16626 {
16627     struct nk_rect empty_north;
16628     struct nk_rect empty_south;
16629     struct nk_rect cursor;
16630 
16631     float scroll_step;
16632     float scroll_offset;
16633     float scroll_off;
16634     float scroll_ratio;
16635 
16636     NK_ASSERT(out);
16637     NK_ASSERT(style);
16638     NK_ASSERT(state);
16639     if (!out || !style) return 0;
16640 
16641     scroll.w = NK_MAX(scroll.w, 1);
16642     scroll.h = NK_MAX(scroll.h, 0);
16643     if (target <= scroll.h) return 0;
16644 
16645     /* optional scrollbar buttons */
16646     if (style->show_buttons) {
16647         nk_flags ws;
16648         float scroll_h;
16649         struct nk_rect button;
16650 
16651         button.x = scroll.x;
16652         button.w = scroll.w;
16653         button.h = scroll.w;
16654 
16655         scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
16656         scroll_step = NK_MIN(step, button_pixel_inc);
16657 
16658         /* decrement button */
16659         button.y = scroll.y;
16660         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
16661             NK_BUTTON_REPEATER, &style->dec_button, in, font))
16662             offset = offset - scroll_step;
16663 
16664         /* increment button */
16665         button.y = scroll.y + scroll.h - button.h;
16666         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
16667             NK_BUTTON_REPEATER, &style->inc_button, in, font))
16668             offset = offset + scroll_step;
16669 
16670         scroll.y = scroll.y + button.h;
16671         scroll.h = scroll_h;
16672     }
16673 
16674     /* calculate scrollbar constants */
16675     scroll_step = NK_MIN(step, scroll.h);
16676     scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
16677     scroll_ratio = scroll.h / target;
16678     scroll_off = scroll_offset / target;
16679 
16680     /* calculate scrollbar cursor bounds */
16681     cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
16682     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
16683     cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
16684     cursor.x = scroll.x + style->border + style->padding.x;
16685 
16686     /* calculate empty space around cursor */
16687     empty_north.x = scroll.x;
16688     empty_north.y = scroll.y;
16689     empty_north.w = scroll.w;
16690     empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
16691 
16692     empty_south.x = scroll.x;
16693     empty_south.y = cursor.y + cursor.h;
16694     empty_south.w = scroll.w;
16695     empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
16696 
16697     /* update scrollbar */
16698     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
16699         &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
16700     scroll_off = scroll_offset / target;
16701     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
16702 
16703     /* draw scrollbar */
16704     if (style->draw_begin) style->draw_begin(out, style->userdata);
16705     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
16706     if (style->draw_end) style->draw_end(out, style->userdata);
16707     return scroll_offset;
16708 }
16709 
16710 NK_INTERN float
16711 nk_do_scrollbarh(nk_flags *state,
16712     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
16713     float offset, float target, float step, float button_pixel_inc,
16714     const struct nk_style_scrollbar *style, struct nk_input *in,
16715     const struct nk_user_font *font)
16716 {
16717     struct nk_rect cursor;
16718     struct nk_rect empty_west;
16719     struct nk_rect empty_east;
16720 
16721     float scroll_step;
16722     float scroll_offset;
16723     float scroll_off;
16724     float scroll_ratio;
16725 
16726     NK_ASSERT(out);
16727     NK_ASSERT(style);
16728     if (!out || !style) return 0;
16729 
16730     /* scrollbar background */
16731     scroll.h = NK_MAX(scroll.h, 1);
16732     scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
16733     if (target <= scroll.w) return 0;
16734 
16735     /* optional scrollbar buttons */
16736     if (style->show_buttons) {
16737         nk_flags ws;
16738         float scroll_w;
16739         struct nk_rect button;
16740         button.y = scroll.y;
16741         button.w = scroll.h;
16742         button.h = scroll.h;
16743 
16744         scroll_w = scroll.w - 2 * button.w;
16745         scroll_step = NK_MIN(step, button_pixel_inc);
16746 
16747         /* decrement button */
16748         button.x = scroll.x;
16749         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
16750             NK_BUTTON_REPEATER, &style->dec_button, in, font))
16751             offset = offset - scroll_step;
16752 
16753         /* increment button */
16754         button.x = scroll.x + scroll.w - button.w;
16755         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
16756             NK_BUTTON_REPEATER, &style->inc_button, in, font))
16757             offset = offset + scroll_step;
16758 
16759         scroll.x = scroll.x + button.w;
16760         scroll.w = scroll_w;
16761     }
16762 
16763     /* calculate scrollbar constants */
16764     scroll_step = NK_MIN(step, scroll.w);
16765     scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
16766     scroll_ratio = scroll.w / target;
16767     scroll_off = scroll_offset / target;
16768 
16769     /* calculate cursor bounds */
16770     cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
16771     cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
16772     cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
16773     cursor.y = scroll.y + style->border + style->padding.y;
16774 
16775     /* calculate empty space around cursor */
16776     empty_west.x = scroll.x;
16777     empty_west.y = scroll.y;
16778     empty_west.w = cursor.x - scroll.x;
16779     empty_west.h = scroll.h;
16780 
16781     empty_east.x = cursor.x + cursor.w;
16782     empty_east.y = scroll.y;
16783     empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
16784     empty_east.h = scroll.h;
16785 
16786     /* update scrollbar */
16787     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
16788         &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
16789     scroll_off = scroll_offset / target;
16790     cursor.x = scroll.x + (scroll_off * scroll.w);
16791 
16792     /* draw scrollbar */
16793     if (style->draw_begin) style->draw_begin(out, style->userdata);
16794     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
16795     if (style->draw_end) style->draw_end(out, style->userdata);
16796     return scroll_offset;
16797 }
16798 
16799 /* ===============================================================
16800  *
16801  *                          FILTER
16802  *
16803  * ===============================================================*/
16804 NK_API int nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
16805 {(void)unicode;NK_UNUSED(box);return nk_true;}
16806 
16807 NK_API int
16808 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
16809 {
16810     NK_UNUSED(box);
16811     if (unicode > 128) return nk_false;
16812     else return nk_true;
16813 }
16814 
16815 NK_API int
16816 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
16817 {
16818     NK_UNUSED(box);
16819     if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
16820         return nk_false;
16821     else return nk_true;
16822 }
16823 
16824 NK_API int
16825 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
16826 {
16827     NK_UNUSED(box);
16828     if ((unicode < '0' || unicode > '9') && unicode != '-')
16829         return nk_false;
16830     else return nk_true;
16831 }
16832 
16833 NK_API int
16834 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
16835 {
16836     NK_UNUSED(box);
16837     if ((unicode < '0' || unicode > '9') &&
16838         (unicode < 'a' || unicode > 'f') &&
16839         (unicode < 'A' || unicode > 'F'))
16840         return nk_false;
16841     else return nk_true;
16842 }
16843 
16844 NK_API int
16845 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
16846 {
16847     NK_UNUSED(box);
16848     if (unicode < '0' || unicode > '7')
16849         return nk_false;
16850     else return nk_true;
16851 }
16852 
16853 NK_API int
16854 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
16855 {
16856     NK_UNUSED(box);
16857     if (unicode != '0' && unicode != '1')
16858         return nk_false;
16859     else return nk_true;
16860 }
16861 
16862 /* ===============================================================
16863  *
16864  *                          EDIT
16865  *
16866  * ===============================================================*/
16867 NK_INTERN void
16868 nk_edit_draw_text(struct nk_command_buffer *out,
16869     const struct nk_style_edit *style, float pos_x, float pos_y,
16870     float x_offset, const char *text, int byte_len, float row_height,
16871     const struct nk_user_font *font, struct nk_color background,
16872     struct nk_color foreground, int is_selected, struct nk_lexer *lexer,
16873 		int offset)
16874 {
16875     NK_ASSERT(out);
16876     NK_ASSERT(font);
16877     NK_ASSERT(style);
16878     if (!text || !byte_len || !out || !style) return;
16879 
16880     {int glyph_len = 0;
16881     nk_rune unicode = 0;
16882     int text_len = 0;
16883     float line_width = 0;
16884     float glyph_width;
16885     const char *line = text;
16886     float line_offset = 0;
16887     int line_count = 0;
16888 
16889     struct nk_text txt;
16890     txt.padding = nk_vec2(0,0);
16891     txt.background = background;
16892     txt.text = foreground;
16893 
16894     glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
16895     if (!glyph_len) return;
16896     while ((text_len < byte_len) && glyph_len)
16897     {
16898         if (unicode == '\n') {
16899             /* new line separator so draw previous line */
16900             struct nk_rect label;
16901             label.y = pos_y + line_offset;
16902             label.h = row_height;
16903             label.w = line_width;
16904             label.x = pos_x;
16905             if (!line_count)
16906                 label.x += x_offset;
16907 
16908             if (is_selected) /* selection needs to draw different background color */
16909                 nk_fill_rect(out, label, 0, background);
16910 						if(lexer->tokens && !is_selected)
16911 						{
16912 							nk_widget_text_lexed(out, label, line, (int)((text + text_len) - line),
16913 									&txt, NK_TEXT_CENTERED, font, lexer->tokens, line - text + offset);
16914 						}
16915 						else
16916 						{
16917 							nk_widget_text(out, label, line, (int)((text + text_len) - line),
16918 									&txt, NK_TEXT_CENTERED, font);
16919 						}
16920 
16921             text_len++;
16922             line_count++;
16923             line_width = 0;
16924             line = text + text_len;
16925             line_offset += row_height;
16926             glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
16927             continue;
16928         }
16929         if (unicode == '\r') {
16930             text_len++;
16931             glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
16932             continue;
16933         }
16934         glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
16935         line_width += (float)glyph_width;
16936         text_len += glyph_len;
16937         glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
16938         continue;
16939     }
16940     if (line_width > 0) {
16941         /* draw last line */
16942         struct nk_rect label;
16943         label.y = pos_y + line_offset;
16944         label.h = row_height;
16945         label.w = line_width;
16946         label.x = pos_x;
16947         if (!line_count)
16948             label.x += x_offset;
16949 
16950         if (is_selected)
16951             nk_fill_rect(out, label, 0, background);
16952 				if(lexer->tokens && !is_selected)
16953 				{
16954 					nk_widget_text_lexed(out, label, line, (int)((text + text_len) - line),
16955 							&txt, NK_TEXT_LEFT, font, lexer->tokens, line - text + offset);
16956 				}
16957 				else
16958 				{
16959 					nk_widget_text(out, label, line, (int)((text + text_len) - line),
16960 							&txt, NK_TEXT_LEFT, font);
16961 				}
16962     }}
16963 }
16964 
16965 NK_INTERN void
16966 nk_edit_refresh_lex(struct nk_text_edit *edit)
16967 {
16968 	if(edit->lexer.needs_refresh || !edit->lexer.tokens)
16969 	{
16970 		if(edit->lexer.tokens)
16971 			free(edit->lexer.tokens);
16972 
16973 		edit->lexer.tokens = edit->lexer.lex(edit->lexer.data,
16974 			nk_str_get_const(&edit->string), nk_str_len_char(&edit->string));
16975 
16976 		edit->lexer.needs_refresh = 0;
16977 	}
16978 }
16979 
16980 NK_INTERN nk_flags
16981 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
16982     struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
16983     struct nk_text_edit *edit, const struct nk_style_edit *style,
16984     struct nk_input *in, const struct nk_user_font *font)
16985 {
16986     struct nk_rect area;
16987     nk_flags ret = 0;
16988     float row_height;
16989     char prev_state = 0;
16990     char is_hovered = 0;
16991     char select_all = 0;
16992     char cursor_follow = 0;
16993     struct nk_rect old_clip;
16994     struct nk_rect clip;
16995 		int has_changes = 0;
16996 
16997     NK_ASSERT(state);
16998     NK_ASSERT(out);
16999     NK_ASSERT(style);
17000     if (!state || !out || !style)
17001         return ret;
17002 
17003     /* visible text area calculation */
17004     area.x = bounds.x + style->padding.x + style->border;
17005     area.y = bounds.y + style->padding.y + style->border;
17006     area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
17007     area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
17008     if (flags & NK_EDIT_MULTILINE)
17009         area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
17010     row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
17011 
17012     /* calculate clipping rectangle */
17013     old_clip = out->clip;
17014     nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
17015 
17016     /* update edit state */
17017     prev_state = (char)edit->active;
17018     is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
17019     if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) {
17020         edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
17021                                 bounds.x, bounds.y, bounds.w, bounds.h);
17022     }
17023 
17024     /* (de)activate text editor */
17025     if (!prev_state && edit->active) {
17026         const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
17027             NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE;
17028         nk_textedit_reset_state(edit, type, filter);
17029         if (flags & NK_EDIT_AUTO_SELECT)
17030             select_all = nk_true;
17031         if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
17032             edit->cursor = edit->string.len;
17033             in = 0;
17034         }
17035     } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
17036     if (flags & NK_EDIT_READ_ONLY)
17037         edit->mode = NK_TEXT_EDIT_MODE_VIEW;
17038     else if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
17039         edit->mode = NK_TEXT_EDIT_MODE_INSERT;
17040 
17041     ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
17042     if (prev_state != edit->active)
17043         ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
17044 
17045     /* handle user input */
17046     if (edit->active && in)
17047     {
17048         int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
17049         const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
17050         const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
17051 
17052         /* mouse click handler */
17053         is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
17054         if (select_all) {
17055             nk_textedit_select_all(edit);
17056         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
17057             in->mouse.buttons[NK_BUTTON_LEFT].clicked) {
17058             nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
17059         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
17060             (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
17061             nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
17062             cursor_follow = nk_true;
17063         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
17064             in->mouse.buttons[NK_BUTTON_RIGHT].down) {
17065             nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
17066             nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
17067             cursor_follow = nk_true;
17068         }
17069 
17070         {int i; /* keyboard input */
17071         int old_mode = edit->mode;
17072         for (i = 0; i < NK_KEY_MAX; ++i) {
17073             if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
17074             if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
17075                 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
17076                 cursor_follow = nk_true;
17077             }
17078         }
17079         if (old_mode != edit->mode) {
17080             in->keyboard.text_len = 0;
17081         }}
17082 
17083         /* text input */
17084         edit->filter = filter;
17085         if (in->keyboard.text_len) {
17086             nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
17087             cursor_follow = nk_true;
17088             in->keyboard.text_len = 0;
17089         }
17090 
17091         /* enter key handler */
17092         if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) {
17093             cursor_follow = nk_true;
17094             if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
17095                 nk_textedit_text(edit, "\n", 1);
17096             else if (flags & NK_EDIT_SIG_ENTER)
17097                 ret |= NK_EDIT_COMMITED;
17098             else nk_textedit_text(edit, "\n", 1);
17099         }
17100 
17101         /* cut & copy handler */
17102         {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
17103         int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
17104         if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
17105         {
17106             int glyph_len;
17107             nk_rune unicode;
17108             const char *text;
17109             int b = edit->select_start;
17110             int e = edit->select_end;
17111 
17112             int begin = NK_MIN(b, e);
17113             int end = NK_MAX(b, e);
17114             text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
17115             if (edit->clip.copy)
17116                 edit->clip.copy(edit->clip.userdata, text, end - begin);
17117             if (cut && !(flags & NK_EDIT_READ_ONLY)){
17118                 nk_textedit_cut(edit);
17119                 cursor_follow = nk_true;
17120             }
17121         }}
17122 
17123         /* paste handler */
17124         {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
17125         if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
17126             edit->clip.paste(edit->clip.userdata, edit);
17127             cursor_follow = nk_true;
17128         }}
17129 
17130         /* tab handler */
17131         {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
17132         if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
17133             nk_textedit_text(edit, "  ", 2);
17134             cursor_follow = nk_true;
17135         }}
17136     }
17137 
17138     /* set widget state */
17139     if (edit->active)
17140         *state = NK_WIDGET_STATE_ACTIVE;
17141     else nk_widget_state_reset(state);
17142 
17143     if (is_hovered)
17144         *state |= NK_WIDGET_STATE_HOVERED;
17145 
17146     /* DRAW EDIT */
17147     {const char *text = nk_str_get_const(&edit->string);
17148     int len = nk_str_len_char(&edit->string);
17149 
17150     {/* select background colors/images  */
17151     const struct nk_style_item *background;
17152     if (*state & NK_WIDGET_STATE_ACTIVED)
17153         background = &style->active;
17154     else if (*state & NK_WIDGET_STATE_HOVER)
17155         background = &style->hover;
17156     else background = &style->normal;
17157 
17158     /* draw background frame */
17159     if (background->type == NK_STYLE_ITEM_COLOR) {
17160         nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
17161         nk_fill_rect(out, bounds, style->rounding, background->data.color);
17162     } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
17163 
17164     area.w = NK_MAX(0, area.w - style->cursor_size);
17165     if (edit->active)
17166     {
17167         int total_lines = 1;
17168         struct nk_vec2 text_size = nk_vec2(0,0);
17169 
17170         /* text pointer positions */
17171         const char *cursor_ptr = 0;
17172         const char *select_begin_ptr = 0;
17173         const char *select_end_ptr = 0;
17174 
17175         /* 2D pixel positions */
17176         struct nk_vec2 cursor_pos = nk_vec2(0,0);
17177         struct nk_vec2 selection_offset_start = nk_vec2(0,0);
17178         struct nk_vec2 selection_offset_end = nk_vec2(0,0);
17179 
17180         int selection_begin = NK_MIN(edit->select_start, edit->select_end);
17181         int selection_end = NK_MAX(edit->select_start, edit->select_end);
17182 
17183         /* calculate total line count + total space + cursor/selection position */
17184         float line_width = 0.0f;
17185         if (text && len)
17186         {
17187             /* utf8 encoding */
17188             float glyph_width;
17189             int glyph_len = 0;
17190             nk_rune unicode = 0;
17191             int text_len = 0;
17192             int glyphs = 0;
17193             int row_begin = 0;
17194 
17195             glyph_len = nk_utf_decode(text, &unicode, len);
17196             glyph_width = font->width(font->userdata, font->height, text, glyph_len);
17197             line_width = 0;
17198 
17199             /* iterate all lines */
17200             while ((text_len < len) && glyph_len)
17201             {
17202                 /* set cursor 2D position and line */
17203                 if (!cursor_ptr && glyphs == edit->cursor)
17204                 {
17205                     int glyph_offset;
17206                     struct nk_vec2 out_offset;
17207                     struct nk_vec2 row_size;
17208                     const char *remaining;
17209 
17210                     /* calculate 2d position */
17211                     cursor_pos.y = (float)(total_lines-1) * row_height;
17212                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
17213                                 text_len-row_begin, row_height, &remaining,
17214                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
17215                     cursor_pos.x = row_size.x;
17216                     cursor_ptr = text + text_len;
17217                 }
17218 
17219                 /* set start selection 2D position and line */
17220                 if (!select_begin_ptr && edit->select_start != edit->select_end &&
17221                     glyphs == selection_begin)
17222                 {
17223                     int glyph_offset;
17224                     struct nk_vec2 out_offset;
17225                     struct nk_vec2 row_size;
17226                     const char *remaining;
17227 
17228                     /* calculate 2d position */
17229                     selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
17230                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
17231                                 text_len-row_begin, row_height, &remaining,
17232                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
17233                     selection_offset_start.x = row_size.x;
17234                     select_begin_ptr = text + text_len;
17235                 }
17236 
17237                 /* set end selection 2D position and line */
17238                 if (!select_end_ptr && edit->select_start != edit->select_end &&
17239                     glyphs == selection_end)
17240                 {
17241                     int glyph_offset;
17242                     struct nk_vec2 out_offset;
17243                     struct nk_vec2 row_size;
17244                     const char *remaining;
17245 
17246                     /* calculate 2d position */
17247                     selection_offset_end.y = (float)(total_lines-1) * row_height;
17248                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
17249                                 text_len-row_begin, row_height, &remaining,
17250                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
17251                     selection_offset_end.x = row_size.x;
17252                     select_end_ptr = text + text_len;
17253                 }
17254                 if (unicode == '\n') {
17255                     text_size.x = NK_MAX(text_size.x, line_width);
17256                     total_lines++;
17257                     line_width = 0;
17258                     text_len++;
17259                     glyphs++;
17260                     row_begin = text_len;
17261                     glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
17262                     glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
17263                     continue;
17264                 }
17265 
17266                 glyphs++;
17267                 text_len += glyph_len;
17268                 line_width += (float)glyph_width;
17269 
17270                 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
17271                 glyph_width = font->width(font->userdata, font->height,
17272                     text+text_len, glyph_len);
17273                 continue;
17274             }
17275             text_size.y = (float)total_lines * row_height;
17276 
17277             /* handle case when cursor is at end of text buffer */
17278             if (!cursor_ptr && edit->cursor == edit->string.len) {
17279                 cursor_pos.x = line_width;
17280                 cursor_pos.y = text_size.y - row_height;
17281             }
17282         }
17283         {
17284             /* scrollbar */
17285             if (cursor_follow)
17286             {
17287                 /* update scrollbar to follow cursor */
17288                 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
17289                     /* horizontal scroll */
17290                     const float scroll_increment = area.w * 0.25f;
17291                     if (cursor_pos.x < edit->scrollbar.x)
17292                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
17293                     if (cursor_pos.x >= edit->scrollbar.x + area.w)
17294                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x);
17295                 } else edit->scrollbar.x = 0;
17296 
17297                 if (flags & NK_EDIT_MULTILINE) {
17298                     /* vertical scroll */
17299                     if (cursor_pos.y < edit->scrollbar.y)
17300                         edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
17301                     if (cursor_pos.y >= edit->scrollbar.y + area.h)
17302                         edit->scrollbar.y = edit->scrollbar.y + row_height;
17303                 } else edit->scrollbar.y = 0;
17304             }
17305 
17306             /* scrollbar widget */
17307             if (flags & NK_EDIT_MULTILINE)
17308             {
17309                 nk_flags ws;
17310                 struct nk_rect scroll;
17311                 float scroll_target;
17312                 float scroll_offset;
17313                 float scroll_step;
17314                 float scroll_inc;
17315 
17316                 scroll = area;
17317                 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
17318                 scroll.w = style->scrollbar_size.x;
17319 
17320                 scroll_offset = edit->scrollbar.y;
17321                 scroll_step = scroll.h * 0.10f;
17322                 scroll_inc = scroll.h * 0.01f;
17323                 scroll_target = text_size.y;
17324                 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, nk_true,
17325                         scroll_offset, scroll_target, scroll_step, scroll_inc,
17326                         &style->scrollbar, in, font);
17327             }
17328         }
17329 
17330         /* draw text */
17331         {struct nk_color background_color;
17332         struct nk_color text_color;
17333         struct nk_color sel_background_color;
17334         struct nk_color sel_text_color;
17335         struct nk_color cursor_color;
17336         struct nk_color cursor_text_color;
17337         const struct nk_style_item *background;
17338         nk_push_scissor(out, clip);
17339 
17340         /* select correct colors to draw */
17341         if (*state & NK_WIDGET_STATE_ACTIVED) {
17342             background = &style->active;
17343             text_color = style->text_active;
17344             sel_text_color = style->selected_text_hover;
17345             sel_background_color = style->selected_hover;
17346             cursor_color = style->cursor_hover;
17347             cursor_text_color = style->cursor_text_hover;
17348         } else if (*state & NK_WIDGET_STATE_HOVER) {
17349             background = &style->hover;
17350             text_color = style->text_hover;
17351             sel_text_color = style->selected_text_hover;
17352             sel_background_color = style->selected_hover;
17353             cursor_text_color = style->cursor_text_hover;
17354             cursor_color = style->cursor_hover;
17355         } else {
17356             background = &style->normal;
17357             text_color = style->text_normal;
17358             sel_text_color = style->selected_text_normal;
17359             sel_background_color = style->selected_normal;
17360             cursor_color = style->cursor_normal;
17361             cursor_text_color = style->cursor_text_normal;
17362         }
17363         if (background->type == NK_STYLE_ITEM_IMAGE)
17364             background_color = nk_rgba(0,0,0,0);
17365         else background_color = background->data.color;
17366 
17367 				if(edit->lexer.lex)
17368 				{
17369 					if(has_changes)
17370 						edit->lexer.needs_refresh = 1;
17371 
17372 					nk_edit_refresh_lex(edit);
17373 				}
17374 
17375         if (edit->select_start == edit->select_end) {
17376             /* no selection so just draw the complete text */
17377             const char *begin = nk_str_get_const(&edit->string);
17378             int l = nk_str_len_char(&edit->string);
17379             nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
17380                 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
17381                 background_color, text_color, nk_false, &edit->lexer, 0);
17382         } else {
17383             /* edit has selection so draw 1-3 text chunks */
17384             if (edit->select_start != edit->select_end && selection_begin > 0){
17385                 /* draw unselected text before selection */
17386                 const char *begin = nk_str_get_const(&edit->string);
17387                 NK_ASSERT(select_begin_ptr);
17388                 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
17389                     area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
17390                     row_height, font, background_color, text_color, nk_false, &edit->lexer, 0);
17391             }
17392             if (edit->select_start != edit->select_end) {
17393 								const int offset = edit->select_start < edit->select_end ? edit->select_start : edit->select_end;
17394 								int glyph_offset;
17395 								nk_rune unicode;
17396 								const char *ptr = nk_str_at_const(&edit->string, offset, &unicode, &glyph_offset);
17397 								const int offset2 = ptr - nk_str_get_const(&edit->string);
17398                 /* draw selected text */
17399                 NK_ASSERT(select_begin_ptr);
17400                 if (!select_end_ptr) {
17401                     const char *begin = nk_str_get_const(&edit->string);
17402                     select_end_ptr = begin + nk_str_len_char(&edit->string);
17403                 }
17404                 nk_edit_draw_text(out, style,
17405                     area.x - edit->scrollbar.x,
17406                     area.y + selection_offset_start.y - edit->scrollbar.y,
17407                     selection_offset_start.x,
17408                     select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
17409                     row_height, font, sel_background_color, sel_text_color, nk_true,
17410 										&edit->lexer, offset2);
17411             }
17412             if ((edit->select_start != edit->select_end &&
17413                 selection_end < edit->string.len))
17414             {
17415                 /* draw unselected text after selected text */
17416                 const char *begin = select_end_ptr;
17417                 const char *end = nk_str_get_const(&edit->string) +
17418                                     nk_str_len_char(&edit->string);
17419 								const int offset = edit->select_start < edit->select_end ? edit->select_end : edit->select_start;
17420 								int glyph_offset;
17421 								nk_rune unicode;
17422 								const char *ptr = nk_str_at_const(&edit->string, offset, &unicode, &glyph_offset);
17423 								const int offset2 = ptr - nk_str_get_const(&edit->string);
17424                 NK_ASSERT(select_end_ptr);
17425                 nk_edit_draw_text(out, style,
17426                     area.x - edit->scrollbar.x,
17427                     area.y + selection_offset_end.y - edit->scrollbar.y,
17428                     selection_offset_end.x,
17429                     begin, (int)(end - begin), row_height, font,
17430                     background_color, text_color, nk_false,
17431 										&edit->lexer, offset2);
17432             }
17433         }
17434 
17435         /* cursor */
17436         if (edit->select_start == edit->select_end)
17437         {
17438             if (edit->cursor >= nk_str_len(&edit->string) ||
17439                 (cursor_ptr && *cursor_ptr == '\n')) {
17440                 /* draw cursor at end of line */
17441                 struct nk_rect cursor;
17442                 cursor.w = style->cursor_size;
17443                 cursor.h = font->height;
17444                 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
17445                 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
17446                 cursor.y -= edit->scrollbar.y;
17447                 nk_fill_rect(out, cursor, 0, cursor_color);
17448             } else {
17449                 /* draw cursor inside text */
17450                 int glyph_len;
17451                 struct nk_rect label;
17452                 struct nk_text txt;
17453 
17454                 nk_rune unicode;
17455                 NK_ASSERT(cursor_ptr);
17456                 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
17457 
17458                 label.x = area.x + cursor_pos.x - edit->scrollbar.x;
17459                 label.y = area.y + cursor_pos.y - edit->scrollbar.y;
17460                 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
17461                 label.h = row_height;
17462 
17463                 txt.padding = nk_vec2(0,0);
17464                 txt.background = cursor_color;;
17465                 txt.text = cursor_text_color;
17466                 nk_fill_rect(out, label, 0, cursor_color);
17467                 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
17468             }
17469         }}
17470     } else {
17471         /* not active so just draw text */
17472         int l = nk_str_len_char(&edit->string);
17473         const char *begin = nk_str_get_const(&edit->string);
17474 
17475 				if(edit->lexer.lex)
17476 					nk_edit_refresh_lex(edit);
17477 
17478         const struct nk_style_item *background;
17479         struct nk_color background_color;
17480         struct nk_color text_color;
17481         nk_push_scissor(out, clip);
17482         if (*state & NK_WIDGET_STATE_ACTIVED) {
17483             background = &style->active;
17484             text_color = style->text_active;
17485         } else if (*state & NK_WIDGET_STATE_HOVER) {
17486             background = &style->hover;
17487             text_color = style->text_hover;
17488         } else {
17489             background = &style->normal;
17490             text_color = style->text_normal;
17491         }
17492         if (background->type == NK_STYLE_ITEM_IMAGE)
17493             background_color = nk_rgba(0,0,0,0);
17494         else background_color = background->data.color;
17495         nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
17496             area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
17497             background_color, text_color, nk_false, &edit->lexer, 0);
17498     }
17499     nk_push_scissor(out, old_clip);}
17500     return ret;
17501 }
17502 
17503 /* ===============================================================
17504  *
17505  *                          PROPERTY
17506  *
17507  * ===============================================================*/
17508 enum nk_property_status {
17509     NK_PROPERTY_DEFAULT,
17510     NK_PROPERTY_EDIT,
17511     NK_PROPERTY_DRAG
17512 };
17513 enum nk_property_filter {
17514     NK_FILTER_INT,
17515     NK_FILTER_FLOAT
17516 };
17517 enum nk_property_kind {
17518     NK_PROPERTY_INT,
17519     NK_PROPERTY_FLOAT,
17520     NK_PROPERTY_DOUBLE
17521 };
17522 union nk_property {
17523     int i;
17524     float f;
17525     double d;
17526 };
17527 struct nk_property_variant {
17528     enum nk_property_kind kind;
17529     union nk_property value;
17530     union nk_property min_value;
17531     union nk_property max_value;
17532     union nk_property step;
17533 };
17534 
17535 NK_INTERN void
17536 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
17537     struct nk_rect drag, struct nk_property_variant *variant,
17538     float inc_per_pixel)
17539 {
17540     int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
17541     int left_mouse_click_in_cursor = in &&
17542         nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true);
17543 
17544     nk_widget_state_reset(state);
17545     if (nk_input_is_mouse_hovering_rect(in, drag))
17546         *state = NK_WIDGET_STATE_HOVERED;
17547 
17548     if (left_mouse_down && left_mouse_click_in_cursor) {
17549         float delta, pixels;
17550         pixels = in->mouse.delta.x;
17551         delta = pixels * inc_per_pixel;
17552         switch (variant->kind) {
17553         default: break;
17554         case NK_PROPERTY_INT:
17555             variant->value.i = variant->value.i + (int)delta;
17556             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
17557             break;
17558         case NK_PROPERTY_FLOAT:
17559             variant->value.f = variant->value.f + (float)delta;
17560             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
17561             break;
17562         case NK_PROPERTY_DOUBLE:
17563             variant->value.d = variant->value.d + (double)delta;
17564             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
17565             break;
17566         }
17567         *state = NK_WIDGET_STATE_ACTIVE;
17568     }
17569     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
17570         *state |= NK_WIDGET_STATE_ENTERED;
17571     else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
17572         *state |= NK_WIDGET_STATE_LEFT;
17573 }
17574 
17575 NK_INTERN void
17576 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
17577     struct nk_rect property,  struct nk_rect label, struct nk_rect edit,
17578     struct nk_rect empty, int *state, struct nk_property_variant *variant,
17579     float inc_per_pixel)
17580 {
17581     if (in && *state == NK_PROPERTY_DEFAULT) {
17582         if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
17583             *state = NK_PROPERTY_EDIT;
17584         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true))
17585             *state = NK_PROPERTY_DRAG;
17586         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true))
17587             *state = NK_PROPERTY_DRAG;
17588     }
17589     if (*state == NK_PROPERTY_DRAG) {
17590         nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
17591         if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
17592     }
17593 }
17594 
17595 NK_INTERN void
17596 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
17597     const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
17598     const char *name, int len, const struct nk_user_font *font)
17599 {
17600     struct nk_text text;
17601     const struct nk_style_item *background;
17602 
17603     /* select correct background and text color */
17604     if (state & NK_WIDGET_STATE_ACTIVED) {
17605         background = &style->active;
17606         text.text = style->label_active;
17607     } else if (state & NK_WIDGET_STATE_HOVER) {
17608         background = &style->hover;
17609         text.text = style->label_hover;
17610     } else {
17611         background = &style->normal;
17612         text.text = style->label_normal;
17613     }
17614 
17615     /* draw background */
17616     if (background->type == NK_STYLE_ITEM_IMAGE) {
17617         nk_draw_image(out, *bounds, &background->data.image, nk_white);
17618         text.background = nk_rgba(0,0,0,0);
17619     } else {
17620         text.background = background->data.color;
17621         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
17622         nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
17623     }
17624 
17625     /* draw label */
17626     text.padding = nk_vec2(0,0);
17627     nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
17628 }
17629 
17630 NK_INTERN void
17631 nk_do_property(nk_flags *ws,
17632     struct nk_command_buffer *out, struct nk_rect property,
17633     const char *name, struct nk_property_variant *variant,
17634     float inc_per_pixel, char *buffer, int *len,
17635     int *state, int *cursor, int *select_begin, int *select_end,
17636     const struct nk_style_property *style,
17637     enum nk_property_filter filter, struct nk_input *in,
17638     const struct nk_user_font *font, struct nk_text_edit *text_edit,
17639     enum nk_button_behavior behavior)
17640 {
17641     const nk_plugin_filter filters[] = {
17642         nk_filter_decimal,
17643         nk_filter_float
17644     };
17645     int active, old;
17646     int num_len, name_len;
17647     char string[NK_MAX_NUMBER_BUFFER];
17648     float size;
17649 
17650     char *dst = 0;
17651     int *length;
17652 
17653     struct nk_rect left;
17654     struct nk_rect right;
17655     struct nk_rect label;
17656     struct nk_rect edit;
17657     struct nk_rect empty;
17658 
17659     /* left decrement button */
17660     left.h = font->height/2;
17661     left.w = left.h;
17662     left.x = property.x + style->border + style->padding.x;
17663     left.y = property.y + style->border + property.h/2.0f - left.h/2;
17664 
17665     /* text label */
17666     name_len = nk_strlen(name);
17667     size = font->width(font->userdata, font->height, name, name_len);
17668     label.x = left.x + left.w + style->padding.x;
17669     label.w = (float)size + 2 * style->padding.x;
17670     label.y = property.y + style->border + style->padding.y;
17671     label.h = property.h - (2 * style->border + 2 * style->padding.y);
17672 
17673     /* right increment button */
17674     right.y = left.y;
17675     right.w = left.w;
17676     right.h = left.h;
17677     right.x = property.x + property.w - (right.w + style->padding.x);
17678 
17679     /* edit */
17680     if (*state == NK_PROPERTY_EDIT) {
17681         size = font->width(font->userdata, font->height, buffer, *len);
17682         size += style->edit.cursor_size;
17683         length = len;
17684         dst = buffer;
17685     } else {
17686         switch (variant->kind) {
17687         default: break;
17688         case NK_PROPERTY_INT:
17689             nk_itoa(string, variant->value.i);
17690             num_len = nk_strlen(string);
17691             break;
17692         case NK_PROPERTY_FLOAT:
17693             NK_DTOA(string, (double)variant->value.f);
17694             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
17695             break;
17696         case NK_PROPERTY_DOUBLE:
17697             NK_DTOA(string, variant->value.d);
17698             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
17699             break;
17700         }
17701         size = font->width(font->userdata, font->height, string, num_len);
17702         dst = string;
17703         length = &num_len;
17704     }
17705 
17706     edit.w =  (float)size + 2 * style->padding.x;
17707     edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
17708     edit.x = right.x - (edit.w + style->padding.x);
17709     edit.y = property.y + style->border;
17710     edit.h = property.h - (2 * style->border);
17711 
17712     /* empty left space activator */
17713     empty.w = edit.x - (label.x + label.w);
17714     empty.x = label.x + label.w;
17715     empty.y = property.y;
17716     empty.h = property.h;
17717 
17718     /* update property */
17719     old = (*state == NK_PROPERTY_EDIT);
17720     nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
17721 
17722     /* draw property */
17723     if (style->draw_begin) style->draw_begin(out, style->userdata);
17724     nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
17725     if (style->draw_end) style->draw_end(out, style->userdata);
17726 
17727     /* execute right button  */
17728     if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
17729         switch (variant->kind) {
17730         default: break;
17731         case NK_PROPERTY_INT:
17732             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
17733         case NK_PROPERTY_FLOAT:
17734             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
17735         case NK_PROPERTY_DOUBLE:
17736             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
17737         }
17738     }
17739     /* execute left button  */
17740     if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
17741         switch (variant->kind) {
17742         default: break;
17743         case NK_PROPERTY_INT:
17744             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
17745         case NK_PROPERTY_FLOAT:
17746             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
17747         case NK_PROPERTY_DOUBLE:
17748             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
17749         }
17750     }
17751     if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
17752         /* property has been activated so setup buffer */
17753         NK_MEMCPY(buffer, dst, (nk_size)*length);
17754         *cursor = nk_utf_len(buffer, *length);
17755         *len = *length;
17756         length = len;
17757         dst = buffer;
17758         active = 0;
17759     } else active = (*state == NK_PROPERTY_EDIT);
17760 
17761     /* execute and run text edit field */
17762     nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
17763     text_edit->active = (unsigned char)active;
17764     text_edit->string.len = *length;
17765     text_edit->cursor = NK_CLAMP(0, *cursor, *length);
17766     text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
17767     text_edit->select_end = NK_CLAMP(0,*select_end, *length);
17768     text_edit->string.buffer.allocated = (nk_size)*length;
17769     text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER;
17770     text_edit->string.buffer.memory.ptr = dst;
17771     text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
17772     text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
17773     nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
17774         filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
17775 
17776     *length = text_edit->string.len;
17777     *cursor = text_edit->cursor;
17778     *select_begin = text_edit->select_start;
17779     *select_end = text_edit->select_end;
17780     if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
17781         text_edit->active = nk_false;
17782 
17783     if (active && !text_edit->active) {
17784         /* property is now not active so convert edit text to value*/
17785         *state = NK_PROPERTY_DEFAULT;
17786         buffer[*len] = '\0';
17787         switch (variant->kind) {
17788         default: break;
17789         case NK_PROPERTY_INT:
17790             variant->value.i = nk_strtoi(buffer, 0);
17791             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
17792             break;
17793         case NK_PROPERTY_FLOAT:
17794             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
17795             variant->value.f = nk_strtof(buffer, 0);
17796             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
17797             break;
17798         case NK_PROPERTY_DOUBLE:
17799             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
17800             variant->value.d = nk_strtod(buffer, 0);
17801             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
17802             break;
17803         }
17804     }
17805 }
17806 /* ===============================================================
17807  *
17808  *                          COLOR PICKER
17809  *
17810  * ===============================================================*/
17811 NK_INTERN int
17812 nk_color_picker_behavior(nk_flags *state,
17813     const struct nk_rect *bounds, const struct nk_rect *matrix,
17814     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
17815     struct nk_colorf *color, const struct nk_input *in)
17816 {
17817     float hsva[4];
17818     int value_changed = 0;
17819     int hsv_changed = 0;
17820 
17821     NK_ASSERT(state);
17822     NK_ASSERT(matrix);
17823     NK_ASSERT(hue_bar);
17824     NK_ASSERT(color);
17825 
17826     /* color matrix */
17827     nk_colorf_hsva_fv(hsva, *color);
17828     if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
17829         hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
17830         hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
17831         value_changed = hsv_changed = 1;
17832     }
17833     /* hue bar */
17834     if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
17835         hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
17836         value_changed = hsv_changed = 1;
17837     }
17838     /* alpha bar */
17839     if (alpha_bar) {
17840         if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
17841             hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
17842             value_changed = 1;
17843         }
17844     }
17845     nk_widget_state_reset(state);
17846     if (hsv_changed) {
17847         *color = nk_hsva_colorfv(hsva);
17848         *state = NK_WIDGET_STATE_ACTIVE;
17849     }
17850     if (value_changed) {
17851         color->a = hsva[3];
17852         *state = NK_WIDGET_STATE_ACTIVE;
17853     }
17854     /* set color picker widget state */
17855     if (nk_input_is_mouse_hovering_rect(in, *bounds))
17856         *state = NK_WIDGET_STATE_HOVERED;
17857     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
17858         *state |= NK_WIDGET_STATE_ENTERED;
17859     else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
17860         *state |= NK_WIDGET_STATE_LEFT;
17861     return value_changed;
17862 }
17863 
17864 NK_INTERN void
17865 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
17866     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
17867     struct nk_colorf col)
17868 {
17869     NK_STORAGE const struct nk_color black = {0,0,0,255};
17870     NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
17871     NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
17872 
17873     const float crosshair_size = 7.0f;
17874     struct nk_color temp;
17875     float hsva[4];
17876     float line_y;
17877     int i;
17878 
17879     NK_ASSERT(o);
17880     NK_ASSERT(matrix);
17881     NK_ASSERT(hue_bar);
17882 
17883     /* draw hue bar */
17884     nk_colorf_hsva_fv(hsva, col);
17885     for (i = 0; i < 6; ++i) {
17886         NK_GLOBAL const struct nk_color hue_colors[] = {
17887             {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255},
17888             {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}
17889         };
17890         nk_fill_rect_multi_color(o,
17891             nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
17892                 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
17893                 hue_colors[i+1], hue_colors[i+1]);
17894     }
17895     line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
17896     nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
17897         line_y, 1, nk_rgb(255,255,255));
17898 
17899     /* draw alpha bar */
17900     if (alpha_bar) {
17901         float alpha = NK_SATURATE(col.a);
17902         line_y = (float)(int)(alpha_bar->y +  (1.0f - alpha) * matrix->h + 0.5f);
17903 
17904         nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
17905         nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
17906             line_y, 1, nk_rgb(255,255,255));
17907     }
17908 
17909     /* draw color matrix */
17910     temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
17911     nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
17912     nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
17913 
17914     /* draw cross-hair */
17915     {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
17916     p.x = (float)(int)(matrix->x + S * matrix->w);
17917     p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
17918     nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
17919     nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
17920     nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
17921     nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
17922 }
17923 
17924 NK_INTERN int
17925 nk_do_color_picker(nk_flags *state,
17926     struct nk_command_buffer *out, struct nk_colorf *col,
17927     enum nk_color_format fmt, struct nk_rect bounds,
17928     struct nk_vec2 padding, const struct nk_input *in,
17929     const struct nk_user_font *font)
17930 {
17931     int ret = 0;
17932     struct nk_rect matrix;
17933     struct nk_rect hue_bar;
17934     struct nk_rect alpha_bar;
17935     float bar_w;
17936 
17937     NK_ASSERT(out);
17938     NK_ASSERT(col);
17939     NK_ASSERT(state);
17940     NK_ASSERT(font);
17941     if (!out || !col || !state || !font)
17942         return ret;
17943 
17944     bar_w = font->height;
17945     bounds.x += padding.x;
17946     bounds.y += padding.x;
17947     bounds.w -= 2 * padding.x;
17948     bounds.h -= 2 * padding.y;
17949 
17950     matrix.x = bounds.x;
17951     matrix.y = bounds.y;
17952     matrix.h = bounds.h;
17953     matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
17954 
17955     hue_bar.w = bar_w;
17956     hue_bar.y = bounds.y;
17957     hue_bar.h = matrix.h;
17958     hue_bar.x = matrix.x + matrix.w + padding.x;
17959 
17960     alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
17961     alpha_bar.y = bounds.y;
17962     alpha_bar.w = bar_w;
17963     alpha_bar.h = matrix.h;
17964 
17965     ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
17966         (fmt == NK_RGBA) ? &alpha_bar:0, col, in);
17967     nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col);
17968     return ret;
17969 }
17970 
17971 /* ==============================================================
17972  *
17973  *                          STYLE
17974  *
17975  * ===============================================================*/
17976 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
17977 #define NK_COLOR_MAP(NK_COLOR)\
17978     NK_COLOR(NK_COLOR_TEXT,                 175,175,175,255) \
17979     NK_COLOR(NK_COLOR_WINDOW,               45, 45, 45, 255) \
17980     NK_COLOR(NK_COLOR_HEADER,               40, 40, 40, 255) \
17981     NK_COLOR(NK_COLOR_BORDER,               65, 65, 65, 255) \
17982     NK_COLOR(NK_COLOR_BUTTON,               50, 50, 50, 255) \
17983     NK_COLOR(NK_COLOR_BUTTON_HOVER,         40, 40, 40, 255) \
17984     NK_COLOR(NK_COLOR_BUTTON_ACTIVE,        35, 35, 35, 255) \
17985     NK_COLOR(NK_COLOR_TOGGLE,               100,100,100,255) \
17986     NK_COLOR(NK_COLOR_TOGGLE_HOVER,         120,120,120,255) \
17987     NK_COLOR(NK_COLOR_TOGGLE_CURSOR,        45, 45, 45, 255) \
17988     NK_COLOR(NK_COLOR_SELECT,               45, 45, 45, 255) \
17989     NK_COLOR(NK_COLOR_SELECT_ACTIVE,        35, 35, 35,255) \
17990     NK_COLOR(NK_COLOR_SLIDER,               38, 38, 38, 255) \
17991     NK_COLOR(NK_COLOR_SLIDER_CURSOR,        100,100,100,255) \
17992     NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER,  120,120,120,255) \
17993     NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
17994     NK_COLOR(NK_COLOR_PROPERTY,             38, 38, 38, 255) \
17995     NK_COLOR(NK_COLOR_EDIT,                 38, 38, 38, 255)  \
17996     NK_COLOR(NK_COLOR_EDIT_CURSOR,          175,175,175,255) \
17997     NK_COLOR(NK_COLOR_COMBO,                45, 45, 45, 255) \
17998     NK_COLOR(NK_COLOR_CHART,                120,120,120,255) \
17999     NK_COLOR(NK_COLOR_CHART_COLOR,          45, 45, 45, 255) \
18000     NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,255, 0,  0, 255) \
18001     NK_COLOR(NK_COLOR_SCROLLBAR,            40, 40, 40, 255) \
18002     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR,     100,100,100,255) \
18003     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,120,120,120,255) \
18004     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,150,150,150,255) \
18005     NK_COLOR(NK_COLOR_TAB_HEADER,           40, 40, 40,255)
18006 
18007 NK_GLOBAL const struct nk_color
18008 nk_default_color_style[NK_COLOR_COUNT] = {
18009 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
18010     NK_COLOR_MAP(NK_COLOR)
18011 #undef NK_COLOR
18012 };
18013 
18014 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
18015 #define NK_COLOR(a,b,c,d,e) #a,
18016     NK_COLOR_MAP(NK_COLOR)
18017 #undef NK_COLOR
18018 };
18019 
18020 NK_API const char *nk_style_get_color_by_name(enum nk_style_colors c)
18021 {return nk_color_names[c];}
18022 
18023 NK_API struct nk_style_item nk_style_item_image(struct nk_image img)
18024 {struct nk_style_item i; i.type = NK_STYLE_ITEM_IMAGE; i.data.image = img; return i;}
18025 
18026 NK_API struct nk_style_item nk_style_item_color(struct nk_color col)
18027 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = col; return i;}
18028 
18029 NK_API struct nk_style_item nk_style_item_hide(void)
18030 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = nk_rgba(0,0,0,0); return i;}
18031 
18032 NK_API void
18033 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
18034 {
18035     struct nk_style *style;
18036     struct nk_style_text *text;
18037     struct nk_style_button *button;
18038     struct nk_style_toggle *toggle;
18039     struct nk_style_selectable *select;
18040     struct nk_style_slider *slider;
18041     struct nk_style_progress *prog;
18042     struct nk_style_scrollbar *scroll;
18043     struct nk_style_edit *edit;
18044     struct nk_style_property *property;
18045     struct nk_style_combo *combo;
18046     struct nk_style_chart *chart;
18047     struct nk_style_tab *tab;
18048     struct nk_style_window *win;
18049 
18050     NK_ASSERT(ctx);
18051     if (!ctx) return;
18052     style = &ctx->style;
18053     table = (!table) ? nk_default_color_style: table;
18054 
18055     /* default text */
18056     text = &style->text;
18057     text->color = table[NK_COLOR_TEXT];
18058     text->padding = nk_vec2(0,0);
18059 
18060     /* default button */
18061     button = &style->button;
18062     nk_zero_struct(*button);
18063     button->normal          = nk_style_item_color(table[NK_COLOR_BUTTON]);
18064     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
18065     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
18066     button->border_color    = table[NK_COLOR_BORDER];
18067     button->text_background = table[NK_COLOR_BUTTON];
18068     button->text_normal     = table[NK_COLOR_TEXT];
18069     button->text_hover      = table[NK_COLOR_TEXT];
18070     button->text_active     = table[NK_COLOR_TEXT];
18071     button->padding         = nk_vec2(2.0f,2.0f);
18072     button->image_padding   = nk_vec2(0.0f,0.0f);
18073     button->touch_padding   = nk_vec2(0.0f, 0.0f);
18074     button->userdata        = nk_handle_ptr(0);
18075     button->text_alignment  = NK_TEXT_CENTERED;
18076     button->border          = 1.0f;
18077     button->rounding        = 4.0f;
18078     button->draw_begin      = 0;
18079     button->draw_end        = 0;
18080 
18081     /* contextual button */
18082     button = &style->contextual_button;
18083     nk_zero_struct(*button);
18084     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
18085     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
18086     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
18087     button->border_color    = table[NK_COLOR_WINDOW];
18088     button->text_background = table[NK_COLOR_WINDOW];
18089     button->text_normal     = table[NK_COLOR_TEXT];
18090     button->text_hover      = table[NK_COLOR_TEXT];
18091     button->text_active     = table[NK_COLOR_TEXT];
18092     button->padding         = nk_vec2(2.0f,2.0f);
18093     button->touch_padding   = nk_vec2(0.0f,0.0f);
18094     button->userdata        = nk_handle_ptr(0);
18095     button->text_alignment  = NK_TEXT_CENTERED;
18096     button->border          = 0.0f;
18097     button->rounding        = 0.0f;
18098     button->draw_begin      = 0;
18099     button->draw_end        = 0;
18100 
18101     /* menu button */
18102     button = &style->menu_button;
18103     nk_zero_struct(*button);
18104     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
18105     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
18106     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
18107     button->border_color    = table[NK_COLOR_WINDOW];
18108     button->text_background = table[NK_COLOR_WINDOW];
18109     button->text_normal     = table[NK_COLOR_TEXT];
18110     button->text_hover      = table[NK_COLOR_TEXT];
18111     button->text_active     = table[NK_COLOR_TEXT];
18112     button->padding         = nk_vec2(2.0f,2.0f);
18113     button->touch_padding   = nk_vec2(0.0f,0.0f);
18114     button->userdata        = nk_handle_ptr(0);
18115     button->text_alignment  = NK_TEXT_CENTERED;
18116     button->border          = 0.0f;
18117     button->rounding        = 1.0f;
18118     button->draw_begin      = 0;
18119     button->draw_end        = 0;
18120 
18121     /* checkbox toggle */
18122     toggle = &style->checkbox;
18123     nk_zero_struct(*toggle);
18124     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
18125     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
18126     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
18127     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
18128     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
18129     toggle->userdata        = nk_handle_ptr(0);
18130     toggle->text_background = table[NK_COLOR_WINDOW];
18131     toggle->text_normal     = table[NK_COLOR_TEXT];
18132     toggle->text_hover      = table[NK_COLOR_TEXT];
18133     toggle->text_active     = table[NK_COLOR_TEXT];
18134     toggle->padding         = nk_vec2(2.0f, 2.0f);
18135     toggle->touch_padding   = nk_vec2(0,0);
18136     toggle->border_color    = nk_rgba(0,0,0,0);
18137     toggle->border          = 0.0f;
18138     toggle->spacing         = 4;
18139 
18140     /* option toggle */
18141     toggle = &style->option;
18142     nk_zero_struct(*toggle);
18143     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
18144     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
18145     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
18146     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
18147     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
18148     toggle->userdata        = nk_handle_ptr(0);
18149     toggle->text_background = table[NK_COLOR_WINDOW];
18150     toggle->text_normal     = table[NK_COLOR_TEXT];
18151     toggle->text_hover      = table[NK_COLOR_TEXT];
18152     toggle->text_active     = table[NK_COLOR_TEXT];
18153     toggle->padding         = nk_vec2(3.0f, 3.0f);
18154     toggle->touch_padding   = nk_vec2(0,0);
18155     toggle->border_color    = nk_rgba(0,0,0,0);
18156     toggle->border          = 0.0f;
18157     toggle->spacing         = 4;
18158 
18159     /* selectable */
18160     select = &style->selectable;
18161     nk_zero_struct(*select);
18162     select->normal          = nk_style_item_color(table[NK_COLOR_SELECT]);
18163     select->hover           = nk_style_item_color(table[NK_COLOR_SELECT]);
18164     select->pressed         = nk_style_item_color(table[NK_COLOR_SELECT]);
18165     select->normal_active   = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
18166     select->hover_active    = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
18167     select->pressed_active  = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
18168     select->text_normal     = table[NK_COLOR_TEXT];
18169     select->text_hover      = table[NK_COLOR_TEXT];
18170     select->text_pressed    = table[NK_COLOR_TEXT];
18171     select->text_normal_active  = table[NK_COLOR_TEXT];
18172     select->text_hover_active   = table[NK_COLOR_TEXT];
18173     select->text_pressed_active = table[NK_COLOR_TEXT];
18174     select->padding         = nk_vec2(2.0f,2.0f);
18175     select->touch_padding   = nk_vec2(0,0);
18176     select->userdata        = nk_handle_ptr(0);
18177     select->rounding        = 0.0f;
18178     select->draw_begin      = 0;
18179     select->draw_end        = 0;
18180 
18181     /* slider */
18182     slider = &style->slider;
18183     nk_zero_struct(*slider);
18184     slider->normal          = nk_style_item_hide();
18185     slider->hover           = nk_style_item_hide();
18186     slider->active          = nk_style_item_hide();
18187     slider->bar_normal      = table[NK_COLOR_SLIDER];
18188     slider->bar_hover       = table[NK_COLOR_SLIDER];
18189     slider->bar_active      = table[NK_COLOR_SLIDER];
18190     slider->bar_filled      = table[NK_COLOR_SLIDER_CURSOR];
18191     slider->cursor_normal   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
18192     slider->cursor_hover    = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
18193     slider->cursor_active   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
18194     slider->inc_symbol      = NK_SYMBOL_TRIANGLE_RIGHT;
18195     slider->dec_symbol      = NK_SYMBOL_TRIANGLE_LEFT;
18196     slider->cursor_size     = nk_vec2(16,16);
18197     slider->padding         = nk_vec2(2,2);
18198     slider->spacing         = nk_vec2(2,2);
18199     slider->userdata        = nk_handle_ptr(0);
18200     slider->show_buttons    = nk_false;
18201     slider->bar_height      = 8;
18202     slider->rounding        = 0;
18203     slider->draw_begin      = 0;
18204     slider->draw_end        = 0;
18205 
18206     /* slider buttons */
18207     button = &style->slider.inc_button;
18208     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
18209     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
18210     button->active          = nk_style_item_color(nk_rgb(44,44,44));
18211     button->border_color    = nk_rgb(65,65,65);
18212     button->text_background = nk_rgb(40,40,40);
18213     button->text_normal     = nk_rgb(175,175,175);
18214     button->text_hover      = nk_rgb(175,175,175);
18215     button->text_active     = nk_rgb(175,175,175);
18216     button->padding         = nk_vec2(8.0f,8.0f);
18217     button->touch_padding   = nk_vec2(0.0f,0.0f);
18218     button->userdata        = nk_handle_ptr(0);
18219     button->text_alignment  = NK_TEXT_CENTERED;
18220     button->border          = 1.0f;
18221     button->rounding        = 0.0f;
18222     button->draw_begin      = 0;
18223     button->draw_end        = 0;
18224     style->slider.dec_button = style->slider.inc_button;
18225 
18226     /* progressbar */
18227     prog = &style->progress;
18228     nk_zero_struct(*prog);
18229     prog->normal            = nk_style_item_color(table[NK_COLOR_SLIDER]);
18230     prog->hover             = nk_style_item_color(table[NK_COLOR_SLIDER]);
18231     prog->active            = nk_style_item_color(table[NK_COLOR_SLIDER]);
18232     prog->cursor_normal     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
18233     prog->cursor_hover      = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
18234     prog->cursor_active     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
18235     prog->border_color      = nk_rgba(0,0,0,0);
18236     prog->cursor_border_color = nk_rgba(0,0,0,0);
18237     prog->userdata          = nk_handle_ptr(0);
18238     prog->padding           = nk_vec2(4,4);
18239     prog->rounding          = 0;
18240     prog->border            = 0;
18241     prog->cursor_rounding   = 0;
18242     prog->cursor_border     = 0;
18243     prog->draw_begin        = 0;
18244     prog->draw_end          = 0;
18245 
18246     /* scrollbars */
18247     scroll = &style->scrollh;
18248     nk_zero_struct(*scroll);
18249     scroll->normal          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
18250     scroll->hover           = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
18251     scroll->active          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
18252     scroll->cursor_normal   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]);
18253     scroll->cursor_hover    = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]);
18254     scroll->cursor_active   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]);
18255     scroll->dec_symbol      = NK_SYMBOL_CIRCLE_SOLID;
18256     scroll->inc_symbol      = NK_SYMBOL_CIRCLE_SOLID;
18257     scroll->userdata        = nk_handle_ptr(0);
18258     scroll->border_color    = table[NK_COLOR_SCROLLBAR];
18259     scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
18260     scroll->padding         = nk_vec2(0,0);
18261     scroll->show_buttons    = nk_false;
18262     scroll->border          = 0;
18263     scroll->rounding        = 0;
18264     scroll->border_cursor   = 0;
18265     scroll->rounding_cursor = 0;
18266     scroll->draw_begin      = 0;
18267     scroll->draw_end        = 0;
18268     style->scrollv = style->scrollh;
18269 
18270     /* scrollbars buttons */
18271     button = &style->scrollh.inc_button;
18272     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
18273     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
18274     button->active          = nk_style_item_color(nk_rgb(44,44,44));
18275     button->border_color    = nk_rgb(65,65,65);
18276     button->text_background = nk_rgb(40,40,40);
18277     button->text_normal     = nk_rgb(175,175,175);
18278     button->text_hover      = nk_rgb(175,175,175);
18279     button->text_active     = nk_rgb(175,175,175);
18280     button->padding         = nk_vec2(4.0f,4.0f);
18281     button->touch_padding   = nk_vec2(0.0f,0.0f);
18282     button->userdata        = nk_handle_ptr(0);
18283     button->text_alignment  = NK_TEXT_CENTERED;
18284     button->border          = 1.0f;
18285     button->rounding        = 0.0f;
18286     button->draw_begin      = 0;
18287     button->draw_end        = 0;
18288     style->scrollh.dec_button = style->scrollh.inc_button;
18289     style->scrollv.inc_button = style->scrollh.inc_button;
18290     style->scrollv.dec_button = style->scrollh.inc_button;
18291 
18292     /* edit */
18293     edit = &style->edit;
18294     nk_zero_struct(*edit);
18295     edit->normal            = nk_style_item_color(table[NK_COLOR_EDIT]);
18296     edit->hover             = nk_style_item_color(table[NK_COLOR_EDIT]);
18297     edit->active            = nk_style_item_color(table[NK_COLOR_EDIT]);
18298     edit->cursor_normal     = table[NK_COLOR_TEXT];
18299     edit->cursor_hover      = table[NK_COLOR_TEXT];
18300     edit->cursor_text_normal= table[NK_COLOR_EDIT];
18301     edit->cursor_text_hover = table[NK_COLOR_EDIT];
18302     edit->border_color      = table[NK_COLOR_BORDER];
18303     edit->text_normal       = table[NK_COLOR_TEXT];
18304     edit->text_hover        = table[NK_COLOR_TEXT];
18305     edit->text_active       = table[NK_COLOR_TEXT];
18306     edit->selected_normal   = table[NK_COLOR_TEXT];
18307     edit->selected_hover    = table[NK_COLOR_TEXT];
18308     edit->selected_text_normal  = table[NK_COLOR_EDIT];
18309     edit->selected_text_hover   = table[NK_COLOR_EDIT];
18310     edit->scrollbar_size    = nk_vec2(10,10);
18311     edit->scrollbar         = style->scrollv;
18312     edit->padding           = nk_vec2(4,4);
18313     edit->row_padding       = 2;
18314     edit->cursor_size       = 4;
18315     edit->border            = 1;
18316     edit->rounding          = 0;
18317 
18318     /* property */
18319     property = &style->property;
18320     nk_zero_struct(*property);
18321     property->normal        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18322     property->hover         = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18323     property->active        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18324     property->border_color  = table[NK_COLOR_BORDER];
18325     property->label_normal  = table[NK_COLOR_TEXT];
18326     property->label_hover   = table[NK_COLOR_TEXT];
18327     property->label_active  = table[NK_COLOR_TEXT];
18328     property->sym_left      = NK_SYMBOL_TRIANGLE_LEFT;
18329     property->sym_right     = NK_SYMBOL_TRIANGLE_RIGHT;
18330     property->userdata      = nk_handle_ptr(0);
18331     property->padding       = nk_vec2(4,4);
18332     property->border        = 1;
18333     property->rounding      = 10;
18334     property->draw_begin    = 0;
18335     property->draw_end      = 0;
18336 
18337     /* property buttons */
18338     button = &style->property.dec_button;
18339     nk_zero_struct(*button);
18340     button->normal          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18341     button->hover           = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18342     button->active          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18343     button->border_color    = nk_rgba(0,0,0,0);
18344     button->text_background = table[NK_COLOR_PROPERTY];
18345     button->text_normal     = table[NK_COLOR_TEXT];
18346     button->text_hover      = table[NK_COLOR_TEXT];
18347     button->text_active     = table[NK_COLOR_TEXT];
18348     button->padding         = nk_vec2(0.0f,0.0f);
18349     button->touch_padding   = nk_vec2(0.0f,0.0f);
18350     button->userdata        = nk_handle_ptr(0);
18351     button->text_alignment  = NK_TEXT_CENTERED;
18352     button->border          = 0.0f;
18353     button->rounding        = 0.0f;
18354     button->draw_begin      = 0;
18355     button->draw_end        = 0;
18356     style->property.inc_button = style->property.dec_button;
18357 
18358     /* property edit */
18359     edit = &style->property.edit;
18360     nk_zero_struct(*edit);
18361     edit->normal            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18362     edit->hover             = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18363     edit->active            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
18364     edit->border_color      = nk_rgba(0,0,0,0);
18365     edit->cursor_normal     = table[NK_COLOR_TEXT];
18366     edit->cursor_hover      = table[NK_COLOR_TEXT];
18367     edit->cursor_text_normal= table[NK_COLOR_EDIT];
18368     edit->cursor_text_hover = table[NK_COLOR_EDIT];
18369     edit->text_normal       = table[NK_COLOR_TEXT];
18370     edit->text_hover        = table[NK_COLOR_TEXT];
18371     edit->text_active       = table[NK_COLOR_TEXT];
18372     edit->selected_normal   = table[NK_COLOR_TEXT];
18373     edit->selected_hover    = table[NK_COLOR_TEXT];
18374     edit->selected_text_normal  = table[NK_COLOR_EDIT];
18375     edit->selected_text_hover   = table[NK_COLOR_EDIT];
18376     edit->padding           = nk_vec2(0,0);
18377     edit->cursor_size       = 8;
18378     edit->border            = 0;
18379     edit->rounding          = 0;
18380 
18381     /* chart */
18382     chart = &style->chart;
18383     nk_zero_struct(*chart);
18384     chart->background       = nk_style_item_color(table[NK_COLOR_CHART]);
18385     chart->border_color     = table[NK_COLOR_BORDER];
18386     chart->selected_color   = table[NK_COLOR_CHART_COLOR_HIGHLIGHT];
18387     chart->color            = table[NK_COLOR_CHART_COLOR];
18388     chart->padding          = nk_vec2(4,4);
18389     chart->border           = 0;
18390     chart->rounding         = 0;
18391 
18392     /* combo */
18393     combo = &style->combo;
18394     combo->normal           = nk_style_item_color(table[NK_COLOR_COMBO]);
18395     combo->hover            = nk_style_item_color(table[NK_COLOR_COMBO]);
18396     combo->active           = nk_style_item_color(table[NK_COLOR_COMBO]);
18397     combo->border_color     = table[NK_COLOR_BORDER];
18398     combo->label_normal     = table[NK_COLOR_TEXT];
18399     combo->label_hover      = table[NK_COLOR_TEXT];
18400     combo->label_active     = table[NK_COLOR_TEXT];
18401     combo->sym_normal       = NK_SYMBOL_TRIANGLE_DOWN;
18402     combo->sym_hover        = NK_SYMBOL_TRIANGLE_DOWN;
18403     combo->sym_active       = NK_SYMBOL_TRIANGLE_DOWN;
18404     combo->content_padding  = nk_vec2(4,4);
18405     combo->button_padding   = nk_vec2(0,4);
18406     combo->spacing          = nk_vec2(4,0);
18407     combo->border           = 1;
18408     combo->rounding         = 0;
18409 
18410     /* combo button */
18411     button = &style->combo.button;
18412     nk_zero_struct(*button);
18413     button->normal          = nk_style_item_color(table[NK_COLOR_COMBO]);
18414     button->hover           = nk_style_item_color(table[NK_COLOR_COMBO]);
18415     button->active          = nk_style_item_color(table[NK_COLOR_COMBO]);
18416     button->border_color    = nk_rgba(0,0,0,0);
18417     button->text_background = table[NK_COLOR_COMBO];
18418     button->text_normal     = table[NK_COLOR_TEXT];
18419     button->text_hover      = table[NK_COLOR_TEXT];
18420     button->text_active     = table[NK_COLOR_TEXT];
18421     button->padding         = nk_vec2(2.0f,2.0f);
18422     button->touch_padding   = nk_vec2(0.0f,0.0f);
18423     button->userdata        = nk_handle_ptr(0);
18424     button->text_alignment  = NK_TEXT_CENTERED;
18425     button->border          = 0.0f;
18426     button->rounding        = 0.0f;
18427     button->draw_begin      = 0;
18428     button->draw_end        = 0;
18429 
18430     /* tab */
18431     tab = &style->tab;
18432     tab->background         = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
18433     tab->border_color       = table[NK_COLOR_BORDER];
18434     tab->text               = table[NK_COLOR_TEXT];
18435     tab->sym_minimize       = NK_SYMBOL_TRIANGLE_RIGHT;
18436     tab->sym_maximize       = NK_SYMBOL_TRIANGLE_DOWN;
18437     tab->padding            = nk_vec2(4,4);
18438     tab->spacing            = nk_vec2(4,4);
18439     tab->indent             = 10.0f;
18440     tab->border             = 1;
18441     tab->rounding           = 0;
18442 
18443     /* tab button */
18444     button = &style->tab.tab_minimize_button;
18445     nk_zero_struct(*button);
18446     button->normal          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
18447     button->hover           = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
18448     button->active          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
18449     button->border_color    = nk_rgba(0,0,0,0);
18450     button->text_background = table[NK_COLOR_TAB_HEADER];
18451     button->text_normal     = table[NK_COLOR_TEXT];
18452     button->text_hover      = table[NK_COLOR_TEXT];
18453     button->text_active     = table[NK_COLOR_TEXT];
18454     button->padding         = nk_vec2(2.0f,2.0f);
18455     button->touch_padding   = nk_vec2(0.0f,0.0f);
18456     button->userdata        = nk_handle_ptr(0);
18457     button->text_alignment  = NK_TEXT_CENTERED;
18458     button->border          = 0.0f;
18459     button->rounding        = 0.0f;
18460     button->draw_begin      = 0;
18461     button->draw_end        = 0;
18462     style->tab.tab_maximize_button =*button;
18463 
18464     /* node button */
18465     button = &style->tab.node_minimize_button;
18466     nk_zero_struct(*button);
18467     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
18468     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
18469     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
18470     button->border_color    = nk_rgba(0,0,0,0);
18471     button->text_background = table[NK_COLOR_TAB_HEADER];
18472     button->text_normal     = table[NK_COLOR_TEXT];
18473     button->text_hover      = table[NK_COLOR_TEXT];
18474     button->text_active     = table[NK_COLOR_TEXT];
18475     button->padding         = nk_vec2(2.0f,2.0f);
18476     button->touch_padding   = nk_vec2(0.0f,0.0f);
18477     button->userdata        = nk_handle_ptr(0);
18478     button->text_alignment  = NK_TEXT_CENTERED;
18479     button->border          = 0.0f;
18480     button->rounding        = 0.0f;
18481     button->draw_begin      = 0;
18482     button->draw_end        = 0;
18483     style->tab.node_maximize_button =*button;
18484 
18485     /* window header */
18486     win = &style->window;
18487     win->header.align = NK_HEADER_RIGHT;
18488     win->header.close_symbol = NK_SYMBOL_X;
18489     win->header.minimize_symbol = NK_SYMBOL_MINUS;
18490     win->header.maximize_symbol = NK_SYMBOL_PLUS;
18491     win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]);
18492     win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]);
18493     win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]);
18494     win->header.label_normal = table[NK_COLOR_TEXT];
18495     win->header.label_hover = table[NK_COLOR_TEXT];
18496     win->header.label_active = table[NK_COLOR_TEXT];
18497     win->header.label_padding = nk_vec2(4,4);
18498     win->header.padding = nk_vec2(4,4);
18499     win->header.spacing = nk_vec2(0,0);
18500 
18501     /* window header close button */
18502     button = &style->window.header.close_button;
18503     nk_zero_struct(*button);
18504     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
18505     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
18506     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
18507     button->border_color    = nk_rgba(0,0,0,0);
18508     button->text_background = table[NK_COLOR_HEADER];
18509     button->text_normal     = table[NK_COLOR_TEXT];
18510     button->text_hover      = table[NK_COLOR_TEXT];
18511     button->text_active     = table[NK_COLOR_TEXT];
18512     button->padding         = nk_vec2(0.0f,0.0f);
18513     button->touch_padding   = nk_vec2(0.0f,0.0f);
18514     button->userdata        = nk_handle_ptr(0);
18515     button->text_alignment  = NK_TEXT_CENTERED;
18516     button->border          = 0.0f;
18517     button->rounding        = 0.0f;
18518     button->draw_begin      = 0;
18519     button->draw_end        = 0;
18520 
18521     /* window header minimize button */
18522     button = &style->window.header.minimize_button;
18523     nk_zero_struct(*button);
18524     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
18525     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
18526     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
18527     button->border_color    = nk_rgba(0,0,0,0);
18528     button->text_background = table[NK_COLOR_HEADER];
18529     button->text_normal     = table[NK_COLOR_TEXT];
18530     button->text_hover      = table[NK_COLOR_TEXT];
18531     button->text_active     = table[NK_COLOR_TEXT];
18532     button->padding         = nk_vec2(0.0f,0.0f);
18533     button->touch_padding   = nk_vec2(0.0f,0.0f);
18534     button->userdata        = nk_handle_ptr(0);
18535     button->text_alignment  = NK_TEXT_CENTERED;
18536     button->border          = 0.0f;
18537     button->rounding        = 0.0f;
18538     button->draw_begin      = 0;
18539     button->draw_end        = 0;
18540 
18541     /* window */
18542     win->background = table[NK_COLOR_WINDOW];
18543     win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]);
18544     win->border_color = table[NK_COLOR_BORDER];
18545     win->popup_border_color = table[NK_COLOR_BORDER];
18546     win->combo_border_color = table[NK_COLOR_BORDER];
18547     win->contextual_border_color = table[NK_COLOR_BORDER];
18548     win->menu_border_color = table[NK_COLOR_BORDER];
18549     win->group_border_color = table[NK_COLOR_BORDER];
18550     win->tooltip_border_color = table[NK_COLOR_BORDER];
18551     win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
18552 
18553     win->rounding = 0.0f;
18554     win->spacing = nk_vec2(4,4);
18555     win->scrollbar_size = nk_vec2(10,10);
18556     win->min_size = nk_vec2(64,64);
18557 
18558     win->combo_border = 1.0f;
18559     win->contextual_border = 1.0f;
18560     win->menu_border = 1.0f;
18561     win->group_border = 1.0f;
18562     win->tooltip_border = 1.0f;
18563     win->popup_border = 1.0f;
18564     win->border = 2.0f;
18565     win->min_row_height_padding = 8;
18566 
18567     win->padding = nk_vec2(4,4);
18568     win->group_padding = nk_vec2(4,4);
18569     win->popup_padding = nk_vec2(4,4);
18570     win->combo_padding = nk_vec2(4,4);
18571     win->contextual_padding = nk_vec2(4,4);
18572     win->menu_padding = nk_vec2(4,4);
18573     win->tooltip_padding = nk_vec2(4,4);
18574 }
18575 
18576 NK_API void
18577 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
18578 {
18579     struct nk_style *style;
18580     NK_ASSERT(ctx);
18581 
18582     if (!ctx) return;
18583     style = &ctx->style;
18584     style->font = font;
18585     ctx->stacks.fonts.head = 0;
18586     if (ctx->current)
18587         nk_layout_reset_min_row_height(ctx);
18588 }
18589 
18590 NK_API int
18591 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
18592 {
18593     struct nk_config_stack_user_font *font_stack;
18594     struct nk_config_stack_user_font_element *element;
18595 
18596     NK_ASSERT(ctx);
18597     if (!ctx) return 0;
18598 
18599     font_stack = &ctx->stacks.fonts;
18600     NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
18601     if (font_stack->head >= (int)NK_LEN(font_stack->elements))
18602         return 0;
18603 
18604     element = &font_stack->elements[font_stack->head++];
18605     element->address = &ctx->style.font;
18606     element->old_value = ctx->style.font;
18607     ctx->style.font = font;
18608     return 1;
18609 }
18610 
18611 NK_API int
18612 nk_style_pop_font(struct nk_context *ctx)
18613 {
18614     struct nk_config_stack_user_font *font_stack;
18615     struct nk_config_stack_user_font_element *element;
18616 
18617     NK_ASSERT(ctx);
18618     if (!ctx) return 0;
18619 
18620     font_stack = &ctx->stacks.fonts;
18621     NK_ASSERT(font_stack->head > 0);
18622     if (font_stack->head < 1)
18623         return 0;
18624 
18625     element = &font_stack->elements[--font_stack->head];
18626     *element->address = element->old_value;
18627     return 1;
18628 }
18629 
18630 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
18631 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
18632 {\
18633     struct nk_config_stack_##type * type_stack;\
18634     struct nk_config_stack_##type##_element *element;\
18635     NK_ASSERT(ctx);\
18636     if (!ctx) return 0;\
18637     type_stack = &ctx->stacks.stack;\
18638     NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
18639     if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
18640         return 0;\
18641     element = &type_stack->elements[type_stack->head++];\
18642     element->address = address;\
18643     element->old_value = *address;\
18644     *address = value;\
18645     return 1;\
18646 }
18647 
18648 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
18649 nk_style_pop_##type(struct nk_context *ctx)\
18650 {\
18651     struct nk_config_stack_##type *type_stack;\
18652     struct nk_config_stack_##type##_element *element;\
18653     NK_ASSERT(ctx);\
18654     if (!ctx) return 0;\
18655     type_stack = &ctx->stacks.stack;\
18656     NK_ASSERT(type_stack->head > 0);\
18657     if (type_stack->head < 1)\
18658         return 0;\
18659     element = &type_stack->elements[--type_stack->head];\
18660     *element->address = element->old_value;\
18661     return 1;\
18662 }
18663 
18664 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
18665 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
18666 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
18667 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
18668 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
18669 
18670 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
18671 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
18672 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
18673 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
18674 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
18675 
18676 NK_API int
18677 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
18678 {
18679     struct nk_style *style;
18680     NK_ASSERT(ctx);
18681     if (!ctx) return 0;
18682     style = &ctx->style;
18683     if (style->cursors[c]) {
18684         style->cursor_active = style->cursors[c];
18685         return 1;
18686     }
18687     return 0;
18688 }
18689 
18690 NK_API void
18691 nk_style_show_cursor(struct nk_context *ctx)
18692 {
18693     ctx->style.cursor_visible = nk_true;
18694 }
18695 
18696 NK_API void
18697 nk_style_hide_cursor(struct nk_context *ctx)
18698 {
18699     ctx->style.cursor_visible = nk_false;
18700 }
18701 
18702 NK_API void
18703 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
18704     const struct nk_cursor *c)
18705 {
18706     struct nk_style *style;
18707     NK_ASSERT(ctx);
18708     if (!ctx) return;
18709     style = &ctx->style;
18710     style->cursors[cursor] = c;
18711 }
18712 
18713 NK_API void
18714 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors)
18715 {
18716     int i = 0;
18717     struct nk_style *style;
18718     NK_ASSERT(ctx);
18719     if (!ctx) return;
18720     style = &ctx->style;
18721     for (i = 0; i < NK_CURSOR_COUNT; ++i)
18722         style->cursors[i] = &cursors[i];
18723     style->cursor_visible = nk_true;
18724 }
18725 
18726 /* ===============================================================
18727  *
18728  *                          POOL
18729  *
18730  * ===============================================================*/
18731 NK_INTERN void
18732 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
18733     unsigned int capacity)
18734 {
18735     nk_zero(pool, sizeof(*pool));
18736     pool->alloc = *alloc;
18737     pool->capacity = capacity;
18738     pool->type = NK_BUFFER_DYNAMIC;
18739     pool->pages = 0;
18740 }
18741 
18742 NK_INTERN void
18743 nk_pool_free(struct nk_pool *pool)
18744 {
18745     struct nk_page *iter = pool->pages;
18746     if (!pool) return;
18747     if (pool->type == NK_BUFFER_FIXED) return;
18748     while (iter) {
18749         struct nk_page *next = iter->next;
18750         pool->alloc.free(pool->alloc.userdata, iter);
18751         iter = next;
18752     }
18753 }
18754 
18755 NK_INTERN void
18756 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
18757 {
18758     nk_zero(pool, sizeof(*pool));
18759     NK_ASSERT(size >= sizeof(struct nk_page));
18760     if (size < sizeof(struct nk_page)) return;
18761     pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
18762     pool->pages = (struct nk_page*)memory;
18763     pool->type = NK_BUFFER_FIXED;
18764     pool->size = size;
18765 }
18766 
18767 NK_INTERN struct nk_page_element*
18768 nk_pool_alloc(struct nk_pool *pool)
18769 {
18770     if (!pool->pages || pool->pages->size >= pool->capacity) {
18771         /* allocate new page */
18772         struct nk_page *page;
18773         if (pool->type == NK_BUFFER_FIXED) {
18774             if (!pool->pages) {
18775                 NK_ASSERT(pool->pages);
18776                 return 0;
18777             }
18778             NK_ASSERT(pool->pages->size < pool->capacity);
18779             return 0;
18780         } else {
18781             nk_size size = sizeof(struct nk_page);
18782             size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
18783             page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
18784             page->next = pool->pages;
18785             pool->pages = page;
18786             page->size = 0;
18787         }
18788     }
18789     return &pool->pages->win[pool->pages->size++];
18790 }
18791 
18792 /* ===============================================================
18793  *
18794  *                          CONTEXT
18795  *
18796  * ===============================================================*/
18797 NK_INTERN void* nk_create_window(struct nk_context *ctx);
18798 NK_INTERN void nk_remove_window(struct nk_context*, struct nk_window*);
18799 NK_INTERN void nk_free_window(struct nk_context *ctx, struct nk_window *win);
18800 NK_INTERN void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
18801 NK_INTERN void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
18802 NK_INTERN void* nk_create_panel(struct nk_context *ctx);
18803 NK_INTERN void nk_free_panel(struct nk_context*, struct nk_panel *pan);
18804 
18805 NK_INTERN void
18806 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
18807 {
18808     NK_ASSERT(ctx);
18809     if (!ctx) return;
18810     nk_zero_struct(*ctx);
18811     nk_style_default(ctx);
18812     ctx->seq = 1;
18813     if (font) ctx->style.font = font;
18814 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
18815     nk_draw_list_init(&ctx->draw_list);
18816 #endif
18817 }
18818 
18819 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
18820 NK_API int
18821 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
18822 {
18823     struct nk_allocator alloc;
18824     alloc.userdata.ptr = 0;
18825     alloc.alloc = nk_malloc;
18826     alloc.free = nk_mfree;
18827     return nk_init(ctx, &alloc, font);
18828 }
18829 #endif
18830 
18831 NK_API int
18832 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
18833     const struct nk_user_font *font)
18834 {
18835     NK_ASSERT(memory);
18836     if (!memory) return 0;
18837     nk_setup(ctx, font);
18838     nk_buffer_init_fixed(&ctx->memory, memory, size);
18839     ctx->use_pool = nk_false;
18840     return 1;
18841 }
18842 
18843 NK_API int
18844 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
18845     struct nk_buffer *pool, const struct nk_user_font *font)
18846 {
18847     NK_ASSERT(cmds);
18848     NK_ASSERT(pool);
18849     if (!cmds || !pool) return 0;
18850 
18851     nk_setup(ctx, font);
18852     ctx->memory = *cmds;
18853     if (pool->type == NK_BUFFER_FIXED) {
18854         /* take memory from buffer and alloc fixed pool */
18855         nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
18856     } else {
18857         /* create dynamic pool from buffer allocator */
18858         struct nk_allocator *alloc = &pool->pool;
18859         nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
18860     }
18861     ctx->use_pool = nk_true;
18862     return 1;
18863 }
18864 
18865 NK_API int
18866 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
18867     const struct nk_user_font *font)
18868 {
18869     NK_ASSERT(alloc);
18870     if (!alloc) return 0;
18871     nk_setup(ctx, font);
18872     nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
18873     nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
18874     ctx->use_pool = nk_true;
18875     return 1;
18876 }
18877 
18878 #ifdef NK_INCLUDE_COMMAND_USERDATA
18879 NK_API void
18880 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
18881 {
18882     if (!ctx) return;
18883     ctx->userdata = handle;
18884     if (ctx->current)
18885         ctx->current->buffer.userdata = handle;
18886 }
18887 #endif
18888 
18889 NK_API void
18890 nk_free(struct nk_context *ctx)
18891 {
18892     NK_ASSERT(ctx);
18893     if (!ctx) return;
18894     nk_buffer_free(&ctx->memory);
18895     if (ctx->use_pool)
18896         nk_pool_free(&ctx->pool);
18897 
18898     nk_zero(&ctx->input, sizeof(ctx->input));
18899     nk_zero(&ctx->style, sizeof(ctx->style));
18900     nk_zero(&ctx->memory, sizeof(ctx->memory));
18901 
18902     ctx->seq = 0;
18903     ctx->build = 0;
18904     ctx->begin = 0;
18905     ctx->end = 0;
18906     ctx->active = 0;
18907     ctx->current = 0;
18908     ctx->freelist = 0;
18909     ctx->count = 0;
18910 }
18911 
18912 NK_API void
18913 nk_clear(struct nk_context *ctx)
18914 {
18915     struct nk_window *iter;
18916     struct nk_window *next;
18917     NK_ASSERT(ctx);
18918 
18919     if (!ctx) return;
18920     if (ctx->use_pool)
18921         nk_buffer_clear(&ctx->memory);
18922     else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
18923 
18924     ctx->build = 0;
18925     ctx->memory.calls = 0;
18926     ctx->last_widget_state = 0;
18927     ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
18928     NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
18929 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
18930     //nk_draw_list_clear(&ctx->draw_list);
18931 #endif
18932 
18933     /* garbage collector */
18934     iter = ctx->begin;
18935     while (iter) {
18936         /* make sure valid minimized windows do not get removed */
18937         if ((iter->flags & NK_WINDOW_MINIMIZED) &&
18938             !(iter->flags & NK_WINDOW_CLOSED) &&
18939             iter->seq == ctx->seq) {
18940             iter = iter->next;
18941             continue;
18942         }
18943         /* remove hotness from hidden or closed windows*/
18944         if (((iter->flags & NK_WINDOW_HIDDEN) ||
18945             (iter->flags & NK_WINDOW_CLOSED)) &&
18946             iter == ctx->active) {
18947             ctx->active = iter->prev;
18948             ctx->end = iter->prev;
18949             if (!ctx->end)
18950                 ctx->begin = 0;
18951             if (ctx->active)
18952                 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
18953         }
18954         /* free unused popup windows */
18955         if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
18956             nk_free_window(ctx, iter->popup.win);
18957             iter->popup.win = 0;
18958         }
18959         /* remove unused window state tables */
18960         {struct nk_table *n, *it = iter->tables;
18961         while (it) {
18962             n = it->next;
18963             if (it->seq != ctx->seq) {
18964                 nk_remove_table(iter, it);
18965                 nk_zero(it, sizeof(union nk_page_data));
18966                 nk_free_table(ctx, it);
18967                 if (it == iter->tables)
18968                     iter->tables = n;
18969             } it = n;
18970         }}
18971         /* window itself is not used anymore so free */
18972         if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
18973             next = iter->next;
18974             nk_remove_window(ctx, iter);
18975             nk_free_window(ctx, iter);
18976             iter = next;
18977         } else iter = iter->next;
18978     }
18979     ctx->seq++;
18980 }
18981 
18982 /* ----------------------------------------------------------------
18983  *
18984  *                          BUFFERING
18985  *
18986  * ---------------------------------------------------------------*/
18987 NK_INTERN void
18988 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
18989 {
18990     NK_ASSERT(ctx);
18991     NK_ASSERT(buffer);
18992     if (!ctx || !buffer) return;
18993     buffer->begin = ctx->memory.allocated;
18994     buffer->end = buffer->begin;
18995     buffer->last = buffer->begin;
18996     buffer->clip = nk_null_rect;
18997 }
18998 
18999 NK_INTERN void
19000 nk_start(struct nk_context *ctx, struct nk_window *win)
19001 {
19002     NK_ASSERT(ctx);
19003     NK_ASSERT(win);
19004     nk_start_buffer(ctx, &win->buffer);
19005 }
19006 
19007 NK_INTERN void
19008 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
19009 {
19010     struct nk_popup_buffer *buf;
19011     NK_ASSERT(ctx);
19012     NK_ASSERT(win);
19013     if (!ctx || !win) return;
19014 
19015     /* save buffer fill state for popup */
19016     buf = &win->popup.buf;
19017     buf->begin = win->buffer.end;
19018     buf->end = win->buffer.end;
19019     buf->parent = win->buffer.last;
19020     buf->last = buf->begin;
19021     buf->active = nk_true;
19022 }
19023 
19024 NK_INTERN void
19025 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
19026 {
19027     struct nk_popup_buffer *buf;
19028     NK_ASSERT(ctx);
19029     NK_ASSERT(win);
19030     if (!ctx || !win) return;
19031 
19032     buf = &win->popup.buf;
19033     buf->last = win->buffer.last;
19034     buf->end = win->buffer.end;
19035 }
19036 
19037 NK_INTERN void
19038 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
19039 {
19040     NK_ASSERT(ctx);
19041     NK_ASSERT(buffer);
19042     if (!ctx || !buffer) return;
19043     buffer->end = ctx->memory.allocated;
19044 }
19045 
19046 NK_INTERN void
19047 nk_finish(struct nk_context *ctx, struct nk_window *win)
19048 {
19049     struct nk_popup_buffer *buf;
19050     struct nk_command *parent_last;
19051     void *memory;
19052 
19053     NK_ASSERT(ctx);
19054     NK_ASSERT(win);
19055     if (!ctx || !win) return;
19056     nk_finish_buffer(ctx, &win->buffer);
19057     if (!win->popup.buf.active) return;
19058 
19059     buf = &win->popup.buf;
19060     memory = ctx->memory.memory.ptr;
19061     parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
19062     parent_last->next = buf->end;
19063 }
19064 
19065 NK_INTERN void
19066 nk_build(struct nk_context *ctx)
19067 {
19068     struct nk_window *it = 0;
19069     struct nk_command *cmd = 0;
19070     nk_byte *buffer = 0;
19071 
19072     /* draw cursor overlay */
19073     if (!ctx->style.cursor_active)
19074         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
19075     if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
19076         struct nk_rect mouse_bounds;
19077         const struct nk_cursor *cursor = ctx->style.cursor_active;
19078         nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
19079         nk_start_buffer(ctx, &ctx->overlay);
19080 
19081         mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
19082         mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
19083         mouse_bounds.w = cursor->size.x;
19084         mouse_bounds.h = cursor->size.y;
19085 
19086         nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
19087         nk_finish_buffer(ctx, &ctx->overlay);
19088     }
19089     /* build one big draw command list out of all window buffers */
19090     it = ctx->begin;
19091     buffer = (nk_byte*)ctx->memory.memory.ptr;
19092     while (it != 0) {
19093         struct nk_window *next = it->next;
19094         if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
19095             it->seq != ctx->seq)
19096             goto cont;
19097 
19098         cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
19099         while (next && ((next->buffer.last == next->buffer.begin) ||
19100             (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
19101             next = next->next; /* skip empty command buffers */
19102 
19103         if (next) cmd->next = next->buffer.begin;
19104         cont: it = next;
19105     }
19106     /* append all popup draw commands into lists */
19107     it = ctx->begin;
19108     while (it != 0) {
19109         struct nk_window *next = it->next;
19110         struct nk_popup_buffer *buf;
19111         if (!it->popup.buf.active)
19112             goto skip;
19113 
19114         buf = &it->popup.buf;
19115         cmd->next = buf->begin;
19116         cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
19117         buf->active = nk_false;
19118         skip: it = next;
19119     }
19120     if (cmd) {
19121         /* append overlay commands */
19122         if (ctx->overlay.end != ctx->overlay.begin)
19123             cmd->next = ctx->overlay.begin;
19124         else cmd->next = ctx->memory.allocated;
19125     }
19126 }
19127 
19128 NK_API const struct nk_command*
19129 nk__begin(struct nk_context *ctx)
19130 {
19131     struct nk_window *iter;
19132     nk_byte *buffer;
19133     NK_ASSERT(ctx);
19134     if (!ctx) return 0;
19135     if (!ctx->count) return 0;
19136 
19137     buffer = (nk_byte*)ctx->memory.memory.ptr;
19138     if (!ctx->build) {
19139         nk_build(ctx);
19140         ctx->build = nk_true;
19141     }
19142     iter = ctx->begin;
19143     while (iter && ((iter->buffer.begin == iter->buffer.end) ||
19144         (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
19145         iter = iter->next;
19146     if (!iter) return 0;
19147     return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
19148 }
19149 
19150 NK_API const struct nk_command*
19151 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
19152 {
19153     nk_byte *buffer;
19154     const struct nk_command *next;
19155     NK_ASSERT(ctx);
19156     if (!ctx || !cmd || !ctx->count) return 0;
19157     if (cmd->next >= ctx->memory.allocated) return 0;
19158     buffer = (nk_byte*)ctx->memory.memory.ptr;
19159     next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
19160     return next;
19161 }
19162 
19163 /* ----------------------------------------------------------------
19164  *
19165  *                          PANEL
19166  *
19167  * ---------------------------------------------------------------*/
19168 static int
19169 nk_panel_has_header(nk_flags flags, const char *title)
19170 {
19171     int active = 0;
19172     active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
19173     active = active || (flags & NK_WINDOW_TITLE);
19174     active = active && !(flags & NK_WINDOW_HIDDEN) && title;
19175     return active;
19176 }
19177 
19178 NK_INTERN struct nk_vec2
19179 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
19180 {
19181     switch (type) {
19182     default:
19183     case NK_PANEL_WINDOW: return style->window.padding;
19184     case NK_PANEL_GROUP: return style->window.group_padding;
19185     case NK_PANEL_POPUP: return style->window.popup_padding;
19186     case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
19187     case NK_PANEL_COMBO: return style->window.combo_padding;
19188     case NK_PANEL_MENU: return style->window.menu_padding;
19189     case NK_PANEL_TOOLTIP: return style->window.menu_padding;
19190     }
19191 }
19192 
19193 NK_INTERN float
19194 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
19195     enum nk_panel_type type)
19196 {
19197     if (flags & NK_WINDOW_BORDER) {
19198         switch (type) {
19199         default:
19200         case NK_PANEL_WINDOW: return style->window.border;
19201         case NK_PANEL_GROUP: return style->window.group_border;
19202         case NK_PANEL_POPUP: return style->window.popup_border;
19203         case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
19204         case NK_PANEL_COMBO: return style->window.combo_border;
19205         case NK_PANEL_MENU: return style->window.menu_border;
19206         case NK_PANEL_TOOLTIP: return style->window.menu_border;
19207     }} else return 0;
19208 }
19209 
19210 NK_INTERN struct nk_color
19211 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
19212 {
19213     switch (type) {
19214     default:
19215     case NK_PANEL_WINDOW: return style->window.border_color;
19216     case NK_PANEL_GROUP: return style->window.group_border_color;
19217     case NK_PANEL_POPUP: return style->window.popup_border_color;
19218     case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
19219     case NK_PANEL_COMBO: return style->window.combo_border_color;
19220     case NK_PANEL_MENU: return style->window.menu_border_color;
19221     case NK_PANEL_TOOLTIP: return style->window.menu_border_color;
19222     }
19223 }
19224 
19225 NK_INTERN int
19226 nk_panel_is_sub(enum nk_panel_type type)
19227 {
19228     return (type & NK_PANEL_SET_SUB)?1:0;
19229 }
19230 
19231 NK_INTERN int
19232 nk_panel_is_nonblock(enum nk_panel_type type)
19233 {
19234     return (type & NK_PANEL_SET_NONBLOCK)?1:0;
19235 }
19236 
19237 NK_INTERN int
19238 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
19239 {
19240     struct nk_input *in;
19241     struct nk_window *win;
19242     struct nk_panel *layout;
19243     struct nk_command_buffer *out;
19244     const struct nk_style *style;
19245     const struct nk_user_font *font;
19246 
19247     struct nk_vec2 scrollbar_size;
19248     struct nk_vec2 panel_padding;
19249 
19250     NK_ASSERT(ctx);
19251     NK_ASSERT(ctx->current);
19252     NK_ASSERT(ctx->current->layout);
19253     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
19254     nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
19255     if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
19256         nk_zero(ctx->current->layout, sizeof(struct nk_panel));
19257         ctx->current->layout->type = panel_type;
19258         return 0;
19259     }
19260     /* pull state into local stack */
19261     style = &ctx->style;
19262     font = style->font;
19263     win = ctx->current;
19264     layout = win->layout;
19265     out = &win->buffer;
19266     in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
19267 #ifdef NK_INCLUDE_COMMAND_USERDATA
19268     win->buffer.userdata = ctx->userdata;
19269 #endif
19270     /* pull style configuration into local stack */
19271     scrollbar_size = style->window.scrollbar_size;
19272     panel_padding = nk_panel_get_padding(style, panel_type);
19273 
19274     /* window movement */
19275     if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
19276         int left_mouse_down;
19277         int left_mouse_click_in_cursor;
19278 
19279         /* calculate draggable window space */
19280         struct nk_rect header;
19281         header.x = win->bounds.x;
19282         header.y = win->bounds.y;
19283         header.w = win->bounds.w;
19284         if (nk_panel_has_header(win->flags, title)) {
19285             header.h = font->height + 2.0f * style->window.header.padding.y;
19286             header.h += 2.0f * style->window.header.label_padding.y;
19287         } else header.h = panel_padding.y;
19288 
19289         /* window movement by dragging */
19290         left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
19291         left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
19292             NK_BUTTON_LEFT, header, nk_true);
19293         if (left_mouse_down && left_mouse_click_in_cursor) {
19294             win->bounds.x = win->bounds.x + in->mouse.delta.x;
19295             win->bounds.y = win->bounds.y + in->mouse.delta.y;
19296             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
19297             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
19298             ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
19299         }
19300     }
19301 
19302     /* setup panel */
19303     layout->type = panel_type;
19304     layout->flags = win->flags;
19305     layout->bounds = win->bounds;
19306     layout->bounds.x += panel_padding.x;
19307     layout->bounds.w -= 2*panel_padding.x;
19308     if (win->flags & NK_WINDOW_BORDER) {
19309         layout->border = nk_panel_get_border(style, win->flags, panel_type);
19310         layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
19311     } else layout->border = 0;
19312     layout->at_y = layout->bounds.y;
19313     layout->at_x = layout->bounds.x;
19314     layout->max_x = 0;
19315     layout->header_height = 0;
19316     layout->footer_height = 0;
19317     nk_layout_reset_min_row_height(ctx);
19318     layout->row.index = 0;
19319     layout->row.columns = 0;
19320     layout->row.ratio = 0;
19321     layout->row.item_width = 0;
19322     layout->row.tree_depth = 0;
19323     layout->row.height = panel_padding.y;
19324     layout->has_scrolling = nk_true;
19325     if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
19326         layout->bounds.w -= scrollbar_size.x;
19327     if (!nk_panel_is_nonblock(panel_type)) {
19328         layout->footer_height = 0;
19329         if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
19330             layout->footer_height = scrollbar_size.y;
19331         layout->bounds.h -= layout->footer_height;
19332     }
19333 
19334     /* panel header */
19335     if (nk_panel_has_header(win->flags, title))
19336     {
19337         struct nk_text text;
19338         struct nk_rect header;
19339         const struct nk_style_item *background = 0;
19340 
19341         /* calculate header bounds */
19342         header.x = win->bounds.x;
19343         header.y = win->bounds.y;
19344         header.w = win->bounds.w;
19345         header.h = font->height + 2.0f * style->window.header.padding.y;
19346         header.h += (2.0f * style->window.header.label_padding.y);
19347 
19348         /* shrink panel by header */
19349         layout->header_height = header.h;
19350         layout->bounds.y += header.h;
19351         layout->bounds.h -= header.h;
19352         layout->at_y += header.h;
19353 
19354         /* select correct header background and text color */
19355         if (ctx->active == win) {
19356             background = &style->window.header.active;
19357             text.text = style->window.header.label_active;
19358         } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
19359             background = &style->window.header.hover;
19360             text.text = style->window.header.label_hover;
19361         } else {
19362             background = &style->window.header.normal;
19363             text.text = style->window.header.label_normal;
19364         }
19365 
19366         /* draw header background */
19367         header.h += 1.0f;
19368         if (background->type == NK_STYLE_ITEM_IMAGE) {
19369             text.background = nk_rgba(0,0,0,0);
19370             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
19371         } else {
19372             text.background = background->data.color;
19373             nk_fill_rect(out, header, 0, background->data.color);
19374         }
19375 
19376         /* window close button */
19377         {struct nk_rect button;
19378         button.y = header.y + style->window.header.padding.y;
19379         button.h = header.h - 2 * style->window.header.padding.y;
19380         button.w = button.h;
19381         if (win->flags & NK_WINDOW_CLOSABLE) {
19382             nk_flags ws = 0;
19383             if (style->window.header.align == NK_HEADER_RIGHT) {
19384                 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
19385                 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
19386             } else {
19387                 button.x = header.x + style->window.header.padding.x;
19388                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
19389             }
19390 
19391             if (nk_do_button_symbol(&ws, &win->buffer, button,
19392                 style->window.header.close_symbol, NK_BUTTON_DEFAULT,
19393                 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
19394             {
19395                 layout->flags |= NK_WINDOW_HIDDEN;
19396                 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
19397             }
19398         }
19399 
19400         /* window minimize button */
19401         if (win->flags & NK_WINDOW_MINIMIZABLE) {
19402             nk_flags ws = 0;
19403             if (style->window.header.align == NK_HEADER_RIGHT) {
19404                 button.x = (header.w + header.x) - button.w;
19405                 if (!(win->flags & NK_WINDOW_CLOSABLE)) {
19406                     button.x -= style->window.header.padding.x;
19407                     header.w -= style->window.header.padding.x;
19408                 }
19409                 header.w -= button.w + style->window.header.spacing.x;
19410             } else {
19411                 button.x = header.x;
19412                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
19413             }
19414             if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
19415                 style->window.header.maximize_symbol: style->window.header.minimize_symbol,
19416                 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
19417                 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
19418                     layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
19419                     layout->flags | NK_WINDOW_MINIMIZED;
19420         }}
19421 
19422         {/* window header title */
19423         int text_len = nk_strlen(title);
19424         struct nk_rect label = {0,0,0,0};
19425         float t = font->width(font->userdata, font->height, title, text_len);
19426         text.padding = nk_vec2(0,0);
19427 
19428         label.x = header.x + style->window.header.padding.x;
19429         label.x += style->window.header.label_padding.x;
19430         label.y = header.y + style->window.header.label_padding.y;
19431         label.h = font->height + 2 * style->window.header.label_padding.y;
19432         label.w = t + 2 * style->window.header.spacing.x;
19433         label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
19434         nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
19435     }
19436 
19437     /* draw window background */
19438     if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
19439         struct nk_rect body;
19440         body.x = win->bounds.x;
19441         body.w = win->bounds.w;
19442         body.y = (win->bounds.y + layout->header_height);
19443         body.h = (win->bounds.h - layout->header_height);
19444         if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE)
19445             nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
19446         else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
19447     }
19448 
19449     /* set clipping rectangle */
19450     {struct nk_rect clip;
19451     layout->clip = layout->bounds;
19452     nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
19453         layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
19454     nk_push_scissor(out, clip);
19455     layout->clip = clip;}
19456     return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
19457 }
19458 
19459 NK_INTERN void
19460 nk_panel_end(struct nk_context *ctx)
19461 {
19462     struct nk_input *in;
19463     struct nk_window *window;
19464     struct nk_panel *layout;
19465     const struct nk_style *style;
19466     struct nk_command_buffer *out;
19467 
19468     struct nk_vec2 scrollbar_size;
19469     struct nk_vec2 panel_padding;
19470 
19471     NK_ASSERT(ctx);
19472     NK_ASSERT(ctx->current);
19473     NK_ASSERT(ctx->current->layout);
19474     if (!ctx || !ctx->current || !ctx->current->layout)
19475         return;
19476 
19477     window = ctx->current;
19478     layout = window->layout;
19479     style = &ctx->style;
19480     out = &window->buffer;
19481     in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
19482     if (!nk_panel_is_sub(layout->type))
19483         nk_push_scissor(out, nk_null_rect);
19484 
19485     /* cache configuration data */
19486     scrollbar_size = style->window.scrollbar_size;
19487     panel_padding = nk_panel_get_padding(style, layout->type);
19488 
19489     /* update the current cursor Y-position to point over the last added widget */
19490     layout->at_y += layout->row.height;
19491 
19492     /* dynamic panels */
19493     if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
19494     {
19495         /* update panel height to fit dynamic growth */
19496         struct nk_rect empty_space;
19497         if (layout->at_y < (layout->bounds.y + layout->bounds.h))
19498             layout->bounds.h = layout->at_y - layout->bounds.y;
19499 
19500         /* fill top empty space */
19501         empty_space.x = window->bounds.x;
19502         empty_space.y = layout->bounds.y;
19503         empty_space.h = panel_padding.y;
19504         empty_space.w = window->bounds.w;
19505         nk_fill_rect(out, empty_space, 0, style->window.background);
19506 
19507         /* fill left empty space */
19508         empty_space.x = window->bounds.x;
19509         empty_space.y = layout->bounds.y;
19510         empty_space.w = panel_padding.x + layout->border;
19511         empty_space.h = layout->bounds.h;
19512         nk_fill_rect(out, empty_space, 0, style->window.background);
19513 
19514         /* fill right empty space */
19515         empty_space.x = layout->bounds.x + layout->bounds.w - layout->border;
19516         empty_space.y = layout->bounds.y;
19517         empty_space.w = panel_padding.x + layout->border;
19518         empty_space.h = layout->bounds.h;
19519         if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
19520             empty_space.w += scrollbar_size.x;
19521         nk_fill_rect(out, empty_space, 0, style->window.background);
19522 
19523         /* fill bottom empty space */
19524         if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) {
19525             empty_space.x = window->bounds.x;
19526             empty_space.y = layout->bounds.y + layout->bounds.h;
19527             empty_space.w = window->bounds.w;
19528             empty_space.h = scrollbar_size.y;
19529             nk_fill_rect(out, empty_space, 0, style->window.background);
19530         }
19531     }
19532 
19533     /* scrollbars */
19534     if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
19535         !(layout->flags & NK_WINDOW_MINIMIZED) &&
19536         window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
19537     {
19538         struct nk_rect scroll;
19539         int scroll_has_scrolling;
19540         float scroll_target;
19541         float scroll_offset;
19542         float scroll_step;
19543         float scroll_inc;
19544 
19545         /* mouse wheel scrolling */
19546         if (nk_panel_is_sub(layout->type))
19547         {
19548             /* sub-window mouse wheel scrolling */
19549             struct nk_window *root_window = window;
19550             struct nk_panel *root_panel = window->layout;
19551             while (root_panel->parent)
19552                 root_panel = root_panel->parent;
19553             while (root_window->parent)
19554                 root_window = root_window->parent;
19555 
19556             /* only allow scrolling if parent window is active */
19557             scroll_has_scrolling = 0;
19558             if ((root_window == ctx->active) && layout->has_scrolling) {
19559                 /* and panel is being hovered and inside clip rect*/
19560                 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
19561                     NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
19562                         root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
19563                 {
19564                     /* deactivate all parent scrolling */
19565                     root_panel = window->layout;
19566                     while (root_panel->parent) {
19567                         root_panel->has_scrolling = nk_false;
19568                         root_panel = root_panel->parent;
19569                     }
19570                     root_panel->has_scrolling = nk_false;
19571                     scroll_has_scrolling = nk_true;
19572                 }
19573             }
19574         } else if (!nk_panel_is_sub(layout->type)) {
19575             /* window mouse wheel scrolling */
19576             scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
19577             if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
19578                 window->scrolled = nk_true;
19579             else window->scrolled = nk_false;
19580         } else scroll_has_scrolling = nk_false;
19581 
19582         {
19583             /* vertical scrollbar */
19584             nk_flags state = 0;
19585             scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
19586             scroll.y = layout->bounds.y;
19587             scroll.w = scrollbar_size.x;
19588             scroll.h = layout->bounds.h;
19589 
19590             scroll_offset = (float)*layout->offset_y;
19591             scroll_step = scroll.h * 0.10f;
19592             scroll_inc = scroll.h * 0.01f;
19593             scroll_target = (float)(int)(layout->at_y - scroll.y);
19594             scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
19595                 scroll_offset, scroll_target, scroll_step, scroll_inc,
19596                 &ctx->style.scrollv, in, style->font);
19597             *layout->offset_y = (nk_uint)scroll_offset;
19598             if (in && scroll_has_scrolling)
19599                 in->mouse.scroll_delta.y = 0;
19600         }
19601         {
19602             /* horizontal scrollbar */
19603             nk_flags state = 0;
19604             scroll.x = layout->bounds.x;
19605             scroll.y = layout->bounds.y + layout->bounds.h;
19606             scroll.w = layout->bounds.w;
19607             scroll.h = scrollbar_size.y;
19608 
19609             scroll_offset = (float)*layout->offset_x;
19610             scroll_target = (float)(int)(layout->max_x - scroll.x);
19611             scroll_step = layout->max_x * 0.05f;
19612             scroll_inc = layout->max_x * 0.005f;
19613             scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
19614                 scroll_offset, scroll_target, scroll_step, scroll_inc,
19615                 &ctx->style.scrollh, in, style->font);
19616             *layout->offset_x = (nk_uint)scroll_offset;
19617         }
19618     }
19619 
19620     /* hide scroll if no user input */
19621     if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
19622         int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
19623         int is_window_hovered = nk_window_is_hovered(ctx);
19624         int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
19625         if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
19626             window->scrollbar_hiding_timer += ctx->delta_time_seconds;
19627         else window->scrollbar_hiding_timer = 0;
19628     } else window->scrollbar_hiding_timer = 0;
19629 
19630     /* window border */
19631     if (layout->flags & NK_WINDOW_BORDER)
19632     {
19633         struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
19634         const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED)
19635             ? (style->window.border + window->bounds.y + layout->header_height)
19636             : ((layout->flags & NK_WINDOW_DYNAMIC)
19637                 ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
19638                 : (window->bounds.y + window->bounds.h));
19639         struct nk_rect b = window->bounds;
19640         b.h = padding_y - window->bounds.y;
19641         nk_stroke_rect(out, b, 0, layout->border, border_color);
19642     }
19643 
19644     /* scaler */
19645     if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
19646     {
19647         /* calculate scaler bounds */
19648         struct nk_rect scaler;
19649         scaler.w = scrollbar_size.x;
19650         scaler.h = scrollbar_size.y;
19651         scaler.y = layout->bounds.y + layout->bounds.h;
19652         if (layout->flags & NK_WINDOW_SCALE_LEFT)
19653             scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
19654         else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
19655         if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
19656             scaler.x -= scaler.w;
19657 
19658         /* draw scaler */
19659         {const struct nk_style_item *item = &style->window.scaler;
19660         if (item->type == NK_STYLE_ITEM_IMAGE)
19661             nk_draw_image(out, scaler, &item->data.image, nk_white);
19662         else {
19663             if (layout->flags & NK_WINDOW_SCALE_LEFT) {
19664                 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
19665                     scaler.y + scaler.h, scaler.x + scaler.w,
19666                     scaler.y + scaler.h, item->data.color);
19667             } else {
19668                 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
19669                     scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
19670             }
19671         }}
19672 
19673         /* do window scaling */
19674         if (!(window->flags & NK_WINDOW_ROM)) {
19675             struct nk_vec2 window_size = style->window.min_size;
19676             int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
19677             int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
19678                     NK_BUTTON_LEFT, scaler, nk_true);
19679 
19680             if (left_mouse_down && left_mouse_click_in_scaler) {
19681                 float delta_x = in->mouse.delta.x;
19682                 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
19683                     delta_x = -delta_x;
19684                     window->bounds.x += in->mouse.delta.x;
19685                 }
19686                 /* dragging in x-direction  */
19687                 if (window->bounds.w + delta_x >= window_size.x) {
19688                     if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
19689                         window->bounds.w = window->bounds.w + delta_x;
19690                         scaler.x += in->mouse.delta.x;
19691                     }
19692                 }
19693                 /* dragging in y-direction (only possible if static window) */
19694                 if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
19695                     if (window_size.y < window->bounds.h + in->mouse.delta.y) {
19696                         if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
19697                             window->bounds.h = window->bounds.h + in->mouse.delta.y;
19698                             scaler.y += in->mouse.delta.y;
19699                         }
19700                     }
19701                 }
19702                 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
19703                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
19704                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
19705             }
19706         }
19707     }
19708     if (!nk_panel_is_sub(layout->type)) {
19709         /* window is hidden so clear command buffer  */
19710         if (layout->flags & NK_WINDOW_HIDDEN)
19711             nk_command_buffer_reset(&window->buffer);
19712         /* window is visible and not tab */
19713         else nk_finish(ctx, window);
19714     }
19715 
19716     /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
19717     if (layout->flags & NK_WINDOW_REMOVE_ROM) {
19718         layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
19719         layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
19720     }
19721     window->flags = layout->flags;
19722 
19723     /* property garbage collector */
19724     if (window->property.active && window->property.old != window->property.seq &&
19725         window->property.active == window->property.prev) {
19726         nk_zero(&window->property, sizeof(window->property));
19727     } else {
19728         window->property.old = window->property.seq;
19729         window->property.prev = window->property.active;
19730         window->property.seq = 0;
19731     }
19732     /* edit garbage collector */
19733     if (window->edit.active && window->edit.old != window->edit.seq &&
19734        window->edit.active == window->edit.prev) {
19735         nk_zero(&window->edit, sizeof(window->edit));
19736     } else {
19737         window->edit.old = window->edit.seq;
19738         window->edit.prev = window->edit.active;
19739         window->edit.seq = 0;
19740     }
19741     /* contextual garbage collector */
19742     if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
19743         window->popup.con_count = 0;
19744         window->popup.con_old = 0;
19745         window->popup.active_con = 0;
19746     } else {
19747         window->popup.con_old = window->popup.con_count;
19748         window->popup.con_count = 0;
19749     }
19750     window->popup.combo_count = 0;
19751     /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
19752     NK_ASSERT(!layout->row.tree_depth);
19753 }
19754 
19755 /* ----------------------------------------------------------------
19756  *
19757  *                          PAGE ELEMENT
19758  *
19759  * ---------------------------------------------------------------*/
19760 NK_INTERN struct nk_page_element*
19761 nk_create_page_element(struct nk_context *ctx)
19762 {
19763     struct nk_page_element *elem;
19764     if (ctx->freelist) {
19765         /* unlink page element from free list */
19766         elem = ctx->freelist;
19767         ctx->freelist = elem->next;
19768     } else if (ctx->use_pool) {
19769         /* allocate page element from memory pool */
19770         elem = nk_pool_alloc(&ctx->pool);
19771         NK_ASSERT(elem);
19772         if (!elem) return 0;
19773     } else {
19774         /* allocate new page element from back of fixed size memory buffer */
19775         NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
19776         NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
19777         elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
19778         NK_ASSERT(elem);
19779         if (!elem) return 0;
19780     }
19781     nk_zero_struct(*elem);
19782     elem->next = 0;
19783     elem->prev = 0;
19784     return elem;
19785 }
19786 
19787 NK_INTERN void
19788 nk_link_page_element_into_freelist(struct nk_context *ctx,
19789     struct nk_page_element *elem)
19790 {
19791     /* link table into freelist */
19792     if (!ctx->freelist) {
19793         ctx->freelist = elem;
19794     } else {
19795         elem->next = ctx->freelist;
19796         ctx->freelist = elem;
19797     }
19798 }
19799 
19800 NK_INTERN void
19801 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
19802 {
19803     /* we have a pool so just add to free list */
19804     if (ctx->use_pool) {
19805         nk_link_page_element_into_freelist(ctx, elem);
19806         return;
19807     }
19808     /* if possible remove last element from back of fixed memory buffer */
19809     {void *elem_end = (void*)(elem + 1);
19810     void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
19811     if (elem_end == buffer_end)
19812         ctx->memory.size -= sizeof(struct nk_page_element);
19813     else nk_link_page_element_into_freelist(ctx, elem);}
19814 }
19815 
19816 /* ----------------------------------------------------------------
19817  *
19818  *                          PANEL
19819  *
19820  * ---------------------------------------------------------------*/
19821 NK_INTERN void*
19822 nk_create_panel(struct nk_context *ctx)
19823 {
19824     struct nk_page_element *elem;
19825     elem = nk_create_page_element(ctx);
19826     if (!elem) return 0;
19827     nk_zero_struct(*elem);
19828     return &elem->data.pan;
19829 }
19830 
19831 NK_INTERN void
19832 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
19833 {
19834     union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
19835     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
19836     nk_free_page_element(ctx, pe);
19837 }
19838 
19839 /* ----------------------------------------------------------------
19840  *
19841  *                          TABLES
19842  *
19843  * ---------------------------------------------------------------*/
19844 NK_INTERN struct nk_table*
19845 nk_create_table(struct nk_context *ctx)
19846 {
19847     struct nk_page_element *elem;
19848     elem = nk_create_page_element(ctx);
19849     if (!elem) return 0;
19850     nk_zero_struct(*elem);
19851     return &elem->data.tbl;
19852 }
19853 
19854 NK_INTERN void
19855 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
19856 {
19857     union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
19858     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
19859     nk_free_page_element(ctx, pe);
19860 }
19861 
19862 NK_INTERN void
19863 nk_push_table(struct nk_window *win, struct nk_table *tbl)
19864 {
19865     if (!win->tables) {
19866         win->tables = tbl;
19867         tbl->next = 0;
19868         tbl->prev = 0;
19869         tbl->size = 0;
19870         win->table_count = 1;
19871         return;
19872     }
19873     win->tables->prev = tbl;
19874     tbl->next = win->tables;
19875     tbl->prev = 0;
19876     tbl->size = 0;
19877     win->tables = tbl;
19878     win->table_count++;
19879 }
19880 
19881 NK_INTERN void
19882 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
19883 {
19884     if (win->tables == tbl)
19885         win->tables = tbl->next;
19886     if (tbl->next)
19887         tbl->next->prev = tbl->prev;
19888     if (tbl->prev)
19889         tbl->prev->next = tbl->next;
19890     tbl->next = 0;
19891     tbl->prev = 0;
19892 }
19893 
19894 NK_INTERN nk_uint*
19895 nk_add_value(struct nk_context *ctx, struct nk_window *win,
19896             nk_hash name, nk_uint value)
19897 {
19898     NK_ASSERT(ctx);
19899     NK_ASSERT(win);
19900     if (!win || !ctx) return 0;
19901     if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
19902         struct nk_table *tbl = nk_create_table(ctx);
19903         NK_ASSERT(tbl);
19904         if (!tbl) return 0;
19905         nk_push_table(win, tbl);
19906     }
19907     win->tables->seq = win->seq;
19908     win->tables->keys[win->tables->size] = name;
19909     win->tables->values[win->tables->size] = value;
19910     return &win->tables->values[win->tables->size++];
19911 }
19912 
19913 NK_INTERN nk_uint*
19914 nk_find_value(struct nk_window *win, nk_hash name)
19915 {
19916     struct nk_table *iter = win->tables;
19917     while (iter) {
19918         unsigned int i = 0;
19919         unsigned int size = iter->size;
19920         for (i = 0; i < size; ++i) {
19921             if (iter->keys[i] == name) {
19922                 iter->seq = win->seq;
19923                 return &iter->values[i];
19924             }
19925         } size = NK_VALUE_PAGE_CAPACITY;
19926         iter = iter->next;
19927     }
19928     return 0;
19929 }
19930 
19931 /* ----------------------------------------------------------------
19932  *
19933  *                          WINDOW
19934  *
19935  * ---------------------------------------------------------------*/
19936 NK_INTERN void*
19937 nk_create_window(struct nk_context *ctx)
19938 {
19939     struct nk_page_element *elem;
19940     elem = nk_create_page_element(ctx);
19941     if (!elem) return 0;
19942     elem->data.win.seq = ctx->seq;
19943     return &elem->data.win;
19944 }
19945 
19946 NK_INTERN void
19947 nk_free_window(struct nk_context *ctx, struct nk_window *win)
19948 {
19949     /* unlink windows from list */
19950     struct nk_table *it = win->tables;
19951     if (win->popup.win) {
19952         nk_free_window(ctx, win->popup.win);
19953         win->popup.win = 0;
19954     }
19955     win->next = 0;
19956     win->prev = 0;
19957 
19958     while (it) {
19959         /*free window state tables */
19960         struct nk_table *n = it->next;
19961         nk_remove_table(win, it);
19962         nk_free_table(ctx, it);
19963         if (it == win->tables)
19964             win->tables = n;
19965         it = n;
19966     }
19967 
19968     /* link windows into freelist */
19969     {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
19970     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
19971     nk_free_page_element(ctx, pe);}
19972 }
19973 
19974 NK_INTERN struct nk_window*
19975 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
19976 {
19977     struct nk_window *iter;
19978     iter = ctx->begin;
19979     while (iter) {
19980         NK_ASSERT(iter != iter->next);
19981         if (iter->name == hash) {
19982             int max_len = nk_strlen(iter->name_string);
19983             if (!nk_stricmpn(iter->name_string, name, max_len))
19984                 return iter;
19985         }
19986         iter = iter->next;
19987     }
19988     return 0;
19989 }
19990 
19991 enum nk_window_insert_location {
19992     NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
19993     NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
19994 };
19995 NK_INTERN void
19996 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
19997     enum nk_window_insert_location loc)
19998 {
19999     const struct nk_window *iter;
20000     NK_ASSERT(ctx);
20001     NK_ASSERT(win);
20002     if (!win || !ctx) return;
20003 
20004     iter = ctx->begin;
20005     while (iter) {
20006         NK_ASSERT(iter != iter->next);
20007         NK_ASSERT(iter != win);
20008         if (iter == win) return;
20009         iter = iter->next;
20010     }
20011 
20012     if (!ctx->begin) {
20013         win->next = 0;
20014         win->prev = 0;
20015         ctx->begin = win;
20016         ctx->end = win;
20017         ctx->count = 1;
20018         return;
20019     }
20020     if (loc == NK_INSERT_BACK) {
20021         struct nk_window *end;
20022         end = ctx->end;
20023         end->flags |= NK_WINDOW_ROM;
20024         end->next = win;
20025         win->prev = ctx->end;
20026         win->next = 0;
20027         ctx->end = win;
20028         ctx->active = ctx->end;
20029         ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
20030     } else {
20031         /*ctx->end->flags |= NK_WINDOW_ROM;*/
20032         ctx->begin->prev = win;
20033         win->next = ctx->begin;
20034         win->prev = 0;
20035         ctx->begin = win;
20036         ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
20037     }
20038     ctx->count++;
20039 }
20040 
20041 NK_INTERN void
20042 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
20043 {
20044     if (win == ctx->begin || win == ctx->end) {
20045         if (win == ctx->begin) {
20046             ctx->begin = win->next;
20047             if (win->next)
20048                 win->next->prev = 0;
20049         }
20050         if (win == ctx->end) {
20051             ctx->end = win->prev;
20052             if (win->prev)
20053                 win->prev->next = 0;
20054         }
20055     } else {
20056         if (win->next)
20057             win->next->prev = win->prev;
20058         if (win->prev)
20059             win->prev->next = win->next;
20060     }
20061     if (win == ctx->active || !ctx->active) {
20062         ctx->active = ctx->end;
20063         if (ctx->end)
20064             ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
20065     }
20066     win->next = 0;
20067     win->prev = 0;
20068     ctx->count--;
20069 }
20070 
20071 NK_API int
20072 nk_begin(struct nk_context *ctx, const char *title,
20073     struct nk_rect bounds, nk_flags flags)
20074 {
20075     return nk_begin_titled(ctx, title, title, bounds, flags);
20076 }
20077 
20078 NK_API int
20079 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
20080     struct nk_rect bounds, nk_flags flags)
20081 {
20082     struct nk_window *win;
20083     struct nk_style *style;
20084     nk_hash title_hash;
20085     int title_len;
20086     int ret = 0;
20087 
20088     NK_ASSERT(ctx);
20089     NK_ASSERT(name);
20090     NK_ASSERT(title);
20091     NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
20092     NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
20093     if (!ctx || ctx->current || !title || !name)
20094         return 0;
20095 
20096     /* find or create window */
20097     style = &ctx->style;
20098     title_len = (int)nk_strlen(name);
20099     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20100     win = nk_find_window(ctx, title_hash, name);
20101     if (!win) {
20102         /* create new window */
20103         nk_size name_length = (nk_size)nk_strlen(name);
20104         win = (struct nk_window*)nk_create_window(ctx);
20105         NK_ASSERT(win);
20106         if (!win) return 0;
20107 
20108         if (flags & NK_WINDOW_BACKGROUND)
20109             nk_insert_window(ctx, win, NK_INSERT_FRONT);
20110         else nk_insert_window(ctx, win, NK_INSERT_BACK);
20111         nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
20112 
20113         win->flags = flags;
20114         win->bounds = bounds;
20115         win->name = title_hash;
20116         name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
20117         NK_MEMCPY(win->name_string, name, name_length);
20118         win->name_string[name_length] = 0;
20119         win->popup.win = 0;
20120         if (!ctx->active)
20121             ctx->active = win;
20122     } else {
20123         /* update window */
20124         win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
20125         win->flags |= flags;
20126         if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
20127             win->bounds = bounds;
20128         /* If this assert triggers you either:
20129          *
20130          * I.) Have more than one window with the same name or
20131          * II.) You forgot to actually draw the window.
20132          *      More specific you did not call `nk_clear` (nk_clear will be
20133          *      automatically called for you if you are using one of the
20134          *      provided demo backends). */
20135         NK_ASSERT(win->seq != ctx->seq);
20136         win->seq = ctx->seq;
20137         if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
20138             ctx->active = win;
20139             ctx->end = win;
20140         }
20141     }
20142     if (win->flags & NK_WINDOW_HIDDEN) {
20143         ctx->current = win;
20144         win->layout = 0;
20145         return 0;
20146     } else nk_start(ctx, win);
20147 
20148     /* window overlapping */
20149     if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
20150     {
20151         int inpanel, ishovered;
20152         struct nk_window *iter = win;
20153         float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
20154             (2.0f * style->window.header.label_padding.y);
20155         struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
20156             win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
20157 
20158         /* activate window if hovered and no other window is overlapping this window */
20159         inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
20160         inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
20161         ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
20162         if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
20163             iter = win->next;
20164             while (iter) {
20165                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
20166                     iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
20167                 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
20168                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
20169                     (!(iter->flags & NK_WINDOW_HIDDEN)))
20170                     break;
20171 
20172                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
20173                     NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
20174                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
20175                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
20176                     break;
20177                 iter = iter->next;
20178             }
20179         }
20180 
20181         /* activate window if clicked */
20182         if (iter && inpanel && (win != ctx->end)) {
20183             iter = win->next;
20184             while (iter) {
20185                 /* try to find a panel with higher priority in the same position */
20186                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
20187                 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
20188                 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
20189                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
20190                     !(iter->flags & NK_WINDOW_HIDDEN))
20191                     break;
20192                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
20193                     NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
20194                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
20195                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
20196                     break;
20197                 iter = iter->next;
20198             }
20199         }
20200         if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
20201             win->flags |= (nk_flags)NK_WINDOW_ROM;
20202             iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
20203             ctx->active = iter;
20204             if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
20205                 /* current window is active in that position so transfer to top
20206                  * at the highest priority in stack */
20207                 nk_remove_window(ctx, iter);
20208                 nk_insert_window(ctx, iter, NK_INSERT_BACK);
20209             }
20210         } else {
20211             if (!iter && ctx->end != win) {
20212                 if (!(win->flags & NK_WINDOW_BACKGROUND)) {
20213                     /* current window is active in that position so transfer to top
20214                      * at the highest priority in stack */
20215                     nk_remove_window(ctx, win);
20216                     nk_insert_window(ctx, win, NK_INSERT_BACK);
20217                 }
20218                 win->flags &= ~(nk_flags)NK_WINDOW_ROM;
20219                 ctx->active = win;
20220             }
20221             if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
20222                 win->flags |= NK_WINDOW_ROM;
20223         }
20224     }
20225     win->layout = (struct nk_panel*)nk_create_panel(ctx);
20226     ctx->current = win;
20227     ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
20228     win->layout->offset_x = &win->scrollbar.x;
20229     win->layout->offset_y = &win->scrollbar.y;
20230     return ret;
20231 }
20232 
20233 NK_API void
20234 nk_end(struct nk_context *ctx)
20235 {
20236     struct nk_panel *layout;
20237     NK_ASSERT(ctx);
20238     NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
20239     if (!ctx || !ctx->current)
20240         return;
20241 
20242     layout = ctx->current->layout;
20243     if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
20244         ctx->current = 0;
20245         return;
20246     }
20247     nk_panel_end(ctx);
20248     nk_free_panel(ctx, ctx->current->layout);
20249     ctx->current = 0;
20250 }
20251 
20252 NK_API struct nk_rect
20253 nk_window_get_bounds(const struct nk_context *ctx)
20254 {
20255     NK_ASSERT(ctx);
20256     NK_ASSERT(ctx->current);
20257     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
20258     return ctx->current->bounds;
20259 }
20260 
20261 NK_API struct nk_vec2
20262 nk_window_get_position(const struct nk_context *ctx)
20263 {
20264     NK_ASSERT(ctx);
20265     NK_ASSERT(ctx->current);
20266     if (!ctx || !ctx->current) return nk_vec2(0,0);
20267     return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
20268 }
20269 
20270 NK_API struct nk_vec2
20271 nk_window_get_size(const struct nk_context *ctx)
20272 {
20273     NK_ASSERT(ctx);
20274     NK_ASSERT(ctx->current);
20275     if (!ctx || !ctx->current) return nk_vec2(0,0);
20276     return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
20277 }
20278 
20279 NK_API float
20280 nk_window_get_width(const struct nk_context *ctx)
20281 {
20282     NK_ASSERT(ctx);
20283     NK_ASSERT(ctx->current);
20284     if (!ctx || !ctx->current) return 0;
20285     return ctx->current->bounds.w;
20286 }
20287 
20288 NK_API float
20289 nk_window_get_height(const struct nk_context *ctx)
20290 {
20291     NK_ASSERT(ctx);
20292     NK_ASSERT(ctx->current);
20293     if (!ctx || !ctx->current) return 0;
20294     return ctx->current->bounds.h;
20295 }
20296 
20297 NK_API struct nk_rect
20298 nk_window_get_content_region(struct nk_context *ctx)
20299 {
20300     NK_ASSERT(ctx);
20301     NK_ASSERT(ctx->current);
20302     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
20303     return ctx->current->layout->clip;
20304 }
20305 
20306 NK_API struct nk_vec2
20307 nk_window_get_content_region_min(struct nk_context *ctx)
20308 {
20309     NK_ASSERT(ctx);
20310     NK_ASSERT(ctx->current);
20311     NK_ASSERT(ctx->current->layout);
20312     if (!ctx || !ctx->current) return nk_vec2(0,0);
20313     return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
20314 }
20315 
20316 NK_API struct nk_vec2
20317 nk_window_get_content_region_max(struct nk_context *ctx)
20318 {
20319     NK_ASSERT(ctx);
20320     NK_ASSERT(ctx->current);
20321     NK_ASSERT(ctx->current->layout);
20322     if (!ctx || !ctx->current) return nk_vec2(0,0);
20323     return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
20324         ctx->current->layout->clip.y + ctx->current->layout->clip.h);
20325 }
20326 
20327 NK_API struct nk_vec2
20328 nk_window_get_content_region_size(struct nk_context *ctx)
20329 {
20330     NK_ASSERT(ctx);
20331     NK_ASSERT(ctx->current);
20332     NK_ASSERT(ctx->current->layout);
20333     if (!ctx || !ctx->current) return nk_vec2(0,0);
20334     return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
20335 }
20336 
20337 NK_API struct nk_command_buffer*
20338 nk_window_get_canvas(struct nk_context *ctx)
20339 {
20340     NK_ASSERT(ctx);
20341     NK_ASSERT(ctx->current);
20342     NK_ASSERT(ctx->current->layout);
20343     if (!ctx || !ctx->current) return 0;
20344     return &ctx->current->buffer;
20345 }
20346 
20347 NK_API struct nk_panel*
20348 nk_window_get_panel(struct nk_context *ctx)
20349 {
20350     NK_ASSERT(ctx);
20351     NK_ASSERT(ctx->current);
20352     if (!ctx || !ctx->current) return 0;
20353     return ctx->current->layout;
20354 }
20355 
20356 NK_API int
20357 nk_window_has_focus(const struct nk_context *ctx)
20358 {
20359     NK_ASSERT(ctx);
20360     NK_ASSERT(ctx->current);
20361     NK_ASSERT(ctx->current->layout);
20362     if (!ctx || !ctx->current) return 0;
20363     return ctx->current == ctx->active;
20364 }
20365 
20366 NK_API int
20367 nk_window_is_hovered(struct nk_context *ctx)
20368 {
20369     NK_ASSERT(ctx);
20370     NK_ASSERT(ctx->current);
20371     if (!ctx || !ctx->current) return 0;
20372     if(ctx->current->flags & NK_WINDOW_HIDDEN)
20373         return 0;
20374     return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
20375 }
20376 
20377 NK_API int
20378 nk_window_is_any_hovered(struct nk_context *ctx)
20379 {
20380     struct nk_window *iter;
20381     NK_ASSERT(ctx);
20382     if (!ctx) return 0;
20383     iter = ctx->begin;
20384     while (iter) {
20385         /* check if window is being hovered */
20386         if(!(iter->flags & NK_WINDOW_HIDDEN)) {
20387             /* check if window popup is being hovered */
20388             if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
20389                 return 1;
20390 
20391             if (iter->flags & NK_WINDOW_MINIMIZED) {
20392                 struct nk_rect header = iter->bounds;
20393                 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
20394                 if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
20395                     return 1;
20396             } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
20397                 return 1;
20398             }
20399         }
20400         iter = iter->next;
20401     }
20402     return 0;
20403 }
20404 
20405 NK_API int
20406 nk_item_is_any_active(struct nk_context *ctx)
20407 {
20408     int any_hovered = nk_window_is_any_hovered(ctx);
20409     int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
20410     return any_hovered || any_active;
20411 }
20412 
20413 NK_API int
20414 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
20415 {
20416     int title_len;
20417     nk_hash title_hash;
20418     struct nk_window *win;
20419     NK_ASSERT(ctx);
20420     if (!ctx) return 0;
20421 
20422     title_len = (int)nk_strlen(name);
20423     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20424     win = nk_find_window(ctx, title_hash, name);
20425     if (!win) return 0;
20426     return win->flags & NK_WINDOW_MINIMIZED;
20427 }
20428 
20429 NK_API int
20430 nk_window_is_closed(struct nk_context *ctx, const char *name)
20431 {
20432     int title_len;
20433     nk_hash title_hash;
20434     struct nk_window *win;
20435     NK_ASSERT(ctx);
20436     if (!ctx) return 1;
20437 
20438     title_len = (int)nk_strlen(name);
20439     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20440     win = nk_find_window(ctx, title_hash, name);
20441     if (!win) return 1;
20442     return (win->flags & NK_WINDOW_CLOSED);
20443 }
20444 
20445 NK_API int
20446 nk_window_is_hidden(struct nk_context *ctx, const char *name)
20447 {
20448     int title_len;
20449     nk_hash title_hash;
20450     struct nk_window *win;
20451     NK_ASSERT(ctx);
20452     if (!ctx) return 1;
20453 
20454     title_len = (int)nk_strlen(name);
20455     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20456     win = nk_find_window(ctx, title_hash, name);
20457     if (!win) return 1;
20458     return (win->flags & NK_WINDOW_HIDDEN);
20459 }
20460 
20461 NK_API int
20462 nk_window_is_active(struct nk_context *ctx, const char *name)
20463 {
20464     int title_len;
20465     nk_hash title_hash;
20466     struct nk_window *win;
20467     NK_ASSERT(ctx);
20468     if (!ctx) return 0;
20469 
20470     title_len = (int)nk_strlen(name);
20471     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20472     win = nk_find_window(ctx, title_hash, name);
20473     if (!win) return 0;
20474     return win == ctx->active;
20475 }
20476 
20477 NK_API struct nk_window*
20478 nk_window_find(struct nk_context *ctx, const char *name)
20479 {
20480     int title_len;
20481     nk_hash title_hash;
20482     title_len = (int)nk_strlen(name);
20483     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20484     return nk_find_window(ctx, title_hash, name);
20485 }
20486 
20487 NK_API void
20488 nk_window_close(struct nk_context *ctx, const char *name)
20489 {
20490     struct nk_window *win;
20491     NK_ASSERT(ctx);
20492     if (!ctx) return;
20493     win = nk_window_find(ctx, name);
20494     if (!win) return;
20495     NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
20496     if (ctx->current == win) return;
20497     win->flags |= NK_WINDOW_HIDDEN;
20498     win->flags |= NK_WINDOW_CLOSED;
20499 }
20500 
20501 NK_API void
20502 nk_window_set_bounds(struct nk_context *ctx,
20503     const char *name, struct nk_rect bounds)
20504 {
20505     struct nk_window *win;
20506     NK_ASSERT(ctx);
20507     if (!ctx) return;
20508     win = nk_window_find(ctx, name);
20509     if (!win) return;
20510     NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
20511     win->bounds = bounds;
20512 }
20513 
20514 NK_API void
20515 nk_window_set_position(struct nk_context *ctx,
20516     const char *name, struct nk_vec2 pos)
20517 {
20518     struct nk_window *win = nk_window_find(ctx, name);
20519     if (!win) return;
20520     win->bounds.x = pos.x;
20521     win->bounds.y = pos.y;
20522 }
20523 
20524 NK_API void
20525 nk_window_set_size(struct nk_context *ctx,
20526     const char *name, struct nk_vec2 size)
20527 {
20528     struct nk_window *win = nk_window_find(ctx, name);
20529     if (!win) return;
20530     win->bounds.w = size.x;
20531     win->bounds.h = size.y;
20532 }
20533 
20534 NK_API void
20535 nk_window_collapse(struct nk_context *ctx, const char *name,
20536                     enum nk_collapse_states c)
20537 {
20538     int title_len;
20539     nk_hash title_hash;
20540     struct nk_window *win;
20541     NK_ASSERT(ctx);
20542     if (!ctx) return;
20543 
20544     title_len = (int)nk_strlen(name);
20545     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20546     win = nk_find_window(ctx, title_hash, name);
20547     if (!win) return;
20548     if (c == NK_MINIMIZED)
20549         win->flags |= NK_WINDOW_MINIMIZED;
20550     else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
20551 }
20552 
20553 NK_API void
20554 nk_window_collapse_if(struct nk_context *ctx, const char *name,
20555     enum nk_collapse_states c, int cond)
20556 {
20557     NK_ASSERT(ctx);
20558     if (!ctx || !cond) return;
20559     nk_window_collapse(ctx, name, c);
20560 }
20561 
20562 NK_API void
20563 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
20564 {
20565     int title_len;
20566     nk_hash title_hash;
20567     struct nk_window *win;
20568     NK_ASSERT(ctx);
20569     if (!ctx) return;
20570 
20571     title_len = (int)nk_strlen(name);
20572     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20573     win = nk_find_window(ctx, title_hash, name);
20574     if (!win) return;
20575     if (s == NK_HIDDEN) {
20576         win->flags |= NK_WINDOW_HIDDEN;
20577     } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
20578 }
20579 
20580 NK_API void
20581 nk_window_show_if(struct nk_context *ctx, const char *name,
20582     enum nk_show_states s, int cond)
20583 {
20584     NK_ASSERT(ctx);
20585     if (!ctx || !cond) return;
20586     nk_window_show(ctx, name, s);
20587 }
20588 
20589 NK_API void
20590 nk_window_set_focus(struct nk_context *ctx, const char *name)
20591 {
20592     int title_len;
20593     nk_hash title_hash;
20594     struct nk_window *win;
20595     NK_ASSERT(ctx);
20596     if (!ctx) return;
20597 
20598     title_len = (int)nk_strlen(name);
20599     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
20600     win = nk_find_window(ctx, title_hash, name);
20601     if (win && ctx->end != win) {
20602         nk_remove_window(ctx, win);
20603         nk_insert_window(ctx, win, NK_INSERT_BACK);
20604     }
20605     ctx->active = win;
20606 }
20607 
20608 /*----------------------------------------------------------------
20609  *
20610  *                          MENUBAR
20611  *
20612  * --------------------------------------------------------------*/
20613 NK_API void
20614 nk_menubar_begin(struct nk_context *ctx)
20615 {
20616     struct nk_panel *layout;
20617     NK_ASSERT(ctx);
20618     NK_ASSERT(ctx->current);
20619     NK_ASSERT(ctx->current->layout);
20620     if (!ctx || !ctx->current || !ctx->current->layout)
20621         return;
20622 
20623     layout = ctx->current->layout;
20624     NK_ASSERT(layout->at_y == layout->bounds.y);
20625     /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
20626     If you want a menubar the first nuklear function after `nk_begin` has to be a
20627     `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
20628     widgets (also supports multiple rows).
20629     Example:
20630         if (nk_begin(...)) {
20631             nk_menubar_begin(...);
20632                 nk_layout_xxxx(...);
20633                 nk_button(...);
20634                 nk_layout_xxxx(...);
20635                 nk_button(...);
20636             nk_menubar_end(...);
20637         }
20638         nk_end(...);
20639     */
20640     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
20641         return;
20642 
20643     layout->menu.x = layout->at_x;
20644     layout->menu.y = layout->at_y + layout->row.height;
20645     layout->menu.w = layout->bounds.w;
20646     layout->menu.offset.x = *layout->offset_x;
20647     layout->menu.offset.y = *layout->offset_y;
20648     *layout->offset_y = 0;
20649 }
20650 
20651 NK_API void
20652 nk_menubar_end(struct nk_context *ctx)
20653 {
20654     struct nk_window *win;
20655     struct nk_panel *layout;
20656     struct nk_command_buffer *out;
20657 
20658     NK_ASSERT(ctx);
20659     NK_ASSERT(ctx->current);
20660     NK_ASSERT(ctx->current->layout);
20661     if (!ctx || !ctx->current || !ctx->current->layout)
20662         return;
20663 
20664     win = ctx->current;
20665     out = &win->buffer;
20666     layout = win->layout;
20667     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
20668         return;
20669 
20670     layout->menu.h = layout->at_y - layout->menu.y;
20671     layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
20672     layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
20673 
20674     *layout->offset_x = layout->menu.offset.x;
20675     *layout->offset_y = layout->menu.offset.y;
20676     layout->at_y = layout->bounds.y - layout->row.height;
20677 
20678     layout->clip.y = layout->bounds.y;
20679     layout->clip.h = layout->bounds.h;
20680     nk_push_scissor(out, layout->clip);
20681 }
20682 /* -------------------------------------------------------------
20683  *
20684  *                          LAYOUT
20685  *
20686  * --------------------------------------------------------------*/
20687 NK_API void
20688 nk_layout_set_min_row_height(struct nk_context *ctx, float height)
20689 {
20690     struct nk_window *win;
20691     struct nk_panel *layout;
20692 
20693     NK_ASSERT(ctx);
20694     NK_ASSERT(ctx->current);
20695     NK_ASSERT(ctx->current->layout);
20696     if (!ctx || !ctx->current || !ctx->current->layout)
20697         return;
20698 
20699     win = ctx->current;
20700     layout = win->layout;
20701     layout->row.min_height = height;
20702 }
20703 
20704 NK_API void
20705 nk_layout_reset_min_row_height(struct nk_context *ctx)
20706 {
20707     struct nk_window *win;
20708     struct nk_panel *layout;
20709 
20710     NK_ASSERT(ctx);
20711     NK_ASSERT(ctx->current);
20712     NK_ASSERT(ctx->current->layout);
20713     if (!ctx || !ctx->current || !ctx->current->layout)
20714         return;
20715 
20716     win = ctx->current;
20717     layout = win->layout;
20718     layout->row.min_height = ctx->style.font->height;
20719     layout->row.min_height += ctx->style.text.padding.y*2;
20720     layout->row.min_height += ctx->style.window.min_row_height_padding*2;
20721 }
20722 
20723 NK_INTERN float
20724 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
20725     float total_space, int columns)
20726 {
20727     float panel_padding;
20728     float panel_spacing;
20729     float panel_space;
20730 
20731     struct nk_vec2 spacing;
20732     struct nk_vec2 padding;
20733 
20734     spacing = style->window.spacing;
20735     padding = nk_panel_get_padding(style, type);
20736 
20737     /* calculate the usable panel space */
20738     panel_padding = 2 * padding.x;
20739     panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
20740     panel_space  = total_space - panel_padding - panel_spacing;
20741     return panel_space;
20742 }
20743 
20744 NK_INTERN void
20745 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
20746     float height, int cols)
20747 {
20748     struct nk_panel *layout;
20749     const struct nk_style *style;
20750     struct nk_command_buffer *out;
20751 
20752     struct nk_vec2 item_spacing;
20753     struct nk_color color;
20754 
20755     NK_ASSERT(ctx);
20756     NK_ASSERT(ctx->current);
20757     NK_ASSERT(ctx->current->layout);
20758     if (!ctx || !ctx->current || !ctx->current->layout)
20759         return;
20760 
20761     /* prefetch some configuration data */
20762     layout = win->layout;
20763     style = &ctx->style;
20764     out = &win->buffer;
20765     color = style->window.background;
20766     item_spacing = style->window.spacing;
20767 
20768     /*  if one of these triggers you forgot to add an `if` condition around either
20769         a window, group, popup, combobox or contextual menu `begin` and `end` block.
20770         Example:
20771             if (nk_begin(...) {...} nk_end(...); or
20772             if (nk_group_begin(...) { nk_group_end(...);} */
20773     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
20774     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
20775     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
20776 
20777     /* update the current row and set the current row layout */
20778     layout->row.index = 0;
20779     layout->at_y += layout->row.height;
20780     layout->row.columns = cols;
20781     if (height == 0.0f)
20782         layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
20783     else layout->row.height = height + item_spacing.y;
20784 
20785     layout->row.item_offset = 0;
20786     if (layout->flags & NK_WINDOW_DYNAMIC) {
20787         /* draw background for dynamic panels */
20788         struct nk_rect background;
20789         background.x = win->bounds.x;
20790         background.w = win->bounds.w;
20791         background.y = layout->at_y - 1.0f;
20792         background.h = layout->row.height + 1.0f;
20793         nk_fill_rect(out, background, 0, color);
20794     }
20795 }
20796 
20797 NK_INTERN void
20798 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
20799     float height, int cols, int width)
20800 {
20801     /* update the current row and set the current row layout */
20802     struct nk_window *win;
20803     NK_ASSERT(ctx);
20804     NK_ASSERT(ctx->current);
20805     NK_ASSERT(ctx->current->layout);
20806     if (!ctx || !ctx->current || !ctx->current->layout)
20807         return;
20808 
20809     win = ctx->current;
20810     nk_panel_layout(ctx, win, height, cols);
20811     if (fmt == NK_DYNAMIC)
20812         win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED;
20813     else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
20814 
20815     win->layout->row.ratio = 0;
20816     win->layout->row.filled = 0;
20817     win->layout->row.item_offset = 0;
20818     win->layout->row.item_width = (float)width;
20819 }
20820 
20821 NK_API float
20822 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
20823 {
20824     struct nk_window *win;
20825     NK_ASSERT(ctx);
20826     NK_ASSERT(pixel_width);
20827     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
20828     win = ctx->current;
20829     return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
20830 }
20831 
20832 NK_API void
20833 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
20834 {
20835     nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
20836 }
20837 
20838 NK_API void
20839 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
20840 {
20841     nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
20842 }
20843 
20844 NK_API void
20845 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
20846     float row_height, int cols)
20847 {
20848     struct nk_window *win;
20849     struct nk_panel *layout;
20850 
20851     NK_ASSERT(ctx);
20852     NK_ASSERT(ctx->current);
20853     NK_ASSERT(ctx->current->layout);
20854     if (!ctx || !ctx->current || !ctx->current->layout)
20855         return;
20856 
20857     win = ctx->current;
20858     layout = win->layout;
20859     nk_panel_layout(ctx, win, row_height, cols);
20860     if (fmt == NK_DYNAMIC)
20861         layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
20862     else layout->row.type = NK_LAYOUT_STATIC_ROW;
20863 
20864     layout->row.ratio = 0;
20865     layout->row.filled = 0;
20866     layout->row.item_width = 0;
20867     layout->row.item_offset = 0;
20868     layout->row.columns = cols;
20869 }
20870 
20871 NK_API void
20872 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
20873 {
20874     struct nk_window *win;
20875     struct nk_panel *layout;
20876 
20877     NK_ASSERT(ctx);
20878     NK_ASSERT(ctx->current);
20879     NK_ASSERT(ctx->current->layout);
20880     if (!ctx || !ctx->current || !ctx->current->layout)
20881         return;
20882 
20883     win = ctx->current;
20884     layout = win->layout;
20885     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
20886     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
20887         return;
20888 
20889     if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
20890         float ratio = ratio_or_width;
20891         if ((ratio + layout->row.filled) > 1.0f) return;
20892         if (ratio > 0.0f)
20893             layout->row.item_width = NK_SATURATE(ratio);
20894         else layout->row.item_width = 1.0f - layout->row.filled;
20895     } else layout->row.item_width = ratio_or_width;
20896 }
20897 
20898 NK_API void
20899 nk_layout_row_end(struct nk_context *ctx)
20900 {
20901     struct nk_window *win;
20902     struct nk_panel *layout;
20903 
20904     NK_ASSERT(ctx);
20905     NK_ASSERT(ctx->current);
20906     NK_ASSERT(ctx->current->layout);
20907     if (!ctx || !ctx->current || !ctx->current->layout)
20908         return;
20909 
20910     win = ctx->current;
20911     layout = win->layout;
20912     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
20913     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
20914         return;
20915     layout->row.item_width = 0;
20916     layout->row.item_offset = 0;
20917 }
20918 
20919 NK_API void
20920 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
20921     float height, int cols, const float *ratio)
20922 {
20923     int i;
20924     int n_undef = 0;
20925     struct nk_window *win;
20926     struct nk_panel *layout;
20927 
20928     NK_ASSERT(ctx);
20929     NK_ASSERT(ctx->current);
20930     NK_ASSERT(ctx->current->layout);
20931     if (!ctx || !ctx->current || !ctx->current->layout)
20932         return;
20933 
20934     win = ctx->current;
20935     layout = win->layout;
20936     nk_panel_layout(ctx, win, height, cols);
20937     if (fmt == NK_DYNAMIC) {
20938         /* calculate width of undefined widget ratios */
20939         float r = 0;
20940         layout->row.ratio = ratio;
20941         for (i = 0; i < cols; ++i) {
20942             if (ratio[i] < 0.0f)
20943                 n_undef++;
20944             else r += ratio[i];
20945         }
20946         r = NK_SATURATE(1.0f - r);
20947         layout->row.type = NK_LAYOUT_DYNAMIC;
20948         layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
20949     } else {
20950         layout->row.ratio = ratio;
20951         layout->row.type = NK_LAYOUT_STATIC;
20952         layout->row.item_width = 0;
20953         layout->row.item_offset = 0;
20954     }
20955     layout->row.item_offset = 0;
20956     layout->row.filled = 0;
20957 }
20958 
20959 NK_API void
20960 nk_layout_row_template_begin(struct nk_context *ctx, float height)
20961 {
20962     struct nk_window *win;
20963     struct nk_panel *layout;
20964 
20965     NK_ASSERT(ctx);
20966     NK_ASSERT(ctx->current);
20967     NK_ASSERT(ctx->current->layout);
20968     if (!ctx || !ctx->current || !ctx->current->layout)
20969         return;
20970 
20971     win = ctx->current;
20972     layout = win->layout;
20973     nk_panel_layout(ctx, win, height, 1);
20974     layout->row.type = NK_LAYOUT_TEMPLATE;
20975     layout->row.columns = 0;
20976     layout->row.ratio = 0;
20977     layout->row.item_width = 0;
20978     layout->row.item_height = 0;
20979     layout->row.item_offset = 0;
20980     layout->row.filled = 0;
20981     layout->row.item.x = 0;
20982     layout->row.item.y = 0;
20983     layout->row.item.w = 0;
20984     layout->row.item.h = 0;
20985 }
20986 
20987 NK_API void
20988 nk_layout_row_template_push_dynamic(struct nk_context *ctx)
20989 {
20990     struct nk_window *win;
20991     struct nk_panel *layout;
20992 
20993     NK_ASSERT(ctx);
20994     NK_ASSERT(ctx->current);
20995     NK_ASSERT(ctx->current->layout);
20996     if (!ctx || !ctx->current || !ctx->current->layout)
20997         return;
20998 
20999     win = ctx->current;
21000     layout = win->layout;
21001     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
21002     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
21003     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
21004     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
21005     layout->row.templates[layout->row.columns++] = -1.0f;
21006 }
21007 
21008 NK_API void
21009 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
21010 {
21011     struct nk_window *win;
21012     struct nk_panel *layout;
21013 
21014     NK_ASSERT(ctx);
21015     NK_ASSERT(ctx->current);
21016     NK_ASSERT(ctx->current->layout);
21017     if (!ctx || !ctx->current || !ctx->current->layout)
21018         return;
21019 
21020     win = ctx->current;
21021     layout = win->layout;
21022     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
21023     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
21024     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
21025     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
21026     layout->row.templates[layout->row.columns++] = -min_width;
21027 }
21028 
21029 NK_API void
21030 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
21031 {
21032     struct nk_window *win;
21033     struct nk_panel *layout;
21034 
21035     NK_ASSERT(ctx);
21036     NK_ASSERT(ctx->current);
21037     NK_ASSERT(ctx->current->layout);
21038     if (!ctx || !ctx->current || !ctx->current->layout)
21039         return;
21040 
21041     win = ctx->current;
21042     layout = win->layout;
21043     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
21044     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
21045     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
21046     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
21047     layout->row.templates[layout->row.columns++] = width;
21048 }
21049 
21050 NK_API void
21051 nk_layout_row_template_end(struct nk_context *ctx)
21052 {
21053     struct nk_window *win;
21054     struct nk_panel *layout;
21055 
21056     int i = 0;
21057     int variable_count = 0;
21058     int min_variable_count = 0;
21059     float min_fixed_width = 0.0f;
21060     float total_fixed_width = 0.0f;
21061     float max_variable_width = 0.0f;
21062 
21063     NK_ASSERT(ctx);
21064     NK_ASSERT(ctx->current);
21065     NK_ASSERT(ctx->current->layout);
21066     if (!ctx || !ctx->current || !ctx->current->layout)
21067         return;
21068 
21069     win = ctx->current;
21070     layout = win->layout;
21071     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
21072     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
21073     for (i = 0; i < layout->row.columns; ++i) {
21074         float width = layout->row.templates[i];
21075         if (width >= 0.0f) {
21076             total_fixed_width += width;
21077             min_fixed_width += width;
21078         } else if (width < -1.0f) {
21079             width = -width;
21080             total_fixed_width += width;
21081             max_variable_width = NK_MAX(max_variable_width, width);
21082             variable_count++;
21083         } else {
21084             min_variable_count++;
21085             variable_count++;
21086         }
21087     }
21088     if (variable_count) {
21089         float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
21090                             layout->bounds.w, layout->row.columns);
21091         float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
21092         int enough_space = var_width >= max_variable_width;
21093         if (!enough_space)
21094             var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
21095         for (i = 0; i < layout->row.columns; ++i) {
21096             float *width = &layout->row.templates[i];
21097             *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
21098         }
21099     }
21100 }
21101 
21102 NK_API void
21103 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
21104     float height, int widget_count)
21105 {
21106     struct nk_window *win;
21107     struct nk_panel *layout;
21108 
21109     NK_ASSERT(ctx);
21110     NK_ASSERT(ctx->current);
21111     NK_ASSERT(ctx->current->layout);
21112     if (!ctx || !ctx->current || !ctx->current->layout)
21113         return;
21114 
21115     win = ctx->current;
21116     layout = win->layout;
21117     nk_panel_layout(ctx, win, height, widget_count);
21118     if (fmt == NK_STATIC)
21119         layout->row.type = NK_LAYOUT_STATIC_FREE;
21120     else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
21121 
21122     layout->row.ratio = 0;
21123     layout->row.filled = 0;
21124     layout->row.item_width = 0;
21125     layout->row.item_offset = 0;
21126 }
21127 
21128 NK_API void
21129 nk_layout_space_end(struct nk_context *ctx)
21130 {
21131     struct nk_window *win;
21132     struct nk_panel *layout;
21133 
21134     NK_ASSERT(ctx);
21135     NK_ASSERT(ctx->current);
21136     NK_ASSERT(ctx->current->layout);
21137     if (!ctx || !ctx->current || !ctx->current->layout)
21138         return;
21139 
21140     win = ctx->current;
21141     layout = win->layout;
21142     layout->row.item_width = 0;
21143     layout->row.item_height = 0;
21144     layout->row.item_offset = 0;
21145     nk_zero(&layout->row.item, sizeof(layout->row.item));
21146 }
21147 
21148 NK_API void
21149 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
21150 {
21151     struct nk_window *win;
21152     struct nk_panel *layout;
21153 
21154     NK_ASSERT(ctx);
21155     NK_ASSERT(ctx->current);
21156     NK_ASSERT(ctx->current->layout);
21157     if (!ctx || !ctx->current || !ctx->current->layout)
21158         return;
21159 
21160     win = ctx->current;
21161     layout = win->layout;
21162     layout->row.item = rect;
21163 }
21164 
21165 NK_API struct nk_rect
21166 nk_layout_space_bounds(struct nk_context *ctx)
21167 {
21168     struct nk_rect ret;
21169     struct nk_window *win;
21170     struct nk_panel *layout;
21171 
21172     NK_ASSERT(ctx);
21173     NK_ASSERT(ctx->current);
21174     NK_ASSERT(ctx->current->layout);
21175     win = ctx->current;
21176     layout = win->layout;
21177 
21178     ret.x = layout->clip.x;
21179     ret.y = layout->clip.y;
21180     ret.w = layout->clip.w;
21181     ret.h = layout->row.height;
21182     return ret;
21183 }
21184 
21185 NK_API struct nk_rect
21186 nk_layout_widget_bounds(struct nk_context *ctx)
21187 {
21188     struct nk_rect ret;
21189     struct nk_window *win;
21190     struct nk_panel *layout;
21191 
21192     NK_ASSERT(ctx);
21193     NK_ASSERT(ctx->current);
21194     NK_ASSERT(ctx->current->layout);
21195     win = ctx->current;
21196     layout = win->layout;
21197 
21198     ret.x = layout->at_x;
21199     ret.y = layout->at_y;
21200     ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
21201     ret.h = layout->row.height;
21202     return ret;
21203 }
21204 
21205 NK_API struct nk_vec2
21206 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
21207 {
21208     struct nk_window *win;
21209     struct nk_panel *layout;
21210 
21211     NK_ASSERT(ctx);
21212     NK_ASSERT(ctx->current);
21213     NK_ASSERT(ctx->current->layout);
21214     win = ctx->current;
21215     layout = win->layout;
21216 
21217     ret.x += layout->at_x - (float)*layout->offset_x;
21218     ret.y += layout->at_y - (float)*layout->offset_y;
21219     return ret;
21220 }
21221 
21222 NK_API struct nk_vec2
21223 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
21224 {
21225     struct nk_window *win;
21226     struct nk_panel *layout;
21227 
21228     NK_ASSERT(ctx);
21229     NK_ASSERT(ctx->current);
21230     NK_ASSERT(ctx->current->layout);
21231     win = ctx->current;
21232     layout = win->layout;
21233 
21234     ret.x += -layout->at_x + (float)*layout->offset_x;
21235     ret.y += -layout->at_y + (float)*layout->offset_y;
21236     return ret;
21237 }
21238 
21239 NK_API struct nk_rect
21240 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret)
21241 {
21242     struct nk_window *win;
21243     struct nk_panel *layout;
21244 
21245     NK_ASSERT(ctx);
21246     NK_ASSERT(ctx->current);
21247     NK_ASSERT(ctx->current->layout);
21248     win = ctx->current;
21249     layout = win->layout;
21250 
21251     ret.x += layout->at_x - (float)*layout->offset_x;
21252     ret.y += layout->at_y - (float)*layout->offset_y;
21253     return ret;
21254 }
21255 
21256 NK_API struct nk_rect
21257 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret)
21258 {
21259     struct nk_window *win;
21260     struct nk_panel *layout;
21261 
21262     NK_ASSERT(ctx);
21263     NK_ASSERT(ctx->current);
21264     NK_ASSERT(ctx->current->layout);
21265     win = ctx->current;
21266     layout = win->layout;
21267 
21268     ret.x += -layout->at_x + (float)*layout->offset_x;
21269     ret.y += -layout->at_y + (float)*layout->offset_y;
21270     return ret;
21271 }
21272 
21273 NK_INTERN void
21274 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
21275 {
21276     struct nk_panel *layout = win->layout;
21277     struct nk_vec2 spacing = ctx->style.window.spacing;
21278     const float row_height = layout->row.height - spacing.y;
21279     nk_panel_layout(ctx, win, row_height, layout->row.columns);
21280 }
21281 
21282 NK_INTERN void
21283 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
21284     struct nk_window *win, int modify)
21285 {
21286     struct nk_panel *layout;
21287     const struct nk_style *style;
21288 
21289     struct nk_vec2 spacing;
21290     struct nk_vec2 padding;
21291 
21292     float item_offset = 0;
21293     float item_width = 0;
21294     float item_spacing = 0;
21295     float panel_space = 0;
21296 
21297     NK_ASSERT(ctx);
21298     NK_ASSERT(ctx->current);
21299     NK_ASSERT(ctx->current->layout);
21300     if (!ctx || !ctx->current || !ctx->current->layout)
21301         return;
21302 
21303     win = ctx->current;
21304     layout = win->layout;
21305     style = &ctx->style;
21306     NK_ASSERT(bounds);
21307 
21308     spacing = style->window.spacing;
21309     padding = nk_panel_get_padding(style, layout->type);
21310     panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
21311                                             layout->bounds.w, layout->row.columns);
21312 
21313     /* calculate the width of one item inside the current layout space */
21314     switch (layout->row.type) {
21315     case NK_LAYOUT_DYNAMIC_FIXED: {
21316         /* scaling fixed size widgets item width */
21317         item_width = NK_MAX(1.0f,panel_space) / (float)layout->row.columns;
21318         item_offset = (float)layout->row.index * item_width;
21319         item_spacing = (float)layout->row.index * spacing.x;
21320     } break;
21321     case NK_LAYOUT_DYNAMIC_ROW: {
21322         /* scaling single ratio widget width */
21323         item_width = layout->row.item_width * panel_space;
21324         item_offset = layout->row.item_offset;
21325         item_spacing = 0;
21326 
21327         if (modify) {
21328             layout->row.item_offset += item_width + spacing.x;
21329             layout->row.filled += layout->row.item_width;
21330             layout->row.index = 0;
21331         }
21332     } break;
21333     case NK_LAYOUT_DYNAMIC_FREE: {
21334         /* panel width depended free widget placing */
21335         bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
21336         bounds->x -= (float)*layout->offset_x;
21337         bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
21338         bounds->y -= (float)*layout->offset_y;
21339         bounds->w = layout->bounds.w  * layout->row.item.w;
21340         bounds->h = layout->row.height * layout->row.item.h;
21341         return;
21342     } break;
21343     case NK_LAYOUT_DYNAMIC: {
21344         /* scaling arrays of panel width ratios for every widget */
21345         float ratio;
21346         NK_ASSERT(layout->row.ratio);
21347         ratio = (layout->row.ratio[layout->row.index] < 0) ?
21348             layout->row.item_width : layout->row.ratio[layout->row.index];
21349 
21350         item_spacing = (float)layout->row.index * spacing.x;
21351         item_width = (ratio * panel_space);
21352         item_offset = layout->row.item_offset;
21353 
21354         if (modify) {
21355             layout->row.item_offset += item_width;
21356             layout->row.filled += ratio;
21357         }
21358     } break;
21359     case NK_LAYOUT_STATIC_FIXED: {
21360         /* non-scaling fixed widgets item width */
21361         item_width = layout->row.item_width;
21362         item_offset = (float)layout->row.index * item_width;
21363         item_spacing = (float)layout->row.index * spacing.x;
21364     } break;
21365     case NK_LAYOUT_STATIC_ROW: {
21366         /* scaling single ratio widget width */
21367         item_width = layout->row.item_width;
21368         item_offset = layout->row.item_offset;
21369         item_spacing = (float)layout->row.index * spacing.x;
21370         if (modify) layout->row.item_offset += item_width;
21371     } break;
21372     case NK_LAYOUT_STATIC_FREE: {
21373         /* free widget placing */
21374         bounds->x = layout->at_x + layout->row.item.x;
21375         bounds->w = layout->row.item.w;
21376         if (((bounds->x + bounds->w) > layout->max_x) && modify)
21377             layout->max_x = (bounds->x + bounds->w);
21378         bounds->x -= (float)*layout->offset_x;
21379         bounds->y = layout->at_y + layout->row.item.y;
21380         bounds->y -= (float)*layout->offset_y;
21381         bounds->h = layout->row.item.h;
21382         return;
21383     } break;
21384     case NK_LAYOUT_STATIC: {
21385         /* non-scaling array of panel pixel width for every widget */
21386         item_spacing = (float)layout->row.index * spacing.x;
21387         item_width = layout->row.ratio[layout->row.index];
21388         item_offset = layout->row.item_offset;
21389         if (modify) layout->row.item_offset += item_width;
21390     } break;
21391     case NK_LAYOUT_TEMPLATE: {
21392         /* stretchy row layout with combined dynamic/static widget width*/
21393         NK_ASSERT(layout->row.index < layout->row.columns);
21394         NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
21395         item_width = layout->row.templates[layout->row.index];
21396         item_offset = layout->row.item_offset;
21397         item_spacing = (float)layout->row.index * spacing.x;
21398         if (modify) layout->row.item_offset += item_width;
21399     } break;
21400     default: NK_ASSERT(0); break;
21401     };
21402 
21403     /* set the bounds of the newly allocated widget */
21404     bounds->w = item_width;
21405     bounds->h = layout->row.height - spacing.y;
21406     bounds->y = layout->at_y - (float)*layout->offset_y;
21407     bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
21408     if (((bounds->x + bounds->w) > layout->max_x) && modify)
21409         layout->max_x = bounds->x + bounds->w;
21410     bounds->x -= (float)*layout->offset_x;
21411 }
21412 
21413 NK_INTERN void
21414 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
21415 {
21416     struct nk_window *win;
21417     struct nk_panel *layout;
21418 
21419     NK_ASSERT(ctx);
21420     NK_ASSERT(ctx->current);
21421     NK_ASSERT(ctx->current->layout);
21422     if (!ctx || !ctx->current || !ctx->current->layout)
21423         return;
21424 
21425     /* check if the end of the row has been hit and begin new row if so */
21426     win = ctx->current;
21427     layout = win->layout;
21428     if (layout->row.index >= layout->row.columns)
21429         nk_panel_alloc_row(ctx, win);
21430 
21431     /* calculate widget position and size */
21432     nk_layout_widget_space(bounds, ctx, win, nk_true);
21433     layout->row.index++;
21434 }
21435 
21436 NK_INTERN void
21437 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
21438 {
21439     float y;
21440     int index;
21441     struct nk_window *win;
21442     struct nk_panel *layout;
21443 
21444     NK_ASSERT(ctx);
21445     NK_ASSERT(ctx->current);
21446     NK_ASSERT(ctx->current->layout);
21447     if (!ctx || !ctx->current || !ctx->current->layout)
21448         return;
21449 
21450     win = ctx->current;
21451     layout = win->layout;
21452     y = layout->at_y;
21453     index = layout->row.index;
21454     if (layout->row.index >= layout->row.columns) {
21455         layout->at_y += layout->row.height;
21456         layout->row.index = 0;
21457     }
21458     nk_layout_widget_space(bounds, ctx, win, nk_false);
21459     if (!layout->row.index) {
21460         bounds->x -= layout->row.item_offset;
21461     }
21462     layout->at_y = y;
21463     layout->row.index = index;
21464 }
21465 
21466 NK_INTERN int
21467 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
21468     struct nk_image *img, const char *title, enum nk_collapse_states *state)
21469 {
21470     struct nk_window *win;
21471     struct nk_panel *layout;
21472     const struct nk_style *style;
21473     struct nk_command_buffer *out;
21474     const struct nk_input *in;
21475     const struct nk_style_button *button;
21476     enum nk_symbol_type symbol;
21477     float row_height;
21478 
21479     struct nk_vec2 item_spacing;
21480     struct nk_rect header = {0,0,0,0};
21481     struct nk_rect sym = {0,0,0,0};
21482     struct nk_text text;
21483 
21484     nk_flags ws = 0;
21485     enum nk_widget_layout_states widget_state;
21486 
21487     NK_ASSERT(ctx);
21488     NK_ASSERT(ctx->current);
21489     NK_ASSERT(ctx->current->layout);
21490     if (!ctx || !ctx->current || !ctx->current->layout)
21491         return 0;
21492 
21493     /* cache some data */
21494     win = ctx->current;
21495     layout = win->layout;
21496     out = &win->buffer;
21497     style = &ctx->style;
21498     item_spacing = style->window.spacing;
21499 
21500     /* calculate header bounds and draw background */
21501     row_height = style->font->height + 2 * style->tab.padding.y;
21502     nk_layout_set_min_row_height(ctx, row_height);
21503     nk_layout_row_dynamic(ctx, row_height, 1);
21504     nk_layout_reset_min_row_height(ctx);
21505 
21506     widget_state = nk_widget(&header, ctx);
21507     if (type == NK_TREE_TAB) {
21508         const struct nk_style_item *background = &style->tab.background;
21509         if (background->type == NK_STYLE_ITEM_IMAGE) {
21510             nk_draw_image(out, header, &background->data.image, nk_white);
21511             text.background = nk_rgba(0,0,0,0);
21512         } else {
21513             text.background = background->data.color;
21514             nk_fill_rect(out, header, 0, style->tab.border_color);
21515             nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
21516                 style->tab.rounding, background->data.color);
21517         }
21518     } else text.background = style->window.background;
21519 
21520     /* update node state */
21521     in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
21522     in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
21523     if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
21524         *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
21525 
21526     /* select correct button style */
21527     if (*state == NK_MAXIMIZED) {
21528         symbol = style->tab.sym_maximize;
21529         if (type == NK_TREE_TAB)
21530             button = &style->tab.tab_maximize_button;
21531         else button = &style->tab.node_maximize_button;
21532     } else {
21533         symbol = style->tab.sym_minimize;
21534         if (type == NK_TREE_TAB)
21535             button = &style->tab.tab_minimize_button;
21536         else button = &style->tab.node_minimize_button;
21537     }
21538 
21539     {/* draw triangle button */
21540     sym.w = sym.h = style->font->height;
21541     sym.y = header.y + style->tab.padding.y;
21542     sym.x = header.x + style->tab.padding.x;
21543     nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
21544         button, 0, style->font);
21545 
21546     if (img) {
21547         /* draw optional image icon */
21548         sym.x = sym.x + sym.w + 4 * item_spacing.x;
21549         nk_draw_image(&win->buffer, sym, img, nk_white);
21550         sym.w = style->font->height + style->tab.spacing.x;}
21551     }
21552 
21553     {/* draw label */
21554     struct nk_rect label;
21555     header.w = NK_MAX(header.w, sym.w + item_spacing.x);
21556     label.x = sym.x + sym.w + item_spacing.x;
21557     label.y = sym.y;
21558     label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
21559     label.h = style->font->height;
21560     text.text = style->tab.text;
21561     text.padding = nk_vec2(0,0);
21562     nk_widget_text(out, label, title, nk_strlen(title), &text,
21563         NK_TEXT_LEFT, style->font);}
21564 
21565     /* increase x-axis cursor widget position pointer */
21566     if (*state == NK_MAXIMIZED) {
21567         layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
21568         layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
21569         layout->bounds.w -= (style->tab.indent + style->window.padding.x);
21570         layout->row.tree_depth++;
21571         return nk_true;
21572     } else return nk_false;
21573 }
21574 
21575 NK_INTERN int
21576 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
21577     struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
21578     const char *hash, int len, int line)
21579 {
21580     struct nk_window *win = ctx->current;
21581     int title_len = 0;
21582     nk_hash tree_hash = 0;
21583     nk_uint *state = 0;
21584 
21585     /* retrieve tree state from internal widget state tables */
21586     if (!hash) {
21587         title_len = (int)nk_strlen(title);
21588         tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
21589     } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
21590     state = nk_find_value(win, tree_hash);
21591     if (!state) {
21592         state = nk_add_value(ctx, win, tree_hash, 0);
21593         *state = initial_state;
21594     }
21595     return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
21596 }
21597 
21598 NK_API int
21599 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
21600     const char *title, enum nk_collapse_states *state)
21601 {return nk_tree_state_base(ctx, type, 0, title, state);}
21602 
21603 NK_API int
21604 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
21605     struct nk_image img, const char *title, enum nk_collapse_states *state)
21606 {return nk_tree_state_base(ctx, type, &img, title, state);}
21607 
21608 NK_API void
21609 nk_tree_state_pop(struct nk_context *ctx)
21610 {
21611     struct nk_window *win = 0;
21612     struct nk_panel *layout = 0;
21613 
21614     NK_ASSERT(ctx);
21615     NK_ASSERT(ctx->current);
21616     NK_ASSERT(ctx->current->layout);
21617     if (!ctx || !ctx->current || !ctx->current->layout)
21618         return;
21619 
21620     win = ctx->current;
21621     layout = win->layout;
21622     layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
21623     layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
21624     NK_ASSERT(layout->row.tree_depth);
21625     layout->row.tree_depth--;
21626 }
21627 
21628 NK_API int
21629 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
21630     const char *title, enum nk_collapse_states initial_state,
21631     const char *hash, int len, int line)
21632 {return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);}
21633 
21634 NK_API int
21635 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
21636     struct nk_image img, const char *title, enum nk_collapse_states initial_state,
21637     const char *hash, int len,int seed)
21638 {return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);}
21639 
21640 NK_API void
21641 nk_tree_pop(struct nk_context *ctx)
21642 {nk_tree_state_pop(ctx);}
21643 
21644 /*----------------------------------------------------------------
21645  *
21646  *                          WIDGETS
21647  *
21648  * --------------------------------------------------------------*/
21649 NK_API struct nk_rect
21650 nk_widget_bounds(struct nk_context *ctx)
21651 {
21652     struct nk_rect bounds;
21653     NK_ASSERT(ctx);
21654     NK_ASSERT(ctx->current);
21655     if (!ctx || !ctx->current)
21656         return nk_rect(0,0,0,0);
21657     nk_layout_peek(&bounds, ctx);
21658     return bounds;
21659 }
21660 
21661 NK_API struct nk_vec2
21662 nk_widget_position(struct nk_context *ctx)
21663 {
21664     struct nk_rect bounds;
21665     NK_ASSERT(ctx);
21666     NK_ASSERT(ctx->current);
21667     if (!ctx || !ctx->current)
21668         return nk_vec2(0,0);
21669 
21670     nk_layout_peek(&bounds, ctx);
21671     return nk_vec2(bounds.x, bounds.y);
21672 }
21673 
21674 NK_API struct nk_vec2
21675 nk_widget_size(struct nk_context *ctx)
21676 {
21677     struct nk_rect bounds;
21678     NK_ASSERT(ctx);
21679     NK_ASSERT(ctx->current);
21680     if (!ctx || !ctx->current)
21681         return nk_vec2(0,0);
21682 
21683     nk_layout_peek(&bounds, ctx);
21684     return nk_vec2(bounds.w, bounds.h);
21685 }
21686 
21687 NK_API float
21688 nk_widget_width(struct nk_context *ctx)
21689 {
21690     struct nk_rect bounds;
21691     NK_ASSERT(ctx);
21692     NK_ASSERT(ctx->current);
21693     if (!ctx || !ctx->current)
21694         return 0;
21695 
21696     nk_layout_peek(&bounds, ctx);
21697     return bounds.w;
21698 }
21699 
21700 NK_API float
21701 nk_widget_height(struct nk_context *ctx)
21702 {
21703     struct nk_rect bounds;
21704     NK_ASSERT(ctx);
21705     NK_ASSERT(ctx->current);
21706     if (!ctx || !ctx->current)
21707         return 0;
21708 
21709     nk_layout_peek(&bounds, ctx);
21710     return bounds.h;
21711 }
21712 
21713 NK_API int
21714 nk_widget_is_hovered(struct nk_context *ctx)
21715 {
21716     struct nk_rect c, v;
21717     struct nk_rect bounds;
21718     NK_ASSERT(ctx);
21719     NK_ASSERT(ctx->current);
21720     if (!ctx || !ctx->current || ctx->active != ctx->current)
21721         return 0;
21722 
21723     c = ctx->current->layout->clip;
21724     c.x = (float)((int)c.x);
21725     c.y = (float)((int)c.y);
21726     c.w = (float)((int)c.w);
21727     c.h = (float)((int)c.h);
21728 
21729     nk_layout_peek(&bounds, ctx);
21730     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
21731     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
21732         return 0;
21733     return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
21734 }
21735 
21736 NK_API int
21737 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
21738 {
21739     struct nk_rect c, v;
21740     struct nk_rect bounds;
21741     NK_ASSERT(ctx);
21742     NK_ASSERT(ctx->current);
21743     if (!ctx || !ctx->current || ctx->active != ctx->current)
21744         return 0;
21745 
21746     c = ctx->current->layout->clip;
21747     c.x = (float)((int)c.x);
21748     c.y = (float)((int)c.y);
21749     c.w = (float)((int)c.w);
21750     c.h = (float)((int)c.h);
21751 
21752     nk_layout_peek(&bounds, ctx);
21753     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
21754     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
21755         return 0;
21756     return nk_input_mouse_clicked(&ctx->input, btn, bounds);
21757 }
21758 
21759 NK_API int
21760 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
21761 {
21762     struct nk_rect c, v;
21763     struct nk_rect bounds;
21764     NK_ASSERT(ctx);
21765     NK_ASSERT(ctx->current);
21766     if (!ctx || !ctx->current || ctx->active != ctx->current)
21767         return 0;
21768 
21769     c = ctx->current->layout->clip;
21770     c.x = (float)((int)c.x);
21771     c.y = (float)((int)c.y);
21772     c.w = (float)((int)c.w);
21773     c.h = (float)((int)c.h);
21774 
21775     nk_layout_peek(&bounds, ctx);
21776     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
21777     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
21778         return 0;
21779     return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
21780 }
21781 
21782 NK_API enum nk_widget_layout_states
21783 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
21784 {
21785     struct nk_rect c, v;
21786     struct nk_window *win;
21787     struct nk_panel *layout;
21788     const struct nk_input *in;
21789 
21790     NK_ASSERT(ctx);
21791     NK_ASSERT(ctx->current);
21792     NK_ASSERT(ctx->current->layout);
21793     if (!ctx || !ctx->current || !ctx->current->layout)
21794         return NK_WIDGET_INVALID;
21795 
21796     /* allocate space and check if the widget needs to be updated and drawn */
21797     nk_panel_alloc_space(bounds, ctx);
21798     win = ctx->current;
21799     layout = win->layout;
21800     in = &ctx->input;
21801     c = layout->clip;
21802 
21803     /*  if one of these triggers you forgot to add an `if` condition around either
21804         a window, group, popup, combobox or contextual menu `begin` and `end` block.
21805         Example:
21806             if (nk_begin(...) {...} nk_end(...); or
21807             if (nk_group_begin(...) { nk_group_end(...);} */
21808     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
21809     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
21810     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
21811 
21812     /* need to convert to int here to remove floating point errors */
21813     bounds->x = (float)((int)bounds->x);
21814     bounds->y = (float)((int)bounds->y);
21815     bounds->w = (float)((int)bounds->w);
21816     bounds->h = (float)((int)bounds->h);
21817 
21818     c.x = (float)((int)c.x);
21819     c.y = (float)((int)c.y);
21820     c.w = (float)((int)c.w);
21821     c.h = (float)((int)c.h);
21822 
21823     nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
21824     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
21825         return NK_WIDGET_INVALID;
21826     if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
21827         return NK_WIDGET_ROM;
21828     return NK_WIDGET_VALID;
21829 }
21830 
21831 NK_API enum nk_widget_layout_states
21832 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
21833     struct nk_vec2 item_padding)
21834 {
21835     /* update the bounds to stand without padding  */
21836     struct nk_window *win;
21837     struct nk_style *style;
21838     struct nk_panel *layout;
21839     enum nk_widget_layout_states state;
21840     struct nk_vec2 panel_padding;
21841 
21842     NK_ASSERT(ctx);
21843     NK_ASSERT(ctx->current);
21844     NK_ASSERT(ctx->current->layout);
21845     if (!ctx || !ctx->current || !ctx->current->layout)
21846         return NK_WIDGET_INVALID;
21847 
21848     win = ctx->current;
21849     style = &ctx->style;
21850     layout = win->layout;
21851     state = nk_widget(bounds, ctx);
21852 
21853     panel_padding = nk_panel_get_padding(style, layout->type);
21854     if (layout->row.index == 1) {
21855         bounds->w += panel_padding.x;
21856         bounds->x -= panel_padding.x;
21857     } else bounds->x -= item_padding.x;
21858 
21859     if (layout->row.index == layout->row.columns)
21860         bounds->w += panel_padding.x;
21861     else bounds->w += item_padding.x;
21862     return state;
21863 }
21864 
21865 /*----------------------------------------------------------------
21866  *
21867  *                          MISC
21868  *
21869  * --------------------------------------------------------------*/
21870 NK_API void
21871 nk_spacing(struct nk_context *ctx, int cols)
21872 {
21873     struct nk_window *win;
21874     struct nk_panel *layout;
21875     struct nk_rect none;
21876     int i, index, rows;
21877 
21878     NK_ASSERT(ctx);
21879     NK_ASSERT(ctx->current);
21880     NK_ASSERT(ctx->current->layout);
21881     if (!ctx || !ctx->current || !ctx->current->layout)
21882         return;
21883 
21884     /* spacing over row boundaries */
21885     win = ctx->current;
21886     layout = win->layout;
21887     index = (layout->row.index + cols) % layout->row.columns;
21888     rows = (layout->row.index + cols) / layout->row.columns;
21889     if (rows) {
21890         for (i = 0; i < rows; ++i)
21891             nk_panel_alloc_row(ctx, win);
21892         cols = index;
21893     }
21894     /* non table layout need to allocate space */
21895     if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
21896         layout->row.type != NK_LAYOUT_STATIC_FIXED) {
21897         for (i = 0; i < cols; ++i)
21898             nk_panel_alloc_space(&none, ctx);
21899     }
21900     layout->row.index = index;
21901 }
21902 
21903 /*----------------------------------------------------------------
21904  *
21905  *                          TEXT
21906  *
21907  * --------------------------------------------------------------*/
21908 NK_API void
21909 nk_text_colored(struct nk_context *ctx, const char *str, int len,
21910     nk_flags alignment, struct nk_color color)
21911 {
21912     struct nk_window *win;
21913     const struct nk_style *style;
21914 
21915     struct nk_vec2 item_padding;
21916     struct nk_rect bounds;
21917     struct nk_text text;
21918 
21919     NK_ASSERT(ctx);
21920     NK_ASSERT(ctx->current);
21921     NK_ASSERT(ctx->current->layout);
21922     if (!ctx || !ctx->current || !ctx->current->layout) return;
21923 
21924     win = ctx->current;
21925     style = &ctx->style;
21926     nk_panel_alloc_space(&bounds, ctx);
21927     item_padding = style->text.padding;
21928 
21929     text.padding.x = item_padding.x;
21930     text.padding.y = item_padding.y;
21931     text.background = style->window.background;
21932     text.text = color;
21933     nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
21934 }
21935 
21936 NK_API void
21937 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
21938     int len, struct nk_color color)
21939 {
21940     struct nk_window *win;
21941     const struct nk_style *style;
21942 
21943     struct nk_vec2 item_padding;
21944     struct nk_rect bounds;
21945     struct nk_text text;
21946 
21947     NK_ASSERT(ctx);
21948     NK_ASSERT(ctx->current);
21949     NK_ASSERT(ctx->current->layout);
21950     if (!ctx || !ctx->current || !ctx->current->layout) return;
21951 
21952     win = ctx->current;
21953     style = &ctx->style;
21954     nk_panel_alloc_space(&bounds, ctx);
21955     item_padding = style->text.padding;
21956 
21957     text.padding.x = item_padding.x;
21958     text.padding.y = item_padding.y;
21959     text.background = style->window.background;
21960     text.text = color;
21961     nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
21962 }
21963 
21964 #ifdef NK_INCLUDE_STANDARD_VARARGS
21965 NK_API void
21966 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
21967     struct nk_color color, const char *fmt, ...)
21968 {
21969     char buf[256];
21970     va_list args;
21971     va_start(args, fmt);
21972     nk_strfmt(buf, NK_LEN(buf), fmt, args);
21973     nk_label_colored(ctx, buf, flags, color);
21974     va_end(args);
21975 }
21976 
21977 NK_API void
21978 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
21979     const char *fmt, ...)
21980 {
21981     char buf[256];
21982     va_list args;
21983     va_start(args, fmt);
21984     nk_strfmt(buf, NK_LEN(buf), fmt, args);
21985     nk_label_colored_wrap(ctx, buf, color);
21986     va_end(args);
21987 }
21988 
21989 NK_API void
21990 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
21991 {
21992     char buf[256];
21993     va_list args;
21994     va_start(args, fmt);
21995     nk_strfmt(buf, NK_LEN(buf), fmt, args);
21996     nk_label(ctx, buf, flags);
21997     va_end(args);
21998 }
21999 
22000 NK_API void
22001 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
22002 {
22003     char buf[256];
22004     va_list args;
22005     va_start(args, fmt);
22006     nk_strfmt(buf, NK_LEN(buf), fmt, args);
22007     nk_label_wrap(ctx, buf);
22008     va_end(args);
22009 }
22010 
22011 NK_API void
22012 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
22013 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));}
22014 
22015 NK_API void
22016 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
22017 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);}
22018 
22019 NK_API void
22020 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
22021 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);}
22022 
22023 NK_API void
22024 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
22025 {
22026     double double_value = (double)value;
22027     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
22028 }
22029 
22030 NK_API void
22031 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
22032 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);}
22033 
22034 NK_API void
22035 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
22036 {
22037     double c[4]; nk_color_dv(c, color);
22038     nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
22039         p, c[0], c[1], c[2], c[3]);
22040 }
22041 
22042 NK_API void
22043 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
22044 {
22045     char hex[16];
22046     nk_color_hex_rgba(hex, color);
22047     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
22048 }
22049 #endif
22050 
22051 NK_API void
22052 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
22053 {
22054     NK_ASSERT(ctx);
22055     if (!ctx) return;
22056     nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
22057 }
22058 
22059 NK_API void
22060 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
22061 {
22062     NK_ASSERT(ctx);
22063     if (!ctx) return;
22064     nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
22065 }
22066 
22067 NK_API void
22068 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
22069 {nk_text(ctx, str, nk_strlen(str), alignment);}
22070 
22071 NK_API void
22072 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
22073     struct nk_color color)
22074 {nk_text_colored(ctx, str, nk_strlen(str), align, color);}
22075 
22076 NK_API void
22077 nk_label_wrap(struct nk_context *ctx, const char *str)
22078 {nk_text_wrap(ctx, str, nk_strlen(str));}
22079 
22080 NK_API void
22081 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
22082 {nk_text_wrap_colored(ctx, str, nk_strlen(str), color);}
22083 
22084 NK_API void
22085 nk_image(struct nk_context *ctx, struct nk_image img)
22086 {
22087     struct nk_window *win;
22088     struct nk_rect bounds;
22089 
22090     NK_ASSERT(ctx);
22091     NK_ASSERT(ctx->current);
22092     NK_ASSERT(ctx->current->layout);
22093     if (!ctx || !ctx->current || !ctx->current->layout) return;
22094 
22095     win = ctx->current;
22096     if (!nk_widget(&bounds, ctx)) return;
22097     nk_draw_image(&win->buffer, bounds, &img, nk_white);
22098 }
22099 NK_API void
22100 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col)
22101 {
22102     struct nk_window *win;
22103     struct nk_rect bounds;
22104 
22105     NK_ASSERT(ctx);
22106     NK_ASSERT(ctx->current);
22107     NK_ASSERT(ctx->current->layout);
22108     if (!ctx || !ctx->current || !ctx->current->layout) return;
22109 
22110     win = ctx->current;
22111     if (!nk_widget(&bounds, ctx)) return;
22112     nk_draw_image(&win->buffer, bounds, &img, col);
22113 }
22114 /*----------------------------------------------------------------
22115  *
22116  *                          BUTTON
22117  *
22118  * --------------------------------------------------------------*/
22119 NK_API void
22120 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
22121 {
22122     NK_ASSERT(ctx);
22123     if (!ctx) return;
22124     ctx->button_behavior = behavior;
22125 }
22126 
22127 NK_API int
22128 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
22129 {
22130     struct nk_config_stack_button_behavior *button_stack;
22131     struct nk_config_stack_button_behavior_element *element;
22132 
22133     NK_ASSERT(ctx);
22134     if (!ctx) return 0;
22135 
22136     button_stack = &ctx->stacks.button_behaviors;
22137     NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
22138     if (button_stack->head >= (int)NK_LEN(button_stack->elements))
22139         return 0;
22140 
22141     element = &button_stack->elements[button_stack->head++];
22142     element->address = &ctx->button_behavior;
22143     element->old_value = ctx->button_behavior;
22144     ctx->button_behavior = behavior;
22145     return 1;
22146 }
22147 
22148 NK_API int
22149 nk_button_pop_behavior(struct nk_context *ctx)
22150 {
22151     struct nk_config_stack_button_behavior *button_stack;
22152     struct nk_config_stack_button_behavior_element *element;
22153 
22154     NK_ASSERT(ctx);
22155     if (!ctx) return 0;
22156 
22157     button_stack = &ctx->stacks.button_behaviors;
22158     NK_ASSERT(button_stack->head > 0);
22159     if (button_stack->head < 1)
22160         return 0;
22161 
22162     element = &button_stack->elements[--button_stack->head];
22163     *element->address = element->old_value;
22164     return 1;
22165 }
22166 
22167 NK_API int
22168 nk_button_text_styled(struct nk_context *ctx,
22169     const struct nk_style_button *style, const char *title, int len)
22170 {
22171     struct nk_window *win;
22172     struct nk_panel *layout;
22173     const struct nk_input *in;
22174 
22175     struct nk_rect bounds;
22176     enum nk_widget_layout_states state;
22177 
22178     NK_ASSERT(ctx);
22179     NK_ASSERT(style);
22180     NK_ASSERT(ctx->current);
22181     NK_ASSERT(ctx->current->layout);
22182     if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
22183 
22184     win = ctx->current;
22185     layout = win->layout;
22186     state = nk_widget(&bounds, ctx);
22187 
22188     if (!state) return 0;
22189     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22190     return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
22191                     title, len, style->text_alignment, ctx->button_behavior,
22192                     style, in, ctx->style.font);
22193 }
22194 
22195 NK_API int
22196 nk_button_text(struct nk_context *ctx, const char *title, int len)
22197 {
22198     NK_ASSERT(ctx);
22199     if (!ctx) return 0;
22200     return nk_button_text_styled(ctx, &ctx->style.button, title, len);
22201 }
22202 
22203 NK_API int nk_button_label_styled(struct nk_context *ctx,
22204     const struct nk_style_button *style, const char *title)
22205 {return nk_button_text_styled(ctx, style, title, nk_strlen(title));}
22206 
22207 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
22208 {return nk_button_text(ctx, title, nk_strlen(title));}
22209 
22210 NK_API int
22211 nk_button_color(struct nk_context *ctx, struct nk_color color)
22212 {
22213     struct nk_window *win;
22214     struct nk_panel *layout;
22215     const struct nk_input *in;
22216     struct nk_style_button button;
22217 
22218     int ret = 0;
22219     struct nk_rect bounds;
22220     struct nk_rect content;
22221     enum nk_widget_layout_states state;
22222 
22223     NK_ASSERT(ctx);
22224     NK_ASSERT(ctx->current);
22225     NK_ASSERT(ctx->current->layout);
22226     if (!ctx || !ctx->current || !ctx->current->layout)
22227         return 0;
22228 
22229     win = ctx->current;
22230     layout = win->layout;
22231 
22232     state = nk_widget(&bounds, ctx);
22233     if (!state) return 0;
22234     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22235 
22236     button = ctx->style.button;
22237     button.normal = nk_style_item_color(color);
22238     button.hover = nk_style_item_color(color);
22239     button.active = nk_style_item_color(color);
22240     ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
22241                 &button, in, ctx->button_behavior, &content);
22242     nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
22243     return ret;
22244 }
22245 
22246 NK_API int
22247 nk_button_symbol_styled(struct nk_context *ctx,
22248     const struct nk_style_button *style, enum nk_symbol_type symbol)
22249 {
22250     struct nk_window *win;
22251     struct nk_panel *layout;
22252     const struct nk_input *in;
22253 
22254     struct nk_rect bounds;
22255     enum nk_widget_layout_states state;
22256 
22257     NK_ASSERT(ctx);
22258     NK_ASSERT(ctx->current);
22259     NK_ASSERT(ctx->current->layout);
22260     if (!ctx || !ctx->current || !ctx->current->layout)
22261         return 0;
22262 
22263     win = ctx->current;
22264     layout = win->layout;
22265     state = nk_widget(&bounds, ctx);
22266     if (!state) return 0;
22267     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22268     return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
22269             symbol, ctx->button_behavior, style, in, ctx->style.font);
22270 }
22271 
22272 NK_API int
22273 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
22274 {
22275     NK_ASSERT(ctx);
22276     if (!ctx) return 0;
22277     return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
22278 }
22279 
22280 NK_API int
22281 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
22282     struct nk_image img)
22283 {
22284     struct nk_window *win;
22285     struct nk_panel *layout;
22286     const struct nk_input *in;
22287 
22288     struct nk_rect bounds;
22289     enum nk_widget_layout_states state;
22290 
22291     NK_ASSERT(ctx);
22292     NK_ASSERT(ctx->current);
22293     NK_ASSERT(ctx->current->layout);
22294     if (!ctx || !ctx->current || !ctx->current->layout)
22295         return 0;
22296 
22297     win = ctx->current;
22298     layout = win->layout;
22299 
22300     state = nk_widget(&bounds, ctx);
22301     if (!state) return 0;
22302     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22303     return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
22304                 img, ctx->button_behavior, style, in);
22305 }
22306 
22307 NK_API int
22308 nk_button_image(struct nk_context *ctx, struct nk_image img)
22309 {
22310     NK_ASSERT(ctx);
22311     if (!ctx) return 0;
22312     return nk_button_image_styled(ctx, &ctx->style.button, img);
22313 }
22314 
22315 NK_API int
22316 nk_button_symbol_text_styled(struct nk_context *ctx,
22317     const struct nk_style_button *style, enum nk_symbol_type symbol,
22318     const char *text, int len, nk_flags align)
22319 {
22320     struct nk_window *win;
22321     struct nk_panel *layout;
22322     const struct nk_input *in;
22323 
22324     struct nk_rect bounds;
22325     enum nk_widget_layout_states state;
22326 
22327     NK_ASSERT(ctx);
22328     NK_ASSERT(ctx->current);
22329     NK_ASSERT(ctx->current->layout);
22330     if (!ctx || !ctx->current || !ctx->current->layout)
22331         return 0;
22332 
22333     win = ctx->current;
22334     layout = win->layout;
22335 
22336     state = nk_widget(&bounds, ctx);
22337     if (!state) return 0;
22338     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22339     return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
22340                 symbol, text, len, align, ctx->button_behavior,
22341                 style, ctx->style.font, in);
22342 }
22343 
22344 NK_API int
22345 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
22346     const char* text, int len, nk_flags align)
22347 {
22348     NK_ASSERT(ctx);
22349     if (!ctx) return 0;
22350     return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
22351 }
22352 
22353 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
22354     const char *label, nk_flags align)
22355 {return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);}
22356 
22357 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx,
22358     const struct nk_style_button *style, enum nk_symbol_type symbol,
22359     const char *title, nk_flags align)
22360 {return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);}
22361 
22362 NK_API int
22363 nk_button_image_text_styled(struct nk_context *ctx,
22364     const struct nk_style_button *style, struct nk_image img, const char *text,
22365     int len, nk_flags align)
22366 {
22367     struct nk_window *win;
22368     struct nk_panel *layout;
22369     const struct nk_input *in;
22370 
22371     struct nk_rect bounds;
22372     enum nk_widget_layout_states state;
22373 
22374     NK_ASSERT(ctx);
22375     NK_ASSERT(ctx->current);
22376     NK_ASSERT(ctx->current->layout);
22377     if (!ctx || !ctx->current || !ctx->current->layout)
22378         return 0;
22379 
22380     win = ctx->current;
22381     layout = win->layout;
22382 
22383     state = nk_widget(&bounds, ctx);
22384     if (!state) return 0;
22385     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22386     return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
22387             bounds, img, text, len, align, ctx->button_behavior,
22388             style, ctx->style.font, in);
22389 }
22390 
22391 NK_API int
22392 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
22393     const char *text, int len, nk_flags align)
22394 {return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);}
22395 
22396 
22397 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
22398     const char *label, nk_flags align)
22399 {return nk_button_image_text(ctx, img, label, nk_strlen(label), align);}
22400 
22401 NK_API int nk_button_image_label_styled(struct nk_context *ctx,
22402     const struct nk_style_button *style, struct nk_image img,
22403     const char *label, nk_flags text_alignment)
22404 {return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);}
22405 
22406 /*----------------------------------------------------------------
22407  *
22408  *                          SELECTABLE
22409  *
22410  * --------------------------------------------------------------*/
22411 NK_API int
22412 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
22413     nk_flags align, int *value)
22414 {
22415     struct nk_window *win;
22416     struct nk_panel *layout;
22417     const struct nk_input *in;
22418     const struct nk_style *style;
22419 
22420     enum nk_widget_layout_states state;
22421     struct nk_rect bounds;
22422 
22423     NK_ASSERT(ctx);
22424     NK_ASSERT(value);
22425     NK_ASSERT(ctx->current);
22426     NK_ASSERT(ctx->current->layout);
22427     if (!ctx || !ctx->current || !ctx->current->layout || !value)
22428         return 0;
22429 
22430     win = ctx->current;
22431     layout = win->layout;
22432     style = &ctx->style;
22433 
22434     state = nk_widget(&bounds, ctx);
22435     if (!state) return 0;
22436     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22437     return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
22438                 str, len, align, value, &style->selectable, in, style->font);
22439 }
22440 
22441 NK_API int
22442 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
22443     const char *str, int len, nk_flags align, int *value)
22444 {
22445     struct nk_window *win;
22446     struct nk_panel *layout;
22447     const struct nk_input *in;
22448     const struct nk_style *style;
22449 
22450     enum nk_widget_layout_states state;
22451     struct nk_rect bounds;
22452 
22453     NK_ASSERT(ctx);
22454     NK_ASSERT(value);
22455     NK_ASSERT(ctx->current);
22456     NK_ASSERT(ctx->current->layout);
22457     if (!ctx || !ctx->current || !ctx->current->layout || !value)
22458         return 0;
22459 
22460     win = ctx->current;
22461     layout = win->layout;
22462     style = &ctx->style;
22463 
22464     state = nk_widget(&bounds, ctx);
22465     if (!state) return 0;
22466     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22467     return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
22468                 str, len, align, value, &img, &style->selectable, in, style->font);
22469 }
22470 
22471 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
22472     nk_flags align, int value)
22473 {nk_selectable_text(ctx, str, len, align, &value);return value;}
22474 
22475 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
22476 {return nk_selectable_text(ctx, str, nk_strlen(str), align, value);}
22477 
22478 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
22479     const char *str, nk_flags align, int *value)
22480 {return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);}
22481 
22482 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
22483 {nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;}
22484 
22485 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
22486     const char *str, nk_flags align, int value)
22487 {nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;}
22488 
22489 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
22490     const char *str, int len, nk_flags align, int value)
22491 {nk_selectable_image_text(ctx, img, str, len, align, &value);return value;}
22492 
22493 /*----------------------------------------------------------------
22494  *
22495  *                          CHECKBOX
22496  *
22497  * --------------------------------------------------------------*/
22498 NK_API int
22499 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
22500 {
22501     struct nk_window *win;
22502     struct nk_panel *layout;
22503     const struct nk_input *in;
22504     const struct nk_style *style;
22505 
22506     struct nk_rect bounds;
22507     enum nk_widget_layout_states state;
22508 
22509     NK_ASSERT(ctx);
22510     NK_ASSERT(ctx->current);
22511     NK_ASSERT(ctx->current->layout);
22512     if (!ctx || !ctx->current || !ctx->current->layout)
22513         return active;
22514 
22515     win = ctx->current;
22516     style = &ctx->style;
22517     layout = win->layout;
22518 
22519     state = nk_widget(&bounds, ctx);
22520     if (!state) return active;
22521     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22522     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
22523         text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
22524     return active;
22525 }
22526 
22527 NK_API unsigned int
22528 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
22529     unsigned int flags, unsigned int value)
22530 {
22531     int old_active;
22532     NK_ASSERT(ctx);
22533     NK_ASSERT(text);
22534     if (!ctx || !text) return flags;
22535     old_active = (int)((flags & value) & value);
22536     if (nk_check_text(ctx, text, len, old_active))
22537         flags |= value;
22538     else flags &= ~value;
22539     return flags;
22540 }
22541 
22542 NK_API int
22543 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
22544 {
22545     int old_val;
22546     NK_ASSERT(ctx);
22547     NK_ASSERT(text);
22548     NK_ASSERT(active);
22549     if (!ctx || !text || !active) return 0;
22550     old_val = *active;
22551     *active = nk_check_text(ctx, text, len, *active);
22552     return old_val != *active;
22553 }
22554 
22555 NK_API int
22556 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
22557     unsigned int *flags, unsigned int value)
22558 {
22559     int active;
22560     NK_ASSERT(ctx);
22561     NK_ASSERT(text);
22562     NK_ASSERT(flags);
22563     if (!ctx || !text || !flags) return 0;
22564 
22565     active = (int)((*flags & value) & value);
22566     if (nk_checkbox_text(ctx, text, len, &active)) {
22567         if (active) *flags |= value;
22568         else *flags &= ~value;
22569         return 1;
22570     }
22571     return 0;
22572 }
22573 
22574 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
22575 {return nk_check_text(ctx, label, nk_strlen(label), active);}
22576 
22577 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
22578     unsigned int flags, unsigned int value)
22579 {return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);}
22580 
22581 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
22582 {return nk_checkbox_text(ctx, label, nk_strlen(label), active);}
22583 
22584 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
22585     unsigned int *flags, unsigned int value)
22586 {return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);}
22587 
22588 /*----------------------------------------------------------------
22589  *
22590  *                          OPTION
22591  *
22592  * --------------------------------------------------------------*/
22593 NK_API int
22594 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
22595 {
22596     struct nk_window *win;
22597     struct nk_panel *layout;
22598     const struct nk_input *in;
22599     const struct nk_style *style;
22600 
22601     struct nk_rect bounds;
22602     enum nk_widget_layout_states state;
22603 
22604     NK_ASSERT(ctx);
22605     NK_ASSERT(ctx->current);
22606     NK_ASSERT(ctx->current->layout);
22607     if (!ctx || !ctx->current || !ctx->current->layout)
22608         return is_active;
22609 
22610     win = ctx->current;
22611     style = &ctx->style;
22612     layout = win->layout;
22613 
22614     state = nk_widget(&bounds, ctx);
22615     if (!state) return state;
22616     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22617     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
22618         text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
22619     return is_active;
22620 }
22621 
22622 NK_API int
22623 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
22624 {
22625     int old_value;
22626     NK_ASSERT(ctx);
22627     NK_ASSERT(text);
22628     NK_ASSERT(active);
22629     if (!ctx || !text || !active) return 0;
22630     old_value = *active;
22631     *active = nk_option_text(ctx, text, len, old_value);
22632     return old_value != *active;
22633 }
22634 
22635 NK_API int
22636 nk_option_label(struct nk_context *ctx, const char *label, int active)
22637 {return nk_option_text(ctx, label, nk_strlen(label), active);}
22638 
22639 NK_API int
22640 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
22641 {return nk_radio_text(ctx, label, nk_strlen(label), active);}
22642 
22643 /*----------------------------------------------------------------
22644  *
22645  *                          SLIDER
22646  *
22647  * --------------------------------------------------------------*/
22648 NK_API int
22649 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
22650     float value_step)
22651 {
22652     struct nk_window *win;
22653     struct nk_panel *layout;
22654     struct nk_input *in;
22655     const struct nk_style *style;
22656 
22657     int ret = 0;
22658     float old_value;
22659     struct nk_rect bounds;
22660     enum nk_widget_layout_states state;
22661 
22662     NK_ASSERT(ctx);
22663     NK_ASSERT(ctx->current);
22664     NK_ASSERT(ctx->current->layout);
22665     NK_ASSERT(value);
22666     if (!ctx || !ctx->current || !ctx->current->layout || !value)
22667         return ret;
22668 
22669     win = ctx->current;
22670     style = &ctx->style;
22671     layout = win->layout;
22672 
22673     state = nk_widget(&bounds, ctx);
22674     if (!state) return ret;
22675     in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22676 
22677     old_value = *value;
22678     *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
22679                 old_value, max_value, value_step, &style->slider, in, style->font);
22680     return (old_value > *value || old_value < *value);
22681 }
22682 
22683 NK_API float
22684 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
22685 {
22686     nk_slider_float(ctx, min, &val, max, step); return val;
22687 }
22688 
22689 NK_API int
22690 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
22691 {
22692     float value = (float)val;
22693     nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
22694     return (int)value;
22695 }
22696 
22697 NK_API int
22698 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
22699 {
22700     int ret;
22701     float value = (float)*val;
22702     ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
22703     *val =  (int)value;
22704     return ret;
22705 }
22706 
22707 /*----------------------------------------------------------------
22708  *
22709  *                          PROGRESSBAR
22710  *
22711  * --------------------------------------------------------------*/
22712 NK_API int
22713 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
22714 {
22715     struct nk_window *win;
22716     struct nk_panel *layout;
22717     const struct nk_style *style;
22718     struct nk_input *in;
22719 
22720     struct nk_rect bounds;
22721     enum nk_widget_layout_states state;
22722     nk_size old_value;
22723 
22724     NK_ASSERT(ctx);
22725     NK_ASSERT(cur);
22726     NK_ASSERT(ctx->current);
22727     NK_ASSERT(ctx->current->layout);
22728     if (!ctx || !ctx->current || !ctx->current->layout || !cur)
22729         return 0;
22730 
22731     win = ctx->current;
22732     style = &ctx->style;
22733     layout = win->layout;
22734     state = nk_widget(&bounds, ctx);
22735     if (!state) return 0;
22736 
22737     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22738     old_value = *cur;
22739     *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
22740             *cur, max, is_modifyable, &style->progress, in);
22741     return (*cur != old_value);
22742 }
22743 
22744 NK_API nk_size nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
22745 {nk_progress(ctx, &cur, max, modifyable);return cur;}
22746 
22747 /*----------------------------------------------------------------
22748  *
22749  *                          EDIT
22750  *
22751  * --------------------------------------------------------------*/
22752 NK_API void
22753 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
22754 {
22755     nk_hash hash;
22756     struct nk_window *win;
22757 
22758     NK_ASSERT(ctx);
22759     NK_ASSERT(ctx->current);
22760     if (!ctx || !ctx->current) return;
22761 
22762     win = ctx->current;
22763     hash = win->edit.seq;
22764     win->edit.active = nk_true;
22765     win->edit.name = hash;
22766     if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
22767         win->edit.mode = NK_TEXT_EDIT_MODE_INSERT;
22768 }
22769 
22770 NK_API void
22771 nk_edit_unfocus(struct nk_context *ctx)
22772 {
22773     struct nk_window *win;
22774     NK_ASSERT(ctx);
22775     NK_ASSERT(ctx->current);
22776     if (!ctx || !ctx->current) return;
22777 
22778     win = ctx->current;
22779     win->edit.active = nk_false;
22780     win->edit.name = 0;
22781 }
22782 
22783 NK_API nk_flags
22784 nk_edit_string(struct nk_context *ctx, nk_flags flags,
22785     char *memory, int *len, int max, nk_plugin_filter filter)
22786 {
22787     nk_hash hash;
22788     nk_flags state;
22789     struct nk_text_edit *edit;
22790     struct nk_window *win;
22791 
22792     NK_ASSERT(ctx);
22793     NK_ASSERT(memory);
22794     NK_ASSERT(len);
22795     if (!ctx || !memory || !len)
22796         return 0;
22797 
22798     filter = (!filter) ? nk_filter_default: filter;
22799     win = ctx->current;
22800     hash = win->edit.seq;
22801     edit = &ctx->text_edit;
22802     nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
22803         NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter);
22804 
22805     if (win->edit.active && hash == win->edit.name) {
22806         if (flags & NK_EDIT_NO_CURSOR)
22807             edit->cursor = nk_utf_len(memory, *len);
22808         else edit->cursor = win->edit.cursor;
22809         if (!(flags & NK_EDIT_SELECTABLE)) {
22810             edit->select_start = win->edit.cursor;
22811             edit->select_end = win->edit.cursor;
22812         } else {
22813             edit->select_start = win->edit.sel_start;
22814             edit->select_end = win->edit.sel_end;
22815         }
22816         edit->mode = win->edit.mode;
22817         edit->scrollbar.x = (float)win->edit.scrollbar.x;
22818         edit->scrollbar.y = (float)win->edit.scrollbar.y;
22819         edit->active = nk_true;
22820     } else edit->active = nk_false;
22821 
22822     max = NK_MAX(1, max);
22823     *len = NK_MIN(*len, max-1);
22824     nk_str_init_fixed(&edit->string, memory, (nk_size)max);
22825     edit->string.buffer.allocated = (nk_size)*len;
22826     edit->string.len = nk_utf_len(memory, *len);
22827     state = nk_edit_buffer(ctx, flags, edit, filter);
22828     *len = (int)edit->string.buffer.allocated;
22829 
22830     if (edit->active) {
22831         win->edit.cursor = edit->cursor;
22832         win->edit.sel_start = edit->select_start;
22833         win->edit.sel_end = edit->select_end;
22834         win->edit.mode = edit->mode;
22835         win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x;
22836         win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y;
22837     } return state;
22838 }
22839 
22840 NK_API nk_flags
22841 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
22842     struct nk_text_edit *edit, nk_plugin_filter filter)
22843 {
22844     struct nk_window *win;
22845     struct nk_style *style;
22846     struct nk_input *in;
22847 
22848     enum nk_widget_layout_states state;
22849     struct nk_rect bounds;
22850 
22851     nk_flags ret_flags = 0;
22852     unsigned char prev_state;
22853     nk_hash hash;
22854 
22855     /* make sure correct values */
22856     NK_ASSERT(ctx);
22857     NK_ASSERT(edit);
22858     NK_ASSERT(ctx->current);
22859     NK_ASSERT(ctx->current->layout);
22860     if (!ctx || !ctx->current || !ctx->current->layout)
22861         return 0;
22862 
22863     win = ctx->current;
22864     style = &ctx->style;
22865     state = nk_widget(&bounds, ctx);
22866     if (!state) return state;
22867     in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22868 
22869     /* check if edit is currently hot item */
22870     hash = win->edit.seq++;
22871     if (win->edit.active && hash == win->edit.name) {
22872         if (flags & NK_EDIT_NO_CURSOR)
22873             edit->cursor = edit->string.len;
22874         if (!(flags & NK_EDIT_SELECTABLE)) {
22875             edit->select_start = edit->cursor;
22876             edit->select_end = edit->cursor;
22877         }
22878         if (flags & NK_EDIT_CLIPBOARD)
22879             edit->clip = ctx->clip;
22880         edit->active = (unsigned char)win->edit.active;
22881     } else edit->active = nk_false;
22882     edit->mode = win->edit.mode;
22883 
22884     filter = (!filter) ? nk_filter_default: filter;
22885     prev_state = (unsigned char)edit->active;
22886     in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
22887     ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
22888                     filter, edit, &style->edit, in, style->font);
22889 
22890     if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22891         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT];
22892     if (edit->active && prev_state != edit->active) {
22893         /* current edit is now hot */
22894         win->edit.active = nk_true;
22895         win->edit.name = hash;
22896     } else if (prev_state && !edit->active) {
22897         /* current edit is now cold */
22898         win->edit.active = nk_false;
22899     } return ret_flags;
22900 }
22901 
22902 NK_API nk_flags
22903 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
22904     char *buffer, int max, nk_plugin_filter filter)
22905 {
22906     nk_flags result;
22907     int len = nk_strlen(buffer);
22908     result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
22909     buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
22910     return result;
22911 }
22912 
22913 /*----------------------------------------------------------------
22914  *
22915  *                          PROPERTY
22916  *
22917  * --------------------------------------------------------------*/
22918 NK_INTERN struct nk_property_variant
22919 nk_property_variant_int(int value, int min_value, int max_value, int step)
22920 {
22921     struct nk_property_variant result;
22922     result.kind = NK_PROPERTY_INT;
22923     result.value.i = value;
22924     result.min_value.i = min_value;
22925     result.max_value.i = max_value;
22926     result.step.i = step;
22927     return result;
22928 }
22929 
22930 NK_INTERN struct nk_property_variant
22931 nk_property_variant_float(float value, float min_value, float max_value, float step)
22932 {
22933     struct nk_property_variant result;
22934     result.kind = NK_PROPERTY_FLOAT;
22935     result.value.f = value;
22936     result.min_value.f = min_value;
22937     result.max_value.f = max_value;
22938     result.step.f = step;
22939     return result;
22940 }
22941 
22942 NK_INTERN struct nk_property_variant
22943 nk_property_variant_double(double value, double min_value, double max_value,
22944     double step)
22945 {
22946     struct nk_property_variant result;
22947     result.kind = NK_PROPERTY_DOUBLE;
22948     result.value.d = value;
22949     result.min_value.d = min_value;
22950     result.max_value.d = max_value;
22951     result.step.d = step;
22952     return result;
22953 }
22954 
22955 NK_INTERN void
22956 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
22957     float inc_per_pixel, const enum nk_property_filter filter)
22958 {
22959     struct nk_window *win;
22960     struct nk_panel *layout;
22961     struct nk_input *in;
22962     const struct nk_style *style;
22963 
22964     struct nk_rect bounds;
22965     enum nk_widget_layout_states s;
22966 
22967     int *state = 0;
22968     nk_hash hash = 0;
22969     char *buffer = 0;
22970     int *len = 0;
22971     int *cursor = 0;
22972     int *select_begin = 0;
22973     int *select_end = 0;
22974     int old_state;
22975 
22976     char dummy_buffer[NK_MAX_NUMBER_BUFFER];
22977     int dummy_state = NK_PROPERTY_DEFAULT;
22978     int dummy_length = 0;
22979     int dummy_cursor = 0;
22980     int dummy_select_begin = 0;
22981     int dummy_select_end = 0;
22982 
22983     NK_ASSERT(ctx);
22984     NK_ASSERT(ctx->current);
22985     NK_ASSERT(ctx->current->layout);
22986     if (!ctx || !ctx->current || !ctx->current->layout)
22987         return;
22988 
22989     win = ctx->current;
22990     layout = win->layout;
22991     style = &ctx->style;
22992     s = nk_widget(&bounds, ctx);
22993     if (!s) return;
22994 
22995     /* calculate hash from name */
22996     if (name[0] == '#') {
22997         hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
22998         name++; /* special number hash */
22999     } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
23000 
23001     /* check if property is currently hot item */
23002     if (win->property.active && hash == win->property.name) {
23003         buffer = win->property.buffer;
23004         len = &win->property.length;
23005         cursor = &win->property.cursor;
23006         state = &win->property.state;
23007         select_begin = &win->property.select_start;
23008         select_end = &win->property.select_end;
23009     } else {
23010         buffer = dummy_buffer;
23011         len = &dummy_length;
23012         cursor = &dummy_cursor;
23013         state = &dummy_state;
23014         select_begin =  &dummy_select_begin;
23015         select_end = &dummy_select_end;
23016     }
23017 
23018     /* execute property widget */
23019     old_state = *state;
23020     ctx->text_edit.clip = ctx->clip;
23021     in = ((s == NK_WIDGET_ROM && !win->property.active) ||
23022         layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23023     nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
23024         variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
23025         select_end, &style->property, filter, in, style->font, &ctx->text_edit,
23026         ctx->button_behavior);
23027 
23028     if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
23029         /* current property is now hot */
23030         win->property.active = 1;
23031         NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
23032         win->property.length = *len;
23033         win->property.cursor = *cursor;
23034         win->property.state = *state;
23035         win->property.name = hash;
23036         win->property.select_start = *select_begin;
23037         win->property.select_end = *select_end;
23038         if (*state == NK_PROPERTY_DRAG) {
23039             ctx->input.mouse.grab = nk_true;
23040             ctx->input.mouse.grabbed = nk_true;
23041         }
23042     }
23043     /* check if previously active property is now inactive */
23044     if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
23045         if (old_state == NK_PROPERTY_DRAG) {
23046             ctx->input.mouse.grab = nk_false;
23047             ctx->input.mouse.grabbed = nk_false;
23048             ctx->input.mouse.ungrab = nk_true;
23049         }
23050         win->property.select_start = 0;
23051         win->property.select_end = 0;
23052         win->property.active = 0;
23053     }
23054 }
23055 
23056 NK_API void
23057 nk_property_int(struct nk_context *ctx, const char *name,
23058     int min, int *val, int max, int step, float inc_per_pixel)
23059 {
23060     struct nk_property_variant variant;
23061     NK_ASSERT(ctx);
23062     NK_ASSERT(name);
23063     NK_ASSERT(val);
23064 
23065     if (!ctx || !ctx->current || !name || !val) return;
23066     variant = nk_property_variant_int(*val, min, max, step);
23067     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
23068     *val = variant.value.i;
23069 }
23070 
23071 NK_API void
23072 nk_property_float(struct nk_context *ctx, const char *name,
23073     float min, float *val, float max, float step, float inc_per_pixel)
23074 {
23075     struct nk_property_variant variant;
23076     NK_ASSERT(ctx);
23077     NK_ASSERT(name);
23078     NK_ASSERT(val);
23079 
23080     if (!ctx || !ctx->current || !name || !val) return;
23081     variant = nk_property_variant_float(*val, min, max, step);
23082     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23083     *val = variant.value.f;
23084 }
23085 
23086 NK_API void
23087 nk_property_double(struct nk_context *ctx, const char *name,
23088     double min, double *val, double max, double step, float inc_per_pixel)
23089 {
23090     struct nk_property_variant variant;
23091     NK_ASSERT(ctx);
23092     NK_ASSERT(name);
23093     NK_ASSERT(val);
23094 
23095     if (!ctx || !ctx->current || !name || !val) return;
23096     variant = nk_property_variant_double(*val, min, max, step);
23097     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23098     *val = variant.value.d;
23099 }
23100 
23101 NK_API int
23102 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
23103     int max, int step, float inc_per_pixel)
23104 {
23105     struct nk_property_variant variant;
23106     NK_ASSERT(ctx);
23107     NK_ASSERT(name);
23108 
23109     if (!ctx || !ctx->current || !name) return val;
23110     variant = nk_property_variant_int(val, min, max, step);
23111     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
23112     val = variant.value.i;
23113     return val;
23114 }
23115 
23116 NK_API float
23117 nk_propertyf(struct nk_context *ctx, const char *name, float min,
23118     float val, float max, float step, float inc_per_pixel)
23119 {
23120     struct nk_property_variant variant;
23121     NK_ASSERT(ctx);
23122     NK_ASSERT(name);
23123 
23124     if (!ctx || !ctx->current || !name) return val;
23125     variant = nk_property_variant_float(val, min, max, step);
23126     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23127     val = variant.value.f;
23128     return val;
23129 }
23130 
23131 NK_API double
23132 nk_propertyd(struct nk_context *ctx, const char *name, double min,
23133     double val, double max, double step, float inc_per_pixel)
23134 {
23135     struct nk_property_variant variant;
23136     NK_ASSERT(ctx);
23137     NK_ASSERT(name);
23138 
23139     if (!ctx || !ctx->current || !name) return val;
23140     variant = nk_property_variant_double(val, min, max, step);
23141     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23142     val = variant.value.d;
23143     return val;
23144 }
23145 
23146 /*----------------------------------------------------------------
23147  *
23148  *                          COLOR PICKER
23149  *
23150  * --------------------------------------------------------------*/
23151 NK_API int
23152 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color,
23153     enum nk_color_format fmt)
23154 {
23155     struct nk_window *win;
23156     struct nk_panel *layout;
23157     const struct nk_style *config;
23158     const struct nk_input *in;
23159 
23160     enum nk_widget_layout_states state;
23161     struct nk_rect bounds;
23162 
23163     NK_ASSERT(ctx);
23164     NK_ASSERT(color);
23165     NK_ASSERT(ctx->current);
23166     NK_ASSERT(ctx->current->layout);
23167     if (!ctx || !ctx->current || !ctx->current->layout || !color)
23168         return 0;
23169 
23170     win = ctx->current;
23171     config = &ctx->style;
23172     layout = win->layout;
23173     state = nk_widget(&bounds, ctx);
23174     if (!state) return 0;
23175     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23176     return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
23177                 nk_vec2(0,0), in, config->font);
23178 }
23179 
23180 NK_API struct nk_colorf
23181 nk_color_picker(struct nk_context *ctx, struct nk_colorf color,
23182     enum nk_color_format fmt)
23183 {
23184     nk_color_pick(ctx, &color, fmt);
23185     return color;
23186 }
23187 
23188 /* -------------------------------------------------------------
23189  *
23190  *                          CHART
23191  *
23192  * --------------------------------------------------------------*/
23193 NK_API int
23194 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
23195     struct nk_color color, struct nk_color highlight,
23196     int count, float min_value, float max_value)
23197 {
23198     struct nk_window *win;
23199     struct nk_chart *chart;
23200     const struct nk_style *config;
23201     const struct nk_style_chart *style;
23202 
23203     const struct nk_style_item *background;
23204     struct nk_rect bounds = {0, 0, 0, 0};
23205 
23206     NK_ASSERT(ctx);
23207     NK_ASSERT(ctx->current);
23208     NK_ASSERT(ctx->current->layout);
23209 
23210     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
23211     if (!nk_widget(&bounds, ctx)) {
23212         chart = &ctx->current->layout->chart;
23213         nk_zero(chart, sizeof(*chart));
23214         return 0;
23215     }
23216 
23217     win = ctx->current;
23218     config = &ctx->style;
23219     chart = &win->layout->chart;
23220     style = &config->chart;
23221 
23222     /* setup basic generic chart  */
23223     nk_zero(chart, sizeof(*chart));
23224     chart->x = bounds.x + style->padding.x;
23225     chart->y = bounds.y + style->padding.y;
23226     chart->w = bounds.w - 2 * style->padding.x;
23227     chart->h = bounds.h - 2 * style->padding.y;
23228     chart->w = NK_MAX(chart->w, 2 * style->padding.x);
23229     chart->h = NK_MAX(chart->h, 2 * style->padding.y);
23230 
23231     /* add first slot into chart */
23232     {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
23233     slot->type = type;
23234     slot->count = count;
23235     slot->color = color;
23236     slot->highlight = highlight;
23237     slot->min = NK_MIN(min_value, max_value);
23238     slot->max = NK_MAX(min_value, max_value);
23239     slot->range = slot->max - slot->min;}
23240 
23241     /* draw chart background */
23242     background = &style->background;
23243     if (background->type == NK_STYLE_ITEM_IMAGE) {
23244         nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
23245     } else {
23246         nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
23247         nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
23248             style->rounding, style->background.data.color);
23249     }
23250     return 1;
23251 }
23252 
23253 NK_API int
23254 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
23255     int count, float min_value, float max_value)
23256 {return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
23257 
23258 NK_API void
23259 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
23260     struct nk_color color, struct nk_color highlight,
23261     int count, float min_value, float max_value)
23262 {
23263     NK_ASSERT(ctx);
23264     NK_ASSERT(ctx->current);
23265     NK_ASSERT(ctx->current->layout);
23266     NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
23267     if (!ctx || !ctx->current || !ctx->current->layout) return;
23268     if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
23269 
23270     /* add another slot into the graph */
23271     {struct nk_chart *chart = &ctx->current->layout->chart;
23272     struct nk_chart_slot *slot = &chart->slots[chart->slot++];
23273     slot->type = type;
23274     slot->count = count;
23275     slot->color = color;
23276     slot->highlight = highlight;
23277     slot->min = NK_MIN(min_value, max_value);
23278     slot->max = NK_MAX(min_value, max_value);
23279     slot->range = slot->max - slot->min;}
23280 }
23281 
23282 NK_API void
23283 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
23284     int count, float min_value, float max_value)
23285 {nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
23286 
23287 NK_INTERN nk_flags
23288 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
23289     struct nk_chart *g, float value, int slot)
23290 {
23291     struct nk_panel *layout = win->layout;
23292     const struct nk_input *i = &ctx->input;
23293     struct nk_command_buffer *out = &win->buffer;
23294 
23295     nk_flags ret = 0;
23296     struct nk_vec2 cur;
23297     struct nk_rect bounds;
23298     struct nk_color color;
23299     float step;
23300     float range;
23301     float ratio;
23302 
23303     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
23304     step = g->w / (float)g->slots[slot].count;
23305     range = g->slots[slot].max - g->slots[slot].min;
23306     ratio = (value - g->slots[slot].min) / range;
23307 
23308     if (g->slots[slot].index == 0) {
23309         /* first data point does not have a connection */
23310         g->slots[slot].last.x = g->x;
23311         g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
23312 
23313         bounds.x = g->slots[slot].last.x - 2;
23314         bounds.y = g->slots[slot].last.y - 2;
23315         bounds.w = bounds.h = 4;
23316 
23317         color = g->slots[slot].color;
23318         if (!(layout->flags & NK_WINDOW_ROM) &&
23319             NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
23320             ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
23321             ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
23322                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
23323             color = g->slots[slot].highlight;
23324         }
23325         nk_fill_rect(out, bounds, 0, color);
23326         g->slots[slot].index += 1;
23327         return ret;
23328     }
23329 
23330     /* draw a line between the last data point and the new one */
23331     color = g->slots[slot].color;
23332     cur.x = g->x + (float)(step * (float)g->slots[slot].index);
23333     cur.y = (g->y + g->h) - (ratio * (float)g->h);
23334     nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
23335 
23336     bounds.x = cur.x - 3;
23337     bounds.y = cur.y - 3;
23338     bounds.w = bounds.h = 6;
23339 
23340     /* user selection of current data point */
23341     if (!(layout->flags & NK_WINDOW_ROM)) {
23342         if (nk_input_is_mouse_hovering_rect(i, bounds)) {
23343             ret = NK_CHART_HOVERING;
23344             ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
23345                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
23346             color = g->slots[slot].highlight;
23347         }
23348     }
23349     nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
23350 
23351     /* save current data point position */
23352     g->slots[slot].last.x = cur.x;
23353     g->slots[slot].last.y = cur.y;
23354     g->slots[slot].index  += 1;
23355     return ret;
23356 }
23357 
23358 NK_INTERN nk_flags
23359 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
23360     struct nk_chart *chart, float value, int slot)
23361 {
23362     struct nk_command_buffer *out = &win->buffer;
23363     const struct nk_input *in = &ctx->input;
23364     struct nk_panel *layout = win->layout;
23365 
23366     float ratio;
23367     nk_flags ret = 0;
23368     struct nk_color color;
23369     struct nk_rect item = {0,0,0,0};
23370 
23371     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
23372     if (chart->slots[slot].index  >= chart->slots[slot].count)
23373         return nk_false;
23374     if (chart->slots[slot].count) {
23375         float padding = (float)(chart->slots[slot].count-1);
23376         item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
23377     }
23378 
23379     /* calculate bounds of current bar chart entry */
23380     color = chart->slots[slot].color;;
23381     item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
23382     if (value >= 0) {
23383         ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
23384         item.y = (chart->y + chart->h) - chart->h * ratio;
23385     } else {
23386         ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
23387         item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
23388     }
23389     item.x = chart->x + ((float)chart->slots[slot].index * item.w);
23390     item.x = item.x + ((float)chart->slots[slot].index);
23391 
23392     /* user chart bar selection */
23393     if (!(layout->flags & NK_WINDOW_ROM) &&
23394         NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
23395         ret = NK_CHART_HOVERING;
23396         ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
23397                 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
23398         color = chart->slots[slot].highlight;
23399     }
23400     nk_fill_rect(out, item, 0, color);
23401     chart->slots[slot].index += 1;
23402     return ret;
23403 }
23404 
23405 NK_API nk_flags
23406 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
23407 {
23408     nk_flags flags;
23409     struct nk_window *win;
23410 
23411     NK_ASSERT(ctx);
23412     NK_ASSERT(ctx->current);
23413     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
23414     NK_ASSERT(slot < ctx->current->layout->chart.slot);
23415     if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
23416     if (slot >= ctx->current->layout->chart.slot) return nk_false;
23417 
23418     win = ctx->current;
23419     if (win->layout->chart.slot < slot) return nk_false;
23420     switch (win->layout->chart.slots[slot].type) {
23421     case NK_CHART_LINES:
23422         flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
23423     case NK_CHART_COLUMN:
23424         flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
23425     default:
23426     case NK_CHART_MAX:
23427         flags = 0;
23428     }
23429     return flags;
23430 }
23431 
23432 NK_API nk_flags
23433 nk_chart_push(struct nk_context *ctx, float value)
23434 {return nk_chart_push_slot(ctx, value, 0);}
23435 
23436 NK_API void
23437 nk_chart_end(struct nk_context *ctx)
23438 {
23439     struct nk_window *win;
23440     struct nk_chart *chart;
23441 
23442     NK_ASSERT(ctx);
23443     NK_ASSERT(ctx->current);
23444     if (!ctx || !ctx->current)
23445         return;
23446 
23447     win = ctx->current;
23448     chart = &win->layout->chart;
23449     NK_MEMSET(chart, 0, sizeof(*chart));
23450     return;
23451 }
23452 
23453 NK_API void
23454 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
23455     int count, int offset)
23456 {
23457     int i = 0;
23458     float min_value;
23459     float max_value;
23460 
23461     NK_ASSERT(ctx);
23462     NK_ASSERT(values);
23463     if (!ctx || !values || !count) return;
23464 
23465     min_value = values[offset];
23466     max_value = values[offset];
23467     for (i = 0; i < count; ++i) {
23468         min_value = NK_MIN(values[i + offset], min_value);
23469         max_value = NK_MAX(values[i + offset], max_value);
23470     }
23471 
23472     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
23473         for (i = 0; i < count; ++i)
23474             nk_chart_push(ctx, values[i + offset]);
23475         nk_chart_end(ctx);
23476     }
23477 }
23478 
23479 NK_API void
23480 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
23481     float(*value_getter)(void* user, int index), int count, int offset)
23482 {
23483     int i = 0;
23484     float min_value;
23485     float max_value;
23486 
23487     NK_ASSERT(ctx);
23488     NK_ASSERT(value_getter);
23489     if (!ctx || !value_getter || !count) return;
23490 
23491     max_value = min_value = value_getter(userdata, offset);
23492     for (i = 0; i < count; ++i) {
23493         float value = value_getter(userdata, i + offset);
23494         min_value = NK_MIN(value, min_value);
23495         max_value = NK_MAX(value, max_value);
23496     }
23497 
23498     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
23499         for (i = 0; i < count; ++i)
23500             nk_chart_push(ctx, value_getter(userdata, i + offset));
23501         nk_chart_end(ctx);
23502     }
23503 }
23504 
23505 /* -------------------------------------------------------------
23506  *
23507  *                          GROUP
23508  *
23509  * --------------------------------------------------------------*/
23510 NK_API int
23511 nk_group_scrolled_offset_begin(struct nk_context *ctx,
23512     nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
23513 {
23514     struct nk_rect bounds;
23515     struct nk_window panel;
23516     struct nk_window *win;
23517 
23518     win = ctx->current;
23519     nk_panel_alloc_space(&bounds, ctx);
23520     {const struct nk_rect *c = &win->layout->clip;
23521     if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
23522         !(flags & NK_WINDOW_MOVABLE)) {
23523         return 0;
23524     }}
23525     if (win->flags & NK_WINDOW_ROM)
23526         flags |= NK_WINDOW_ROM;
23527 
23528     /* initialize a fake window to create the panel from */
23529     nk_zero(&panel, sizeof(panel));
23530     panel.bounds = bounds;
23531     panel.flags = flags;
23532     panel.scrollbar.x = *x_offset;
23533     panel.scrollbar.y = *y_offset;
23534     panel.buffer = win->buffer;
23535     panel.layout = (struct nk_panel*)nk_create_panel(ctx);
23536     ctx->current = &panel;
23537     nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
23538 
23539     win->buffer = panel.buffer;
23540     win->buffer.clip = panel.layout->clip;
23541     panel.layout->offset_x = x_offset;
23542     panel.layout->offset_y = y_offset;
23543     panel.layout->parent = win->layout;
23544     win->layout = panel.layout;
23545 
23546     ctx->current = win;
23547     if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
23548         (panel.layout->flags & NK_WINDOW_MINIMIZED))
23549     {
23550         nk_flags f = panel.layout->flags;
23551         nk_group_scrolled_end(ctx);
23552         if (f & NK_WINDOW_CLOSED)
23553             return NK_WINDOW_CLOSED;
23554         if (f & NK_WINDOW_MINIMIZED)
23555             return NK_WINDOW_MINIMIZED;
23556     }
23557     return 1;
23558 }
23559 
23560 NK_API void
23561 nk_group_scrolled_end(struct nk_context *ctx)
23562 {
23563     struct nk_window *win;
23564     struct nk_panel *parent;
23565     struct nk_panel *g;
23566 
23567     struct nk_rect clip;
23568     struct nk_window pan;
23569     struct nk_vec2 panel_padding;
23570 
23571     NK_ASSERT(ctx);
23572     NK_ASSERT(ctx->current);
23573     if (!ctx || !ctx->current)
23574         return;
23575 
23576     /* make sure nk_group_begin was called correctly */
23577     NK_ASSERT(ctx->current);
23578     win = ctx->current;
23579     NK_ASSERT(win->layout);
23580     g = win->layout;
23581     NK_ASSERT(g->parent);
23582     parent = g->parent;
23583 
23584     /* dummy window */
23585     nk_zero_struct(pan);
23586     panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
23587     pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
23588     pan.bounds.x = g->bounds.x - panel_padding.x;
23589     pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
23590     pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
23591     if (g->flags & NK_WINDOW_BORDER) {
23592         pan.bounds.x -= g->border;
23593         pan.bounds.y -= g->border;
23594         pan.bounds.w += 2*g->border;
23595         pan.bounds.h += 2*g->border;
23596     }
23597     if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
23598         pan.bounds.w += ctx->style.window.scrollbar_size.x;
23599         pan.bounds.h += ctx->style.window.scrollbar_size.y;
23600     }
23601     pan.scrollbar.x = *g->offset_x;
23602     pan.scrollbar.y = *g->offset_y;
23603     pan.flags = g->flags;
23604     pan.buffer = win->buffer;
23605     pan.layout = g;
23606     pan.parent = win;
23607     ctx->current = &pan;
23608 
23609     /* make sure group has correct clipping rectangle */
23610     nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
23611         pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
23612     nk_push_scissor(&pan.buffer, clip);
23613     nk_end(ctx);
23614 
23615     win->buffer = pan.buffer;
23616     nk_push_scissor(&win->buffer, parent->clip);
23617     ctx->current = win;
23618     win->layout = parent;
23619     g->bounds = pan.bounds;
23620     return;
23621 }
23622 
23623 NK_API int
23624 nk_group_scrolled_begin(struct nk_context *ctx,
23625     struct nk_scroll *scroll, const char *title, nk_flags flags)
23626 {return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);}
23627 
23628 NK_API int
23629 nk_group_begin_titled(struct nk_context *ctx, const char *id,
23630     const char *title, nk_flags flags)
23631 {
23632     int id_len;
23633     nk_hash id_hash;
23634     struct nk_window *win;
23635     nk_uint *x_offset;
23636     nk_uint *y_offset;
23637 
23638     NK_ASSERT(ctx);
23639     NK_ASSERT(id);
23640     NK_ASSERT(ctx->current);
23641     NK_ASSERT(ctx->current->layout);
23642     if (!ctx || !ctx->current || !ctx->current->layout || !id)
23643         return 0;
23644 
23645     /* find persistent group scrollbar value */
23646     win = ctx->current;
23647     id_len = (int)nk_strlen(id);
23648     id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
23649     x_offset = nk_find_value(win, id_hash);
23650     y_offset = nk_find_value(win, id_hash+1);
23651     if (!x_offset) {
23652         x_offset = nk_add_value(ctx, win, id_hash, 0);
23653         NK_ASSERT(x_offset);
23654         if (!x_offset) return 0;
23655         *x_offset = 0;
23656     }
23657     if (!y_offset) {
23658         y_offset = nk_add_value(ctx, win, id_hash+1, 0);
23659         NK_ASSERT(y_offset);
23660         if (!y_offset) return 0;
23661         *y_offset = 0;
23662     }
23663     return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
23664 }
23665 
23666 NK_API int
23667 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
23668 {
23669     return nk_group_begin_titled(ctx, title, title, flags);
23670 }
23671 
23672 NK_API void
23673 nk_group_end(struct nk_context *ctx)
23674 {nk_group_scrolled_end(ctx);}
23675 
23676 NK_API int
23677 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
23678     const char *title, nk_flags flags, int row_height, int row_count)
23679 {
23680     int title_len;
23681     nk_hash title_hash;
23682     nk_uint *x_offset;
23683     nk_uint *y_offset;
23684 
23685     int result;
23686     struct nk_window *win;
23687     struct nk_panel *layout;
23688     const struct nk_style *style;
23689     struct nk_vec2 item_spacing;
23690 
23691     NK_ASSERT(ctx);
23692     NK_ASSERT(view);
23693     NK_ASSERT(title);
23694     if (!ctx || !view || !title) return 0;
23695 
23696     win = ctx->current;
23697     style = &ctx->style;
23698     item_spacing = style->window.spacing;
23699     row_height += NK_MAX(0, (int)item_spacing.y);
23700 
23701     /* find persistent list view scrollbar offset */
23702     title_len = (int)nk_strlen(title);
23703     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
23704     x_offset = nk_find_value(win, title_hash);
23705     y_offset = nk_find_value(win, title_hash+1);
23706     if (!x_offset) {
23707         x_offset = nk_add_value(ctx, win, title_hash, 0);
23708         NK_ASSERT(x_offset);
23709         if (!x_offset) return 0;
23710         *x_offset = 0;
23711     }
23712     if (!y_offset) {
23713         y_offset = nk_add_value(ctx, win, title_hash+1, 0);
23714         NK_ASSERT(y_offset);
23715         if (!y_offset) return 0;
23716         *y_offset = 0;
23717     }
23718     view->scroll_value = *y_offset;
23719     view->scroll_pointer = y_offset;
23720 
23721     *y_offset = 0;
23722     result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
23723     win = ctx->current;
23724     layout = win->layout;
23725 
23726     view->total_height = row_height * NK_MAX(row_count,1);
23727     view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
23728     view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0);
23729     view->end = view->begin + view->count;
23730     view->ctx = ctx;
23731     return result;
23732 }
23733 
23734 NK_API void
23735 nk_list_view_end(struct nk_list_view *view)
23736 {
23737     struct nk_context *ctx;
23738     struct nk_window *win;
23739     struct nk_panel *layout;
23740 
23741     NK_ASSERT(view);
23742     NK_ASSERT(view->ctx);
23743     NK_ASSERT(view->scroll_pointer);
23744     if (!view || !view->ctx) return;
23745 
23746     ctx = view->ctx;
23747     win = ctx->current;
23748     layout = win->layout;
23749     layout->at_y = layout->bounds.y + (float)view->total_height;
23750     *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
23751     nk_group_end(view->ctx);
23752 }
23753 
23754 /* --------------------------------------------------------------
23755  *
23756  *                          POPUP
23757  *
23758  * --------------------------------------------------------------*/
23759 NK_API int
23760 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
23761     const char *title, nk_flags flags, struct nk_rect rect)
23762 {
23763     struct nk_window *popup;
23764     struct nk_window *win;
23765     struct nk_panel *panel;
23766 
23767     int title_len;
23768     nk_hash title_hash;
23769     nk_size allocated;
23770 
23771     NK_ASSERT(ctx);
23772     NK_ASSERT(title);
23773     NK_ASSERT(ctx->current);
23774     NK_ASSERT(ctx->current->layout);
23775     if (!ctx || !ctx->current || !ctx->current->layout)
23776         return 0;
23777 
23778     win = ctx->current;
23779     panel = win->layout;
23780     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
23781     (void)panel;
23782     title_len = (int)nk_strlen(title);
23783     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
23784 
23785     popup = win->popup.win;
23786     if (!popup) {
23787         popup = (struct nk_window*)nk_create_window(ctx);
23788         popup->parent = win;
23789         win->popup.win = popup;
23790         win->popup.active = 0;
23791         win->popup.type = NK_PANEL_POPUP;
23792     }
23793 
23794     /* make sure we have correct popup */
23795     if (win->popup.name != title_hash) {
23796         if (!win->popup.active) {
23797             nk_zero(popup, sizeof(*popup));
23798             win->popup.name = title_hash;
23799             win->popup.active = 1;
23800             win->popup.type = NK_PANEL_POPUP;
23801         } else return 0;
23802     }
23803 
23804     /* popup position is local to window */
23805     ctx->current = popup;
23806     rect.x += win->layout->clip.x;
23807     rect.y += win->layout->clip.y;
23808 
23809     /* setup popup data */
23810     popup->parent = win;
23811     popup->bounds = rect;
23812     popup->seq = ctx->seq;
23813     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
23814     popup->flags = flags;
23815     popup->flags |= NK_WINDOW_BORDER;
23816     if (type == NK_POPUP_DYNAMIC)
23817         popup->flags |= NK_WINDOW_DYNAMIC;
23818 
23819     popup->buffer = win->buffer;
23820     nk_start_popup(ctx, win);
23821     allocated = ctx->memory.allocated;
23822     nk_push_scissor(&popup->buffer, nk_null_rect);
23823 
23824     if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
23825         /* popup is running therefore invalidate parent panels */
23826         struct nk_panel *root;
23827         root = win->layout;
23828         while (root) {
23829             root->flags |= NK_WINDOW_ROM;
23830             root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
23831             root = root->parent;
23832         }
23833         win->popup.active = 1;
23834         popup->layout->offset_x = &popup->scrollbar.x;
23835         popup->layout->offset_y = &popup->scrollbar.y;
23836         popup->layout->parent = win->layout;
23837         return 1;
23838     } else {
23839         /* popup was closed/is invalid so cleanup */
23840         struct nk_panel *root;
23841         root = win->layout;
23842         while (root) {
23843             root->flags |= NK_WINDOW_REMOVE_ROM;
23844             root = root->parent;
23845         }
23846         win->popup.buf.active = 0;
23847         win->popup.active = 0;
23848         ctx->memory.allocated = allocated;
23849         ctx->current = win;
23850         nk_free_panel(ctx, popup->layout);
23851         popup->layout = 0;
23852         return 0;
23853     }
23854 }
23855 
23856 NK_INTERN int
23857 nk_nonblock_begin(struct nk_context *ctx,
23858     nk_flags flags, struct nk_rect body, struct nk_rect header,
23859     enum nk_panel_type panel_type)
23860 {
23861     struct nk_window *popup;
23862     struct nk_window *win;
23863     struct nk_panel *panel;
23864     int is_active = nk_true;
23865 
23866     NK_ASSERT(ctx);
23867     NK_ASSERT(ctx->current);
23868     NK_ASSERT(ctx->current->layout);
23869     if (!ctx || !ctx->current || !ctx->current->layout)
23870         return 0;
23871 
23872     /* popups cannot have popups */
23873     win = ctx->current;
23874     panel = win->layout;
23875     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
23876     (void)panel;
23877     popup = win->popup.win;
23878     if (!popup) {
23879         /* create window for nonblocking popup */
23880         popup = (struct nk_window*)nk_create_window(ctx);
23881         popup->parent = win;
23882         win->popup.win = popup;
23883         win->popup.type = panel_type;
23884         nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
23885     } else {
23886         /* close the popup if user pressed outside or in the header */
23887         int pressed, in_body, in_header;
23888         pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
23889         in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
23890         in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
23891         if (pressed && (!in_body || in_header))
23892             is_active = nk_false;
23893     }
23894     win->popup.header = header;
23895 
23896     if (!is_active) {
23897         /* remove read only mode from all parent panels */
23898         struct nk_panel *root = win->layout;
23899         while (root) {
23900             root->flags |= NK_WINDOW_REMOVE_ROM;
23901             root = root->parent;
23902         }
23903         return is_active;
23904     }
23905 
23906     popup->bounds = body;
23907     popup->parent = win;
23908     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
23909     popup->flags = flags;
23910     popup->flags |= NK_WINDOW_BORDER;
23911     popup->flags |= NK_WINDOW_DYNAMIC;
23912     popup->seq = ctx->seq;
23913     win->popup.active = 1;
23914     NK_ASSERT(popup->layout);
23915 
23916     nk_start_popup(ctx, win);
23917     popup->buffer = win->buffer;
23918     nk_push_scissor(&popup->buffer, nk_null_rect);
23919     ctx->current = popup;
23920 
23921     nk_panel_begin(ctx, 0, panel_type);
23922     win->buffer = popup->buffer;
23923     popup->layout->parent = win->layout;
23924     popup->layout->offset_x = &popup->scrollbar.x;
23925     popup->layout->offset_y = &popup->scrollbar.y;
23926 
23927     /* set read only mode to all parent panels */
23928     {struct nk_panel *root;
23929     root = win->layout;
23930     while (root) {
23931         root->flags |= NK_WINDOW_ROM;
23932         root = root->parent;
23933     }}
23934     return is_active;
23935 }
23936 
23937 NK_API void
23938 nk_popup_close(struct nk_context *ctx)
23939 {
23940     struct nk_window *popup;
23941     NK_ASSERT(ctx);
23942     if (!ctx || !ctx->current) return;
23943 
23944     popup = ctx->current;
23945     NK_ASSERT(popup->parent);
23946     NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
23947     popup->flags |= NK_WINDOW_HIDDEN;
23948 }
23949 
23950 NK_API void
23951 nk_popup_end(struct nk_context *ctx)
23952 {
23953     struct nk_window *win;
23954     struct nk_window *popup;
23955 
23956     NK_ASSERT(ctx);
23957     NK_ASSERT(ctx->current);
23958     NK_ASSERT(ctx->current->layout);
23959     if (!ctx || !ctx->current || !ctx->current->layout)
23960         return;
23961 
23962     popup = ctx->current;
23963     if (!popup->parent) return;
23964     win = popup->parent;
23965     if (popup->flags & NK_WINDOW_HIDDEN) {
23966         struct nk_panel *root;
23967         root = win->layout;
23968         while (root) {
23969             root->flags |= NK_WINDOW_REMOVE_ROM;
23970             root = root->parent;
23971         }
23972         win->popup.active = 0;
23973     }
23974     nk_push_scissor(&popup->buffer, nk_null_rect);
23975     nk_end(ctx);
23976 
23977     win->buffer = popup->buffer;
23978     nk_finish_popup(ctx, win);
23979     ctx->current = win;
23980     nk_push_scissor(&win->buffer, win->layout->clip);
23981 }
23982 /* -------------------------------------------------------------
23983  *
23984  *                          TOOLTIP
23985  *
23986  * -------------------------------------------------------------- */
23987 NK_API int
23988 nk_tooltip_begin(struct nk_context *ctx, float width)
23989 {
23990     int x,y,w,h;
23991     struct nk_window *win;
23992     const struct nk_input *in;
23993     struct nk_rect bounds;
23994     int ret;
23995 
23996     NK_ASSERT(ctx);
23997     NK_ASSERT(ctx->current);
23998     NK_ASSERT(ctx->current->layout);
23999     if (!ctx || !ctx->current || !ctx->current->layout)
24000         return 0;
24001 
24002     /* make sure that no nonblocking popup is currently active */
24003     win = ctx->current;
24004     in = &ctx->input;
24005     if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
24006         return 0;
24007 
24008     w = nk_iceilf(width);
24009     h = nk_iceilf(nk_null_rect.h);
24010     x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x;
24011     y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y;
24012 
24013     bounds.x = (float)x;
24014     bounds.y = (float)y;
24015     bounds.w = (float)w;
24016     bounds.h = (float)h;
24017 
24018     ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
24019         "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
24020     if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
24021     win->popup.type = NK_PANEL_TOOLTIP;
24022     ctx->current->layout->type = NK_PANEL_TOOLTIP;
24023     return ret;
24024 }
24025 
24026 NK_API void
24027 nk_tooltip_end(struct nk_context *ctx)
24028 {
24029     NK_ASSERT(ctx);
24030     NK_ASSERT(ctx->current);
24031     if (!ctx || !ctx->current) return;
24032     ctx->current->seq--;
24033     nk_popup_close(ctx);
24034     nk_popup_end(ctx);
24035 }
24036 
24037 NK_API void
24038 nk_tooltip(struct nk_context *ctx, const char *text)
24039 {
24040     const struct nk_style *style;
24041     struct nk_vec2 padding;
24042 
24043     int text_len;
24044     float text_width;
24045     float text_height;
24046 
24047     NK_ASSERT(ctx);
24048     NK_ASSERT(ctx->current);
24049     NK_ASSERT(ctx->current->layout);
24050     NK_ASSERT(text);
24051     if (!ctx || !ctx->current || !ctx->current->layout || !text)
24052         return;
24053 
24054     /* fetch configuration data */
24055     style = &ctx->style;
24056     padding = style->window.padding;
24057 
24058     /* calculate size of the text and tooltip */
24059     text_len = nk_strlen(text);
24060     text_width = style->font->width(style->font->userdata,
24061                     style->font->height, text, text_len);
24062     text_width += (4 * padding.x);
24063     text_height = (style->font->height + 2 * padding.y);
24064 
24065     /* execute tooltip and fill with text */
24066     if (nk_tooltip_begin(ctx, (float)text_width)) {
24067         nk_layout_row_dynamic(ctx, (float)text_height, 1);
24068         nk_text(ctx, text, text_len, NK_TEXT_LEFT);
24069         nk_tooltip_end(ctx);
24070     }
24071 }
24072 #ifdef NK_INCLUDE_STANDARD_VARARGS
24073 NK_API void
24074 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...)
24075 {
24076     char buf[256];
24077     va_list args;
24078     va_start(args, fmt);
24079     nk_strfmt(buf, NK_LEN(buf), fmt, args);
24080     va_end(args);
24081     nk_tooltip(ctx, buf);
24082 }
24083 #endif
24084 
24085 /* -------------------------------------------------------------
24086  *
24087  *                          CONTEXTUAL
24088  *
24089  * -------------------------------------------------------------- */
24090 NK_API int
24091 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
24092     struct nk_rect trigger_bounds)
24093 {
24094     struct nk_window *win;
24095     struct nk_window *popup;
24096     struct nk_rect body;
24097 
24098     NK_STORAGE const struct nk_rect null_rect = {0,0,0,0};
24099     int is_clicked = 0;
24100     int is_active = 0;
24101     int is_open = 0;
24102     int ret = 0;
24103 
24104     NK_ASSERT(ctx);
24105     NK_ASSERT(ctx->current);
24106     NK_ASSERT(ctx->current->layout);
24107     if (!ctx || !ctx->current || !ctx->current->layout)
24108         return 0;
24109 
24110     win = ctx->current;
24111     ++win->popup.con_count;
24112 
24113     /* check if currently active contextual is active */
24114     popup = win->popup.win;
24115     is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
24116     is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
24117     if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
24118         return 0;
24119     if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked))
24120         return 0;
24121 
24122     /* calculate contextual position on click */
24123     win->popup.active_con = win->popup.con_count;
24124     if (is_clicked) {
24125         body.x = ctx->input.mouse.pos.x;
24126         body.y = ctx->input.mouse.pos.y;
24127     } else {
24128         body.x = popup->bounds.x;
24129         body.y = popup->bounds.y;
24130     }
24131     body.w = size.x;
24132     body.h = size.y;
24133 
24134     /* start nonblocking contextual popup */
24135     ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
24136             null_rect, NK_PANEL_CONTEXTUAL);
24137     if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
24138     else {
24139         win->popup.active_con = 0;
24140         if (win->popup.win)
24141             win->popup.win->flags = 0;
24142     }
24143     return ret;
24144 }
24145 
24146 NK_API int
24147 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
24148     nk_flags alignment)
24149 {
24150     struct nk_window *win;
24151     const struct nk_input *in;
24152     const struct nk_style *style;
24153 
24154     struct nk_rect bounds;
24155     enum nk_widget_layout_states state;
24156 
24157     NK_ASSERT(ctx);
24158     NK_ASSERT(ctx->current);
24159     NK_ASSERT(ctx->current->layout);
24160     if (!ctx || !ctx->current || !ctx->current->layout)
24161         return 0;
24162 
24163     win = ctx->current;
24164     style = &ctx->style;
24165     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
24166     if (!state) return nk_false;
24167 
24168     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
24169     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
24170         text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
24171         nk_contextual_close(ctx);
24172         return nk_true;
24173     }
24174     return nk_false;
24175 }
24176 
24177 NK_API int nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
24178 {return nk_contextual_item_text(ctx, label, nk_strlen(label), align);}
24179 
24180 NK_API int
24181 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
24182     const char *text, int len, nk_flags align)
24183 {
24184     struct nk_window *win;
24185     const struct nk_input *in;
24186     const struct nk_style *style;
24187 
24188     struct nk_rect bounds;
24189     enum nk_widget_layout_states state;
24190 
24191     NK_ASSERT(ctx);
24192     NK_ASSERT(ctx->current);
24193     NK_ASSERT(ctx->current->layout);
24194     if (!ctx || !ctx->current || !ctx->current->layout)
24195         return 0;
24196 
24197     win = ctx->current;
24198     style = &ctx->style;
24199     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
24200     if (!state) return nk_false;
24201 
24202     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
24203     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
24204         img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
24205         nk_contextual_close(ctx);
24206         return nk_true;
24207     }
24208     return nk_false;
24209 }
24210 
24211 NK_API int nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
24212     const char *label, nk_flags align)
24213 {return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);}
24214 
24215 NK_API int
24216 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
24217     const char *text, int len, nk_flags align)
24218 {
24219     struct nk_window *win;
24220     const struct nk_input *in;
24221     const struct nk_style *style;
24222 
24223     struct nk_rect bounds;
24224     enum nk_widget_layout_states state;
24225 
24226     NK_ASSERT(ctx);
24227     NK_ASSERT(ctx->current);
24228     NK_ASSERT(ctx->current->layout);
24229     if (!ctx || !ctx->current || !ctx->current->layout)
24230         return 0;
24231 
24232     win = ctx->current;
24233     style = &ctx->style;
24234     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
24235     if (!state) return nk_false;
24236 
24237     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
24238     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
24239         symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
24240         nk_contextual_close(ctx);
24241         return nk_true;
24242     }
24243     return nk_false;
24244 }
24245 
24246 NK_API int nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
24247     const char *text, nk_flags align)
24248 {return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);}
24249 
24250 NK_API void
24251 nk_contextual_close(struct nk_context *ctx)
24252 {
24253     NK_ASSERT(ctx);
24254     NK_ASSERT(ctx->current);
24255     NK_ASSERT(ctx->current->layout);
24256     if (!ctx || !ctx->current || !ctx->current->layout) return;
24257     nk_popup_close(ctx);
24258 }
24259 
24260 NK_API void
24261 nk_contextual_end(struct nk_context *ctx)
24262 {
24263     struct nk_window *popup;
24264     struct nk_panel *panel;
24265     NK_ASSERT(ctx);
24266     NK_ASSERT(ctx->current);
24267     if (!ctx || !ctx->current) return;
24268 
24269     popup = ctx->current;
24270     panel = popup->layout;
24271     NK_ASSERT(popup->parent);
24272     NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
24273     if (panel->flags & NK_WINDOW_DYNAMIC) {
24274         /* Close behavior
24275         This is a bit of a hack solution since we do not know before we end our popup
24276         how big it will be. We therefore do not directly know when a
24277         click outside the non-blocking popup must close it at that direct frame.
24278         Instead it will be closed in the next frame.*/
24279         struct nk_rect body = {0,0,0,0};
24280         if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
24281             struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
24282             body = panel->bounds;
24283             body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
24284             body.h = (panel->bounds.y + panel->bounds.h) - body.y;
24285         }
24286         {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
24287         int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
24288         if (pressed && in_body)
24289             popup->flags |= NK_WINDOW_HIDDEN;
24290         }
24291     }
24292     if (popup->flags & NK_WINDOW_HIDDEN)
24293         popup->seq = 0;
24294     nk_popup_end(ctx);
24295     return;
24296 }
24297 /* -------------------------------------------------------------
24298  *
24299  *                          COMBO
24300  *
24301  * --------------------------------------------------------------*/
24302 NK_INTERN int
24303 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
24304     struct nk_vec2 size, int is_clicked, struct nk_rect header)
24305 {
24306     struct nk_window *popup;
24307     int is_open = 0;
24308     int is_active = 0;
24309     struct nk_rect body;
24310     nk_hash hash;
24311 
24312     NK_ASSERT(ctx);
24313     NK_ASSERT(ctx->current);
24314     NK_ASSERT(ctx->current->layout);
24315     if (!ctx || !ctx->current || !ctx->current->layout)
24316         return 0;
24317 
24318     popup = win->popup.win;
24319     body.x = header.x;
24320     body.w = size.x;
24321     body.y = header.y + header.h-ctx->style.window.combo_border;
24322     body.h = size.y;
24323 
24324     hash = win->popup.combo_count++;
24325     is_open = (popup) ? nk_true:nk_false;
24326     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
24327     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
24328         (!is_open && !is_active && !is_clicked)) return 0;
24329     if (!nk_nonblock_begin(ctx, 0, body,
24330         (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
24331 
24332     win->popup.type = NK_PANEL_COMBO;
24333     win->popup.name = hash;
24334     return 1;
24335 }
24336 
24337 NK_API int
24338 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
24339     struct nk_vec2 size)
24340 {
24341     const struct nk_input *in;
24342     struct nk_window *win;
24343     struct nk_style *style;
24344 
24345     enum nk_widget_layout_states s;
24346     int is_clicked = nk_false;
24347     struct nk_rect header;
24348     const struct nk_style_item *background;
24349     struct nk_text text;
24350 
24351     NK_ASSERT(ctx);
24352     NK_ASSERT(selected);
24353     NK_ASSERT(ctx->current);
24354     NK_ASSERT(ctx->current->layout);
24355     if (!ctx || !ctx->current || !ctx->current->layout || !selected)
24356         return 0;
24357 
24358     win = ctx->current;
24359     style = &ctx->style;
24360     s = nk_widget(&header, ctx);
24361     if (s == NK_WIDGET_INVALID)
24362         return 0;
24363 
24364     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24365     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24366         is_clicked = nk_true;
24367 
24368     /* draw combo box header background and border */
24369     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
24370         background = &style->combo.active;
24371         text.text = style->combo.label_active;
24372     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24373         background = &style->combo.hover;
24374         text.text = style->combo.label_hover;
24375     } else {
24376         background = &style->combo.normal;
24377         text.text = style->combo.label_normal;
24378     }
24379     if (background->type == NK_STYLE_ITEM_IMAGE) {
24380         text.background = nk_rgba(0,0,0,0);
24381         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24382     } else {
24383         text.background = background->data.color;
24384         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24385         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24386     }
24387     {
24388         /* print currently selected text item */
24389         struct nk_rect label;
24390         struct nk_rect button;
24391         struct nk_rect content;
24392 
24393         enum nk_symbol_type sym;
24394         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24395             sym = style->combo.sym_hover;
24396         else if (is_clicked)
24397             sym = style->combo.sym_active;
24398         else sym = style->combo.sym_normal;
24399 
24400         /* calculate button */
24401         button.w = header.h - 2 * style->combo.button_padding.y;
24402         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24403         button.y = header.y + style->combo.button_padding.y;
24404         button.h = button.w;
24405 
24406         content.x = button.x + style->combo.button.padding.x;
24407         content.y = button.y + style->combo.button.padding.y;
24408         content.w = button.w - 2 * style->combo.button.padding.x;
24409         content.h = button.h - 2 * style->combo.button.padding.y;
24410 
24411         /* draw selected label */
24412         text.padding = nk_vec2(0,0);
24413         label.x = header.x + style->combo.content_padding.x;
24414         label.y = header.y + style->combo.content_padding.y;
24415         label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
24416         label.h = header.h - 2 * style->combo.content_padding.y;
24417         nk_widget_text(&win->buffer, label, selected, len, &text,
24418             NK_TEXT_LEFT, ctx->style.font);
24419 
24420         /* draw open/close button */
24421         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24422             &ctx->style.combo.button, sym, style->font);
24423     }
24424     return nk_combo_begin(ctx, win, size, is_clicked, header);
24425 }
24426 
24427 NK_API int nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
24428 {return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);}
24429 
24430 NK_API int
24431 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
24432 {
24433     struct nk_window *win;
24434     struct nk_style *style;
24435     const struct nk_input *in;
24436 
24437     struct nk_rect header;
24438     int is_clicked = nk_false;
24439     enum nk_widget_layout_states s;
24440     const struct nk_style_item *background;
24441 
24442     NK_ASSERT(ctx);
24443     NK_ASSERT(ctx->current);
24444     NK_ASSERT(ctx->current->layout);
24445     if (!ctx || !ctx->current || !ctx->current->layout)
24446         return 0;
24447 
24448     win = ctx->current;
24449     style = &ctx->style;
24450     s = nk_widget(&header, ctx);
24451     if (s == NK_WIDGET_INVALID)
24452         return 0;
24453 
24454     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24455     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24456         is_clicked = nk_true;
24457 
24458     /* draw combo box header background and border */
24459     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
24460         background = &style->combo.active;
24461     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24462         background = &style->combo.hover;
24463     else background = &style->combo.normal;
24464 
24465     if (background->type == NK_STYLE_ITEM_IMAGE) {
24466         nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
24467     } else {
24468         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24469         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24470     }
24471     {
24472         struct nk_rect content;
24473         struct nk_rect button;
24474         struct nk_rect bounds;
24475 
24476         enum nk_symbol_type sym;
24477         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24478             sym = style->combo.sym_hover;
24479         else if (is_clicked)
24480             sym = style->combo.sym_active;
24481         else sym = style->combo.sym_normal;
24482 
24483         /* calculate button */
24484         button.w = header.h - 2 * style->combo.button_padding.y;
24485         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24486         button.y = header.y + style->combo.button_padding.y;
24487         button.h = button.w;
24488 
24489         content.x = button.x + style->combo.button.padding.x;
24490         content.y = button.y + style->combo.button.padding.y;
24491         content.w = button.w - 2 * style->combo.button.padding.x;
24492         content.h = button.h - 2 * style->combo.button.padding.y;
24493 
24494         /* draw color */
24495         bounds.h = header.h - 4 * style->combo.content_padding.y;
24496         bounds.y = header.y + 2 * style->combo.content_padding.y;
24497         bounds.x = header.x + 2 * style->combo.content_padding.x;
24498         bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
24499         nk_fill_rect(&win->buffer, bounds, 0, color);
24500 
24501         /* draw open/close button */
24502         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24503             &ctx->style.combo.button, sym, style->font);
24504     }
24505     return nk_combo_begin(ctx, win, size, is_clicked, header);
24506 }
24507 
24508 NK_API int
24509 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
24510 {
24511     struct nk_window *win;
24512     struct nk_style *style;
24513     const struct nk_input *in;
24514 
24515     struct nk_rect header;
24516     int is_clicked = nk_false;
24517     enum nk_widget_layout_states s;
24518     const struct nk_style_item *background;
24519     struct nk_color sym_background;
24520     struct nk_color symbol_color;
24521 
24522     NK_ASSERT(ctx);
24523     NK_ASSERT(ctx->current);
24524     NK_ASSERT(ctx->current->layout);
24525     if (!ctx || !ctx->current || !ctx->current->layout)
24526         return 0;
24527 
24528     win = ctx->current;
24529     style = &ctx->style;
24530     s = nk_widget(&header, ctx);
24531     if (s == NK_WIDGET_INVALID)
24532         return 0;
24533 
24534     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24535     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24536         is_clicked = nk_true;
24537 
24538     /* draw combo box header background and border */
24539     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
24540         background = &style->combo.active;
24541         symbol_color = style->combo.symbol_active;
24542     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24543         background = &style->combo.hover;
24544         symbol_color = style->combo.symbol_hover;
24545     } else {
24546         background = &style->combo.normal;
24547         symbol_color = style->combo.symbol_hover;
24548     }
24549 
24550     if (background->type == NK_STYLE_ITEM_IMAGE) {
24551         sym_background = nk_rgba(0,0,0,0);
24552         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24553     } else {
24554         sym_background = background->data.color;
24555         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24556         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24557     }
24558     {
24559         struct nk_rect bounds = {0,0,0,0};
24560         struct nk_rect content;
24561         struct nk_rect button;
24562 
24563         enum nk_symbol_type sym;
24564         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24565             sym = style->combo.sym_hover;
24566         else if (is_clicked)
24567             sym = style->combo.sym_active;
24568         else sym = style->combo.sym_normal;
24569 
24570         /* calculate button */
24571         button.w = header.h - 2 * style->combo.button_padding.y;
24572         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
24573         button.y = header.y + style->combo.button_padding.y;
24574         button.h = button.w;
24575 
24576         content.x = button.x + style->combo.button.padding.x;
24577         content.y = button.y + style->combo.button.padding.y;
24578         content.w = button.w - 2 * style->combo.button.padding.x;
24579         content.h = button.h - 2 * style->combo.button.padding.y;
24580 
24581         /* draw symbol */
24582         bounds.h = header.h - 2 * style->combo.content_padding.y;
24583         bounds.y = header.y + style->combo.content_padding.y;
24584         bounds.x = header.x + style->combo.content_padding.x;
24585         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
24586         nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
24587             1.0f, style->font);
24588 
24589         /* draw open/close button */
24590         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
24591             &ctx->style.combo.button, sym, style->font);
24592     }
24593     return nk_combo_begin(ctx, win, size, is_clicked, header);
24594 }
24595 
24596 NK_API int
24597 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
24598     enum nk_symbol_type symbol, struct nk_vec2 size)
24599 {
24600     struct nk_window *win;
24601     struct nk_style *style;
24602     struct nk_input *in;
24603 
24604     struct nk_rect header;
24605     int is_clicked = nk_false;
24606     enum nk_widget_layout_states s;
24607     const struct nk_style_item *background;
24608     struct nk_color symbol_color;
24609     struct nk_text text;
24610 
24611     NK_ASSERT(ctx);
24612     NK_ASSERT(ctx->current);
24613     NK_ASSERT(ctx->current->layout);
24614     if (!ctx || !ctx->current || !ctx->current->layout)
24615         return 0;
24616 
24617     win = ctx->current;
24618     style = &ctx->style;
24619     s = nk_widget(&header, ctx);
24620     if (!s) return 0;
24621 
24622     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24623     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24624         is_clicked = nk_true;
24625 
24626     /* draw combo box header background and border */
24627     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
24628         background = &style->combo.active;
24629         symbol_color = style->combo.symbol_active;
24630         text.text = style->combo.label_active;
24631     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24632         background = &style->combo.hover;
24633         symbol_color = style->combo.symbol_hover;
24634         text.text = style->combo.label_hover;
24635     } else {
24636         background = &style->combo.normal;
24637         symbol_color = style->combo.symbol_normal;
24638         text.text = style->combo.label_normal;
24639     }
24640     if (background->type == NK_STYLE_ITEM_IMAGE) {
24641         text.background = nk_rgba(0,0,0,0);
24642         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24643     } else {
24644         text.background = background->data.color;
24645         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24646         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24647     }
24648     {
24649         struct nk_rect content;
24650         struct nk_rect button;
24651         struct nk_rect label;
24652         struct nk_rect image;
24653 
24654         enum nk_symbol_type sym;
24655         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24656             sym = style->combo.sym_hover;
24657         else if (is_clicked)
24658             sym = style->combo.sym_active;
24659         else sym = style->combo.sym_normal;
24660 
24661         /* calculate button */
24662         button.w = header.h - 2 * style->combo.button_padding.y;
24663         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24664         button.y = header.y + style->combo.button_padding.y;
24665         button.h = button.w;
24666 
24667         content.x = button.x + style->combo.button.padding.x;
24668         content.y = button.y + style->combo.button.padding.y;
24669         content.w = button.w - 2 * style->combo.button.padding.x;
24670         content.h = button.h - 2 * style->combo.button.padding.y;
24671         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24672             &ctx->style.combo.button, sym, style->font);
24673 
24674         /* draw symbol */
24675         image.x = header.x + style->combo.content_padding.x;
24676         image.y = header.y + style->combo.content_padding.y;
24677         image.h = header.h - 2 * style->combo.content_padding.y;
24678         image.w = image.h;
24679         nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
24680             1.0f, style->font);
24681 
24682         /* draw label */
24683         text.padding = nk_vec2(0,0);
24684         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
24685         label.y = header.y + style->combo.content_padding.y;
24686         label.w = (button.x - style->combo.content_padding.x) - label.x;
24687         label.h = header.h - 2 * style->combo.content_padding.y;
24688         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
24689     }
24690     return nk_combo_begin(ctx, win, size, is_clicked, header);
24691 }
24692 
24693 NK_API int
24694 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
24695 {
24696     struct nk_window *win;
24697     struct nk_style *style;
24698     const struct nk_input *in;
24699 
24700     struct nk_rect header;
24701     int is_clicked = nk_false;
24702     enum nk_widget_layout_states s;
24703     const struct nk_style_item *background;
24704 
24705     NK_ASSERT(ctx);
24706     NK_ASSERT(ctx->current);
24707     NK_ASSERT(ctx->current->layout);
24708     if (!ctx || !ctx->current || !ctx->current->layout)
24709         return 0;
24710 
24711     win = ctx->current;
24712     style = &ctx->style;
24713     s = nk_widget(&header, ctx);
24714     if (s == NK_WIDGET_INVALID)
24715         return 0;
24716 
24717     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24718     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24719         is_clicked = nk_true;
24720 
24721     /* draw combo box header background and border */
24722     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
24723         background = &style->combo.active;
24724     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24725         background = &style->combo.hover;
24726     else background = &style->combo.normal;
24727 
24728     if (background->type == NK_STYLE_ITEM_IMAGE) {
24729         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24730     } else {
24731         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24732         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24733     }
24734     {
24735         struct nk_rect bounds = {0,0,0,0};
24736         struct nk_rect content;
24737         struct nk_rect button;
24738 
24739         enum nk_symbol_type sym;
24740         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24741             sym = style->combo.sym_hover;
24742         else if (is_clicked)
24743             sym = style->combo.sym_active;
24744         else sym = style->combo.sym_normal;
24745 
24746         /* calculate button */
24747         button.w = header.h - 2 * style->combo.button_padding.y;
24748         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
24749         button.y = header.y + style->combo.button_padding.y;
24750         button.h = button.w;
24751 
24752         content.x = button.x + style->combo.button.padding.x;
24753         content.y = button.y + style->combo.button.padding.y;
24754         content.w = button.w - 2 * style->combo.button.padding.x;
24755         content.h = button.h - 2 * style->combo.button.padding.y;
24756 
24757         /* draw image */
24758         bounds.h = header.h - 2 * style->combo.content_padding.y;
24759         bounds.y = header.y + style->combo.content_padding.y;
24760         bounds.x = header.x + style->combo.content_padding.x;
24761         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
24762         nk_draw_image(&win->buffer, bounds, &img, nk_white);
24763 
24764         /* draw open/close button */
24765         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
24766             &ctx->style.combo.button, sym, style->font);
24767     }
24768     return nk_combo_begin(ctx, win, size, is_clicked, header);
24769 }
24770 
24771 NK_API int
24772 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
24773     struct nk_image img, struct nk_vec2 size)
24774 {
24775     struct nk_window *win;
24776     struct nk_style *style;
24777     struct nk_input *in;
24778 
24779     struct nk_rect header;
24780     int is_clicked = nk_false;
24781     enum nk_widget_layout_states s;
24782     const struct nk_style_item *background;
24783     struct nk_text text;
24784 
24785     NK_ASSERT(ctx);
24786     NK_ASSERT(ctx->current);
24787     NK_ASSERT(ctx->current->layout);
24788     if (!ctx || !ctx->current || !ctx->current->layout)
24789         return 0;
24790 
24791     win = ctx->current;
24792     style = &ctx->style;
24793     s = nk_widget(&header, ctx);
24794     if (!s) return 0;
24795 
24796     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24797     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24798         is_clicked = nk_true;
24799 
24800     /* draw combo box header background and border */
24801     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
24802         background = &style->combo.active;
24803         text.text = style->combo.label_active;
24804     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24805         background = &style->combo.hover;
24806         text.text = style->combo.label_hover;
24807     } else {
24808         background = &style->combo.normal;
24809         text.text = style->combo.label_normal;
24810     }
24811     if (background->type == NK_STYLE_ITEM_IMAGE) {
24812         text.background = nk_rgba(0,0,0,0);
24813         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24814     } else {
24815         text.background = background->data.color;
24816         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24817         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24818     }
24819     {
24820         struct nk_rect content;
24821         struct nk_rect button;
24822         struct nk_rect label;
24823         struct nk_rect image;
24824 
24825         enum nk_symbol_type sym;
24826         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24827             sym = style->combo.sym_hover;
24828         else if (is_clicked)
24829             sym = style->combo.sym_active;
24830         else sym = style->combo.sym_normal;
24831 
24832         /* calculate button */
24833         button.w = header.h - 2 * style->combo.button_padding.y;
24834         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24835         button.y = header.y + style->combo.button_padding.y;
24836         button.h = button.w;
24837 
24838         content.x = button.x + style->combo.button.padding.x;
24839         content.y = button.y + style->combo.button.padding.y;
24840         content.w = button.w - 2 * style->combo.button.padding.x;
24841         content.h = button.h - 2 * style->combo.button.padding.y;
24842         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24843             &ctx->style.combo.button, sym, style->font);
24844 
24845         /* draw image */
24846         image.x = header.x + style->combo.content_padding.x;
24847         image.y = header.y + style->combo.content_padding.y;
24848         image.h = header.h - 2 * style->combo.content_padding.y;
24849         image.w = image.h;
24850         nk_draw_image(&win->buffer, image, &img, nk_white);
24851 
24852         /* draw label */
24853         text.padding = nk_vec2(0,0);
24854         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
24855         label.y = header.y + style->combo.content_padding.y;
24856         label.w = (button.x - style->combo.content_padding.x) - label.x;
24857         label.h = header.h - 2 * style->combo.content_padding.y;
24858         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
24859     }
24860     return nk_combo_begin(ctx, win, size, is_clicked, header);
24861 }
24862 
24863 NK_API int nk_combo_begin_symbol_label(struct nk_context *ctx,
24864     const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
24865 {return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);}
24866 
24867 NK_API int nk_combo_begin_image_label(struct nk_context *ctx,
24868     const char *selected, struct nk_image img, struct nk_vec2 size)
24869 {return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);}
24870 
24871 NK_API int nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
24872 {return nk_contextual_item_text(ctx, text, len, align);}
24873 
24874 NK_API int nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
24875 {return nk_contextual_item_label(ctx, label, align);}
24876 
24877 NK_API int nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
24878     int len, nk_flags alignment)
24879 {return nk_contextual_item_image_text(ctx, img, text, len, alignment);}
24880 
24881 NK_API int nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
24882     const char *text, nk_flags alignment)
24883 {return nk_contextual_item_image_label(ctx, img, text, alignment);}
24884 
24885 NK_API int nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
24886     const char *text, int len, nk_flags alignment)
24887 {return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);}
24888 
24889 NK_API int nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
24890     const char *label, nk_flags alignment)
24891 {return nk_contextual_item_symbol_label(ctx, sym, label, alignment);}
24892 
24893 NK_API void nk_combo_end(struct nk_context *ctx)
24894 {nk_contextual_end(ctx);}
24895 
24896 NK_API void nk_combo_close(struct nk_context *ctx)
24897 {nk_contextual_close(ctx);}
24898 
24899 NK_API int
24900 nk_combo(struct nk_context *ctx, const char **items, int count,
24901     int selected, int item_height, struct nk_vec2 size)
24902 {
24903     int i = 0;
24904     int max_height;
24905     struct nk_vec2 item_spacing;
24906     struct nk_vec2 window_padding;
24907 
24908     NK_ASSERT(ctx);
24909     NK_ASSERT(items);
24910     NK_ASSERT(ctx->current);
24911     if (!ctx || !items ||!count)
24912         return selected;
24913 
24914     item_spacing = ctx->style.window.spacing;
24915     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
24916     max_height = count * item_height + count * (int)item_spacing.y;
24917     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
24918     size.y = NK_MIN(size.y, (float)max_height);
24919     if (nk_combo_begin_label(ctx, items[selected], size)) {
24920         nk_layout_row_dynamic(ctx, (float)item_height, 1);
24921         for (i = 0; i < count; ++i) {
24922             if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
24923                 selected = i;
24924         }
24925         nk_combo_end(ctx);
24926     }
24927     return selected;
24928 }
24929 
24930 NK_API int
24931 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
24932     int separator, int selected, int count, int item_height, struct nk_vec2 size)
24933 {
24934     int i;
24935     int max_height;
24936     struct nk_vec2 item_spacing;
24937     struct nk_vec2 window_padding;
24938     const char *current_item;
24939     const char *iter;
24940     int length = 0;
24941 
24942     NK_ASSERT(ctx);
24943     NK_ASSERT(items_separated_by_separator);
24944     if (!ctx || !items_separated_by_separator)
24945         return selected;
24946 
24947     /* calculate popup window */
24948     item_spacing = ctx->style.window.spacing;
24949     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
24950     max_height = count * item_height + count * (int)item_spacing.y;
24951     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
24952     size.y = NK_MIN(size.y, (float)max_height);
24953 
24954     /* find selected item */
24955     current_item = items_separated_by_separator;
24956     for (i = 0; i < count; ++i) {
24957         iter = current_item;
24958         while (*iter && *iter != separator) iter++;
24959         length = (int)(iter - current_item);
24960         if (i == selected) break;
24961         current_item = iter + 1;
24962     }
24963 
24964     if (nk_combo_begin_text(ctx, current_item, length, size)) {
24965         current_item = items_separated_by_separator;
24966         nk_layout_row_dynamic(ctx, (float)item_height, 1);
24967         for (i = 0; i < count; ++i) {
24968             iter = current_item;
24969             while (*iter && *iter != separator) iter++;
24970             length = (int)(iter - current_item);
24971             if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
24972                 selected = i;
24973             current_item = current_item + length + 1;
24974         }
24975         nk_combo_end(ctx);
24976     }
24977     return selected;
24978 }
24979 
24980 NK_API int
24981 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
24982     int selected, int count, int item_height, struct nk_vec2 size)
24983 {return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);}
24984 
24985 NK_API int
24986 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
24987     void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
24988 {
24989     int i;
24990     int max_height;
24991     struct nk_vec2 item_spacing;
24992     struct nk_vec2 window_padding;
24993     const char *item;
24994 
24995     NK_ASSERT(ctx);
24996     NK_ASSERT(item_getter);
24997     if (!ctx || !item_getter)
24998         return selected;
24999 
25000     /* calculate popup window */
25001     item_spacing = ctx->style.window.spacing;
25002     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
25003     max_height = count * item_height + count * (int)item_spacing.y;
25004     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
25005     size.y = NK_MIN(size.y, (float)max_height);
25006 
25007     item_getter(userdata, selected, &item);
25008     if (nk_combo_begin_label(ctx, item, size)) {
25009         nk_layout_row_dynamic(ctx, (float)item_height, 1);
25010         for (i = 0; i < count; ++i) {
25011             item_getter(userdata, i, &item);
25012             if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
25013                 selected = i;
25014         }
25015         nk_combo_end(ctx);
25016     }
25017     return selected;
25018 }
25019 
25020 NK_API void nk_combobox(struct nk_context *ctx, const char **items, int count,
25021     int *selected, int item_height, struct nk_vec2 size)
25022 {*selected = nk_combo(ctx, items, count, *selected, item_height, size);}
25023 
25024 NK_API void nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
25025     int *selected, int count, int item_height, struct nk_vec2 size)
25026 {*selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);}
25027 
25028 NK_API void nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
25029     int separator,int *selected, int count, int item_height, struct nk_vec2 size)
25030 {*selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
25031     *selected, count, item_height, size);}
25032 
25033 NK_API void nk_combobox_callback(struct nk_context *ctx,
25034     void(*item_getter)(void* data, int id, const char **out_text),
25035     void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
25036 {*selected = nk_combo_callback(ctx, item_getter, userdata,  *selected, count, item_height, size);}
25037 
25038 /*
25039  * -------------------------------------------------------------
25040  *
25041  *                          MENU
25042  *
25043  * --------------------------------------------------------------
25044  */
25045 NK_INTERN int
25046 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
25047     const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
25048 {
25049     int is_open = 0;
25050     int is_active = 0;
25051     struct nk_rect body;
25052     struct nk_window *popup;
25053     nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
25054 
25055     NK_ASSERT(ctx);
25056     NK_ASSERT(ctx->current);
25057     NK_ASSERT(ctx->current->layout);
25058     if (!ctx || !ctx->current || !ctx->current->layout)
25059         return 0;
25060 
25061     body.x = header.x;
25062     body.w = size.x;
25063     body.y = header.y + header.h;
25064     body.h = size.y;
25065 
25066     popup = win->popup.win;
25067     is_open = popup ? nk_true : nk_false;
25068     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
25069     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
25070         (!is_open && !is_active && !is_clicked)) return 0;
25071     if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
25072         return 0;
25073 
25074     win->popup.type = NK_PANEL_MENU;
25075     win->popup.name = hash;
25076     return 1;
25077 }
25078 
25079 NK_API int
25080 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
25081     nk_flags align, struct nk_vec2 size)
25082 {
25083     struct nk_window *win;
25084     const struct nk_input *in;
25085     struct nk_rect header;
25086     int is_clicked = nk_false;
25087     nk_flags state;
25088 
25089     NK_ASSERT(ctx);
25090     NK_ASSERT(ctx->current);
25091     NK_ASSERT(ctx->current->layout);
25092     if (!ctx || !ctx->current || !ctx->current->layout)
25093         return 0;
25094 
25095     win = ctx->current;
25096     state = nk_widget(&header, ctx);
25097     if (!state) return 0;
25098     in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25099     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
25100         title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
25101         is_clicked = nk_true;
25102     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
25103 }
25104 
25105 NK_API int nk_menu_begin_label(struct nk_context *ctx,
25106     const char *text, nk_flags align, struct nk_vec2 size)
25107 {return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);}
25108 
25109 NK_API int
25110 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
25111     struct nk_vec2 size)
25112 {
25113     struct nk_window *win;
25114     struct nk_rect header;
25115     const struct nk_input *in;
25116     int is_clicked = nk_false;
25117     nk_flags state;
25118 
25119     NK_ASSERT(ctx);
25120     NK_ASSERT(ctx->current);
25121     NK_ASSERT(ctx->current->layout);
25122     if (!ctx || !ctx->current || !ctx->current->layout)
25123         return 0;
25124 
25125     win = ctx->current;
25126     state = nk_widget(&header, ctx);
25127     if (!state) return 0;
25128     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25129     if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
25130         img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
25131         is_clicked = nk_true;
25132     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
25133 }
25134 
25135 NK_API int
25136 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
25137     enum nk_symbol_type sym, struct nk_vec2 size)
25138 {
25139     struct nk_window *win;
25140     const struct nk_input *in;
25141     struct nk_rect header;
25142     int is_clicked = nk_false;
25143     nk_flags state;
25144 
25145     NK_ASSERT(ctx);
25146     NK_ASSERT(ctx->current);
25147     NK_ASSERT(ctx->current->layout);
25148     if (!ctx || !ctx->current || !ctx->current->layout)
25149         return 0;
25150 
25151     win = ctx->current;
25152     state = nk_widget(&header, ctx);
25153     if (!state) return 0;
25154     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25155     if (nk_do_button_symbol(&ctx->last_widget_state,  &win->buffer, header,
25156         sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
25157         is_clicked = nk_true;
25158     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
25159 }
25160 
25161 NK_API int
25162 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
25163     nk_flags align, struct nk_image img, struct nk_vec2 size)
25164 {
25165     struct nk_window *win;
25166     struct nk_rect header;
25167     const struct nk_input *in;
25168     int is_clicked = nk_false;
25169     nk_flags state;
25170 
25171     NK_ASSERT(ctx);
25172     NK_ASSERT(ctx->current);
25173     NK_ASSERT(ctx->current->layout);
25174     if (!ctx || !ctx->current || !ctx->current->layout)
25175         return 0;
25176 
25177     win = ctx->current;
25178     state = nk_widget(&header, ctx);
25179     if (!state) return 0;
25180     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25181     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
25182         header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
25183         ctx->style.font, in))
25184         is_clicked = nk_true;
25185     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
25186 }
25187 
25188 NK_API int nk_menu_begin_image_label(struct nk_context *ctx,
25189     const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
25190 {return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);}
25191 
25192 NK_API int
25193 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
25194     nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
25195 {
25196     struct nk_window *win;
25197     struct nk_rect header;
25198     const struct nk_input *in;
25199     int is_clicked = nk_false;
25200     nk_flags state;
25201 
25202     NK_ASSERT(ctx);
25203     NK_ASSERT(ctx->current);
25204     NK_ASSERT(ctx->current->layout);
25205     if (!ctx || !ctx->current || !ctx->current->layout)
25206         return 0;
25207 
25208     win = ctx->current;
25209     state = nk_widget(&header, ctx);
25210     if (!state) return 0;
25211 
25212     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25213     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
25214         header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
25215         ctx->style.font, in)) is_clicked = nk_true;
25216     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
25217 }
25218 
25219 NK_API int nk_menu_begin_symbol_label(struct nk_context *ctx,
25220     const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
25221 {return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);}
25222 
25223 NK_API int nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
25224 {return nk_contextual_item_text(ctx, title, len, align);}
25225 
25226 NK_API int nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
25227 {return nk_contextual_item_label(ctx, label, align);}
25228 
25229 NK_API int nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
25230     const char *label, nk_flags align)
25231 {return nk_contextual_item_image_label(ctx, img, label, align);}
25232 
25233 NK_API int nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
25234     const char *text, int len, nk_flags align)
25235 {return nk_contextual_item_image_text(ctx, img, text, len, align);}
25236 
25237 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
25238     const char *text, int len, nk_flags align)
25239 {return nk_contextual_item_symbol_text(ctx, sym, text, len, align);}
25240 
25241 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
25242     const char *label, nk_flags align)
25243 {return nk_contextual_item_symbol_label(ctx, sym, label, align);}
25244 
25245 NK_API void nk_menu_close(struct nk_context *ctx)
25246 {nk_contextual_close(ctx);}
25247 
25248 NK_API void
25249 nk_menu_end(struct nk_context *ctx)
25250 {nk_contextual_end(ctx);}
25251 
25252 #endif /* NK_IMPLEMENTATION */
25253 
25254 /*
25255 /// ## License
25256 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
25257 ///    ------------------------------------------------------------------------------
25258 ///    This software is available under 2 licenses -- choose whichever you prefer.
25259 ///    ------------------------------------------------------------------------------
25260 ///    ALTERNATIVE A - MIT License
25261 ///    Copyright (c) 2016-2018 Micha Mettke
25262 ///    Permission is hereby granted, free of charge, to any person obtaining a copy of
25263 ///    this software and associated documentation files (the "Software"), to deal in
25264 ///    the Software without restriction, including without limitation the rights to
25265 ///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
25266 ///    of the Software, and to permit persons to whom the Software is furnished to do
25267 ///    so, subject to the following conditions:
25268 ///    The above copyright notice and this permission notice shall be included in all
25269 ///    copies or substantial portions of the Software.
25270 ///    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25271 ///    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25272 ///    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25273 ///    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25274 ///    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25275 ///    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25276 ///    SOFTWARE.
25277 ///    ------------------------------------------------------------------------------
25278 ///    ALTERNATIVE B - Public Domain (www.unlicense.org)
25279 ///    This is free and unencumbered software released into the public domain.
25280 ///    Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
25281 ///    software, either in source code form or as a compiled binary, for any purpose,
25282 ///    commercial or non-commercial, and by any means.
25283 ///    In jurisdictions that recognize copyright laws, the author or authors of this
25284 ///    software dedicate any and all copyright interest in the software to the public
25285 ///    domain. We make this dedication for the benefit of the public at large and to
25286 ///    the detriment of our heirs and successors. We intend this dedication to be an
25287 ///    overt act of relinquishment in perpetuity of all present and future rights to
25288 ///    this software under copyright law.
25289 ///    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25290 ///    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25291 ///    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25292 ///    AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25293 ///    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25294 ///    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25295 ///    ------------------------------------------------------------------------------
25296 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25297 
25298 /// ## Changelog
25299 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
25300 /// [date][x.yy.zz]-[description]
25301 /// -[date]: date on which the change has been pushed
25302 /// -[x.yy.zz]: Numerical version string representation. Each version number on the right
25303 ///             resets back to zero if version on the left is incremented.
25304 ///    - [x]: Major version with API and library breaking
25305 ///    - [yy]: Minor version with non-breaking API and library changes
25306 ///    - [zz]: Bug fix version with no direct changes to API
25307 ///
25308 /// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior
25309 /// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process
25310 /// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype
25311 /// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug
25312 /// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separed group identifier and title
25313 /// - 2018/01/07 (3.00.1) - Started to change documentation style
25314 /// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken
25315 ///                        because of conversions between float and byte color representation.
25316 ///                        Color pickers now use floating point values to represent
25317 ///                        HSV values. To get back the old behavior I added some additional
25318 ///                        color conversion functions to cast between nk_color and
25319 ///                        nk_colorf.
25320 /// - 2017/12/23 (2.00.7) - Fixed small warning
25321 /// - 2017/12/23 (2.00.7) - Fixed nk_edit_buffer behavior if activated to allow input
25322 /// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior
25323 /// - 2017/12/04 (2.00.6) - Added formated string tooltip widget
25324 /// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag NK_WINDOW_NO_INPUT
25325 /// - 2017/11/15 (2.00.4) - Fixed font merging
25326 /// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions
25327 /// - 2017/09/14 (2.00.2) - Fixed nk_edit_buffer and nk_edit_focus behavior
25328 /// - 2017/09/14 (2.00.1) - Fixed window closing behavior
25329 /// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifing window position and size funtions now
25330 ///                        require the name of the window and must happen outside the window
25331 ///                        building process (between function call nk_begin and nk_end).
25332 /// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last
25333 /// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows
25334 /// - 2017/08/27 (1.40.7) - Fixed window background flag
25335 /// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked
25336 ///                        query for widgets
25337 /// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked
25338 ///                        and filled rectangles
25339 /// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in
25340 ///                        process of being destroyed.
25341 /// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in
25342 ///                        window instead of directly in table.
25343 /// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro
25344 /// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero
25345 /// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only
25346 ///                        comes in effect if you pass in zero was row height argument
25347 /// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change
25348 ///                        how layouting works. From now there will be an internal minimum
25349 ///                        row height derived from font height. If you need a row smaller than
25350 ///                        that you can directly set it by `nk_layout_set_min_row_height` and
25351 ///                        reset the value back by calling `nk_layout_reset_min_row_height.
25352 /// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix
25353 /// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a nk_layout_xxx function
25354 /// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer
25355 /// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped
25356 /// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundries
25357 /// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space
25358 /// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size
25359 /// - 2017/05/06 (1.38.0) - Added platform double-click support
25360 /// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends
25361 /// - 2017/04/20 (1.37.0) - Extended properties with selection and clipbard support
25362 /// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing
25363 /// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error
25364 /// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags
25365 /// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption
25366 /// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows
25367 /// - 2017/03/25 (1.35.1) - Fixed windows closing behavior
25368 /// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377
25369 /// - 2017/03/18 (1.34.3) - Fixed long window header titles
25370 /// - 2017/03/04 (1.34.2) - Fixed text edit filtering
25371 /// - 2017/03/04 (1.34.1) - Fixed group closable flag
25372 /// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support
25373 /// - 2017/01/24 (1.33.0) - Added programatic way of remove edit focus
25374 /// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows
25375 /// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows
25376 /// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing
25377 /// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner
25378 /// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both
25379 ///                        dynamic and static widgets.
25380 /// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit
25381 /// - 2016/12/31 (1.29.2)- Fixed closing window bug of minimized windows
25382 /// - 2016/12/03 (1.29.1)- Fixed wrapped text with no seperator and C89 error
25383 /// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters
25384 /// - 2016/11/22 (1.28.6)- Fixed window minimized closing bug
25385 /// - 2016/11/19 (1.28.5)- Fixed abstract combo box closing behavior
25386 /// - 2016/11/19 (1.28.4)- Fixed tooltip flickering
25387 /// - 2016/11/19 (1.28.3)- Fixed memory leak caused by popup repeated closing
25388 /// - 2016/11/18 (1.28.2)- Fixed memory leak caused by popup panel allocation
25389 /// - 2016/11/10 (1.28.1)- Fixed some warnings and C++ error
25390 /// - 2016/11/10 (1.28.0)- Added additional `nk_button` versions which allows to directly
25391 ///                        pass in a style struct to change buttons visual.
25392 /// - 2016/11/10 (1.27.0)- Added additional 'nk_tree' versions to support external state
25393 ///                        storage. Just like last the `nk_group` commit the main
25394 ///                        advantage is that you optionally can minimize nuklears runtime
25395 ///                        memory consumption or handle hash collisions.
25396 /// - 2016/11/09 (1.26.0)- Added additional `nk_group` version to support external scrollbar
25397 ///                        offset storage. Main advantage is that you can externalize
25398 ///                        the memory management for the offset. It could also be helpful
25399 ///                        if you have a hash collision in `nk_group_begin` but really
25400 ///                        want the name. In addition I added `nk_list_view` which allows
25401 ///                        to draw big lists inside a group without actually having to
25402 ///                        commit the whole list to nuklear (issue #269).
25403 /// - 2016/10/30 (1.25.1)- Fixed clipping rectangle bug inside `nk_draw_list`
25404 /// - 2016/10/29 (1.25.0)- Pulled `nk_panel` memory management into nuklear and out of
25405 ///                        the hands of the user. From now on users don't have to care
25406 ///                        about panels unless they care about some information. If you
25407 ///                        still need the panel just call `nk_window_get_panel`.
25408 /// - 2016/10/21 (1.24.0)- Changed widget border drawing to stroked rectangle from filled
25409 ///                        rectangle for less overdraw and widget background transparency.
25410 /// - 2016/10/18 (1.23.0)- Added `nk_edit_focus` for manually edit widget focus control
25411 /// - 2016/09/29 (1.22.7)- Fixed deduction of basic type in non `<stdint.h>` compilation
25412 /// - 2016/09/29 (1.22.6)- Fixed edit widget UTF-8 text cursor drawing bug
25413 /// - 2016/09/28 (1.22.5)- Fixed edit widget UTF-8 text appending/inserting/removing
25414 /// - 2016/09/28 (1.22.4)- Fixed drawing bug inside edit widgets which offset all text
25415 ///                        text in every edit widget if one of them is scrolled.
25416 /// - 2016/09/28 (1.22.3)- Fixed small bug in edit widgets if not active. The wrong
25417 ///                        text length is passed. It should have been in bytes but
25418 ///                        was passed as glyphes.
25419 /// - 2016/09/20 (1.22.2)- Fixed color button size calculation
25420 /// - 2016/09/20 (1.22.1)- Fixed some `nk_vsnprintf` behavior bugs and removed
25421 ///                        `<stdio.h>` again from `NK_INCLUDE_STANDARD_VARARGS`.
25422 /// - 2016/09/18 (1.22.0)- C89 does not support vsnprintf only C99 and newer as well
25423 ///                        as C++11 and newer. In addition to use vsnprintf you have
25424 ///                        to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS`
25425 ///                        is not enough. That behavior is now fixed. By default if
25426 ///                        both varargs as well as stdio is selected I try to use
25427 ///                        vsnprintf if not possible I will revert to vsprintf. If
25428 ///                        varargs but not stdio was defined I will use my own function.
25429 /// - 2016/09/15 (1.21.2)- Fixed panel `close` behavior for deeper panel levels
25430 /// - 2016/09/15 (1.21.1)- Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`
25431 /// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo,
25432 ///                        and contextual which prevented closing in y-direction if
25433 ///                        popup did not reach max height.
25434 ///                        In addition the height parameter was changed into vec2
25435 ///                        for width and height to have more control over the popup size.
25436 /// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection
25437 /// - 2016/09/13 (1.20.2)- Fixed slider behavior hopefully for the last time. This time
25438 ///                        all calculation are correct so no more hackery.
25439 /// - 2016/09/13 (1.20.1)- Internal change to divide window/panel flags into panel flags and types.
25440 ///                        Suprisinly spend years in C and still happened to confuse types
25441 ///                        with flags. Probably something to take note.
25442 /// - 2016/09/08 (1.20.0)- Added additional helper function to make it easier to just
25443 ///                        take the produced buffers from `nk_convert` and unplug the
25444 ///                        iteration process from `nk_context`. So now you can
25445 ///                        just use the vertex,element and command buffer + two pointer
25446 ///                        inside the command buffer retrieved by calls `nk__draw_begin`
25447 ///                        and `nk__draw_end` and macro `nk_draw_foreach_bounded`.
25448 /// - 2016/09/08 (1.19.0)- Added additional asserts to make sure every `nk_xxx_begin` call
25449 ///                        for windows, popups, combobox, menu and contextual is guarded by
25450 ///                        `if` condition and does not produce false drawing output.
25451 /// - 2016/09/08 (1.18.0)- Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT`
25452 ///                        to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and
25453 ///                        `NK_SYMBOL_RECT_OUTLINE`.
25454 /// - 2016/09/08 (1.17.0)- Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE`
25455 ///                        to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and
25456 ///                        `NK_SYMBOL_CIRCLE_OUTLINE`.
25457 /// - 2016/09/08 (1.16.0)- Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES`
25458 ///                        is not defined by supporting the biggest compiler GCC, clang and MSVC.
25459 /// - 2016/09/07 (1.15.3)- Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error
25460 /// - 2016/09/04 (1.15.2)- Fixed wrong combobox height calculation
25461 /// - 2016/09/03 (1.15.1)- Fixed gaps inside combo boxes in OpenGL
25462 /// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and
25463 ///                        instead made it user provided. The range of types to convert
25464 ///                        to is quite limited at the moment, but I would be more than
25465 ///                        happy to accept PRs to add additional.
25466 /// - 2016/08/30 (1.14.2) - Removed unused variables
25467 /// - 2016/08/30 (1.14.1) - Fixed C++ build errors
25468 /// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly
25469 /// - 2016/08/30 (1.13.4) - Tweaked some default styling variables
25470 /// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would
25471 ///                        refrain from using slider with a big number of steps.
25472 /// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the
25473 ///                        window was in Read Only Mode.
25474 /// - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just
25475 ///                        a hack for combo box and menu.
25476 /// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since
25477 ///                        it is bugged and causes issues in window selection.
25478 /// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now
25479 ///                        determined by the scrollbar size
25480 /// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11
25481 /// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection
25482 /// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code
25483 ///                        handling panel padding and panel border.
25484 /// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`
25485 /// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups
25486 /// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes
25487 /// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for
25488 ///                        hash collisions. Currently limited to NK_WINDOW_MAX_NAME
25489 ///                        which in term can be redefined if not big enough.
25490 /// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code
25491 /// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released'
25492 ///                        to account for key press and release happening in one frame.
25493 /// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate
25494 /// - 2016/08/17 (1.09.6)- Removed invalid check for value zero in nk_propertyx
25495 /// - 2016/08/16 (1.09.5)- Fixed ROM mode for deeper levels of popup windows parents.
25496 /// - 2016/08/15 (1.09.4)- Editbox are now still active if enter was pressed with flag
25497 ///                        `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep
25498 ///                        typing after commiting.
25499 /// - 2016/08/15 (1.09.4)- Removed redundant code
25500 /// - 2016/08/15 (1.09.4)- Fixed negative numbers in `nk_strtoi` and remove unused variable
25501 /// - 2016/08/15 (1.09.3)- Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background
25502 ///                        window only as selected by hovering and not by clicking.
25503 /// - 2016/08/14 (1.09.2)- Fixed a bug in font atlas which caused wrong loading
25504 ///                        of glyphes for font with multiple ranges.
25505 /// - 2016/08/12 (1.09.1)- Added additional function to check if window is currently
25506 ///                        hidden and therefore not visible.
25507 /// - 2016/08/12 (1.09.1)- nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED`
25508 ///                        instead of the old flag `NK_WINDOW_HIDDEN`
25509 /// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed
25510 ///                        the underlying implementation to not cast to float and instead
25511 ///                        work directly on the given values.
25512 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
25513 ///                        floating pointer number to string conversion for additional
25514 ///                        precision.
25515 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
25516 ///                        string to floating point number conversion for additional
25517 ///                        precision.
25518 /// - 2016/08/08 (1.07.2)- Fixed compiling error without define NK_INCLUDE_FIXED_TYPE
25519 /// - 2016/08/08 (1.07.1)- Fixed possible floating point error inside `nk_widget` leading
25520 ///                        to wrong wiget width calculation which results in widgets falsly
25521 ///                        becomming tagged as not inside window and cannot be accessed.
25522 /// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and
25523 ///                        closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown
25524 ///                        by using `nk_window_show` and closed by either clicking the close
25525 ///                        icon in a window or by calling `nk_window_close`. Only closed
25526 ///                        windows get removed at the end of the frame while hidden windows
25527 ///                        remain.
25528 /// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to
25529 ///                        `nk_edit_string` which takes, edits and outputs a '\0' terminated string.
25530 /// - 2016/08/08 (1.05.4)- Fixed scrollbar auto hiding behavior
25531 /// - 2016/08/08 (1.05.3)- Fixed wrong panel padding selection in `nk_layout_widget_space`
25532 /// - 2016/08/07 (1.05.2)- Fixed old bug in dynamic immediate mode layout API, calculating
25533 ///                        wrong item spacing and panel width.
25534 ///- 2016/08/07 (1.05.1)- Hopefully finally fixed combobox popup drawing bug
25535 ///- 2016/08/07 (1.05.0) - Split varargs away from NK_INCLUDE_STANDARD_IO into own
25536 ///                        define NK_INCLUDE_STANDARD_VARARGS to allow more fine
25537 ///                        grained controlled over library includes.
25538 /// - 2016/08/06 (1.04.5)- Changed memset calls to NK_MEMSET
25539 /// - 2016/08/04 (1.04.4)- Fixed fast window scaling behavior
25540 /// - 2016/08/04 (1.04.3)- Fixed window scaling, movement bug which appears if you
25541 ///                        move/scale a window and another window is behind it.
25542 ///                        If you are fast enough then the window behind gets activated
25543 ///                        and the operation is blocked. I now require activating
25544 ///                        by hovering only if mouse is not pressed.
25545 /// - 2016/08/04 (1.04.2)- Fixed changing fonts
25546 /// - 2016/08/03 (1.04.1)- Fixed `NK_WINDOW_BACKGROUND` behavior
25547 /// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`
25548 /// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for
25549 ///                        sub windows (combo, menu, ...)
25550 /// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor
25551 /// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window
25552 ///                        to be always in the background of the screen
25553 /// - 2016/08/03 (1.03.2)- Removed invalid assert macro for NK_RGB color picker
25554 /// - 2016/08/01 (1.03.1)- Added helper macros into header include guard
25555 /// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to
25556 ///                        simplify memory management by removing the need to
25557 ///                        allocate the pool.
25558 /// - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled
25559 ///                        will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT
25560 ///                        seconds without window interaction. To make it work
25561 ///                        you have to also set a delta time inside the `nk_context`.
25562 /// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs
25563 /// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`
25564 /// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument
25565 /// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified
25566 ///                        font atlas memory management by converting pointer
25567 ///                        arrays for fonts and font configurations to lists.
25568 /// - 2016/07/15 (1.00.0) - Changed button API to use context dependend button
25569 ///                        behavior instead of passing it for every function call.
25570 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25571 ///
25572 /// ## Gallery
25573 /// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png)
25574 /// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png)
25575 /// ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png)
25576 /// ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png)
25577 /// ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png)
25578 /// ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png)
25579 /// ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif)
25580 /// ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png)
25581 /// ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png)
25582 ///
25583 /// ## Credits
25584 /// Developed by Micha Mettke and every direct or indirect github contributor. <br /><br />
25585 ///
25586 /// 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 />
25587 /// Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from r-lyeh@github.com for documentation generation <br /><br />
25588 /// Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br />
25589 ///
25590 /// Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and
25591 /// giving me the inspiration for this library, Casey Muratori for handmade hero
25592 /// and his original immediate mode graphical user interface idea and Sean
25593 /// Barret for his amazing single header libraries which restored my faith
25594 /// in libraries and brought me to create some of my own.
25595 ///
25596 */
25597