• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 /// # Nuklear
3 /// ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif)
4 ///
5 /// ## Contents
6 /// 1. About section
7 /// 2. Highlights section
8 /// 3. Features section
9 /// 4. Usage section
10 ///     1. Flags section
11 ///     2. Constants section
12 ///     3. Dependencies section
13 /// 5. Example section
14 /// 6. API section
15 ///     1. Context section
16 ///     2. Input section
17 ///     3. Drawing section
18 ///     4. Window section
19 ///     5. Layouting section
20 ///     6. Groups section
21 ///     7. Tree section
22 ///     8. Properties section
23 /// 7. License section
24 /// 8. Changelog section
25 /// 9. Gallery section
26 /// 10. Credits section
27 ///
28 /// ## About
29 /// This is a minimal state immediate mode graphical user interface toolkit
30 /// written in ANSI C and licensed under public domain. It was designed as a simple
31 /// embeddable user interface for application and does not have any dependencies,
32 /// a default renderbackend or OS window and input handling but instead provides a very modular
33 /// library approach by using simple input state for input and draw
34 /// commands describing primitive shapes as output. So instead of providing a
35 /// layered library that tries to abstract over a number of platform and
36 /// render backends it only focuses on the actual UI.
37 ///
38 /// ## Highlights
39 /// - Graphical user interface toolkit
40 /// - Single header library
41 /// - Written in C89 (a.k.a. ANSI C or ISO C90)
42 /// - Small codebase (~18kLOC)
43 /// - Focus on portability, efficiency and simplicity
44 /// - No dependencies (not even the standard library if not wanted)
45 /// - Fully skinnable and customizable
46 /// - Low memory footprint with total memory control if needed or wanted
47 /// - UTF-8 support
48 /// - No global or hidden state
49 /// - Customizable library modules (you can compile and use only what you need)
50 /// - Optional font baker and vertex buffer output
51 ///
52 /// ## Features
53 /// - Absolutely no platform dependent code
54 /// - Memory management control ranging from/to
55 ///     - Ease of use by allocating everything from standard library
56 ///     - Control every byte of memory inside the library
57 /// - Font handling control ranging from/to
58 ///     - Use your own font implementation for everything
59 ///     - Use this libraries internal font baking and handling API
60 /// - Drawing output control ranging from/to
61 ///     - Simple shapes for more high level APIs which already have drawing capabilities
62 ///     - Hardware accessible anti-aliased vertex buffer output
63 /// - Customizable colors and properties ranging from/to
64 ///     - Simple changes to color by filling a simple color table
65 ///     - Complete control with ability to use skinning to decorate widgets
66 /// - Bendable UI library with widget ranging from/to
67 ///     - Basic widgets like buttons, checkboxes, slider, ...
68 ///     - Advanced widget like abstract comboboxes, contextual menus,...
69 /// - Compile time configuration to only compile what you need
70 ///     - Subset which can be used if you do not want to link or use the standard library
71 /// - Can be easily modified to only update on user input instead of frame updates
72 ///
73 /// ## Usage
74 /// This library is self contained in one single header file and can be used either
75 /// in header only mode or in implementation mode. The header only mode is used
76 /// by default when included and allows including this header in other headers
77 /// and does not contain the actual implementation. <br /><br />
78 ///
79 /// The implementation mode requires to define  the preprocessor macro
80 /// NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.:
81 ///
82 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C
83 ///     #define NK_IMPLEMENTATION
84 ///     #include "nuklear.h"
85 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
86 ///
87 /// Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
88 /// below in header and implementation mode if you want to use additional functionality
89 /// or need more control over the library.
90 ///
91 /// !!! WARNING
92 ///     Every time nuklear is included define the same compiler flags. This very important not doing so could lead to compiler errors or even worse stack corruptions.
93 ///
94 /// ### Flags
95 /// Flag                            | Description
96 /// --------------------------------|------------------------------------------
97 /// NK_PRIVATE                      | If defined declares all functions as static, so they can only be accessed inside the file that contains the implementation
98 /// NK_INCLUDE_FIXED_TYPES          | If defined it will include header `<stdint.h>` for fixed sized types otherwise nuklear tries to select the correct type. If that fails it will throw a compiler error and you have to select the correct types yourself.
99 /// NK_INCLUDE_DEFAULT_ALLOCATOR    | If defined it will include header `<stdlib.h>` and provide additional functions to use this library without caring for memory allocation control and therefore ease memory management.
100 /// NK_INCLUDE_STANDARD_IO          | If defined it will include header `<stdio.h>` and provide additional functions depending on file loading.
101 /// NK_INCLUDE_STANDARD_VARARGS     | If defined it will include header <stdio.h> and provide additional functions depending on file loading.
102 /// NK_INCLUDE_VERTEX_BUFFER_OUTPUT | Defining this adds a vertex draw command list backend to this library, which allows you to convert queue commands into vertex draw commands. This is mainly if you need a hardware accessible format for OpenGL, DirectX, Vulkan, Metal,...
103 /// NK_INCLUDE_FONT_BAKING          | Defining this adds `stb_truetype` and `stb_rect_pack` implementation to this library and provides font baking and rendering. If you already have font handling or do not want to use this font handler you don't have to define it.
104 /// NK_INCLUDE_DEFAULT_FONT         | Defining this adds the default font: ProggyClean.ttf into this library which can be loaded into a font atlas and allows using this library without having a truetype font
105 /// NK_INCLUDE_COMMAND_USERDATA     | Defining this adds a userdata pointer into each command. Can be useful for example if you want to provide custom shaders depending on the used widget. Can be combined with the style structures.
106 /// NK_BUTTON_TRIGGER_ON_RELEASE    | Different platforms require button clicks occurring either on buttons being pressed (up to down) or released (down to up). By default this library will react on buttons being pressed, but if you define this it will only trigger if a button is released.
107 /// NK_ZERO_COMMAND_MEMORY          | Defining this will zero out memory for each drawing command added to a drawing queue (inside nk_command_buffer_push). Zeroing command memory is very useful for fast checking (using memcmp) if command buffers are equal and avoid drawing frames when nothing on screen has changed since previous frame.
108 /// NK_UINT_DRAW_INDEX              | Defining this will set the size of vertex index elements when using NK_VERTEX_BUFFER_OUTPUT to 32bit instead of the default of 16bit
109 /// NK_KEYSTATE_BASED_INPUT         | Define this if your backend uses key state for each frame rather than key press/release events
110 ///
111 /// !!! WARNING
112 ///     The following flags will pull in the standard C library:
113 ///     - NK_INCLUDE_DEFAULT_ALLOCATOR
114 ///     - NK_INCLUDE_STANDARD_IO
115 ///     - NK_INCLUDE_STANDARD_VARARGS
116 ///
117 /// !!! WARNING
118 ///     The following flags if defined need to be defined for both header and implementation:
119 ///     - NK_INCLUDE_FIXED_TYPES
120 ///     - NK_INCLUDE_DEFAULT_ALLOCATOR
121 ///     - NK_INCLUDE_STANDARD_VARARGS
122 ///     - NK_INCLUDE_VERTEX_BUFFER_OUTPUT
123 ///     - NK_INCLUDE_FONT_BAKING
124 ///     - NK_INCLUDE_DEFAULT_FONT
125 ///     - NK_INCLUDE_STANDARD_VARARGS
126 ///     - NK_INCLUDE_COMMAND_USERDATA
127 ///     - NK_UINT_DRAW_INDEX
128 ///
129 /// ### Constants
130 /// Define                          | Description
131 /// --------------------------------|---------------------------------------
132 /// 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.
133 /// NK_MAX_NUMBER_BUFFER            | Maximum buffer size for the conversion buffer between float and string Under normal circumstances this should be more than sufficient.
134 /// 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.
135 ///
136 /// !!! WARNING
137 ///     The following constants if defined need to be defined for both header and implementation:
138 ///     - NK_MAX_NUMBER_BUFFER
139 ///     - NK_BUFFER_DEFAULT_INITIAL_SIZE
140 ///     - NK_INPUT_MAX
141 ///
142 /// ### Dependencies
143 /// Function    | Description
144 /// ------------|---------------------------------------------------------------
145 /// NK_ASSERT   | If you don't define this, nuklear will use <assert.h> with assert().
146 /// NK_MEMSET   | You can define this to 'memset' or your own memset implementation replacement. If not nuklear will use its own version.
147 /// NK_MEMCPY   | You can define this to 'memcpy' or your own memcpy implementation replacement. If not nuklear will use its own version.
148 /// 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.
149 /// NK_SIN      | You can define this to 'sinf' or your own sine implementation replacement. If not nuklear will use its own approximation implementation.
150 /// NK_COS      | You can define this to 'cosf' or your own cosine implementation replacement. If not nuklear will use its own approximation implementation.
151 /// 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!).
152 /// 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!).
153 /// 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.
154 ///
155 /// !!! WARNING
156 ///     The following dependencies will pull in the standard C library if not redefined:
157 ///     - NK_ASSERT
158 ///
159 /// !!! WARNING
160 ///     The following dependencies if defined need to be defined for both header and implementation:
161 ///     - NK_ASSERT
162 ///
163 /// !!! WARNING
164 ///     The following dependencies if defined need to be defined only for the implementation part:
165 ///     - NK_MEMSET
166 ///     - NK_MEMCPY
167 ///     - NK_SQRT
168 ///     - NK_SIN
169 ///     - NK_COS
170 ///     - NK_STRTOD
171 ///     - NK_DTOA
172 ///     - NK_VSNPRINTF
173 ///
174 /// ## Example
175 ///
176 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
177 /// // init gui state
178 /// enum {EASY, HARD};
179 /// static int op = EASY;
180 /// static float value = 0.6f;
181 /// static int i =  20;
182 /// struct nk_context ctx;
183 ///
184 /// nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);
185 /// if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220),
186 ///     NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
187 ///     // fixed widget pixel width
188 ///     nk_layout_row_static(&ctx, 30, 80, 1);
189 ///     if (nk_button_label(&ctx, "button")) {
190 ///         // event handling
191 ///     }
192 ///
193 ///     // fixed widget window ratio width
194 ///     nk_layout_row_dynamic(&ctx, 30, 2);
195 ///     if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY;
196 ///     if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD;
197 ///
198 ///     // custom widget pixel width
199 ///     nk_layout_row_begin(&ctx, NK_STATIC, 30, 2);
200 ///     {
201 ///         nk_layout_row_push(&ctx, 50);
202 ///         nk_label(&ctx, "Volume:", NK_TEXT_LEFT);
203 ///         nk_layout_row_push(&ctx, 110);
204 ///         nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
205 ///     }
206 ///     nk_layout_row_end(&ctx);
207 /// }
208 /// nk_end(&ctx);
209 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
210 ///
211 /// ![](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png)
212 ///
213 /// ## API
214 ///
215 */
216 #ifndef NK_SINGLE_FILE
217   #define NK_SINGLE_FILE
218 #endif
219 
220 #ifndef NK_NUKLEAR_H_
221 #define NK_NUKLEAR_H_
222 
223 #ifdef __cplusplus
224 extern "C" {
225 #endif
226 /*
227  * ==============================================================
228  *
229  *                          CONSTANTS
230  *
231  * ===============================================================
232  */
233 #define NK_UNDEFINED (-1.0f)
234 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
235 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
236 #ifndef NK_INPUT_MAX
237   #define NK_INPUT_MAX 16
238 #endif
239 #ifndef NK_MAX_NUMBER_BUFFER
240   #define NK_MAX_NUMBER_BUFFER 64
241 #endif
242 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
243   #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
244 #endif
245 /*
246  * ==============================================================
247  *
248  *                          HELPER
249  *
250  * ===============================================================
251  */
252 #ifndef NK_API
253   #ifdef NK_PRIVATE
254     #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
255       #define NK_API static inline
256     #elif defined(__cplusplus)
257       #define NK_API static inline
258     #else
259       #define NK_API static
260     #endif
261   #else
262     #define NK_API extern
263   #endif
264 #endif
265 #ifndef NK_LIB
266   #ifdef NK_SINGLE_FILE
267     #define NK_LIB static
268   #else
269     #define NK_LIB extern
270   #endif
271 #endif
272 
273 #define NK_INTERN static
274 #define NK_STORAGE static
275 #define NK_GLOBAL static
276 
277 #define NK_FLAG(x) (1 << (x))
278 #define NK_STRINGIFY(x) #x
279 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
280 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
281 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
282 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
283 
284 #ifdef _MSC_VER
285   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
286 #else
287   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
288 #endif
289 
290 #ifndef NK_STATIC_ASSERT
291   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
292 #endif
293 
294 #ifndef NK_FILE_LINE
295 #ifdef _MSC_VER
296   #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
297 #else
298   #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
299 #endif
300 #endif
301 
302 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
303 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
304 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
305 
306 #ifdef NK_INCLUDE_STANDARD_VARARGS
307   #include <stdarg.h> /* valist, va_start, va_end, ... */
308   #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
309     #include <sal.h>
310     #define NK_PRINTF_FORMAT_STRING _Printf_format_string_
311   #else
312     #define NK_PRINTF_FORMAT_STRING
313   #endif
314   #if defined(__GNUC__)
315     #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1)))
316     #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0)))
317   #else
318     #define NK_PRINTF_VARARG_FUNC(fmtargnumber)
319     #define NK_PRINTF_VALIST_FUNC(fmtargnumber)
320   #endif
321 #endif
322 
323 /*
324  * ===============================================================
325  *
326  *                          BASIC
327  *
328  * ===============================================================
329  */
330 #ifdef NK_INCLUDE_FIXED_TYPES
331  #include <stdint.h>
332  #define NK_INT8 int8_t
333  #define NK_UINT8 uint8_t
334  #define NK_INT16 int16_t
335  #define NK_UINT16 uint16_t
336  #define NK_INT32 int32_t
337  #define NK_UINT32 uint32_t
338  #define NK_SIZE_TYPE uintptr_t
339  #define NK_POINTER_TYPE uintptr_t
340 #else
341   #ifndef NK_INT8
342     #define NK_INT8 signed char
343   #endif
344   #ifndef NK_UINT8
345     #define NK_UINT8 unsigned char
346   #endif
347   #ifndef NK_INT16
348     #define NK_INT16 signed short
349   #endif
350   #ifndef NK_UINT16
351     #define NK_UINT16 unsigned short
352   #endif
353   #ifndef NK_INT32
354     #if defined(_MSC_VER)
355       #define NK_INT32 __int32
356     #else
357       #define NK_INT32 signed int
358     #endif
359   #endif
360   #ifndef NK_UINT32
361     #if defined(_MSC_VER)
362       #define NK_UINT32 unsigned __int32
363     #else
364       #define NK_UINT32 unsigned int
365     #endif
366   #endif
367   #ifndef NK_SIZE_TYPE
368     #if defined(_WIN64) && defined(_MSC_VER)
369       #define NK_SIZE_TYPE unsigned __int64
370     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
371       #define NK_SIZE_TYPE unsigned __int32
372     #elif defined(__GNUC__) || defined(__clang__)
373       #if defined(__x86_64__) || defined(__ppc64__)
374         #define NK_SIZE_TYPE unsigned long
375       #else
376         #define NK_SIZE_TYPE unsigned int
377       #endif
378     #else
379       #define NK_SIZE_TYPE unsigned long
380     #endif
381   #endif
382   #ifndef NK_POINTER_TYPE
383     #if defined(_WIN64) && defined(_MSC_VER)
384       #define NK_POINTER_TYPE unsigned __int64
385     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
386       #define NK_POINTER_TYPE unsigned __int32
387     #elif defined(__GNUC__) || defined(__clang__)
388       #if defined(__x86_64__) || defined(__ppc64__)
389         #define NK_POINTER_TYPE unsigned long
390       #else
391         #define NK_POINTER_TYPE unsigned int
392       #endif
393     #else
394       #define NK_POINTER_TYPE unsigned long
395     #endif
396   #endif
397 #endif
398 
399 typedef NK_INT8 nk_char;
400 typedef NK_UINT8 nk_uchar;
401 typedef NK_UINT8 nk_byte;
402 typedef NK_INT16 nk_short;
403 typedef NK_UINT16 nk_ushort;
404 typedef NK_INT32 nk_int;
405 typedef NK_UINT32 nk_uint;
406 typedef NK_SIZE_TYPE nk_size;
407 typedef NK_POINTER_TYPE nk_ptr;
408 
409 typedef nk_uint nk_hash;
410 typedef nk_uint nk_flags;
411 typedef nk_uint nk_rune;
412 
413 /* Make sure correct type size:
414  * This will fire with a negative subscript error if the type sizes
415  * are set incorrectly by the compiler, and compile out if not */
416 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
417 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
418 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
419 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
420 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
421 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
422 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
423 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
424 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
425 
426 /* ============================================================================
427  *
428  *                                  API
429  *
430  * =========================================================================== */
431 struct nk_buffer;
432 struct nk_allocator;
433 struct nk_command_buffer;
434 struct nk_draw_command;
435 struct nk_convert_config;
436 struct nk_style_item;
437 struct nk_text_edit;
438 struct nk_draw_list;
439 struct nk_user_font;
440 struct nk_panel;
441 struct nk_context;
442 struct nk_draw_vertex_layout_element;
443 struct nk_style_button;
444 struct nk_style_toggle;
445 struct nk_style_selectable;
446 struct nk_style_slide;
447 struct nk_style_progress;
448 struct nk_style_scrollbar;
449 struct nk_style_edit;
450 struct nk_style_property;
451 struct nk_style_chart;
452 struct nk_style_combo;
453 struct nk_style_tab;
454 struct nk_style_window_header;
455 struct nk_style_window;
456 
457 enum {nk_false, nk_true};
458 struct nk_color {nk_byte r,g,b,a;};
459 struct nk_colorf {float r,g,b,a;};
460 struct nk_vec2 {float x,y;};
461 struct nk_vec2i {short x, y;};
462 struct nk_rect {float x,y,w,h;};
463 struct nk_recti {short x,y,w,h;};
464 typedef char nk_glyph[NK_UTF_SIZE];
465 typedef union {void *ptr; int id;} nk_handle;
466 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
467 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
468 struct nk_scroll {nk_uint x, y;};
469 
470 enum nk_heading         {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
471 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
472 enum nk_modify          {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
473 enum nk_orientation     {NK_VERTICAL, NK_HORIZONTAL};
474 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true};
475 enum nk_show_states     {NK_HIDDEN = nk_false, NK_SHOWN = nk_true};
476 enum nk_chart_type      {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX};
477 enum nk_chart_event     {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02};
478 enum nk_color_format    {NK_RGB, NK_RGBA};
479 enum nk_popup_type      {NK_POPUP_STATIC, NK_POPUP_DYNAMIC};
480 enum nk_layout_format   {NK_DYNAMIC, NK_STATIC};
481 enum nk_tree_type       {NK_TREE_NODE, NK_TREE_TAB};
482 
483 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
484 typedef void (*nk_plugin_free)(nk_handle, void *old);
485 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
486 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
487 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
488 
489 struct nk_allocator {
490     nk_handle userdata;
491     nk_plugin_alloc alloc;
492     nk_plugin_free free;
493 };
494 enum nk_symbol_type {
495     NK_SYMBOL_NONE,
496     NK_SYMBOL_X,
497     NK_SYMBOL_UNDERSCORE,
498     NK_SYMBOL_CIRCLE_SOLID,
499     NK_SYMBOL_CIRCLE_OUTLINE,
500     NK_SYMBOL_RECT_SOLID,
501     NK_SYMBOL_RECT_OUTLINE,
502     NK_SYMBOL_TRIANGLE_UP,
503     NK_SYMBOL_TRIANGLE_DOWN,
504     NK_SYMBOL_TRIANGLE_LEFT,
505     NK_SYMBOL_TRIANGLE_RIGHT,
506     NK_SYMBOL_PLUS,
507     NK_SYMBOL_MINUS,
508     NK_SYMBOL_MAX
509 };
510 /* =============================================================================
511  *
512  *                                  CONTEXT
513  *
514  * =============================================================================*/
515 /*/// ### Context
516 /// Contexts are the main entry point and the majestro of nuklear and contain all required state.
517 /// They are used for window, memory, input, style, stack, commands and time management and need
518 /// to be passed into all nuklear GUI specific functions.
519 ///
520 /// #### Usage
521 /// To use a context it first has to be initialized which can be achieved by calling
522 /// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
523 /// Each takes in a font handle and a specific way of handling memory. Memory control
524 /// hereby ranges from standard library to just specifying a fixed sized block of memory
525 /// which nuklear has to manage itself from.
526 ///
527 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
528 /// struct nk_context ctx;
529 /// nk_init_xxx(&ctx, ...);
530 /// while (1) {
531 ///     // [...]
532 ///     nk_clear(&ctx);
533 /// }
534 /// nk_free(&ctx);
535 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
536 ///
537 /// #### Reference
538 /// Function            | Description
539 /// --------------------|-------------------------------------------------------
540 /// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free)
541 /// __nk_init_fixed__   | Initializes context from single fixed size memory block
542 /// __nk_init__         | Initializes context with memory allocator callbacks for alloc and free
543 /// __nk_init_custom__  | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
544 /// __nk_clear__        | Called at the end of the frame to reset and prepare the context for the next frame
545 /// __nk_free__         | Shutdown and free all memory allocated inside the context
546 /// __nk_set_user_data__| Utility function to pass user data to draw command
547  */
548 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
549 /*/// #### nk_init_default
550 /// Initializes a `nk_context` struct with a default standard library allocator.
551 /// Should be used if you don't want to be bothered with memory management in nuklear.
552 ///
553 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
554 /// int nk_init_default(struct nk_context *ctx, const struct nk_user_font *font);
555 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
556 ///
557 /// Parameter   | Description
558 /// ------------|---------------------------------------------------------------
559 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
560 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
561 ///
562 /// Returns either `false(0)` on failure or `true(1)` on success.
563 ///
564 */
565 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
566 #endif
567 /*/// #### nk_init_fixed
568 /// Initializes a `nk_context` struct from single fixed size memory block
569 /// Should be used if you want complete control over nuklear's memory management.
570 /// Especially recommended for system with little memory or systems with virtual memory.
571 /// For the later case you can just allocate for example 16MB of virtual memory
572 /// and only the required amount of memory will actually be committed.
573 ///
574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
575 /// int nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font);
576 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
577 ///
578 /// !!! Warning
579 ///     make sure the passed memory block is aligned correctly for `nk_draw_commands`.
580 ///
581 /// Parameter   | Description
582 /// ------------|--------------------------------------------------------------
583 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
584 /// __memory__  | Must point to a previously allocated memory block
585 /// __size__    | Must contain the total size of __memory__
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_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
591 /*/// #### nk_init
592 /// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
593 /// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
594 /// interface to nuklear. Can be useful for cases like monitoring memory consumption.
595 ///
596 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
597 /// int nk_init(struct nk_context *ctx, struct nk_allocator *alloc, 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 /// __alloc__   | Must point to a previously allocated memory allocator
604 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
605 ///
606 /// Returns either `false(0)` on failure or `true(1)` on success.
607 */
608 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
609 /*/// #### nk_init_custom
610 /// Initializes a `nk_context` struct from two different either fixed or growing
611 /// buffers. The first buffer is for allocating draw commands while the second buffer is
612 /// used for allocating windows, panels and state tables.
613 ///
614 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
615 /// int nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font);
616 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
617 ///
618 /// Parameter   | Description
619 /// ------------|---------------------------------------------------------------
620 /// __ctx__     | Must point to an either stack or heap allocated `nk_context` struct
621 /// __cmds__    | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
622 /// __pool__    | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
623 /// __font__    | Must point to a previously initialized font handle for more info look at font documentation
624 ///
625 /// Returns either `false(0)` on failure or `true(1)` on success.
626 */
627 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
628 /*/// #### nk_clear
629 /// Resets the context state at the end of the frame. This includes mostly
630 /// garbage collector tasks like removing windows or table not called and therefore
631 /// used anymore.
632 ///
633 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
634 /// void nk_clear(struct nk_context *ctx);
635 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
636 ///
637 /// Parameter   | Description
638 /// ------------|-----------------------------------------------------------
639 /// __ctx__     | Must point to a previously initialized `nk_context` struct
640 */
641 NK_API void nk_clear(struct nk_context*);
642 /*/// #### nk_free
643 /// Frees all memory allocated by nuklear. Not needed if context was
644 /// initialized with `nk_init_fixed`.
645 ///
646 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
647 /// void nk_free(struct nk_context *ctx);
648 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
649 ///
650 /// Parameter   | Description
651 /// ------------|-----------------------------------------------------------
652 /// __ctx__     | Must point to a previously initialized `nk_context` struct
653 */
654 NK_API void nk_free(struct nk_context*);
655 #ifdef NK_INCLUDE_COMMAND_USERDATA
656 /*/// #### nk_set_user_data
657 /// Sets the currently passed userdata passed down into each draw command.
658 ///
659 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
660 /// void nk_set_user_data(struct nk_context *ctx, nk_handle data);
661 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
662 ///
663 /// Parameter   | Description
664 /// ------------|--------------------------------------------------------------
665 /// __ctx__     | Must point to a previously initialized `nk_context` struct
666 /// __data__    | Handle with either pointer or index to be passed into every draw commands
667 */
668 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
669 #endif
670 /* =============================================================================
671  *
672  *                                  INPUT
673  *
674  * =============================================================================*/
675 /*/// ### Input
676 /// The input API is responsible for holding the current input state composed of
677 /// mouse, key and text input states.
678 /// It is worth noting that no direct OS or window handling is done in nuklear.
679 /// Instead all input state has to be provided by platform specific code. This on one hand
680 /// expects more work from the user and complicates usage but on the other hand
681 /// provides simple abstraction over a big number of platforms, libraries and other
682 /// already provided functionality.
683 ///
684 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
685 /// nk_input_begin(&ctx);
686 /// while (GetEvent(&evt)) {
687 ///     if (evt.type == MOUSE_MOVE)
688 ///         nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
689 ///     else if (evt.type == [...]) {
690 ///         // [...]
691 ///     }
692 /// } nk_input_end(&ctx);
693 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
694 ///
695 /// #### Usage
696 /// Input state needs to be provided to nuklear by first calling `nk_input_begin`
697 /// which resets internal state like delta mouse position and button transistions.
698 /// After `nk_input_begin` all current input state needs to be provided. This includes
699 /// mouse motion, button and key pressed and released, text input and scrolling.
700 /// Both event- or state-based input handling are supported by this API
701 /// and should work without problems. Finally after all input state has been
702 /// mirrored `nk_input_end` needs to be called to finish input process.
703 ///
704 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
705 /// struct nk_context ctx;
706 /// nk_init_xxx(&ctx, ...);
707 /// while (1) {
708 ///     Event evt;
709 ///     nk_input_begin(&ctx);
710 ///     while (GetEvent(&evt)) {
711 ///         if (evt.type == MOUSE_MOVE)
712 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
713 ///         else if (evt.type == [...]) {
714 ///             // [...]
715 ///         }
716 ///     }
717 ///     nk_input_end(&ctx);
718 ///     // [...]
719 ///     nk_clear(&ctx);
720 /// } nk_free(&ctx);
721 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
722 ///
723 /// #### Reference
724 /// Function            | Description
725 /// --------------------|-------------------------------------------------------
726 /// __nk_input_begin__  | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
727 /// __nk_input_motion__ | Mirrors mouse cursor position
728 /// __nk_input_key__    | Mirrors key state with either pressed or released
729 /// __nk_input_button__ | Mirrors mouse button state with either pressed or released
730 /// __nk_input_scroll__ | Mirrors mouse scroll values
731 /// __nk_input_char__   | Adds a single ASCII text character into an internal text buffer
732 /// __nk_input_glyph__  | Adds a single multi-byte UTF-8 character into an internal text buffer
733 /// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer
734 /// __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
735 */
736 enum nk_keys {
737     NK_KEY_NONE,
738     NK_KEY_SHIFT,
739     NK_KEY_CTRL,
740     NK_KEY_DEL,
741     NK_KEY_ENTER,
742     NK_KEY_TAB,
743     NK_KEY_BACKSPACE,
744     NK_KEY_COPY,
745     NK_KEY_CUT,
746     NK_KEY_PASTE,
747     NK_KEY_UP,
748     NK_KEY_DOWN,
749     NK_KEY_LEFT,
750     NK_KEY_RIGHT,
751     /* Shortcuts: text field */
752     NK_KEY_TEXT_INSERT_MODE,
753     NK_KEY_TEXT_REPLACE_MODE,
754     NK_KEY_TEXT_RESET_MODE,
755     NK_KEY_TEXT_LINE_START,
756     NK_KEY_TEXT_LINE_END,
757     NK_KEY_TEXT_START,
758     NK_KEY_TEXT_END,
759     NK_KEY_TEXT_UNDO,
760     NK_KEY_TEXT_REDO,
761     NK_KEY_TEXT_SELECT_ALL,
762     NK_KEY_TEXT_WORD_LEFT,
763     NK_KEY_TEXT_WORD_RIGHT,
764     /* Shortcuts: scrollbar */
765     NK_KEY_SCROLL_START,
766     NK_KEY_SCROLL_END,
767     NK_KEY_SCROLL_DOWN,
768     NK_KEY_SCROLL_UP,
769     NK_KEY_MAX
770 };
771 enum nk_buttons {
772     NK_BUTTON_LEFT,
773     NK_BUTTON_MIDDLE,
774     NK_BUTTON_RIGHT,
775     NK_BUTTON_DOUBLE,
776     NK_BUTTON_MAX
777 };
778 /*/// #### nk_input_begin
779 /// Begins the input mirroring process by resetting text, scroll
780 /// mouse, previous mouse position and movement as well as key state transitions,
781 ///
782 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
783 /// void nk_input_begin(struct nk_context*);
784 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
785 ///
786 /// Parameter   | Description
787 /// ------------|-----------------------------------------------------------
788 /// __ctx__     | Must point to a previously initialized `nk_context` struct
789 */
790 NK_API void nk_input_begin(struct nk_context*);
791 /*/// #### nk_input_motion
792 /// Mirrors current mouse position to nuklear
793 ///
794 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
795 /// void nk_input_motion(struct nk_context *ctx, int x, int y);
796 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
797 ///
798 /// Parameter   | Description
799 /// ------------|-----------------------------------------------------------
800 /// __ctx__     | Must point to a previously initialized `nk_context` struct
801 /// __x__       | Must hold an integer describing the current mouse cursor x-position
802 /// __y__       | Must hold an integer describing the current mouse cursor y-position
803 */
804 NK_API void nk_input_motion(struct nk_context*, int x, int y);
805 /*/// #### nk_input_key
806 /// Mirrors the state of a specific key to nuklear
807 ///
808 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
809 /// void nk_input_key(struct nk_context*, enum nk_keys key, int down);
810 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
811 ///
812 /// Parameter   | Description
813 /// ------------|-----------------------------------------------------------
814 /// __ctx__     | Must point to a previously initialized `nk_context` struct
815 /// __key__     | Must be any value specified in enum `nk_keys` that needs to be mirrored
816 /// __down__    | Must be 0 for key is up and 1 for key is down
817 */
818 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
819 /*/// #### nk_input_button
820 /// Mirrors the state of a specific mouse button to nuklear
821 ///
822 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
823 /// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, int down);
824 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
825 ///
826 /// Parameter   | Description
827 /// ------------|-----------------------------------------------------------
828 /// __ctx__     | Must point to a previously initialized `nk_context` struct
829 /// __btn__     | Must be any value specified in enum `nk_buttons` that needs to be mirrored
830 /// __x__       | Must contain an integer describing mouse cursor x-position on click up/down
831 /// __y__       | Must contain an integer describing mouse cursor y-position on click up/down
832 /// __down__    | Must be 0 for key is up and 1 for key is down
833 */
834 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
835 /*/// #### nk_input_scroll
836 /// Copies the last mouse scroll value to nuklear. Is generally
837 /// a scroll value. So does not have to come from mouse and could also originate
838 /// TODO finish this sentence
839 ///
840 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
841 /// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val);
842 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
843 ///
844 /// Parameter   | Description
845 /// ------------|-----------------------------------------------------------
846 /// __ctx__     | Must point to a previously initialized `nk_context` struct
847 /// __val__     | vector with both X- as well as Y-scroll value
848 */
849 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
850 /*/// #### nk_input_char
851 /// Copies a single ASCII character into an internal text buffer
852 /// This is basically a helper function to quickly push ASCII characters into
853 /// nuklear.
854 ///
855 /// !!! Note
856 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
857 ///
858 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
859 /// void nk_input_char(struct nk_context *ctx, char c);
860 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
861 ///
862 /// Parameter   | Description
863 /// ------------|-----------------------------------------------------------
864 /// __ctx__     | Must point to a previously initialized `nk_context` struct
865 /// __c__       | Must be a single ASCII character preferable one that can be printed
866 */
867 NK_API void nk_input_char(struct nk_context*, char);
868 /*/// #### nk_input_glyph
869 /// Converts an encoded unicode rune into UTF-8 and copies the result into an
870 /// internal text buffer.
871 ///
872 /// !!! Note
873 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
874 ///
875 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
876 /// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g);
877 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
878 ///
879 /// Parameter   | Description
880 /// ------------|-----------------------------------------------------------
881 /// __ctx__     | Must point to a previously initialized `nk_context` struct
882 /// __g__       | UTF-32 unicode codepoint
883 */
884 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
885 /*/// #### nk_input_unicode
886 /// Converts a unicode rune into UTF-8 and copies the result
887 /// into an internal text buffer.
888 /// !!! Note
889 ///     Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
890 ///
891 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
892 /// void nk_input_unicode(struct nk_context*, nk_rune rune);
893 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
894 ///
895 /// Parameter   | Description
896 /// ------------|-----------------------------------------------------------
897 /// __ctx__     | Must point to a previously initialized `nk_context` struct
898 /// __rune__    | UTF-32 unicode codepoint
899 */
900 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
901 /*/// #### nk_input_end
902 /// End the input mirroring process by resetting mouse grabbing
903 /// state to ensure the mouse cursor is not grabbed indefinitely.
904 ///
905 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
906 /// void nk_input_end(struct nk_context *ctx);
907 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
908 ///
909 /// Parameter   | Description
910 /// ------------|-----------------------------------------------------------
911 /// __ctx__     | Must point to a previously initialized `nk_context` struct
912 */
913 NK_API void nk_input_end(struct nk_context*);
914 /* =============================================================================
915  *
916  *                                  DRAWING
917  *
918  * =============================================================================*/
919 /*/// ### Drawing
920 /// This library was designed to be render backend agnostic so it does
921 /// not draw anything to screen directly. Instead all drawn shapes, widgets
922 /// are made of, are buffered into memory and make up a command queue.
923 /// Each frame therefore fills the command buffer with draw commands
924 /// that then need to be executed by the user and his own render backend.
925 /// After that the command buffer needs to be cleared and a new frame can be
926 /// started. It is probably important to note that the command buffer is the main
927 /// drawing API and the optional vertex buffer API only takes this format and
928 /// converts it into a hardware accessible format.
929 ///
930 /// #### Usage
931 /// To draw all draw commands accumulated over a frame you need your own render
932 /// backend able to draw a number of 2D primitives. This includes at least
933 /// filled and stroked rectangles, circles, text, lines, triangles and scissors.
934 /// As soon as this criterion is met you can iterate over each draw command
935 /// and execute each draw command in a interpreter like fashion:
936 ///
937 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
938 /// const struct nk_command *cmd = 0;
939 /// nk_foreach(cmd, &ctx) {
940 ///     switch (cmd->type) {
941 ///     case NK_COMMAND_LINE:
942 ///         your_draw_line_function(...)
943 ///         break;
944 ///     case NK_COMMAND_RECT
945 ///         your_draw_rect_function(...)
946 ///         break;
947 ///     case //...:
948 ///         //[...]
949 ///     }
950 /// }
951 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
952 ///
953 /// In program flow context draw commands need to be executed after input has been
954 /// gathered and the complete UI with windows and their contained widgets have
955 /// been executed and before calling `nk_clear` which frees all previously
956 /// allocated draw commands.
957 ///
958 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
959 /// struct nk_context ctx;
960 /// nk_init_xxx(&ctx, ...);
961 /// while (1) {
962 ///     Event evt;
963 ///     nk_input_begin(&ctx);
964 ///     while (GetEvent(&evt)) {
965 ///         if (evt.type == MOUSE_MOVE)
966 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
967 ///         else if (evt.type == [...]) {
968 ///             [...]
969 ///         }
970 ///     }
971 ///     nk_input_end(&ctx);
972 ///     //
973 ///     // [...]
974 ///     //
975 ///     const struct nk_command *cmd = 0;
976 ///     nk_foreach(cmd, &ctx) {
977 ///     switch (cmd->type) {
978 ///     case NK_COMMAND_LINE:
979 ///         your_draw_line_function(...)
980 ///         break;
981 ///     case NK_COMMAND_RECT
982 ///         your_draw_rect_function(...)
983 ///         break;
984 ///     case ...:
985 ///         // [...]
986 ///     }
987 ///     nk_clear(&ctx);
988 /// }
989 /// nk_free(&ctx);
990 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
991 ///
992 /// You probably noticed that you have to draw all of the UI each frame which is
993 /// quite wasteful. While the actual UI updating loop is quite fast rendering
994 /// without actually needing it is not. So there are multiple things you could do.
995 ///
996 /// First is only update on input. This of course is only an option if your
997 /// application only depends on the UI and does not require any outside calculations.
998 /// If you actually only update on input make sure to update the UI two times each
999 /// frame and call `nk_clear` directly after the first pass and only draw in
1000 /// the second pass. In addition it is recommended to also add additional timers
1001 /// to make sure the UI is not drawn more than a fixed number of frames per second.
1002 ///
1003 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1004 /// struct nk_context ctx;
1005 /// nk_init_xxx(&ctx, ...);
1006 /// while (1) {
1007 ///     // [...wait for input ]
1008 ///     // [...do two UI passes ...]
1009 ///     do_ui(...)
1010 ///     nk_clear(&ctx);
1011 ///     do_ui(...)
1012 ///     //
1013 ///     // draw
1014 ///     const struct nk_command *cmd = 0;
1015 ///     nk_foreach(cmd, &ctx) {
1016 ///     switch (cmd->type) {
1017 ///     case NK_COMMAND_LINE:
1018 ///         your_draw_line_function(...)
1019 ///         break;
1020 ///     case NK_COMMAND_RECT
1021 ///         your_draw_rect_function(...)
1022 ///         break;
1023 ///     case ...:
1024 ///         //[...]
1025 ///     }
1026 ///     nk_clear(&ctx);
1027 /// }
1028 /// nk_free(&ctx);
1029 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1030 ///
1031 /// The second probably more applicable trick is to only draw if anything changed.
1032 /// It is not really useful for applications with continuous draw loop but
1033 /// quite useful for desktop applications. To actually get nuklear to only
1034 /// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
1035 /// allocate a memory buffer that will store each unique drawing output.
1036 /// After each frame you compare the draw command memory inside the library
1037 /// with your allocated buffer by memcmp. If memcmp detects differences
1038 /// you have to copy the command buffer into the allocated buffer
1039 /// and then draw like usual (this example uses fixed memory but you could
1040 /// use dynamically allocated memory).
1041 ///
1042 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1043 /// //[... other defines ...]
1044 /// #define NK_ZERO_COMMAND_MEMORY
1045 /// #include "nuklear.h"
1046 /// //
1047 /// // setup context
1048 /// struct nk_context ctx;
1049 /// void *last = calloc(1,64*1024);
1050 /// void *buf = calloc(1,64*1024);
1051 /// nk_init_fixed(&ctx, buf, 64*1024);
1052 /// //
1053 /// // loop
1054 /// while (1) {
1055 ///     // [...input...]
1056 ///     // [...ui...]
1057 ///     void *cmds = nk_buffer_memory(&ctx.memory);
1058 ///     if (memcmp(cmds, last, ctx.memory.allocated)) {
1059 ///         memcpy(last,cmds,ctx.memory.allocated);
1060 ///         const struct nk_command *cmd = 0;
1061 ///         nk_foreach(cmd, &ctx) {
1062 ///             switch (cmd->type) {
1063 ///             case NK_COMMAND_LINE:
1064 ///                 your_draw_line_function(...)
1065 ///                 break;
1066 ///             case NK_COMMAND_RECT
1067 ///                 your_draw_rect_function(...)
1068 ///                 break;
1069 ///             case ...:
1070 ///                 // [...]
1071 ///             }
1072 ///         }
1073 ///     }
1074 ///     nk_clear(&ctx);
1075 /// }
1076 /// nk_free(&ctx);
1077 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1078 ///
1079 /// Finally while using draw commands makes sense for higher abstracted platforms like
1080 /// X11 and Win32 or drawing libraries it is often desirable to use graphics
1081 /// hardware directly. Therefore it is possible to just define
1082 /// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
1083 /// To access the vertex output you first have to convert all draw commands into
1084 /// vertexes by calling `nk_convert` which takes in your preferred vertex format.
1085 /// After successfully converting all draw commands just iterate over and execute all
1086 /// vertex draw commands:
1087 ///
1088 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1089 /// // fill configuration
1090 /// struct your_vertex
1091 /// {
1092 ///     float pos[2]; // important to keep it to 2 floats
1093 ///     float uv[2];
1094 ///     unsigned char col[4];
1095 /// };
1096 /// struct nk_convert_config cfg = {};
1097 /// static const struct nk_draw_vertex_layout_element vertex_layout[] = {
1098 ///     {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
1099 ///     {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
1100 ///     {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
1101 ///     {NK_VERTEX_LAYOUT_END}
1102 /// };
1103 /// cfg.shape_AA = NK_ANTI_ALIASING_ON;
1104 /// cfg.line_AA = NK_ANTI_ALIASING_ON;
1105 /// cfg.vertex_layout = vertex_layout;
1106 /// cfg.vertex_size = sizeof(struct your_vertex);
1107 /// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
1108 /// cfg.circle_segment_count = 22;
1109 /// cfg.curve_segment_count = 22;
1110 /// cfg.arc_segment_count = 22;
1111 /// cfg.global_alpha = 1.0f;
1112 /// cfg.null = dev->null;
1113 /// //
1114 /// // setup buffers and convert
1115 /// struct nk_buffer cmds, verts, idx;
1116 /// nk_buffer_init_default(&cmds);
1117 /// nk_buffer_init_default(&verts);
1118 /// nk_buffer_init_default(&idx);
1119 /// nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
1120 /// //
1121 /// // draw
1122 /// nk_draw_foreach(cmd, &ctx, &cmds) {
1123 /// if (!cmd->elem_count) continue;
1124 ///     //[...]
1125 /// }
1126 /// nk_buffer_free(&cms);
1127 /// nk_buffer_free(&verts);
1128 /// nk_buffer_free(&idx);
1129 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1130 ///
1131 /// #### Reference
1132 /// Function            | Description
1133 /// --------------------|-------------------------------------------------------
1134 /// __nk__begin__       | Returns the first draw command in the context draw command list to be drawn
1135 /// __nk__next__        | Increments the draw command iterator to the next command inside the context draw command list
1136 /// __nk_foreach__      | Iterates over each draw command inside the context draw command list
1137 /// __nk_convert__      | Converts from the abstract draw commands list into a hardware accessible vertex format
1138 /// __nk_draw_begin__   | Returns the first vertex command in the context vertex draw list to be executed
1139 /// __nk__draw_next__   | Increments the vertex command iterator to the next command inside the context vertex command list
1140 /// __nk__draw_end__    | Returns the end of the vertex draw list
1141 /// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list
1142 */
1143 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON};
1144 enum nk_convert_result {
1145     NK_CONVERT_SUCCESS = 0,
1146     NK_CONVERT_INVALID_PARAM = 1,
1147     NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1),
1148     NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2),
1149     NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3)
1150 };
1151 struct nk_draw_null_texture {
1152     nk_handle texture; /* texture handle to a texture with a white pixel */
1153     struct nk_vec2 uv; /* coordinates to a white pixel in the texture  */
1154 };
1155 struct nk_convert_config {
1156     float global_alpha; /* global alpha value */
1157     enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
1158     enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
1159     unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
1160     unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
1161     unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
1162     struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
1163     const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
1164     nk_size vertex_size; /* sizeof one vertex for vertex packing */
1165     nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
1166 };
1167 /*/// #### nk__begin
1168 /// Returns a draw command list iterator to iterate all draw
1169 /// commands accumulated over one frame.
1170 ///
1171 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1172 /// const struct nk_command* nk__begin(struct nk_context*);
1173 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1174 ///
1175 /// Parameter   | Description
1176 /// ------------|-----------------------------------------------------------
1177 /// __ctx__     | must point to an previously initialized `nk_context` struct at the end of a frame
1178 ///
1179 /// Returns draw command pointer pointing to the first command inside the draw command list
1180 */
1181 NK_API const struct nk_command* nk__begin(struct nk_context*);
1182 /*/// #### nk__next
1183 /// Returns draw command pointer pointing to the next command inside the draw command list
1184 ///
1185 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1186 /// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1187 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1188 ///
1189 /// Parameter   | Description
1190 /// ------------|-----------------------------------------------------------
1191 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1192 /// __cmd__     | Must point to an previously a draw command either returned by `nk__begin` or `nk__next`
1193 ///
1194 /// Returns draw command pointer pointing to the next command inside the draw command list
1195 */
1196 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1197 /*/// #### nk_foreach
1198 /// Iterates over each draw command inside the context draw command list
1199 ///
1200 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1201 /// #define nk_foreach(c, ctx)
1202 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1203 ///
1204 /// Parameter   | Description
1205 /// ------------|-----------------------------------------------------------
1206 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1207 /// __cmd__     | Command pointer initialized to NULL
1208 ///
1209 /// Iterates over each draw command inside the context draw command list
1210 */
1211 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1212 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1213 /*/// #### nk_convert
1214 /// Converts all internal draw commands into vertex draw commands and fills
1215 /// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format
1216 /// as well as some other configuration values have to be configured by filling out a
1217 /// `nk_convert_config` struct.
1218 ///
1219 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1220 /// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
1221 ///     struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1222 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1223 ///
1224 /// Parameter   | Description
1225 /// ------------|-----------------------------------------------------------
1226 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1227 /// __cmds__    | Must point to a previously initialized buffer to hold converted vertex draw commands
1228 /// __vertices__| Must point to a previously initialized buffer to hold all produced vertices
1229 /// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices
1230 /// __config__  | Must point to a filled out `nk_config` struct to configure the conversion process
1231 ///
1232 /// Returns one of enum nk_convert_result error codes
1233 ///
1234 /// Parameter                       | Description
1235 /// --------------------------------|-----------------------------------------------------------
1236 /// NK_CONVERT_SUCCESS              | Signals a successful draw command to vertex buffer conversion
1237 /// NK_CONVERT_INVALID_PARAM        | An invalid argument was passed in the function call
1238 /// NK_CONVERT_COMMAND_BUFFER_FULL  | The provided buffer for storing draw commands is full or failed to allocate more memory
1239 /// NK_CONVERT_VERTEX_BUFFER_FULL   | The provided buffer for storing vertices is full or failed to allocate more memory
1240 /// NK_CONVERT_ELEMENT_BUFFER_FULL  | The provided buffer for storing indicies is full or failed to allocate more memory
1241 */
1242 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*);
1243 /*/// #### nk__draw_begin
1244 /// Returns a draw vertex command buffer iterator to iterate over the vertex draw command buffer
1245 ///
1246 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1247 /// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1248 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1249 ///
1250 /// Parameter   | Description
1251 /// ------------|-----------------------------------------------------------
1252 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1253 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
1254 ///
1255 /// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer
1256 */
1257 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1258 /*/// #### nk__draw_end
1259 /// Returns the vertex draw command at the end of the vertex draw command buffer
1260 ///
1261 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1262 /// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf);
1263 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1264 ///
1265 /// Parameter   | Description
1266 /// ------------|-----------------------------------------------------------
1267 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1268 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
1269 ///
1270 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
1271 */
1272 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1273 /*/// #### nk__draw_next
1274 /// Increments the vertex draw command buffer iterator
1275 ///
1276 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1277 /// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1278 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1279 ///
1280 /// Parameter   | Description
1281 /// ------------|-----------------------------------------------------------
1282 /// __cmd__     | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
1283 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
1284 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1285 ///
1286 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
1287 */
1288 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1289 /*/// #### nk_draw_foreach
1290 /// Iterates over each vertex draw command inside a vertex draw command buffer
1291 ///
1292 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1293 /// #define nk_draw_foreach(cmd,ctx, b)
1294 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1295 ///
1296 /// Parameter   | Description
1297 /// ------------|-----------------------------------------------------------
1298 /// __cmd__     | `nk_draw_command`iterator set to NULL
1299 /// __buf__     | Must point to an previously by `nk_convert` filled out vertex draw command buffer
1300 /// __ctx__     | Must point to an previously initialized `nk_context` struct at the end of a frame
1301 */
1302 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1303 #endif
1304 /* =============================================================================
1305  *
1306  *                                  WINDOW
1307  *
1308  * =============================================================================
1309 /// ### Window
1310 /// Windows are the main persistent state used inside nuklear and are life time
1311 /// controlled by simply "retouching" (i.e. calling) each window each frame.
1312 /// All widgets inside nuklear can only be added inside the function pair `nk_begin_xxx`
1313 /// and `nk_end`. Calling any widgets outside these two functions will result in an
1314 /// assert in debug or no state change in release mode.<br /><br />
1315 ///
1316 /// Each window holds frame persistent state like position, size, flags, state tables,
1317 /// and some garbage collected internal persistent widget state. Each window
1318 /// is linked into a window stack list which determines the drawing and overlapping
1319 /// order. The topmost window thereby is the currently active window.<br /><br />
1320 ///
1321 /// To change window position inside the stack occurs either automatically by
1322 /// user input by being clicked on or programmatically by calling `nk_window_focus`.
1323 /// Windows by default are visible unless explicitly being defined with flag
1324 /// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
1325 /// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
1326 /// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.<br /><br />
1327 ///
1328 /// #### Usage
1329 /// To create and keep a window you have to call one of the two `nk_begin_xxx`
1330 /// functions to start window declarations and `nk_end` at the end. Furthermore it
1331 /// is recommended to check the return value of `nk_begin_xxx` and only process
1332 /// widgets inside the window if the value is not 0. Either way you have to call
1333 /// `nk_end` at the end of window declarations. Furthermore, do not attempt to
1334 /// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
1335 /// in a segmentation fault.
1336 ///
1337 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1338 /// if (nk_begin_xxx(...) {
1339 ///     // [... widgets ...]
1340 /// }
1341 /// nk_end(ctx);
1342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1343 ///
1344 /// In the grand concept window and widget declarations need to occur after input
1345 /// handling and before drawing to screen. Not doing so can result in higher
1346 /// latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
1347 /// is called at the end of the frame. While nuklear's default platform backends
1348 /// already call `nk_clear` for you if you write your own backend not calling
1349 /// `nk_clear` can cause asserts or even worse undefined behavior.
1350 ///
1351 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1352 /// struct nk_context ctx;
1353 /// nk_init_xxx(&ctx, ...);
1354 /// while (1) {
1355 ///     Event evt;
1356 ///     nk_input_begin(&ctx);
1357 ///     while (GetEvent(&evt)) {
1358 ///         if (evt.type == MOUSE_MOVE)
1359 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
1360 ///         else if (evt.type == [...]) {
1361 ///             nk_input_xxx(...);
1362 ///         }
1363 ///     }
1364 ///     nk_input_end(&ctx);
1365 ///
1366 ///     if (nk_begin_xxx(...) {
1367 ///         //[...]
1368 ///     }
1369 ///     nk_end(ctx);
1370 ///
1371 ///     const struct nk_command *cmd = 0;
1372 ///     nk_foreach(cmd, &ctx) {
1373 ///     case NK_COMMAND_LINE:
1374 ///         your_draw_line_function(...)
1375 ///         break;
1376 ///     case NK_COMMAND_RECT
1377 ///         your_draw_rect_function(...)
1378 ///         break;
1379 ///     case //...:
1380 ///         //[...]
1381 ///     }
1382 ///     nk_clear(&ctx);
1383 /// }
1384 /// nk_free(&ctx);
1385 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1386 ///
1387 /// #### Reference
1388 /// Function                            | Description
1389 /// ------------------------------------|----------------------------------------
1390 /// nk_begin                            | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1391 /// nk_begin_titled                     | Extended window start with separated title and identifier to allow multiple windows with same name but not title
1392 /// nk_end                              | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
1393 //
1394 /// nk_window_find                      | Finds and returns the window with give name
1395 /// nk_window_get_bounds                | Returns a rectangle with screen position and size of the currently processed window.
1396 /// nk_window_get_position              | Returns the position of the currently processed window
1397 /// nk_window_get_size                  | Returns the size with width and height of the currently processed window
1398 /// nk_window_get_width                 | Returns the width of the currently processed window
1399 /// nk_window_get_height                | Returns the height of the currently processed window
1400 /// nk_window_get_panel                 | Returns the underlying panel which contains all processing state of the current window
1401 /// nk_window_get_content_region        | Returns the position and size of the currently visible and non-clipped space inside the currently processed window
1402 /// nk_window_get_content_region_min    | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1403 /// nk_window_get_content_region_max    | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1404 /// nk_window_get_content_region_size   | Returns the size of the currently visible and non-clipped space inside the currently processed window
1405 /// nk_window_get_canvas                | Returns the draw command buffer. Can be used to draw custom widgets
1406 /// nk_window_get_scroll                | Gets the scroll offset of the current window
1407 /// nk_window_has_focus                 | Returns if the currently processed window is currently active
1408 /// nk_window_is_collapsed              | Returns if the window with given name is currently minimized/collapsed
1409 /// nk_window_is_closed                 | Returns if the currently processed window was closed
1410 /// nk_window_is_hidden                 | Returns if the currently processed window was hidden
1411 /// nk_window_is_active                 | Same as nk_window_has_focus for some reason
1412 /// nk_window_is_hovered                | Returns if the currently processed window is currently being hovered by mouse
1413 /// nk_window_is_any_hovered            | Return if any window currently hovered
1414 /// nk_item_is_any_active               | Returns if any window or widgets is currently hovered or active
1415 //
1416 /// nk_window_set_bounds                | Updates position and size of the currently processed window
1417 /// nk_window_set_position              | Updates position of the currently process window
1418 /// nk_window_set_size                  | Updates the size of the currently processed window
1419 /// nk_window_set_focus                 | Set the currently processed window as active window
1420 /// nk_window_set_scroll                | Sets the scroll offset of the current window
1421 //
1422 /// nk_window_close                     | Closes the window with given window name which deletes the window at the end of the frame
1423 /// nk_window_collapse                  | Collapses the window with given window name
1424 /// nk_window_collapse_if               | Collapses the window with given window name if the given condition was met
1425 /// nk_window_show                      | Hides a visible or reshows a hidden window
1426 /// nk_window_show_if                   | Hides/shows a window depending on condition
1427 */
1428 /*
1429 /// #### nk_panel_flags
1430 /// Flag                        | Description
1431 /// ----------------------------|----------------------------------------
1432 /// NK_WINDOW_BORDER            | Draws a border around the window to visually separate window from the background
1433 /// NK_WINDOW_MOVABLE           | The movable flag indicates that a window can be moved by user input or by dragging the window header
1434 /// 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
1435 /// NK_WINDOW_CLOSABLE          | Adds a closable icon into the header
1436 /// NK_WINDOW_MINIMIZABLE       | Adds a minimize icon into the header
1437 /// NK_WINDOW_NO_SCROLLBAR      | Removes the scrollbar from the window
1438 /// NK_WINDOW_TITLE             | Forces a header at the top at the window showing the title
1439 /// 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
1440 /// NK_WINDOW_BACKGROUND        | Always keep window in the background
1441 /// NK_WINDOW_SCALE_LEFT        | Puts window scaler in the left-bottom corner instead right-bottom
1442 /// NK_WINDOW_NO_INPUT          | Prevents window of scaling, moving or getting focus
1443 ///
1444 /// #### nk_collapse_states
1445 /// State           | Description
1446 /// ----------------|-----------------------------------------------------------
1447 /// __NK_MINIMIZED__| UI section is collased and not visibile until maximized
1448 /// __NK_MAXIMIZED__| UI section is extended and visibile until minimized
1449 /// <br /><br />
1450 */
1451 enum nk_panel_flags {
1452     NK_WINDOW_BORDER            = NK_FLAG(0),
1453     NK_WINDOW_MOVABLE           = NK_FLAG(1),
1454     NK_WINDOW_SCALABLE          = NK_FLAG(2),
1455     NK_WINDOW_CLOSABLE          = NK_FLAG(3),
1456     NK_WINDOW_MINIMIZABLE       = NK_FLAG(4),
1457     NK_WINDOW_NO_SCROLLBAR      = NK_FLAG(5),
1458     NK_WINDOW_TITLE             = NK_FLAG(6),
1459     NK_WINDOW_SCROLL_AUTO_HIDE  = NK_FLAG(7),
1460     NK_WINDOW_BACKGROUND        = NK_FLAG(8),
1461     NK_WINDOW_SCALE_LEFT        = NK_FLAG(9),
1462     NK_WINDOW_NO_INPUT          = NK_FLAG(10)
1463 };
1464 /*/// #### nk_begin
1465 /// Starts a new window; needs to be called every frame for every
1466 /// window (unless hidden) or otherwise the window gets removed
1467 ///
1468 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1469 /// int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1470 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1471 ///
1472 /// Parameter   | Description
1473 /// ------------|-----------------------------------------------------------
1474 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1475 /// __title__   | Window title and identifier. Needs to be persistent over frames to identify the window
1476 /// __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
1477 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different window behaviors
1478 ///
1479 /// Returns `true(1)` if the window can be filled up with widgets from this point
1480 /// until `nk_end` or `false(0)` otherwise for example if minimized
1481 */
1482 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1483 /*/// #### nk_begin_titled
1484 /// Extended window start with separated title and identifier to allow multiple
1485 /// windows with same title but not name
1486 ///
1487 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1488 /// int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1489 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1490 ///
1491 /// Parameter   | Description
1492 /// ------------|-----------------------------------------------------------
1493 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1494 /// __name__    | Window identifier. Needs to be persistent over frames to identify the window
1495 /// __title__   | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
1496 /// __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
1497 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different window behaviors
1498 ///
1499 /// Returns `true(1)` if the window can be filled up with widgets from this point
1500 /// until `nk_end` or `false(0)` otherwise for example if minimized
1501 */
1502 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1503 /*/// #### nk_end
1504 /// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
1505 /// All widget calls after this functions will result in asserts or no state changes
1506 ///
1507 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1508 /// void nk_end(struct nk_context *ctx);
1509 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1510 ///
1511 /// Parameter   | Description
1512 /// ------------|-----------------------------------------------------------
1513 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1514 */
1515 NK_API void nk_end(struct nk_context *ctx);
1516 /*/// #### nk_window_find
1517 /// Finds and returns a window from passed name
1518 ///
1519 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1520 /// struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1521 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1522 ///
1523 /// Parameter   | Description
1524 /// ------------|-----------------------------------------------------------
1525 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1526 /// __name__    | Window identifier
1527 ///
1528 /// Returns a `nk_window` struct pointing to the identified window or NULL if
1529 /// no window with the given name was found
1530 */
1531 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1532 /*/// #### nk_window_get_bounds
1533 /// Returns a rectangle with screen position and size of the currently processed window
1534 ///
1535 /// !!! WARNING
1536 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1537 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1538 /// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
1539 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1540 ///
1541 /// Parameter   | Description
1542 /// ------------|-----------------------------------------------------------
1543 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1544 ///
1545 /// Returns a `nk_rect` struct with window upper left window position and size
1546 */
1547 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
1548 /*/// #### nk_window_get_position
1549 /// Returns the position of the currently processed window.
1550 ///
1551 /// !!! WARNING
1552 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1553 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1554 /// struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
1555 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1556 ///
1557 /// Parameter   | Description
1558 /// ------------|-----------------------------------------------------------
1559 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1560 ///
1561 /// Returns a `nk_vec2` struct with window upper left position
1562 */
1563 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
1564 /*/// #### nk_window_get_size
1565 /// Returns the size with width and height of the currently processed window.
1566 ///
1567 /// !!! WARNING
1568 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1569 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1570 /// struct nk_vec2 nk_window_get_size(const struct nk_context *ctx);
1571 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1572 ///
1573 /// Parameter   | Description
1574 /// ------------|-----------------------------------------------------------
1575 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1576 ///
1577 /// Returns a `nk_vec2` struct with window width and height
1578 */
1579 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*);
1580 /*/// #### nk_window_get_width
1581 /// Returns the width of the currently processed window.
1582 ///
1583 /// !!! WARNING
1584 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1585 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1586 /// float nk_window_get_width(const struct nk_context *ctx);
1587 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1588 ///
1589 /// Parameter   | Description
1590 /// ------------|-----------------------------------------------------------
1591 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1592 ///
1593 /// Returns the current window width
1594 */
1595 NK_API float nk_window_get_width(const struct nk_context*);
1596 /*/// #### nk_window_get_height
1597 /// Returns the height of the currently processed window.
1598 ///
1599 /// !!! WARNING
1600 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1601 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1602 /// float nk_window_get_height(const struct nk_context *ctx);
1603 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1604 ///
1605 /// Parameter   | Description
1606 /// ------------|-----------------------------------------------------------
1607 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1608 ///
1609 /// Returns the current window height
1610 */
1611 NK_API float nk_window_get_height(const struct nk_context*);
1612 /*/// #### nk_window_get_panel
1613 /// Returns the underlying panel which contains all processing state of the current window.
1614 ///
1615 /// !!! WARNING
1616 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1617 /// !!! WARNING
1618 ///     Do not keep the returned panel pointer around, it is only valid until `nk_end`
1619 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1620 /// struct nk_panel* nk_window_get_panel(struct nk_context *ctx);
1621 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1622 ///
1623 /// Parameter   | Description
1624 /// ------------|-----------------------------------------------------------
1625 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1626 ///
1627 /// Returns a pointer to window internal `nk_panel` state.
1628 */
1629 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*);
1630 /*/// #### nk_window_get_content_region
1631 /// Returns the position and size of the currently visible and non-clipped space
1632 /// inside the currently processed window.
1633 ///
1634 /// !!! WARNING
1635 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1636 ///
1637 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1638 /// struct nk_rect nk_window_get_content_region(struct nk_context *ctx);
1639 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1640 ///
1641 /// Parameter   | Description
1642 /// ------------|-----------------------------------------------------------
1643 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1644 ///
1645 /// Returns `nk_rect` struct with screen position and size (no scrollbar offset)
1646 /// of the visible space inside the current window
1647 */
1648 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*);
1649 /*/// #### nk_window_get_content_region_min
1650 /// Returns the upper left position of the currently visible and non-clipped
1651 /// space inside the currently processed window.
1652 ///
1653 /// !!! WARNING
1654 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1655 ///
1656 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1657 /// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx);
1658 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1659 ///
1660 /// Parameter   | Description
1661 /// ------------|-----------------------------------------------------------
1662 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1663 ///
1664 /// returns `nk_vec2` struct with  upper left screen position (no scrollbar offset)
1665 /// of the visible space inside the current window
1666 */
1667 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*);
1668 /*/// #### nk_window_get_content_region_max
1669 /// Returns the lower right screen position of the currently visible and
1670 /// non-clipped space inside the currently processed window.
1671 ///
1672 /// !!! WARNING
1673 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1674 ///
1675 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1676 /// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx);
1677 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1678 ///
1679 /// Parameter   | Description
1680 /// ------------|-----------------------------------------------------------
1681 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1682 ///
1683 /// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset)
1684 /// of the visible space inside the current window
1685 */
1686 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*);
1687 /*/// #### nk_window_get_content_region_size
1688 /// Returns the size of the currently visible and non-clipped space inside the
1689 /// currently processed window
1690 ///
1691 /// !!! WARNING
1692 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1693 ///
1694 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1695 /// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx);
1696 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1697 ///
1698 /// Parameter   | Description
1699 /// ------------|-----------------------------------------------------------
1700 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1701 ///
1702 /// Returns `nk_vec2` struct with size the visible space inside the current window
1703 */
1704 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*);
1705 /*/// #### nk_window_get_canvas
1706 /// Returns the draw command buffer. Can be used to draw custom widgets
1707 /// !!! WARNING
1708 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1709 /// !!! WARNING
1710 ///     Do not keep the returned command buffer pointer around it is only valid until `nk_end`
1711 ///
1712 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1713 /// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx);
1714 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1715 ///
1716 /// Parameter   | Description
1717 /// ------------|-----------------------------------------------------------
1718 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1719 ///
1720 /// Returns a pointer to window internal `nk_command_buffer` struct used as
1721 /// drawing canvas. Can be used to do custom drawing.
1722 */
1723 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*);
1724 /*/// #### nk_window_get_scroll
1725 /// Gets the scroll offset for the current window
1726 /// !!! WARNING
1727 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1728 ///
1729 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1730 /// void nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y);
1731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1732 ///
1733 /// Parameter    | Description
1734 /// -------------|-----------------------------------------------------------
1735 /// __ctx__      | Must point to an previously initialized `nk_context` struct
1736 /// __offset_x__ | A pointer to the x offset output (or NULL to ignore)
1737 /// __offset_y__ | A pointer to the y offset output (or NULL to ignore)
1738 */
1739 NK_API void nk_window_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
1740 /*/// #### nk_window_has_focus
1741 /// Returns if the currently processed window is currently active
1742 /// !!! WARNING
1743 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1744 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1745 /// int nk_window_has_focus(const struct nk_context *ctx);
1746 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1747 ///
1748 /// Parameter   | Description
1749 /// ------------|-----------------------------------------------------------
1750 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1751 ///
1752 /// Returns `false(0)` if current window is not active or `true(1)` if it is
1753 */
1754 NK_API int nk_window_has_focus(const struct nk_context*);
1755 /*/// #### nk_window_is_hovered
1756 /// Return if the current window is being hovered
1757 /// !!! WARNING
1758 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1759 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1760 /// int nk_window_is_hovered(struct nk_context *ctx);
1761 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1762 ///
1763 /// Parameter   | Description
1764 /// ------------|-----------------------------------------------------------
1765 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1766 ///
1767 /// Returns `true(1)` if current window is hovered or `false(0)` otherwise
1768 */
1769 NK_API int nk_window_is_hovered(struct nk_context*);
1770 /*/// #### nk_window_is_collapsed
1771 /// Returns if the window with given name is currently minimized/collapsed
1772 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1773 /// int nk_window_is_collapsed(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 collapsed
1780 ///
1781 /// Returns `true(1)` if current window is minimized and `false(0)` if window not
1782 /// found or is not minimized
1783 */
1784 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1785 /*/// #### nk_window_is_closed
1786 /// Returns if the window with given name was closed by calling `nk_close`
1787 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1788 /// int nk_window_is_closed(struct nk_context *ctx, const char *name);
1789 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1790 ///
1791 /// Parameter   | Description
1792 /// ------------|-----------------------------------------------------------
1793 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1794 /// __name__    | Identifier of window you want to check if it is closed
1795 ///
1796 /// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed
1797 */
1798 NK_API int nk_window_is_closed(struct nk_context*, const char*);
1799 /*/// #### nk_window_is_hidden
1800 /// Returns if the window with given name is hidden
1801 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1802 /// int nk_window_is_hidden(struct nk_context *ctx, const char *name);
1803 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1804 ///
1805 /// Parameter   | Description
1806 /// ------------|-----------------------------------------------------------
1807 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1808 /// __name__    | Identifier of window you want to check if it is hidden
1809 ///
1810 /// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible
1811 */
1812 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1813 /*/// #### nk_window_is_active
1814 /// Same as nk_window_has_focus for some reason
1815 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1816 /// int nk_window_is_active(struct nk_context *ctx, const char *name);
1817 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1818 ///
1819 /// Parameter   | Description
1820 /// ------------|-----------------------------------------------------------
1821 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1822 /// __name__    | Identifier of window you want to check if it is active
1823 ///
1824 /// Returns `true(1)` if current window is active or `false(0)` window not found or not active
1825 */
1826 NK_API int nk_window_is_active(struct nk_context*, const char*);
1827 /*/// #### nk_window_is_any_hovered
1828 /// Returns if the any window is being hovered
1829 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1830 /// int nk_window_is_any_hovered(struct nk_context*);
1831 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1832 ///
1833 /// Parameter   | Description
1834 /// ------------|-----------------------------------------------------------
1835 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1836 ///
1837 /// Returns `true(1)` if any window is hovered or `false(0)` otherwise
1838 */
1839 NK_API int nk_window_is_any_hovered(struct nk_context*);
1840 /*/// #### nk_item_is_any_active
1841 /// Returns if the any window is being hovered or any widget is currently active.
1842 /// Can be used to decide if input should be processed by UI or your specific input handling.
1843 /// Example could be UI and 3D camera to move inside a 3D space.
1844 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1845 /// int nk_item_is_any_active(struct nk_context*);
1846 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1847 ///
1848 /// Parameter   | Description
1849 /// ------------|-----------------------------------------------------------
1850 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1851 ///
1852 /// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise
1853 */
1854 NK_API int nk_item_is_any_active(struct nk_context*);
1855 /*/// #### nk_window_set_bounds
1856 /// Updates position and size of window with passed in name
1857 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1858 /// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
1859 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1860 ///
1861 /// Parameter   | Description
1862 /// ------------|-----------------------------------------------------------
1863 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1864 /// __name__    | Identifier of the window to modify both position and size
1865 /// __bounds__  | Must point to a `nk_rect` struct with the new position and size
1866 */
1867 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
1868 /*/// #### nk_window_set_position
1869 /// Updates position of window with passed name
1870 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1871 /// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
1872 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1873 ///
1874 /// Parameter   | Description
1875 /// ------------|-----------------------------------------------------------
1876 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1877 /// __name__    | Identifier of the window to modify both position
1878 /// __pos__     | Must point to a `nk_vec2` struct with the new position
1879 */
1880 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
1881 /*/// #### nk_window_set_size
1882 /// Updates size of window with passed in name
1883 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1884 /// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
1885 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1886 ///
1887 /// Parameter   | Description
1888 /// ------------|-----------------------------------------------------------
1889 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1890 /// __name__    | Identifier of the window to modify both window size
1891 /// __size__    | Must point to a `nk_vec2` struct with new window size
1892 */
1893 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
1894 /*/// #### nk_window_set_focus
1895 /// Sets the window with given name as active
1896 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1897 /// void nk_window_set_focus(struct nk_context*, const char *name);
1898 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1899 ///
1900 /// Parameter   | Description
1901 /// ------------|-----------------------------------------------------------
1902 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1903 /// __name__    | Identifier of the window to set focus on
1904 */
1905 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1906 /*/// #### nk_window_set_scroll
1907 /// Sets the scroll offset for the current window
1908 /// !!! WARNING
1909 ///     Only call this function between calls `nk_begin_xxx` and `nk_end`
1910 ///
1911 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1912 /// void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y);
1913 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1914 ///
1915 /// Parameter    | Description
1916 /// -------------|-----------------------------------------------------------
1917 /// __ctx__      | Must point to an previously initialized `nk_context` struct
1918 /// __offset_x__ | The x offset to scroll to
1919 /// __offset_y__ | The y offset to scroll to
1920 */
1921 NK_API void nk_window_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
1922 /*/// #### nk_window_close
1923 /// Closes a window and marks it for being freed at the end of the frame
1924 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1925 /// void nk_window_close(struct nk_context *ctx, const char *name);
1926 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1927 ///
1928 /// Parameter   | Description
1929 /// ------------|-----------------------------------------------------------
1930 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1931 /// __name__    | Identifier of the window to close
1932 */
1933 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1934 /*/// #### nk_window_collapse
1935 /// Updates collapse state of a window with given name
1936 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1937 /// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1938 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1939 ///
1940 /// Parameter   | Description
1941 /// ------------|-----------------------------------------------------------
1942 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1943 /// __name__    | Identifier of the window to close
1944 /// __state__   | value out of nk_collapse_states section
1945 */
1946 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1947 /*/// #### nk_window_collapse_if
1948 /// Updates collapse state of a window with given name if given condition is met
1949 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1950 /// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1951 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1952 ///
1953 /// Parameter   | Description
1954 /// ------------|-----------------------------------------------------------
1955 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1956 /// __name__    | Identifier of the window to either collapse or maximize
1957 /// __state__   | value out of nk_collapse_states section the window should be put into
1958 /// __cond__    | condition that has to be met to actually commit the collapse state change
1959 */
1960 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1961 /*/// #### nk_window_show
1962 /// updates visibility state of a window with given name
1963 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1964 /// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1965 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1966 ///
1967 /// Parameter   | Description
1968 /// ------------|-----------------------------------------------------------
1969 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1970 /// __name__    | Identifier of the window to either collapse or maximize
1971 /// __state__   | state with either visible or hidden to modify the window with
1972 */
1973 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1974 /*/// #### nk_window_show_if
1975 /// Updates visibility state of a window with given name if a given condition is met
1976 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
1977 /// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1978 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1979 ///
1980 /// Parameter   | Description
1981 /// ------------|-----------------------------------------------------------
1982 /// __ctx__     | Must point to an previously initialized `nk_context` struct
1983 /// __name__    | Identifier of the window to either hide or show
1984 /// __state__   | state with either visible or hidden to modify the window with
1985 /// __cond__    | condition that has to be met to actually commit the visbility state change
1986 */
1987 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1988 /* =============================================================================
1989  *
1990  *                                  LAYOUT
1991  *
1992  * =============================================================================
1993 /// ### Layouting
1994 /// Layouting in general describes placing widget inside a window with position and size.
1995 /// While in this particular implementation there are five different APIs for layouting
1996 /// each with different trade offs between control and ease of use. <br /><br />
1997 ///
1998 /// All layouting methods in this library are based around the concept of a row.
1999 /// A row has a height the window content grows by and a number of columns and each
2000 /// layouting method specifies how each widget is placed inside the row.
2001 /// After a row has been allocated by calling a layouting functions and then
2002 /// filled with widgets will advance an internal pointer over the allocated row. <br /><br />
2003 ///
2004 /// To actually define a layout you just call the appropriate layouting function
2005 /// and each subsequent widget call will place the widget as specified. Important
2006 /// here is that if you define more widgets then columns defined inside the layout
2007 /// functions it will allocate the next row without you having to make another layouting <br /><br />
2008 /// call.
2009 ///
2010 /// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
2011 /// is that you have to define the row height for each. However the row height
2012 /// often depends on the height of the font. <br /><br />
2013 ///
2014 /// To fix that internally nuklear uses a minimum row height that is set to the
2015 /// height plus padding of currently active font and overwrites the row height
2016 /// value if zero. <br /><br />
2017 ///
2018 /// If you manually want to change the minimum row height then
2019 /// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to
2020 /// reset it back to be derived from font height. <br /><br />
2021 ///
2022 /// Also if you change the font in nuklear it will automatically change the minimum
2023 /// row height for you and. This means if you change the font but still want
2024 /// a minimum row height smaller than the font you have to repush your value. <br /><br />
2025 ///
2026 /// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
2027 /// layouting method in combination with a cassowary constraint solver (there are
2028 /// some versions on github with permissive license model) to take over all control over widget
2029 /// layouting yourself. However for quick and dirty layouting using all the other layouting
2030 /// functions should be fine.
2031 ///
2032 /// #### Usage
2033 /// 1.  __nk_layout_row_dynamic__<br /><br />
2034 ///     The easiest layouting function is `nk_layout_row_dynamic`. It provides each
2035 ///     widgets with same horizontal space inside the row and dynamically grows
2036 ///     if the owning window grows in width. So the number of columns dictates
2037 ///     the size of each widget dynamically by formula:
2038 ///
2039 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2040 ///     widget_width = (window_width - padding - spacing) * (1/colum_count)
2041 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2042 ///
2043 ///     Just like all other layouting APIs if you define more widget than columns this
2044 ///     library will allocate a new row and keep all layouting parameters previously
2045 ///     defined.
2046 ///
2047 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2048 ///     if (nk_begin_xxx(...) {
2049 ///         // first row with height: 30 composed of two widgets
2050 ///         nk_layout_row_dynamic(&ctx, 30, 2);
2051 ///         nk_widget(...);
2052 ///         nk_widget(...);
2053 ///         //
2054 ///         // second row with same parameter as defined above
2055 ///         nk_widget(...);
2056 ///         nk_widget(...);
2057 ///         //
2058 ///         // third row uses 0 for height which will use auto layouting
2059 ///         nk_layout_row_dynamic(&ctx, 0, 2);
2060 ///         nk_widget(...);
2061 ///         nk_widget(...);
2062 ///     }
2063 ///     nk_end(...);
2064 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2065 ///
2066 /// 2.  __nk_layout_row_static__<br /><br />
2067 ///     Another easy layouting function is `nk_layout_row_static`. It provides each
2068 ///     widget with same horizontal pixel width inside the row and does not grow
2069 ///     if the owning window scales smaller or bigger.
2070 ///
2071 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2072 ///     if (nk_begin_xxx(...) {
2073 ///         // first row with height: 30 composed of two widgets with width: 80
2074 ///         nk_layout_row_static(&ctx, 30, 80, 2);
2075 ///         nk_widget(...);
2076 ///         nk_widget(...);
2077 ///         //
2078 ///         // second row with same parameter as defined above
2079 ///         nk_widget(...);
2080 ///         nk_widget(...);
2081 ///         //
2082 ///         // third row uses 0 for height which will use auto layouting
2083 ///         nk_layout_row_static(&ctx, 0, 80, 2);
2084 ///         nk_widget(...);
2085 ///         nk_widget(...);
2086 ///     }
2087 ///     nk_end(...);
2088 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2089 ///
2090 /// 3.  __nk_layout_row_xxx__<br /><br />
2091 ///     A little bit more advanced layouting API are functions `nk_layout_row_begin`,
2092 ///     `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
2093 ///     specify each column pixel or window ratio in a row. It supports either
2094 ///     directly setting per column pixel width or widget window ratio but not
2095 ///     both. Furthermore it is a immediate mode API so each value is directly
2096 ///     pushed before calling a widget. Therefore the layout is not automatically
2097 ///     repeating like the last two layouting functions.
2098 ///
2099 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2100 ///     if (nk_begin_xxx(...) {
2101 ///         // first row with height: 25 composed of two widgets with width 60 and 40
2102 ///         nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
2103 ///         nk_layout_row_push(ctx, 60);
2104 ///         nk_widget(...);
2105 ///         nk_layout_row_push(ctx, 40);
2106 ///         nk_widget(...);
2107 ///         nk_layout_row_end(ctx);
2108 ///         //
2109 ///         // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
2110 ///         nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
2111 ///         nk_layout_row_push(ctx, 0.25f);
2112 ///         nk_widget(...);
2113 ///         nk_layout_row_push(ctx, 0.75f);
2114 ///         nk_widget(...);
2115 ///         nk_layout_row_end(ctx);
2116 ///         //
2117 ///         // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75
2118 ///         nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
2119 ///         nk_layout_row_push(ctx, 0.25f);
2120 ///         nk_widget(...);
2121 ///         nk_layout_row_push(ctx, 0.75f);
2122 ///         nk_widget(...);
2123 ///         nk_layout_row_end(ctx);
2124 ///     }
2125 ///     nk_end(...);
2126 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2127 ///
2128 /// 4.  __nk_layout_row__<br /><br />
2129 ///     The array counterpart to API nk_layout_row_xxx is the single nk_layout_row
2130 ///     functions. Instead of pushing either pixel or window ratio for every widget
2131 ///     it allows to define it by array. The trade of for less control is that
2132 ///     `nk_layout_row` is automatically repeating. Otherwise the behavior is the
2133 ///     same.
2134 ///
2135 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2136 ///     if (nk_begin_xxx(...) {
2137 ///         // two rows with height: 30 composed of two widgets with width 60 and 40
2138 ///         const float size[] = {60,40};
2139 ///         nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
2140 ///         nk_widget(...);
2141 ///         nk_widget(...);
2142 ///         nk_widget(...);
2143 ///         nk_widget(...);
2144 ///         //
2145 ///         // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
2146 ///         const float ratio[] = {0.25, 0.75};
2147 ///         nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
2148 ///         nk_widget(...);
2149 ///         nk_widget(...);
2150 ///         nk_widget(...);
2151 ///         nk_widget(...);
2152 ///         //
2153 ///         // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75
2154 ///         const float ratio[] = {0.25, 0.75};
2155 ///         nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
2156 ///         nk_widget(...);
2157 ///         nk_widget(...);
2158 ///         nk_widget(...);
2159 ///         nk_widget(...);
2160 ///     }
2161 ///     nk_end(...);
2162 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2163 ///
2164 /// 5.  __nk_layout_row_template_xxx__<br /><br />
2165 ///     The most complex and second most flexible API is a simplified flexbox version without
2166 ///     line wrapping and weights for dynamic widgets. It is an immediate mode API but
2167 ///     unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
2168 ///     before calling the templated widgets.
2169 ///     The row template layout has three different per widget size specifier. The first
2170 ///     one is the `nk_layout_row_template_push_static`  with fixed widget pixel width.
2171 ///     They do not grow if the row grows and will always stay the same.
2172 ///     The second size specifier is `nk_layout_row_template_push_variable`
2173 ///     which defines a minimum widget size but it also can grow if more space is available
2174 ///     not taken by other widgets.
2175 ///     Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic`
2176 ///     which are completely flexible and unlike variable widgets can even shrink
2177 ///     to zero if not enough space is provided.
2178 ///
2179 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2180 ///     if (nk_begin_xxx(...) {
2181 ///         // two rows with height: 30 composed of three widgets
2182 ///         nk_layout_row_template_begin(ctx, 30);
2183 ///         nk_layout_row_template_push_dynamic(ctx);
2184 ///         nk_layout_row_template_push_variable(ctx, 80);
2185 ///         nk_layout_row_template_push_static(ctx, 80);
2186 ///         nk_layout_row_template_end(ctx);
2187 ///         //
2188 ///         // first row
2189 ///         nk_widget(...); // dynamic widget can go to zero if not enough space
2190 ///         nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
2191 ///         nk_widget(...); // static widget with fixed 80 pixel width
2192 ///         //
2193 ///         // second row same layout
2194 ///         nk_widget(...);
2195 ///         nk_widget(...);
2196 ///         nk_widget(...);
2197 ///     }
2198 ///     nk_end(...);
2199 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2200 ///
2201 /// 6.  __nk_layout_space_xxx__<br /><br />
2202 ///     Finally the most flexible API directly allows you to place widgets inside the
2203 ///     window. The space layout API is an immediate mode API which does not support
2204 ///     row auto repeat and directly sets position and size of a widget. Position
2205 ///     and size hereby can be either specified as ratio of allocated space or
2206 ///     allocated space local position and pixel size. Since this API is quite
2207 ///     powerful there are a number of utility functions to get the available space
2208 ///     and convert between local allocated space and screen space.
2209 ///
2210 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2211 ///     if (nk_begin_xxx(...) {
2212 ///         // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
2213 ///         nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
2214 ///         nk_layout_space_push(ctx, nk_rect(0,0,150,200));
2215 ///         nk_widget(...);
2216 ///         nk_layout_space_push(ctx, nk_rect(200,200,100,200));
2217 ///         nk_widget(...);
2218 ///         nk_layout_space_end(ctx);
2219 ///         //
2220 ///         // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
2221 ///         nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
2222 ///         nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
2223 ///         nk_widget(...);
2224 ///         nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
2225 ///         nk_widget(...);
2226 ///     }
2227 ///     nk_end(...);
2228 ///     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2229 ///
2230 /// #### Reference
2231 /// Function                                | Description
2232 /// ----------------------------------------|------------------------------------
2233 /// nk_layout_set_min_row_height            | Set the currently used minimum row height to a specified value
2234 /// nk_layout_reset_min_row_height          | Resets the currently used minimum row height to font height
2235 /// nk_layout_widget_bounds                 | Calculates current width a static layout row can fit inside a window
2236 /// nk_layout_ratio_from_pixel              | Utility functions to calculate window ratio from pixel size
2237 //
2238 /// nk_layout_row_dynamic                   | Current layout is divided into n same sized growing columns
2239 /// nk_layout_row_static                    | Current layout is divided into n same fixed sized columns
2240 /// nk_layout_row_begin                     | Starts a new row with given height and number of columns
2241 /// nk_layout_row_push                      | Pushes another column with given size or window ratio
2242 /// nk_layout_row_end                       | Finished previously started row
2243 /// nk_layout_row                           | Specifies row columns in array as either window ratio or size
2244 //
2245 /// nk_layout_row_template_begin            | Begins the row template declaration
2246 /// nk_layout_row_template_push_dynamic     | Adds a dynamic column that dynamically grows and can go to zero if not enough space
2247 /// nk_layout_row_template_push_variable    | Adds a variable column that dynamically grows but does not shrink below specified pixel width
2248 /// nk_layout_row_template_push_static      | Adds a static column that does not grow and will always have the same size
2249 /// nk_layout_row_template_end              | Marks the end of the row template
2250 //
2251 /// nk_layout_space_begin                   | Begins a new layouting space that allows to specify each widgets position and size
2252 /// nk_layout_space_push                    | Pushes position and size of the next widget in own coordinate space either as pixel or ratio
2253 /// nk_layout_space_end                     | Marks the end of the layouting space
2254 //
2255 /// nk_layout_space_bounds                  | Callable after nk_layout_space_begin and returns total space allocated
2256 /// nk_layout_space_to_screen               | Converts vector from nk_layout_space coordinate space into screen space
2257 /// nk_layout_space_to_local                | Converts vector from screen space into nk_layout_space coordinates
2258 /// nk_layout_space_rect_to_screen          | Converts rectangle from nk_layout_space coordinate space into screen space
2259 /// nk_layout_space_rect_to_local           | Converts rectangle from screen space into nk_layout_space coordinates
2260 */
2261 /*/// #### nk_layout_set_min_row_height
2262 /// Sets the currently used minimum row height.
2263 /// !!! WARNING
2264 ///     The passed height needs to include both your preferred row height
2265 ///     as well as padding. No internal padding is added.
2266 ///
2267 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2268 /// void nk_layout_set_min_row_height(struct nk_context*, float height);
2269 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2270 ///
2271 /// Parameter   | Description
2272 /// ------------|-----------------------------------------------------------
2273 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2274 /// __height__  | New minimum row height to be used for auto generating the row height
2275 */
2276 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height);
2277 /*/// #### nk_layout_reset_min_row_height
2278 /// Reset the currently used minimum row height back to `font_height + text_padding + padding`
2279 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2280 /// void nk_layout_reset_min_row_height(struct nk_context*);
2281 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2282 ///
2283 /// Parameter   | Description
2284 /// ------------|-----------------------------------------------------------
2285 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2286 */
2287 NK_API void nk_layout_reset_min_row_height(struct nk_context*);
2288 /*/// #### nk_layout_widget_bounds
2289 /// Returns the width of the next row allocate by one of the layouting functions
2290 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2291 /// struct nk_rect nk_layout_widget_bounds(struct nk_context*);
2292 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2293 ///
2294 /// Parameter   | Description
2295 /// ------------|-----------------------------------------------------------
2296 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2297 ///
2298 /// Return `nk_rect` with both position and size of the next row
2299 */
2300 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*);
2301 /*/// #### nk_layout_ratio_from_pixel
2302 /// Utility functions to calculate window ratio from pixel size
2303 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2304 /// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
2305 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2306 ///
2307 /// Parameter   | Description
2308 /// ------------|-----------------------------------------------------------
2309 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2310 /// __pixel__   | Pixel_width to convert to window ratio
2311 ///
2312 /// Returns `nk_rect` with both position and size of the next row
2313 */
2314 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
2315 /*/// #### nk_layout_row_dynamic
2316 /// Sets current row layout to share horizontal space
2317 /// between @cols number of widgets evenly. Once called all subsequent widget
2318 /// calls greater than @cols will allocate a new row with same layout.
2319 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2320 /// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
2321 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2322 ///
2323 /// Parameter   | Description
2324 /// ------------|-----------------------------------------------------------
2325 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2326 /// __height__  | Holds height of each widget in row or zero for auto layouting
2327 /// __columns__ | Number of widget inside row
2328 */
2329 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
2330 /*/// #### nk_layout_row_static
2331 /// Sets current row layout to fill @cols number of widgets
2332 /// in row with same @item_width horizontal size. Once called all subsequent widget
2333 /// calls greater than @cols will allocate a new row with same layout.
2334 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2335 /// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
2336 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2337 ///
2338 /// Parameter   | Description
2339 /// ------------|-----------------------------------------------------------
2340 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2341 /// __height__  | Holds height of each widget in row or zero for auto layouting
2342 /// __width__   | Holds pixel width of each widget in the row
2343 /// __columns__ | Number of widget inside row
2344 */
2345 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
2346 /*/// #### nk_layout_row_begin
2347 /// Starts a new dynamic or fixed row with given height and columns.
2348 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2349 /// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
2350 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2351 ///
2352 /// Parameter   | Description
2353 /// ------------|-----------------------------------------------------------
2354 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2355 /// __fmt__     | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
2356 /// __height__  | holds height of each widget in row or zero for auto layouting
2357 /// __columns__ | Number of widget inside row
2358 */
2359 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
2360 /*/// #### nk_layout_row_push
2361 /// Specifies either window ratio or width of a single column
2362 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2363 /// void nk_layout_row_push(struct nk_context*, float value);
2364 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2365 ///
2366 /// Parameter   | Description
2367 /// ------------|-----------------------------------------------------------
2368 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2369 /// __value__   | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call
2370 */
2371 NK_API void nk_layout_row_push(struct nk_context*, float value);
2372 /*/// #### nk_layout_row_end
2373 /// Finished previously started row
2374 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2375 /// void nk_layout_row_end(struct nk_context*);
2376 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2377 ///
2378 /// Parameter   | Description
2379 /// ------------|-----------------------------------------------------------
2380 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2381 */
2382 NK_API void nk_layout_row_end(struct nk_context*);
2383 /*/// #### nk_layout_row
2384 /// Specifies row columns in array as either window ratio or size
2385 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2386 /// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
2387 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2388 ///
2389 /// Parameter   | Description
2390 /// ------------|-----------------------------------------------------------
2391 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2392 /// __fmt__     | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
2393 /// __height__  | Holds height of each widget in row or zero for auto layouting
2394 /// __columns__ | Number of widget inside row
2395 */
2396 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
2397 /*/// #### nk_layout_row_template_begin
2398 /// Begins the row template declaration
2399 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2400 /// void nk_layout_row_template_begin(struct nk_context*, float row_height);
2401 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2402 ///
2403 /// Parameter   | Description
2404 /// ------------|-----------------------------------------------------------
2405 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2406 /// __height__  | Holds height of each widget in row or zero for auto layouting
2407 */
2408 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
2409 /*/// #### nk_layout_row_template_push_dynamic
2410 /// Adds a dynamic column that dynamically grows and can go to zero if not enough space
2411 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2412 /// void nk_layout_row_template_push_dynamic(struct nk_context*);
2413 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2414 ///
2415 /// Parameter   | Description
2416 /// ------------|-----------------------------------------------------------
2417 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2418 /// __height__  | Holds height of each widget in row or zero for auto layouting
2419 */
2420 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*);
2421 /*/// #### nk_layout_row_template_push_variable
2422 /// Adds a variable column that dynamically grows but does not shrink below specified pixel width
2423 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2424 /// void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
2425 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2426 ///
2427 /// Parameter   | Description
2428 /// ------------|-----------------------------------------------------------
2429 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2430 /// __width__   | Holds the minimum pixel width the next column must always be
2431 */
2432 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
2433 /*/// #### nk_layout_row_template_push_static
2434 /// Adds a static column that does not grow and will always have the same size
2435 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2436 /// void nk_layout_row_template_push_static(struct nk_context*, float width);
2437 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2438 ///
2439 /// Parameter   | Description
2440 /// ------------|-----------------------------------------------------------
2441 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2442 /// __width__   | Holds the absolute pixel width value the next column must be
2443 */
2444 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
2445 /*/// #### nk_layout_row_template_end
2446 /// Marks the end of the row template
2447 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2448 /// void nk_layout_row_template_end(struct nk_context*);
2449 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2450 ///
2451 /// Parameter   | Description
2452 /// ------------|-----------------------------------------------------------
2453 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2454 */
2455 NK_API void nk_layout_row_template_end(struct nk_context*);
2456 /*/// #### nk_layout_space_begin
2457 /// Begins a new layouting space that allows to specify each widgets position and size.
2458 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2459 /// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
2460 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2461 ///
2462 /// Parameter   | Description
2463 /// ------------|-----------------------------------------------------------
2464 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
2465 /// __fmt__     | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
2466 /// __height__  | Holds height of each widget in row or zero for auto layouting
2467 /// __columns__ | Number of widgets inside row
2468 */
2469 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
2470 /*/// #### nk_layout_space_push
2471 /// Pushes position and size of the next widget in own coordinate space either as pixel or ratio
2472 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2473 /// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds);
2474 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2475 ///
2476 /// Parameter   | Description
2477 /// ------------|-----------------------------------------------------------
2478 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2479 /// __bounds__  | Position and size in laoyut space local coordinates
2480 */
2481 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds);
2482 /*/// #### nk_layout_space_end
2483 /// Marks the end of the layout space
2484 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2485 /// void nk_layout_space_end(struct nk_context*);
2486 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2487 ///
2488 /// Parameter   | Description
2489 /// ------------|-----------------------------------------------------------
2490 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2491 */
2492 NK_API void nk_layout_space_end(struct nk_context*);
2493 /*/// #### nk_layout_space_bounds
2494 /// Utility function to calculate total space allocated for `nk_layout_space`
2495 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2496 /// struct nk_rect nk_layout_space_bounds(struct nk_context*);
2497 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2498 ///
2499 /// Parameter   | Description
2500 /// ------------|-----------------------------------------------------------
2501 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2502 ///
2503 /// Returns `nk_rect` holding the total space allocated
2504 */
2505 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*);
2506 /*/// #### nk_layout_space_to_screen
2507 /// Converts vector from nk_layout_space coordinate space into screen space
2508 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2509 /// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
2510 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2511 ///
2512 /// Parameter   | Description
2513 /// ------------|-----------------------------------------------------------
2514 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2515 /// __vec__     | Position to convert from layout space into screen coordinate space
2516 ///
2517 /// Returns transformed `nk_vec2` in screen space coordinates
2518 */
2519 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
2520 /*/// #### nk_layout_space_to_local
2521 /// Converts vector from layout space into screen space
2522 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2523 /// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
2524 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2525 ///
2526 /// Parameter   | Description
2527 /// ------------|-----------------------------------------------------------
2528 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2529 /// __vec__     | Position to convert from screen space into layout coordinate space
2530 ///
2531 /// Returns transformed `nk_vec2` in layout space coordinates
2532 */
2533 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
2534 /*/// #### nk_layout_space_rect_to_screen
2535 /// Converts rectangle from screen space into layout space
2536 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2537 /// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
2538 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2539 ///
2540 /// Parameter   | Description
2541 /// ------------|-----------------------------------------------------------
2542 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2543 /// __bounds__  | Rectangle to convert from layout space into screen space
2544 ///
2545 /// Returns transformed `nk_rect` in screen space coordinates
2546 */
2547 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
2548 /*/// #### nk_layout_space_rect_to_local
2549 /// Converts rectangle from layout space into screen space
2550 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2551 /// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
2552 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2553 ///
2554 /// Parameter   | Description
2555 /// ------------|-----------------------------------------------------------
2556 /// __ctx__     | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
2557 /// __bounds__  | Rectangle to convert from layout space into screen space
2558 ///
2559 /// Returns transformed `nk_rect` in layout space coordinates
2560 */
2561 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
2562 /* =============================================================================
2563  *
2564  *                                  GROUP
2565  *
2566  * =============================================================================
2567 /// ### Groups
2568 /// Groups are basically windows inside windows. They allow to subdivide space
2569 /// in a window to layout widgets as a group. Almost all more complex widget
2570 /// layouting requirements can be solved using groups and basic layouting
2571 /// fuctionality. Groups just like windows are identified by an unique name and
2572 /// internally keep track of scrollbar offsets by default. However additional
2573 /// versions are provided to directly manage the scrollbar.
2574 ///
2575 /// #### Usage
2576 /// To create a group you have to call one of the three `nk_group_begin_xxx`
2577 /// functions to start group declarations and `nk_group_end` at the end. Furthermore it
2578 /// is required to check the return value of `nk_group_begin_xxx` and only process
2579 /// widgets inside the window if the value is not 0.
2580 /// Nesting groups is possible and even encouraged since many layouting schemes
2581 /// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end`
2582 /// to be only called if the corosponding `nk_group_begin_xxx` call does not return 0:
2583 ///
2584 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2585 /// if (nk_group_begin_xxx(ctx, ...) {
2586 ///     // [... widgets ...]
2587 ///     nk_group_end(ctx);
2588 /// }
2589 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2590 ///
2591 /// In the grand concept groups can be called after starting a window
2592 /// with `nk_begin_xxx` and before calling `nk_end`:
2593 ///
2594 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2595 /// struct nk_context ctx;
2596 /// nk_init_xxx(&ctx, ...);
2597 /// while (1) {
2598 ///     // Input
2599 ///     Event evt;
2600 ///     nk_input_begin(&ctx);
2601 ///     while (GetEvent(&evt)) {
2602 ///         if (evt.type == MOUSE_MOVE)
2603 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
2604 ///         else if (evt.type == [...]) {
2605 ///             nk_input_xxx(...);
2606 ///         }
2607 ///     }
2608 ///     nk_input_end(&ctx);
2609 ///     //
2610 ///     // Window
2611 ///     if (nk_begin_xxx(...) {
2612 ///         // [...widgets...]
2613 ///         nk_layout_row_dynamic(...);
2614 ///         if (nk_group_begin_xxx(ctx, ...) {
2615 ///             //[... widgets ...]
2616 ///             nk_group_end(ctx);
2617 ///         }
2618 ///     }
2619 ///     nk_end(ctx);
2620 ///     //
2621 ///     // Draw
2622 ///     const struct nk_command *cmd = 0;
2623 ///     nk_foreach(cmd, &ctx) {
2624 ///     switch (cmd->type) {
2625 ///     case NK_COMMAND_LINE:
2626 ///         your_draw_line_function(...)
2627 ///         break;
2628 ///     case NK_COMMAND_RECT
2629 ///         your_draw_rect_function(...)
2630 ///         break;
2631 ///     case ...:
2632 ///         // [...]
2633 ///     }
2634 ///     nk_clear(&ctx);
2635 /// }
2636 /// nk_free(&ctx);
2637 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2638 /// #### Reference
2639 /// Function                        | Description
2640 /// --------------------------------|-------------------------------------------
2641 /// nk_group_begin                  | Start a new group with internal scrollbar handling
2642 /// nk_group_begin_titled           | Start a new group with separeted name and title and internal scrollbar handling
2643 /// nk_group_end                    | Ends a group. Should only be called if nk_group_begin returned non-zero
2644 /// nk_group_scrolled_offset_begin  | Start a new group with manual separated handling of scrollbar x- and y-offset
2645 /// nk_group_scrolled_begin         | Start a new group with manual scrollbar handling
2646 /// nk_group_scrolled_end           | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero
2647 /// nk_group_get_scroll             | Gets the scroll offset for the given group
2648 /// nk_group_set_scroll             | Sets the scroll offset for the given group
2649 */
2650 /*/// #### nk_group_begin
2651 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
2652 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2653 /// int nk_group_begin(struct nk_context*, const char *title, nk_flags);
2654 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2655 ///
2656 /// Parameter   | Description
2657 /// ------------|-----------------------------------------------------------
2658 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2659 /// __title__   | Must be an unique identifier for this group that is also used for the group header
2660 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different group behaviors
2661 ///
2662 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2663 */
2664 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
2665 /*/// #### nk_group_begin_titled
2666 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
2667 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2668 /// int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
2669 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2670 ///
2671 /// Parameter   | Description
2672 /// ------------|-----------------------------------------------------------
2673 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2674 /// __id__      | Must be an unique identifier for this group
2675 /// __title__   | Group header title
2676 /// __flags__   | Window flags defined in the nk_panel_flags section with a number of different group behaviors
2677 ///
2678 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2679 */
2680 NK_API int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
2681 /*/// #### nk_group_end
2682 /// Ends a widget group
2683 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2684 /// void nk_group_end(struct nk_context*);
2685 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2686 ///
2687 /// Parameter   | Description
2688 /// ------------|-----------------------------------------------------------
2689 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2690 */
2691 NK_API void nk_group_end(struct nk_context*);
2692 /*/// #### nk_group_scrolled_offset_begin
2693 /// starts a new widget group. requires a previous layouting function to specify
2694 /// a size. Does not keep track of scrollbar.
2695 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2696 /// int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
2697 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2698 ///
2699 /// Parameter   | Description
2700 /// ------------|-----------------------------------------------------------
2701 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2702 /// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally.
2703 /// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically
2704 /// __title__   | Window unique group title used to both identify and display in the group header
2705 /// __flags__   | Window flags from the nk_panel_flags section
2706 ///
2707 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2708 */
2709 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);
2710 /*/// #### nk_group_scrolled_begin
2711 /// Starts a new widget group. requires a previous
2712 /// layouting function to specify a size. Does not keep track of scrollbar.
2713 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2714 /// int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
2715 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2716 ///
2717 /// Parameter   | Description
2718 /// ------------|-----------------------------------------------------------
2719 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2720 /// __off__     | Both x- and y- scroll offset. Allows for manual scrollbar control
2721 /// __title__   | Window unique group title used to both identify and display in the group header
2722 /// __flags__   | Window flags from nk_panel_flags section
2723 ///
2724 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2725 */
2726 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
2727 /*/// #### nk_group_scrolled_end
2728 /// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin.
2729 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2730 /// void nk_group_scrolled_end(struct nk_context*);
2731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2732 ///
2733 /// Parameter   | Description
2734 /// ------------|-----------------------------------------------------------
2735 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2736 */
2737 NK_API void nk_group_scrolled_end(struct nk_context*);
2738 /*/// #### nk_group_get_scroll
2739 /// Gets the scroll position of the given group.
2740 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2741 /// void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset);
2742 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2743 ///
2744 /// Parameter    | Description
2745 /// -------------|-----------------------------------------------------------
2746 /// __ctx__      | Must point to an previously initialized `nk_context` struct
2747 /// __id__       | The id of the group to get the scroll position of
2748 /// __x_offset__ | A pointer to the x offset output (or NULL to ignore)
2749 /// __y_offset__ | A pointer to the y offset output (or NULL to ignore)
2750 */
2751 NK_API void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset);
2752 /*/// #### nk_group_set_scroll
2753 /// Sets the scroll position of the given group.
2754 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2755 /// void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset);
2756 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2757 ///
2758 /// Parameter    | Description
2759 /// -------------|-----------------------------------------------------------
2760 /// __ctx__      | Must point to an previously initialized `nk_context` struct
2761 /// __id__       | The id of the group to scroll
2762 /// __x_offset__ | The x offset to scroll to
2763 /// __y_offset__ | The y offset to scroll to
2764 */
2765 NK_API void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset);
2766 /* =============================================================================
2767  *
2768  *                                  TREE
2769  *
2770  * =============================================================================
2771 /// ### Tree
2772 /// Trees represent two different concept. First the concept of a collapsable
2773 /// UI section that can be either in a hidden or visibile state. They allow the UI
2774 /// user to selectively minimize the current set of visible UI to comprehend.
2775 /// The second concept are tree widgets for visual UI representation of trees.<br /><br />
2776 ///
2777 /// Trees thereby can be nested for tree representations and multiple nested
2778 /// collapsable UI sections. All trees are started by calling of the
2779 /// `nk_tree_xxx_push_tree` functions and ended by calling one of the
2780 /// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label
2781 /// and optionally an image to be displayed and the initial collapse state from
2782 /// the nk_collapse_states section.<br /><br />
2783 ///
2784 /// The runtime state of the tree is either stored outside the library by the caller
2785 /// or inside which requires a unique ID. The unique ID can either be generated
2786 /// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`,
2787 /// by `__FILE__` and a user provided ID generated for example by loop index with
2788 /// function `nk_tree_push_id` or completely provided from outside by user with
2789 /// function `nk_tree_push_hashed`.
2790 ///
2791 /// #### Usage
2792 /// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx`
2793 /// functions to start a collapsable UI section and `nk_tree_xxx_pop` to mark the
2794 /// end.
2795 /// Each starting function will either return `false(0)` if the tree is collapsed
2796 /// or hidden and therefore does not need to be filled with content or `true(1)`
2797 /// if visible and required to be filled.
2798 ///
2799 /// !!! Note
2800 ///     The tree header does not require and layouting function and instead
2801 ///     calculates a auto height based on the currently used font size
2802 ///
2803 /// The tree ending functions only need to be called if the tree content is
2804 /// actually visible. So make sure the tree push function is guarded by `if`
2805 /// and the pop call is only taken if the tree is visible.
2806 ///
2807 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2808 /// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) {
2809 ///     nk_layout_row_dynamic(...);
2810 ///     nk_widget(...);
2811 ///     nk_tree_pop(ctx);
2812 /// }
2813 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2814 ///
2815 /// #### Reference
2816 /// Function                    | Description
2817 /// ----------------------------|-------------------------------------------
2818 /// nk_tree_push                | Start a collapsable UI section with internal state management
2819 /// nk_tree_push_id             | Start a collapsable UI section with internal state management callable in a look
2820 /// nk_tree_push_hashed         | Start a collapsable UI section with internal state management with full control over internal unique ID use to store state
2821 /// nk_tree_image_push          | Start a collapsable UI section with image and label header
2822 /// nk_tree_image_push_id       | Start a collapsable UI section with image and label header and internal state management callable in a look
2823 /// 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
2824 /// nk_tree_pop                 | Ends a collapsable UI section
2825 //
2826 /// nk_tree_state_push          | Start a collapsable UI section with external state management
2827 /// nk_tree_state_image_push    | Start a collapsable UI section with image and label header and external state management
2828 /// nk_tree_state_pop           | Ends a collapsabale UI section
2829 ///
2830 /// #### nk_tree_type
2831 /// Flag            | Description
2832 /// ----------------|----------------------------------------
2833 /// NK_TREE_NODE    | Highlighted tree header to mark a collapsable UI section
2834 /// NK_TREE_TAB     | Non-highighted tree header closer to tree representations
2835 */
2836 /*/// #### nk_tree_push
2837 /// Starts a collapsable UI section with internal state management
2838 /// !!! WARNING
2839 ///     To keep track of the runtime tree collapsable state this function uses
2840 ///     defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
2841 ///     to call this function in a loop please use `nk_tree_push_id` or
2842 ///     `nk_tree_push_hashed` instead.
2843 ///
2844 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2845 /// #define nk_tree_push(ctx, type, title, state)
2846 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2847 ///
2848 /// Parameter   | Description
2849 /// ------------|-----------------------------------------------------------
2850 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2851 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2852 /// __title__   | Label printed in the tree header
2853 /// __state__   | Initial tree state value out of nk_collapse_states
2854 ///
2855 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2856 */
2857 #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__)
2858 /*/// #### nk_tree_push_id
2859 /// Starts a collapsable UI section with internal state management callable in a look
2860 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2861 /// #define nk_tree_push_id(ctx, type, title, state, id)
2862 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2863 ///
2864 /// Parameter   | Description
2865 /// ------------|-----------------------------------------------------------
2866 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2867 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2868 /// __title__   | Label printed in the tree header
2869 /// __state__   | Initial tree state value out of nk_collapse_states
2870 /// __id__      | Loop counter index if this function is called in a loop
2871 ///
2872 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2873 */
2874 #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)
2875 /*/// #### nk_tree_push_hashed
2876 /// Start a collapsable UI section with internal state management with full
2877 /// control over internal unique ID used to store state
2878 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2879 /// 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);
2880 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2881 ///
2882 /// Parameter   | Description
2883 /// ------------|-----------------------------------------------------------
2884 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2885 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2886 /// __title__   | Label printed in the tree header
2887 /// __state__   | Initial tree state value out of nk_collapse_states
2888 /// __hash__    | Memory block or string to generate the ID from
2889 /// __len__     | Size of passed memory block or string in __hash__
2890 /// __seed__    | Seeding value if this function is called in a loop or default to `0`
2891 ///
2892 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2893 */
2894 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);
2895 /*/// #### nk_tree_image_push
2896 /// Start a collapsable UI section with image and label header
2897 /// !!! WARNING
2898 ///     To keep track of the runtime tree collapsable state this function uses
2899 ///     defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
2900 ///     to call this function in a loop please use `nk_tree_image_push_id` or
2901 ///     `nk_tree_image_push_hashed` instead.
2902 ///
2903 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2904 /// #define nk_tree_image_push(ctx, type, img, title, state)
2905 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2906 //
2907 /// Parameter   | Description
2908 /// ------------|-----------------------------------------------------------
2909 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2910 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2911 /// __img__     | Image to display inside the header on the left of the label
2912 /// __title__   | Label printed in the tree header
2913 /// __state__   | Initial tree state value out of nk_collapse_states
2914 ///
2915 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2916 */
2917 #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__)
2918 /*/// #### nk_tree_image_push_id
2919 /// Start a collapsable UI section with image and label header and internal state
2920 /// management callable in a look
2921 ///
2922 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2923 /// #define nk_tree_image_push_id(ctx, type, img, title, state, id)
2924 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2925 ///
2926 /// Parameter   | Description
2927 /// ------------|-----------------------------------------------------------
2928 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2929 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2930 /// __img__     | Image to display inside the header on the left of the label
2931 /// __title__   | Label printed in the tree header
2932 /// __state__   | Initial tree state value out of nk_collapse_states
2933 /// __id__      | Loop counter index if this function is called in a loop
2934 ///
2935 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2936 */
2937 #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)
2938 /*/// #### nk_tree_image_push_hashed
2939 /// Start a collapsable UI section with internal state management with full
2940 /// control over internal unique ID used to store state
2941 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2942 /// 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);
2943 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2944 ///
2945 /// Parameter   | Description
2946 /// ------------|-----------------------------------------------------------
2947 /// __ctx__     | Must point to an previously initialized `nk_context` struct
2948 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2949 /// __img__     | Image to display inside the header on the left of the label
2950 /// __title__   | Label printed in the tree header
2951 /// __state__   | Initial tree state value out of nk_collapse_states
2952 /// __hash__    | Memory block or string to generate the ID from
2953 /// __len__     | Size of passed memory block or string in __hash__
2954 /// __seed__    | Seeding value if this function is called in a loop or default to `0`
2955 ///
2956 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2957 */
2958 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);
2959 /*/// #### nk_tree_pop
2960 /// Ends a collapsabale UI section
2961 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2962 /// void nk_tree_pop(struct nk_context*);
2963 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2964 ///
2965 /// Parameter   | Description
2966 /// ------------|-----------------------------------------------------------
2967 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
2968 */
2969 NK_API void nk_tree_pop(struct nk_context*);
2970 /*/// #### nk_tree_state_push
2971 /// Start a collapsable UI section with external state management
2972 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2973 /// int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
2974 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2975 ///
2976 /// Parameter   | Description
2977 /// ------------|-----------------------------------------------------------
2978 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
2979 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2980 /// __title__   | Label printed in the tree header
2981 /// __state__   | Persistent state to update
2982 ///
2983 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
2984 */
2985 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
2986 /*/// #### nk_tree_state_image_push
2987 /// Start a collapsable UI section with image and label header and external state management
2988 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
2989 /// int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
2990 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2991 ///
2992 /// Parameter   | Description
2993 /// ------------|-----------------------------------------------------------
2994 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
2995 /// __img__     | Image to display inside the header on the left of the label
2996 /// __type__    | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
2997 /// __title__   | Label printed in the tree header
2998 /// __state__   | Persistent state to update
2999 ///
3000 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
3001 */
3002 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);
3003 /*/// #### nk_tree_state_pop
3004 /// Ends a collapsabale UI section
3005 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3006 /// void nk_tree_state_pop(struct nk_context*);
3007 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3008 ///
3009 /// Parameter   | Description
3010 /// ------------|-----------------------------------------------------------
3011 /// __ctx__     | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
3012 */
3013 NK_API void nk_tree_state_pop(struct nk_context*);
3014 
3015 #define nk_tree_element_push(ctx, type, title, state, sel) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
3016 #define nk_tree_element_push_id(ctx, type, title, state, sel, id) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
3017 NK_API int nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed);
3018 NK_API int nk_tree_element_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len,int seed);
3019 NK_API void nk_tree_element_pop(struct nk_context*);
3020 
3021 /* =============================================================================
3022  *
3023  *                                  LIST VIEW
3024  *
3025  * ============================================================================= */
3026 struct nk_list_view {
3027 /* public: */
3028     int begin, end, count;
3029 /* private: */
3030     int total_height;
3031     struct nk_context *ctx;
3032     nk_uint *scroll_pointer;
3033     nk_uint scroll_value;
3034 };
3035 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);
3036 NK_API void nk_list_view_end(struct nk_list_view*);
3037 /* =============================================================================
3038  *
3039  *                                  WIDGET
3040  *
3041  * ============================================================================= */
3042 enum nk_widget_layout_states {
3043     NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
3044     NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
3045     NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
3046 };
3047 enum nk_widget_states {
3048     NK_WIDGET_STATE_MODIFIED    = NK_FLAG(1),
3049     NK_WIDGET_STATE_INACTIVE    = NK_FLAG(2), /* widget is neither active nor hovered */
3050     NK_WIDGET_STATE_ENTERED     = NK_FLAG(3), /* widget has been hovered on the current frame */
3051     NK_WIDGET_STATE_HOVER       = NK_FLAG(4), /* widget is being hovered */
3052     NK_WIDGET_STATE_ACTIVED     = NK_FLAG(5),/* widget is currently activated */
3053     NK_WIDGET_STATE_LEFT        = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
3054     NK_WIDGET_STATE_HOVERED     = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */
3055     NK_WIDGET_STATE_ACTIVE      = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */
3056 };
3057 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
3058 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2);
3059 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
3060 NK_API struct nk_vec2 nk_widget_position(struct nk_context*);
3061 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
3062 NK_API float nk_widget_width(struct nk_context*);
3063 NK_API float nk_widget_height(struct nk_context*);
3064 NK_API int nk_widget_is_hovered(struct nk_context*);
3065 NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons);
3066 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
3067 NK_API void nk_spacing(struct nk_context*, int cols);
3068 /* =============================================================================
3069  *
3070  *                                  TEXT
3071  *
3072  * ============================================================================= */
3073 enum nk_text_align {
3074     NK_TEXT_ALIGN_LEFT        = 0x01,
3075     NK_TEXT_ALIGN_CENTERED    = 0x02,
3076     NK_TEXT_ALIGN_RIGHT       = 0x04,
3077     NK_TEXT_ALIGN_TOP         = 0x08,
3078     NK_TEXT_ALIGN_MIDDLE      = 0x10,
3079     NK_TEXT_ALIGN_BOTTOM      = 0x20
3080 };
3081 enum nk_text_alignment {
3082     NK_TEXT_LEFT        = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT,
3083     NK_TEXT_CENTERED    = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED,
3084     NK_TEXT_RIGHT       = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT
3085 };
3086 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
3087 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
3088 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
3089 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
3090 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
3091 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
3092 NK_API void nk_label_wrap(struct nk_context*, const char*);
3093 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
3094 NK_API void nk_image(struct nk_context*, struct nk_image);
3095 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color);
3096 #ifdef NK_INCLUDE_STANDARD_VARARGS
3097 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3);
3098 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);
3099 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2);
3100 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3);
3101 NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
3102 NK_API void nk_labelfv_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(4);
3103 NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
3104 NK_API void nk_labelfv_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
3105 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
3106 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
3107 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
3108 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
3109 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
3110 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
3111 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
3112 #endif
3113 /* =============================================================================
3114  *
3115  *                                  BUTTON
3116  *
3117  * ============================================================================= */
3118 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
3119 NK_API int nk_button_label(struct nk_context*, const char *title);
3120 NK_API int nk_button_color(struct nk_context*, struct nk_color);
3121 NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type);
3122 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
3123 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
3124 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3125 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
3126 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
3127 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
3128 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
3129 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
3130 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
3131 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);
3132 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);
3133 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);
3134 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);
3135 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior);
3136 NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior);
3137 NK_API int nk_button_pop_behavior(struct nk_context*);
3138 /* =============================================================================
3139  *
3140  *                                  CHECKBOX
3141  *
3142  * ============================================================================= */
3143 NK_API int nk_check_label(struct nk_context*, const char*, int active);
3144 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
3145 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
3146 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
3147 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
3148 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
3149 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
3150 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
3151 /* =============================================================================
3152  *
3153  *                                  RADIO BUTTON
3154  *
3155  * ============================================================================= */
3156 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
3157 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
3158 NK_API int nk_option_label(struct nk_context*, const char*, int active);
3159 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
3160 /* =============================================================================
3161  *
3162  *                                  SELECTABLE
3163  *
3164  * ============================================================================= */
3165 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
3166 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
3167 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image,  const char*, nk_flags align, int *value);
3168 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
3169 NK_API int nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type,  const char*, nk_flags align, int *value);
3170 NK_API int nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int *value);
3171 
3172 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
3173 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
3174 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
3175 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
3176 NK_API int nk_select_symbol_label(struct nk_context*,enum nk_symbol_type,  const char*, nk_flags align, int value);
3177 NK_API int nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int value);
3178 
3179 /* =============================================================================
3180  *
3181  *                                  SLIDER
3182  *
3183  * ============================================================================= */
3184 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
3185 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
3186 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
3187 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
3188 /* =============================================================================
3189  *
3190  *                                  PROGRESSBAR
3191  *
3192  * ============================================================================= */
3193 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
3194 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
3195 
3196 /* =============================================================================
3197  *
3198  *                                  COLOR PICKER
3199  *
3200  * ============================================================================= */
3201 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format);
3202 NK_API int nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format);
3203 /* =============================================================================
3204  *
3205  *                                  PROPERTIES
3206  *
3207  * =============================================================================
3208 /// ### Properties
3209 /// Properties are the main value modification widgets in Nuklear. Changing a value
3210 /// can be achieved by dragging, adding/removing incremental steps on button click
3211 /// or by directly typing a number.
3212 ///
3213 /// #### Usage
3214 /// Each property requires a unique name for identifaction that is also used for
3215 /// displaying a label. If you want to use the same name multiple times make sure
3216 /// add a '#' before your name. The '#' will not be shown but will generate a
3217 /// unique ID. Each propery also takes in a minimum and maximum value. If you want
3218 /// to make use of the complete number range of a type just use the provided
3219 /// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for
3220 /// `nk_property_int` and `nk_propertyi`. In additional each property takes in
3221 /// a increment value that will be added or subtracted if either the increment
3222 /// decrement button is clicked. Finally there is a value for increment per pixel
3223 /// dragged that is added or subtracted from the value.
3224 ///
3225 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3226 /// int value = 0;
3227 /// struct nk_context ctx;
3228 /// nk_init_xxx(&ctx, ...);
3229 /// while (1) {
3230 ///     // Input
3231 ///     Event evt;
3232 ///     nk_input_begin(&ctx);
3233 ///     while (GetEvent(&evt)) {
3234 ///         if (evt.type == MOUSE_MOVE)
3235 ///             nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
3236 ///         else if (evt.type == [...]) {
3237 ///             nk_input_xxx(...);
3238 ///         }
3239 ///     }
3240 ///     nk_input_end(&ctx);
3241 ///     //
3242 ///     // Window
3243 ///     if (nk_begin_xxx(...) {
3244 ///         // Property
3245 ///         nk_layout_row_dynamic(...);
3246 ///         nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1);
3247 ///     }
3248 ///     nk_end(ctx);
3249 ///     //
3250 ///     // Draw
3251 ///     const struct nk_command *cmd = 0;
3252 ///     nk_foreach(cmd, &ctx) {
3253 ///     switch (cmd->type) {
3254 ///     case NK_COMMAND_LINE:
3255 ///         your_draw_line_function(...)
3256 ///         break;
3257 ///     case NK_COMMAND_RECT
3258 ///         your_draw_rect_function(...)
3259 ///         break;
3260 ///     case ...:
3261 ///         // [...]
3262 ///     }
3263 ///     nk_clear(&ctx);
3264 /// }
3265 /// nk_free(&ctx);
3266 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3267 ///
3268 /// #### Reference
3269 /// Function            | Description
3270 /// --------------------|-------------------------------------------
3271 /// nk_property_int     | Integer property directly modifing a passed in value
3272 /// nk_property_float   | Float property directly modifing a passed in value
3273 /// nk_property_double  | Double property directly modifing a passed in value
3274 /// nk_propertyi        | Integer property returning the modified int value
3275 /// nk_propertyf        | Float property returning the modified float value
3276 /// nk_propertyd        | Double property returning the modified double value
3277 ///
3278 */
3279 /*/// #### nk_property_int
3280 /// Integer property directly modifing a passed in value
3281 /// !!! WARNING
3282 ///     To generate a unique property ID using the same label make sure to insert
3283 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3284 ///
3285 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3286 /// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
3287 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3288 ///
3289 /// Parameter           | Description
3290 /// --------------------|-----------------------------------------------------------
3291 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3292 /// __name__            | String used both as a label as well as a unique identifier
3293 /// __min__             | Minimum value not allowed to be underflown
3294 /// __val__             | Integer pointer to be modified
3295 /// __max__             | Maximum value not allowed to be overflown
3296 /// __step__            | Increment added and subtracted on increment and decrement button
3297 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3298 */
3299 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
3300 /*/// #### nk_property_float
3301 /// Float property directly modifing a passed in value
3302 /// !!! WARNING
3303 ///     To generate a unique property ID using the same label make sure to insert
3304 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3305 ///
3306 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3307 /// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
3308 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3309 ///
3310 /// Parameter           | Description
3311 /// --------------------|-----------------------------------------------------------
3312 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3313 /// __name__            | String used both as a label as well as a unique identifier
3314 /// __min__             | Minimum value not allowed to be underflown
3315 /// __val__             | Float pointer to be modified
3316 /// __max__             | Maximum value not allowed to be overflown
3317 /// __step__            | Increment added and subtracted on increment and decrement button
3318 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3319 */
3320 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
3321 /*/// #### nk_property_double
3322 /// Double property directly modifing a passed in value
3323 /// !!! WARNING
3324 ///     To generate a unique property ID using the same label make sure to insert
3325 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3326 ///
3327 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3328 /// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel);
3329 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3330 ///
3331 /// Parameter           | Description
3332 /// --------------------|-----------------------------------------------------------
3333 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3334 /// __name__            | String used both as a label as well as a unique identifier
3335 /// __min__             | Minimum value not allowed to be underflown
3336 /// __val__             | Double pointer to be modified
3337 /// __max__             | Maximum value not allowed to be overflown
3338 /// __step__            | Increment added and subtracted on increment and decrement button
3339 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3340 */
3341 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
3342 /*/// #### nk_propertyi
3343 /// Integer property modifing a passed in value and returning the new value
3344 /// !!! WARNING
3345 ///     To generate a unique property ID using the same label make sure to insert
3346 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3347 ///
3348 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3349 /// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel);
3350 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3351 ///
3352 /// Parameter           | Description
3353 /// --------------------|-----------------------------------------------------------
3354 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3355 /// __name__            | String used both as a label as well as a unique identifier
3356 /// __min__             | Minimum value not allowed to be underflown
3357 /// __val__             | Current integer value to be modified and returned
3358 /// __max__             | Maximum value not allowed to be overflown
3359 /// __step__            | Increment added and subtracted on increment and decrement button
3360 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3361 ///
3362 /// Returns the new modified integer value
3363 */
3364 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
3365 /*/// #### nk_propertyf
3366 /// Float property modifing a passed in value and returning the new value
3367 /// !!! WARNING
3368 ///     To generate a unique property ID using the same label make sure to insert
3369 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3370 ///
3371 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3372 /// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel);
3373 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3374 ///
3375 /// Parameter           | Description
3376 /// --------------------|-----------------------------------------------------------
3377 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3378 /// __name__            | String used both as a label as well as a unique identifier
3379 /// __min__             | Minimum value not allowed to be underflown
3380 /// __val__             | Current float value to be modified and returned
3381 /// __max__             | Maximum value not allowed to be overflown
3382 /// __step__            | Increment added and subtracted on increment and decrement button
3383 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3384 ///
3385 /// Returns the new modified float value
3386 */
3387 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
3388 /*/// #### nk_propertyd
3389 /// Float property modifing a passed in value and returning the new value
3390 /// !!! WARNING
3391 ///     To generate a unique property ID using the same label make sure to insert
3392 ///     a `#` at the beginning. It will not be shown but guarantees correct behavior.
3393 ///
3394 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
3395 /// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel);
3396 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3397 ///
3398 /// Parameter           | Description
3399 /// --------------------|-----------------------------------------------------------
3400 /// __ctx__             | Must point to an previously initialized `nk_context` struct after calling a layouting function
3401 /// __name__            | String used both as a label as well as a unique identifier
3402 /// __min__             | Minimum value not allowed to be underflown
3403 /// __val__             | Current double value to be modified and returned
3404 /// __max__             | Maximum value not allowed to be overflown
3405 /// __step__            | Increment added and subtracted on increment and decrement button
3406 /// __inc_per_pixel__   | Value per pixel added or subtracted on dragging
3407 ///
3408 /// Returns the new modified double value
3409 */
3410 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
3411 /* =============================================================================
3412  *
3413  *                                  TEXT EDIT
3414  *
3415  * ============================================================================= */
3416 enum nk_edit_flags {
3417     NK_EDIT_DEFAULT                 = 0,
3418     NK_EDIT_READ_ONLY               = NK_FLAG(0),
3419     NK_EDIT_AUTO_SELECT             = NK_FLAG(1),
3420     NK_EDIT_SIG_ENTER               = NK_FLAG(2),
3421     NK_EDIT_ALLOW_TAB               = NK_FLAG(3),
3422     NK_EDIT_NO_CURSOR               = NK_FLAG(4),
3423     NK_EDIT_SELECTABLE              = NK_FLAG(5),
3424     NK_EDIT_CLIPBOARD               = NK_FLAG(6),
3425     NK_EDIT_CTRL_ENTER_NEWLINE      = NK_FLAG(7),
3426     NK_EDIT_NO_HORIZONTAL_SCROLL    = NK_FLAG(8),
3427     NK_EDIT_ALWAYS_INSERT_MODE      = NK_FLAG(9),
3428     NK_EDIT_MULTILINE               = NK_FLAG(10),
3429     NK_EDIT_GOTO_END_ON_ACTIVATE    = NK_FLAG(11)
3430 };
3431 enum nk_edit_types {
3432     NK_EDIT_SIMPLE  = NK_EDIT_ALWAYS_INSERT_MODE,
3433     NK_EDIT_FIELD   = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD,
3434     NK_EDIT_BOX     = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD,
3435     NK_EDIT_EDITOR  = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD
3436 };
3437 enum nk_edit_events {
3438     NK_EDIT_ACTIVE      = NK_FLAG(0), /* edit widget is currently being modified */
3439     NK_EDIT_INACTIVE    = NK_FLAG(1), /* edit widget is not active and is not being modified */
3440     NK_EDIT_ACTIVATED   = NK_FLAG(2), /* edit widget went from state inactive to state active */
3441     NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
3442     NK_EDIT_COMMITED    = NK_FLAG(4) /* edit widget has received an enter and lost focus */
3443 };
3444 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
3445 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
3446 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
3447 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
3448 NK_API void nk_edit_unfocus(struct nk_context*);
3449 /* =============================================================================
3450  *
3451  *                                  CHART
3452  *
3453  * ============================================================================= */
3454 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
3455 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);
3456 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
3457 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);
3458 NK_API nk_flags nk_chart_push(struct nk_context*, float);
3459 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
3460 NK_API void nk_chart_end(struct nk_context*);
3461 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
3462 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);
3463 /* =============================================================================
3464  *
3465  *                                  POPUP
3466  *
3467  * ============================================================================= */
3468 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
3469 NK_API void nk_popup_close(struct nk_context*);
3470 NK_API void nk_popup_end(struct nk_context*);
3471 NK_API void nk_popup_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
3472 NK_API void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
3473 /* =============================================================================
3474  *
3475  *                                  COMBOBOX
3476  *
3477  * ============================================================================= */
3478 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
3479 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);
3480 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);
3481 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);
3482 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
3483 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);
3484 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);
3485 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);
3486 /* =============================================================================
3487  *
3488  *                                  ABSTRACT COMBOBOX
3489  *
3490  * ============================================================================= */
3491 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
3492 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
3493 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
3494 NK_API int nk_combo_begin_symbol(struct nk_context*,  enum nk_symbol_type,  struct nk_vec2 size);
3495 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
3496 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
3497 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img,  struct nk_vec2 size);
3498 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
3499 NK_API int nk_combo_begin_image_text(struct nk_context*,  const char *selected, int, struct nk_image, struct nk_vec2 size);
3500 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
3501 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
3502 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3503 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
3504 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3505 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3506 NK_API void nk_combo_close(struct nk_context*);
3507 NK_API void nk_combo_end(struct nk_context*);
3508 /* =============================================================================
3509  *
3510  *                                  CONTEXTUAL
3511  *
3512  * ============================================================================= */
3513 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
3514 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
3515 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
3516 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3517 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3518 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3519 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3520 NK_API void nk_contextual_close(struct nk_context*);
3521 NK_API void nk_contextual_end(struct nk_context*);
3522 /* =============================================================================
3523  *
3524  *                                  TOOLTIP
3525  *
3526  * ============================================================================= */
3527 NK_API void nk_tooltip(struct nk_context*, const char*);
3528 #ifdef NK_INCLUDE_STANDARD_VARARGS
3529 NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2);
3530 NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
3531 #endif
3532 NK_API int nk_tooltip_begin(struct nk_context*, float width);
3533 NK_API void nk_tooltip_end(struct nk_context*);
3534 /* =============================================================================
3535  *
3536  *                                  MENU
3537  *
3538  * ============================================================================= */
3539 NK_API void nk_menubar_begin(struct nk_context*);
3540 NK_API void nk_menubar_end(struct nk_context*);
3541 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
3542 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
3543 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
3544 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
3545 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
3546 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
3547 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);
3548 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
3549 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
3550 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
3551 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3552 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3553 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3554 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3555 NK_API void nk_menu_close(struct nk_context*);
3556 NK_API void nk_menu_end(struct nk_context*);
3557 /* =============================================================================
3558  *
3559  *                                  STYLE
3560  *
3561  * ============================================================================= */
3562 enum nk_style_colors {
3563     NK_COLOR_TEXT,
3564     NK_COLOR_WINDOW,
3565     NK_COLOR_HEADER,
3566     NK_COLOR_BORDER,
3567     NK_COLOR_BUTTON,
3568     NK_COLOR_BUTTON_HOVER,
3569     NK_COLOR_BUTTON_ACTIVE,
3570     NK_COLOR_TOGGLE,
3571     NK_COLOR_TOGGLE_HOVER,
3572     NK_COLOR_TOGGLE_CURSOR,
3573     NK_COLOR_SELECT,
3574     NK_COLOR_SELECT_ACTIVE,
3575     NK_COLOR_SLIDER,
3576     NK_COLOR_SLIDER_CURSOR,
3577     NK_COLOR_SLIDER_CURSOR_HOVER,
3578     NK_COLOR_SLIDER_CURSOR_ACTIVE,
3579     NK_COLOR_PROPERTY,
3580     NK_COLOR_EDIT,
3581     NK_COLOR_EDIT_CURSOR,
3582     NK_COLOR_COMBO,
3583     NK_COLOR_CHART,
3584     NK_COLOR_CHART_COLOR,
3585     NK_COLOR_CHART_COLOR_HIGHLIGHT,
3586     NK_COLOR_SCROLLBAR,
3587     NK_COLOR_SCROLLBAR_CURSOR,
3588     NK_COLOR_SCROLLBAR_CURSOR_HOVER,
3589     NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,
3590     NK_COLOR_TAB_HEADER,
3591     NK_COLOR_COUNT
3592 };
3593 enum nk_style_cursor {
3594     NK_CURSOR_ARROW,
3595     NK_CURSOR_TEXT,
3596     NK_CURSOR_MOVE,
3597     NK_CURSOR_RESIZE_VERTICAL,
3598     NK_CURSOR_RESIZE_HORIZONTAL,
3599     NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT,
3600     NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT,
3601     NK_CURSOR_COUNT
3602 };
3603 NK_API void nk_style_default(struct nk_context*);
3604 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
3605 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
3606 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
3607 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors);
3608 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
3609 NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor);
3610 NK_API void nk_style_show_cursor(struct nk_context*);
3611 NK_API void nk_style_hide_cursor(struct nk_context*);
3612 
3613 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*);
3614 NK_API int nk_style_push_float(struct nk_context*, float*, float);
3615 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
3616 NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item);
3617 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
3618 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
3619 
3620 NK_API int nk_style_pop_font(struct nk_context*);
3621 NK_API int nk_style_pop_float(struct nk_context*);
3622 NK_API int nk_style_pop_vec2(struct nk_context*);
3623 NK_API int nk_style_pop_style_item(struct nk_context*);
3624 NK_API int nk_style_pop_flags(struct nk_context*);
3625 NK_API int nk_style_pop_color(struct nk_context*);
3626 /* =============================================================================
3627  *
3628  *                                  COLOR
3629  *
3630  * ============================================================================= */
3631 NK_API struct nk_color nk_rgb(int r, int g, int b);
3632 NK_API struct nk_color nk_rgb_iv(const int *rgb);
3633 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
3634 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
3635 NK_API struct nk_color nk_rgb_fv(const float *rgb);
3636 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c);
3637 NK_API struct nk_color nk_rgb_hex(const char *rgb);
3638 
3639 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
3640 NK_API struct nk_color nk_rgba_u32(nk_uint);
3641 NK_API struct nk_color nk_rgba_iv(const int *rgba);
3642 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
3643 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
3644 NK_API struct nk_color nk_rgba_fv(const float *rgba);
3645 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c);
3646 NK_API struct nk_color nk_rgba_hex(const char *rgb);
3647 
3648 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a);
3649 NK_API struct nk_colorf nk_hsva_colorfv(float *c);
3650 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in);
3651 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in);
3652 
3653 NK_API struct nk_color nk_hsv(int h, int s, int v);
3654 NK_API struct nk_color nk_hsv_iv(const int *hsv);
3655 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
3656 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
3657 NK_API struct nk_color nk_hsv_fv(const float *hsv);
3658 
3659 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
3660 NK_API struct nk_color nk_hsva_iv(const int *hsva);
3661 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
3662 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
3663 NK_API struct nk_color nk_hsva_fv(const float *hsva);
3664 
3665 /* color (conversion nuklear --> user) */
3666 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
3667 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
3668 NK_API struct nk_colorf nk_color_cf(struct nk_color);
3669 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
3670 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
3671 
3672 NK_API nk_uint nk_color_u32(struct nk_color);
3673 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
3674 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
3675 
3676 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
3677 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
3678 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
3679 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
3680 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
3681 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
3682 
3683 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
3684 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
3685 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
3686 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
3687 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
3688 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
3689 /* =============================================================================
3690  *
3691  *                                  IMAGE
3692  *
3693  * ============================================================================= */
3694 NK_API nk_handle nk_handle_ptr(void*);
3695 NK_API nk_handle nk_handle_id(int);
3696 NK_API struct nk_image nk_image_handle(nk_handle);
3697 NK_API struct nk_image nk_image_ptr(void*);
3698 NK_API struct nk_image nk_image_id(int);
3699 NK_API int nk_image_is_subimage(const struct nk_image* img);
3700 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
3701 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
3702 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
3703 /* =============================================================================
3704  *
3705  *                                  MATH
3706  *
3707  * ============================================================================= */
3708 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
3709 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
3710 
3711 NK_API struct nk_vec2 nk_vec2(float x, float y);
3712 NK_API struct nk_vec2 nk_vec2i(int x, int y);
3713 NK_API struct nk_vec2 nk_vec2v(const float *xy);
3714 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
3715 
3716 NK_API struct nk_rect nk_get_null_rect(void);
3717 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
3718 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
3719 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
3720 NK_API struct nk_rect nk_rectv(const float *xywh);
3721 NK_API struct nk_rect nk_rectiv(const int *xywh);
3722 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
3723 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
3724 /* =============================================================================
3725  *
3726  *                                  STRING
3727  *
3728  * ============================================================================= */
3729 NK_API int nk_strlen(const char *str);
3730 NK_API int nk_stricmp(const char *s1, const char *s2);
3731 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
3732 NK_API int nk_strtoi(const char *str, const char **endptr);
3733 NK_API float nk_strtof(const char *str, const char **endptr);
3734 NK_API double nk_strtod(const char *str, const char **endptr);
3735 NK_API int nk_strfilter(const char *text, const char *regexp);
3736 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
3737 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
3738 /* =============================================================================
3739  *
3740  *                                  UTF-8
3741  *
3742  * ============================================================================= */
3743 NK_API int nk_utf_decode(const char*, nk_rune*, int);
3744 NK_API int nk_utf_encode(nk_rune, char*, int);
3745 NK_API int nk_utf_len(const char*, int byte_len);
3746 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
3747 /* ===============================================================
3748  *
3749  *                          FONT
3750  *
3751  * ===============================================================*/
3752 /*  Font handling in this library was designed to be quite customizable and lets
3753     you decide what you want to use and what you want to provide. There are three
3754     different ways to use the font atlas. The first two will use your font
3755     handling scheme and only requires essential data to run nuklear. The next
3756     slightly more advanced features is font handling with vertex buffer output.
3757     Finally the most complex API wise is using nuklear's font baking API.
3758 
3759     1.) Using your own implementation without vertex buffer output
3760     --------------------------------------------------------------
3761     So first up the easiest way to do font handling is by just providing a
3762     `nk_user_font` struct which only requires the height in pixel of the used
3763     font and a callback to calculate the width of a string. This way of handling
3764     fonts is best fitted for using the normal draw shape command API where you
3765     do all the text drawing yourself and the library does not require any kind
3766     of deeper knowledge about which font handling mechanism you use.
3767     IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
3768     over the complete life time! I know this sucks but it is currently the only
3769     way to switch between fonts.
3770 
3771         float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
3772         {
3773             your_font_type *type = handle.ptr;
3774             float text_width = ...;
3775             return text_width;
3776         }
3777 
3778         struct nk_user_font font;
3779         font.userdata.ptr = &your_font_class_or_struct;
3780         font.height = your_font_height;
3781         font.width = your_text_width_calculation;
3782 
3783         struct nk_context ctx;
3784         nk_init_default(&ctx, &font);
3785 
3786     2.) Using your own implementation with vertex buffer output
3787     --------------------------------------------------------------
3788     While the first approach works fine if you don't want to use the optional
3789     vertex buffer output it is not enough if you do. To get font handling working
3790     for these cases you have to provide two additional parameters inside the
3791     `nk_user_font`. First a texture atlas handle used to draw text as subimages
3792     of a bigger font atlas texture and a callback to query a character's glyph
3793     information (offset, size, ...). So it is still possible to provide your own
3794     font and use the vertex buffer output.
3795 
3796         float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
3797         {
3798             your_font_type *type = handle.ptr;
3799             float text_width = ...;
3800             return text_width;
3801         }
3802         void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
3803         {
3804             your_font_type *type = handle.ptr;
3805             glyph.width = ...;
3806             glyph.height = ...;
3807             glyph.xadvance = ...;
3808             glyph.uv[0].x = ...;
3809             glyph.uv[0].y = ...;
3810             glyph.uv[1].x = ...;
3811             glyph.uv[1].y = ...;
3812             glyph.offset.x = ...;
3813             glyph.offset.y = ...;
3814         }
3815 
3816         struct nk_user_font font;
3817         font.userdata.ptr = &your_font_class_or_struct;
3818         font.height = your_font_height;
3819         font.width = your_text_width_calculation;
3820         font.query = query_your_font_glyph;
3821         font.texture.id = your_font_texture;
3822 
3823         struct nk_context ctx;
3824         nk_init_default(&ctx, &font);
3825 
3826     3.) Nuklear font baker
3827     ------------------------------------
3828     The final approach if you do not have a font handling functionality or don't
3829     want to use it in this library is by using the optional font baker.
3830     The font baker APIs can be used to create a font plus font atlas texture
3831     and can be used with or without the vertex buffer output.
3832 
3833     It still uses the `nk_user_font` struct and the two different approaches
3834     previously stated still work. The font baker is not located inside
3835     `nk_context` like all other systems since it can be understood as more of
3836     an extension to nuklear and does not really depend on any `nk_context` state.
3837 
3838     Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
3839     functions. If you don't care about memory just call the default version
3840     `nk_font_atlas_init_default` which will allocate all memory from the standard library.
3841     If you want to control memory allocation but you don't care if the allocated
3842     memory is temporary and therefore can be freed directly after the baking process
3843     is over or permanent you can call `nk_font_atlas_init`.
3844 
3845     After successfully initializing the font baker you can add Truetype(.ttf) fonts from
3846     different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
3847     functions. Adding font will permanently store each font, font config and ttf memory block(!)
3848     inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
3849     the font baker by for example adding additional fonts you can call
3850     `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
3851 
3852     As soon as you added all fonts you wanted you can now start the baking process
3853     for every selected glyph to image by calling `nk_font_atlas_bake`.
3854     The baking process returns image memory, width and height which can be used to
3855     either create your own image object or upload it to any graphics library.
3856     No matter which case you finally have to call `nk_font_atlas_end` which
3857     will free all temporary memory including the font atlas image so make sure
3858     you created our texture beforehand. `nk_font_atlas_end` requires a handle
3859     to your font texture or object and optionally fills a `struct nk_draw_null_texture`
3860     which can be used for the optional vertex output. If you don't want it just
3861     set the argument to `NULL`.
3862 
3863     At this point you are done and if you don't want to reuse the font atlas you
3864     can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
3865     memory. Finally if you don't use the font atlas and any of it's fonts anymore
3866     you need to call `nk_font_atlas_clear` to free all memory still being used.
3867 
3868         struct nk_font_atlas atlas;
3869         nk_font_atlas_init_default(&atlas);
3870         nk_font_atlas_begin(&atlas);
3871         nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
3872         nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
3873         const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
3874         nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
3875 
3876         struct nk_context ctx;
3877         nk_init_default(&ctx, &font->handle);
3878         while (1) {
3879 
3880         }
3881         nk_font_atlas_clear(&atlas);
3882 
3883     The font baker API is probably the most complex API inside this library and
3884     I would suggest reading some of my examples `example/` to get a grip on how
3885     to use the font atlas. There are a number of details I left out. For example
3886     how to merge fonts, configure a font with `nk_font_config` to use other languages,
3887     use another texture coordinate format and a lot more:
3888 
3889         struct nk_font_config cfg = nk_font_config(font_pixel_height);
3890         cfg.merge_mode = nk_false or nk_true;
3891         cfg.range = nk_font_korean_glyph_ranges();
3892         cfg.coord_type = NK_COORD_PIXEL;
3893         nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
3894 
3895 */
3896 struct nk_user_font_glyph;
3897 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
3898 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
3899                                     struct nk_user_font_glyph *glyph,
3900                                     nk_rune codepoint, nk_rune next_codepoint);
3901 
3902 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT)
3903 struct nk_user_font_glyph {
3904     struct nk_vec2 uv[2];
3905     /* texture coordinates */
3906     struct nk_vec2 offset;
3907     /* offset between top left and glyph */
3908     float width, height;
3909     /* size of the glyph  */
3910     float xadvance;
3911     /* offset to the next glyph */
3912 };
3913 #endif
3914 
3915 struct nk_user_font {
3916     nk_handle userdata;
3917     /* user provided font handle */
3918     float height;
3919     /* max height of the font */
3920     nk_text_width_f width;
3921     /* font string width in pixel callback */
3922 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3923     nk_query_font_glyph_f query;
3924     /* font glyph callback to query drawing info */
3925     nk_handle texture;
3926     /* texture handle to the used font atlas or texture */
3927 #endif
3928 };
3929 
3930 #ifdef NK_INCLUDE_FONT_BAKING
3931 enum nk_font_coord_type {
3932     NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
3933     NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
3934 };
3935 
3936 struct nk_font;
3937 struct nk_baked_font {
3938     float height;
3939     /* height of the font  */
3940     float ascent, descent;
3941     /* font glyphs ascent and descent  */
3942     nk_rune glyph_offset;
3943     /* glyph array offset inside the font glyph baking output array  */
3944     nk_rune glyph_count;
3945     /* number of glyphs of this font inside the glyph baking array output */
3946     const nk_rune *ranges;
3947     /* font codepoint ranges as pairs of (from/to) and 0 as last element */
3948 };
3949 
3950 struct nk_font_config {
3951     struct nk_font_config *next;
3952     /* NOTE: only used internally */
3953     void *ttf_blob;
3954     /* pointer to loaded TTF file memory block.
3955      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
3956     nk_size ttf_size;
3957     /* size of the loaded TTF file memory block
3958      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
3959 
3960     unsigned char ttf_data_owned_by_atlas;
3961     /* used inside font atlas: default to: 0*/
3962     unsigned char merge_mode;
3963     /* merges this font into the last font */
3964     unsigned char pixel_snap;
3965     /* align every character to pixel boundary (if true set oversample (1,1)) */
3966     unsigned char oversample_v, oversample_h;
3967     /* rasterize at hight quality for sub-pixel position */
3968     unsigned char padding[3];
3969 
3970     float size;
3971     /* baked pixel height of the font */
3972     enum nk_font_coord_type coord_type;
3973     /* texture coordinate format with either pixel or UV coordinates */
3974     struct nk_vec2 spacing;
3975     /* extra pixel spacing between glyphs  */
3976     const nk_rune *range;
3977     /* list of unicode ranges (2 values per range, zero terminated) */
3978     struct nk_baked_font *font;
3979     /* font to setup in the baking process: NOTE: not needed for font atlas */
3980     nk_rune fallback_glyph;
3981     /* fallback glyph to use if a given rune is not found */
3982     struct nk_font_config *n;
3983     struct nk_font_config *p;
3984 };
3985 
3986 struct nk_font_glyph {
3987     nk_rune codepoint;
3988     float xadvance;
3989     float x0, y0, x1, y1, w, h;
3990     float u0, v0, u1, v1;
3991 };
3992 
3993 struct nk_font {
3994     struct nk_font *next;
3995     struct nk_user_font handle;
3996     struct nk_baked_font info;
3997     float scale;
3998     struct nk_font_glyph *glyphs;
3999     const struct nk_font_glyph *fallback;
4000     nk_rune fallback_codepoint;
4001     nk_handle texture;
4002     struct nk_font_config *config;
4003 };
4004 
4005 enum nk_font_atlas_format {
4006     NK_FONT_ATLAS_ALPHA8,
4007     NK_FONT_ATLAS_RGBA32
4008 };
4009 
4010 struct nk_font_atlas {
4011     void *pixel;
4012     int tex_width;
4013     int tex_height;
4014 
4015     struct nk_allocator permanent;
4016     struct nk_allocator temporary;
4017 
4018     struct nk_recti custom;
4019     struct nk_cursor cursors[NK_CURSOR_COUNT];
4020 
4021     int glyph_count;
4022     struct nk_font_glyph *glyphs;
4023     struct nk_font *default_font;
4024     struct nk_font *fonts;
4025     struct nk_font_config *config;
4026     int font_num;
4027 };
4028 
4029 /* some language glyph codepoint ranges */
4030 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
4031 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
4032 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
4033 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
4034 
4035 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4036 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
4037 #endif
4038 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
4039 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
4040 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
4041 NK_API struct nk_font_config nk_font_config(float pixel_height);
4042 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
4043 #ifdef NK_INCLUDE_DEFAULT_FONT
4044 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
4045 #endif
4046 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);
4047 #ifdef NK_INCLUDE_STANDARD_IO
4048 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*);
4049 #endif
4050 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*);
4051 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);
4052 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
4053 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
4054 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
4055 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
4056 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
4057 
4058 #endif
4059 
4060 /* ==============================================================
4061  *
4062  *                          MEMORY BUFFER
4063  *
4064  * ===============================================================*/
4065 /*  A basic (double)-buffer with linear allocation and resetting as only
4066     freeing policy. The buffer's main purpose is to control all memory management
4067     inside the GUI toolkit and still leave memory control as much as possible in
4068     the hand of the user while also making sure the library is easy to use if
4069     not as much control is needed.
4070     In general all memory inside this library can be provided from the user in
4071     three different ways.
4072 
4073     The first way and the one providing most control is by just passing a fixed
4074     size memory block. In this case all control lies in the hand of the user
4075     since he can exactly control where the memory comes from and how much memory
4076     the library should consume. Of course using the fixed size API removes the
4077     ability to automatically resize a buffer if not enough memory is provided so
4078     you have to take over the resizing. While being a fixed sized buffer sounds
4079     quite limiting, it is very effective in this library since the actual memory
4080     consumption is quite stable and has a fixed upper bound for a lot of cases.
4081 
4082     If you don't want to think about how much memory the library should allocate
4083     at all time or have a very dynamic UI with unpredictable memory consumption
4084     habits but still want control over memory allocation you can use the dynamic
4085     allocator based API. The allocator consists of two callbacks for allocating
4086     and freeing memory and optional userdata so you can plugin your own allocator.
4087 
4088     The final and easiest way can be used by defining
4089     NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
4090     allocation functions malloc and free and takes over complete control over
4091     memory in this library.
4092 */
4093 struct nk_memory_status {
4094     void *memory;
4095     unsigned int type;
4096     nk_size size;
4097     nk_size allocated;
4098     nk_size needed;
4099     nk_size calls;
4100 };
4101 
4102 enum nk_allocation_type {
4103     NK_BUFFER_FIXED,
4104     NK_BUFFER_DYNAMIC
4105 };
4106 
4107 enum nk_buffer_allocation_type {
4108     NK_BUFFER_FRONT,
4109     NK_BUFFER_BACK,
4110     NK_BUFFER_MAX
4111 };
4112 
4113 struct nk_buffer_marker {
4114     int active;
4115     nk_size offset;
4116 };
4117 
4118 struct nk_memory {void *ptr;nk_size size;};
4119 struct nk_buffer {
4120     struct nk_buffer_marker marker[NK_BUFFER_MAX];
4121     /* buffer marker to free a buffer to a certain offset */
4122     struct nk_allocator pool;
4123     /* allocator callback for dynamic buffers */
4124     enum nk_allocation_type type;
4125     /* memory management type */
4126     struct nk_memory memory;
4127     /* memory and size of the current memory block */
4128     float grow_factor;
4129     /* growing factor for dynamic memory management */
4130     nk_size allocated;
4131     /* total amount of memory allocated */
4132     nk_size needed;
4133     /* totally consumed memory given that enough memory is present */
4134     nk_size calls;
4135     /* number of allocation calls */
4136     nk_size size;
4137     /* current size of the buffer */
4138 };
4139 
4140 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4141 NK_API void nk_buffer_init_default(struct nk_buffer*);
4142 #endif
4143 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
4144 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
4145 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
4146 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
4147 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
4148 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type);
4149 NK_API void nk_buffer_clear(struct nk_buffer*);
4150 NK_API void nk_buffer_free(struct nk_buffer*);
4151 NK_API void *nk_buffer_memory(struct nk_buffer*);
4152 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
4153 NK_API nk_size nk_buffer_total(struct nk_buffer*);
4154 
4155 /* ==============================================================
4156  *
4157  *                          STRING
4158  *
4159  * ===============================================================*/
4160 /*  Basic string buffer which is only used in context with the text editor
4161  *  to manage and manipulate dynamic or fixed size string content. This is _NOT_
4162  *  the default string handling method. The only instance you should have any contact
4163  *  with this API is if you interact with an `nk_text_edit` object inside one of the
4164  *  copy and paste functions and even there only for more advanced cases. */
4165 struct nk_str {
4166     struct nk_buffer buffer;
4167     int len; /* in codepoints/runes/glyphs */
4168 };
4169 
4170 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4171 NK_API void nk_str_init_default(struct nk_str*);
4172 #endif
4173 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
4174 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
4175 NK_API void nk_str_clear(struct nk_str*);
4176 NK_API void nk_str_free(struct nk_str*);
4177 
4178 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
4179 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
4180 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
4181 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
4182 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
4183 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
4184 
4185 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
4186 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
4187 
4188 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
4189 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
4190 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
4191 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
4192 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
4193 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
4194 
4195 NK_API void nk_str_remove_chars(struct nk_str*, int len);
4196 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
4197 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
4198 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
4199 
4200 NK_API char *nk_str_at_char(struct nk_str*, int pos);
4201 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
4202 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
4203 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
4204 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
4205 
4206 NK_API char *nk_str_get(struct nk_str*);
4207 NK_API const char *nk_str_get_const(const struct nk_str*);
4208 NK_API int nk_str_len(struct nk_str*);
4209 NK_API int nk_str_len_char(struct nk_str*);
4210 
4211 /*===============================================================
4212  *
4213  *                      TEXT EDITOR
4214  *
4215  * ===============================================================*/
4216 /* Editing text in this library is handled by either `nk_edit_string` or
4217  * `nk_edit_buffer`. But like almost everything in this library there are multiple
4218  * ways of doing it and a balance between control and ease of use with memory
4219  * as well as functionality controlled by flags.
4220  *
4221  * This library generally allows three different levels of memory control:
4222  * First of is the most basic way of just providing a simple char array with
4223  * string length. This method is probably the easiest way of handling simple
4224  * user text input. Main upside is complete control over memory while the biggest
4225  * downside in comparison with the other two approaches is missing undo/redo.
4226  *
4227  * For UIs that require undo/redo the second way was created. It is based on
4228  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
4229  * This is mainly useful if you want something more like a text editor but don't want
4230  * to have a dynamically growing buffer.
4231  *
4232  * The final way is using a dynamically growing nk_text_edit struct, which
4233  * has both a default version if you don't care where memory comes from and an
4234  * allocator version if you do. While the text editor is quite powerful for its
4235  * complexity I would not recommend editing gigabytes of data with it.
4236  * It is rather designed for uses cases which make sense for a GUI library not for
4237  * an full blown text editor.
4238  */
4239 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
4240 #define NK_TEXTEDIT_UNDOSTATECOUNT     99
4241 #endif
4242 
4243 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
4244 #define NK_TEXTEDIT_UNDOCHARCOUNT      999
4245 #endif
4246 
4247 struct nk_text_edit;
4248 struct nk_clipboard {
4249     nk_handle userdata;
4250     nk_plugin_paste paste;
4251     nk_plugin_copy copy;
4252 };
4253 
4254 struct nk_text_undo_record {
4255    int where;
4256    short insert_length;
4257    short delete_length;
4258    short char_storage;
4259 };
4260 
4261 struct nk_text_undo_state {
4262    struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT];
4263    nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT];
4264    short undo_point;
4265    short redo_point;
4266    short undo_char_point;
4267    short redo_char_point;
4268 };
4269 
4270 enum nk_text_edit_type {
4271     NK_TEXT_EDIT_SINGLE_LINE,
4272     NK_TEXT_EDIT_MULTI_LINE
4273 };
4274 
4275 enum nk_text_edit_mode {
4276     NK_TEXT_EDIT_MODE_VIEW,
4277     NK_TEXT_EDIT_MODE_INSERT,
4278     NK_TEXT_EDIT_MODE_REPLACE
4279 };
4280 
4281 struct nk_text_edit {
4282     struct nk_clipboard clip;
4283     struct nk_str string;
4284     nk_plugin_filter filter;
4285     struct nk_vec2 scrollbar;
4286 
4287     int cursor;
4288     int select_start;
4289     int select_end;
4290     unsigned char mode;
4291     unsigned char cursor_at_end_of_line;
4292     unsigned char initialized;
4293     unsigned char has_preferred_x;
4294     unsigned char single_line;
4295     unsigned char active;
4296     unsigned char padding1;
4297     float preferred_x;
4298     struct nk_text_undo_state undo;
4299 };
4300 
4301 /* filter function */
4302 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
4303 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
4304 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
4305 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
4306 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
4307 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
4308 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
4309 
4310 /* text editor */
4311 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4312 NK_API void nk_textedit_init_default(struct nk_text_edit*);
4313 #endif
4314 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
4315 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
4316 NK_API void nk_textedit_free(struct nk_text_edit*);
4317 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
4318 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
4319 NK_API void nk_textedit_delete_selection(struct nk_text_edit*);
4320 NK_API void nk_textedit_select_all(struct nk_text_edit*);
4321 NK_API int nk_textedit_cut(struct nk_text_edit*);
4322 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
4323 NK_API void nk_textedit_undo(struct nk_text_edit*);
4324 NK_API void nk_textedit_redo(struct nk_text_edit*);
4325 
4326 /* ===============================================================
4327  *
4328  *                          DRAWING
4329  *
4330  * ===============================================================*/
4331 /*  This library was designed to be render backend agnostic so it does
4332     not draw anything to screen. Instead all drawn shapes, widgets
4333     are made of, are buffered into memory and make up a command queue.
4334     Each frame therefore fills the command buffer with draw commands
4335     that then need to be executed by the user and his own render backend.
4336     After that the command buffer needs to be cleared and a new frame can be
4337     started. It is probably important to note that the command buffer is the main
4338     drawing API and the optional vertex buffer API only takes this format and
4339     converts it into a hardware accessible format.
4340 
4341     To use the command queue to draw your own widgets you can access the
4342     command buffer of each window by calling `nk_window_get_canvas` after
4343     previously having called `nk_begin`:
4344 
4345         void draw_red_rectangle_widget(struct nk_context *ctx)
4346         {
4347             struct nk_command_buffer *canvas;
4348             struct nk_input *input = &ctx->input;
4349             canvas = nk_window_get_canvas(ctx);
4350 
4351             struct nk_rect space;
4352             enum nk_widget_layout_states state;
4353             state = nk_widget(&space, ctx);
4354             if (!state) return;
4355 
4356             if (state != NK_WIDGET_ROM)
4357                 update_your_widget_by_user_input(...);
4358             nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
4359         }
4360 
4361         if (nk_begin(...)) {
4362             nk_layout_row_dynamic(ctx, 25, 1);
4363             draw_red_rectangle_widget(ctx);
4364         }
4365         nk_end(..)
4366 
4367     Important to know if you want to create your own widgets is the `nk_widget`
4368     call. It allocates space on the panel reserved for this widget to be used,
4369     but also returns the state of the widget space. If your widget is not seen and does
4370     not have to be updated it is '0' and you can just return. If it only has
4371     to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
4372     update and draw your widget. The reason for separating is to only draw and
4373     update what is actually necessary which is crucial for performance.
4374 */
4375 enum nk_command_type {
4376     NK_COMMAND_NOP,
4377     NK_COMMAND_SCISSOR,
4378     NK_COMMAND_LINE,
4379     NK_COMMAND_CURVE,
4380     NK_COMMAND_RECT,
4381     NK_COMMAND_RECT_FILLED,
4382     NK_COMMAND_RECT_MULTI_COLOR,
4383     NK_COMMAND_CIRCLE,
4384     NK_COMMAND_CIRCLE_FILLED,
4385     NK_COMMAND_ARC,
4386     NK_COMMAND_ARC_FILLED,
4387     NK_COMMAND_TRIANGLE,
4388     NK_COMMAND_TRIANGLE_FILLED,
4389     NK_COMMAND_POLYGON,
4390     NK_COMMAND_POLYGON_FILLED,
4391     NK_COMMAND_POLYLINE,
4392     NK_COMMAND_TEXT,
4393     NK_COMMAND_IMAGE,
4394     NK_COMMAND_CUSTOM
4395 };
4396 
4397 /* command base and header of every command inside the buffer */
4398 struct nk_command {
4399     enum nk_command_type type;
4400     nk_size next;
4401 #ifdef NK_INCLUDE_COMMAND_USERDATA
4402     nk_handle userdata;
4403 #endif
4404 };
4405 
4406 struct nk_command_scissor {
4407     struct nk_command header;
4408     short x, y;
4409     unsigned short w, h;
4410 };
4411 
4412 struct nk_command_line {
4413     struct nk_command header;
4414     unsigned short line_thickness;
4415     struct nk_vec2i begin;
4416     struct nk_vec2i end;
4417     struct nk_color color;
4418 };
4419 
4420 struct nk_command_curve {
4421     struct nk_command header;
4422     unsigned short line_thickness;
4423     struct nk_vec2i begin;
4424     struct nk_vec2i end;
4425     struct nk_vec2i ctrl[2];
4426     struct nk_color color;
4427 };
4428 
4429 struct nk_command_rect {
4430     struct nk_command header;
4431     unsigned short rounding;
4432     unsigned short line_thickness;
4433     short x, y;
4434     unsigned short w, h;
4435     struct nk_color color;
4436 };
4437 
4438 struct nk_command_rect_filled {
4439     struct nk_command header;
4440     unsigned short rounding;
4441     short x, y;
4442     unsigned short w, h;
4443     struct nk_color color;
4444 };
4445 
4446 struct nk_command_rect_multi_color {
4447     struct nk_command header;
4448     short x, y;
4449     unsigned short w, h;
4450     struct nk_color left;
4451     struct nk_color top;
4452     struct nk_color bottom;
4453     struct nk_color right;
4454 };
4455 
4456 struct nk_command_triangle {
4457     struct nk_command header;
4458     unsigned short line_thickness;
4459     struct nk_vec2i a;
4460     struct nk_vec2i b;
4461     struct nk_vec2i c;
4462     struct nk_color color;
4463 };
4464 
4465 struct nk_command_triangle_filled {
4466     struct nk_command header;
4467     struct nk_vec2i a;
4468     struct nk_vec2i b;
4469     struct nk_vec2i c;
4470     struct nk_color color;
4471 };
4472 
4473 struct nk_command_circle {
4474     struct nk_command header;
4475     short x, y;
4476     unsigned short line_thickness;
4477     unsigned short w, h;
4478     struct nk_color color;
4479 };
4480 
4481 struct nk_command_circle_filled {
4482     struct nk_command header;
4483     short x, y;
4484     unsigned short w, h;
4485     struct nk_color color;
4486 };
4487 
4488 struct nk_command_arc {
4489     struct nk_command header;
4490     short cx, cy;
4491     unsigned short r;
4492     unsigned short line_thickness;
4493     float a[2];
4494     struct nk_color color;
4495 };
4496 
4497 struct nk_command_arc_filled {
4498     struct nk_command header;
4499     short cx, cy;
4500     unsigned short r;
4501     float a[2];
4502     struct nk_color color;
4503 };
4504 
4505 struct nk_command_polygon {
4506     struct nk_command header;
4507     struct nk_color color;
4508     unsigned short line_thickness;
4509     unsigned short point_count;
4510     struct nk_vec2i points[1];
4511 };
4512 
4513 struct nk_command_polygon_filled {
4514     struct nk_command header;
4515     struct nk_color color;
4516     unsigned short point_count;
4517     struct nk_vec2i points[1];
4518 };
4519 
4520 struct nk_command_polyline {
4521     struct nk_command header;
4522     struct nk_color color;
4523     unsigned short line_thickness;
4524     unsigned short point_count;
4525     struct nk_vec2i points[1];
4526 };
4527 
4528 struct nk_command_image {
4529     struct nk_command header;
4530     short x, y;
4531     unsigned short w, h;
4532     struct nk_image img;
4533     struct nk_color col;
4534 };
4535 
4536 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
4537     unsigned short w, unsigned short h, nk_handle callback_data);
4538 struct nk_command_custom {
4539     struct nk_command header;
4540     short x, y;
4541     unsigned short w, h;
4542     nk_handle callback_data;
4543     nk_command_custom_callback callback;
4544 };
4545 
4546 struct nk_command_text {
4547     struct nk_command header;
4548     const struct nk_user_font *font;
4549     struct nk_color background;
4550     struct nk_color foreground;
4551     short x, y;
4552     unsigned short w, h;
4553     float height;
4554     int length;
4555     char string[1];
4556 };
4557 
4558 enum nk_command_clipping {
4559     NK_CLIPPING_OFF = nk_false,
4560     NK_CLIPPING_ON = nk_true
4561 };
4562 
4563 struct nk_command_buffer {
4564     struct nk_buffer *base;
4565     struct nk_rect clip;
4566     int use_clipping;
4567     nk_handle userdata;
4568     nk_size begin, end, last;
4569 };
4570 
4571 /* shape outlines */
4572 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);
4573 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
4574 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
4575 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
4576 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);
4577 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
4578 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
4579 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
4580 
4581 /* filled shades */
4582 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
4583 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);
4584 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
4585 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);
4586 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);
4587 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
4588 
4589 /* misc */
4590 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
4591 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);
4592 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
4593 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
4594 
4595 /* ===============================================================
4596  *
4597  *                          INPUT
4598  *
4599  * ===============================================================*/
4600 struct nk_mouse_button {
4601     int down;
4602     unsigned int clicked;
4603     struct nk_vec2 clicked_pos;
4604 };
4605 struct nk_mouse {
4606     struct nk_mouse_button buttons[NK_BUTTON_MAX];
4607     struct nk_vec2 pos;
4608     struct nk_vec2 prev;
4609     struct nk_vec2 delta;
4610     struct nk_vec2 scroll_delta;
4611     unsigned char grab;
4612     unsigned char grabbed;
4613     unsigned char ungrab;
4614 };
4615 
4616 struct nk_key {
4617     int down;
4618     unsigned int clicked;
4619 };
4620 struct nk_keyboard {
4621     struct nk_key keys[NK_KEY_MAX];
4622     char text[NK_INPUT_MAX];
4623     int text_len;
4624 };
4625 
4626 struct nk_input {
4627     struct nk_keyboard keyboard;
4628     struct nk_mouse mouse;
4629 };
4630 
4631 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
4632 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4633 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
4634 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4635 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);
4636 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
4637 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
4638 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
4639 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
4640 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
4641 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
4642 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
4643 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
4644 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
4645 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
4646 
4647 /* ===============================================================
4648  *
4649  *                          DRAW LIST
4650  *
4651  * ===============================================================*/
4652 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4653 /*  The optional vertex buffer draw list provides a 2D drawing context
4654     with antialiasing functionality which takes basic filled or outlined shapes
4655     or a path and outputs vertexes, elements and draw commands.
4656     The actual draw list API is not required to be used directly while using this
4657     library since converting the default library draw command output is done by
4658     just calling `nk_convert` but I decided to still make this library accessible
4659     since it can be useful.
4660 
4661     The draw list is based on a path buffering and polygon and polyline
4662     rendering API which allows a lot of ways to draw 2D content to screen.
4663     In fact it is probably more powerful than needed but allows even more crazy
4664     things than this library provides by default.
4665 */
4666 #ifdef NK_UINT_DRAW_INDEX
4667 typedef nk_uint nk_draw_index;
4668 #else
4669 typedef nk_ushort nk_draw_index;
4670 #endif
4671 enum nk_draw_list_stroke {
4672     NK_STROKE_OPEN = nk_false,
4673     /* build up path has no connection back to the beginning */
4674     NK_STROKE_CLOSED = nk_true
4675     /* build up path has a connection back to the beginning */
4676 };
4677 
4678 enum nk_draw_vertex_layout_attribute {
4679     NK_VERTEX_POSITION,
4680     NK_VERTEX_COLOR,
4681     NK_VERTEX_TEXCOORD,
4682     NK_VERTEX_ATTRIBUTE_COUNT
4683 };
4684 
4685 enum nk_draw_vertex_layout_format {
4686     NK_FORMAT_SCHAR,
4687     NK_FORMAT_SSHORT,
4688     NK_FORMAT_SINT,
4689     NK_FORMAT_UCHAR,
4690     NK_FORMAT_USHORT,
4691     NK_FORMAT_UINT,
4692     NK_FORMAT_FLOAT,
4693     NK_FORMAT_DOUBLE,
4694 
4695 NK_FORMAT_COLOR_BEGIN,
4696     NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
4697     NK_FORMAT_R16G15B16,
4698     NK_FORMAT_R32G32B32,
4699 
4700     NK_FORMAT_R8G8B8A8,
4701     NK_FORMAT_B8G8R8A8,
4702     NK_FORMAT_R16G15B16A16,
4703     NK_FORMAT_R32G32B32A32,
4704     NK_FORMAT_R32G32B32A32_FLOAT,
4705     NK_FORMAT_R32G32B32A32_DOUBLE,
4706 
4707     NK_FORMAT_RGB32,
4708     NK_FORMAT_RGBA32,
4709 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
4710     NK_FORMAT_COUNT
4711 };
4712 
4713 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
4714 struct nk_draw_vertex_layout_element {
4715     enum nk_draw_vertex_layout_attribute attribute;
4716     enum nk_draw_vertex_layout_format format;
4717     nk_size offset;
4718 };
4719 
4720 struct nk_draw_command {
4721     unsigned int elem_count;
4722     /* number of elements in the current draw batch */
4723     struct nk_rect clip_rect;
4724     /* current screen clipping rectangle */
4725     nk_handle texture;
4726     /* current texture to set */
4727 #ifdef NK_INCLUDE_COMMAND_USERDATA
4728     nk_handle userdata;
4729 #endif
4730 };
4731 
4732 struct nk_draw_list {
4733     struct nk_rect clip_rect;
4734     struct nk_vec2 circle_vtx[12];
4735     struct nk_convert_config config;
4736 
4737     struct nk_buffer *buffer;
4738     struct nk_buffer *vertices;
4739     struct nk_buffer *elements;
4740 
4741     unsigned int element_count;
4742     unsigned int vertex_count;
4743     unsigned int cmd_count;
4744     nk_size cmd_offset;
4745 
4746     unsigned int path_count;
4747     unsigned int path_offset;
4748 
4749     enum nk_anti_aliasing line_AA;
4750     enum nk_anti_aliasing shape_AA;
4751 
4752 #ifdef NK_INCLUDE_COMMAND_USERDATA
4753     nk_handle userdata;
4754 #endif
4755 };
4756 
4757 /* draw list */
4758 NK_API void nk_draw_list_init(struct nk_draw_list*);
4759 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);
4760 
4761 /* drawing */
4762 #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))
4763 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
4764 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*);
4765 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
4766 
4767 /* path */
4768 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
4769 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
4770 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);
4771 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);
4772 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
4773 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);
4774 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
4775 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
4776 
4777 /* stroke */
4778 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);
4779 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
4780 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);
4781 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);
4782 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);
4783 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);
4784 
4785 /* fill */
4786 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
4787 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);
4788 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);
4789 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);
4790 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);
4791 
4792 /* misc */
4793 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
4794 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);
4795 #ifdef NK_INCLUDE_COMMAND_USERDATA
4796 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
4797 #endif
4798 
4799 #endif
4800 
4801 /* ===============================================================
4802  *
4803  *                          GUI
4804  *
4805  * ===============================================================*/
4806 enum nk_style_item_type {
4807     NK_STYLE_ITEM_COLOR,
4808     NK_STYLE_ITEM_IMAGE
4809 };
4810 
4811 union nk_style_item_data {
4812     struct nk_image image;
4813     struct nk_color color;
4814 };
4815 
4816 struct nk_style_item {
4817     enum nk_style_item_type type;
4818     union nk_style_item_data data;
4819 };
4820 
4821 struct nk_style_text {
4822     struct nk_color color;
4823     struct nk_vec2 padding;
4824 };
4825 
4826 struct nk_style_button {
4827     /* background */
4828     struct nk_style_item normal;
4829     struct nk_style_item hover;
4830     struct nk_style_item active;
4831     struct nk_color border_color;
4832 
4833     /* text */
4834     struct nk_color text_background;
4835     struct nk_color text_normal;
4836     struct nk_color text_hover;
4837     struct nk_color text_active;
4838     nk_flags text_alignment;
4839 
4840     /* properties */
4841     float border;
4842     float rounding;
4843     struct nk_vec2 padding;
4844     struct nk_vec2 image_padding;
4845     struct nk_vec2 touch_padding;
4846 
4847     /* optional user callbacks */
4848     nk_handle userdata;
4849     void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata);
4850     void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
4851 };
4852 
4853 struct nk_style_toggle {
4854     /* background */
4855     struct nk_style_item normal;
4856     struct nk_style_item hover;
4857     struct nk_style_item active;
4858     struct nk_color border_color;
4859 
4860     /* cursor */
4861     struct nk_style_item cursor_normal;
4862     struct nk_style_item cursor_hover;
4863 
4864     /* text */
4865     struct nk_color text_normal;
4866     struct nk_color text_hover;
4867     struct nk_color text_active;
4868     struct nk_color text_background;
4869     nk_flags text_alignment;
4870 
4871     /* properties */
4872     struct nk_vec2 padding;
4873     struct nk_vec2 touch_padding;
4874     float spacing;
4875     float border;
4876 
4877     /* optional user callbacks */
4878     nk_handle userdata;
4879     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4880     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4881 };
4882 
4883 struct nk_style_selectable {
4884     /* background (inactive) */
4885     struct nk_style_item normal;
4886     struct nk_style_item hover;
4887     struct nk_style_item pressed;
4888 
4889     /* background (active) */
4890     struct nk_style_item normal_active;
4891     struct nk_style_item hover_active;
4892     struct nk_style_item pressed_active;
4893 
4894     /* text color (inactive) */
4895     struct nk_color text_normal;
4896     struct nk_color text_hover;
4897     struct nk_color text_pressed;
4898 
4899     /* text color (active) */
4900     struct nk_color text_normal_active;
4901     struct nk_color text_hover_active;
4902     struct nk_color text_pressed_active;
4903     struct nk_color text_background;
4904     nk_flags text_alignment;
4905 
4906     /* properties */
4907     float rounding;
4908     struct nk_vec2 padding;
4909     struct nk_vec2 touch_padding;
4910     struct nk_vec2 image_padding;
4911 
4912     /* optional user callbacks */
4913     nk_handle userdata;
4914     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4915     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4916 };
4917 
4918 struct nk_style_slider {
4919     /* background */
4920     struct nk_style_item normal;
4921     struct nk_style_item hover;
4922     struct nk_style_item active;
4923     struct nk_color border_color;
4924 
4925     /* background bar */
4926     struct nk_color bar_normal;
4927     struct nk_color bar_hover;
4928     struct nk_color bar_active;
4929     struct nk_color bar_filled;
4930 
4931     /* cursor */
4932     struct nk_style_item cursor_normal;
4933     struct nk_style_item cursor_hover;
4934     struct nk_style_item cursor_active;
4935 
4936     /* properties */
4937     float border;
4938     float rounding;
4939     float bar_height;
4940     struct nk_vec2 padding;
4941     struct nk_vec2 spacing;
4942     struct nk_vec2 cursor_size;
4943 
4944     /* optional buttons */
4945     int show_buttons;
4946     struct nk_style_button inc_button;
4947     struct nk_style_button dec_button;
4948     enum nk_symbol_type inc_symbol;
4949     enum nk_symbol_type dec_symbol;
4950 
4951     /* optional user callbacks */
4952     nk_handle userdata;
4953     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4954     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4955 };
4956 
4957 struct nk_style_progress {
4958     /* background */
4959     struct nk_style_item normal;
4960     struct nk_style_item hover;
4961     struct nk_style_item active;
4962     struct nk_color border_color;
4963 
4964     /* cursor */
4965     struct nk_style_item cursor_normal;
4966     struct nk_style_item cursor_hover;
4967     struct nk_style_item cursor_active;
4968     struct nk_color cursor_border_color;
4969 
4970     /* properties */
4971     float rounding;
4972     float border;
4973     float cursor_border;
4974     float cursor_rounding;
4975     struct nk_vec2 padding;
4976 
4977     /* optional user callbacks */
4978     nk_handle userdata;
4979     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4980     void(*draw_end)(struct nk_command_buffer*, nk_handle);
4981 };
4982 
4983 struct nk_style_scrollbar {
4984     /* background */
4985     struct nk_style_item normal;
4986     struct nk_style_item hover;
4987     struct nk_style_item active;
4988     struct nk_color border_color;
4989 
4990     /* cursor */
4991     struct nk_style_item cursor_normal;
4992     struct nk_style_item cursor_hover;
4993     struct nk_style_item cursor_active;
4994     struct nk_color cursor_border_color;
4995 
4996     /* properties */
4997     float border;
4998     float rounding;
4999     float border_cursor;
5000     float rounding_cursor;
5001     struct nk_vec2 padding;
5002 
5003     /* optional buttons */
5004     int show_buttons;
5005     struct nk_style_button inc_button;
5006     struct nk_style_button dec_button;
5007     enum nk_symbol_type inc_symbol;
5008     enum nk_symbol_type dec_symbol;
5009 
5010     /* optional user callbacks */
5011     nk_handle userdata;
5012     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
5013     void(*draw_end)(struct nk_command_buffer*, nk_handle);
5014 };
5015 
5016 struct nk_style_edit {
5017     /* background */
5018     struct nk_style_item normal;
5019     struct nk_style_item hover;
5020     struct nk_style_item active;
5021     struct nk_color border_color;
5022     struct nk_style_scrollbar scrollbar;
5023 
5024     /* cursor  */
5025     struct nk_color cursor_normal;
5026     struct nk_color cursor_hover;
5027     struct nk_color cursor_text_normal;
5028     struct nk_color cursor_text_hover;
5029 
5030     /* text (unselected) */
5031     struct nk_color text_normal;
5032     struct nk_color text_hover;
5033     struct nk_color text_active;
5034 
5035     /* text (selected) */
5036     struct nk_color selected_normal;
5037     struct nk_color selected_hover;
5038     struct nk_color selected_text_normal;
5039     struct nk_color selected_text_hover;
5040 
5041     /* properties */
5042     float border;
5043     float rounding;
5044     float cursor_size;
5045     struct nk_vec2 scrollbar_size;
5046     struct nk_vec2 padding;
5047     float row_padding;
5048 };
5049 
5050 struct nk_style_property {
5051     /* background */
5052     struct nk_style_item normal;
5053     struct nk_style_item hover;
5054     struct nk_style_item active;
5055     struct nk_color border_color;
5056 
5057     /* text */
5058     struct nk_color label_normal;
5059     struct nk_color label_hover;
5060     struct nk_color label_active;
5061 
5062     /* symbols */
5063     enum nk_symbol_type sym_left;
5064     enum nk_symbol_type sym_right;
5065 
5066     /* properties */
5067     float border;
5068     float rounding;
5069     struct nk_vec2 padding;
5070 
5071     struct nk_style_edit edit;
5072     struct nk_style_button inc_button;
5073     struct nk_style_button dec_button;
5074 
5075     /* optional user callbacks */
5076     nk_handle userdata;
5077     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
5078     void(*draw_end)(struct nk_command_buffer*, nk_handle);
5079 };
5080 
5081 struct nk_style_chart {
5082     /* colors */
5083     struct nk_style_item background;
5084     struct nk_color border_color;
5085     struct nk_color selected_color;
5086     struct nk_color color;
5087 
5088     /* properties */
5089     float border;
5090     float rounding;
5091     struct nk_vec2 padding;
5092 };
5093 
5094 struct nk_style_combo {
5095     /* background */
5096     struct nk_style_item normal;
5097     struct nk_style_item hover;
5098     struct nk_style_item active;
5099     struct nk_color border_color;
5100 
5101     /* label */
5102     struct nk_color label_normal;
5103     struct nk_color label_hover;
5104     struct nk_color label_active;
5105 
5106     /* symbol */
5107     struct nk_color symbol_normal;
5108     struct nk_color symbol_hover;
5109     struct nk_color symbol_active;
5110 
5111     /* button */
5112     struct nk_style_button button;
5113     enum nk_symbol_type sym_normal;
5114     enum nk_symbol_type sym_hover;
5115     enum nk_symbol_type sym_active;
5116 
5117     /* properties */
5118     float border;
5119     float rounding;
5120     struct nk_vec2 content_padding;
5121     struct nk_vec2 button_padding;
5122     struct nk_vec2 spacing;
5123 };
5124 
5125 struct nk_style_tab {
5126     /* background */
5127     struct nk_style_item background;
5128     struct nk_color border_color;
5129     struct nk_color text;
5130 
5131     /* button */
5132     struct nk_style_button tab_maximize_button;
5133     struct nk_style_button tab_minimize_button;
5134     struct nk_style_button node_maximize_button;
5135     struct nk_style_button node_minimize_button;
5136     enum nk_symbol_type sym_minimize;
5137     enum nk_symbol_type sym_maximize;
5138 
5139     /* properties */
5140     float border;
5141     float rounding;
5142     float indent;
5143     struct nk_vec2 padding;
5144     struct nk_vec2 spacing;
5145 };
5146 
5147 enum nk_style_header_align {
5148     NK_HEADER_LEFT,
5149     NK_HEADER_RIGHT
5150 };
5151 struct nk_style_window_header {
5152     /* background */
5153     struct nk_style_item normal;
5154     struct nk_style_item hover;
5155     struct nk_style_item active;
5156 
5157     /* button */
5158     struct nk_style_button close_button;
5159     struct nk_style_button minimize_button;
5160     enum nk_symbol_type close_symbol;
5161     enum nk_symbol_type minimize_symbol;
5162     enum nk_symbol_type maximize_symbol;
5163 
5164     /* title */
5165     struct nk_color label_normal;
5166     struct nk_color label_hover;
5167     struct nk_color label_active;
5168 
5169     /* properties */
5170     enum nk_style_header_align align;
5171     struct nk_vec2 padding;
5172     struct nk_vec2 label_padding;
5173     struct nk_vec2 spacing;
5174 };
5175 
5176 struct nk_style_window {
5177     struct nk_style_window_header header;
5178     struct nk_style_item fixed_background;
5179     struct nk_color background;
5180 
5181     struct nk_color border_color;
5182     struct nk_color popup_border_color;
5183     struct nk_color combo_border_color;
5184     struct nk_color contextual_border_color;
5185     struct nk_color menu_border_color;
5186     struct nk_color group_border_color;
5187     struct nk_color tooltip_border_color;
5188     struct nk_style_item scaler;
5189 
5190     float border;
5191     float combo_border;
5192     float contextual_border;
5193     float menu_border;
5194     float group_border;
5195     float tooltip_border;
5196     float popup_border;
5197     float min_row_height_padding;
5198 
5199     float rounding;
5200     struct nk_vec2 spacing;
5201     struct nk_vec2 scrollbar_size;
5202     struct nk_vec2 min_size;
5203 
5204     struct nk_vec2 padding;
5205     struct nk_vec2 group_padding;
5206     struct nk_vec2 popup_padding;
5207     struct nk_vec2 combo_padding;
5208     struct nk_vec2 contextual_padding;
5209     struct nk_vec2 menu_padding;
5210     struct nk_vec2 tooltip_padding;
5211 };
5212 
5213 struct nk_style {
5214     const struct nk_user_font *font;
5215     const struct nk_cursor *cursors[NK_CURSOR_COUNT];
5216     const struct nk_cursor *cursor_active;
5217     struct nk_cursor *cursor_last;
5218     int cursor_visible;
5219 
5220     struct nk_style_text text;
5221     struct nk_style_button button;
5222     struct nk_style_button contextual_button;
5223     struct nk_style_button menu_button;
5224     struct nk_style_toggle option;
5225     struct nk_style_toggle checkbox;
5226     struct nk_style_selectable selectable;
5227     struct nk_style_slider slider;
5228     struct nk_style_progress progress;
5229     struct nk_style_property property;
5230     struct nk_style_edit edit;
5231     struct nk_style_chart chart;
5232     struct nk_style_scrollbar scrollh;
5233     struct nk_style_scrollbar scrollv;
5234     struct nk_style_tab tab;
5235     struct nk_style_combo combo;
5236     struct nk_style_window window;
5237 };
5238 
5239 NK_API struct nk_style_item nk_style_item_image(struct nk_image img);
5240 NK_API struct nk_style_item nk_style_item_color(struct nk_color);
5241 NK_API struct nk_style_item nk_style_item_hide(void);
5242 
5243 /*==============================================================
5244  *                          PANEL
5245  * =============================================================*/
5246 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
5247 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
5248 #endif
5249 #ifndef NK_CHART_MAX_SLOT
5250 #define NK_CHART_MAX_SLOT 4
5251 #endif
5252 
5253 enum nk_panel_type {
5254     NK_PANEL_NONE       = 0,
5255     NK_PANEL_WINDOW     = NK_FLAG(0),
5256     NK_PANEL_GROUP      = NK_FLAG(1),
5257     NK_PANEL_POPUP      = NK_FLAG(2),
5258     NK_PANEL_CONTEXTUAL = NK_FLAG(4),
5259     NK_PANEL_COMBO      = NK_FLAG(5),
5260     NK_PANEL_MENU       = NK_FLAG(6),
5261     NK_PANEL_TOOLTIP    = NK_FLAG(7)
5262 };
5263 enum nk_panel_set {
5264     NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP,
5265     NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP,
5266     NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP
5267 };
5268 
5269 struct nk_chart_slot {
5270     enum nk_chart_type type;
5271     struct nk_color color;
5272     struct nk_color highlight;
5273     float min, max, range;
5274     int count;
5275     struct nk_vec2 last;
5276     int index;
5277 };
5278 
5279 struct nk_chart {
5280     int slot;
5281     float x, y, w, h;
5282     struct nk_chart_slot slots[NK_CHART_MAX_SLOT];
5283 };
5284 
5285 enum nk_panel_row_layout_type {
5286     NK_LAYOUT_DYNAMIC_FIXED = 0,
5287     NK_LAYOUT_DYNAMIC_ROW,
5288     NK_LAYOUT_DYNAMIC_FREE,
5289     NK_LAYOUT_DYNAMIC,
5290     NK_LAYOUT_STATIC_FIXED,
5291     NK_LAYOUT_STATIC_ROW,
5292     NK_LAYOUT_STATIC_FREE,
5293     NK_LAYOUT_STATIC,
5294     NK_LAYOUT_TEMPLATE,
5295     NK_LAYOUT_COUNT
5296 };
5297 struct nk_row_layout {
5298     enum nk_panel_row_layout_type type;
5299     int index;
5300     float height;
5301     float min_height;
5302     int columns;
5303     const float *ratio;
5304     float item_width;
5305     float item_height;
5306     float item_offset;
5307     float filled;
5308     struct nk_rect item;
5309     int tree_depth;
5310     float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS];
5311 };
5312 
5313 struct nk_popup_buffer {
5314     nk_size begin;
5315     nk_size parent;
5316     nk_size last;
5317     nk_size end;
5318     int active;
5319 };
5320 
5321 struct nk_menu_state {
5322     float x, y, w, h;
5323     struct nk_scroll offset;
5324 };
5325 
5326 struct nk_panel {
5327     enum nk_panel_type type;
5328     nk_flags flags;
5329     struct nk_rect bounds;
5330     nk_uint *offset_x;
5331     nk_uint *offset_y;
5332     float at_x, at_y, max_x;
5333     float footer_height;
5334     float header_height;
5335     float border;
5336     unsigned int has_scrolling;
5337     struct nk_rect clip;
5338     struct nk_menu_state menu;
5339     struct nk_row_layout row;
5340     struct nk_chart chart;
5341     struct nk_command_buffer *buffer;
5342     struct nk_panel *parent;
5343 };
5344 
5345 /*==============================================================
5346  *                          WINDOW
5347  * =============================================================*/
5348 #ifndef NK_WINDOW_MAX_NAME
5349 #define NK_WINDOW_MAX_NAME 64
5350 #endif
5351 
5352 struct nk_table;
5353 enum nk_window_flags {
5354     NK_WINDOW_PRIVATE       = NK_FLAG(11),
5355     NK_WINDOW_DYNAMIC       = NK_WINDOW_PRIVATE,
5356     /* special window type growing up in height while being filled to a certain maximum height */
5357     NK_WINDOW_ROM           = NK_FLAG(12),
5358     /* sets window widgets into a read only mode and does not allow input changes */
5359     NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT,
5360     /* prevents all interaction caused by input to either window or widgets inside */
5361     NK_WINDOW_HIDDEN        = NK_FLAG(13),
5362     /* Hides window and stops any window interaction and drawing */
5363     NK_WINDOW_CLOSED        = NK_FLAG(14),
5364     /* Directly closes and frees the window at the end of the frame */
5365     NK_WINDOW_MINIMIZED     = NK_FLAG(15),
5366     /* marks the window as minimized */
5367     NK_WINDOW_REMOVE_ROM    = NK_FLAG(16)
5368     /* Removes read only mode at the end of the window */
5369 };
5370 
5371 struct nk_popup_state {
5372     struct nk_window *win;
5373     enum nk_panel_type type;
5374     struct nk_popup_buffer buf;
5375     nk_hash name;
5376     int active;
5377     unsigned combo_count;
5378     unsigned con_count, con_old;
5379     unsigned active_con;
5380     struct nk_rect header;
5381 };
5382 
5383 struct nk_edit_state {
5384     nk_hash name;
5385     unsigned int seq;
5386     unsigned int old;
5387     int active, prev;
5388     int cursor;
5389     int sel_start;
5390     int sel_end;
5391     struct nk_scroll scrollbar;
5392     unsigned char mode;
5393     unsigned char single_line;
5394 };
5395 
5396 struct nk_property_state {
5397     int active, prev;
5398     char buffer[NK_MAX_NUMBER_BUFFER];
5399     int length;
5400     int cursor;
5401     int select_start;
5402     int select_end;
5403     nk_hash name;
5404     unsigned int seq;
5405     unsigned int old;
5406     int state;
5407 };
5408 
5409 struct nk_window {
5410     unsigned int seq;
5411     nk_hash name;
5412     char name_string[NK_WINDOW_MAX_NAME];
5413     nk_flags flags;
5414 
5415     struct nk_rect bounds;
5416     struct nk_scroll scrollbar;
5417     struct nk_command_buffer buffer;
5418     struct nk_panel *layout;
5419     float scrollbar_hiding_timer;
5420 
5421     /* persistent widget state */
5422     struct nk_property_state property;
5423     struct nk_popup_state popup;
5424     struct nk_edit_state edit;
5425     unsigned int scrolled;
5426 
5427     struct nk_table *tables;
5428     unsigned int table_count;
5429 
5430     /* window list hooks */
5431     struct nk_window *next;
5432     struct nk_window *prev;
5433     struct nk_window *parent;
5434 };
5435 
5436 /*==============================================================
5437  *                          STACK
5438  * =============================================================*/
5439 /* The style modifier stack can be used to temporarily change a
5440  * property inside `nk_style`. For example if you want a special
5441  * red button you can temporarily push the old button color onto a stack
5442  * draw the button with a red color and then you just pop the old color
5443  * back from the stack:
5444  *
5445  *      nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
5446  *      nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
5447  *      nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
5448  *      nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
5449  *
5450  *      nk_button(...);
5451  *
5452  *      nk_style_pop_style_item(ctx);
5453  *      nk_style_pop_style_item(ctx);
5454  *      nk_style_pop_style_item(ctx);
5455  *      nk_style_pop_vec2(ctx);
5456  *
5457  * Nuklear has a stack for style_items, float properties, vector properties,
5458  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
5459  * which can be changed at compile time.
5460  */
5461 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
5462 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
5463 #endif
5464 
5465 #ifndef NK_FONT_STACK_SIZE
5466 #define NK_FONT_STACK_SIZE 8
5467 #endif
5468 
5469 #ifndef NK_STYLE_ITEM_STACK_SIZE
5470 #define NK_STYLE_ITEM_STACK_SIZE 16
5471 #endif
5472 
5473 #ifndef NK_FLOAT_STACK_SIZE
5474 #define NK_FLOAT_STACK_SIZE 32
5475 #endif
5476 
5477 #ifndef NK_VECTOR_STACK_SIZE
5478 #define NK_VECTOR_STACK_SIZE 16
5479 #endif
5480 
5481 #ifndef NK_FLAGS_STACK_SIZE
5482 #define NK_FLAGS_STACK_SIZE 32
5483 #endif
5484 
5485 #ifndef NK_COLOR_STACK_SIZE
5486 #define NK_COLOR_STACK_SIZE 32
5487 #endif
5488 
5489 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
5490     struct nk_config_stack_##name##_element {\
5491         prefix##_##type *address;\
5492         prefix##_##type old_value;\
5493     }
5494 #define NK_CONFIG_STACK(type,size)\
5495     struct nk_config_stack_##type {\
5496         int head;\
5497         struct nk_config_stack_##type##_element elements[size];\
5498     }
5499 
5500 #define nk_float float
5501 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
5502 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
5503 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
5504 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags);
5505 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
5506 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
5507 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
5508 
5509 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE);
5510 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE);
5511 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE);
5512 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE);
5513 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE);
5514 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE);
5515 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE);
5516 
5517 struct nk_configuration_stacks {
5518     struct nk_config_stack_style_item style_items;
5519     struct nk_config_stack_float floats;
5520     struct nk_config_stack_vec2 vectors;
5521     struct nk_config_stack_flags flags;
5522     struct nk_config_stack_color colors;
5523     struct nk_config_stack_user_font fonts;
5524     struct nk_config_stack_button_behavior button_behaviors;
5525 };
5526 
5527 /*==============================================================
5528  *                          CONTEXT
5529  * =============================================================*/
5530 #define NK_VALUE_PAGE_CAPACITY \
5531     (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
5532 
5533 struct nk_table {
5534     unsigned int seq;
5535     unsigned int size;
5536     nk_hash keys[NK_VALUE_PAGE_CAPACITY];
5537     nk_uint values[NK_VALUE_PAGE_CAPACITY];
5538     struct nk_table *next, *prev;
5539 };
5540 
5541 union nk_page_data {
5542     struct nk_table tbl;
5543     struct nk_panel pan;
5544     struct nk_window win;
5545 };
5546 
5547 struct nk_page_element {
5548     union nk_page_data data;
5549     struct nk_page_element *next;
5550     struct nk_page_element *prev;
5551 };
5552 
5553 struct nk_page {
5554     unsigned int size;
5555     struct nk_page *next;
5556     struct nk_page_element win[1];
5557 };
5558 
5559 struct nk_pool {
5560     struct nk_allocator alloc;
5561     enum nk_allocation_type type;
5562     unsigned int page_count;
5563     struct nk_page *pages;
5564     struct nk_page_element *freelist;
5565     unsigned capacity;
5566     nk_size size;
5567     nk_size cap;
5568 };
5569 
5570 struct nk_context {
5571 /* public: can be accessed freely */
5572     struct nk_input input;
5573     struct nk_style style;
5574     struct nk_buffer memory;
5575     struct nk_clipboard clip;
5576     nk_flags last_widget_state;
5577     enum nk_button_behavior button_behavior;
5578     struct nk_configuration_stacks stacks;
5579     float delta_time_seconds;
5580 
5581 /* private:
5582     should only be accessed if you
5583     know what you are doing */
5584 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
5585     struct nk_draw_list draw_list;
5586 #endif
5587 #ifdef NK_INCLUDE_COMMAND_USERDATA
5588     nk_handle userdata;
5589 #endif
5590     /* text editor objects are quite big because of an internal
5591      * undo/redo stack. Therefore it does not make sense to have one for
5592      * each window for temporary use cases, so I only provide *one* instance
5593      * for all windows. This works because the content is cleared anyway */
5594     struct nk_text_edit text_edit;
5595     /* draw buffer used for overlay drawing operation like cursor */
5596     struct nk_command_buffer overlay;
5597 
5598     /* windows */
5599     int build;
5600     int use_pool;
5601     struct nk_pool pool;
5602     struct nk_window *begin;
5603     struct nk_window *end;
5604     struct nk_window *active;
5605     struct nk_window *current;
5606     struct nk_page_element *freelist;
5607     unsigned int count;
5608     unsigned int seq;
5609 };
5610 
5611 /* ==============================================================
5612  *                          MATH
5613  * =============================================================== */
5614 #define NK_PI 3.141592654f
5615 #define NK_UTF_INVALID 0xFFFD
5616 #define NK_MAX_FLOAT_PRECISION 2
5617 
5618 #define NK_UNUSED(x) ((void)(x))
5619 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
5620 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
5621 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
5622 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
5623 #define NK_INBOX(px, py, x, y, w, h)\
5624     (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
5625 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
5626     (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
5627 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
5628     (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
5629 
5630 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
5631 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
5632 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
5633 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
5634 
5635 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
5636 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
5637 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
5638 
5639 /* ==============================================================
5640  *                          ALIGNMENT
5641  * =============================================================== */
5642 /* Pointer to Integer type conversion for pointer alignment */
5643 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
5644 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
5645 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
5646 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
5647 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
5648 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
5649 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
5650 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
5651 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
5652 #else /* generates warning but works */
5653 # define NK_UINT_TO_PTR(x) ((void*)(x))
5654 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
5655 #endif
5656 
5657 #define NK_ALIGN_PTR(x, mask)\
5658     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
5659 #define NK_ALIGN_PTR_BACK(x, mask)\
5660     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
5661 
5662 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
5663 #define NK_CONTAINER_OF(ptr,type,member)\
5664     (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
5665 
5666 #ifdef __cplusplus
5667 }
5668 #endif
5669 
5670 #ifdef __cplusplus
5671 template<typename T> struct nk_alignof;
5672 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
5673 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
5674 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
5675     diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
5676 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
5677 #elif defined(_MSC_VER)
5678 #define NK_ALIGNOF(t) (__alignof(t))
5679 #else
5680 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
5681 #endif
5682 
5683 #endif /* NK_NUKLEAR_H_ */
5684 
5685 #ifdef NK_IMPLEMENTATION
5686 
5687 #ifndef NK_INTERNAL_H
5688 #define NK_INTERNAL_H
5689 
5690 #ifndef NK_POOL_DEFAULT_CAPACITY
5691 #define NK_POOL_DEFAULT_CAPACITY 16
5692 #endif
5693 
5694 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
5695 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
5696 #endif
5697 
5698 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
5699 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
5700 #endif
5701 
5702 /* standard library headers */
5703 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5704 #include <stdlib.h> /* malloc, free */
5705 #endif
5706 #ifdef NK_INCLUDE_STANDARD_IO
5707 #include <stdio.h> /* fopen, fclose,... */
5708 #endif
5709 #ifndef NK_ASSERT
5710 #include <assert.h>
5711 #define NK_ASSERT(expr) assert(expr)
5712 #endif
5713 
5714 #ifndef NK_MEMSET
5715 #define NK_MEMSET nk_memset
5716 #endif
5717 #ifndef NK_MEMCPY
5718 #define NK_MEMCPY nk_memcopy
5719 #endif
5720 #ifndef NK_SQRT
5721 #define NK_SQRT nk_sqrt
5722 #endif
5723 #ifndef NK_SIN
5724 #define NK_SIN nk_sin
5725 #endif
5726 #ifndef NK_COS
5727 #define NK_COS nk_cos
5728 #endif
5729 #ifndef NK_STRTOD
5730 #define NK_STRTOD nk_strtod
5731 #endif
5732 #ifndef NK_DTOA
5733 #define NK_DTOA nk_dtoa
5734 #endif
5735 
5736 #define NK_DEFAULT (-1)
5737 
5738 #ifndef NK_VSNPRINTF
5739 /* If your compiler does support `vsnprintf` I would highly recommend
5740  * defining this to vsnprintf instead since `vsprintf` is basically
5741  * unbelievable unsafe and should *NEVER* be used. But I have to support
5742  * it since C89 only provides this unsafe version. */
5743   #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
5744       (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
5745       (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
5746       (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
5747        defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
5748       #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
5749   #else
5750     #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
5751   #endif
5752 #endif
5753 
5754 #define NK_SCHAR_MIN (-127)
5755 #define NK_SCHAR_MAX 127
5756 #define NK_UCHAR_MIN 0
5757 #define NK_UCHAR_MAX 256
5758 #define NK_SSHORT_MIN (-32767)
5759 #define NK_SSHORT_MAX 32767
5760 #define NK_USHORT_MIN 0
5761 #define NK_USHORT_MAX 65535
5762 #define NK_SINT_MIN (-2147483647)
5763 #define NK_SINT_MAX 2147483647
5764 #define NK_UINT_MIN 0
5765 #define NK_UINT_MAX 4294967295u
5766 
5767 /* Make sure correct type size:
5768  * This will fire with a negative subscript error if the type sizes
5769  * are set incorrectly by the compiler, and compile out if not */
5770 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
5771 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
5772 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
5773 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
5774 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
5775 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
5776 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
5777 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
5778 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
5779 
5780 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
5781 #define NK_FLOAT_PRECISION 0.00000000000001
5782 
5783 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
5784 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
5785 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
5786 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
5787 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
5788 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
5789 
5790 /* widget */
5791 #define nk_widget_state_reset(s)\
5792     if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
5793         (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
5794     else (*(s)) = NK_WIDGET_STATE_INACTIVE;
5795 
5796 /* math */
5797 NK_LIB float nk_inv_sqrt(float n);
5798 NK_LIB float nk_sqrt(float x);
5799 NK_LIB float nk_sin(float x);
5800 NK_LIB float nk_cos(float x);
5801 NK_LIB nk_uint nk_round_up_pow2(nk_uint v);
5802 NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount);
5803 NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad);
5804 NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1);
5805 NK_LIB double nk_pow(double x, int n);
5806 NK_LIB int nk_ifloord(double x);
5807 NK_LIB int nk_ifloorf(float x);
5808 NK_LIB int nk_iceilf(float x);
5809 NK_LIB int nk_log10(double n);
5810 
5811 /* util */
5812 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
5813 NK_LIB int nk_is_lower(int c);
5814 NK_LIB int nk_is_upper(int c);
5815 NK_LIB int nk_to_upper(int c);
5816 NK_LIB int nk_to_lower(int c);
5817 NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n);
5818 NK_LIB void nk_memset(void *ptr, int c0, nk_size size);
5819 NK_LIB void nk_zero(void *ptr, nk_size size);
5820 NK_LIB char *nk_itoa(char *s, long n);
5821 NK_LIB int nk_string_float_limit(char *string, int prec);
5822 NK_LIB char *nk_dtoa(char *s, double n);
5823 NK_LIB int nk_text_clamp(const struct nk_user_font *font, const char *text, int text_len, float space, int *glyphs, float *text_width, nk_rune *sep_list, int sep_count);
5824 NK_LIB struct nk_vec2 nk_text_calculate_text_bounds(const struct nk_user_font *font, const char *begin, int byte_len, float row_height, const char **remaining, struct nk_vec2 *out_offset, int *glyphs, int op);
5825 #ifdef NK_INCLUDE_STANDARD_VARARGS
5826 NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args);
5827 #endif
5828 #ifdef NK_INCLUDE_STANDARD_IO
5829 NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc);
5830 #endif
5831 
5832 /* buffer */
5833 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5834 NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size);
5835 NK_LIB void nk_mfree(nk_handle unused, void *ptr);
5836 #endif
5837 NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type);
5838 NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align);
5839 NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size);
5840 
5841 /* draw */
5842 NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip);
5843 NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b);
5844 NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size);
5845 NK_LIB void nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, struct nk_rect content, struct nk_color background, struct nk_color foreground, float border_width, const struct nk_user_font *font);
5846 
5847 /* buffering */
5848 NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
5849 NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win);
5850 NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win);
5851 NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*);
5852 NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
5853 NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w);
5854 NK_LIB void nk_build(struct nk_context *ctx);
5855 
5856 /* text editor */
5857 NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter);
5858 NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
5859 NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
5860 NK_LIB void nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, const struct nk_user_font *font, float row_height);
5861 
5862 /* window */
5863 enum nk_window_insert_location {
5864     NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
5865     NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
5866 };
5867 NK_LIB void *nk_create_window(struct nk_context *ctx);
5868 NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*);
5869 NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win);
5870 NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name);
5871 NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc);
5872 
5873 /* pool */
5874 NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity);
5875 NK_LIB void nk_pool_free(struct nk_pool *pool);
5876 NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size);
5877 NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool);
5878 
5879 /* page-element */
5880 NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx);
5881 NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem);
5882 NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem);
5883 
5884 /* table */
5885 NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx);
5886 NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
5887 NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
5888 NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl);
5889 NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value);
5890 NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name);
5891 
5892 /* panel */
5893 NK_LIB void *nk_create_panel(struct nk_context *ctx);
5894 NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan);
5895 NK_LIB int nk_panel_has_header(nk_flags flags, const char *title);
5896 NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type);
5897 NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type);
5898 NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type);
5899 NK_LIB int nk_panel_is_sub(enum nk_panel_type type);
5900 NK_LIB int nk_panel_is_nonblock(enum nk_panel_type type);
5901 NK_LIB int nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type);
5902 NK_LIB void nk_panel_end(struct nk_context *ctx);
5903 
5904 /* layout */
5905 NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns);
5906 NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols);
5907 NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width);
5908 NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win);
5909 NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify);
5910 NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx);
5911 NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx);
5912 
5913 /* popup */
5914 NK_LIB int nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type);
5915 
5916 /* text */
5917 struct nk_text {
5918     struct nk_vec2 padding;
5919     struct nk_color background;
5920     struct nk_color text;
5921 };
5922 NK_LIB void nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, nk_flags a, const struct nk_user_font *f);
5923 NK_LIB void nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, const struct nk_user_font *f);
5924 
5925 /* button */
5926 NK_LIB int nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior);
5927 NK_LIB const struct nk_style_item* nk_draw_button(struct nk_command_buffer *out, const struct nk_rect *bounds, nk_flags state, const struct nk_style_button *style);
5928 NK_LIB int nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, const struct nk_style_button *style, const struct nk_input *in, enum nk_button_behavior behavior, struct nk_rect *content);
5929 NK_LIB void nk_draw_button_text(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const char *txt, int len, nk_flags text_alignment, const struct nk_user_font *font);
5930 NK_LIB int nk_do_button_text(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *string, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
5931 NK_LIB void nk_draw_button_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, enum nk_symbol_type type, const struct nk_user_font *font);
5932 NK_LIB int nk_do_button_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
5933 NK_LIB void nk_draw_button_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const struct nk_image *img);
5934 NK_LIB int nk_do_button_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, enum nk_button_behavior b, const struct nk_style_button *style, const struct nk_input *in);
5935 NK_LIB void nk_draw_button_text_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, const char *str, int len, enum nk_symbol_type type, const struct nk_user_font *font);
5936 NK_LIB int nk_do_button_text_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, const char *str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
5937 NK_LIB void nk_draw_button_text_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, const char *str, int len, const struct nk_user_font *font, const struct nk_image *img);
5938 NK_LIB int nk_do_button_text_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, const char* str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
5939 
5940 /* toggle */
5941 enum nk_toggle_type {
5942     NK_TOGGLE_CHECK,
5943     NK_TOGGLE_OPTION
5944 };
5945 NK_LIB int nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, int active);
5946 NK_LIB void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
5947 NK_LIB void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
5948 NK_LIB int nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, int *active, const char *str, int len, enum nk_toggle_type type, const struct nk_style_toggle *style, const struct nk_input *in, const struct nk_user_font *font);
5949 
5950 /* progress */
5951 NK_LIB nk_size nk_progress_behavior(nk_flags *state, struct nk_input *in, struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable);
5952 NK_LIB void nk_draw_progress(struct nk_command_buffer *out, nk_flags state, const struct nk_style_progress *style, const struct nk_rect *bounds, const struct nk_rect *scursor, nk_size value, nk_size max);
5953 NK_LIB nk_size nk_do_progress(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_size value, nk_size max, int modifiable, const struct nk_style_progress *style, struct nk_input *in);
5954 
5955 /* slider */
5956 NK_LIB float nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, struct nk_rect *visual_cursor, struct nk_input *in, struct nk_rect bounds, float slider_min, float slider_max, float slider_value, float slider_step, float slider_steps);
5957 NK_LIB void nk_draw_slider(struct nk_command_buffer *out, nk_flags state, const struct nk_style_slider *style, const struct nk_rect *bounds, const struct nk_rect *visual_cursor, float min, float value, float max);
5958 NK_LIB float nk_do_slider(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, float min, float val, float max, float step, const struct nk_style_slider *style, struct nk_input *in, const struct nk_user_font *font);
5959 
5960 /* scrollbar */
5961 NK_LIB float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o);
5962 NK_LIB void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll);
5963 NK_LIB float nk_do_scrollbarv(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
5964 NK_LIB float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
5965 
5966 /* selectable */
5967 NK_LIB void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, int active, const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, const char *string, int len, nk_flags align, const struct nk_user_font *font);
5968 NK_LIB int nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
5969 NK_LIB int nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
5970 
5971 /* edit */
5972 NK_LIB void nk_edit_draw_text(struct nk_command_buffer *out, const struct nk_style_edit *style, float pos_x, float pos_y, float x_offset, const char *text, int byte_len, float row_height, const struct nk_user_font *font, struct nk_color background, struct nk_color foreground, int is_selected);
5973 NK_LIB nk_flags nk_do_edit(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, struct nk_text_edit *edit, const struct nk_style_edit *style, struct nk_input *in, const struct nk_user_font *font);
5974 
5975 /* color-picker */
5976 NK_LIB int nk_color_picker_behavior(nk_flags *state, const struct nk_rect *bounds, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf *color, const struct nk_input *in);
5977 NK_LIB void nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf col);
5978 NK_LIB int nk_do_color_picker(nk_flags *state, struct nk_command_buffer *out, struct nk_colorf *col, enum nk_color_format fmt, struct nk_rect bounds, struct nk_vec2 padding, const struct nk_input *in, const struct nk_user_font *font);
5979 
5980 /* property */
5981 enum nk_property_status {
5982     NK_PROPERTY_DEFAULT,
5983     NK_PROPERTY_EDIT,
5984     NK_PROPERTY_DRAG
5985 };
5986 enum nk_property_filter {
5987     NK_FILTER_INT,
5988     NK_FILTER_FLOAT
5989 };
5990 enum nk_property_kind {
5991     NK_PROPERTY_INT,
5992     NK_PROPERTY_FLOAT,
5993     NK_PROPERTY_DOUBLE
5994 };
5995 union nk_property {
5996     int i;
5997     float f;
5998     double d;
5999 };
6000 struct nk_property_variant {
6001     enum nk_property_kind kind;
6002     union nk_property value;
6003     union nk_property min_value;
6004     union nk_property max_value;
6005     union nk_property step;
6006 };
6007 NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step);
6008 NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step);
6009 NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step);
6010 
6011 NK_LIB void nk_drag_behavior(nk_flags *state, const struct nk_input *in, struct nk_rect drag, struct nk_property_variant *variant, float inc_per_pixel);
6012 NK_LIB void nk_property_behavior(nk_flags *ws, const struct nk_input *in, struct nk_rect property,  struct nk_rect label, struct nk_rect edit, struct nk_rect empty, int *state, struct nk_property_variant *variant, float inc_per_pixel);
6013 NK_LIB void nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, const char *name, int len, const struct nk_user_font *font);
6014 NK_LIB void nk_do_property(nk_flags *ws, struct nk_command_buffer *out, struct nk_rect property, const char *name, struct nk_property_variant *variant, float inc_per_pixel, char *buffer, int *len, int *state, int *cursor, int *select_begin, int *select_end, const struct nk_style_property *style, enum nk_property_filter filter, struct nk_input *in, const struct nk_user_font *font, struct nk_text_edit *text_edit, enum nk_button_behavior behavior);
6015 NK_LIB void nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, float inc_per_pixel, const enum nk_property_filter filter);
6016 
6017 #endif
6018 
6019 
6020 
6021 
6022 
6023 /* ===============================================================
6024  *
6025  *                              MATH
6026  *
6027  * ===============================================================*/
6028 /*  Since nuklear is supposed to work on all systems providing floating point
6029     math without any dependencies I also had to implement my own math functions
6030     for sqrt, sin and cos. Since the actual highly accurate implementations for
6031     the standard library functions are quite complex and I do not need high
6032     precision for my use cases I use approximations.
6033 
6034     Sqrt
6035     ----
6036     For square root nuklear uses the famous fast inverse square root:
6037     https://en.wikipedia.org/wiki/Fast_inverse_square_root with
6038     slightly tweaked magic constant. While on today's hardware it is
6039     probably not faster it is still fast and accurate enough for
6040     nuklear's use cases. IMPORTANT: this requires float format IEEE 754
6041 
6042     Sine/Cosine
6043     -----------
6044     All constants inside both function are generated Remez's minimax
6045     approximations for value range 0...2*PI. The reason why I decided to
6046     approximate exactly that range is that nuklear only needs sine and
6047     cosine to generate circles which only requires that exact range.
6048     In addition I used Remez instead of Taylor for additional precision:
6049     www.lolengine.net/blog/2011/12/21/better-function-approximations.
6050 
6051     The tool I used to generate constants for both sine and cosine
6052     (it can actually approximate a lot more functions) can be
6053     found here: www.lolengine.net/wiki/oss/lolremez
6054 */
6055 NK_LIB float
6056 nk_inv_sqrt(float n)
6057 {
6058     float x2;
6059     const float threehalfs = 1.5f;
6060     union {nk_uint i; float f;} conv = {0};
6061     conv.f = n;
6062     x2 = n * 0.5f;
6063     conv.i = 0x5f375A84 - (conv.i >> 1);
6064     conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
6065     return conv.f;
6066 }
6067 NK_LIB float
6068 nk_sqrt(float x)
6069 {
6070     return x * nk_inv_sqrt(x);
6071 }
6072 NK_LIB float
6073 nk_sin(float x)
6074 {
6075     NK_STORAGE const float a0 = +1.91059300966915117e-31f;
6076     NK_STORAGE const float a1 = +1.00086760103908896f;
6077     NK_STORAGE const float a2 = -1.21276126894734565e-2f;
6078     NK_STORAGE const float a3 = -1.38078780785773762e-1f;
6079     NK_STORAGE const float a4 = -2.67353392911981221e-2f;
6080     NK_STORAGE const float a5 = +2.08026600266304389e-2f;
6081     NK_STORAGE const float a6 = -3.03996055049204407e-3f;
6082     NK_STORAGE const float a7 = +1.38235642404333740e-4f;
6083     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
6084 }
6085 NK_LIB float
6086 nk_cos(float x)
6087 {
6088     /* New implementation. Also generated using lolremez. */
6089     /* Old version significantly deviated from expected results. */
6090     NK_STORAGE const float a0 = 9.9995999154986614e-1f;
6091     NK_STORAGE const float a1 = 1.2548995793001028e-3f;
6092     NK_STORAGE const float a2 = -5.0648546280678015e-1f;
6093     NK_STORAGE const float a3 = 1.2942246466519995e-2f;
6094     NK_STORAGE const float a4 = 2.8668384702547972e-2f;
6095     NK_STORAGE const float a5 = 7.3726485210586547e-3f;
6096     NK_STORAGE const float a6 = -3.8510875386947414e-3f;
6097     NK_STORAGE const float a7 = 4.7196604604366623e-4f;
6098     NK_STORAGE const float a8 = -1.8776444013090451e-5f;
6099     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8)))))));
6100 }
6101 NK_LIB nk_uint
6102 nk_round_up_pow2(nk_uint v)
6103 {
6104     v--;
6105     v |= v >> 1;
6106     v |= v >> 2;
6107     v |= v >> 4;
6108     v |= v >> 8;
6109     v |= v >> 16;
6110     v++;
6111     return v;
6112 }
6113 NK_LIB double
6114 nk_pow(double x, int n)
6115 {
6116     /*  check the sign of n */
6117     double r = 1;
6118     int plus = n >= 0;
6119     n = (plus) ? n : -n;
6120     while (n > 0) {
6121         if ((n & 1) == 1)
6122             r *= x;
6123         n /= 2;
6124         x *= x;
6125     }
6126     return plus ? r : 1.0 / r;
6127 }
6128 NK_LIB int
6129 nk_ifloord(double x)
6130 {
6131     x = (double)((int)x - ((x < 0.0) ? 1 : 0));
6132     return (int)x;
6133 }
6134 NK_LIB int
6135 nk_ifloorf(float x)
6136 {
6137     x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
6138     return (int)x;
6139 }
6140 NK_LIB int
6141 nk_iceilf(float x)
6142 {
6143     if (x >= 0) {
6144         int i = (int)x;
6145         return (x > i) ? i+1: i;
6146     } else {
6147         int t = (int)x;
6148         float r = x - (float)t;
6149         return (r > 0.0f) ? t+1: t;
6150     }
6151 }
6152 NK_LIB int
6153 nk_log10(double n)
6154 {
6155     int neg;
6156     int ret;
6157     int exp = 0;
6158 
6159     neg = (n < 0) ? 1 : 0;
6160     ret = (neg) ? (int)-n : (int)n;
6161     while ((ret / 10) > 0) {
6162         ret /= 10;
6163         exp++;
6164     }
6165     if (neg) exp = -exp;
6166     return exp;
6167 }
6168 NK_API struct nk_rect
6169 nk_get_null_rect(void)
6170 {
6171     return nk_null_rect;
6172 }
6173 NK_API struct nk_rect
6174 nk_rect(float x, float y, float w, float h)
6175 {
6176     struct nk_rect r;
6177     r.x = x; r.y = y;
6178     r.w = w; r.h = h;
6179     return r;
6180 }
6181 NK_API struct nk_rect
6182 nk_recti(int x, int y, int w, int h)
6183 {
6184     struct nk_rect r;
6185     r.x = (float)x;
6186     r.y = (float)y;
6187     r.w = (float)w;
6188     r.h = (float)h;
6189     return r;
6190 }
6191 NK_API struct nk_rect
6192 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
6193 {
6194     return nk_rect(pos.x, pos.y, size.x, size.y);
6195 }
6196 NK_API struct nk_rect
6197 nk_rectv(const float *r)
6198 {
6199     return nk_rect(r[0], r[1], r[2], r[3]);
6200 }
6201 NK_API struct nk_rect
6202 nk_rectiv(const int *r)
6203 {
6204     return nk_recti(r[0], r[1], r[2], r[3]);
6205 }
6206 NK_API struct nk_vec2
6207 nk_rect_pos(struct nk_rect r)
6208 {
6209     struct nk_vec2 ret;
6210     ret.x = r.x; ret.y = r.y;
6211     return ret;
6212 }
6213 NK_API struct nk_vec2
6214 nk_rect_size(struct nk_rect r)
6215 {
6216     struct nk_vec2 ret;
6217     ret.x = r.w; ret.y = r.h;
6218     return ret;
6219 }
6220 NK_LIB struct nk_rect
6221 nk_shrink_rect(struct nk_rect r, float amount)
6222 {
6223     struct nk_rect res;
6224     r.w = NK_MAX(r.w, 2 * amount);
6225     r.h = NK_MAX(r.h, 2 * amount);
6226     res.x = r.x + amount;
6227     res.y = r.y + amount;
6228     res.w = r.w - 2 * amount;
6229     res.h = r.h - 2 * amount;
6230     return res;
6231 }
6232 NK_LIB struct nk_rect
6233 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
6234 {
6235     r.w = NK_MAX(r.w, 2 * pad.x);
6236     r.h = NK_MAX(r.h, 2 * pad.y);
6237     r.x += pad.x; r.y += pad.y;
6238     r.w -= 2 * pad.x;
6239     r.h -= 2 * pad.y;
6240     return r;
6241 }
6242 NK_API struct nk_vec2
6243 nk_vec2(float x, float y)
6244 {
6245     struct nk_vec2 ret;
6246     ret.x = x; ret.y = y;
6247     return ret;
6248 }
6249 NK_API struct nk_vec2
6250 nk_vec2i(int x, int y)
6251 {
6252     struct nk_vec2 ret;
6253     ret.x = (float)x;
6254     ret.y = (float)y;
6255     return ret;
6256 }
6257 NK_API struct nk_vec2
6258 nk_vec2v(const float *v)
6259 {
6260     return nk_vec2(v[0], v[1]);
6261 }
6262 NK_API struct nk_vec2
6263 nk_vec2iv(const int *v)
6264 {
6265     return nk_vec2i(v[0], v[1]);
6266 }
6267 NK_LIB void
6268 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6269     float x1, float y1)
6270 {
6271     NK_ASSERT(a);
6272     NK_ASSERT(clip);
6273     clip->x = NK_MAX(a->x, x0);
6274     clip->y = NK_MAX(a->y, y0);
6275     clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6276     clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6277     clip->w = NK_MAX(0, clip->w);
6278     clip->h = NK_MAX(0, clip->h);
6279 }
6280 
6281 NK_API void
6282 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
6283     float pad_x, float pad_y, enum nk_heading direction)
6284 {
6285     float w_half, h_half;
6286     NK_ASSERT(result);
6287 
6288     r.w = NK_MAX(2 * pad_x, r.w);
6289     r.h = NK_MAX(2 * pad_y, r.h);
6290     r.w = r.w - 2 * pad_x;
6291     r.h = r.h - 2 * pad_y;
6292 
6293     r.x = r.x + pad_x;
6294     r.y = r.y + pad_y;
6295 
6296     w_half = r.w / 2.0f;
6297     h_half = r.h / 2.0f;
6298 
6299     if (direction == NK_UP) {
6300         result[0] = nk_vec2(r.x + w_half, r.y);
6301         result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6302         result[2] = nk_vec2(r.x, r.y + r.h);
6303     } else if (direction == NK_RIGHT) {
6304         result[0] = nk_vec2(r.x, r.y);
6305         result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6306         result[2] = nk_vec2(r.x, r.y + r.h);
6307     } else if (direction == NK_DOWN) {
6308         result[0] = nk_vec2(r.x, r.y);
6309         result[1] = nk_vec2(r.x + r.w, r.y);
6310         result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6311     } else {
6312         result[0] = nk_vec2(r.x, r.y + h_half);
6313         result[1] = nk_vec2(r.x + r.w, r.y);
6314         result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6315     }
6316 }
6317 
6318 
6319 
6320 
6321 
6322 /* ===============================================================
6323  *
6324  *                              UTIL
6325  *
6326  * ===============================================================*/
6327 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
6328 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
6329 NK_LIB int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
6330 NK_LIB int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
6331 NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
6332 NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
6333 
6334 NK_LIB void*
6335 nk_memcopy(void *dst0, const void *src0, nk_size length)
6336 {
6337     nk_ptr t;
6338     char *dst = (char*)dst0;
6339     const char *src = (const char*)src0;
6340     if (length == 0 || dst == src)
6341         goto done;
6342 
6343     #define nk_word int
6344     #define nk_wsize sizeof(nk_word)
6345     #define nk_wmask (nk_wsize-1)
6346     #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
6347     #define NK_TLOOP1(s) do { s; } while (--t)
6348 
6349     if (dst < src) {
6350         t = (nk_ptr)src; /* only need low bits */
6351         if ((t | (nk_ptr)dst) & nk_wmask) {
6352             if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
6353                 t = length;
6354             else
6355                 t = nk_wsize - (t & nk_wmask);
6356             length -= t;
6357             NK_TLOOP1(*dst++ = *src++);
6358         }
6359         t = length / nk_wsize;
6360         NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
6361             src += nk_wsize; dst += nk_wsize);
6362         t = length & nk_wmask;
6363         NK_TLOOP(*dst++ = *src++);
6364     } else {
6365         src += length;
6366         dst += length;
6367         t = (nk_ptr)src;
6368         if ((t | (nk_ptr)dst) & nk_wmask) {
6369             if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
6370                 t = length;
6371             else
6372                 t &= nk_wmask;
6373             length -= t;
6374             NK_TLOOP1(*--dst = *--src);
6375         }
6376         t = length / nk_wsize;
6377         NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
6378             *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
6379         t = length & nk_wmask;
6380         NK_TLOOP(*--dst = *--src);
6381     }
6382     #undef nk_word
6383     #undef nk_wsize
6384     #undef nk_wmask
6385     #undef NK_TLOOP
6386     #undef NK_TLOOP1
6387 done:
6388     return (dst0);
6389 }
6390 NK_LIB void
6391 nk_memset(void *ptr, int c0, nk_size size)
6392 {
6393     #define nk_word unsigned
6394     #define nk_wsize sizeof(nk_word)
6395     #define nk_wmask (nk_wsize - 1)
6396     nk_byte *dst = (nk_byte*)ptr;
6397     unsigned c = 0;
6398     nk_size t = 0;
6399 
6400     if ((c = (nk_byte)c0) != 0) {
6401         c = (c << 8) | c; /* at least 16-bits  */
6402         if (sizeof(unsigned int) > 2)
6403             c = (c << 16) | c; /* at least 32-bits*/
6404     }
6405 
6406     /* too small of a word count */
6407     dst = (nk_byte*)ptr;
6408     if (size < 3 * nk_wsize) {
6409         while (size--) *dst++ = (nk_byte)c0;
6410         return;
6411     }
6412 
6413     /* align destination */
6414     if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
6415         t = nk_wsize -t;
6416         size -= t;
6417         do {
6418             *dst++ = (nk_byte)c0;
6419         } while (--t != 0);
6420     }
6421 
6422     /* fill word */
6423     t = size / nk_wsize;
6424     do {
6425         *(nk_word*)((void*)dst) = c;
6426         dst += nk_wsize;
6427     } while (--t != 0);
6428 
6429     /* fill trailing bytes */
6430     t = (size & nk_wmask);
6431     if (t != 0) {
6432         do {
6433             *dst++ = (nk_byte)c0;
6434         } while (--t != 0);
6435     }
6436 
6437     #undef nk_word
6438     #undef nk_wsize
6439     #undef nk_wmask
6440 }
6441 NK_LIB void
6442 nk_zero(void *ptr, nk_size size)
6443 {
6444     NK_ASSERT(ptr);
6445     NK_MEMSET(ptr, 0, size);
6446 }
6447 NK_API int
6448 nk_strlen(const char *str)
6449 {
6450     int siz = 0;
6451     NK_ASSERT(str);
6452     while (str && *str++ != '\0') siz++;
6453     return siz;
6454 }
6455 NK_API int
6456 nk_strtoi(const char *str, const char **endptr)
6457 {
6458     int neg = 1;
6459     const char *p = str;
6460     int value = 0;
6461 
6462     NK_ASSERT(str);
6463     if (!str) return 0;
6464 
6465     /* skip whitespace */
6466     while (*p == ' ') p++;
6467     if (*p == '-') {
6468         neg = -1;
6469         p++;
6470     }
6471     while (*p && *p >= '0' && *p <= '9') {
6472         value = value * 10 + (int) (*p - '0');
6473         p++;
6474     }
6475     if (endptr)
6476         *endptr = p;
6477     return neg*value;
6478 }
6479 NK_API double
6480 nk_strtod(const char *str, const char **endptr)
6481 {
6482     double m;
6483     double neg = 1.0;
6484     const char *p = str;
6485     double value = 0;
6486     double number = 0;
6487 
6488     NK_ASSERT(str);
6489     if (!str) return 0;
6490 
6491     /* skip whitespace */
6492     while (*p == ' ') p++;
6493     if (*p == '-') {
6494         neg = -1.0;
6495         p++;
6496     }
6497 
6498     while (*p && *p != '.' && *p != 'e') {
6499         value = value * 10.0 + (double) (*p - '0');
6500         p++;
6501     }
6502 
6503     if (*p == '.') {
6504         p++;
6505         for(m = 0.1; *p && *p != 'e'; p++ ) {
6506             value = value + (double) (*p - '0') * m;
6507             m *= 0.1;
6508         }
6509     }
6510     if (*p == 'e') {
6511         int i, pow, div;
6512         p++;
6513         if (*p == '-') {
6514             div = nk_true;
6515             p++;
6516         } else if (*p == '+') {
6517             div = nk_false;
6518             p++;
6519         } else div = nk_false;
6520 
6521         for (pow = 0; *p; p++)
6522             pow = pow * 10 + (int) (*p - '0');
6523 
6524         for (m = 1.0, i = 0; i < pow; i++)
6525             m *= 10.0;
6526 
6527         if (div)
6528             value /= m;
6529         else value *= m;
6530     }
6531     number = value * neg;
6532     if (endptr)
6533         *endptr = p;
6534     return number;
6535 }
6536 NK_API float
6537 nk_strtof(const char *str, const char **endptr)
6538 {
6539     float float_value;
6540     double double_value;
6541     double_value = NK_STRTOD(str, endptr);
6542     float_value = (float)double_value;
6543     return float_value;
6544 }
6545 NK_API int
6546 nk_stricmp(const char *s1, const char *s2)
6547 {
6548     nk_int c1,c2,d;
6549     do {
6550         c1 = *s1++;
6551         c2 = *s2++;
6552         d = c1 - c2;
6553         while (d) {
6554             if (c1 <= 'Z' && c1 >= 'A') {
6555                 d += ('a' - 'A');
6556                 if (!d) break;
6557             }
6558             if (c2 <= 'Z' && c2 >= 'A') {
6559                 d -= ('a' - 'A');
6560                 if (!d) break;
6561             }
6562             return ((d >= 0) << 1) - 1;
6563         }
6564     } while (c1);
6565     return 0;
6566 }
6567 NK_API int
6568 nk_stricmpn(const char *s1, const char *s2, int n)
6569 {
6570     int c1,c2,d;
6571     NK_ASSERT(n >= 0);
6572     do {
6573         c1 = *s1++;
6574         c2 = *s2++;
6575         if (!n--) return 0;
6576 
6577         d = c1 - c2;
6578         while (d) {
6579             if (c1 <= 'Z' && c1 >= 'A') {
6580                 d += ('a' - 'A');
6581                 if (!d) break;
6582             }
6583             if (c2 <= 'Z' && c2 >= 'A') {
6584                 d -= ('a' - 'A');
6585                 if (!d) break;
6586             }
6587             return ((d >= 0) << 1) - 1;
6588         }
6589     } while (c1);
6590     return 0;
6591 }
6592 NK_INTERN int
6593 nk_str_match_here(const char *regexp, const char *text)
6594 {
6595     if (regexp[0] == '\0')
6596         return 1;
6597     if (regexp[1] == '*')
6598         return nk_str_match_star(regexp[0], regexp+2, text);
6599     if (regexp[0] == '$' && regexp[1] == '\0')
6600         return *text == '\0';
6601     if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
6602         return nk_str_match_here(regexp+1, text+1);
6603     return 0;
6604 }
6605 NK_INTERN int
6606 nk_str_match_star(int c, const char *regexp, const char *text)
6607 {
6608     do {/* a '* matches zero or more instances */
6609         if (nk_str_match_here(regexp, text))
6610             return 1;
6611     } while (*text != '\0' && (*text++ == c || c == '.'));
6612     return 0;
6613 }
6614 NK_API int
6615 nk_strfilter(const char *text, const char *regexp)
6616 {
6617     /*
6618     c    matches any literal character c
6619     .    matches any single character
6620     ^    matches the beginning of the input string
6621     $    matches the end of the input string
6622     *    matches zero or more occurrences of the previous character*/
6623     if (regexp[0] == '^')
6624         return nk_str_match_here(regexp+1, text);
6625     do {    /* must look even if string is empty */
6626         if (nk_str_match_here(regexp, text))
6627             return 1;
6628     } while (*text++ != '\0');
6629     return 0;
6630 }
6631 NK_API int
6632 nk_strmatch_fuzzy_text(const char *str, int str_len,
6633     const char *pattern, int *out_score)
6634 {
6635     /* Returns true if each character in pattern is found sequentially within str
6636      * if found then out_score is also set. Score value has no intrinsic meaning.
6637      * Range varies with pattern. Can only compare scores with same search pattern. */
6638 
6639     /* bonus for adjacent matches */
6640     #define NK_ADJACENCY_BONUS 5
6641     /* bonus if match occurs after a separator */
6642     #define NK_SEPARATOR_BONUS 10
6643     /* bonus if match is uppercase and prev is lower */
6644     #define NK_CAMEL_BONUS 10
6645     /* penalty applied for every letter in str before the first match */
6646     #define NK_LEADING_LETTER_PENALTY (-3)
6647     /* maximum penalty for leading letters */
6648     #define NK_MAX_LEADING_LETTER_PENALTY (-9)
6649     /* penalty for every letter that doesn't matter */
6650     #define NK_UNMATCHED_LETTER_PENALTY (-1)
6651 
6652     /* loop variables */
6653     int score = 0;
6654     char const * pattern_iter = pattern;
6655     int str_iter = 0;
6656     int prev_matched = nk_false;
6657     int prev_lower = nk_false;
6658     /* true so if first letter match gets separator bonus*/
6659     int prev_separator = nk_true;
6660 
6661     /* use "best" matched letter if multiple string letters match the pattern */
6662     char const * best_letter = 0;
6663     int best_letter_score = 0;
6664 
6665     /* loop over strings */
6666     NK_ASSERT(str);
6667     NK_ASSERT(pattern);
6668     if (!str || !str_len || !pattern) return 0;
6669     while (str_iter < str_len)
6670     {
6671         const char pattern_letter = *pattern_iter;
6672         const char str_letter = str[str_iter];
6673 
6674         int next_match = *pattern_iter != '\0' &&
6675             nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
6676         int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
6677 
6678         int advanced = next_match && best_letter;
6679         int pattern_repeat = best_letter && *pattern_iter != '\0';
6680         pattern_repeat = pattern_repeat &&
6681             nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
6682 
6683         if (advanced || pattern_repeat) {
6684             score += best_letter_score;
6685             best_letter = 0;
6686             best_letter_score = 0;
6687         }
6688 
6689         if (next_match || rematch)
6690         {
6691             int new_score = 0;
6692             /* Apply penalty for each letter before the first pattern match */
6693             if (pattern_iter == pattern) {
6694                 int count = (int)(&str[str_iter] - str);
6695                 int penalty = NK_LEADING_LETTER_PENALTY * count;
6696                 if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
6697                     penalty = NK_MAX_LEADING_LETTER_PENALTY;
6698 
6699                 score += penalty;
6700             }
6701 
6702             /* apply bonus for consecutive bonuses */
6703             if (prev_matched)
6704                 new_score += NK_ADJACENCY_BONUS;
6705 
6706             /* apply bonus for matches after a separator */
6707             if (prev_separator)
6708                 new_score += NK_SEPARATOR_BONUS;
6709 
6710             /* apply bonus across camel case boundaries */
6711             if (prev_lower && nk_is_upper(str_letter))
6712                 new_score += NK_CAMEL_BONUS;
6713 
6714             /* update pattern iter IFF the next pattern letter was matched */
6715             if (next_match)
6716                 ++pattern_iter;
6717 
6718             /* update best letter in str which may be for a "next" letter or a rematch */
6719             if (new_score >= best_letter_score) {
6720                 /* apply penalty for now skipped letter */
6721                 if (best_letter != 0)
6722                     score += NK_UNMATCHED_LETTER_PENALTY;
6723 
6724                 best_letter = &str[str_iter];
6725                 best_letter_score = new_score;
6726             }
6727             prev_matched = nk_true;
6728         } else {
6729             score += NK_UNMATCHED_LETTER_PENALTY;
6730             prev_matched = nk_false;
6731         }
6732 
6733         /* separators should be more easily defined */
6734         prev_lower = nk_is_lower(str_letter) != 0;
6735         prev_separator = str_letter == '_' || str_letter == ' ';
6736 
6737         ++str_iter;
6738     }
6739 
6740     /* apply score for last match */
6741     if (best_letter)
6742         score += best_letter_score;
6743 
6744     /* did not match full pattern */
6745     if (*pattern_iter != '\0')
6746         return nk_false;
6747 
6748     if (out_score)
6749         *out_score = score;
6750     return nk_true;
6751 }
6752 NK_API int
6753 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
6754 {
6755     return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);
6756 }
6757 NK_LIB int
6758 nk_string_float_limit(char *string, int prec)
6759 {
6760     int dot = 0;
6761     char *c = string;
6762     while (*c) {
6763         if (*c == '.') {
6764             dot = 1;
6765             c++;
6766             continue;
6767         }
6768         if (dot == (prec+1)) {
6769             *c = 0;
6770             break;
6771         }
6772         if (dot > 0) dot++;
6773         c++;
6774     }
6775     return (int)(c - string);
6776 }
6777 NK_INTERN void
6778 nk_strrev_ascii(char *s)
6779 {
6780     int len = nk_strlen(s);
6781     int end = len / 2;
6782     int i = 0;
6783     char t;
6784     for (; i < end; ++i) {
6785         t = s[i];
6786         s[i] = s[len - 1 - i];
6787         s[len -1 - i] = t;
6788     }
6789 }
6790 NK_LIB char*
6791 nk_itoa(char *s, long n)
6792 {
6793     long i = 0;
6794     if (n == 0) {
6795         s[i++] = '0';
6796         s[i] = 0;
6797         return s;
6798     }
6799     if (n < 0) {
6800         s[i++] = '-';
6801         n = -n;
6802     }
6803     while (n > 0) {
6804         s[i++] = (char)('0' + (n % 10));
6805         n /= 10;
6806     }
6807     s[i] = 0;
6808     if (s[0] == '-')
6809         ++s;
6810 
6811     nk_strrev_ascii(s);
6812     return s;
6813 }
6814 NK_LIB char*
6815 nk_dtoa(char *s, double n)
6816 {
6817     int useExp = 0;
6818     int digit = 0, m = 0, m1 = 0;
6819     char *c = s;
6820     int neg = 0;
6821 
6822     NK_ASSERT(s);
6823     if (!s) return 0;
6824 
6825     if (n == 0.0) {
6826         s[0] = '0'; s[1] = '\0';
6827         return s;
6828     }
6829 
6830     neg = (n < 0);
6831     if (neg) n = -n;
6832 
6833     /* calculate magnitude */
6834     m = nk_log10(n);
6835     useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
6836     if (neg) *(c++) = '-';
6837 
6838     /* set up for scientific notation */
6839     if (useExp) {
6840         if (m < 0)
6841            m -= 1;
6842         n = n / (double)nk_pow(10.0, m);
6843         m1 = m;
6844         m = 0;
6845     }
6846     if (m < 1.0) {
6847         m = 0;
6848     }
6849 
6850     /* convert the number */
6851     while (n > NK_FLOAT_PRECISION || m >= 0) {
6852         double weight = nk_pow(10.0, m);
6853         if (weight > 0) {
6854             double t = (double)n / weight;
6855             digit = nk_ifloord(t);
6856             n -= ((double)digit * weight);
6857             *(c++) = (char)('0' + (char)digit);
6858         }
6859         if (m == 0 && n > 0)
6860             *(c++) = '.';
6861         m--;
6862     }
6863 
6864     if (useExp) {
6865         /* convert the exponent */
6866         int i, j;
6867         *(c++) = 'e';
6868         if (m1 > 0) {
6869             *(c++) = '+';
6870         } else {
6871             *(c++) = '-';
6872             m1 = -m1;
6873         }
6874         m = 0;
6875         while (m1 > 0) {
6876             *(c++) = (char)('0' + (char)(m1 % 10));
6877             m1 /= 10;
6878             m++;
6879         }
6880         c -= m;
6881         for (i = 0, j = m-1; i<j; i++, j--) {
6882             /* swap without temporary */
6883             c[i] ^= c[j];
6884             c[j] ^= c[i];
6885             c[i] ^= c[j];
6886         }
6887         c += m;
6888     }
6889     *(c) = '\0';
6890     return s;
6891 }
6892 #ifdef NK_INCLUDE_STANDARD_VARARGS
6893 #ifndef NK_INCLUDE_STANDARD_IO
6894 NK_INTERN int
6895 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
6896 {
6897     enum nk_arg_type {
6898         NK_ARG_TYPE_CHAR,
6899         NK_ARG_TYPE_SHORT,
6900         NK_ARG_TYPE_DEFAULT,
6901         NK_ARG_TYPE_LONG
6902     };
6903     enum nk_arg_flags {
6904         NK_ARG_FLAG_LEFT = 0x01,
6905         NK_ARG_FLAG_PLUS = 0x02,
6906         NK_ARG_FLAG_SPACE = 0x04,
6907         NK_ARG_FLAG_NUM = 0x10,
6908         NK_ARG_FLAG_ZERO = 0x20
6909     };
6910 
6911     char number_buffer[NK_MAX_NUMBER_BUFFER];
6912     enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
6913     int precision = NK_DEFAULT;
6914     int width = NK_DEFAULT;
6915     nk_flags flag = 0;
6916 
6917     int len = 0;
6918     int result = -1;
6919     const char *iter = fmt;
6920 
6921     NK_ASSERT(buf);
6922     NK_ASSERT(buf_size);
6923     if (!buf || !buf_size || !fmt) return 0;
6924     for (iter = fmt; *iter && len < buf_size; iter++) {
6925         /* copy all non-format characters */
6926         while (*iter && (*iter != '%') && (len < buf_size))
6927             buf[len++] = *iter++;
6928         if (!(*iter) || len >= buf_size) break;
6929         iter++;
6930 
6931         /* flag arguments */
6932         while (*iter) {
6933             if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
6934             else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
6935             else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
6936             else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
6937             else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
6938             else break;
6939             iter++;
6940         }
6941 
6942         /* width argument */
6943         width = NK_DEFAULT;
6944         if (*iter >= '1' && *iter <= '9') {
6945             const char *end;
6946             width = nk_strtoi(iter, &end);
6947             if (end == iter)
6948                 width = -1;
6949             else iter = end;
6950         } else if (*iter == '*') {
6951             width = va_arg(args, int);
6952             iter++;
6953         }
6954 
6955         /* precision argument */
6956         precision = NK_DEFAULT;
6957         if (*iter == '.') {
6958             iter++;
6959             if (*iter == '*') {
6960                 precision = va_arg(args, int);
6961                 iter++;
6962             } else {
6963                 const char *end;
6964                 precision = nk_strtoi(iter, &end);
6965                 if (end == iter)
6966                     precision = -1;
6967                 else iter = end;
6968             }
6969         }
6970 
6971         /* length modifier */
6972         if (*iter == 'h') {
6973             if (*(iter+1) == 'h') {
6974                 arg_type = NK_ARG_TYPE_CHAR;
6975                 iter++;
6976             } else arg_type = NK_ARG_TYPE_SHORT;
6977             iter++;
6978         } else if (*iter == 'l') {
6979             arg_type = NK_ARG_TYPE_LONG;
6980             iter++;
6981         } else arg_type = NK_ARG_TYPE_DEFAULT;
6982 
6983         /* specifier */
6984         if (*iter == '%') {
6985             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6986             NK_ASSERT(precision == NK_DEFAULT);
6987             NK_ASSERT(width == NK_DEFAULT);
6988             if (len < buf_size)
6989                 buf[len++] = '%';
6990         } else if (*iter == 's') {
6991             /* string  */
6992             const char *str = va_arg(args, const char*);
6993             NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
6994             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
6995             NK_ASSERT(precision == NK_DEFAULT);
6996             NK_ASSERT(width == NK_DEFAULT);
6997             if (str == buf) return -1;
6998             while (str && *str && len < buf_size)
6999                 buf[len++] = *str++;
7000         } else if (*iter == 'n') {
7001             /* current length callback */
7002             signed int *n = va_arg(args, int*);
7003             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
7004             NK_ASSERT(precision == NK_DEFAULT);
7005             NK_ASSERT(width == NK_DEFAULT);
7006             if (n) *n = len;
7007         } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
7008             /* signed integer */
7009             long value = 0;
7010             const char *num_iter;
7011             int num_len, num_print, padding;
7012             int cur_precision = NK_MAX(precision, 1);
7013             int cur_width = NK_MAX(width, 0);
7014 
7015             /* retrieve correct value type */
7016             if (arg_type == NK_ARG_TYPE_CHAR)
7017                 value = (signed char)va_arg(args, int);
7018             else if (arg_type == NK_ARG_TYPE_SHORT)
7019                 value = (signed short)va_arg(args, int);
7020             else if (arg_type == NK_ARG_TYPE_LONG)
7021                 value = va_arg(args, signed long);
7022             else if (*iter == 'c')
7023                 value = (unsigned char)va_arg(args, int);
7024             else value = va_arg(args, signed int);
7025 
7026             /* convert number to string */
7027             nk_itoa(number_buffer, value);
7028             num_len = nk_strlen(number_buffer);
7029             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
7030             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
7031                 padding = NK_MAX(padding-1, 0);
7032 
7033             /* fill left padding up to a total of `width` characters */
7034             if (!(flag & NK_ARG_FLAG_LEFT)) {
7035                 while (padding-- > 0 && (len < buf_size)) {
7036                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
7037                         buf[len++] = '0';
7038                     else buf[len++] = ' ';
7039                 }
7040             }
7041 
7042             /* copy string value representation into buffer */
7043             if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
7044                 buf[len++] = '+';
7045             else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
7046                 buf[len++] = ' ';
7047 
7048             /* fill up to precision number of digits with '0' */
7049             num_print = NK_MAX(cur_precision, num_len);
7050             while (precision && (num_print > num_len) && (len < buf_size)) {
7051                 buf[len++] = '0';
7052                 num_print--;
7053             }
7054 
7055             /* copy string value representation into buffer */
7056             num_iter = number_buffer;
7057             while (precision && *num_iter && len < buf_size)
7058                 buf[len++] = *num_iter++;
7059 
7060             /* fill right padding up to width characters */
7061             if (flag & NK_ARG_FLAG_LEFT) {
7062                 while ((padding-- > 0) && (len < buf_size))
7063                     buf[len++] = ' ';
7064             }
7065         } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
7066             /* unsigned integer */
7067             unsigned long value = 0;
7068             int num_len = 0, num_print, padding = 0;
7069             int cur_precision = NK_MAX(precision, 1);
7070             int cur_width = NK_MAX(width, 0);
7071             unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
7072 
7073             /* print oct/hex/dec value */
7074             const char *upper_output_format = "0123456789ABCDEF";
7075             const char *lower_output_format = "0123456789abcdef";
7076             const char *output_format = (*iter == 'x') ?
7077                 lower_output_format: upper_output_format;
7078 
7079             /* retrieve correct value type */
7080             if (arg_type == NK_ARG_TYPE_CHAR)
7081                 value = (unsigned char)va_arg(args, int);
7082             else if (arg_type == NK_ARG_TYPE_SHORT)
7083                 value = (unsigned short)va_arg(args, int);
7084             else if (arg_type == NK_ARG_TYPE_LONG)
7085                 value = va_arg(args, unsigned long);
7086             else value = va_arg(args, unsigned int);
7087 
7088             do {
7089                 /* convert decimal number into hex/oct number */
7090                 int digit = output_format[value % base];
7091                 if (num_len < NK_MAX_NUMBER_BUFFER)
7092                     number_buffer[num_len++] = (char)digit;
7093                 value /= base;
7094             } while (value > 0);
7095 
7096             num_print = NK_MAX(cur_precision, num_len);
7097             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
7098             if (flag & NK_ARG_FLAG_NUM)
7099                 padding = NK_MAX(padding-1, 0);
7100 
7101             /* fill left padding up to a total of `width` characters */
7102             if (!(flag & NK_ARG_FLAG_LEFT)) {
7103                 while ((padding-- > 0) && (len < buf_size)) {
7104                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
7105                         buf[len++] = '0';
7106                     else buf[len++] = ' ';
7107                 }
7108             }
7109 
7110             /* fill up to precision number of digits */
7111             if (num_print && (flag & NK_ARG_FLAG_NUM)) {
7112                 if ((*iter == 'o') && (len < buf_size)) {
7113                     buf[len++] = '0';
7114                 } else if ((*iter == 'x') && ((len+1) < buf_size)) {
7115                     buf[len++] = '0';
7116                     buf[len++] = 'x';
7117                 } else if ((*iter == 'X') && ((len+1) < buf_size)) {
7118                     buf[len++] = '0';
7119                     buf[len++] = 'X';
7120                 }
7121             }
7122             while (precision && (num_print > num_len) && (len < buf_size)) {
7123                 buf[len++] = '0';
7124                 num_print--;
7125             }
7126 
7127             /* reverse number direction */
7128             while (num_len > 0) {
7129                 if (precision && (len < buf_size))
7130                     buf[len++] = number_buffer[num_len-1];
7131                 num_len--;
7132             }
7133 
7134             /* fill right padding up to width characters */
7135             if (flag & NK_ARG_FLAG_LEFT) {
7136                 while ((padding-- > 0) && (len < buf_size))
7137                     buf[len++] = ' ';
7138             }
7139         } else if (*iter == 'f') {
7140             /* floating point */
7141             const char *num_iter;
7142             int cur_precision = (precision < 0) ? 6: precision;
7143             int prefix, cur_width = NK_MAX(width, 0);
7144             double value = va_arg(args, double);
7145             int num_len = 0, frac_len = 0, dot = 0;
7146             int padding = 0;
7147 
7148             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
7149             NK_DTOA(number_buffer, value);
7150             num_len = nk_strlen(number_buffer);
7151 
7152             /* calculate padding */
7153             num_iter = number_buffer;
7154             while (*num_iter && *num_iter != '.')
7155                 num_iter++;
7156 
7157             prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
7158             padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
7159             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
7160                 padding = NK_MAX(padding-1, 0);
7161 
7162             /* fill left padding up to a total of `width` characters */
7163             if (!(flag & NK_ARG_FLAG_LEFT)) {
7164                 while (padding-- > 0 && (len < buf_size)) {
7165                     if (flag & NK_ARG_FLAG_ZERO)
7166                         buf[len++] = '0';
7167                     else buf[len++] = ' ';
7168                 }
7169             }
7170 
7171             /* copy string value representation into buffer */
7172             num_iter = number_buffer;
7173             if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
7174                 buf[len++] = '+';
7175             else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
7176                 buf[len++] = ' ';
7177             while (*num_iter) {
7178                 if (dot) frac_len++;
7179                 if (len < buf_size)
7180                     buf[len++] = *num_iter;
7181                 if (*num_iter == '.') dot = 1;
7182                 if (frac_len >= cur_precision) break;
7183                 num_iter++;
7184             }
7185 
7186             /* fill number up to precision */
7187             while (frac_len < cur_precision) {
7188                 if (!dot && len < buf_size) {
7189                     buf[len++] = '.';
7190                     dot = 1;
7191                 }
7192                 if (len < buf_size)
7193                     buf[len++] = '0';
7194                 frac_len++;
7195             }
7196 
7197             /* fill right padding up to width characters */
7198             if (flag & NK_ARG_FLAG_LEFT) {
7199                 while ((padding-- > 0) && (len < buf_size))
7200                     buf[len++] = ' ';
7201             }
7202         } else {
7203             /* Specifier not supported: g,G,e,E,p,z */
7204             NK_ASSERT(0 && "specifier is not supported!");
7205             return result;
7206         }
7207     }
7208     buf[(len >= buf_size)?(buf_size-1):len] = 0;
7209     result = (len >= buf_size)?-1:len;
7210     return result;
7211 }
7212 #endif
7213 NK_LIB int
7214 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
7215 {
7216     int result = -1;
7217     NK_ASSERT(buf);
7218     NK_ASSERT(buf_size);
7219     if (!buf || !buf_size || !fmt) return 0;
7220 #ifdef NK_INCLUDE_STANDARD_IO
7221     result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
7222     result = (result >= buf_size) ? -1: result;
7223     buf[buf_size-1] = 0;
7224 #else
7225     result = nk_vsnprintf(buf, buf_size, fmt, args);
7226 #endif
7227     return result;
7228 }
7229 #endif
7230 NK_API nk_hash
7231 nk_murmur_hash(const void * key, int len, nk_hash seed)
7232 {
7233     /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
7234     #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
7235 
7236     nk_uint h1 = seed;
7237     nk_uint k1;
7238     const nk_byte *data = (const nk_byte*)key;
7239     const nk_byte *keyptr = data;
7240     nk_byte *k1ptr;
7241     const int bsize = sizeof(k1);
7242     const int nblocks = len/4;
7243 
7244     const nk_uint c1 = 0xcc9e2d51;
7245     const nk_uint c2 = 0x1b873593;
7246     const nk_byte *tail;
7247     int i;
7248 
7249     /* body */
7250     if (!key) return 0;
7251     for (i = 0; i < nblocks; ++i, keyptr += bsize) {
7252         k1ptr = (nk_byte*)&k1;
7253         k1ptr[0] = keyptr[0];
7254         k1ptr[1] = keyptr[1];
7255         k1ptr[2] = keyptr[2];
7256         k1ptr[3] = keyptr[3];
7257 
7258         k1 *= c1;
7259         k1 = NK_ROTL(k1,15);
7260         k1 *= c2;
7261 
7262         h1 ^= k1;
7263         h1 = NK_ROTL(h1,13);
7264         h1 = h1*5+0xe6546b64;
7265     }
7266 
7267     /* tail */
7268     tail = (const nk_byte*)(data + nblocks*4);
7269     k1 = 0;
7270     switch (len & 3) {
7271         case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
7272         case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
7273         case 1: k1 ^= tail[0];
7274             k1 *= c1;
7275             k1 = NK_ROTL(k1,15);
7276             k1 *= c2;
7277             h1 ^= k1;
7278             break;
7279         default: break;
7280     }
7281 
7282     /* finalization */
7283     h1 ^= (nk_uint)len;
7284     /* fmix32 */
7285     h1 ^= h1 >> 16;
7286     h1 *= 0x85ebca6b;
7287     h1 ^= h1 >> 13;
7288     h1 *= 0xc2b2ae35;
7289     h1 ^= h1 >> 16;
7290 
7291     #undef NK_ROTL
7292     return h1;
7293 }
7294 #ifdef NK_INCLUDE_STANDARD_IO
7295 NK_LIB char*
7296 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
7297 {
7298     char *buf;
7299     FILE *fd;
7300     long ret;
7301 
7302     NK_ASSERT(path);
7303     NK_ASSERT(siz);
7304     NK_ASSERT(alloc);
7305     if (!path || !siz || !alloc)
7306         return 0;
7307 
7308     fd = fopen(path, "rb");
7309     if (!fd) return 0;
7310     fseek(fd, 0, SEEK_END);
7311     ret = ftell(fd);
7312     if (ret < 0) {
7313         fclose(fd);
7314         return 0;
7315     }
7316     *siz = (nk_size)ret;
7317     fseek(fd, 0, SEEK_SET);
7318     buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
7319     NK_ASSERT(buf);
7320     if (!buf) {
7321         fclose(fd);
7322         return 0;
7323     }
7324     *siz = (nk_size)fread(buf, 1,*siz, fd);
7325     fclose(fd);
7326     return buf;
7327 }
7328 #endif
7329 NK_LIB int
7330 nk_text_clamp(const struct nk_user_font *font, const char *text,
7331     int text_len, float space, int *glyphs, float *text_width,
7332     nk_rune *sep_list, int sep_count)
7333 {
7334     int i = 0;
7335     int glyph_len = 0;
7336     float last_width = 0;
7337     nk_rune unicode = 0;
7338     float width = 0;
7339     int len = 0;
7340     int g = 0;
7341     float s;
7342 
7343     int sep_len = 0;
7344     int sep_g = 0;
7345     float sep_width = 0;
7346     sep_count = NK_MAX(sep_count,0);
7347 
7348     glyph_len = nk_utf_decode(text, &unicode, text_len);
7349     while (glyph_len && (width < space) && (len < text_len)) {
7350         len += glyph_len;
7351         s = font->width(font->userdata, font->height, text, len);
7352         for (i = 0; i < sep_count; ++i) {
7353             if (unicode != sep_list[i]) continue;
7354             sep_width = last_width = width;
7355             sep_g = g+1;
7356             sep_len = len;
7357             break;
7358         }
7359         if (i == sep_count){
7360             last_width = sep_width = width;
7361             sep_g = g+1;
7362         }
7363         width = s;
7364         glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
7365         g++;
7366     }
7367     if (len >= text_len) {
7368         *glyphs = g;
7369         *text_width = last_width;
7370         return len;
7371     } else {
7372         *glyphs = sep_g;
7373         *text_width = sep_width;
7374         return (!sep_len) ? len: sep_len;
7375     }
7376 }
7377 NK_LIB struct nk_vec2
7378 nk_text_calculate_text_bounds(const struct nk_user_font *font,
7379     const char *begin, int byte_len, float row_height, const char **remaining,
7380     struct nk_vec2 *out_offset, int *glyphs, int op)
7381 {
7382     float line_height = row_height;
7383     struct nk_vec2 text_size = nk_vec2(0,0);
7384     float line_width = 0.0f;
7385 
7386     float glyph_width;
7387     int glyph_len = 0;
7388     nk_rune unicode = 0;
7389     int text_len = 0;
7390     if (!begin || byte_len <= 0 || !font)
7391         return nk_vec2(0,row_height);
7392 
7393     glyph_len = nk_utf_decode(begin, &unicode, byte_len);
7394     if (!glyph_len) return text_size;
7395     glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
7396 
7397     *glyphs = 0;
7398     while ((text_len < byte_len) && glyph_len) {
7399         if (unicode == '\n') {
7400             text_size.x = NK_MAX(text_size.x, line_width);
7401             text_size.y += line_height;
7402             line_width = 0;
7403             *glyphs+=1;
7404             if (op == NK_STOP_ON_NEW_LINE)
7405                 break;
7406 
7407             text_len++;
7408             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7409             continue;
7410         }
7411 
7412         if (unicode == '\r') {
7413             text_len++;
7414             *glyphs+=1;
7415             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7416             continue;
7417         }
7418 
7419         *glyphs = *glyphs + 1;
7420         text_len += glyph_len;
7421         line_width += (float)glyph_width;
7422         glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
7423         glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
7424         continue;
7425     }
7426 
7427     if (text_size.x < line_width)
7428         text_size.x = line_width;
7429     if (out_offset)
7430         *out_offset = nk_vec2(line_width, text_size.y + line_height);
7431     if (line_width > 0 || text_size.y == 0.0f)
7432         text_size.y += line_height;
7433     if (remaining)
7434         *remaining = begin+text_len;
7435     return text_size;
7436 }
7437 
7438 
7439 
7440 
7441 
7442 /* ==============================================================
7443  *
7444  *                          COLOR
7445  *
7446  * ===============================================================*/
7447 NK_INTERN int
7448 nk_parse_hex(const char *p, int length)
7449 {
7450     int i = 0;
7451     int len = 0;
7452     while (len < length) {
7453         i <<= 4;
7454         if (p[len] >= 'a' && p[len] <= 'f')
7455             i += ((p[len] - 'a') + 10);
7456         else if (p[len] >= 'A' && p[len] <= 'F')
7457             i += ((p[len] - 'A') + 10);
7458         else i += (p[len] - '0');
7459         len++;
7460     }
7461     return i;
7462 }
7463 NK_API struct nk_color
7464 nk_rgba(int r, int g, int b, int a)
7465 {
7466     struct nk_color ret;
7467     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
7468     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
7469     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
7470     ret.a = (nk_byte)NK_CLAMP(0, a, 255);
7471     return ret;
7472 }
7473 NK_API struct nk_color
7474 nk_rgb_hex(const char *rgb)
7475 {
7476     struct nk_color col;
7477     const char *c = rgb;
7478     if (*c == '#') c++;
7479     col.r = (nk_byte)nk_parse_hex(c, 2);
7480     col.g = (nk_byte)nk_parse_hex(c+2, 2);
7481     col.b = (nk_byte)nk_parse_hex(c+4, 2);
7482     col.a = 255;
7483     return col;
7484 }
7485 NK_API struct nk_color
7486 nk_rgba_hex(const char *rgb)
7487 {
7488     struct nk_color col;
7489     const char *c = rgb;
7490     if (*c == '#') c++;
7491     col.r = (nk_byte)nk_parse_hex(c, 2);
7492     col.g = (nk_byte)nk_parse_hex(c+2, 2);
7493     col.b = (nk_byte)nk_parse_hex(c+4, 2);
7494     col.a = (nk_byte)nk_parse_hex(c+6, 2);
7495     return col;
7496 }
7497 NK_API void
7498 nk_color_hex_rgba(char *output, struct nk_color col)
7499 {
7500     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
7501     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
7502     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
7503     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
7504     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
7505     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
7506     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
7507     output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
7508     output[7] = (char)NK_TO_HEX((col.a & 0x0F));
7509     output[8] = '\0';
7510     #undef NK_TO_HEX
7511 }
7512 NK_API void
7513 nk_color_hex_rgb(char *output, struct nk_color col)
7514 {
7515     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
7516     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
7517     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
7518     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
7519     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
7520     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
7521     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
7522     output[6] = '\0';
7523     #undef NK_TO_HEX
7524 }
7525 NK_API struct nk_color
7526 nk_rgba_iv(const int *c)
7527 {
7528     return nk_rgba(c[0], c[1], c[2], c[3]);
7529 }
7530 NK_API struct nk_color
7531 nk_rgba_bv(const nk_byte *c)
7532 {
7533     return nk_rgba(c[0], c[1], c[2], c[3]);
7534 }
7535 NK_API struct nk_color
7536 nk_rgb(int r, int g, int b)
7537 {
7538     struct nk_color ret;
7539     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
7540     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
7541     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
7542     ret.a = (nk_byte)255;
7543     return ret;
7544 }
7545 NK_API struct nk_color
7546 nk_rgb_iv(const int *c)
7547 {
7548     return nk_rgb(c[0], c[1], c[2]);
7549 }
7550 NK_API struct nk_color
7551 nk_rgb_bv(const nk_byte* c)
7552 {
7553     return nk_rgb(c[0], c[1], c[2]);
7554 }
7555 NK_API struct nk_color
7556 nk_rgba_u32(nk_uint in)
7557 {
7558     struct nk_color ret;
7559     ret.r = (in & 0xFF);
7560     ret.g = ((in >> 8) & 0xFF);
7561     ret.b = ((in >> 16) & 0xFF);
7562     ret.a = (nk_byte)((in >> 24) & 0xFF);
7563     return ret;
7564 }
7565 NK_API struct nk_color
7566 nk_rgba_f(float r, float g, float b, float a)
7567 {
7568     struct nk_color ret;
7569     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
7570     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
7571     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
7572     ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
7573     return ret;
7574 }
7575 NK_API struct nk_color
7576 nk_rgba_fv(const float *c)
7577 {
7578     return nk_rgba_f(c[0], c[1], c[2], c[3]);
7579 }
7580 NK_API struct nk_color
7581 nk_rgba_cf(struct nk_colorf c)
7582 {
7583     return nk_rgba_f(c.r, c.g, c.b, c.a);
7584 }
7585 NK_API struct nk_color
7586 nk_rgb_f(float r, float g, float b)
7587 {
7588     struct nk_color ret;
7589     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
7590     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
7591     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
7592     ret.a = 255;
7593     return ret;
7594 }
7595 NK_API struct nk_color
7596 nk_rgb_fv(const float *c)
7597 {
7598     return nk_rgb_f(c[0], c[1], c[2]);
7599 }
7600 NK_API struct nk_color
7601 nk_rgb_cf(struct nk_colorf c)
7602 {
7603     return nk_rgb_f(c.r, c.g, c.b);
7604 }
7605 NK_API struct nk_color
7606 nk_hsv(int h, int s, int v)
7607 {
7608     return nk_hsva(h, s, v, 255);
7609 }
7610 NK_API struct nk_color
7611 nk_hsv_iv(const int *c)
7612 {
7613     return nk_hsv(c[0], c[1], c[2]);
7614 }
7615 NK_API struct nk_color
7616 nk_hsv_bv(const nk_byte *c)
7617 {
7618     return nk_hsv(c[0], c[1], c[2]);
7619 }
7620 NK_API struct nk_color
7621 nk_hsv_f(float h, float s, float v)
7622 {
7623     return nk_hsva_f(h, s, v, 1.0f);
7624 }
7625 NK_API struct nk_color
7626 nk_hsv_fv(const float *c)
7627 {
7628     return nk_hsv_f(c[0], c[1], c[2]);
7629 }
7630 NK_API struct nk_color
7631 nk_hsva(int h, int s, int v, int a)
7632 {
7633     float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
7634     float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
7635     float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
7636     float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
7637     return nk_hsva_f(hf, sf, vf, af);
7638 }
7639 NK_API struct nk_color
7640 nk_hsva_iv(const int *c)
7641 {
7642     return nk_hsva(c[0], c[1], c[2], c[3]);
7643 }
7644 NK_API struct nk_color
7645 nk_hsva_bv(const nk_byte *c)
7646 {
7647     return nk_hsva(c[0], c[1], c[2], c[3]);
7648 }
7649 NK_API struct nk_colorf
7650 nk_hsva_colorf(float h, float s, float v, float a)
7651 {
7652     int i;
7653     float p, q, t, f;
7654     struct nk_colorf out = {0,0,0,0};
7655     if (s <= 0.0f) {
7656         out.r = v; out.g = v; out.b = v; out.a = a;
7657         return out;
7658     }
7659     h = h / (60.0f/360.0f);
7660     i = (int)h;
7661     f = h - (float)i;
7662     p = v * (1.0f - s);
7663     q = v * (1.0f - (s * f));
7664     t = v * (1.0f - s * (1.0f - f));
7665 
7666     switch (i) {
7667     case 0: default: out.r = v; out.g = t; out.b = p; break;
7668     case 1: out.r = q; out.g = v; out.b = p; break;
7669     case 2: out.r = p; out.g = v; out.b = t; break;
7670     case 3: out.r = p; out.g = q; out.b = v; break;
7671     case 4: out.r = t; out.g = p; out.b = v; break;
7672     case 5: out.r = v; out.g = p; out.b = q; break;}
7673     out.a = a;
7674     return out;
7675 }
7676 NK_API struct nk_colorf
7677 nk_hsva_colorfv(float *c)
7678 {
7679     return nk_hsva_colorf(c[0], c[1], c[2], c[3]);
7680 }
7681 NK_API struct nk_color
7682 nk_hsva_f(float h, float s, float v, float a)
7683 {
7684     struct nk_colorf c = nk_hsva_colorf(h, s, v, a);
7685     return nk_rgba_f(c.r, c.g, c.b, c.a);
7686 }
7687 NK_API struct nk_color
7688 nk_hsva_fv(const float *c)
7689 {
7690     return nk_hsva_f(c[0], c[1], c[2], c[3]);
7691 }
7692 NK_API nk_uint
7693 nk_color_u32(struct nk_color in)
7694 {
7695     nk_uint out = (nk_uint)in.r;
7696     out |= ((nk_uint)in.g << 8);
7697     out |= ((nk_uint)in.b << 16);
7698     out |= ((nk_uint)in.a << 24);
7699     return out;
7700 }
7701 NK_API void
7702 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
7703 {
7704     NK_STORAGE const float s = 1.0f/255.0f;
7705     *r = (float)in.r * s;
7706     *g = (float)in.g * s;
7707     *b = (float)in.b * s;
7708     *a = (float)in.a * s;
7709 }
7710 NK_API void
7711 nk_color_fv(float *c, struct nk_color in)
7712 {
7713     nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
7714 }
7715 NK_API struct nk_colorf
7716 nk_color_cf(struct nk_color in)
7717 {
7718     struct nk_colorf o;
7719     nk_color_f(&o.r, &o.g, &o.b, &o.a, in);
7720     return o;
7721 }
7722 NK_API void
7723 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
7724 {
7725     NK_STORAGE const double s = 1.0/255.0;
7726     *r = (double)in.r * s;
7727     *g = (double)in.g * s;
7728     *b = (double)in.b * s;
7729     *a = (double)in.a * s;
7730 }
7731 NK_API void
7732 nk_color_dv(double *c, struct nk_color in)
7733 {
7734     nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
7735 }
7736 NK_API void
7737 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
7738 {
7739     float a;
7740     nk_color_hsva_f(out_h, out_s, out_v, &a, in);
7741 }
7742 NK_API void
7743 nk_color_hsv_fv(float *out, struct nk_color in)
7744 {
7745     float a;
7746     nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
7747 }
7748 NK_API void
7749 nk_colorf_hsva_f(float *out_h, float *out_s,
7750     float *out_v, float *out_a, struct nk_colorf in)
7751 {
7752     float chroma;
7753     float K = 0.0f;
7754     if (in.g < in.b) {
7755         const float t = in.g; in.g = in.b; in.b = t;
7756         K = -1.f;
7757     }
7758     if (in.r < in.g) {
7759         const float t = in.r; in.r = in.g; in.g = t;
7760         K = -2.f/6.0f - K;
7761     }
7762     chroma = in.r - ((in.g < in.b) ? in.g: in.b);
7763     *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f));
7764     *out_s = chroma / (in.r + 1e-20f);
7765     *out_v = in.r;
7766     *out_a = in.a;
7767 
7768 }
7769 NK_API void
7770 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
7771 {
7772     nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in);
7773 }
7774 NK_API void
7775 nk_color_hsva_f(float *out_h, float *out_s,
7776     float *out_v, float *out_a, struct nk_color in)
7777 {
7778     struct nk_colorf col;
7779     nk_color_f(&col.r,&col.g,&col.b,&col.a, in);
7780     nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col);
7781 }
7782 NK_API void
7783 nk_color_hsva_fv(float *out, struct nk_color in)
7784 {
7785     nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
7786 }
7787 NK_API void
7788 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
7789                 int *out_a, struct nk_color in)
7790 {
7791     float h,s,v,a;
7792     nk_color_hsva_f(&h, &s, &v, &a, in);
7793     *out_h = (nk_byte)(h * 255.0f);
7794     *out_s = (nk_byte)(s * 255.0f);
7795     *out_v = (nk_byte)(v * 255.0f);
7796     *out_a = (nk_byte)(a * 255.0f);
7797 }
7798 NK_API void
7799 nk_color_hsva_iv(int *out, struct nk_color in)
7800 {
7801     nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
7802 }
7803 NK_API void
7804 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
7805 {
7806     int tmp[4];
7807     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7808     out[0] = (nk_byte)tmp[0];
7809     out[1] = (nk_byte)tmp[1];
7810     out[2] = (nk_byte)tmp[2];
7811     out[3] = (nk_byte)tmp[3];
7812 }
7813 NK_API void
7814 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
7815 {
7816     int tmp[4];
7817     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7818     *h = (nk_byte)tmp[0];
7819     *s = (nk_byte)tmp[1];
7820     *v = (nk_byte)tmp[2];
7821     *a = (nk_byte)tmp[3];
7822 }
7823 NK_API void
7824 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
7825 {
7826     int a;
7827     nk_color_hsva_i(out_h, out_s, out_v, &a, in);
7828 }
7829 NK_API void
7830 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
7831 {
7832     int tmp[4];
7833     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
7834     *out_h = (nk_byte)tmp[0];
7835     *out_s = (nk_byte)tmp[1];
7836     *out_v = (nk_byte)tmp[2];
7837 }
7838 NK_API void
7839 nk_color_hsv_iv(int *out, struct nk_color in)
7840 {
7841     nk_color_hsv_i(&out[0], &out[1], &out[2], in);
7842 }
7843 NK_API void
7844 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
7845 {
7846     int tmp[4];
7847     nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
7848     out[0] = (nk_byte)tmp[0];
7849     out[1] = (nk_byte)tmp[1];
7850     out[2] = (nk_byte)tmp[2];
7851 }
7852 
7853 
7854 
7855 
7856 
7857 /* ===============================================================
7858  *
7859  *                              UTF-8
7860  *
7861  * ===============================================================*/
7862 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
7863 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
7864 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
7865 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
7866 
7867 NK_INTERN int
7868 nk_utf_validate(nk_rune *u, int i)
7869 {
7870     NK_ASSERT(u);
7871     if (!u) return 0;
7872     if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
7873          NK_BETWEEN(*u, 0xD800, 0xDFFF))
7874             *u = NK_UTF_INVALID;
7875     for (i = 1; *u > nk_utfmax[i]; ++i);
7876     return i;
7877 }
7878 NK_INTERN nk_rune
7879 nk_utf_decode_byte(char c, int *i)
7880 {
7881     NK_ASSERT(i);
7882     if (!i) return 0;
7883     for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
7884         if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
7885             return (nk_byte)(c & ~nk_utfmask[*i]);
7886     }
7887     return 0;
7888 }
7889 NK_API int
7890 nk_utf_decode(const char *c, nk_rune *u, int clen)
7891 {
7892     int i, j, len, type=0;
7893     nk_rune udecoded;
7894 
7895     NK_ASSERT(c);
7896     NK_ASSERT(u);
7897 
7898     if (!c || !u) return 0;
7899     if (!clen) return 0;
7900     *u = NK_UTF_INVALID;
7901 
7902     udecoded = nk_utf_decode_byte(c[0], &len);
7903     if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
7904         return 1;
7905 
7906     for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
7907         udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
7908         if (type != 0)
7909             return j;
7910     }
7911     if (j < len)
7912         return 0;
7913     *u = udecoded;
7914     nk_utf_validate(u, len);
7915     return len;
7916 }
7917 NK_INTERN char
7918 nk_utf_encode_byte(nk_rune u, int i)
7919 {
7920     return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
7921 }
7922 NK_API int
7923 nk_utf_encode(nk_rune u, char *c, int clen)
7924 {
7925     int len, i;
7926     len = nk_utf_validate(&u, 0);
7927     if (clen < len || !len || len > NK_UTF_SIZE)
7928         return 0;
7929 
7930     for (i = len - 1; i != 0; --i) {
7931         c[i] = nk_utf_encode_byte(u, 0);
7932         u >>= 6;
7933     }
7934     c[0] = nk_utf_encode_byte(u, len);
7935     return len;
7936 }
7937 NK_API int
7938 nk_utf_len(const char *str, int len)
7939 {
7940     const char *text;
7941     int glyphs = 0;
7942     int text_len;
7943     int glyph_len;
7944     int src_len = 0;
7945     nk_rune unicode;
7946 
7947     NK_ASSERT(str);
7948     if (!str || !len) return 0;
7949 
7950     text = str;
7951     text_len = len;
7952     glyph_len = nk_utf_decode(text, &unicode, text_len);
7953     while (glyph_len && src_len < len) {
7954         glyphs++;
7955         src_len = src_len + glyph_len;
7956         glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
7957     }
7958     return glyphs;
7959 }
7960 NK_API const char*
7961 nk_utf_at(const char *buffer, int length, int index,
7962     nk_rune *unicode, int *len)
7963 {
7964     int i = 0;
7965     int src_len = 0;
7966     int glyph_len = 0;
7967     const char *text;
7968     int text_len;
7969 
7970     NK_ASSERT(buffer);
7971     NK_ASSERT(unicode);
7972     NK_ASSERT(len);
7973 
7974     if (!buffer || !unicode || !len) return 0;
7975     if (index < 0) {
7976         *unicode = NK_UTF_INVALID;
7977         *len = 0;
7978         return 0;
7979     }
7980 
7981     text = buffer;
7982     text_len = length;
7983     glyph_len = nk_utf_decode(text, unicode, text_len);
7984     while (glyph_len) {
7985         if (i == index) {
7986             *len = glyph_len;
7987             break;
7988         }
7989 
7990         i++;
7991         src_len = src_len + glyph_len;
7992         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7993     }
7994     if (i != index) return 0;
7995     return buffer + src_len;
7996 }
7997 
7998 
7999 
8000 
8001 
8002 /* ==============================================================
8003  *
8004  *                          BUFFER
8005  *
8006  * ===============================================================*/
8007 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
8008 NK_LIB void*
8009 nk_malloc(nk_handle unused, void *old,nk_size size)
8010 {
8011     NK_UNUSED(unused);
8012     NK_UNUSED(old);
8013     return malloc(size);
8014 }
8015 NK_LIB void
8016 nk_mfree(nk_handle unused, void *ptr)
8017 {
8018     NK_UNUSED(unused);
8019     free(ptr);
8020 }
8021 NK_API void
8022 nk_buffer_init_default(struct nk_buffer *buffer)
8023 {
8024     struct nk_allocator alloc;
8025     alloc.userdata.ptr = 0;
8026     alloc.alloc = nk_malloc;
8027     alloc.free = nk_mfree;
8028     nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
8029 }
8030 #endif
8031 
8032 NK_API void
8033 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
8034     nk_size initial_size)
8035 {
8036     NK_ASSERT(b);
8037     NK_ASSERT(a);
8038     NK_ASSERT(initial_size);
8039     if (!b || !a || !initial_size) return;
8040 
8041     nk_zero(b, sizeof(*b));
8042     b->type = NK_BUFFER_DYNAMIC;
8043     b->memory.ptr = a->alloc(a->userdata,0, initial_size);
8044     b->memory.size = initial_size;
8045     b->size = initial_size;
8046     b->grow_factor = 2.0f;
8047     b->pool = *a;
8048 }
8049 NK_API void
8050 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
8051 {
8052     NK_ASSERT(b);
8053     NK_ASSERT(m);
8054     NK_ASSERT(size);
8055     if (!b || !m || !size) return;
8056 
8057     nk_zero(b, sizeof(*b));
8058     b->type = NK_BUFFER_FIXED;
8059     b->memory.ptr = m;
8060     b->memory.size = size;
8061     b->size = size;
8062 }
8063 NK_LIB void*
8064 nk_buffer_align(void *unaligned,
8065     nk_size align, nk_size *alignment,
8066     enum nk_buffer_allocation_type type)
8067 {
8068     void *memory = 0;
8069     switch (type) {
8070     default:
8071     case NK_BUFFER_MAX:
8072     case NK_BUFFER_FRONT:
8073         if (align) {
8074             memory = NK_ALIGN_PTR(unaligned, align);
8075             *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
8076         } else {
8077             memory = unaligned;
8078             *alignment = 0;
8079         }
8080         break;
8081     case NK_BUFFER_BACK:
8082         if (align) {
8083             memory = NK_ALIGN_PTR_BACK(unaligned, align);
8084             *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
8085         } else {
8086             memory = unaligned;
8087             *alignment = 0;
8088         }
8089         break;
8090     }
8091     return memory;
8092 }
8093 NK_LIB void*
8094 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
8095 {
8096     void *temp;
8097     nk_size buffer_size;
8098 
8099     NK_ASSERT(b);
8100     NK_ASSERT(size);
8101     if (!b || !size || !b->pool.alloc || !b->pool.free)
8102         return 0;
8103 
8104     buffer_size = b->memory.size;
8105     temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
8106     NK_ASSERT(temp);
8107     if (!temp) return 0;
8108 
8109     *size = capacity;
8110     if (temp != b->memory.ptr) {
8111         NK_MEMCPY(temp, b->memory.ptr, buffer_size);
8112         b->pool.free(b->pool.userdata, b->memory.ptr);
8113     }
8114 
8115     if (b->size == buffer_size) {
8116         /* no back buffer so just set correct size */
8117         b->size = capacity;
8118         return temp;
8119     } else {
8120         /* copy back buffer to the end of the new buffer */
8121         void *dst, *src;
8122         nk_size back_size;
8123         back_size = buffer_size - b->size;
8124         dst = nk_ptr_add(void, temp, capacity - back_size);
8125         src = nk_ptr_add(void, temp, b->size);
8126         NK_MEMCPY(dst, src, back_size);
8127         b->size = capacity - back_size;
8128     }
8129     return temp;
8130 }
8131 NK_LIB void*
8132 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
8133     nk_size size, nk_size align)
8134 {
8135     int full;
8136     nk_size alignment;
8137     void *unaligned;
8138     void *memory;
8139 
8140     NK_ASSERT(b);
8141     NK_ASSERT(size);
8142     if (!b || !size) return 0;
8143     b->needed += size;
8144 
8145     /* calculate total size with needed alignment + size */
8146     if (type == NK_BUFFER_FRONT)
8147         unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
8148     else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
8149     memory = nk_buffer_align(unaligned, align, &alignment, type);
8150 
8151     /* check if buffer has enough memory*/
8152     if (type == NK_BUFFER_FRONT)
8153         full = ((b->allocated + size + alignment) > b->size);
8154     else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
8155 
8156     if (full) {
8157         nk_size capacity;
8158         if (b->type != NK_BUFFER_DYNAMIC)
8159             return 0;
8160         NK_ASSERT(b->pool.alloc && b->pool.free);
8161         if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
8162             return 0;
8163 
8164         /* buffer is full so allocate bigger buffer if dynamic */
8165         capacity = (nk_size)((float)b->memory.size * b->grow_factor);
8166         capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
8167         b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
8168         if (!b->memory.ptr) return 0;
8169 
8170         /* align newly allocated pointer */
8171         if (type == NK_BUFFER_FRONT)
8172             unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
8173         else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
8174         memory = nk_buffer_align(unaligned, align, &alignment, type);
8175     }
8176     if (type == NK_BUFFER_FRONT)
8177         b->allocated += size + alignment;
8178     else b->size -= (size + alignment);
8179     b->needed += alignment;
8180     b->calls++;
8181     return memory;
8182 }
8183 NK_API void
8184 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type,
8185     const void *memory, nk_size size, nk_size align)
8186 {
8187     void *mem = nk_buffer_alloc(b, type, size, align);
8188     if (!mem) return;
8189     NK_MEMCPY(mem, memory, size);
8190 }
8191 NK_API void
8192 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
8193 {
8194     NK_ASSERT(buffer);
8195     if (!buffer) return;
8196     buffer->marker[type].active = nk_true;
8197     if (type == NK_BUFFER_BACK)
8198         buffer->marker[type].offset = buffer->size;
8199     else buffer->marker[type].offset = buffer->allocated;
8200 }
8201 NK_API void
8202 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
8203 {
8204     NK_ASSERT(buffer);
8205     if (!buffer) return;
8206     if (type == NK_BUFFER_BACK) {
8207         /* reset back buffer either back to marker or empty */
8208         buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
8209         if (buffer->marker[type].active)
8210             buffer->size = buffer->marker[type].offset;
8211         else buffer->size = buffer->memory.size;
8212         buffer->marker[type].active = nk_false;
8213     } else {
8214         /* reset front buffer either back to back marker or empty */
8215         buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
8216         if (buffer->marker[type].active)
8217             buffer->allocated = buffer->marker[type].offset;
8218         else buffer->allocated = 0;
8219         buffer->marker[type].active = nk_false;
8220     }
8221 }
8222 NK_API void
8223 nk_buffer_clear(struct nk_buffer *b)
8224 {
8225     NK_ASSERT(b);
8226     if (!b) return;
8227     b->allocated = 0;
8228     b->size = b->memory.size;
8229     b->calls = 0;
8230     b->needed = 0;
8231 }
8232 NK_API void
8233 nk_buffer_free(struct nk_buffer *b)
8234 {
8235     NK_ASSERT(b);
8236     if (!b || !b->memory.ptr) return;
8237     if (b->type == NK_BUFFER_FIXED) return;
8238     if (!b->pool.free) return;
8239     NK_ASSERT(b->pool.free);
8240     b->pool.free(b->pool.userdata, b->memory.ptr);
8241 }
8242 NK_API void
8243 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
8244 {
8245     NK_ASSERT(b);
8246     NK_ASSERT(s);
8247     if (!s || !b) return;
8248     s->allocated = b->allocated;
8249     s->size =  b->memory.size;
8250     s->needed = b->needed;
8251     s->memory = b->memory.ptr;
8252     s->calls = b->calls;
8253 }
8254 NK_API void*
8255 nk_buffer_memory(struct nk_buffer *buffer)
8256 {
8257     NK_ASSERT(buffer);
8258     if (!buffer) return 0;
8259     return buffer->memory.ptr;
8260 }
8261 NK_API const void*
8262 nk_buffer_memory_const(const struct nk_buffer *buffer)
8263 {
8264     NK_ASSERT(buffer);
8265     if (!buffer) return 0;
8266     return buffer->memory.ptr;
8267 }
8268 NK_API nk_size
8269 nk_buffer_total(struct nk_buffer *buffer)
8270 {
8271     NK_ASSERT(buffer);
8272     if (!buffer) return 0;
8273     return buffer->memory.size;
8274 }
8275 
8276 
8277 
8278 
8279 
8280 /* ===============================================================
8281  *
8282  *                              STRING
8283  *
8284  * ===============================================================*/
8285 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
8286 NK_API void
8287 nk_str_init_default(struct nk_str *str)
8288 {
8289     struct nk_allocator alloc;
8290     alloc.userdata.ptr = 0;
8291     alloc.alloc = nk_malloc;
8292     alloc.free = nk_mfree;
8293     nk_buffer_init(&str->buffer, &alloc, 32);
8294     str->len = 0;
8295 }
8296 #endif
8297 
8298 NK_API void
8299 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
8300 {
8301     nk_buffer_init(&str->buffer, alloc, size);
8302     str->len = 0;
8303 }
8304 NK_API void
8305 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
8306 {
8307     nk_buffer_init_fixed(&str->buffer, memory, size);
8308     str->len = 0;
8309 }
8310 NK_API int
8311 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
8312 {
8313     char *mem;
8314     NK_ASSERT(s);
8315     NK_ASSERT(str);
8316     if (!s || !str || !len) return 0;
8317     mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
8318     if (!mem) return 0;
8319     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
8320     s->len += nk_utf_len(str, len);
8321     return len;
8322 }
8323 NK_API int
8324 nk_str_append_str_char(struct nk_str *s, const char *str)
8325 {
8326     return nk_str_append_text_char(s, str, nk_strlen(str));
8327 }
8328 NK_API int
8329 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
8330 {
8331     int i = 0;
8332     int byte_len = 0;
8333     nk_rune unicode;
8334     if (!str || !text || !len) return 0;
8335     for (i = 0; i < len; ++i)
8336         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
8337     nk_str_append_text_char(str, text, byte_len);
8338     return len;
8339 }
8340 NK_API int
8341 nk_str_append_str_utf8(struct nk_str *str, const char *text)
8342 {
8343     int runes = 0;
8344     int byte_len = 0;
8345     int num_runes = 0;
8346     int glyph_len = 0;
8347     nk_rune unicode;
8348     if (!str || !text) return 0;
8349 
8350     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
8351     while (unicode != '\0' && glyph_len) {
8352         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
8353         byte_len += glyph_len;
8354         num_runes++;
8355     }
8356     nk_str_append_text_char(str, text, byte_len);
8357     return runes;
8358 }
8359 NK_API int
8360 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
8361 {
8362     int i = 0;
8363     int byte_len = 0;
8364     nk_glyph glyph;
8365 
8366     NK_ASSERT(str);
8367     if (!str || !text || !len) return 0;
8368     for (i = 0; i < len; ++i) {
8369         byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
8370         if (!byte_len) break;
8371         nk_str_append_text_char(str, glyph, byte_len);
8372     }
8373     return len;
8374 }
8375 NK_API int
8376 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
8377 {
8378     int i = 0;
8379     nk_glyph glyph;
8380     int byte_len;
8381     NK_ASSERT(str);
8382     if (!str || !runes) return 0;
8383     while (runes[i] != '\0') {
8384         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8385         nk_str_append_text_char(str, glyph, byte_len);
8386         i++;
8387     }
8388     return i;
8389 }
8390 NK_API int
8391 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
8392 {
8393     int i;
8394     void *mem;
8395     char *src;
8396     char *dst;
8397 
8398     int copylen;
8399     NK_ASSERT(s);
8400     NK_ASSERT(str);
8401     NK_ASSERT(len >= 0);
8402     if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
8403     if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
8404         (s->buffer.type == NK_BUFFER_FIXED)) return 0;
8405 
8406     copylen = (int)s->buffer.allocated - pos;
8407     if (!copylen) {
8408         nk_str_append_text_char(s, str, len);
8409         return 1;
8410     }
8411     mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
8412     if (!mem) return 0;
8413 
8414     /* memmove */
8415     NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
8416     NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
8417     dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
8418     src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
8419     for (i = 0; i < copylen; ++i) *dst-- = *src--;
8420     mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
8421     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
8422     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8423     return 1;
8424 }
8425 NK_API int
8426 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
8427 {
8428     int glyph_len;
8429     nk_rune unicode;
8430     const char *begin;
8431     const char *buffer;
8432 
8433     NK_ASSERT(str);
8434     NK_ASSERT(cstr);
8435     NK_ASSERT(len);
8436     if (!str || !cstr || !len) return 0;
8437     begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
8438     if (!str->len)
8439         return nk_str_append_text_char(str, cstr, len);
8440     buffer = nk_str_get_const(str);
8441     if (!begin) return 0;
8442     return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
8443 }
8444 NK_API int
8445 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
8446 {
8447     return nk_str_insert_text_utf8(str, pos, text, len);
8448 }
8449 NK_API int
8450 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
8451 {
8452     return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
8453 }
8454 NK_API int
8455 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
8456 {
8457     int i = 0;
8458     int byte_len = 0;
8459     nk_rune unicode;
8460 
8461     NK_ASSERT(str);
8462     NK_ASSERT(text);
8463     if (!str || !text || !len) return 0;
8464     for (i = 0; i < len; ++i)
8465         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
8466     nk_str_insert_at_rune(str, pos, text, byte_len);
8467     return len;
8468 }
8469 NK_API int
8470 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
8471 {
8472     int runes = 0;
8473     int byte_len = 0;
8474     int num_runes = 0;
8475     int glyph_len = 0;
8476     nk_rune unicode;
8477     if (!str || !text) return 0;
8478 
8479     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
8480     while (unicode != '\0' && glyph_len) {
8481         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
8482         byte_len += glyph_len;
8483         num_runes++;
8484     }
8485     nk_str_insert_at_rune(str, pos, text, byte_len);
8486     return runes;
8487 }
8488 NK_API int
8489 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
8490 {
8491     int i = 0;
8492     int byte_len = 0;
8493     nk_glyph glyph;
8494 
8495     NK_ASSERT(str);
8496     if (!str || !runes || !len) return 0;
8497     for (i = 0; i < len; ++i) {
8498         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8499         if (!byte_len) break;
8500         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
8501     }
8502     return len;
8503 }
8504 NK_API int
8505 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
8506 {
8507     int i = 0;
8508     nk_glyph glyph;
8509     int byte_len;
8510     NK_ASSERT(str);
8511     if (!str || !runes) return 0;
8512     while (runes[i] != '\0') {
8513         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
8514         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
8515         i++;
8516     }
8517     return i;
8518 }
8519 NK_API void
8520 nk_str_remove_chars(struct nk_str *s, int len)
8521 {
8522     NK_ASSERT(s);
8523     NK_ASSERT(len >= 0);
8524     if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
8525     NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
8526     s->buffer.allocated -= (nk_size)len;
8527     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8528 }
8529 NK_API void
8530 nk_str_remove_runes(struct nk_str *str, int len)
8531 {
8532     int index;
8533     const char *begin;
8534     const char *end;
8535     nk_rune unicode;
8536 
8537     NK_ASSERT(str);
8538     NK_ASSERT(len >= 0);
8539     if (!str || len < 0) return;
8540     if (len >= str->len) {
8541         str->len = 0;
8542         return;
8543     }
8544 
8545     index = str->len - len;
8546     begin = nk_str_at_rune(str, index, &unicode, &len);
8547     end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
8548     nk_str_remove_chars(str, (int)(end-begin)+1);
8549 }
8550 NK_API void
8551 nk_str_delete_chars(struct nk_str *s, int pos, int len)
8552 {
8553     NK_ASSERT(s);
8554     if (!s || !len || (nk_size)pos > s->buffer.allocated ||
8555         (nk_size)(pos + len) > s->buffer.allocated) return;
8556 
8557     if ((nk_size)(pos + len) < s->buffer.allocated) {
8558         /* memmove */
8559         char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
8560         char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
8561         NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
8562         NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
8563         s->buffer.allocated -= (nk_size)len;
8564     } else nk_str_remove_chars(s, len);
8565     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
8566 }
8567 NK_API void
8568 nk_str_delete_runes(struct nk_str *s, int pos, int len)
8569 {
8570     char *temp;
8571     nk_rune unicode;
8572     char *begin;
8573     char *end;
8574     int unused;
8575 
8576     NK_ASSERT(s);
8577     NK_ASSERT(s->len >= pos + len);
8578     if (s->len < pos + len)
8579         len = NK_CLAMP(0, (s->len - pos), s->len);
8580     if (!len) return;
8581 
8582     temp = (char *)s->buffer.memory.ptr;
8583     begin = nk_str_at_rune(s, pos, &unicode, &unused);
8584     if (!begin) return;
8585     s->buffer.memory.ptr = begin;
8586     end = nk_str_at_rune(s, len, &unicode, &unused);
8587     s->buffer.memory.ptr = temp;
8588     if (!end) return;
8589     nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
8590 }
8591 NK_API char*
8592 nk_str_at_char(struct nk_str *s, int pos)
8593 {
8594     NK_ASSERT(s);
8595     if (!s || pos > (int)s->buffer.allocated) return 0;
8596     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
8597 }
8598 NK_API char*
8599 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
8600 {
8601     int i = 0;
8602     int src_len = 0;
8603     int glyph_len = 0;
8604     char *text;
8605     int text_len;
8606 
8607     NK_ASSERT(str);
8608     NK_ASSERT(unicode);
8609     NK_ASSERT(len);
8610 
8611     if (!str || !unicode || !len) return 0;
8612     if (pos < 0) {
8613         *unicode = 0;
8614         *len = 0;
8615         return 0;
8616     }
8617 
8618     text = (char*)str->buffer.memory.ptr;
8619     text_len = (int)str->buffer.allocated;
8620     glyph_len = nk_utf_decode(text, unicode, text_len);
8621     while (glyph_len) {
8622         if (i == pos) {
8623             *len = glyph_len;
8624             break;
8625         }
8626 
8627         i++;
8628         src_len = src_len + glyph_len;
8629         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
8630     }
8631     if (i != pos) return 0;
8632     return text + src_len;
8633 }
8634 NK_API const char*
8635 nk_str_at_char_const(const struct nk_str *s, int pos)
8636 {
8637     NK_ASSERT(s);
8638     if (!s || pos > (int)s->buffer.allocated) return 0;
8639     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
8640 }
8641 NK_API const char*
8642 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
8643 {
8644     int i = 0;
8645     int src_len = 0;
8646     int glyph_len = 0;
8647     char *text;
8648     int text_len;
8649 
8650     NK_ASSERT(str);
8651     NK_ASSERT(unicode);
8652     NK_ASSERT(len);
8653 
8654     if (!str || !unicode || !len) return 0;
8655     if (pos < 0) {
8656         *unicode = 0;
8657         *len = 0;
8658         return 0;
8659     }
8660 
8661     text = (char*)str->buffer.memory.ptr;
8662     text_len = (int)str->buffer.allocated;
8663     glyph_len = nk_utf_decode(text, unicode, text_len);
8664     while (glyph_len) {
8665         if (i == pos) {
8666             *len = glyph_len;
8667             break;
8668         }
8669 
8670         i++;
8671         src_len = src_len + glyph_len;
8672         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
8673     }
8674     if (i != pos) return 0;
8675     return text + src_len;
8676 }
8677 NK_API nk_rune
8678 nk_str_rune_at(const struct nk_str *str, int pos)
8679 {
8680     int len;
8681     nk_rune unicode = 0;
8682     nk_str_at_const(str, pos, &unicode, &len);
8683     return unicode;
8684 }
8685 NK_API char*
8686 nk_str_get(struct nk_str *s)
8687 {
8688     NK_ASSERT(s);
8689     if (!s || !s->len || !s->buffer.allocated) return 0;
8690     return (char*)s->buffer.memory.ptr;
8691 }
8692 NK_API const char*
8693 nk_str_get_const(const struct nk_str *s)
8694 {
8695     NK_ASSERT(s);
8696     if (!s || !s->len || !s->buffer.allocated) return 0;
8697     return (const char*)s->buffer.memory.ptr;
8698 }
8699 NK_API int
8700 nk_str_len(struct nk_str *s)
8701 {
8702     NK_ASSERT(s);
8703     if (!s || !s->len || !s->buffer.allocated) return 0;
8704     return s->len;
8705 }
8706 NK_API int
8707 nk_str_len_char(struct nk_str *s)
8708 {
8709     NK_ASSERT(s);
8710     if (!s || !s->len || !s->buffer.allocated) return 0;
8711     return (int)s->buffer.allocated;
8712 }
8713 NK_API void
8714 nk_str_clear(struct nk_str *str)
8715 {
8716     NK_ASSERT(str);
8717     nk_buffer_clear(&str->buffer);
8718     str->len = 0;
8719 }
8720 NK_API void
8721 nk_str_free(struct nk_str *str)
8722 {
8723     NK_ASSERT(str);
8724     nk_buffer_free(&str->buffer);
8725     str->len = 0;
8726 }
8727 
8728 
8729 
8730 
8731 
8732 /* ==============================================================
8733  *
8734  *                          DRAW
8735  *
8736  * ===============================================================*/
8737 NK_LIB void
8738 nk_command_buffer_init(struct nk_command_buffer *cb,
8739     struct nk_buffer *b, enum nk_command_clipping clip)
8740 {
8741     NK_ASSERT(cb);
8742     NK_ASSERT(b);
8743     if (!cb || !b) return;
8744     cb->base = b;
8745     cb->use_clipping = (int)clip;
8746     cb->begin = b->allocated;
8747     cb->end = b->allocated;
8748     cb->last = b->allocated;
8749 }
8750 NK_LIB void
8751 nk_command_buffer_reset(struct nk_command_buffer *b)
8752 {
8753     NK_ASSERT(b);
8754     if (!b) return;
8755     b->begin = 0;
8756     b->end = 0;
8757     b->last = 0;
8758     b->clip = nk_null_rect;
8759 #ifdef NK_INCLUDE_COMMAND_USERDATA
8760     b->userdata.ptr = 0;
8761 #endif
8762 }
8763 NK_LIB void*
8764 nk_command_buffer_push(struct nk_command_buffer* b,
8765     enum nk_command_type t, nk_size size)
8766 {
8767     NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
8768     struct nk_command *cmd;
8769     nk_size alignment;
8770     void *unaligned;
8771     void *memory;
8772 
8773     NK_ASSERT(b);
8774     NK_ASSERT(b->base);
8775     if (!b) return 0;
8776     cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
8777     if (!cmd) return 0;
8778 
8779     /* make sure the offset to the next command is aligned */
8780     b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
8781     unaligned = (nk_byte*)cmd + size;
8782     memory = NK_ALIGN_PTR(unaligned, align);
8783     alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
8784 #ifdef NK_ZERO_COMMAND_MEMORY
8785     NK_MEMSET(cmd, 0, size + alignment);
8786 #endif
8787 
8788     cmd->type = t;
8789     cmd->next = b->base->allocated + alignment;
8790 #ifdef NK_INCLUDE_COMMAND_USERDATA
8791     cmd->userdata = b->userdata;
8792 #endif
8793     b->end = cmd->next;
8794     return cmd;
8795 }
8796 NK_API void
8797 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
8798 {
8799     struct nk_command_scissor *cmd;
8800     NK_ASSERT(b);
8801     if (!b) return;
8802 
8803     b->clip.x = r.x;
8804     b->clip.y = r.y;
8805     b->clip.w = r.w;
8806     b->clip.h = r.h;
8807     cmd = (struct nk_command_scissor*)
8808         nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
8809 
8810     if (!cmd) return;
8811     cmd->x = (short)r.x;
8812     cmd->y = (short)r.y;
8813     cmd->w = (unsigned short)NK_MAX(0, r.w);
8814     cmd->h = (unsigned short)NK_MAX(0, r.h);
8815 }
8816 NK_API void
8817 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
8818     float x1, float y1, float line_thickness, struct nk_color c)
8819 {
8820     struct nk_command_line *cmd;
8821     NK_ASSERT(b);
8822     if (!b || line_thickness <= 0) return;
8823     cmd = (struct nk_command_line*)
8824         nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
8825     if (!cmd) return;
8826     cmd->line_thickness = (unsigned short)line_thickness;
8827     cmd->begin.x = (short)x0;
8828     cmd->begin.y = (short)y0;
8829     cmd->end.x = (short)x1;
8830     cmd->end.y = (short)y1;
8831     cmd->color = c;
8832 }
8833 NK_API void
8834 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
8835     float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
8836     float bx, float by, float line_thickness, struct nk_color col)
8837 {
8838     struct nk_command_curve *cmd;
8839     NK_ASSERT(b);
8840     if (!b || col.a == 0 || line_thickness <= 0) return;
8841 
8842     cmd = (struct nk_command_curve*)
8843         nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
8844     if (!cmd) return;
8845     cmd->line_thickness = (unsigned short)line_thickness;
8846     cmd->begin.x = (short)ax;
8847     cmd->begin.y = (short)ay;
8848     cmd->ctrl[0].x = (short)ctrl0x;
8849     cmd->ctrl[0].y = (short)ctrl0y;
8850     cmd->ctrl[1].x = (short)ctrl1x;
8851     cmd->ctrl[1].y = (short)ctrl1y;
8852     cmd->end.x = (short)bx;
8853     cmd->end.y = (short)by;
8854     cmd->color = col;
8855 }
8856 NK_API void
8857 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
8858     float rounding, float line_thickness, struct nk_color c)
8859 {
8860     struct nk_command_rect *cmd;
8861     NK_ASSERT(b);
8862     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
8863     if (b->use_clipping) {
8864         const struct nk_rect *clip = &b->clip;
8865         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8866             clip->x, clip->y, clip->w, clip->h)) return;
8867     }
8868     cmd = (struct nk_command_rect*)
8869         nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
8870     if (!cmd) return;
8871     cmd->rounding = (unsigned short)rounding;
8872     cmd->line_thickness = (unsigned short)line_thickness;
8873     cmd->x = (short)rect.x;
8874     cmd->y = (short)rect.y;
8875     cmd->w = (unsigned short)NK_MAX(0, rect.w);
8876     cmd->h = (unsigned short)NK_MAX(0, rect.h);
8877     cmd->color = c;
8878 }
8879 NK_API void
8880 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
8881     float rounding, struct nk_color c)
8882 {
8883     struct nk_command_rect_filled *cmd;
8884     NK_ASSERT(b);
8885     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
8886     if (b->use_clipping) {
8887         const struct nk_rect *clip = &b->clip;
8888         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8889             clip->x, clip->y, clip->w, clip->h)) return;
8890     }
8891 
8892     cmd = (struct nk_command_rect_filled*)
8893         nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
8894     if (!cmd) return;
8895     cmd->rounding = (unsigned short)rounding;
8896     cmd->x = (short)rect.x;
8897     cmd->y = (short)rect.y;
8898     cmd->w = (unsigned short)NK_MAX(0, rect.w);
8899     cmd->h = (unsigned short)NK_MAX(0, rect.h);
8900     cmd->color = c;
8901 }
8902 NK_API void
8903 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
8904     struct nk_color left, struct nk_color top, struct nk_color right,
8905     struct nk_color bottom)
8906 {
8907     struct nk_command_rect_multi_color *cmd;
8908     NK_ASSERT(b);
8909     if (!b || rect.w == 0 || rect.h == 0) return;
8910     if (b->use_clipping) {
8911         const struct nk_rect *clip = &b->clip;
8912         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8913             clip->x, clip->y, clip->w, clip->h)) return;
8914     }
8915 
8916     cmd = (struct nk_command_rect_multi_color*)
8917         nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
8918     if (!cmd) return;
8919     cmd->x = (short)rect.x;
8920     cmd->y = (short)rect.y;
8921     cmd->w = (unsigned short)NK_MAX(0, rect.w);
8922     cmd->h = (unsigned short)NK_MAX(0, rect.h);
8923     cmd->left = left;
8924     cmd->top = top;
8925     cmd->right = right;
8926     cmd->bottom = bottom;
8927 }
8928 NK_API void
8929 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
8930     float line_thickness, struct nk_color c)
8931 {
8932     struct nk_command_circle *cmd;
8933     if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
8934     if (b->use_clipping) {
8935         const struct nk_rect *clip = &b->clip;
8936         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
8937             return;
8938     }
8939 
8940     cmd = (struct nk_command_circle*)
8941         nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
8942     if (!cmd) return;
8943     cmd->line_thickness = (unsigned short)line_thickness;
8944     cmd->x = (short)r.x;
8945     cmd->y = (short)r.y;
8946     cmd->w = (unsigned short)NK_MAX(r.w, 0);
8947     cmd->h = (unsigned short)NK_MAX(r.h, 0);
8948     cmd->color = c;
8949 }
8950 NK_API void
8951 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
8952 {
8953     struct nk_command_circle_filled *cmd;
8954     NK_ASSERT(b);
8955     if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
8956     if (b->use_clipping) {
8957         const struct nk_rect *clip = &b->clip;
8958         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
8959             return;
8960     }
8961 
8962     cmd = (struct nk_command_circle_filled*)
8963         nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
8964     if (!cmd) return;
8965     cmd->x = (short)r.x;
8966     cmd->y = (short)r.y;
8967     cmd->w = (unsigned short)NK_MAX(r.w, 0);
8968     cmd->h = (unsigned short)NK_MAX(r.h, 0);
8969     cmd->color = c;
8970 }
8971 NK_API void
8972 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
8973     float a_min, float a_max, float line_thickness, struct nk_color c)
8974 {
8975     struct nk_command_arc *cmd;
8976     if (!b || c.a == 0 || line_thickness <= 0) return;
8977     cmd = (struct nk_command_arc*)
8978         nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
8979     if (!cmd) return;
8980     cmd->line_thickness = (unsigned short)line_thickness;
8981     cmd->cx = (short)cx;
8982     cmd->cy = (short)cy;
8983     cmd->r = (unsigned short)radius;
8984     cmd->a[0] = a_min;
8985     cmd->a[1] = a_max;
8986     cmd->color = c;
8987 }
8988 NK_API void
8989 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
8990     float a_min, float a_max, struct nk_color c)
8991 {
8992     struct nk_command_arc_filled *cmd;
8993     NK_ASSERT(b);
8994     if (!b || c.a == 0) return;
8995     cmd = (struct nk_command_arc_filled*)
8996         nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
8997     if (!cmd) return;
8998     cmd->cx = (short)cx;
8999     cmd->cy = (short)cy;
9000     cmd->r = (unsigned short)radius;
9001     cmd->a[0] = a_min;
9002     cmd->a[1] = a_max;
9003     cmd->color = c;
9004 }
9005 NK_API void
9006 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
9007     float y1, float x2, float y2, float line_thickness, struct nk_color c)
9008 {
9009     struct nk_command_triangle *cmd;
9010     NK_ASSERT(b);
9011     if (!b || c.a == 0 || line_thickness <= 0) return;
9012     if (b->use_clipping) {
9013         const struct nk_rect *clip = &b->clip;
9014         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
9015             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
9016             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
9017             return;
9018     }
9019 
9020     cmd = (struct nk_command_triangle*)
9021         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
9022     if (!cmd) return;
9023     cmd->line_thickness = (unsigned short)line_thickness;
9024     cmd->a.x = (short)x0;
9025     cmd->a.y = (short)y0;
9026     cmd->b.x = (short)x1;
9027     cmd->b.y = (short)y1;
9028     cmd->c.x = (short)x2;
9029     cmd->c.y = (short)y2;
9030     cmd->color = c;
9031 }
9032 NK_API void
9033 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
9034     float y1, float x2, float y2, struct nk_color c)
9035 {
9036     struct nk_command_triangle_filled *cmd;
9037     NK_ASSERT(b);
9038     if (!b || c.a == 0) return;
9039     if (!b) return;
9040     if (b->use_clipping) {
9041         const struct nk_rect *clip = &b->clip;
9042         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
9043             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
9044             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
9045             return;
9046     }
9047 
9048     cmd = (struct nk_command_triangle_filled*)
9049         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
9050     if (!cmd) return;
9051     cmd->a.x = (short)x0;
9052     cmd->a.y = (short)y0;
9053     cmd->b.x = (short)x1;
9054     cmd->b.y = (short)y1;
9055     cmd->c.x = (short)x2;
9056     cmd->c.y = (short)y2;
9057     cmd->color = c;
9058 }
9059 NK_API void
9060 nk_stroke_polygon(struct nk_command_buffer *b,  float *points, int point_count,
9061     float line_thickness, struct nk_color col)
9062 {
9063     int i;
9064     nk_size size = 0;
9065     struct nk_command_polygon *cmd;
9066 
9067     NK_ASSERT(b);
9068     if (!b || col.a == 0 || line_thickness <= 0) return;
9069     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
9070     cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
9071     if (!cmd) return;
9072     cmd->color = col;
9073     cmd->line_thickness = (unsigned short)line_thickness;
9074     cmd->point_count = (unsigned short)point_count;
9075     for (i = 0; i < point_count; ++i) {
9076         cmd->points[i].x = (short)points[i*2];
9077         cmd->points[i].y = (short)points[i*2+1];
9078     }
9079 }
9080 NK_API void
9081 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
9082     struct nk_color col)
9083 {
9084     int i;
9085     nk_size size = 0;
9086     struct nk_command_polygon_filled *cmd;
9087 
9088     NK_ASSERT(b);
9089     if (!b || col.a == 0) return;
9090     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
9091     cmd = (struct nk_command_polygon_filled*)
9092         nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
9093     if (!cmd) return;
9094     cmd->color = col;
9095     cmd->point_count = (unsigned short)point_count;
9096     for (i = 0; i < point_count; ++i) {
9097         cmd->points[i].x = (short)points[i*2+0];
9098         cmd->points[i].y = (short)points[i*2+1];
9099     }
9100 }
9101 NK_API void
9102 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count,
9103     float line_thickness, struct nk_color col)
9104 {
9105     int i;
9106     nk_size size = 0;
9107     struct nk_command_polyline *cmd;
9108 
9109     NK_ASSERT(b);
9110     if (!b || col.a == 0 || line_thickness <= 0) return;
9111     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
9112     cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
9113     if (!cmd) return;
9114     cmd->color = col;
9115     cmd->point_count = (unsigned short)point_count;
9116     cmd->line_thickness = (unsigned short)line_thickness;
9117     for (i = 0; i < point_count; ++i) {
9118         cmd->points[i].x = (short)points[i*2];
9119         cmd->points[i].y = (short)points[i*2+1];
9120     }
9121 }
9122 NK_API void
9123 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
9124     const struct nk_image *img, struct nk_color col)
9125 {
9126     struct nk_command_image *cmd;
9127     NK_ASSERT(b);
9128     if (!b) return;
9129     if (b->use_clipping) {
9130         const struct nk_rect *c = &b->clip;
9131         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))
9132             return;
9133     }
9134 
9135     cmd = (struct nk_command_image*)
9136         nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
9137     if (!cmd) return;
9138     cmd->x = (short)r.x;
9139     cmd->y = (short)r.y;
9140     cmd->w = (unsigned short)NK_MAX(0, r.w);
9141     cmd->h = (unsigned short)NK_MAX(0, r.h);
9142     cmd->img = *img;
9143     cmd->col = col;
9144 }
9145 NK_API void
9146 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
9147     nk_command_custom_callback cb, nk_handle usr)
9148 {
9149     struct nk_command_custom *cmd;
9150     NK_ASSERT(b);
9151     if (!b) return;
9152     if (b->use_clipping) {
9153         const struct nk_rect *c = &b->clip;
9154         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))
9155             return;
9156     }
9157 
9158     cmd = (struct nk_command_custom*)
9159         nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
9160     if (!cmd) return;
9161     cmd->x = (short)r.x;
9162     cmd->y = (short)r.y;
9163     cmd->w = (unsigned short)NK_MAX(0, r.w);
9164     cmd->h = (unsigned short)NK_MAX(0, r.h);
9165     cmd->callback_data = usr;
9166     cmd->callback = cb;
9167 }
9168 NK_API void
9169 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
9170     const char *string, int length, const struct nk_user_font *font,
9171     struct nk_color bg, struct nk_color fg)
9172 {
9173     float text_width = 0;
9174     struct nk_command_text *cmd;
9175 
9176     NK_ASSERT(b);
9177     NK_ASSERT(font);
9178     if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
9179     if (b->use_clipping) {
9180         const struct nk_rect *c = &b->clip;
9181         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))
9182             return;
9183     }
9184 
9185     /* make sure text fits inside bounds */
9186     text_width = font->width(font->userdata, font->height, string, length);
9187     if (text_width > r.w){
9188         int glyphs = 0;
9189         float txt_width = (float)text_width;
9190         length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
9191     }
9192 
9193     if (!length) return;
9194     cmd = (struct nk_command_text*)
9195         nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
9196     if (!cmd) return;
9197     cmd->x = (short)r.x;
9198     cmd->y = (short)r.y;
9199     cmd->w = (unsigned short)r.w;
9200     cmd->h = (unsigned short)r.h;
9201     cmd->background = bg;
9202     cmd->foreground = fg;
9203     cmd->font = font;
9204     cmd->length = length;
9205     cmd->height = font->height;
9206     NK_MEMCPY(cmd->string, string, (nk_size)length);
9207     cmd->string[length] = '\0';
9208 }
9209 
9210 
9211 
9212 
9213 
9214 /* ===============================================================
9215  *
9216  *                              VERTEX
9217  *
9218  * ===============================================================*/
9219 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
9220 NK_API void
9221 nk_draw_list_init(struct nk_draw_list *list)
9222 {
9223     nk_size i = 0;
9224     NK_ASSERT(list);
9225     if (!list) return;
9226     nk_zero(list, sizeof(*list));
9227     for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
9228         const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
9229         list->circle_vtx[i].x = (float)NK_COS(a);
9230         list->circle_vtx[i].y = (float)NK_SIN(a);
9231     }
9232 }
9233 NK_API void
9234 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
9235     struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
9236     enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
9237 {
9238     NK_ASSERT(canvas);
9239     NK_ASSERT(config);
9240     NK_ASSERT(cmds);
9241     NK_ASSERT(vertices);
9242     NK_ASSERT(elements);
9243     if (!canvas || !config || !cmds || !vertices || !elements)
9244         return;
9245 
9246     canvas->buffer = cmds;
9247     canvas->config = *config;
9248     canvas->elements = elements;
9249     canvas->vertices = vertices;
9250     canvas->line_AA = line_aa;
9251     canvas->shape_AA = shape_aa;
9252     canvas->clip_rect = nk_null_rect;
9253 
9254     canvas->cmd_offset = 0;
9255     canvas->element_count = 0;
9256     canvas->vertex_count = 0;
9257     canvas->cmd_offset = 0;
9258     canvas->cmd_count = 0;
9259     canvas->path_count = 0;
9260 }
9261 NK_API const struct nk_draw_command*
9262 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
9263 {
9264     nk_byte *memory;
9265     nk_size offset;
9266     const struct nk_draw_command *cmd;
9267 
9268     NK_ASSERT(buffer);
9269     if (!buffer || !buffer->size || !canvas->cmd_count)
9270         return 0;
9271 
9272     memory = (nk_byte*)buffer->memory.ptr;
9273     offset = buffer->memory.size - canvas->cmd_offset;
9274     cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
9275     return cmd;
9276 }
9277 NK_API const struct nk_draw_command*
9278 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
9279 {
9280     nk_size size;
9281     nk_size offset;
9282     nk_byte *memory;
9283     const struct nk_draw_command *end;
9284 
9285     NK_ASSERT(buffer);
9286     NK_ASSERT(canvas);
9287     if (!buffer || !canvas)
9288         return 0;
9289 
9290     memory = (nk_byte*)buffer->memory.ptr;
9291     size = buffer->memory.size;
9292     offset = size - canvas->cmd_offset;
9293     end = nk_ptr_add(const struct nk_draw_command, memory, offset);
9294     end -= (canvas->cmd_count-1);
9295     return end;
9296 }
9297 NK_API const struct nk_draw_command*
9298 nk__draw_list_next(const struct nk_draw_command *cmd,
9299     const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
9300 {
9301     const struct nk_draw_command *end;
9302     NK_ASSERT(buffer);
9303     NK_ASSERT(canvas);
9304     if (!cmd || !buffer || !canvas)
9305         return 0;
9306 
9307     end = nk__draw_list_end(canvas, buffer);
9308     if (cmd <= end) return 0;
9309     return (cmd-1);
9310 }
9311 NK_INTERN struct nk_vec2*
9312 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
9313 {
9314     struct nk_vec2 *points;
9315     NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
9316     NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
9317     points = (struct nk_vec2*)
9318         nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
9319                         point_size * (nk_size)count, point_align);
9320 
9321     if (!points) return 0;
9322     if (!list->path_offset) {
9323         void *memory = nk_buffer_memory(list->buffer);
9324         list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
9325     }
9326     list->path_count += (unsigned int)count;
9327     return points;
9328 }
9329 NK_INTERN struct nk_vec2
9330 nk_draw_list_path_last(struct nk_draw_list *list)
9331 {
9332     void *memory;
9333     struct nk_vec2 *point;
9334     NK_ASSERT(list->path_count);
9335     memory = nk_buffer_memory(list->buffer);
9336     point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
9337     point += (list->path_count-1);
9338     return *point;
9339 }
9340 NK_INTERN struct nk_draw_command*
9341 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
9342     nk_handle texture)
9343 {
9344     NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
9345     NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
9346     struct nk_draw_command *cmd;
9347 
9348     NK_ASSERT(list);
9349     cmd = (struct nk_draw_command*)
9350         nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
9351 
9352     if (!cmd) return 0;
9353     if (!list->cmd_count) {
9354         nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
9355         nk_size total = nk_buffer_total(list->buffer);
9356         memory = nk_ptr_add(nk_byte, memory, total);
9357         list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
9358     }
9359 
9360     cmd->elem_count = 0;
9361     cmd->clip_rect = clip;
9362     cmd->texture = texture;
9363 #ifdef NK_INCLUDE_COMMAND_USERDATA
9364     cmd->userdata = list->userdata;
9365 #endif
9366 
9367     list->cmd_count++;
9368     list->clip_rect = clip;
9369     return cmd;
9370 }
9371 NK_INTERN struct nk_draw_command*
9372 nk_draw_list_command_last(struct nk_draw_list *list)
9373 {
9374     void *memory;
9375     nk_size size;
9376     struct nk_draw_command *cmd;
9377     NK_ASSERT(list->cmd_count);
9378 
9379     memory = nk_buffer_memory(list->buffer);
9380     size = nk_buffer_total(list->buffer);
9381     cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
9382     return (cmd - (list->cmd_count-1));
9383 }
9384 NK_INTERN void
9385 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
9386 {
9387     NK_ASSERT(list);
9388     if (!list) return;
9389     if (!list->cmd_count) {
9390         nk_draw_list_push_command(list, rect, list->config.null.texture);
9391     } else {
9392         struct nk_draw_command *prev = nk_draw_list_command_last(list);
9393         if (prev->elem_count == 0)
9394             prev->clip_rect = rect;
9395         nk_draw_list_push_command(list, rect, prev->texture);
9396     }
9397 }
9398 NK_INTERN void
9399 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
9400 {
9401     NK_ASSERT(list);
9402     if (!list) return;
9403     if (!list->cmd_count) {
9404         nk_draw_list_push_command(list, nk_null_rect, texture);
9405     } else {
9406         struct nk_draw_command *prev = nk_draw_list_command_last(list);
9407         if (prev->elem_count == 0) {
9408             prev->texture = texture;
9409         #ifdef NK_INCLUDE_COMMAND_USERDATA
9410             prev->userdata = list->userdata;
9411         #endif
9412     } else if (prev->texture.id != texture.id
9413         #ifdef NK_INCLUDE_COMMAND_USERDATA
9414             || prev->userdata.id != list->userdata.id
9415         #endif
9416         ) nk_draw_list_push_command(list, prev->clip_rect, texture);
9417     }
9418 }
9419 #ifdef NK_INCLUDE_COMMAND_USERDATA
9420 NK_API void
9421 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
9422 {
9423     list->userdata = userdata;
9424 }
9425 #endif
9426 NK_INTERN void*
9427 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
9428 {
9429     void *vtx;
9430     NK_ASSERT(list);
9431     if (!list) return 0;
9432     vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
9433         list->config.vertex_size*count, list->config.vertex_alignment);
9434     if (!vtx) return 0;
9435     list->vertex_count += (unsigned int)count;
9436 
9437     /* This assert triggers because your are drawing a lot of stuff and nuklear
9438      * defined `nk_draw_index` as `nk_ushort` to safe space be default.
9439      *
9440      * So you reached the maximum number of indicies or rather vertexes.
9441      * To solve this issue please change typdef `nk_draw_index` to `nk_uint`
9442      * and don't forget to specify the new element size in your drawing
9443      * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements`
9444      * instead of specifing `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`.
9445      * Sorry for the inconvenience. */
9446     if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX &&
9447         "To many verticies for 16-bit vertex indicies. Please read comment above on how to solve this problem"));
9448     return vtx;
9449 }
9450 NK_INTERN nk_draw_index*
9451 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
9452 {
9453     nk_draw_index *ids;
9454     struct nk_draw_command *cmd;
9455     NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
9456     NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
9457     NK_ASSERT(list);
9458     if (!list) return 0;
9459 
9460     ids = (nk_draw_index*)
9461         nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
9462     if (!ids) return 0;
9463     cmd = nk_draw_list_command_last(list);
9464     list->element_count += (unsigned int)count;
9465     cmd->elem_count += (unsigned int)count;
9466     return ids;
9467 }
9468 NK_INTERN int
9469 nk_draw_vertex_layout_element_is_end_of_layout(
9470     const struct nk_draw_vertex_layout_element *element)
9471 {
9472     return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
9473             element->format == NK_FORMAT_COUNT);
9474 }
9475 NK_INTERN void
9476 nk_draw_vertex_color(void *attr, const float *vals,
9477     enum nk_draw_vertex_layout_format format)
9478 {
9479     /* if this triggers you tried to provide a value format for a color */
9480     float val[4];
9481     NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
9482     NK_ASSERT(format <= NK_FORMAT_COLOR_END);
9483     if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
9484 
9485     val[0] = NK_SATURATE(vals[0]);
9486     val[1] = NK_SATURATE(vals[1]);
9487     val[2] = NK_SATURATE(vals[2]);
9488     val[3] = NK_SATURATE(vals[3]);
9489 
9490     switch (format) {
9491     default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
9492     case NK_FORMAT_R8G8B8A8:
9493     case NK_FORMAT_R8G8B8: {
9494         struct nk_color col = nk_rgba_fv(val);
9495         NK_MEMCPY(attr, &col.r, sizeof(col));
9496     } break;
9497     case NK_FORMAT_B8G8R8A8: {
9498         struct nk_color col = nk_rgba_fv(val);
9499         struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
9500         NK_MEMCPY(attr, &bgra, sizeof(bgra));
9501     } break;
9502     case NK_FORMAT_R16G15B16: {
9503         nk_ushort col[3];
9504         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
9505         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
9506         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
9507         NK_MEMCPY(attr, col, sizeof(col));
9508     } break;
9509     case NK_FORMAT_R16G15B16A16: {
9510         nk_ushort col[4];
9511         col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
9512         col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
9513         col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
9514         col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX);
9515         NK_MEMCPY(attr, col, sizeof(col));
9516     } break;
9517     case NK_FORMAT_R32G32B32: {
9518         nk_uint col[3];
9519         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
9520         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
9521         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
9522         NK_MEMCPY(attr, col, sizeof(col));
9523     } break;
9524     case NK_FORMAT_R32G32B32A32: {
9525         nk_uint col[4];
9526         col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
9527         col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
9528         col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
9529         col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX);
9530         NK_MEMCPY(attr, col, sizeof(col));
9531     } break;
9532     case NK_FORMAT_R32G32B32A32_FLOAT:
9533         NK_MEMCPY(attr, val, sizeof(float)*4);
9534         break;
9535     case NK_FORMAT_R32G32B32A32_DOUBLE: {
9536         double col[4];
9537         col[0] = (double)val[0];
9538         col[1] = (double)val[1];
9539         col[2] = (double)val[2];
9540         col[3] = (double)val[3];
9541         NK_MEMCPY(attr, col, sizeof(col));
9542     } break;
9543     case NK_FORMAT_RGB32:
9544     case NK_FORMAT_RGBA32: {
9545         struct nk_color col = nk_rgba_fv(val);
9546         nk_uint color = nk_color_u32(col);
9547         NK_MEMCPY(attr, &color, sizeof(color));
9548     } break; }
9549 }
9550 NK_INTERN void
9551 nk_draw_vertex_element(void *dst, const float *values, int value_count,
9552     enum nk_draw_vertex_layout_format format)
9553 {
9554     int value_index;
9555     void *attribute = dst;
9556     /* if this triggers you tried to provide a color format for a value */
9557     NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
9558     if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
9559     for (value_index = 0; value_index < value_count; ++value_index) {
9560         switch (format) {
9561         default: NK_ASSERT(0 && "invalid vertex layout format"); break;
9562         case NK_FORMAT_SCHAR: {
9563             char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX);
9564             NK_MEMCPY(attribute, &value, sizeof(value));
9565             attribute = (void*)((char*)attribute + sizeof(char));
9566         } break;
9567         case NK_FORMAT_SSHORT: {
9568             nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX);
9569             NK_MEMCPY(attribute, &value, sizeof(value));
9570             attribute = (void*)((char*)attribute + sizeof(value));
9571         } break;
9572         case NK_FORMAT_SINT: {
9573             nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX);
9574             NK_MEMCPY(attribute, &value, sizeof(value));
9575             attribute = (void*)((char*)attribute + sizeof(nk_int));
9576         } break;
9577         case NK_FORMAT_UCHAR: {
9578             unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX);
9579             NK_MEMCPY(attribute, &value, sizeof(value));
9580             attribute = (void*)((char*)attribute + sizeof(unsigned char));
9581         } break;
9582         case NK_FORMAT_USHORT: {
9583             nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX);
9584             NK_MEMCPY(attribute, &value, sizeof(value));
9585             attribute = (void*)((char*)attribute + sizeof(value));
9586             } break;
9587         case NK_FORMAT_UINT: {
9588             nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX);
9589             NK_MEMCPY(attribute, &value, sizeof(value));
9590             attribute = (void*)((char*)attribute + sizeof(nk_uint));
9591         } break;
9592         case NK_FORMAT_FLOAT:
9593             NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
9594             attribute = (void*)((char*)attribute + sizeof(float));
9595             break;
9596         case NK_FORMAT_DOUBLE: {
9597             double value = (double)values[value_index];
9598             NK_MEMCPY(attribute, &value, sizeof(value));
9599             attribute = (void*)((char*)attribute + sizeof(double));
9600             } break;
9601         }
9602     }
9603 }
9604 NK_INTERN void*
9605 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
9606     struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
9607 {
9608     void *result = (void*)((char*)dst + config->vertex_size);
9609     const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
9610     while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
9611         void *address = (void*)((char*)dst + elem_iter->offset);
9612         switch (elem_iter->attribute) {
9613         case NK_VERTEX_ATTRIBUTE_COUNT:
9614         default: NK_ASSERT(0 && "wrong element attribute"); break;
9615         case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
9616         case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
9617         case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
9618         }
9619         elem_iter++;
9620     }
9621     return result;
9622 }
9623 NK_API void
9624 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
9625     const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
9626     float thickness, enum nk_anti_aliasing aliasing)
9627 {
9628     nk_size count;
9629     int thick_line;
9630     struct nk_colorf col;
9631     struct nk_colorf col_trans;
9632     NK_ASSERT(list);
9633     if (!list || points_count < 2) return;
9634 
9635     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9636     count = points_count;
9637     if (!closed) count = points_count-1;
9638     thick_line = thickness > 1.0f;
9639 
9640 #ifdef NK_INCLUDE_COMMAND_USERDATA
9641     nk_draw_list_push_userdata(list, list->userdata);
9642 #endif
9643 
9644     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9645     nk_color_fv(&col.r, color);
9646     col_trans = col;
9647     col_trans.a = 0;
9648 
9649     if (aliasing == NK_ANTI_ALIASING_ON) {
9650         /* ANTI-ALIASED STROKE */
9651         const float AA_SIZE = 1.0f;
9652         NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
9653         NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
9654 
9655         /* allocate vertices and elements  */
9656         nk_size i1 = 0;
9657         nk_size vertex_offset;
9658         nk_size index = list->vertex_count;
9659 
9660         const nk_size idx_count = (thick_line) ?  (count * 18) : (count * 12);
9661         const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
9662 
9663         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9664         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9665 
9666         nk_size size;
9667         struct nk_vec2 *normals, *temp;
9668         if (!vtx || !ids) return;
9669 
9670         /* temporary allocate normals + points */
9671         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
9672         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
9673         size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
9674         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
9675         if (!normals) return;
9676         temp = normals + points_count;
9677 
9678         /* make sure vertex pointer is still correct */
9679         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
9680 
9681         /* calculate normals */
9682         for (i1 = 0; i1 < count; ++i1) {
9683             const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
9684             struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
9685             float len;
9686 
9687             /* vec2 inverted length  */
9688             len = nk_vec2_len_sqr(diff);
9689             if (len != 0.0f)
9690                 len = nk_inv_sqrt(len);
9691             else len = 1.0f;
9692 
9693             diff = nk_vec2_muls(diff, len);
9694             normals[i1].x = diff.y;
9695             normals[i1].y = -diff.x;
9696         }
9697 
9698         if (!closed)
9699             normals[points_count-1] = normals[points_count-2];
9700 
9701         if (!thick_line) {
9702             nk_size idx1, i;
9703             if (!closed) {
9704                 struct nk_vec2 d;
9705                 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
9706                 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
9707                 d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
9708                 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
9709                 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
9710             }
9711 
9712             /* fill elements */
9713             idx1 = index;
9714             for (i1 = 0; i1 < count; i1++) {
9715                 struct nk_vec2 dm;
9716                 float dmr2;
9717                 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
9718                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
9719 
9720                 /* average normals */
9721                 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
9722                 dmr2 = dm.x * dm.x + dm.y* dm.y;
9723                 if (dmr2 > 0.000001f) {
9724                     float scale = 1.0f/dmr2;
9725                     scale = NK_MIN(100.0f, scale);
9726                     dm = nk_vec2_muls(dm, scale);
9727                 }
9728 
9729                 dm = nk_vec2_muls(dm, AA_SIZE);
9730                 temp[i2*2+0] = nk_vec2_add(points[i2], dm);
9731                 temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
9732 
9733                 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
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+0);
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;
9740                 idx1 = idx2;
9741             }
9742 
9743             /* fill vertices */
9744             for (i = 0; i < points_count; ++i) {
9745                 const struct nk_vec2 uv = list->config.null.uv;
9746                 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
9747                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
9748                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
9749             }
9750         } else {
9751             nk_size idx1, i;
9752             const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
9753             if (!closed) {
9754                 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
9755                 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
9756 
9757                 temp[0] = nk_vec2_add(points[0], d1);
9758                 temp[1] = nk_vec2_add(points[0], d2);
9759                 temp[2] = nk_vec2_sub(points[0], d2);
9760                 temp[3] = nk_vec2_sub(points[0], d1);
9761 
9762                 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
9763                 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
9764 
9765                 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
9766                 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
9767                 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
9768                 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
9769             }
9770 
9771             /* add all elements */
9772             idx1 = index;
9773             for (i1 = 0; i1 < count; ++i1) {
9774                 struct nk_vec2 dm_out, dm_in;
9775                 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
9776                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
9777 
9778                 /* average normals */
9779                 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
9780                 float dmr2 = dm.x * dm.x + dm.y* dm.y;
9781                 if (dmr2 > 0.000001f) {
9782                     float scale = 1.0f/dmr2;
9783                     scale = NK_MIN(100.0f, scale);
9784                     dm = nk_vec2_muls(dm, scale);
9785                 }
9786 
9787                 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
9788                 dm_in = nk_vec2_muls(dm, half_inner_thickness);
9789                 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
9790                 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
9791                 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
9792                 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
9793 
9794                 /* add indexes */
9795                 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
9796                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
9797                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
9798                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
9799                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
9800                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
9801                 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
9802                 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
9803                 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
9804                 ids += 18;
9805                 idx1 = idx2;
9806             }
9807 
9808             /* add vertices */
9809             for (i = 0; i < points_count; ++i) {
9810                 const struct nk_vec2 uv = list->config.null.uv;
9811                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
9812                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
9813                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
9814                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
9815             }
9816         }
9817         /* free temporary normals + points */
9818         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
9819     } else {
9820         /* NON ANTI-ALIASED STROKE */
9821         nk_size i1 = 0;
9822         nk_size idx = list->vertex_count;
9823         const nk_size idx_count = count * 6;
9824         const nk_size vtx_count = count * 4;
9825         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9826         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9827         if (!vtx || !ids) return;
9828 
9829         for (i1 = 0; i1 < count; ++i1) {
9830             float dx, dy;
9831             const struct nk_vec2 uv = list->config.null.uv;
9832             const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
9833             const struct nk_vec2 p1 = points[i1];
9834             const struct nk_vec2 p2 = points[i2];
9835             struct nk_vec2 diff = nk_vec2_sub(p2, p1);
9836             float len;
9837 
9838             /* vec2 inverted length  */
9839             len = nk_vec2_len_sqr(diff);
9840             if (len != 0.0f)
9841                 len = nk_inv_sqrt(len);
9842             else len = 1.0f;
9843             diff = nk_vec2_muls(diff, len);
9844 
9845             /* add vertices */
9846             dx = diff.x * (thickness * 0.5f);
9847             dy = diff.y * (thickness * 0.5f);
9848 
9849             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
9850             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
9851             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
9852             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
9853 
9854             ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
9855             ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
9856             ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
9857 
9858             ids += 6;
9859             idx += 4;
9860         }
9861     }
9862 }
9863 NK_API void
9864 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
9865     const struct nk_vec2 *points, const unsigned int points_count,
9866     struct nk_color color, enum nk_anti_aliasing aliasing)
9867 {
9868     struct nk_colorf col;
9869     struct nk_colorf col_trans;
9870 
9871     NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
9872     NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
9873     NK_ASSERT(list);
9874     if (!list || points_count < 3) return;
9875 
9876 #ifdef NK_INCLUDE_COMMAND_USERDATA
9877     nk_draw_list_push_userdata(list, list->userdata);
9878 #endif
9879 
9880     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
9881     nk_color_fv(&col.r, color);
9882     col_trans = col;
9883     col_trans.a = 0;
9884 
9885     if (aliasing == NK_ANTI_ALIASING_ON) {
9886         nk_size i = 0;
9887         nk_size i0 = 0;
9888         nk_size i1 = 0;
9889 
9890         const float AA_SIZE = 1.0f;
9891         nk_size vertex_offset = 0;
9892         nk_size index = list->vertex_count;
9893 
9894         const nk_size idx_count = (points_count-2)*3 + points_count*6;
9895         const nk_size vtx_count = (points_count*2);
9896 
9897         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9898         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9899 
9900         nk_size size = 0;
9901         struct nk_vec2 *normals = 0;
9902         unsigned int vtx_inner_idx = (unsigned int)(index + 0);
9903         unsigned int vtx_outer_idx = (unsigned int)(index + 1);
9904         if (!vtx || !ids) return;
9905 
9906         /* temporary allocate normals */
9907         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
9908         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
9909         size = pnt_size * points_count;
9910         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
9911         if (!normals) return;
9912         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
9913 
9914         /* add elements */
9915         for (i = 2; i < points_count; i++) {
9916             ids[0] = (nk_draw_index)(vtx_inner_idx);
9917             ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
9918             ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
9919             ids += 3;
9920         }
9921 
9922         /* compute normals */
9923         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
9924             struct nk_vec2 p0 = points[i0];
9925             struct nk_vec2 p1 = points[i1];
9926             struct nk_vec2 diff = nk_vec2_sub(p1, p0);
9927 
9928             /* vec2 inverted length  */
9929             float len = nk_vec2_len_sqr(diff);
9930             if (len != 0.0f)
9931                 len = nk_inv_sqrt(len);
9932             else len = 1.0f;
9933             diff = nk_vec2_muls(diff, len);
9934 
9935             normals[i0].x = diff.y;
9936             normals[i0].y = -diff.x;
9937         }
9938 
9939         /* add vertices + indexes */
9940         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
9941             const struct nk_vec2 uv = list->config.null.uv;
9942             struct nk_vec2 n0 = normals[i0];
9943             struct nk_vec2 n1 = normals[i1];
9944             struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
9945             float dmr2 = dm.x*dm.x + dm.y*dm.y;
9946             if (dmr2 > 0.000001f) {
9947                 float scale = 1.0f / dmr2;
9948                 scale = NK_MIN(scale, 100.0f);
9949                 dm = nk_vec2_muls(dm, scale);
9950             }
9951             dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
9952 
9953             /* add vertices */
9954             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
9955             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
9956 
9957             /* add indexes */
9958             ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
9959             ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
9960             ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
9961             ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
9962             ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
9963             ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
9964             ids += 6;
9965         }
9966         /* free temporary normals + points */
9967         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
9968     } else {
9969         nk_size i = 0;
9970         nk_size index = list->vertex_count;
9971         const nk_size idx_count = (points_count-2)*3;
9972         const nk_size vtx_count = points_count;
9973         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
9974         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
9975 
9976         if (!vtx || !ids) return;
9977         for (i = 0; i < vtx_count; ++i)
9978             vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
9979         for (i = 2; i < points_count; ++i) {
9980             ids[0] = (nk_draw_index)index;
9981             ids[1] = (nk_draw_index)(index+ i - 1);
9982             ids[2] = (nk_draw_index)(index+i);
9983             ids += 3;
9984         }
9985     }
9986 }
9987 NK_API void
9988 nk_draw_list_path_clear(struct nk_draw_list *list)
9989 {
9990     NK_ASSERT(list);
9991     if (!list) return;
9992     nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
9993     list->path_count = 0;
9994     list->path_offset = 0;
9995 }
9996 NK_API void
9997 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
9998 {
9999     struct nk_vec2 *points = 0;
10000     struct nk_draw_command *cmd = 0;
10001     NK_ASSERT(list);
10002     if (!list) return;
10003     if (!list->cmd_count)
10004         nk_draw_list_add_clip(list, nk_null_rect);
10005 
10006     cmd = nk_draw_list_command_last(list);
10007     if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
10008         nk_draw_list_push_image(list, list->config.null.texture);
10009 
10010     points = nk_draw_list_alloc_path(list, 1);
10011     if (!points) return;
10012     points[0] = pos;
10013 }
10014 NK_API void
10015 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
10016     float radius, int a_min, int a_max)
10017 {
10018     int a = 0;
10019     NK_ASSERT(list);
10020     if (!list) return;
10021     if (a_min <= a_max) {
10022         for (a = a_min; a <= a_max; a++) {
10023             const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
10024             const float x = center.x + c.x * radius;
10025             const float y = center.y + c.y * radius;
10026             nk_draw_list_path_line_to(list, nk_vec2(x, y));
10027         }
10028     }
10029 }
10030 NK_API void
10031 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
10032     float radius, float a_min, float a_max, unsigned int segments)
10033 {
10034     unsigned int i = 0;
10035     NK_ASSERT(list);
10036     if (!list) return;
10037     if (radius == 0.0f) return;
10038 
10039     /*  This algorithm for arc drawing relies on these two trigonometric identities[1]:
10040             sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
10041             cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
10042 
10043         Two coordinates (x, y) of a point on a circle centered on
10044         the origin can be written in polar form as:
10045             x = r * cos(a)
10046             y = r * sin(a)
10047         where r is the radius of the circle,
10048             a is the angle between (x, y) and the origin.
10049 
10050         This allows us to rotate the coordinates around the
10051         origin by an angle b using the following transformation:
10052             x' = r * cos(a + b) = x * cos(b) - y * sin(b)
10053             y' = r * sin(a + b) = y * cos(b) + x * sin(b)
10054 
10055         [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
10056     */
10057     {const float d_angle = (a_max - a_min) / (float)segments;
10058     const float sin_d = (float)NK_SIN(d_angle);
10059     const float cos_d = (float)NK_COS(d_angle);
10060 
10061     float cx = (float)NK_COS(a_min) * radius;
10062     float cy = (float)NK_SIN(a_min) * radius;
10063     for(i = 0; i <= segments; ++i) {
10064         float new_cx, new_cy;
10065         const float x = center.x + cx;
10066         const float y = center.y + cy;
10067         nk_draw_list_path_line_to(list, nk_vec2(x, y));
10068 
10069         new_cx = cx * cos_d - cy * sin_d;
10070         new_cy = cy * cos_d + cx * sin_d;
10071         cx = new_cx;
10072         cy = new_cy;
10073     }}
10074 }
10075 NK_API void
10076 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
10077     struct nk_vec2 b, float rounding)
10078 {
10079     float r;
10080     NK_ASSERT(list);
10081     if (!list) return;
10082     r = rounding;
10083     r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
10084     r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
10085 
10086     if (r == 0.0f) {
10087         nk_draw_list_path_line_to(list, a);
10088         nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
10089         nk_draw_list_path_line_to(list, b);
10090         nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
10091     } else {
10092         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
10093         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
10094         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
10095         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
10096     }
10097 }
10098 NK_API void
10099 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
10100     struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
10101 {
10102     float t_step;
10103     unsigned int i_step;
10104     struct nk_vec2 p1;
10105 
10106     NK_ASSERT(list);
10107     NK_ASSERT(list->path_count);
10108     if (!list || !list->path_count) return;
10109     num_segments = NK_MAX(num_segments, 1);
10110 
10111     p1 = nk_draw_list_path_last(list);
10112     t_step = 1.0f/(float)num_segments;
10113     for (i_step = 1; i_step <= num_segments; ++i_step) {
10114         float t = t_step * (float)i_step;
10115         float u = 1.0f - t;
10116         float w1 = u*u*u;
10117         float w2 = 3*u*u*t;
10118         float w3 = 3*u*t*t;
10119         float w4 = t * t *t;
10120         float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
10121         float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
10122         nk_draw_list_path_line_to(list, nk_vec2(x,y));
10123     }
10124 }
10125 NK_API void
10126 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
10127 {
10128     struct nk_vec2 *points;
10129     NK_ASSERT(list);
10130     if (!list) return;
10131     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
10132     nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
10133     nk_draw_list_path_clear(list);
10134 }
10135 NK_API void
10136 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
10137     enum nk_draw_list_stroke closed, float thickness)
10138 {
10139     struct nk_vec2 *points;
10140     NK_ASSERT(list);
10141     if (!list) return;
10142     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
10143     nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
10144         closed, thickness, list->config.line_AA);
10145     nk_draw_list_path_clear(list);
10146 }
10147 NK_API void
10148 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
10149     struct nk_vec2 b, struct nk_color col, float thickness)
10150 {
10151     NK_ASSERT(list);
10152     if (!list || !col.a) return;
10153     if (list->line_AA == NK_ANTI_ALIASING_ON) {
10154         nk_draw_list_path_line_to(list, a);
10155         nk_draw_list_path_line_to(list, b);
10156     } else {
10157         nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
10158         nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
10159     }
10160     nk_draw_list_path_stroke(list,  col, NK_STROKE_OPEN, thickness);
10161 }
10162 NK_API void
10163 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
10164     struct nk_color col, float rounding)
10165 {
10166     NK_ASSERT(list);
10167     if (!list || !col.a) return;
10168 
10169     if (list->line_AA == NK_ANTI_ALIASING_ON) {
10170         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
10171             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10172     } else {
10173         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
10174             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10175     } nk_draw_list_path_fill(list,  col);
10176 }
10177 NK_API void
10178 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
10179     struct nk_color col, float rounding, float thickness)
10180 {
10181     NK_ASSERT(list);
10182     if (!list || !col.a) return;
10183     if (list->line_AA == NK_ANTI_ALIASING_ON) {
10184         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
10185             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10186     } else {
10187         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
10188             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
10189     } nk_draw_list_path_stroke(list,  col, NK_STROKE_CLOSED, thickness);
10190 }
10191 NK_API void
10192 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
10193     struct nk_color left, struct nk_color top, struct nk_color right,
10194     struct nk_color bottom)
10195 {
10196     void *vtx;
10197     struct nk_colorf col_left, col_top;
10198     struct nk_colorf col_right, col_bottom;
10199     nk_draw_index *idx;
10200     nk_draw_index index;
10201 
10202     nk_color_fv(&col_left.r, left);
10203     nk_color_fv(&col_right.r, right);
10204     nk_color_fv(&col_top.r, top);
10205     nk_color_fv(&col_bottom.r, bottom);
10206 
10207     NK_ASSERT(list);
10208     if (!list) return;
10209 
10210     nk_draw_list_push_image(list, list->config.null.texture);
10211     index = (nk_draw_index)list->vertex_count;
10212     vtx = nk_draw_list_alloc_vertices(list, 4);
10213     idx = nk_draw_list_alloc_elements(list, 6);
10214     if (!vtx || !idx) return;
10215 
10216     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
10217     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
10218     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
10219 
10220     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
10221     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
10222     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
10223     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
10224 }
10225 NK_API void
10226 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
10227     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
10228 {
10229     NK_ASSERT(list);
10230     if (!list || !col.a) return;
10231     nk_draw_list_path_line_to(list, a);
10232     nk_draw_list_path_line_to(list, b);
10233     nk_draw_list_path_line_to(list, c);
10234     nk_draw_list_path_fill(list, col);
10235 }
10236 NK_API void
10237 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
10238     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
10239 {
10240     NK_ASSERT(list);
10241     if (!list || !col.a) return;
10242     nk_draw_list_path_line_to(list, a);
10243     nk_draw_list_path_line_to(list, b);
10244     nk_draw_list_path_line_to(list, c);
10245     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10246 }
10247 NK_API void
10248 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
10249     float radius, struct nk_color col, unsigned int segs)
10250 {
10251     float a_max;
10252     NK_ASSERT(list);
10253     if (!list || !col.a) return;
10254     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
10255     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
10256     nk_draw_list_path_fill(list, col);
10257 }
10258 NK_API void
10259 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
10260     float radius, struct nk_color col, unsigned int segs, float thickness)
10261 {
10262     float a_max;
10263     NK_ASSERT(list);
10264     if (!list || !col.a) return;
10265     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
10266     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
10267     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
10268 }
10269 NK_API void
10270 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
10271     struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
10272     struct nk_color col, unsigned int segments, float thickness)
10273 {
10274     NK_ASSERT(list);
10275     if (!list || !col.a) return;
10276     nk_draw_list_path_line_to(list, p0);
10277     nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
10278     nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
10279 }
10280 NK_INTERN void
10281 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
10282     struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
10283     struct nk_color color)
10284 {
10285     void *vtx;
10286     struct nk_vec2 uvb;
10287     struct nk_vec2 uvd;
10288     struct nk_vec2 b;
10289     struct nk_vec2 d;
10290 
10291     struct nk_colorf col;
10292     nk_draw_index *idx;
10293     nk_draw_index index;
10294     NK_ASSERT(list);
10295     if (!list) return;
10296 
10297     nk_color_fv(&col.r, color);
10298     uvb = nk_vec2(uvc.x, uva.y);
10299     uvd = nk_vec2(uva.x, uvc.y);
10300     b = nk_vec2(c.x, a.y);
10301     d = nk_vec2(a.x, c.y);
10302 
10303     index = (nk_draw_index)list->vertex_count;
10304     vtx = nk_draw_list_alloc_vertices(list, 4);
10305     idx = nk_draw_list_alloc_elements(list, 6);
10306     if (!vtx || !idx) return;
10307 
10308     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
10309     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
10310     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
10311 
10312     vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
10313     vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
10314     vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
10315     vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
10316 }
10317 NK_API void
10318 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
10319     struct nk_rect rect, struct nk_color color)
10320 {
10321     NK_ASSERT(list);
10322     if (!list) return;
10323     /* push new command with given texture */
10324     nk_draw_list_push_image(list, texture.handle);
10325     if (nk_image_is_subimage(&texture)) {
10326         /* add region inside of the texture  */
10327         struct nk_vec2 uv[2];
10328         uv[0].x = (float)texture.region[0]/(float)texture.w;
10329         uv[0].y = (float)texture.region[1]/(float)texture.h;
10330         uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
10331         uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
10332         nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
10333             nk_vec2(rect.x + rect.w, rect.y + rect.h),  uv[0], uv[1], color);
10334     } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
10335             nk_vec2(rect.x + rect.w, rect.y + rect.h),
10336             nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
10337 }
10338 NK_API void
10339 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
10340     struct nk_rect rect, const char *text, int len, float font_height,
10341     struct nk_color fg)
10342 {
10343     float x = 0;
10344     int text_len = 0;
10345     nk_rune unicode = 0;
10346     nk_rune next = 0;
10347     int glyph_len = 0;
10348     int next_glyph_len = 0;
10349     struct nk_user_font_glyph g;
10350 
10351     NK_ASSERT(list);
10352     if (!list || !len || !text) return;
10353     if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
10354         list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
10355 
10356     nk_draw_list_push_image(list, font->texture);
10357     x = rect.x;
10358     glyph_len = nk_utf_decode(text, &unicode, len);
10359     if (!glyph_len) return;
10360 
10361     /* draw every glyph image */
10362     fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
10363     while (text_len < len && glyph_len) {
10364         float gx, gy, gh, gw;
10365         float char_width = 0;
10366         if (unicode == NK_UTF_INVALID) break;
10367 
10368         /* query currently drawn glyph information */
10369         next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
10370         font->query(font->userdata, font_height, &g, unicode,
10371                     (next == NK_UTF_INVALID) ? '\0' : next);
10372 
10373         /* calculate and draw glyph drawing rectangle and image */
10374         gx = x + g.offset.x;
10375         gy = rect.y + g.offset.y;
10376         gw = g.width; gh = g.height;
10377         char_width = g.xadvance;
10378         nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
10379             g.uv[0], g.uv[1], fg);
10380 
10381         /* offset next glyph */
10382         text_len += glyph_len;
10383         x += char_width;
10384         glyph_len = next_glyph_len;
10385         unicode = next;
10386     }
10387 }
10388 NK_API nk_flags
10389 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
10390     struct nk_buffer *vertices, struct nk_buffer *elements,
10391     const struct nk_convert_config *config)
10392 {
10393     nk_flags res = NK_CONVERT_SUCCESS;
10394     const struct nk_command *cmd;
10395     NK_ASSERT(ctx);
10396     NK_ASSERT(cmds);
10397     NK_ASSERT(vertices);
10398     NK_ASSERT(elements);
10399     NK_ASSERT(config);
10400     NK_ASSERT(config->vertex_layout);
10401     NK_ASSERT(config->vertex_size);
10402     if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
10403         return NK_CONVERT_INVALID_PARAM;
10404 
10405     nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
10406         config->line_AA, config->shape_AA);
10407     nk_foreach(cmd, ctx)
10408     {
10409 #ifdef NK_INCLUDE_COMMAND_USERDATA
10410         ctx->draw_list.userdata = cmd->userdata;
10411 #endif
10412         switch (cmd->type) {
10413         case NK_COMMAND_NOP: break;
10414         case NK_COMMAND_SCISSOR: {
10415             const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
10416             nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
10417         } break;
10418         case NK_COMMAND_LINE: {
10419             const struct nk_command_line *l = (const struct nk_command_line*)cmd;
10420             nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
10421                 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
10422         } break;
10423         case NK_COMMAND_CURVE: {
10424             const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
10425             nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
10426                 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
10427                 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
10428                 config->curve_segment_count, q->line_thickness);
10429         } break;
10430         case NK_COMMAND_RECT: {
10431             const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
10432             nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10433                 r->color, (float)r->rounding, r->line_thickness);
10434         } break;
10435         case NK_COMMAND_RECT_FILLED: {
10436             const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
10437             nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10438                 r->color, (float)r->rounding);
10439         } break;
10440         case NK_COMMAND_RECT_MULTI_COLOR: {
10441             const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
10442             nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
10443                 r->left, r->top, r->right, r->bottom);
10444         } break;
10445         case NK_COMMAND_CIRCLE: {
10446             const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
10447             nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
10448                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
10449                 config->circle_segment_count, c->line_thickness);
10450         } break;
10451         case NK_COMMAND_CIRCLE_FILLED: {
10452             const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
10453             nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
10454                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
10455                 config->circle_segment_count);
10456         } break;
10457         case NK_COMMAND_ARC: {
10458             const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
10459             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
10460             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
10461                 c->a[0], c->a[1], config->arc_segment_count);
10462             nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
10463         } break;
10464         case NK_COMMAND_ARC_FILLED: {
10465             const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
10466             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
10467             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
10468                 c->a[0], c->a[1], config->arc_segment_count);
10469             nk_draw_list_path_fill(&ctx->draw_list, c->color);
10470         } break;
10471         case NK_COMMAND_TRIANGLE: {
10472             const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
10473             nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
10474                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
10475                 t->line_thickness);
10476         } break;
10477         case NK_COMMAND_TRIANGLE_FILLED: {
10478             const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
10479             nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
10480                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
10481         } break;
10482         case NK_COMMAND_POLYGON: {
10483             int i;
10484             const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
10485             for (i = 0; i < p->point_count; ++i) {
10486                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10487                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10488             }
10489             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
10490         } break;
10491         case NK_COMMAND_POLYGON_FILLED: {
10492             int i;
10493             const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
10494             for (i = 0; i < p->point_count; ++i) {
10495                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10496                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10497             }
10498             nk_draw_list_path_fill(&ctx->draw_list, p->color);
10499         } break;
10500         case NK_COMMAND_POLYLINE: {
10501             int i;
10502             const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
10503             for (i = 0; i < p->point_count; ++i) {
10504                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
10505                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
10506             }
10507             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
10508         } break;
10509         case NK_COMMAND_TEXT: {
10510             const struct nk_command_text *t = (const struct nk_command_text*)cmd;
10511             nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
10512                 t->string, t->length, t->height, t->foreground);
10513         } break;
10514         case NK_COMMAND_IMAGE: {
10515             const struct nk_command_image *i = (const struct nk_command_image*)cmd;
10516             nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
10517         } break;
10518         case NK_COMMAND_CUSTOM: {
10519             const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
10520             c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
10521         } break;
10522         default: break;
10523         }
10524     }
10525     res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
10526     res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
10527     res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
10528     return res;
10529 }
10530 NK_API const struct nk_draw_command*
10531 nk__draw_begin(const struct nk_context *ctx,
10532     const struct nk_buffer *buffer)
10533 {
10534     return nk__draw_list_begin(&ctx->draw_list, buffer);
10535 }
10536 NK_API const struct nk_draw_command*
10537 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
10538 {
10539     return nk__draw_list_end(&ctx->draw_list, buffer);
10540 }
10541 NK_API const struct nk_draw_command*
10542 nk__draw_next(const struct nk_draw_command *cmd,
10543     const struct nk_buffer *buffer, const struct nk_context *ctx)
10544 {
10545     return nk__draw_list_next(cmd, buffer, &ctx->draw_list);
10546 }
10547 #endif
10548 
10549 
10550 
10551 
10552 
10553 #ifdef NK_INCLUDE_FONT_BAKING
10554 /* -------------------------------------------------------------
10555  *
10556  *                          RECT PACK
10557  *
10558  * --------------------------------------------------------------*/
10559 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
10560 /* Sean Barrett 2014 */
10561 #define NK_RP__MAXVAL  0xffff
10562 typedef unsigned short nk_rp_coord;
10563 
10564 struct nk_rp_rect {
10565     /* reserved for your use: */
10566     int id;
10567     /* input: */
10568     nk_rp_coord w, h;
10569     /* output: */
10570     nk_rp_coord x, y;
10571     int was_packed;
10572     /* non-zero if valid packing */
10573 }; /* 16 bytes, nominally */
10574 
10575 struct nk_rp_node {
10576     nk_rp_coord  x,y;
10577     struct nk_rp_node  *next;
10578 };
10579 
10580 struct nk_rp_context {
10581     int width;
10582     int height;
10583     int align;
10584     int init_mode;
10585     int heuristic;
10586     int num_nodes;
10587     struct nk_rp_node *active_head;
10588     struct nk_rp_node *free_head;
10589     struct nk_rp_node extra[2];
10590     /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
10591 };
10592 
10593 struct nk_rp__findresult {
10594     int x,y;
10595     struct nk_rp_node **prev_link;
10596 };
10597 
10598 enum NK_RP_HEURISTIC {
10599     NK_RP_HEURISTIC_Skyline_default=0,
10600     NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
10601     NK_RP_HEURISTIC_Skyline_BF_sortHeight
10602 };
10603 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
10604 
10605 NK_INTERN void
10606 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
10607 {
10608     if (allow_out_of_mem)
10609         /* if it's ok to run out of memory, then don't bother aligning them; */
10610         /* this gives better packing, but may fail due to OOM (even though */
10611         /* the rectangles easily fit). @TODO a smarter approach would be to only */
10612         /* quantize once we've hit OOM, then we could get rid of this parameter. */
10613         context->align = 1;
10614     else {
10615         /* if it's not ok to run out of memory, then quantize the widths */
10616         /* so that num_nodes is always enough nodes. */
10617         /* */
10618         /* I.e. num_nodes * align >= width */
10619         /*                  align >= width / num_nodes */
10620         /*                  align = ceil(width/num_nodes) */
10621         context->align = (context->width + context->num_nodes-1) / context->num_nodes;
10622     }
10623 }
10624 NK_INTERN void
10625 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
10626     struct nk_rp_node *nodes, int num_nodes)
10627 {
10628     int i;
10629 #ifndef STBRP_LARGE_RECTS
10630     NK_ASSERT(width <= 0xffff && height <= 0xffff);
10631 #endif
10632 
10633     for (i=0; i < num_nodes-1; ++i)
10634         nodes[i].next = &nodes[i+1];
10635     nodes[i].next = 0;
10636     context->init_mode = NK_RP__INIT_skyline;
10637     context->heuristic = NK_RP_HEURISTIC_Skyline_default;
10638     context->free_head = &nodes[0];
10639     context->active_head = &context->extra[0];
10640     context->width = width;
10641     context->height = height;
10642     context->num_nodes = num_nodes;
10643     nk_rp_setup_allow_out_of_mem(context, 0);
10644 
10645     /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
10646     context->extra[0].x = 0;
10647     context->extra[0].y = 0;
10648     context->extra[0].next = &context->extra[1];
10649     context->extra[1].x = (nk_rp_coord) width;
10650     context->extra[1].y = 65535;
10651     context->extra[1].next = 0;
10652 }
10653 /* find minimum y position if it starts at x1 */
10654 NK_INTERN int
10655 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
10656     int x0, int width, int *pwaste)
10657 {
10658     struct nk_rp_node *node = first;
10659     int x1 = x0 + width;
10660     int min_y, visited_width, waste_area;
10661     NK_ASSERT(first->x <= x0);
10662     NK_UNUSED(c);
10663 
10664     NK_ASSERT(node->next->x > x0);
10665     /* we ended up handling this in the caller for efficiency */
10666     NK_ASSERT(node->x <= x0);
10667 
10668     min_y = 0;
10669     waste_area = 0;
10670     visited_width = 0;
10671     while (node->x < x1)
10672     {
10673         if (node->y > min_y) {
10674             /* raise min_y higher. */
10675             /* we've accounted for all waste up to min_y, */
10676             /* but we'll now add more waste for everything we've visited */
10677             waste_area += visited_width * (node->y - min_y);
10678             min_y = node->y;
10679             /* the first time through, visited_width might be reduced */
10680             if (node->x < x0)
10681             visited_width += node->next->x - x0;
10682             else
10683             visited_width += node->next->x - node->x;
10684         } else {
10685             /* add waste area */
10686             int under_width = node->next->x - node->x;
10687             if (under_width + visited_width > width)
10688             under_width = width - visited_width;
10689             waste_area += under_width * (min_y - node->y);
10690             visited_width += under_width;
10691         }
10692         node = node->next;
10693     }
10694     *pwaste = waste_area;
10695     return min_y;
10696 }
10697 NK_INTERN struct nk_rp__findresult
10698 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
10699 {
10700     int best_waste = (1<<30), best_x, best_y = (1 << 30);
10701     struct nk_rp__findresult fr;
10702     struct nk_rp_node **prev, *node, *tail, **best = 0;
10703 
10704     /* align to multiple of c->align */
10705     width = (width + c->align - 1);
10706     width -= width % c->align;
10707     NK_ASSERT(width % c->align == 0);
10708 
10709     node = c->active_head;
10710     prev = &c->active_head;
10711     while (node->x + width <= c->width) {
10712         int y,waste;
10713         y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
10714         /* actually just want to test BL */
10715         if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
10716             /* bottom left */
10717             if (y < best_y) {
10718             best_y = y;
10719             best = prev;
10720             }
10721         } else {
10722             /* best-fit */
10723             if (y + height <= c->height) {
10724                 /* can only use it if it first vertically */
10725                 if (y < best_y || (y == best_y && waste < best_waste)) {
10726                     best_y = y;
10727                     best_waste = waste;
10728                     best = prev;
10729                 }
10730             }
10731         }
10732         prev = &node->next;
10733         node = node->next;
10734     }
10735     best_x = (best == 0) ? 0 : (*best)->x;
10736 
10737     /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
10738     /* */
10739     /* e.g, if fitting */
10740     /* */
10741     /*     ____________________ */
10742     /*    |____________________| */
10743     /* */
10744     /*            into */
10745     /* */
10746     /*   |                         | */
10747     /*   |             ____________| */
10748     /*   |____________| */
10749     /* */
10750     /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
10751     /* */
10752     /* This makes BF take about 2x the time */
10753     if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
10754     {
10755         tail = c->active_head;
10756         node = c->active_head;
10757         prev = &c->active_head;
10758         /* find first node that's admissible */
10759         while (tail->x < width)
10760             tail = tail->next;
10761         while (tail)
10762         {
10763             int xpos = tail->x - width;
10764             int y,waste;
10765             NK_ASSERT(xpos >= 0);
10766             /* find the left position that matches this */
10767             while (node->next->x <= xpos) {
10768                 prev = &node->next;
10769                 node = node->next;
10770             }
10771             NK_ASSERT(node->next->x > xpos && node->x <= xpos);
10772             y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
10773             if (y + height < c->height) {
10774                 if (y <= best_y) {
10775                     if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
10776                         best_x = xpos;
10777                         NK_ASSERT(y <= best_y);
10778                         best_y = y;
10779                         best_waste = waste;
10780                         best = prev;
10781                     }
10782                 }
10783             }
10784             tail = tail->next;
10785         }
10786     }
10787     fr.prev_link = best;
10788     fr.x = best_x;
10789     fr.y = best_y;
10790     return fr;
10791 }
10792 NK_INTERN struct nk_rp__findresult
10793 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
10794 {
10795     /* find best position according to heuristic */
10796     struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
10797     struct nk_rp_node *node, *cur;
10798 
10799     /* bail if: */
10800     /*    1. it failed */
10801     /*    2. the best node doesn't fit (we don't always check this) */
10802     /*    3. we're out of memory */
10803     if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
10804         res.prev_link = 0;
10805         return res;
10806     }
10807 
10808     /* on success, create new node */
10809     node = context->free_head;
10810     node->x = (nk_rp_coord) res.x;
10811     node->y = (nk_rp_coord) (res.y + height);
10812 
10813     context->free_head = node->next;
10814 
10815     /* insert the new node into the right starting point, and */
10816     /* let 'cur' point to the remaining nodes needing to be */
10817     /* stitched back in */
10818     cur = *res.prev_link;
10819     if (cur->x < res.x) {
10820         /* preserve the existing one, so start testing with the next one */
10821         struct nk_rp_node *next = cur->next;
10822         cur->next = node;
10823         cur = next;
10824     } else {
10825         *res.prev_link = node;
10826     }
10827 
10828     /* from here, traverse cur and free the nodes, until we get to one */
10829     /* that shouldn't be freed */
10830     while (cur->next && cur->next->x <= res.x + width) {
10831         struct nk_rp_node *next = cur->next;
10832         /* move the current node to the free list */
10833         cur->next = context->free_head;
10834         context->free_head = cur;
10835         cur = next;
10836     }
10837     /* stitch the list back in */
10838     node->next = cur;
10839 
10840     if (cur->x < res.x + width)
10841         cur->x = (nk_rp_coord) (res.x + width);
10842     return res;
10843 }
10844 NK_INTERN int
10845 nk_rect_height_compare(const void *a, const void *b)
10846 {
10847     const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
10848     const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
10849     if (p->h > q->h)
10850         return -1;
10851     if (p->h < q->h)
10852         return  1;
10853     return (p->w > q->w) ? -1 : (p->w < q->w);
10854 }
10855 NK_INTERN int
10856 nk_rect_original_order(const void *a, const void *b)
10857 {
10858     const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
10859     const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
10860     return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
10861 }
10862 NK_INTERN void
10863 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
10864 {
10865     /* iterative quick sort */
10866     #define NK_MAX_SORT_STACK 64
10867     unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
10868     unsigned seed = len/2 * 69069+1;
10869     for (;;) {
10870         for (; left+1 < len; len++) {
10871             struct nk_rp_rect pivot, tmp;
10872             if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
10873             pivot = array[left+seed%(len-left)];
10874             seed = seed * 69069 + 1;
10875             stack[pos++] = len;
10876             for (right = left-1;;) {
10877                 while (cmp(&array[++right], &pivot) < 0);
10878                 while (cmp(&pivot, &array[--len]) < 0);
10879                 if (right >= len) break;
10880                 tmp = array[right];
10881                 array[right] = array[len];
10882                 array[len] = tmp;
10883             }
10884         }
10885         if (pos == 0) break;
10886         left = len;
10887         len = stack[--pos];
10888     }
10889     #undef NK_MAX_SORT_STACK
10890 }
10891 NK_INTERN void
10892 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
10893 {
10894     int i;
10895     /* we use the 'was_packed' field internally to allow sorting/unsorting */
10896     for (i=0; i < num_rects; ++i) {
10897         rects[i].was_packed = i;
10898     }
10899 
10900     /* sort according to heuristic */
10901     nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
10902 
10903     for (i=0; i < num_rects; ++i) {
10904         struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
10905         if (fr.prev_link) {
10906             rects[i].x = (nk_rp_coord) fr.x;
10907             rects[i].y = (nk_rp_coord) fr.y;
10908         } else {
10909             rects[i].x = rects[i].y = NK_RP__MAXVAL;
10910         }
10911     }
10912 
10913     /* unsort */
10914     nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
10915 
10916     /* set was_packed flags */
10917     for (i=0; i < num_rects; ++i)
10918         rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
10919 }
10920 
10921 /*
10922  * ==============================================================
10923  *
10924  *                          TRUETYPE
10925  *
10926  * ===============================================================
10927  */
10928 /* stb_truetype.h - v1.07 - public domain */
10929 #define NK_TT_MAX_OVERSAMPLE   8
10930 #define NK_TT__OVER_MASK  (NK_TT_MAX_OVERSAMPLE-1)
10931 
10932 struct nk_tt_bakedchar {
10933     unsigned short x0,y0,x1,y1;
10934     /* coordinates of bbox in bitmap */
10935     float xoff,yoff,xadvance;
10936 };
10937 
10938 struct nk_tt_aligned_quad{
10939     float x0,y0,s0,t0; /* top-left */
10940     float x1,y1,s1,t1; /* bottom-right */
10941 };
10942 
10943 struct nk_tt_packedchar {
10944     unsigned short x0,y0,x1,y1;
10945     /* coordinates of bbox in bitmap */
10946     float xoff,yoff,xadvance;
10947     float xoff2,yoff2;
10948 };
10949 
10950 struct nk_tt_pack_range {
10951     float font_size;
10952     int first_unicode_codepoint_in_range;
10953     /* if non-zero, then the chars are continuous, and this is the first codepoint */
10954     int *array_of_unicode_codepoints;
10955     /* if non-zero, then this is an array of unicode codepoints */
10956     int num_chars;
10957     struct nk_tt_packedchar *chardata_for_range; /* output */
10958     unsigned char h_oversample, v_oversample;
10959     /* don't set these, they're used internally */
10960 };
10961 
10962 struct nk_tt_pack_context {
10963     void *pack_info;
10964     int   width;
10965     int   height;
10966     int   stride_in_bytes;
10967     int   padding;
10968     unsigned int   h_oversample, v_oversample;
10969     unsigned char *pixels;
10970     void  *nodes;
10971 };
10972 
10973 struct nk_tt_fontinfo {
10974     const unsigned char* data; /* pointer to .ttf file */
10975     int fontstart;/* offset of start of font */
10976     int numGlyphs;/* number of glyphs, needed for range checking */
10977     int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
10978     int index_map; /* a cmap mapping for our chosen character encoding */
10979     int indexToLocFormat; /* format needed to map from glyph index to glyph */
10980 };
10981 
10982 enum {
10983   NK_TT_vmove=1,
10984   NK_TT_vline,
10985   NK_TT_vcurve
10986 };
10987 
10988 struct nk_tt_vertex {
10989     short x,y,cx,cy;
10990     unsigned char type,padding;
10991 };
10992 
10993 struct nk_tt__bitmap{
10994    int w,h,stride;
10995    unsigned char *pixels;
10996 };
10997 
10998 struct nk_tt__hheap_chunk {
10999     struct nk_tt__hheap_chunk *next;
11000 };
11001 struct nk_tt__hheap {
11002     struct nk_allocator alloc;
11003     struct nk_tt__hheap_chunk *head;
11004     void   *first_free;
11005     int    num_remaining_in_head_chunk;
11006 };
11007 
11008 struct nk_tt__edge {
11009     float x0,y0, x1,y1;
11010     int invert;
11011 };
11012 
11013 struct nk_tt__active_edge {
11014     struct nk_tt__active_edge *next;
11015     float fx,fdx,fdy;
11016     float direction;
11017     float sy;
11018     float ey;
11019 };
11020 struct nk_tt__point {float x,y;};
11021 
11022 #define NK_TT_MACSTYLE_DONTCARE     0
11023 #define NK_TT_MACSTYLE_BOLD         1
11024 #define NK_TT_MACSTYLE_ITALIC       2
11025 #define NK_TT_MACSTYLE_UNDERSCORE   4
11026 #define NK_TT_MACSTYLE_NONE         8
11027 /* <= not same as 0, this makes us check the bitfield is 0 */
11028 
11029 enum { /* platformID */
11030    NK_TT_PLATFORM_ID_UNICODE   =0,
11031    NK_TT_PLATFORM_ID_MAC       =1,
11032    NK_TT_PLATFORM_ID_ISO       =2,
11033    NK_TT_PLATFORM_ID_MICROSOFT =3
11034 };
11035 
11036 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
11037    NK_TT_UNICODE_EID_UNICODE_1_0    =0,
11038    NK_TT_UNICODE_EID_UNICODE_1_1    =1,
11039    NK_TT_UNICODE_EID_ISO_10646      =2,
11040    NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
11041    NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
11042 };
11043 
11044 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
11045    NK_TT_MS_EID_SYMBOL        =0,
11046    NK_TT_MS_EID_UNICODE_BMP   =1,
11047    NK_TT_MS_EID_SHIFTJIS      =2,
11048    NK_TT_MS_EID_UNICODE_FULL  =10
11049 };
11050 
11051 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
11052    NK_TT_MAC_EID_ROMAN        =0,   NK_TT_MAC_EID_ARABIC       =4,
11053    NK_TT_MAC_EID_JAPANESE     =1,   NK_TT_MAC_EID_HEBREW       =5,
11054    NK_TT_MAC_EID_CHINESE_TRAD =2,   NK_TT_MAC_EID_GREEK        =6,
11055    NK_TT_MAC_EID_KOREAN       =3,   NK_TT_MAC_EID_RUSSIAN      =7
11056 };
11057 
11058 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
11059        /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
11060    NK_TT_MS_LANG_ENGLISH     =0x0409,   NK_TT_MS_LANG_ITALIAN     =0x0410,
11061    NK_TT_MS_LANG_CHINESE     =0x0804,   NK_TT_MS_LANG_JAPANESE    =0x0411,
11062    NK_TT_MS_LANG_DUTCH       =0x0413,   NK_TT_MS_LANG_KOREAN      =0x0412,
11063    NK_TT_MS_LANG_FRENCH      =0x040c,   NK_TT_MS_LANG_RUSSIAN     =0x0419,
11064    NK_TT_MS_LANG_GERMAN      =0x0407,   NK_TT_MS_LANG_SPANISH     =0x0409,
11065    NK_TT_MS_LANG_HEBREW      =0x040d,   NK_TT_MS_LANG_SWEDISH     =0x041D
11066 };
11067 
11068 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
11069    NK_TT_MAC_LANG_ENGLISH      =0 ,   NK_TT_MAC_LANG_JAPANESE     =11,
11070    NK_TT_MAC_LANG_ARABIC       =12,   NK_TT_MAC_LANG_KOREAN       =23,
11071    NK_TT_MAC_LANG_DUTCH        =4 ,   NK_TT_MAC_LANG_RUSSIAN      =32,
11072    NK_TT_MAC_LANG_FRENCH       =1 ,   NK_TT_MAC_LANG_SPANISH      =6 ,
11073    NK_TT_MAC_LANG_GERMAN       =2 ,   NK_TT_MAC_LANG_SWEDISH      =5 ,
11074    NK_TT_MAC_LANG_HEBREW       =10,   NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
11075    NK_TT_MAC_LANG_ITALIAN      =3 ,   NK_TT_MAC_LANG_CHINESE_TRAD =19
11076 };
11077 
11078 #define nk_ttBYTE(p)     (* (const nk_byte *) (p))
11079 #define nk_ttCHAR(p)     (* (const char *) (p))
11080 
11081 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
11082    #define nk_ttUSHORT(p)   (* (nk_ushort *) (p))
11083    #define nk_ttSHORT(p)    (* (nk_short *) (p))
11084    #define nk_ttULONG(p)    (* (nk_uint *) (p))
11085    #define nk_ttLONG(p)     (* (nk_int *) (p))
11086 #else
11087     static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
11088     static nk_short nk_ttSHORT(const nk_byte *p)   { return (nk_short)(p[0]*256 + p[1]); }
11089     static nk_uint nk_ttULONG(const nk_byte *p)  { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
11090 #endif
11091 
11092 #define nk_tt_tag4(p,c0,c1,c2,c3)\
11093     ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
11094 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
11095 
11096 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
11097                                 int glyph_index, struct nk_tt_vertex **pvertices);
11098 
11099 NK_INTERN nk_uint
11100 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
11101 {
11102     /* @OPTIMIZE: binary search */
11103     nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
11104     nk_uint tabledir = fontstart + 12;
11105     nk_int i;
11106     for (i = 0; i < num_tables; ++i) {
11107         nk_uint loc = tabledir + (nk_uint)(16*i);
11108         if (nk_tt_tag(data+loc+0, tag))
11109             return nk_ttULONG(data+loc+8);
11110     }
11111     return 0;
11112 }
11113 NK_INTERN int
11114 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
11115 {
11116     nk_uint cmap, t;
11117     nk_int i,numTables;
11118     const nk_byte *data = (const nk_byte *) data2;
11119 
11120     info->data = data;
11121     info->fontstart = fontstart;
11122 
11123     cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap");       /* required */
11124     info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
11125     info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
11126     info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
11127     info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
11128     info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
11129     info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
11130     if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
11131         return 0;
11132 
11133     t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
11134     if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
11135     else info->numGlyphs = 0xffff;
11136 
11137     /* find a cmap encoding table we understand *now* to avoid searching */
11138     /* later. (todo: could make this installable) */
11139     /* the same regardless of glyph. */
11140     numTables = nk_ttUSHORT(data + cmap + 2);
11141     info->index_map = 0;
11142     for (i=0; i < numTables; ++i)
11143     {
11144         nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
11145         /* find an encoding we understand: */
11146         switch(nk_ttUSHORT(data+encoding_record)) {
11147         case NK_TT_PLATFORM_ID_MICROSOFT:
11148             switch (nk_ttUSHORT(data+encoding_record+2)) {
11149             case NK_TT_MS_EID_UNICODE_BMP:
11150             case NK_TT_MS_EID_UNICODE_FULL:
11151                 /* MS/Unicode */
11152                 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
11153                 break;
11154             default: break;
11155             } break;
11156         case NK_TT_PLATFORM_ID_UNICODE:
11157             /* Mac/iOS has these */
11158             /* all the encodingIDs are unicode, so we don't bother to check it */
11159             info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
11160             break;
11161         default: break;
11162         }
11163     }
11164     if (info->index_map == 0)
11165         return 0;
11166     info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
11167     return 1;
11168 }
11169 NK_INTERN int
11170 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
11171 {
11172     const nk_byte *data = info->data;
11173     nk_uint index_map = (nk_uint)info->index_map;
11174 
11175     nk_ushort format = nk_ttUSHORT(data + index_map + 0);
11176     if (format == 0) { /* apple byte encoding */
11177         nk_int bytes = nk_ttUSHORT(data + index_map + 2);
11178         if (unicode_codepoint < bytes-6)
11179             return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
11180         return 0;
11181     } else if (format == 6) {
11182         nk_uint first = nk_ttUSHORT(data + index_map + 6);
11183         nk_uint count = nk_ttUSHORT(data + index_map + 8);
11184         if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
11185             return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
11186         return 0;
11187     } else if (format == 2) {
11188         NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
11189         return 0;
11190     } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
11191         nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
11192         nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
11193         nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
11194         nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
11195 
11196         /* do a binary search of the segments */
11197         nk_uint endCount = index_map + 14;
11198         nk_uint search = endCount;
11199 
11200         if (unicode_codepoint > 0xffff)
11201             return 0;
11202 
11203         /* they lie from endCount .. endCount + segCount */
11204         /* but searchRange is the nearest power of two, so... */
11205         if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
11206             search += (nk_uint)(rangeShift*2);
11207 
11208         /* now decrement to bias correctly to find smallest */
11209         search -= 2;
11210         while (entrySelector) {
11211             nk_ushort end;
11212             searchRange >>= 1;
11213             end = nk_ttUSHORT(data + search + searchRange*2);
11214             if (unicode_codepoint > end)
11215                 search += (nk_uint)(searchRange*2);
11216             --entrySelector;
11217         }
11218         search += 2;
11219 
11220       {
11221          nk_ushort offset, start;
11222          nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
11223 
11224          NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
11225          start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
11226          if (unicode_codepoint < start)
11227             return 0;
11228 
11229          offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
11230          if (offset == 0)
11231             return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
11232 
11233          return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
11234       }
11235    } else if (format == 12 || format == 13) {
11236         nk_uint ngroups = nk_ttULONG(data+index_map+12);
11237         nk_int low,high;
11238         low = 0; high = (nk_int)ngroups;
11239         /* Binary search the right group. */
11240         while (low < high) {
11241             nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
11242             nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
11243             nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
11244             if ((nk_uint) unicode_codepoint < start_char)
11245                 high = mid;
11246             else if ((nk_uint) unicode_codepoint > end_char)
11247                 low = mid+1;
11248             else {
11249                 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
11250                 if (format == 12)
11251                     return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
11252                 else /* format == 13 */
11253                     return (int)start_glyph;
11254             }
11255         }
11256         return 0; /* not found */
11257     }
11258     /* @TODO */
11259     NK_ASSERT(0);
11260     return 0;
11261 }
11262 NK_INTERN void
11263 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
11264 {
11265     v->type = type;
11266     v->x = (nk_short) x;
11267     v->y = (nk_short) y;
11268     v->cx = (nk_short) cx;
11269     v->cy = (nk_short) cy;
11270 }
11271 NK_INTERN int
11272 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
11273 {
11274     int g1,g2;
11275     if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
11276     if (info->indexToLocFormat >= 2)    return -1; /* unknown index->glyph map format */
11277 
11278     if (info->indexToLocFormat == 0) {
11279         g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
11280         g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
11281     } else {
11282         g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
11283         g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
11284     }
11285     return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
11286 }
11287 NK_INTERN int
11288 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
11289     int *x0, int *y0, int *x1, int *y1)
11290 {
11291     int g = nk_tt__GetGlyfOffset(info, glyph_index);
11292     if (g < 0) return 0;
11293 
11294     if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
11295     if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
11296     if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
11297     if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
11298     return 1;
11299 }
11300 NK_INTERN int
11301 nk_tt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
11302     int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
11303 {
11304    if (start_off) {
11305       if (was_off)
11306          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
11307       nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
11308    } else {
11309       if (was_off)
11310          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
11311       else
11312          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
11313    }
11314    return num_vertices;
11315 }
11316 NK_INTERN int
11317 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
11318     int glyph_index, struct nk_tt_vertex **pvertices)
11319 {
11320     nk_short numberOfContours;
11321     const nk_byte *endPtsOfContours;
11322     const nk_byte *data = info->data;
11323     struct nk_tt_vertex *vertices=0;
11324     int num_vertices=0;
11325     int g = nk_tt__GetGlyfOffset(info, glyph_index);
11326     *pvertices = 0;
11327 
11328     if (g < 0) return 0;
11329     numberOfContours = nk_ttSHORT(data + g);
11330     if (numberOfContours > 0) {
11331         nk_byte flags=0,flagcount;
11332         nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
11333         nk_int x,y,cx,cy,sx,sy, scx,scy;
11334         const nk_byte *points;
11335         endPtsOfContours = (data + g + 10);
11336         ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
11337         points = data + g + 10 + numberOfContours * 2 + 2 + ins;
11338 
11339         n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
11340         m = n + 2*numberOfContours;  /* a loose bound on how many vertices we might need */
11341         vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
11342         if (vertices == 0)
11343             return 0;
11344 
11345         next_move = 0;
11346         flagcount=0;
11347 
11348         /* in first pass, we load uninterpreted data into the allocated array */
11349         /* above, shifted to the end of the array so we won't overwrite it when */
11350         /* we create our final data starting from the front */
11351         off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
11352 
11353         /* first load flags */
11354         for (i=0; i < n; ++i) {
11355             if (flagcount == 0) {
11356                 flags = *points++;
11357                 if (flags & 8)
11358                     flagcount = *points++;
11359             } else --flagcount;
11360             vertices[off+i].type = flags;
11361         }
11362 
11363         /* now load x coordinates */
11364         x=0;
11365         for (i=0; i < n; ++i) {
11366             flags = vertices[off+i].type;
11367             if (flags & 2) {
11368                 nk_short dx = *points++;
11369                 x += (flags & 16) ? dx : -dx; /* ??? */
11370             } else {
11371                 if (!(flags & 16)) {
11372                     x = x + (nk_short) (points[0]*256 + points[1]);
11373                     points += 2;
11374                 }
11375             }
11376             vertices[off+i].x = (nk_short) x;
11377         }
11378 
11379         /* now load y coordinates */
11380         y=0;
11381         for (i=0; i < n; ++i) {
11382             flags = vertices[off+i].type;
11383             if (flags & 4) {
11384                 nk_short dy = *points++;
11385                 y += (flags & 32) ? dy : -dy; /* ??? */
11386             } else {
11387                 if (!(flags & 32)) {
11388                     y = y + (nk_short) (points[0]*256 + points[1]);
11389                     points += 2;
11390                 }
11391             }
11392             vertices[off+i].y = (nk_short) y;
11393         }
11394 
11395         /* now convert them to our format */
11396         num_vertices=0;
11397         sx = sy = cx = cy = scx = scy = 0;
11398         for (i=0; i < n; ++i)
11399         {
11400             flags = vertices[off+i].type;
11401             x     = (nk_short) vertices[off+i].x;
11402             y     = (nk_short) vertices[off+i].y;
11403 
11404             if (next_move == i) {
11405                 if (i != 0)
11406                     num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
11407 
11408                 /* now start the new one                */
11409                 start_off = !(flags & 1);
11410                 if (start_off) {
11411                     /* if we start off with an off-curve point, then when we need to find a point on the curve */
11412                     /* where we can start, and we need to save some state for when we wraparound. */
11413                     scx = x;
11414                     scy = y;
11415                     if (!(vertices[off+i+1].type & 1)) {
11416                         /* next point is also a curve point, so interpolate an on-point curve */
11417                         sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
11418                         sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
11419                     } else {
11420                         /* otherwise just use the next point as our start point */
11421                         sx = (nk_int) vertices[off+i+1].x;
11422                         sy = (nk_int) vertices[off+i+1].y;
11423                         ++i; /* we're using point i+1 as the starting point, so skip it */
11424                     }
11425                 } else {
11426                     sx = x;
11427                     sy = y;
11428                 }
11429                 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
11430                 was_off = 0;
11431                 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
11432                 ++j;
11433             } else {
11434                 if (!(flags & 1))
11435                 { /* if it's a curve */
11436                     if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
11437                         nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
11438                     cx = x;
11439                     cy = y;
11440                     was_off = 1;
11441                 } else {
11442                     if (was_off)
11443                         nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
11444                     else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
11445                     was_off = 0;
11446                 }
11447             }
11448         }
11449         num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
11450     } else if (numberOfContours == -1) {
11451         /* Compound shapes. */
11452         int more = 1;
11453         const nk_byte *comp = data + g + 10;
11454         num_vertices = 0;
11455         vertices = 0;
11456 
11457         while (more)
11458         {
11459             nk_ushort flags, gidx;
11460             int comp_num_verts = 0, i;
11461             struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
11462             float mtx[6] = {1,0,0,1,0,0}, m, n;
11463 
11464             flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
11465             gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
11466 
11467             if (flags & 2) { /* XY values */
11468                 if (flags & 1) { /* shorts */
11469                     mtx[4] = nk_ttSHORT(comp); comp+=2;
11470                     mtx[5] = nk_ttSHORT(comp); comp+=2;
11471                 } else {
11472                     mtx[4] = nk_ttCHAR(comp); comp+=1;
11473                     mtx[5] = nk_ttCHAR(comp); comp+=1;
11474                 }
11475             } else {
11476                 /* @TODO handle matching point */
11477                 NK_ASSERT(0);
11478             }
11479             if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
11480                 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11481                 mtx[1] = mtx[2] = 0;
11482             } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
11483                 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11484                 mtx[1] = mtx[2] = 0;
11485                 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11486             } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
11487                 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11488                 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11489                 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11490                 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
11491             }
11492 
11493              /* Find transformation scales. */
11494             m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
11495             n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
11496 
11497              /* Get indexed glyph. */
11498             comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
11499             if (comp_num_verts > 0)
11500             {
11501                 /* Transform vertices. */
11502                 for (i = 0; i < comp_num_verts; ++i) {
11503                     struct nk_tt_vertex* v = &comp_verts[i];
11504                     short x,y;
11505                     x=v->x; y=v->y;
11506                     v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
11507                     v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
11508                     x=v->cx; y=v->cy;
11509                     v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
11510                     v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
11511                 }
11512                 /* Append vertices. */
11513                 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
11514                     (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
11515                 if (!tmp) {
11516                     if (vertices) alloc->free(alloc->userdata, vertices);
11517                     if (comp_verts) alloc->free(alloc->userdata, comp_verts);
11518                     return 0;
11519                 }
11520                 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
11521                 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
11522                 if (vertices) alloc->free(alloc->userdata,vertices);
11523                 vertices = tmp;
11524                 alloc->free(alloc->userdata,comp_verts);
11525                 num_vertices += comp_num_verts;
11526             }
11527             /* More components ? */
11528             more = flags & (1<<5);
11529         }
11530     } else if (numberOfContours < 0) {
11531         /* @TODO other compound variations? */
11532         NK_ASSERT(0);
11533     } else {
11534         /* numberOfCounters == 0, do nothing */
11535     }
11536     *pvertices = vertices;
11537     return num_vertices;
11538 }
11539 NK_INTERN void
11540 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
11541     int *advanceWidth, int *leftSideBearing)
11542 {
11543     nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
11544     if (glyph_index < numOfLongHorMetrics) {
11545         if (advanceWidth)
11546             *advanceWidth    = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
11547         if (leftSideBearing)
11548             *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
11549     } else {
11550         if (advanceWidth)
11551             *advanceWidth    = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
11552         if (leftSideBearing)
11553             *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
11554     }
11555 }
11556 NK_INTERN void
11557 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
11558     int *ascent, int *descent, int *lineGap)
11559 {
11560    if (ascent ) *ascent  = nk_ttSHORT(info->data+info->hhea + 4);
11561    if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
11562    if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
11563 }
11564 NK_INTERN float
11565 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
11566 {
11567    int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
11568    return (float) height / (float)fheight;
11569 }
11570 NK_INTERN float
11571 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
11572 {
11573    int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
11574    return pixels / (float)unitsPerEm;
11575 }
11576 
11577 /*-------------------------------------------------------------
11578  *            antialiasing software rasterizer
11579  * --------------------------------------------------------------*/
11580 NK_INTERN void
11581 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
11582     int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
11583     int *ix0, int *iy0, int *ix1, int *iy1)
11584 {
11585     int x0,y0,x1,y1;
11586     if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
11587         /* e.g. space character */
11588         if (ix0) *ix0 = 0;
11589         if (iy0) *iy0 = 0;
11590         if (ix1) *ix1 = 0;
11591         if (iy1) *iy1 = 0;
11592     } else {
11593         /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
11594         if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
11595         if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
11596         if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
11597         if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
11598     }
11599 }
11600 NK_INTERN void
11601 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
11602     float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
11603 {
11604    nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
11605 }
11606 
11607 /*-------------------------------------------------------------
11608  *                          Rasterizer
11609  * --------------------------------------------------------------*/
11610 NK_INTERN void*
11611 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
11612 {
11613     if (hh->first_free) {
11614         void *p = hh->first_free;
11615         hh->first_free = * (void **) p;
11616         return p;
11617     } else {
11618         if (hh->num_remaining_in_head_chunk == 0) {
11619             int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
11620             struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
11621                 hh->alloc.alloc(hh->alloc.userdata, 0,
11622                 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
11623             if (c == 0) return 0;
11624             c->next = hh->head;
11625             hh->head = c;
11626             hh->num_remaining_in_head_chunk = count;
11627         }
11628         --hh->num_remaining_in_head_chunk;
11629         return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
11630     }
11631 }
11632 NK_INTERN void
11633 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
11634 {
11635     *(void **) p = hh->first_free;
11636     hh->first_free = p;
11637 }
11638 NK_INTERN void
11639 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
11640 {
11641     struct nk_tt__hheap_chunk *c = hh->head;
11642     while (c) {
11643         struct nk_tt__hheap_chunk *n = c->next;
11644         hh->alloc.free(hh->alloc.userdata, c);
11645         c = n;
11646     }
11647 }
11648 NK_INTERN struct nk_tt__active_edge*
11649 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
11650     int off_x, float start_point)
11651 {
11652     struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
11653         nk_tt__hheap_alloc(hh, sizeof(*z));
11654     float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
11655     /*STBTT_assert(e->y0 <= start_point); */
11656     if (!z) return z;
11657     z->fdx = dxdy;
11658     z->fdy = (dxdy != 0) ? (1/dxdy): 0;
11659     z->fx = e->x0 + dxdy * (start_point - e->y0);
11660     z->fx -= (float)off_x;
11661     z->direction = e->invert ? 1.0f : -1.0f;
11662     z->sy = e->y0;
11663     z->ey = e->y1;
11664     z->next = 0;
11665     return z;
11666 }
11667 NK_INTERN void
11668 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
11669     float x0, float y0, float x1, float y1)
11670 {
11671     if (y0 == y1) return;
11672     NK_ASSERT(y0 < y1);
11673     NK_ASSERT(e->sy <= e->ey);
11674     if (y0 > e->ey) return;
11675     if (y1 < e->sy) return;
11676     if (y0 < e->sy) {
11677         x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
11678         y0 = e->sy;
11679     }
11680     if (y1 > e->ey) {
11681         x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
11682         y1 = e->ey;
11683     }
11684 
11685     if (x0 == x) NK_ASSERT(x1 <= x+1);
11686     else if (x0 == x+1) NK_ASSERT(x1 >= x);
11687     else if (x0 <= x) NK_ASSERT(x1 <= x);
11688     else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
11689     else NK_ASSERT(x1 >= x && x1 <= x+1);
11690 
11691     if (x0 <= x && x1 <= x)
11692         scanline[x] += e->direction * (y1-y0);
11693     else if (x0 >= x+1 && x1 >= x+1);
11694     else {
11695         NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
11696         /* coverage = 1 - average x position */
11697         scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
11698     }
11699 }
11700 NK_INTERN void
11701 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
11702     struct nk_tt__active_edge *e, float y_top)
11703 {
11704     float y_bottom = y_top+1;
11705     while (e)
11706     {
11707         /* brute force every pixel */
11708         /* compute intersection points with top & bottom */
11709         NK_ASSERT(e->ey >= y_top);
11710         if (e->fdx == 0) {
11711             float x0 = e->fx;
11712             if (x0 < len) {
11713                 if (x0 >= 0) {
11714                     nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
11715                     nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
11716                 } else {
11717                     nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
11718                 }
11719             }
11720         } else {
11721             float x0 = e->fx;
11722             float dx = e->fdx;
11723             float xb = x0 + dx;
11724             float x_top, x_bottom;
11725             float y0,y1;
11726             float dy = e->fdy;
11727             NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
11728 
11729             /* compute endpoints of line segment clipped to this scanline (if the */
11730             /* line segment starts on this scanline. x0 is the intersection of the */
11731             /* line with y_top, but that may be off the line segment. */
11732             if (e->sy > y_top) {
11733                 x_top = x0 + dx * (e->sy - y_top);
11734                 y0 = e->sy;
11735             } else {
11736                 x_top = x0;
11737                 y0 = y_top;
11738             }
11739 
11740             if (e->ey < y_bottom) {
11741                 x_bottom = x0 + dx * (e->ey - y_top);
11742                 y1 = e->ey;
11743             } else {
11744                 x_bottom = xb;
11745                 y1 = y_bottom;
11746             }
11747 
11748             if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
11749             {
11750                 /* from here on, we don't have to range check x values */
11751                 if ((int) x_top == (int) x_bottom) {
11752                     float height;
11753                     /* simple case, only spans one pixel */
11754                     int x = (int) x_top;
11755                     height = y1 - y0;
11756                     NK_ASSERT(x >= 0 && x < len);
11757                     scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f)  * (float)height;
11758                     scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
11759                 } else {
11760                     int x,x1,x2;
11761                     float y_crossing, step, sign, area;
11762                     /* covers 2+ pixels */
11763                     if (x_top > x_bottom)
11764                     {
11765                         /* flip scanline vertically; signed area is the same */
11766                         float t;
11767                         y0 = y_bottom - (y0 - y_top);
11768                         y1 = y_bottom - (y1 - y_top);
11769                         t = y0; y0 = y1; y1 = t;
11770                         t = x_bottom; x_bottom = x_top; x_top = t;
11771                         dx = -dx;
11772                         dy = -dy;
11773                         t = x0; x0 = xb; xb = t;
11774                     }
11775 
11776                     x1 = (int) x_top;
11777                     x2 = (int) x_bottom;
11778                     /* compute intersection with y axis at x1+1 */
11779                     y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
11780 
11781                     sign = e->direction;
11782                     /* area of the rectangle covered from y0..y_crossing */
11783                     area = sign * (y_crossing-y0);
11784                     /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
11785                     scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
11786 
11787                     step = sign * dy;
11788                     for (x = x1+1; x < x2; ++x) {
11789                         scanline[x] += area + step/2;
11790                         area += step;
11791                     }
11792                     y_crossing += (float)dy * (float)(x2 - (x1+1));
11793 
11794                     scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
11795                     scanline_fill[x2] += sign * (y1-y0);
11796                 }
11797             }
11798             else
11799             {
11800                 /* if edge goes outside of box we're drawing, we require */
11801                 /* clipping logic. since this does not match the intended use */
11802                 /* of this library, we use a different, very slow brute */
11803                 /* force implementation */
11804                 int x;
11805                 for (x=0; x < len; ++x)
11806                 {
11807                     /* cases: */
11808                     /* */
11809                     /* there can be up to two intersections with the pixel. any intersection */
11810                     /* with left or right edges can be handled by splitting into two (or three) */
11811                     /* regions. intersections with top & bottom do not necessitate case-wise logic. */
11812                     /* */
11813                     /* the old way of doing this found the intersections with the left & right edges, */
11814                     /* then used some simple logic to produce up to three segments in sorted order */
11815                     /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
11816                     /* across the x border, then the corresponding y position might not be distinct */
11817                     /* from the other y segment, and it might ignored as an empty segment. to avoid */
11818                     /* that, we need to explicitly produce segments based on x positions. */
11819 
11820                     /* rename variables to clear pairs */
11821                     float ya = y_top;
11822                     float x1 = (float) (x);
11823                     float x2 = (float) (x+1);
11824                     float x3 = xb;
11825                     float y3 = y_bottom;
11826                     float yb,y2;
11827 
11828                     yb = ((float)x - x0) / dx + y_top;
11829                     y2 = ((float)x+1 - x0) / dx + y_top;
11830 
11831                     if (x0 < x1 && x3 > x2) {         /* three segments descending down-right */
11832                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11833                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
11834                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11835                     } else if (x3 < x1 && x0 > x2) {  /* three segments descending 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, x1,yb);
11838                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11839                     } else if (x0 < x1 && x3 > x1) {  /* two segments across x, down-right */
11840                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11841                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11842                     } else if (x3 < x1 && x0 > x1) {  /* two segments across x, down-left */
11843                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
11844                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
11845                     } else if (x0 < x2 && x3 > x2) {  /* two segments across x+1, down-right */
11846                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11847                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11848                     } else if (x3 < x2 && x0 > x2) {  /* two segments across x+1, down-left */
11849                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
11850                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
11851                     } else {  /* one segment */
11852                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
11853                     }
11854                 }
11855             }
11856         }
11857         e = e->next;
11858     }
11859 }
11860 NK_INTERN void
11861 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
11862     int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
11863 {
11864     /* directly AA rasterize edges w/o supersampling */
11865     struct nk_tt__hheap hh;
11866     struct nk_tt__active_edge *active = 0;
11867     int y,j=0, i;
11868     float scanline_data[129], *scanline, *scanline2;
11869 
11870     NK_UNUSED(vsubsample);
11871     nk_zero_struct(hh);
11872     hh.alloc = *alloc;
11873 
11874     if (result->w > 64)
11875         scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
11876     else scanline = scanline_data;
11877 
11878     scanline2 = scanline + result->w;
11879     y = off_y;
11880     e[n].y0 = (float) (off_y + result->h) + 1;
11881 
11882     while (j < result->h)
11883     {
11884         /* find center of pixel for this scanline */
11885         float scan_y_top    = (float)y + 0.0f;
11886         float scan_y_bottom = (float)y + 1.0f;
11887         struct nk_tt__active_edge **step = &active;
11888 
11889         NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
11890         NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
11891 
11892         /* update all active edges; */
11893         /* remove all active edges that terminate before the top of this scanline */
11894         while (*step) {
11895             struct nk_tt__active_edge * z = *step;
11896             if (z->ey <= scan_y_top) {
11897                 *step = z->next; /* delete from list */
11898                 NK_ASSERT(z->direction);
11899                 z->direction = 0;
11900                 nk_tt__hheap_free(&hh, z);
11901             } else {
11902                 step = &((*step)->next); /* advance through list */
11903             }
11904         }
11905 
11906         /* insert all edges that start before the bottom of this scanline */
11907         while (e->y0 <= scan_y_bottom) {
11908             if (e->y0 != e->y1) {
11909                 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
11910                 if (z != 0) {
11911                     NK_ASSERT(z->ey >= scan_y_top);
11912                     /* insert at front */
11913                     z->next = active;
11914                     active = z;
11915                 }
11916             }
11917             ++e;
11918         }
11919 
11920         /* now process all active edges */
11921         if (active)
11922             nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
11923 
11924         {
11925             float sum = 0;
11926             for (i=0; i < result->w; ++i) {
11927                 float k;
11928                 int m;
11929                 sum += scanline2[i];
11930                 k = scanline[i] + sum;
11931                 k = (float) NK_ABS(k) * 255.0f + 0.5f;
11932                 m = (int) k;
11933                 if (m > 255) m = 255;
11934                 result->pixels[j*result->stride + i] = (unsigned char) m;
11935             }
11936         }
11937         /* advance all the edges */
11938         step = &active;
11939         while (*step) {
11940             struct nk_tt__active_edge *z = *step;
11941             z->fx += z->fdx; /* advance to position for current scanline */
11942             step = &((*step)->next); /* advance through list */
11943         }
11944         ++y;
11945         ++j;
11946     }
11947     nk_tt__hheap_cleanup(&hh);
11948     if (scanline != scanline_data)
11949         alloc->free(alloc->userdata, scanline);
11950 }
11951 NK_INTERN void
11952 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
11953 {
11954     int i,j;
11955     #define NK_TT__COMPARE(a,b)  ((a)->y0 < (b)->y0)
11956     for (i=1; i < n; ++i) {
11957         struct nk_tt__edge t = p[i], *a = &t;
11958         j = i;
11959         while (j > 0) {
11960             struct nk_tt__edge *b = &p[j-1];
11961             int c = NK_TT__COMPARE(a,b);
11962             if (!c) break;
11963             p[j] = p[j-1];
11964             --j;
11965         }
11966         if (i != j)
11967             p[j] = t;
11968     }
11969 }
11970 NK_INTERN void
11971 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
11972 {
11973     /* threshold for transitioning to insertion sort */
11974     while (n > 12) {
11975         struct nk_tt__edge t;
11976         int c01,c12,c,m,i,j;
11977 
11978         /* compute median of three */
11979         m = n >> 1;
11980         c01 = NK_TT__COMPARE(&p[0],&p[m]);
11981         c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
11982 
11983         /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
11984         if (c01 != c12) {
11985             /* otherwise, we'll need to swap something else to middle */
11986             int z;
11987             c = NK_TT__COMPARE(&p[0],&p[n-1]);
11988             /* 0>mid && mid<n:  0>n => n; 0<n => 0 */
11989             /* 0<mid && mid>n:  0>n => 0; 0<n => n */
11990             z = (c == c12) ? 0 : n-1;
11991             t = p[z];
11992             p[z] = p[m];
11993             p[m] = t;
11994         }
11995 
11996         /* now p[m] is the median-of-three */
11997         /* swap it to the beginning so it won't move around */
11998         t = p[0];
11999         p[0] = p[m];
12000         p[m] = t;
12001 
12002         /* partition loop */
12003         i=1;
12004         j=n-1;
12005         for(;;) {
12006             /* handling of equality is crucial here */
12007             /* for sentinels & efficiency with duplicates */
12008             for (;;++i) {
12009                 if (!NK_TT__COMPARE(&p[i], &p[0])) break;
12010             }
12011             for (;;--j) {
12012                 if (!NK_TT__COMPARE(&p[0], &p[j])) break;
12013             }
12014 
12015             /* make sure we haven't crossed */
12016              if (i >= j) break;
12017              t = p[i];
12018              p[i] = p[j];
12019              p[j] = t;
12020 
12021             ++i;
12022             --j;
12023 
12024         }
12025 
12026         /* recurse on smaller side, iterate on larger */
12027         if (j < (n-i)) {
12028             nk_tt__sort_edges_quicksort(p,j);
12029             p = p+i;
12030             n = n-i;
12031         } else {
12032             nk_tt__sort_edges_quicksort(p+i, n-i);
12033             n = j;
12034         }
12035     }
12036 }
12037 NK_INTERN void
12038 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
12039 {
12040    nk_tt__sort_edges_quicksort(p, n);
12041    nk_tt__sort_edges_ins_sort(p, n);
12042 }
12043 NK_INTERN void
12044 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
12045     int *wcount, int windings, float scale_x, float scale_y,
12046     float shift_x, float shift_y, int off_x, int off_y, int invert,
12047     struct nk_allocator *alloc)
12048 {
12049     float y_scale_inv = invert ? -scale_y : scale_y;
12050     struct nk_tt__edge *e;
12051     int n,i,j,k,m;
12052     int vsubsample = 1;
12053     /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
12054 
12055     /* now we have to blow out the windings into explicit edge lists */
12056     n = 0;
12057     for (i=0; i < windings; ++i)
12058         n += wcount[i];
12059 
12060     e = (struct nk_tt__edge*)
12061        alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
12062     if (e == 0) return;
12063     n = 0;
12064 
12065     m=0;
12066     for (i=0; i < windings; ++i)
12067     {
12068         struct nk_tt__point *p = pts + m;
12069         m += wcount[i];
12070         j = wcount[i]-1;
12071         for (k=0; k < wcount[i]; j=k++) {
12072             int a=k,b=j;
12073             /* skip the edge if horizontal */
12074             if (p[j].y == p[k].y)
12075                 continue;
12076 
12077             /* add edge from j to k to the list */
12078             e[n].invert = 0;
12079             if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
12080                 e[n].invert = 1;
12081                 a=j,b=k;
12082             }
12083             e[n].x0 = p[a].x * scale_x + shift_x;
12084             e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
12085             e[n].x1 = p[b].x * scale_x + shift_x;
12086             e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
12087             ++n;
12088         }
12089     }
12090 
12091     /* now sort the edges by their highest point (should snap to integer, and then by x) */
12092     /*STBTT_sort(e, n, sizeof(e[0]), nk_tt__edge_compare); */
12093     nk_tt__sort_edges(e, n);
12094     /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
12095     nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
12096     alloc->free(alloc->userdata, e);
12097 }
12098 NK_INTERN void
12099 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
12100 {
12101     if (!points) return; /* during first pass, it's unallocated */
12102     points[n].x = x;
12103     points[n].y = y;
12104 }
12105 NK_INTERN int
12106 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
12107     float x0, float y0, float x1, float y1, float x2, float y2,
12108     float objspace_flatness_squared, int n)
12109 {
12110     /* tesselate until threshold p is happy...
12111      * @TODO warped to compensate for non-linear stretching */
12112     /* midpoint */
12113     float mx = (x0 + 2*x1 + x2)/4;
12114     float my = (y0 + 2*y1 + y2)/4;
12115     /* versus directly drawn line */
12116     float dx = (x0+x2)/2 - mx;
12117     float dy = (y0+y2)/2 - my;
12118     if (n > 16) /* 65536 segments on one curve better be enough! */
12119         return 1;
12120 
12121     /* half-pixel error allowed... need to be smaller if AA */
12122     if (dx*dx+dy*dy > objspace_flatness_squared) {
12123         nk_tt__tesselate_curve(points, num_points, x0,y0,
12124             (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
12125         nk_tt__tesselate_curve(points, num_points, mx,my,
12126             (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
12127     } else {
12128         nk_tt__add_point(points, *num_points,x2,y2);
12129         *num_points = *num_points+1;
12130     }
12131     return 1;
12132 }
12133 NK_INTERN struct nk_tt__point*
12134 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
12135     float objspace_flatness, int **contour_lengths, int *num_contours,
12136     struct nk_allocator *alloc)
12137 {
12138     /* returns number of contours */
12139     struct nk_tt__point *points=0;
12140     int num_points=0;
12141     float objspace_flatness_squared = objspace_flatness * objspace_flatness;
12142     int i;
12143     int n=0;
12144     int start=0;
12145     int pass;
12146 
12147     /* count how many "moves" there are to get the contour count */
12148     for (i=0; i < num_verts; ++i)
12149         if (vertices[i].type == NK_TT_vmove) ++n;
12150 
12151     *num_contours = n;
12152     if (n == 0) return 0;
12153 
12154     *contour_lengths = (int *)
12155         alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
12156     if (*contour_lengths == 0) {
12157         *num_contours = 0;
12158         return 0;
12159     }
12160 
12161     /* make two passes through the points so we don't need to realloc */
12162     for (pass=0; pass < 2; ++pass)
12163     {
12164         float x=0,y=0;
12165         if (pass == 1) {
12166             points = (struct nk_tt__point *)
12167                 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
12168             if (points == 0) goto error;
12169         }
12170         num_points = 0;
12171         n= -1;
12172 
12173         for (i=0; i < num_verts; ++i)
12174         {
12175             switch (vertices[i].type) {
12176             case NK_TT_vmove:
12177                 /* start the next contour */
12178                 if (n >= 0)
12179                 (*contour_lengths)[n] = num_points - start;
12180                 ++n;
12181                 start = num_points;
12182 
12183                 x = vertices[i].x, y = vertices[i].y;
12184                 nk_tt__add_point(points, num_points++, x,y);
12185                 break;
12186             case NK_TT_vline:
12187                x = vertices[i].x, y = vertices[i].y;
12188                nk_tt__add_point(points, num_points++, x, y);
12189                break;
12190             case NK_TT_vcurve:
12191                nk_tt__tesselate_curve(points, &num_points, x,y,
12192                                         vertices[i].cx, vertices[i].cy,
12193                                         vertices[i].x,  vertices[i].y,
12194                                         objspace_flatness_squared, 0);
12195                x = vertices[i].x, y = vertices[i].y;
12196                break;
12197             default: break;
12198          }
12199       }
12200       (*contour_lengths)[n] = num_points - start;
12201    }
12202    return points;
12203 
12204 error:
12205    alloc->free(alloc->userdata, points);
12206    alloc->free(alloc->userdata, *contour_lengths);
12207    *contour_lengths = 0;
12208    *num_contours = 0;
12209    return 0;
12210 }
12211 NK_INTERN void
12212 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
12213     struct nk_tt_vertex *vertices, int num_verts,
12214     float scale_x, float scale_y, float shift_x, float shift_y,
12215     int x_off, int y_off, int invert, struct nk_allocator *alloc)
12216 {
12217     float scale = scale_x > scale_y ? scale_y : scale_x;
12218     int winding_count, *winding_lengths;
12219     struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
12220         flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
12221 
12222     NK_ASSERT(alloc);
12223     if (windings) {
12224         nk_tt__rasterize(result, windings, winding_lengths, winding_count,
12225             scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
12226         alloc->free(alloc->userdata, winding_lengths);
12227         alloc->free(alloc->userdata, windings);
12228     }
12229 }
12230 NK_INTERN void
12231 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
12232     int out_w, int out_h, int out_stride, float scale_x, float scale_y,
12233     float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
12234 {
12235     int ix0,iy0;
12236     struct nk_tt_vertex *vertices;
12237     int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
12238     struct nk_tt__bitmap gbm;
12239 
12240     nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
12241         shift_y, &ix0,&iy0,0,0);
12242     gbm.pixels = output;
12243     gbm.w = out_w;
12244     gbm.h = out_h;
12245     gbm.stride = out_stride;
12246 
12247     if (gbm.w && gbm.h)
12248         nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
12249             shift_x, shift_y, ix0,iy0, 1, alloc);
12250     alloc->free(alloc->userdata, vertices);
12251 }
12252 
12253 /*-------------------------------------------------------------
12254  *                          Bitmap baking
12255  * --------------------------------------------------------------*/
12256 NK_INTERN int
12257 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
12258     int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
12259 {
12260     int num_nodes = pw - padding;
12261     struct nk_rp_context *context = (struct nk_rp_context *)
12262         alloc->alloc(alloc->userdata,0, sizeof(*context));
12263     struct nk_rp_node *nodes = (struct nk_rp_node*)
12264         alloc->alloc(alloc->userdata,0, (sizeof(*nodes  ) * (nk_size)num_nodes));
12265 
12266     if (context == 0 || nodes == 0) {
12267         if (context != 0) alloc->free(alloc->userdata, context);
12268         if (nodes   != 0) alloc->free(alloc->userdata, nodes);
12269         return 0;
12270     }
12271 
12272     spc->width = pw;
12273     spc->height = ph;
12274     spc->pixels = pixels;
12275     spc->pack_info = context;
12276     spc->nodes = nodes;
12277     spc->padding = padding;
12278     spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
12279     spc->h_oversample = 1;
12280     spc->v_oversample = 1;
12281 
12282     nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
12283     if (pixels)
12284         NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
12285     return 1;
12286 }
12287 NK_INTERN void
12288 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
12289 {
12290     alloc->free(alloc->userdata, spc->nodes);
12291     alloc->free(alloc->userdata, spc->pack_info);
12292 }
12293 NK_INTERN void
12294 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
12295     unsigned int h_oversample, unsigned int v_oversample)
12296 {
12297    NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
12298    NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
12299    if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
12300       spc->h_oversample = h_oversample;
12301    if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
12302       spc->v_oversample = v_oversample;
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 NK_INTERN void
12368 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
12369     int kernel_width)
12370 {
12371     unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
12372     int safe_h = h - kernel_width;
12373     int j;
12374 
12375     for (j=0; j < w; ++j)
12376     {
12377         int i;
12378         unsigned int total;
12379         NK_MEMSET(buffer, 0, (nk_size)kernel_width);
12380 
12381         total = 0;
12382 
12383         /* make kernel_width a constant in common cases so compiler can optimize out the divide */
12384         switch (kernel_width) {
12385         case 2:
12386             for (i=0; i <= safe_h; ++i) {
12387                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12388                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12389                 pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
12390             }
12391             break;
12392          case 3:
12393             for (i=0; i <= safe_h; ++i) {
12394                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12395                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12396                 pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
12397             }
12398             break;
12399          case 4:
12400             for (i=0; i <= safe_h; ++i) {
12401                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12402                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12403                 pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
12404             }
12405             break;
12406          case 5:
12407             for (i=0; i <= safe_h; ++i) {
12408                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12409                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12410                 pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
12411             }
12412             break;
12413          default:
12414             for (i=0; i <= safe_h; ++i) {
12415                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
12416                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
12417                 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
12418             }
12419             break;
12420         }
12421 
12422         for (; i < h; ++i) {
12423             NK_ASSERT(pixels[i*stride_in_bytes] == 0);
12424             total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
12425             pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
12426         }
12427         pixels += 1;
12428     }
12429 }
12430 NK_INTERN float
12431 nk_tt__oversample_shift(int oversample)
12432 {
12433     if (!oversample)
12434         return 0.0f;
12435 
12436     /* The prefilter is a box filter of width "oversample", */
12437     /* which shifts phase by (oversample - 1)/2 pixels in */
12438     /* oversampled space. We want to shift in the opposite */
12439     /* direction to counter this. */
12440     return (float)-(oversample - 1) / (2.0f * (float)oversample);
12441 }
12442 NK_INTERN int
12443 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
12444     struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
12445     int num_ranges, struct nk_rp_rect *rects)
12446 {
12447     /* rects array must be big enough to accommodate all characters in the given ranges */
12448     int i,j,k;
12449     k = 0;
12450 
12451     for (i=0; i < num_ranges; ++i) {
12452         float fh = ranges[i].font_size;
12453         float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
12454             nk_tt_ScaleForMappingEmToPixels(info, -fh);
12455         ranges[i].h_oversample = (unsigned char) spc->h_oversample;
12456         ranges[i].v_oversample = (unsigned char) spc->v_oversample;
12457         for (j=0; j < ranges[i].num_chars; ++j) {
12458             int x0,y0,x1,y1;
12459             int codepoint = ranges[i].first_unicode_codepoint_in_range ?
12460                 ranges[i].first_unicode_codepoint_in_range + j :
12461                 ranges[i].array_of_unicode_codepoints[j];
12462 
12463             int glyph = nk_tt_FindGlyphIndex(info, codepoint);
12464             nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
12465                 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
12466             rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
12467             rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
12468             ++k;
12469         }
12470     }
12471     return k;
12472 }
12473 NK_INTERN int
12474 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
12475     struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
12476     int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
12477 {
12478     int i,j,k, return_value = 1;
12479     /* save current values */
12480     int old_h_over = (int)spc->h_oversample;
12481     int old_v_over = (int)spc->v_oversample;
12482     /* rects array must be big enough to accommodate all characters in the given ranges */
12483 
12484     k = 0;
12485     for (i=0; i < num_ranges; ++i)
12486     {
12487         float fh = ranges[i].font_size;
12488         float recip_h,recip_v,sub_x,sub_y;
12489         float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
12490             nk_tt_ScaleForMappingEmToPixels(info, -fh);
12491 
12492         spc->h_oversample = ranges[i].h_oversample;
12493         spc->v_oversample = ranges[i].v_oversample;
12494 
12495         recip_h = 1.0f / (float)spc->h_oversample;
12496         recip_v = 1.0f / (float)spc->v_oversample;
12497 
12498         sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
12499         sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
12500 
12501         for (j=0; j < ranges[i].num_chars; ++j)
12502         {
12503             struct nk_rp_rect *r = &rects[k];
12504             if (r->was_packed)
12505             {
12506                 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
12507                 int advance, lsb, x0,y0,x1,y1;
12508                 int codepoint = ranges[i].first_unicode_codepoint_in_range ?
12509                     ranges[i].first_unicode_codepoint_in_range + j :
12510                     ranges[i].array_of_unicode_codepoints[j];
12511                 int glyph = nk_tt_FindGlyphIndex(info, codepoint);
12512                 nk_rp_coord pad = (nk_rp_coord) spc->padding;
12513 
12514                 /* pad on left and top */
12515                 r->x = (nk_rp_coord)((int)r->x + (int)pad);
12516                 r->y = (nk_rp_coord)((int)r->y + (int)pad);
12517                 r->w = (nk_rp_coord)((int)r->w - (int)pad);
12518                 r->h = (nk_rp_coord)((int)r->h - (int)pad);
12519 
12520                 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
12521                 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
12522                         (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
12523                 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
12524                     (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
12525                     spc->stride_in_bytes, scale * (float)spc->h_oversample,
12526                     scale * (float)spc->v_oversample, 0,0, glyph, alloc);
12527 
12528                 if (spc->h_oversample > 1)
12529                    nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
12530                         r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
12531 
12532                 if (spc->v_oversample > 1)
12533                    nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
12534                         r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
12535 
12536                 bc->x0       = (nk_ushort)  r->x;
12537                 bc->y0       = (nk_ushort)  r->y;
12538                 bc->x1       = (nk_ushort) (r->x + r->w);
12539                 bc->y1       = (nk_ushort) (r->y + r->h);
12540                 bc->xadvance = scale * (float)advance;
12541                 bc->xoff     = (float)  x0 * recip_h + sub_x;
12542                 bc->yoff     = (float)  y0 * recip_v + sub_y;
12543                 bc->xoff2    = ((float)x0 + r->w) * recip_h + sub_x;
12544                 bc->yoff2    = ((float)y0 + r->h) * recip_v + sub_y;
12545             } else {
12546                 return_value = 0; /* if any fail, report failure */
12547             }
12548             ++k;
12549         }
12550     }
12551     /* restore original values */
12552     spc->h_oversample = (unsigned int)old_h_over;
12553     spc->v_oversample = (unsigned int)old_v_over;
12554     return return_value;
12555 }
12556 NK_INTERN void
12557 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
12558     int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
12559     int align_to_integer)
12560 {
12561     float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
12562     struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
12563     if (align_to_integer) {
12564         int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
12565         int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
12566 
12567         float x = (float)tx;
12568         float y = (float)ty;
12569 
12570         q->x0 = x;
12571         q->y0 = y;
12572         q->x1 = x + b->xoff2 - b->xoff;
12573         q->y1 = y + b->yoff2 - b->yoff;
12574     } else {
12575         q->x0 = *xpos + b->xoff;
12576         q->y0 = *ypos + b->yoff;
12577         q->x1 = *xpos + b->xoff2;
12578         q->y1 = *ypos + b->yoff2;
12579     }
12580     q->s0 = b->x0 * ipw;
12581     q->t0 = b->y0 * iph;
12582     q->s1 = b->x1 * ipw;
12583     q->t1 = b->y1 * iph;
12584     *xpos += b->xadvance;
12585 }
12586 
12587 /* -------------------------------------------------------------
12588  *
12589  *                          FONT BAKING
12590  *
12591  * --------------------------------------------------------------*/
12592 struct nk_font_bake_data {
12593     struct nk_tt_fontinfo info;
12594     struct nk_rp_rect *rects;
12595     struct nk_tt_pack_range *ranges;
12596     nk_rune range_count;
12597 };
12598 
12599 struct nk_font_baker {
12600     struct nk_allocator alloc;
12601     struct nk_tt_pack_context spc;
12602     struct nk_font_bake_data *build;
12603     struct nk_tt_packedchar *packed_chars;
12604     struct nk_rp_rect *rects;
12605     struct nk_tt_pack_range *ranges;
12606 };
12607 
12608 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
12609 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
12610 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
12611 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
12612 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
12613 
12614 NK_INTERN int
12615 nk_range_count(const nk_rune *range)
12616 {
12617     const nk_rune *iter = range;
12618     NK_ASSERT(range);
12619     if (!range) return 0;
12620     while (*(iter++) != 0);
12621     return (iter == range) ? 0 : (int)((iter - range)/2);
12622 }
12623 NK_INTERN int
12624 nk_range_glyph_count(const nk_rune *range, int count)
12625 {
12626     int i = 0;
12627     int total_glyphs = 0;
12628     for (i = 0; i < count; ++i) {
12629         int diff;
12630         nk_rune f = range[(i*2)+0];
12631         nk_rune t = range[(i*2)+1];
12632         NK_ASSERT(t >= f);
12633         diff = (int)((t - f) + 1);
12634         total_glyphs += diff;
12635     }
12636     return total_glyphs;
12637 }
12638 NK_API const nk_rune*
12639 nk_font_default_glyph_ranges(void)
12640 {
12641     NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
12642     return ranges;
12643 }
12644 NK_API const nk_rune*
12645 nk_font_chinese_glyph_ranges(void)
12646 {
12647     NK_STORAGE const nk_rune ranges[] = {
12648         0x0020, 0x00FF,
12649         0x3000, 0x30FF,
12650         0x31F0, 0x31FF,
12651         0xFF00, 0xFFEF,
12652         0x4e00, 0x9FAF,
12653         0
12654     };
12655     return ranges;
12656 }
12657 NK_API const nk_rune*
12658 nk_font_cyrillic_glyph_ranges(void)
12659 {
12660     NK_STORAGE const nk_rune ranges[] = {
12661         0x0020, 0x00FF,
12662         0x0400, 0x052F,
12663         0x2DE0, 0x2DFF,
12664         0xA640, 0xA69F,
12665         0
12666     };
12667     return ranges;
12668 }
12669 NK_API const nk_rune*
12670 nk_font_korean_glyph_ranges(void)
12671 {
12672     NK_STORAGE const nk_rune ranges[] = {
12673         0x0020, 0x00FF,
12674         0x3131, 0x3163,
12675         0xAC00, 0xD79D,
12676         0
12677     };
12678     return ranges;
12679 }
12680 NK_INTERN void
12681 nk_font_baker_memory(nk_size *temp, int *glyph_count,
12682     struct nk_font_config *config_list, int count)
12683 {
12684     int range_count = 0;
12685     int total_range_count = 0;
12686     struct nk_font_config *iter, *i;
12687 
12688     NK_ASSERT(config_list);
12689     NK_ASSERT(glyph_count);
12690     if (!config_list) {
12691         *temp = 0;
12692         *glyph_count = 0;
12693         return;
12694     }
12695     *glyph_count = 0;
12696     for (iter = config_list; iter; iter = iter->next) {
12697         i = iter;
12698         do {if (!i->range) iter->range = nk_font_default_glyph_ranges();
12699             range_count = nk_range_count(i->range);
12700             total_range_count += range_count;
12701             *glyph_count += nk_range_glyph_count(i->range, range_count);
12702         } while ((i = i->n) != iter);
12703     }
12704     *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
12705     *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
12706     *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
12707     *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
12708     *temp += sizeof(struct nk_font_baker);
12709     *temp += nk_rect_align + nk_range_align + nk_char_align;
12710     *temp += nk_build_align + nk_baker_align;
12711 }
12712 NK_INTERN struct nk_font_baker*
12713 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
12714 {
12715     struct nk_font_baker *baker;
12716     if (!memory) return 0;
12717     /* setup baker inside a memory block  */
12718     baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
12719     baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
12720     baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
12721     baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
12722     baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
12723     baker->alloc = *alloc;
12724     return baker;
12725 }
12726 NK_INTERN int
12727 nk_font_bake_pack(struct nk_font_baker *baker,
12728     nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
12729     const struct nk_font_config *config_list, int count,
12730     struct nk_allocator *alloc)
12731 {
12732     NK_STORAGE const nk_size max_height = 1024 * 32;
12733     const struct nk_font_config *config_iter, *it;
12734     int total_glyph_count = 0;
12735     int total_range_count = 0;
12736     int range_count = 0;
12737     int i = 0;
12738 
12739     NK_ASSERT(image_memory);
12740     NK_ASSERT(width);
12741     NK_ASSERT(height);
12742     NK_ASSERT(config_list);
12743     NK_ASSERT(count);
12744     NK_ASSERT(alloc);
12745 
12746     if (!image_memory || !width || !height || !config_list || !count) return nk_false;
12747     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
12748         it = config_iter;
12749         do {range_count = nk_range_count(it->range);
12750             total_range_count += range_count;
12751             total_glyph_count += nk_range_glyph_count(it->range, range_count);
12752         } while ((it = it->n) != config_iter);
12753     }
12754     /* setup font baker from temporary memory */
12755     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
12756         it = config_iter;
12757         do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0))
12758             return nk_false;
12759         } while ((it = it->n) != config_iter);
12760     }
12761     *height = 0;
12762     *width = (total_glyph_count > 1000) ? 1024 : 512;
12763     nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
12764     {
12765         int input_i = 0;
12766         int range_n = 0;
12767         int rect_n = 0;
12768         int char_n = 0;
12769 
12770         if (custom) {
12771             /* pack custom user data first so it will be in the upper left corner*/
12772             struct nk_rp_rect custom_space;
12773             nk_zero(&custom_space, sizeof(custom_space));
12774             custom_space.w = (nk_rp_coord)(custom->w);
12775             custom_space.h = (nk_rp_coord)(custom->h);
12776 
12777             nk_tt_PackSetOversampling(&baker->spc, 1, 1);
12778             nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
12779             *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
12780 
12781             custom->x = (short)custom_space.x;
12782             custom->y = (short)custom_space.y;
12783             custom->w = (short)custom_space.w;
12784             custom->h = (short)custom_space.h;
12785         }
12786 
12787         /* first font pass: pack all glyphs */
12788         for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
12789             config_iter = config_iter->next) {
12790             it = config_iter;
12791             do {int n = 0;
12792                 int glyph_count;
12793                 const nk_rune *in_range;
12794                 const struct nk_font_config *cfg = it;
12795                 struct nk_font_bake_data *tmp = &baker->build[input_i++];
12796 
12797                 /* count glyphs + ranges in current font */
12798                 glyph_count = 0; range_count = 0;
12799                 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
12800                     glyph_count += (int)(in_range[1] - in_range[0]) + 1;
12801                     range_count++;
12802                 }
12803 
12804                 /* setup ranges  */
12805                 tmp->ranges = baker->ranges + range_n;
12806                 tmp->range_count = (nk_rune)range_count;
12807                 range_n += range_count;
12808                 for (i = 0; i < range_count; ++i) {
12809                     in_range = &cfg->range[i * 2];
12810                     tmp->ranges[i].font_size = cfg->size;
12811                     tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
12812                     tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
12813                     tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
12814                     char_n += tmp->ranges[i].num_chars;
12815                 }
12816 
12817                 /* pack */
12818                 tmp->rects = baker->rects + rect_n;
12819                 rect_n += glyph_count;
12820                 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
12821                 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
12822                     tmp->ranges, (int)tmp->range_count, tmp->rects);
12823                 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
12824 
12825                 /* texture height */
12826                 for (i = 0; i < n; ++i) {
12827                     if (tmp->rects[i].was_packed)
12828                         *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
12829                 }
12830             } while ((it = it->n) != config_iter);
12831         }
12832         NK_ASSERT(rect_n == total_glyph_count);
12833         NK_ASSERT(char_n == total_glyph_count);
12834         NK_ASSERT(range_n == total_range_count);
12835     }
12836     *height = (int)nk_round_up_pow2((nk_uint)*height);
12837     *image_memory = (nk_size)(*width) * (nk_size)(*height);
12838     return nk_true;
12839 }
12840 NK_INTERN void
12841 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
12842     struct nk_font_glyph *glyphs, int glyphs_count,
12843     const struct nk_font_config *config_list, int font_count)
12844 {
12845     int input_i = 0;
12846     nk_rune glyph_n = 0;
12847     const struct nk_font_config *config_iter;
12848     const struct nk_font_config *it;
12849 
12850     NK_ASSERT(image_memory);
12851     NK_ASSERT(width);
12852     NK_ASSERT(height);
12853     NK_ASSERT(config_list);
12854     NK_ASSERT(baker);
12855     NK_ASSERT(font_count);
12856     NK_ASSERT(glyphs_count);
12857     if (!image_memory || !width || !height || !config_list ||
12858         !font_count || !glyphs || !glyphs_count)
12859         return;
12860 
12861     /* second font pass: render glyphs */
12862     nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
12863     baker->spc.pixels = (unsigned char*)image_memory;
12864     baker->spc.height = (int)height;
12865     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
12866         config_iter = config_iter->next) {
12867         it = config_iter;
12868         do {const struct nk_font_config *cfg = it;
12869             struct nk_font_bake_data *tmp = &baker->build[input_i++];
12870             nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
12871             nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
12872                 (int)tmp->range_count, tmp->rects, &baker->alloc);
12873         } while ((it = it->n) != config_iter);
12874     } nk_tt_PackEnd(&baker->spc, &baker->alloc);
12875 
12876     /* third pass: setup font and glyphs */
12877     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
12878         config_iter = config_iter->next) {
12879         it = config_iter;
12880         do {nk_size i = 0;
12881             int char_idx = 0;
12882             nk_rune glyph_count = 0;
12883             const struct nk_font_config *cfg = it;
12884             struct nk_font_bake_data *tmp = &baker->build[input_i++];
12885             struct nk_baked_font *dst_font = cfg->font;
12886 
12887             float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
12888             int unscaled_ascent, unscaled_descent, unscaled_line_gap;
12889             nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
12890                                     &unscaled_line_gap);
12891 
12892             /* fill baked font */
12893             if (!cfg->merge_mode) {
12894                 dst_font->ranges = cfg->range;
12895                 dst_font->height = cfg->size;
12896                 dst_font->ascent = ((float)unscaled_ascent * font_scale);
12897                 dst_font->descent = ((float)unscaled_descent * font_scale);
12898                 dst_font->glyph_offset = glyph_n;
12899                 // Need to zero this, or it will carry over from a previous
12900                 // bake, and cause a segfault when accessing glyphs[].
12901                 dst_font->glyph_count = 0;
12902             }
12903 
12904             /* fill own baked font glyph array */
12905             for (i = 0; i < tmp->range_count; ++i) {
12906                 struct nk_tt_pack_range *range = &tmp->ranges[i];
12907                 for (char_idx = 0; char_idx < range->num_chars; char_idx++)
12908                 {
12909                     nk_rune codepoint = 0;
12910                     float dummy_x = 0, dummy_y = 0;
12911                     struct nk_tt_aligned_quad q;
12912                     struct nk_font_glyph *glyph;
12913 
12914                     /* query glyph bounds from stb_truetype */
12915                     const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
12916                     if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
12917                     codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
12918                     nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
12919                         (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
12920 
12921                     /* fill own glyph type with data */
12922                     glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count];
12923                     glyph->codepoint = codepoint;
12924                     glyph->x0 = q.x0; glyph->y0 = q.y0;
12925                     glyph->x1 = q.x1; glyph->y1 = q.y1;
12926                     glyph->y0 += (dst_font->ascent + 0.5f);
12927                     glyph->y1 += (dst_font->ascent + 0.5f);
12928                     glyph->w = glyph->x1 - glyph->x0 + 0.5f;
12929                     glyph->h = glyph->y1 - glyph->y0;
12930 
12931                     if (cfg->coord_type == NK_COORD_PIXEL) {
12932                         glyph->u0 = q.s0 * (float)width;
12933                         glyph->v0 = q.t0 * (float)height;
12934                         glyph->u1 = q.s1 * (float)width;
12935                         glyph->v1 = q.t1 * (float)height;
12936                     } else {
12937                         glyph->u0 = q.s0;
12938                         glyph->v0 = q.t0;
12939                         glyph->u1 = q.s1;
12940                         glyph->v1 = q.t1;
12941                     }
12942                     glyph->xadvance = (pc->xadvance + cfg->spacing.x);
12943                     if (cfg->pixel_snap)
12944                         glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
12945                     glyph_count++;
12946                 }
12947             }
12948             dst_font->glyph_count += glyph_count;
12949             glyph_n += glyph_count;
12950         } while ((it = it->n) != config_iter);
12951     }
12952 }
12953 NK_INTERN void
12954 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
12955     struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
12956     int tex_height, char white, char black)
12957 {
12958     nk_byte *pixels;
12959     int y = 0;
12960     int x = 0;
12961     int n = 0;
12962 
12963     NK_ASSERT(img_memory);
12964     NK_ASSERT(img_width);
12965     NK_ASSERT(img_height);
12966     NK_ASSERT(texture_data_mask);
12967     NK_UNUSED(tex_height);
12968     if (!img_memory || !img_width || !img_height || !texture_data_mask)
12969         return;
12970 
12971     pixels = (nk_byte*)img_memory;
12972     for (y = 0, n = 0; y < tex_height; ++y) {
12973         for (x = 0; x < tex_width; ++x, ++n) {
12974             const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
12975             const int off1 = off0 + 1 + tex_width;
12976             pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
12977             pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
12978         }
12979     }
12980 }
12981 NK_INTERN void
12982 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
12983     const void *in_memory)
12984 {
12985     int n = 0;
12986     nk_rune *dst;
12987     const nk_byte *src;
12988 
12989     NK_ASSERT(out_memory);
12990     NK_ASSERT(in_memory);
12991     NK_ASSERT(img_width);
12992     NK_ASSERT(img_height);
12993     if (!out_memory || !in_memory || !img_height || !img_width) return;
12994 
12995     dst = (nk_rune*)out_memory;
12996     src = (const nk_byte*)in_memory;
12997     for (n = (int)(img_width * img_height); n > 0; n--)
12998         *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
12999 }
13000 
13001 /* -------------------------------------------------------------
13002  *
13003  *                          FONT
13004  *
13005  * --------------------------------------------------------------*/
13006 NK_INTERN float
13007 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
13008 {
13009     nk_rune unicode;
13010     int text_len  = 0;
13011     float text_width = 0;
13012     int glyph_len = 0;
13013     float scale = 0;
13014 
13015     struct nk_font *font = (struct nk_font*)handle.ptr;
13016     NK_ASSERT(font);
13017     NK_ASSERT(font->glyphs);
13018     if (!font || !text || !len)
13019         return 0;
13020 
13021     scale = height/font->info.height;
13022     glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
13023     if (!glyph_len) return 0;
13024     while (text_len <= (int)len && glyph_len) {
13025         const struct nk_font_glyph *g;
13026         if (unicode == NK_UTF_INVALID) break;
13027 
13028         /* query currently drawn glyph information */
13029         g = nk_font_find_glyph(font, unicode);
13030         text_width += g->xadvance * scale;
13031 
13032         /* offset next glyph */
13033         glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
13034         text_len += glyph_len;
13035     }
13036     return text_width;
13037 }
13038 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13039 NK_INTERN void
13040 nk_font_query_font_glyph(nk_handle handle, float height,
13041     struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
13042 {
13043     float scale;
13044     const struct nk_font_glyph *g;
13045     struct nk_font *font;
13046 
13047     NK_ASSERT(glyph);
13048     NK_UNUSED(next_codepoint);
13049 
13050     font = (struct nk_font*)handle.ptr;
13051     NK_ASSERT(font);
13052     NK_ASSERT(font->glyphs);
13053     if (!font || !glyph)
13054         return;
13055 
13056     scale = height/font->info.height;
13057     g = nk_font_find_glyph(font, codepoint);
13058     glyph->width = (g->x1 - g->x0) * scale;
13059     glyph->height = (g->y1 - g->y0) * scale;
13060     glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
13061     glyph->xadvance = (g->xadvance * scale);
13062     glyph->uv[0] = nk_vec2(g->u0, g->v0);
13063     glyph->uv[1] = nk_vec2(g->u1, g->v1);
13064 }
13065 #endif
13066 NK_API const struct nk_font_glyph*
13067 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
13068 {
13069     int i = 0;
13070     int count;
13071     int total_glyphs = 0;
13072     const struct nk_font_glyph *glyph = 0;
13073     const struct nk_font_config *iter = 0;
13074 
13075     NK_ASSERT(font);
13076     NK_ASSERT(font->glyphs);
13077     NK_ASSERT(font->info.ranges);
13078     if (!font || !font->glyphs) return 0;
13079 
13080     glyph = font->fallback;
13081     iter = font->config;
13082     do {count = nk_range_count(iter->range);
13083         for (i = 0; i < count; ++i) {
13084             nk_rune f = iter->range[(i*2)+0];
13085             nk_rune t = iter->range[(i*2)+1];
13086             int diff = (int)((t - f) + 1);
13087             if (unicode >= f && unicode <= t)
13088                 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
13089             total_glyphs += diff;
13090         }
13091     } while ((iter = iter->n) != font->config);
13092     return glyph;
13093 }
13094 NK_INTERN void
13095 nk_font_init(struct nk_font *font, float pixel_height,
13096     nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
13097     const struct nk_baked_font *baked_font, nk_handle atlas)
13098 {
13099     struct nk_baked_font baked;
13100     NK_ASSERT(font);
13101     NK_ASSERT(glyphs);
13102     NK_ASSERT(baked_font);
13103     if (!font || !glyphs || !baked_font)
13104         return;
13105 
13106     baked = *baked_font;
13107     font->fallback = 0;
13108     font->info = baked;
13109     font->scale = (float)pixel_height / (float)font->info.height;
13110     font->glyphs = &glyphs[baked_font->glyph_offset];
13111     font->texture = atlas;
13112     font->fallback_codepoint = fallback_codepoint;
13113     font->fallback = nk_font_find_glyph(font, fallback_codepoint);
13114 
13115     font->handle.height = font->info.height * font->scale;
13116     font->handle.width = nk_font_text_width;
13117     font->handle.userdata.ptr = font;
13118 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13119     font->handle.query = nk_font_query_font_glyph;
13120     font->handle.texture = font->texture;
13121 #endif
13122 }
13123 
13124 /* ---------------------------------------------------------------------------
13125  *
13126  *                          DEFAULT FONT
13127  *
13128  * ProggyClean.ttf
13129  * Copyright (c) 2004, 2005 Tristan Grimmer
13130  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
13131  * Download and more information at http://upperbounds.net
13132  *-----------------------------------------------------------------------------*/
13133 #ifdef __clang__
13134 #pragma clang diagnostic push
13135 #pragma clang diagnostic ignored "-Woverlength-strings"
13136 #elif defined(__GNUC__) || defined(__GNUG__)
13137 #pragma GCC diagnostic push
13138 #pragma GCC diagnostic ignored "-Woverlength-strings"
13139 #endif
13140 
13141 #ifdef NK_INCLUDE_DEFAULT_FONT
13142 
13143 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
13144     "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
13145     "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#"
13146     "`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"
13147     "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"
13148     "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"
13149     "*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)"
13150     "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"
13151     "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."
13152     "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"
13153     "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(,)"
13154     "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#"
13155     "'/###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"
13156     "_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"
13157     "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/"
13158     "/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"
13159     "%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&#"
13160     "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)("
13161     "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"
13162     "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"
13163     "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^-"
13164     "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-"
13165     "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"
13166     "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%"
13167     "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]"
13168     "%(?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"
13169     "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:"
13170     "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("
13171     "$/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<"
13172     "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'?"
13173     "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/;"
13174     ")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"
13175     "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("
13176     "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"
13177     "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
13178     "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<-"
13179     "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"
13180     "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"
13181     ".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@@"
13182     "$&)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*"
13183     "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"
13184     "@-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&#"
13185     "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#"
13186     "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"
13187     "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"
13188     "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&#"
13189     "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"
13190     ":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+"
13191     "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*"
13192     "$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"
13193     ":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"
13194     "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"
13195     "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"
13196     "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"
13197     ":^#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@&]>"
13198     "_>@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%"
13199     "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;"
13200     "^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:"
13201     "+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%"
13202     "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-"
13203     "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*"
13204     "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"
13205     "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
13206     "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`"
13207     "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]%/"
13208     "+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"
13209     "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"
13210     "?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"
13211     "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"
13212     ">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'>"
13213     "[%$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"
13214     "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#"
13215     "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$"
13216     "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,)"
13217     "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"
13218     "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"
13219     "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"
13220     "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(#"
13221     ";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&>"
13222     "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#"
13223     "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"
13224     "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#"
13225     "/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-#"
13226     "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#"
13227     "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
13228     "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
13229     "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
13230 
13231 #endif /* NK_INCLUDE_DEFAULT_FONT */
13232 
13233 #define NK_CURSOR_DATA_W 90
13234 #define NK_CURSOR_DATA_H 27
13235 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
13236 {
13237     "..-         -XXXXXXX-    X    -           X           -XXXXXXX          -          XXXXXXX"
13238     "..-         -X.....X-   X.X   -          X.X          -X.....X          -          X.....X"
13239     "---         -XXX.XXX-  X...X  -         X...X         -X....X           -           X....X"
13240     "X           -  X.X  - X.....X -        X.....X        -X...X            -            X...X"
13241     "XX          -  X.X  -X.......X-       X.......X       -X..X.X           -           X.X..X"
13242     "X.X         -  X.X  -XXXX.XXXX-       XXXX.XXXX       -X.X X.X          -          X.X X.X"
13243     "X..X        -  X.X  -   X.X   -          X.X          -XX   X.X         -         X.X   XX"
13244     "X...X       -  X.X  -   X.X   -    XX    X.X    XX    -      X.X        -        X.X      "
13245     "X....X      -  X.X  -   X.X   -   X.X    X.X    X.X   -       X.X       -       X.X       "
13246     "X.....X     -  X.X  -   X.X   -  X..X    X.X    X..X  -        X.X      -      X.X        "
13247     "X......X    -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -         X.X   XX-XX   X.X         "
13248     "X.......X   -  X.X  -   X.X   -X.....................X-          X.X X.X-X.X X.X          "
13249     "X........X  -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -           X.X..X-X..X.X           "
13250     "X.........X -XXX.XXX-   X.X   -  X..X    X.X    X..X  -            X...X-X...X            "
13251     "X..........X-X.....X-   X.X   -   X.X    X.X    X.X   -           X....X-X....X           "
13252     "X......XXXXX-XXXXXXX-   X.X   -    XX    X.X    XX    -          X.....X-X.....X          "
13253     "X...X..X    ---------   X.X   -          X.X          -          XXXXXXX-XXXXXXX          "
13254     "X..X X..X   -       -XXXX.XXXX-       XXXX.XXXX       ------------------------------------"
13255     "X.X  X..X   -       -X.......X-       X.......X       -    XX           XX    -           "
13256     "XX    X..X  -       - X.....X -        X.....X        -   X.X           X.X   -           "
13257     "      X..X          -  X...X  -         X...X         -  X..X           X..X  -           "
13258     "       XX           -   X.X   -          X.X          - X...XXXXXXXXXXXXX...X -           "
13259     "------------        -    X    -           X           -X.....................X-           "
13260     "                    ----------------------------------- X...XXXXXXXXXXXXX...X -           "
13261     "                                                      -  X..X           X..X  -           "
13262     "                                                      -   X.X           X.X   -           "
13263     "                                                      -    XX           XX    -           "
13264 };
13265 
13266 #ifdef __clang__
13267 #pragma clang diagnostic pop
13268 #elif defined(__GNUC__) || defined(__GNUG__)
13269 #pragma GCC diagnostic pop
13270 #endif
13271 
13272 NK_GLOBAL unsigned char *nk__barrier;
13273 NK_GLOBAL unsigned char *nk__barrier2;
13274 NK_GLOBAL unsigned char *nk__barrier3;
13275 NK_GLOBAL unsigned char *nk__barrier4;
13276 NK_GLOBAL unsigned char *nk__dout;
13277 
13278 NK_INTERN unsigned int
13279 nk_decompress_length(unsigned char *input)
13280 {
13281     return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
13282 }
13283 NK_INTERN void
13284 nk__match(unsigned char *data, unsigned int length)
13285 {
13286     /* INVERSE of memmove... write each byte before copying the next...*/
13287     NK_ASSERT (nk__dout + length <= nk__barrier);
13288     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
13289     if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
13290     while (length--) *nk__dout++ = *data++;
13291 }
13292 NK_INTERN void
13293 nk__lit(unsigned char *data, unsigned int length)
13294 {
13295     NK_ASSERT (nk__dout + length <= nk__barrier);
13296     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
13297     if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
13298     NK_MEMCPY(nk__dout, data, length);
13299     nk__dout += length;
13300 }
13301 NK_INTERN unsigned char*
13302 nk_decompress_token(unsigned char *i)
13303 {
13304     #define nk__in2(x)   ((i[x] << 8) + i[(x)+1])
13305     #define nk__in3(x)   ((i[x] << 16) + nk__in2((x)+1))
13306     #define nk__in4(x)   ((i[x] << 24) + nk__in3((x)+1))
13307 
13308     if (*i >= 0x20) { /* use fewer if's for cases that expand small */
13309         if (*i >= 0x80)       nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
13310         else if (*i >= 0x40)  nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
13311         else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
13312     } else { /* more ifs for cases that expand large, since overhead is amortized */
13313         if (*i >= 0x18)       nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
13314         else if (*i >= 0x10)  nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
13315         else if (*i >= 0x08)  nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
13316         else if (*i == 0x07)  nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
13317         else if (*i == 0x06)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
13318         else if (*i == 0x04)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
13319     }
13320     return i;
13321 }
13322 NK_INTERN unsigned int
13323 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
13324 {
13325     const unsigned long ADLER_MOD = 65521;
13326     unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
13327     unsigned long blocklen, i;
13328 
13329     blocklen = buflen % 5552;
13330     while (buflen) {
13331         for (i=0; i + 7 < blocklen; i += 8) {
13332             s1 += buffer[0]; s2 += s1;
13333             s1 += buffer[1]; s2 += s1;
13334             s1 += buffer[2]; s2 += s1;
13335             s1 += buffer[3]; s2 += s1;
13336             s1 += buffer[4]; s2 += s1;
13337             s1 += buffer[5]; s2 += s1;
13338             s1 += buffer[6]; s2 += s1;
13339             s1 += buffer[7]; s2 += s1;
13340             buffer += 8;
13341         }
13342         for (; i < blocklen; ++i) {
13343             s1 += *buffer++; s2 += s1;
13344         }
13345 
13346         s1 %= ADLER_MOD; s2 %= ADLER_MOD;
13347         buflen -= (unsigned int)blocklen;
13348         blocklen = 5552;
13349     }
13350     return (unsigned int)(s2 << 16) + (unsigned int)s1;
13351 }
13352 NK_INTERN unsigned int
13353 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
13354 {
13355     unsigned int olen;
13356     if (nk__in4(0) != 0x57bC0000) return 0;
13357     if (nk__in4(4) != 0)          return 0; /* error! stream is > 4GB */
13358     olen = nk_decompress_length(i);
13359     nk__barrier2 = i;
13360     nk__barrier3 = i+length;
13361     nk__barrier = output + olen;
13362     nk__barrier4 = output;
13363     i += 16;
13364 
13365     nk__dout = output;
13366     for (;;) {
13367         unsigned char *old_i = i;
13368         i = nk_decompress_token(i);
13369         if (i == old_i) {
13370             if (*i == 0x05 && i[1] == 0xfa) {
13371                 NK_ASSERT(nk__dout == output + olen);
13372                 if (nk__dout != output + olen) return 0;
13373                 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
13374                     return 0;
13375                 return olen;
13376             } else {
13377                 NK_ASSERT(0); /* NOTREACHED */
13378                 return 0;
13379             }
13380         }
13381         NK_ASSERT(nk__dout <= output + olen);
13382         if (nk__dout > output + olen)
13383             return 0;
13384     }
13385 }
13386 NK_INTERN unsigned int
13387 nk_decode_85_byte(char c)
13388 {
13389     return (unsigned int)((c >= '\\') ? c-36 : c-35);
13390 }
13391 NK_INTERN void
13392 nk_decode_85(unsigned char* dst, const unsigned char* src)
13393 {
13394     while (*src)
13395     {
13396         unsigned int tmp =
13397             nk_decode_85_byte((char)src[0]) +
13398             85 * (nk_decode_85_byte((char)src[1]) +
13399             85 * (nk_decode_85_byte((char)src[2]) +
13400             85 * (nk_decode_85_byte((char)src[3]) +
13401             85 * nk_decode_85_byte((char)src[4]))));
13402 
13403         /* we can't assume little-endianess. */
13404         dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
13405         dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
13406         dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
13407         dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
13408 
13409         src += 5;
13410         dst += 4;
13411     }
13412 }
13413 
13414 /* -------------------------------------------------------------
13415  *
13416  *                          FONT ATLAS
13417  *
13418  * --------------------------------------------------------------*/
13419 NK_API struct nk_font_config
13420 nk_font_config(float pixel_height)
13421 {
13422     struct nk_font_config cfg;
13423     nk_zero_struct(cfg);
13424     cfg.ttf_blob = 0;
13425     cfg.ttf_size = 0;
13426     cfg.ttf_data_owned_by_atlas = 0;
13427     cfg.size = pixel_height;
13428     cfg.oversample_h = 3;
13429     cfg.oversample_v = 1;
13430     cfg.pixel_snap = 0;
13431     cfg.coord_type = NK_COORD_UV;
13432     cfg.spacing = nk_vec2(0,0);
13433     cfg.range = nk_font_default_glyph_ranges();
13434     cfg.merge_mode = 0;
13435     cfg.fallback_glyph = '?';
13436     cfg.font = 0;
13437     cfg.n = 0;
13438     return cfg;
13439 }
13440 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13441 NK_API void
13442 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
13443 {
13444     NK_ASSERT(atlas);
13445     if (!atlas) return;
13446     nk_zero_struct(*atlas);
13447     atlas->temporary.userdata.ptr = 0;
13448     atlas->temporary.alloc = nk_malloc;
13449     atlas->temporary.free = nk_mfree;
13450     atlas->permanent.userdata.ptr = 0;
13451     atlas->permanent.alloc = nk_malloc;
13452     atlas->permanent.free = nk_mfree;
13453 }
13454 #endif
13455 NK_API void
13456 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
13457 {
13458     NK_ASSERT(atlas);
13459     NK_ASSERT(alloc);
13460     if (!atlas || !alloc) return;
13461     nk_zero_struct(*atlas);
13462     atlas->permanent = *alloc;
13463     atlas->temporary = *alloc;
13464 }
13465 NK_API void
13466 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
13467     struct nk_allocator *permanent, struct nk_allocator *temporary)
13468 {
13469     NK_ASSERT(atlas);
13470     NK_ASSERT(permanent);
13471     NK_ASSERT(temporary);
13472     if (!atlas || !permanent || !temporary) return;
13473     nk_zero_struct(*atlas);
13474     atlas->permanent = *permanent;
13475     atlas->temporary = *temporary;
13476 }
13477 NK_API void
13478 nk_font_atlas_begin(struct nk_font_atlas *atlas)
13479 {
13480     NK_ASSERT(atlas);
13481     NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
13482     NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
13483     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
13484         !atlas->temporary.alloc || !atlas->temporary.free) return;
13485     if (atlas->glyphs) {
13486         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13487         atlas->glyphs = 0;
13488     }
13489     if (atlas->pixel) {
13490         atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
13491         atlas->pixel = 0;
13492     }
13493 }
13494 NK_API struct nk_font*
13495 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
13496 {
13497     struct nk_font *font = 0;
13498     struct nk_font_config *cfg;
13499 
13500     NK_ASSERT(atlas);
13501     NK_ASSERT(atlas->permanent.alloc);
13502     NK_ASSERT(atlas->permanent.free);
13503     NK_ASSERT(atlas->temporary.alloc);
13504     NK_ASSERT(atlas->temporary.free);
13505 
13506     NK_ASSERT(config);
13507     NK_ASSERT(config->ttf_blob);
13508     NK_ASSERT(config->ttf_size);
13509     NK_ASSERT(config->size > 0.0f);
13510 
13511     if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
13512         !atlas->permanent.alloc || !atlas->permanent.free ||
13513         !atlas->temporary.alloc || !atlas->temporary.free)
13514         return 0;
13515 
13516     /* allocate font config  */
13517     cfg = (struct nk_font_config*)
13518         atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
13519     NK_MEMCPY(cfg, config, sizeof(*config));
13520     cfg->n = cfg;
13521     cfg->p = cfg;
13522 
13523     if (!config->merge_mode) {
13524         /* insert font config into list */
13525         if (!atlas->config) {
13526             atlas->config = cfg;
13527             cfg->next = 0;
13528         } else {
13529             struct nk_font_config *i = atlas->config;
13530             while (i->next) i = i->next;
13531             i->next = cfg;
13532             cfg->next = 0;
13533         }
13534         /* allocate new font */
13535         font = (struct nk_font*)
13536             atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
13537         NK_ASSERT(font);
13538         nk_zero(font, sizeof(*font));
13539         if (!font) return 0;
13540         font->config = cfg;
13541 
13542         /* insert font into list */
13543         if (!atlas->fonts) {
13544             atlas->fonts = font;
13545             font->next = 0;
13546         } else {
13547             struct nk_font *i = atlas->fonts;
13548             while (i->next) i = i->next;
13549             i->next = font;
13550             font->next = 0;
13551         }
13552         cfg->font = &font->info;
13553     } else {
13554         /* extend previously added font */
13555         struct nk_font *f = 0;
13556         struct nk_font_config *c = 0;
13557         NK_ASSERT(atlas->font_num);
13558         f = atlas->fonts;
13559         c = f->config;
13560         cfg->font = &f->info;
13561 
13562         cfg->n = c;
13563         cfg->p = c->p;
13564         c->p->n = cfg;
13565         c->p = cfg;
13566     }
13567     /* create own copy of .TTF font blob */
13568     if (!config->ttf_data_owned_by_atlas) {
13569         cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
13570         NK_ASSERT(cfg->ttf_blob);
13571         if (!cfg->ttf_blob) {
13572             atlas->font_num++;
13573             return 0;
13574         }
13575         NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
13576         cfg->ttf_data_owned_by_atlas = 1;
13577     }
13578     atlas->font_num++;
13579     return font;
13580 }
13581 NK_API struct nk_font*
13582 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
13583     nk_size size, float height, const struct nk_font_config *config)
13584 {
13585     struct nk_font_config cfg;
13586     NK_ASSERT(memory);
13587     NK_ASSERT(size);
13588 
13589     NK_ASSERT(atlas);
13590     NK_ASSERT(atlas->temporary.alloc);
13591     NK_ASSERT(atlas->temporary.free);
13592     NK_ASSERT(atlas->permanent.alloc);
13593     NK_ASSERT(atlas->permanent.free);
13594     if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
13595         !atlas->permanent.alloc || !atlas->permanent.free)
13596         return 0;
13597 
13598     cfg = (config) ? *config: nk_font_config(height);
13599     cfg.ttf_blob = memory;
13600     cfg.ttf_size = size;
13601     cfg.size = height;
13602     cfg.ttf_data_owned_by_atlas = 0;
13603     return nk_font_atlas_add(atlas, &cfg);
13604 }
13605 #ifdef NK_INCLUDE_STANDARD_IO
13606 NK_API struct nk_font*
13607 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
13608     float height, const struct nk_font_config *config)
13609 {
13610     nk_size size;
13611     char *memory;
13612     struct nk_font_config cfg;
13613 
13614     NK_ASSERT(atlas);
13615     NK_ASSERT(atlas->temporary.alloc);
13616     NK_ASSERT(atlas->temporary.free);
13617     NK_ASSERT(atlas->permanent.alloc);
13618     NK_ASSERT(atlas->permanent.free);
13619 
13620     if (!atlas || !file_path) return 0;
13621     memory = nk_file_load(file_path, &size, &atlas->permanent);
13622     if (!memory) return 0;
13623 
13624     cfg = (config) ? *config: nk_font_config(height);
13625     cfg.ttf_blob = memory;
13626     cfg.ttf_size = size;
13627     cfg.size = height;
13628     cfg.ttf_data_owned_by_atlas = 1;
13629     return nk_font_atlas_add(atlas, &cfg);
13630 }
13631 #endif
13632 NK_API struct nk_font*
13633 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
13634     void *compressed_data, nk_size compressed_size, float height,
13635     const struct nk_font_config *config)
13636 {
13637     unsigned int decompressed_size;
13638     void *decompressed_data;
13639     struct nk_font_config cfg;
13640 
13641     NK_ASSERT(atlas);
13642     NK_ASSERT(atlas->temporary.alloc);
13643     NK_ASSERT(atlas->temporary.free);
13644     NK_ASSERT(atlas->permanent.alloc);
13645     NK_ASSERT(atlas->permanent.free);
13646 
13647     NK_ASSERT(compressed_data);
13648     NK_ASSERT(compressed_size);
13649     if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
13650         !atlas->permanent.alloc || !atlas->permanent.free)
13651         return 0;
13652 
13653     decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
13654     decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
13655     NK_ASSERT(decompressed_data);
13656     if (!decompressed_data) return 0;
13657     nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
13658         (unsigned int)compressed_size);
13659 
13660     cfg = (config) ? *config: nk_font_config(height);
13661     cfg.ttf_blob = decompressed_data;
13662     cfg.ttf_size = decompressed_size;
13663     cfg.size = height;
13664     cfg.ttf_data_owned_by_atlas = 1;
13665     return nk_font_atlas_add(atlas, &cfg);
13666 }
13667 NK_API struct nk_font*
13668 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
13669     const char *data_base85, float height, const struct nk_font_config *config)
13670 {
13671     int compressed_size;
13672     void *compressed_data;
13673     struct nk_font *font;
13674 
13675     NK_ASSERT(atlas);
13676     NK_ASSERT(atlas->temporary.alloc);
13677     NK_ASSERT(atlas->temporary.free);
13678     NK_ASSERT(atlas->permanent.alloc);
13679     NK_ASSERT(atlas->permanent.free);
13680 
13681     NK_ASSERT(data_base85);
13682     if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
13683         !atlas->permanent.alloc || !atlas->permanent.free)
13684         return 0;
13685 
13686     compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
13687     compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
13688     NK_ASSERT(compressed_data);
13689     if (!compressed_data) return 0;
13690     nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
13691     font = nk_font_atlas_add_compressed(atlas, compressed_data,
13692                     (nk_size)compressed_size, height, config);
13693     atlas->temporary.free(atlas->temporary.userdata, compressed_data);
13694     return font;
13695 }
13696 
13697 #ifdef NK_INCLUDE_DEFAULT_FONT
13698 NK_API struct nk_font*
13699 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
13700     float pixel_height, const struct nk_font_config *config)
13701 {
13702     NK_ASSERT(atlas);
13703     NK_ASSERT(atlas->temporary.alloc);
13704     NK_ASSERT(atlas->temporary.free);
13705     NK_ASSERT(atlas->permanent.alloc);
13706     NK_ASSERT(atlas->permanent.free);
13707     return nk_font_atlas_add_compressed_base85(atlas,
13708         nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
13709 }
13710 #endif
13711 NK_API const void*
13712 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
13713     enum nk_font_atlas_format fmt)
13714 {
13715     int i = 0;
13716     void *tmp = 0;
13717     nk_size tmp_size, img_size;
13718     struct nk_font *font_iter;
13719     struct nk_font_baker *baker;
13720 
13721     NK_ASSERT(atlas);
13722     NK_ASSERT(atlas->temporary.alloc);
13723     NK_ASSERT(atlas->temporary.free);
13724     NK_ASSERT(atlas->permanent.alloc);
13725     NK_ASSERT(atlas->permanent.free);
13726 
13727     NK_ASSERT(width);
13728     NK_ASSERT(height);
13729     if (!atlas || !width || !height ||
13730         !atlas->temporary.alloc || !atlas->temporary.free ||
13731         !atlas->permanent.alloc || !atlas->permanent.free)
13732         return 0;
13733 
13734 #ifdef NK_INCLUDE_DEFAULT_FONT
13735     /* no font added so just use default font */
13736     if (!atlas->font_num)
13737         atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
13738 #endif
13739     NK_ASSERT(atlas->font_num);
13740     if (!atlas->font_num) return 0;
13741 
13742     /* allocate temporary baker memory required for the baking process */
13743     nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
13744     tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
13745     NK_ASSERT(tmp);
13746     if (!tmp) goto failed;
13747 
13748     /* allocate glyph memory for all fonts */
13749     baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
13750     atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
13751         atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
13752     NK_ASSERT(atlas->glyphs);
13753     if (!atlas->glyphs)
13754         goto failed;
13755 
13756     /* pack all glyphs into a tight fit space */
13757     atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
13758     atlas->custom.h = NK_CURSOR_DATA_H + 1;
13759     if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
13760         atlas->config, atlas->font_num, &atlas->temporary))
13761         goto failed;
13762 
13763     /* allocate memory for the baked image font atlas */
13764     atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
13765     NK_ASSERT(atlas->pixel);
13766     if (!atlas->pixel)
13767         goto failed;
13768 
13769     /* bake glyphs and custom white pixel into image */
13770     nk_font_bake(baker, atlas->pixel, *width, *height,
13771         atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
13772     nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
13773             nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
13774 
13775     if (fmt == NK_FONT_ATLAS_RGBA32) {
13776         /* convert alpha8 image into rgba32 image */
13777         void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
13778                             (nk_size)(*width * *height * 4));
13779         NK_ASSERT(img_rgba);
13780         if (!img_rgba) goto failed;
13781         nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
13782         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13783         atlas->pixel = img_rgba;
13784     }
13785     atlas->tex_width = *width;
13786     atlas->tex_height = *height;
13787 
13788     /* initialize each font */
13789     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
13790         struct nk_font *font = font_iter;
13791         struct nk_font_config *config = font->config;
13792         nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
13793             config->font, nk_handle_ptr(0));
13794     }
13795 
13796     /* initialize each cursor */
13797     {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
13798         /* Pos      Size        Offset */
13799         {{ 0, 3},   {12,19},    { 0, 0}},
13800         {{13, 0},   { 7,16},    { 4, 8}},
13801         {{31, 0},   {23,23},    {11,11}},
13802         {{21, 0},   { 9, 23},   { 5,11}},
13803         {{55,18},   {23, 9},    {11, 5}},
13804         {{73, 0},   {17,17},    { 9, 9}},
13805         {{55, 0},   {17,17},    { 9, 9}}
13806     };
13807     for (i = 0; i < NK_CURSOR_COUNT; ++i) {
13808         struct nk_cursor *cursor = &atlas->cursors[i];
13809         cursor->img.w = (unsigned short)*width;
13810         cursor->img.h = (unsigned short)*height;
13811         cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
13812         cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
13813         cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
13814         cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
13815         cursor->size = nk_cursor_data[i][1];
13816         cursor->offset = nk_cursor_data[i][2];
13817     }}
13818     /* free temporary memory */
13819     atlas->temporary.free(atlas->temporary.userdata, tmp);
13820     return atlas->pixel;
13821 
13822 failed:
13823     /* error so cleanup all memory */
13824     if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
13825     if (atlas->glyphs) {
13826         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13827         atlas->glyphs = 0;
13828     }
13829     if (atlas->pixel) {
13830         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13831         atlas->pixel = 0;
13832     }
13833     return 0;
13834 }
13835 NK_API void
13836 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
13837     struct nk_draw_null_texture *null)
13838 {
13839     int i = 0;
13840     struct nk_font *font_iter;
13841     NK_ASSERT(atlas);
13842     if (!atlas) {
13843         if (!null) return;
13844         null->texture = texture;
13845         null->uv = nk_vec2(0.5f,0.5f);
13846     }
13847     if (null) {
13848         null->texture = texture;
13849         null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
13850         null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
13851     }
13852     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
13853         font_iter->texture = texture;
13854 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
13855         font_iter->handle.texture = texture;
13856 #endif
13857     }
13858     for (i = 0; i < NK_CURSOR_COUNT; ++i)
13859         atlas->cursors[i].img.handle = texture;
13860 
13861     atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
13862     atlas->pixel = 0;
13863     atlas->tex_width = 0;
13864     atlas->tex_height = 0;
13865     atlas->custom.x = 0;
13866     atlas->custom.y = 0;
13867     atlas->custom.w = 0;
13868     atlas->custom.h = 0;
13869 }
13870 NK_API void
13871 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
13872 {
13873     NK_ASSERT(atlas);
13874     NK_ASSERT(atlas->temporary.alloc);
13875     NK_ASSERT(atlas->temporary.free);
13876     NK_ASSERT(atlas->permanent.alloc);
13877     NK_ASSERT(atlas->permanent.free);
13878     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
13879     if (atlas->config) {
13880         struct nk_font_config *iter;
13881         for (iter = atlas->config; iter; iter = iter->next) {
13882             struct nk_font_config *i;
13883             for (i = iter->n; i != iter; i = i->n) {
13884                 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
13885                 i->ttf_blob = 0;
13886             }
13887             atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
13888             iter->ttf_blob = 0;
13889         }
13890     }
13891 }
13892 NK_API void
13893 nk_font_atlas_clear(struct nk_font_atlas *atlas)
13894 {
13895     NK_ASSERT(atlas);
13896     NK_ASSERT(atlas->temporary.alloc);
13897     NK_ASSERT(atlas->temporary.free);
13898     NK_ASSERT(atlas->permanent.alloc);
13899     NK_ASSERT(atlas->permanent.free);
13900     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
13901 
13902     if (atlas->config) {
13903         struct nk_font_config *iter, *next;
13904         for (iter = atlas->config; iter; iter = next) {
13905             struct nk_font_config *i, *n;
13906             for (i = iter->n; i != iter; i = n) {
13907                 n = i->n;
13908                 if (i->ttf_blob)
13909                     atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
13910                 atlas->permanent.free(atlas->permanent.userdata, i);
13911             }
13912             next = iter->next;
13913             if (i->ttf_blob)
13914                 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
13915             atlas->permanent.free(atlas->permanent.userdata, iter);
13916         }
13917         atlas->config = 0;
13918     }
13919     if (atlas->fonts) {
13920         struct nk_font *iter, *next;
13921         for (iter = atlas->fonts; iter; iter = next) {
13922             next = iter->next;
13923             atlas->permanent.free(atlas->permanent.userdata, iter);
13924         }
13925         atlas->fonts = 0;
13926     }
13927     if (atlas->glyphs)
13928         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
13929     nk_zero_struct(*atlas);
13930 }
13931 #endif
13932 
13933 
13934 
13935 
13936 
13937 /* ===============================================================
13938  *
13939  *                          INPUT
13940  *
13941  * ===============================================================*/
13942 NK_API void
13943 nk_input_begin(struct nk_context *ctx)
13944 {
13945     int i;
13946     struct nk_input *in;
13947     NK_ASSERT(ctx);
13948     if (!ctx) return;
13949     in = &ctx->input;
13950     for (i = 0; i < NK_BUTTON_MAX; ++i)
13951         in->mouse.buttons[i].clicked = 0;
13952 
13953     in->keyboard.text_len = 0;
13954     in->mouse.scroll_delta = nk_vec2(0,0);
13955     in->mouse.prev.x = in->mouse.pos.x;
13956     in->mouse.prev.y = in->mouse.pos.y;
13957     in->mouse.delta.x = 0;
13958     in->mouse.delta.y = 0;
13959     for (i = 0; i < NK_KEY_MAX; i++)
13960         in->keyboard.keys[i].clicked = 0;
13961 }
13962 NK_API void
13963 nk_input_end(struct nk_context *ctx)
13964 {
13965     struct nk_input *in;
13966     NK_ASSERT(ctx);
13967     if (!ctx) return;
13968     in = &ctx->input;
13969     if (in->mouse.grab)
13970         in->mouse.grab = 0;
13971     if (in->mouse.ungrab) {
13972         in->mouse.grabbed = 0;
13973         in->mouse.ungrab = 0;
13974         in->mouse.grab = 0;
13975     }
13976 }
13977 NK_API void
13978 nk_input_motion(struct nk_context *ctx, int x, int y)
13979 {
13980     struct nk_input *in;
13981     NK_ASSERT(ctx);
13982     if (!ctx) return;
13983     in = &ctx->input;
13984     in->mouse.pos.x = (float)x;
13985     in->mouse.pos.y = (float)y;
13986     in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
13987     in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
13988 }
13989 NK_API void
13990 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
13991 {
13992     struct nk_input *in;
13993     NK_ASSERT(ctx);
13994     if (!ctx) return;
13995     in = &ctx->input;
13996 #ifdef NK_KEYSTATE_BASED_INPUT
13997     if (in->keyboard.keys[key].down != down)
13998         in->keyboard.keys[key].clicked++;
13999 #else
14000     in->keyboard.keys[key].clicked++;
14001 #endif
14002     in->keyboard.keys[key].down = down;
14003 }
14004 NK_API void
14005 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
14006 {
14007     struct nk_mouse_button *btn;
14008     struct nk_input *in;
14009     NK_ASSERT(ctx);
14010     if (!ctx) return;
14011     in = &ctx->input;
14012     if (in->mouse.buttons[id].down == down) return;
14013 
14014     btn = &in->mouse.buttons[id];
14015     btn->clicked_pos.x = (float)x;
14016     btn->clicked_pos.y = (float)y;
14017     btn->down = down;
14018     btn->clicked++;
14019 }
14020 NK_API void
14021 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
14022 {
14023     NK_ASSERT(ctx);
14024     if (!ctx) return;
14025     ctx->input.mouse.scroll_delta.x += val.x;
14026     ctx->input.mouse.scroll_delta.y += val.y;
14027 }
14028 NK_API void
14029 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
14030 {
14031     int len = 0;
14032     nk_rune unicode;
14033     struct nk_input *in;
14034 
14035     NK_ASSERT(ctx);
14036     if (!ctx) return;
14037     in = &ctx->input;
14038 
14039     len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
14040     if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
14041         nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
14042             NK_INPUT_MAX - in->keyboard.text_len);
14043         in->keyboard.text_len += len;
14044     }
14045 }
14046 NK_API void
14047 nk_input_char(struct nk_context *ctx, char c)
14048 {
14049     nk_glyph glyph;
14050     NK_ASSERT(ctx);
14051     if (!ctx) return;
14052     glyph[0] = c;
14053     nk_input_glyph(ctx, glyph);
14054 }
14055 NK_API void
14056 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
14057 {
14058     nk_glyph rune;
14059     NK_ASSERT(ctx);
14060     if (!ctx) return;
14061     nk_utf_encode(unicode, rune, NK_UTF_SIZE);
14062     nk_input_glyph(ctx, rune);
14063 }
14064 NK_API int
14065 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
14066 {
14067     const struct nk_mouse_button *btn;
14068     if (!i) return nk_false;
14069     btn = &i->mouse.buttons[id];
14070     return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
14071 }
14072 NK_API int
14073 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
14074     struct nk_rect b)
14075 {
14076     const struct nk_mouse_button *btn;
14077     if (!i) return nk_false;
14078     btn = &i->mouse.buttons[id];
14079     if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
14080         return nk_false;
14081     return nk_true;
14082 }
14083 NK_API int
14084 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
14085     struct nk_rect b, int down)
14086 {
14087     const struct nk_mouse_button *btn;
14088     if (!i) return nk_false;
14089     btn = &i->mouse.buttons[id];
14090     return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
14091 }
14092 NK_API int
14093 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
14094     struct nk_rect b)
14095 {
14096     const struct nk_mouse_button *btn;
14097     if (!i) return nk_false;
14098     btn = &i->mouse.buttons[id];
14099     return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
14100             btn->clicked) ? nk_true : nk_false;
14101 }
14102 NK_API int
14103 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
14104     struct nk_rect b, int down)
14105 {
14106     const struct nk_mouse_button *btn;
14107     if (!i) return nk_false;
14108     btn = &i->mouse.buttons[id];
14109     return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
14110             btn->clicked) ? nk_true : nk_false;
14111 }
14112 NK_API int
14113 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
14114 {
14115     int i, down = 0;
14116     for (i = 0; i < NK_BUTTON_MAX; ++i)
14117         down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
14118     return down;
14119 }
14120 NK_API int
14121 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
14122 {
14123     if (!i) return nk_false;
14124     return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
14125 }
14126 NK_API int
14127 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
14128 {
14129     if (!i) return nk_false;
14130     return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
14131 }
14132 NK_API int
14133 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
14134 {
14135     if (!i) return nk_false;
14136     if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
14137     return nk_input_is_mouse_click_in_rect(i, id, rect);
14138 }
14139 NK_API int
14140 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
14141 {
14142     if (!i) return nk_false;
14143     return i->mouse.buttons[id].down;
14144 }
14145 NK_API int
14146 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
14147 {
14148     const struct nk_mouse_button *b;
14149     if (!i) return nk_false;
14150     b = &i->mouse.buttons[id];
14151     if (b->down && b->clicked)
14152         return nk_true;
14153     return nk_false;
14154 }
14155 NK_API int
14156 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
14157 {
14158     if (!i) return nk_false;
14159     return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
14160 }
14161 NK_API int
14162 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
14163 {
14164     const struct nk_key *k;
14165     if (!i) return nk_false;
14166     k = &i->keyboard.keys[key];
14167     if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
14168         return nk_true;
14169     return nk_false;
14170 }
14171 NK_API int
14172 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
14173 {
14174     const struct nk_key *k;
14175     if (!i) return nk_false;
14176     k = &i->keyboard.keys[key];
14177     if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
14178         return nk_true;
14179     return nk_false;
14180 }
14181 NK_API int
14182 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
14183 {
14184     const struct nk_key *k;
14185     if (!i) return nk_false;
14186     k = &i->keyboard.keys[key];
14187     if (k->down) return nk_true;
14188     return nk_false;
14189 }
14190 
14191 
14192 
14193 
14194 
14195 /* ===============================================================
14196  *
14197  *                              STYLE
14198  *
14199  * ===============================================================*/
14200 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
14201 #define NK_COLOR_MAP(NK_COLOR)\
14202     NK_COLOR(NK_COLOR_TEXT,                     175,175,175,255) \
14203     NK_COLOR(NK_COLOR_WINDOW,                   45, 45, 45, 255) \
14204     NK_COLOR(NK_COLOR_HEADER,                   40, 40, 40, 255) \
14205     NK_COLOR(NK_COLOR_BORDER,                   65, 65, 65, 255) \
14206     NK_COLOR(NK_COLOR_BUTTON,                   50, 50, 50, 255) \
14207     NK_COLOR(NK_COLOR_BUTTON_HOVER,             40, 40, 40, 255) \
14208     NK_COLOR(NK_COLOR_BUTTON_ACTIVE,            35, 35, 35, 255) \
14209     NK_COLOR(NK_COLOR_TOGGLE,                   100,100,100,255) \
14210     NK_COLOR(NK_COLOR_TOGGLE_HOVER,             120,120,120,255) \
14211     NK_COLOR(NK_COLOR_TOGGLE_CURSOR,            45, 45, 45, 255) \
14212     NK_COLOR(NK_COLOR_SELECT,                   45, 45, 45, 255) \
14213     NK_COLOR(NK_COLOR_SELECT_ACTIVE,            35, 35, 35,255) \
14214     NK_COLOR(NK_COLOR_SLIDER,                   38, 38, 38, 255) \
14215     NK_COLOR(NK_COLOR_SLIDER_CURSOR,            100,100,100,255) \
14216     NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER,      120,120,120,255) \
14217     NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE,     150,150,150,255) \
14218     NK_COLOR(NK_COLOR_PROPERTY,                 38, 38, 38, 255) \
14219     NK_COLOR(NK_COLOR_EDIT,                     38, 38, 38, 255)  \
14220     NK_COLOR(NK_COLOR_EDIT_CURSOR,              175,175,175,255) \
14221     NK_COLOR(NK_COLOR_COMBO,                    45, 45, 45, 255) \
14222     NK_COLOR(NK_COLOR_CHART,                    120,120,120,255) \
14223     NK_COLOR(NK_COLOR_CHART_COLOR,              45, 45, 45, 255) \
14224     NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,    255, 0,  0, 255) \
14225     NK_COLOR(NK_COLOR_SCROLLBAR,                40, 40, 40, 255) \
14226     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR,         100,100,100,255) \
14227     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,   120,120,120,255) \
14228     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,  150,150,150,255) \
14229     NK_COLOR(NK_COLOR_TAB_HEADER,               40, 40, 40,255)
14230 
14231 NK_GLOBAL const struct nk_color
14232 nk_default_color_style[NK_COLOR_COUNT] = {
14233 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
14234     NK_COLOR_MAP(NK_COLOR)
14235 #undef NK_COLOR
14236 };
14237 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
14238 #define NK_COLOR(a,b,c,d,e) #a,
14239     NK_COLOR_MAP(NK_COLOR)
14240 #undef NK_COLOR
14241 };
14242 
14243 NK_API const char*
14244 nk_style_get_color_by_name(enum nk_style_colors c)
14245 {
14246     return nk_color_names[c];
14247 }
14248 NK_API struct nk_style_item
14249 nk_style_item_image(struct nk_image img)
14250 {
14251     struct nk_style_item i;
14252     i.type = NK_STYLE_ITEM_IMAGE;
14253     i.data.image = img;
14254     return i;
14255 }
14256 NK_API struct nk_style_item
14257 nk_style_item_color(struct nk_color col)
14258 {
14259     struct nk_style_item i;
14260     i.type = NK_STYLE_ITEM_COLOR;
14261     i.data.color = col;
14262     return i;
14263 }
14264 NK_API struct nk_style_item
14265 nk_style_item_hide(void)
14266 {
14267     struct nk_style_item i;
14268     i.type = NK_STYLE_ITEM_COLOR;
14269     i.data.color = nk_rgba(0,0,0,0);
14270     return i;
14271 }
14272 NK_API void
14273 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
14274 {
14275     struct nk_style *style;
14276     struct nk_style_text *text;
14277     struct nk_style_button *button;
14278     struct nk_style_toggle *toggle;
14279     struct nk_style_selectable *select;
14280     struct nk_style_slider *slider;
14281     struct nk_style_progress *prog;
14282     struct nk_style_scrollbar *scroll;
14283     struct nk_style_edit *edit;
14284     struct nk_style_property *property;
14285     struct nk_style_combo *combo;
14286     struct nk_style_chart *chart;
14287     struct nk_style_tab *tab;
14288     struct nk_style_window *win;
14289 
14290     NK_ASSERT(ctx);
14291     if (!ctx) return;
14292     style = &ctx->style;
14293     table = (!table) ? nk_default_color_style: table;
14294 
14295     /* default text */
14296     text = &style->text;
14297     text->color = table[NK_COLOR_TEXT];
14298     text->padding = nk_vec2(0,0);
14299 
14300     /* default button */
14301     button = &style->button;
14302     nk_zero_struct(*button);
14303     button->normal          = nk_style_item_color(table[NK_COLOR_BUTTON]);
14304     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
14305     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
14306     button->border_color    = table[NK_COLOR_BORDER];
14307     button->text_background = table[NK_COLOR_BUTTON];
14308     button->text_normal     = table[NK_COLOR_TEXT];
14309     button->text_hover      = table[NK_COLOR_TEXT];
14310     button->text_active     = table[NK_COLOR_TEXT];
14311     button->padding         = nk_vec2(2.0f,2.0f);
14312     button->image_padding   = nk_vec2(0.0f,0.0f);
14313     button->touch_padding   = nk_vec2(0.0f, 0.0f);
14314     button->userdata        = nk_handle_ptr(0);
14315     button->text_alignment  = NK_TEXT_CENTERED;
14316     button->border          = 1.0f;
14317     button->rounding        = 4.0f;
14318     button->draw_begin      = 0;
14319     button->draw_end        = 0;
14320 
14321     /* contextual button */
14322     button = &style->contextual_button;
14323     nk_zero_struct(*button);
14324     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
14325     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
14326     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
14327     button->border_color    = table[NK_COLOR_WINDOW];
14328     button->text_background = table[NK_COLOR_WINDOW];
14329     button->text_normal     = table[NK_COLOR_TEXT];
14330     button->text_hover      = table[NK_COLOR_TEXT];
14331     button->text_active     = table[NK_COLOR_TEXT];
14332     button->padding         = nk_vec2(2.0f,2.0f);
14333     button->touch_padding   = nk_vec2(0.0f,0.0f);
14334     button->userdata        = nk_handle_ptr(0);
14335     button->text_alignment  = NK_TEXT_CENTERED;
14336     button->border          = 0.0f;
14337     button->rounding        = 0.0f;
14338     button->draw_begin      = 0;
14339     button->draw_end        = 0;
14340 
14341     /* menu button */
14342     button = &style->menu_button;
14343     nk_zero_struct(*button);
14344     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
14345     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
14346     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
14347     button->border_color    = table[NK_COLOR_WINDOW];
14348     button->text_background = table[NK_COLOR_WINDOW];
14349     button->text_normal     = table[NK_COLOR_TEXT];
14350     button->text_hover      = table[NK_COLOR_TEXT];
14351     button->text_active     = table[NK_COLOR_TEXT];
14352     button->padding         = nk_vec2(2.0f,2.0f);
14353     button->touch_padding   = nk_vec2(0.0f,0.0f);
14354     button->userdata        = nk_handle_ptr(0);
14355     button->text_alignment  = NK_TEXT_CENTERED;
14356     button->border          = 0.0f;
14357     button->rounding        = 1.0f;
14358     button->draw_begin      = 0;
14359     button->draw_end        = 0;
14360 
14361     /* checkbox toggle */
14362     toggle = &style->checkbox;
14363     nk_zero_struct(*toggle);
14364     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
14365     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
14366     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
14367     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
14368     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
14369     toggle->userdata        = nk_handle_ptr(0);
14370     toggle->text_background = table[NK_COLOR_WINDOW];
14371     toggle->text_normal     = table[NK_COLOR_TEXT];
14372     toggle->text_hover      = table[NK_COLOR_TEXT];
14373     toggle->text_active     = table[NK_COLOR_TEXT];
14374     toggle->padding         = nk_vec2(2.0f, 2.0f);
14375     toggle->touch_padding   = nk_vec2(0,0);
14376     toggle->border_color    = nk_rgba(0,0,0,0);
14377     toggle->border          = 0.0f;
14378     toggle->spacing         = 4;
14379 
14380     /* option toggle */
14381     toggle = &style->option;
14382     nk_zero_struct(*toggle);
14383     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
14384     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
14385     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
14386     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
14387     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
14388     toggle->userdata        = nk_handle_ptr(0);
14389     toggle->text_background = table[NK_COLOR_WINDOW];
14390     toggle->text_normal     = table[NK_COLOR_TEXT];
14391     toggle->text_hover      = table[NK_COLOR_TEXT];
14392     toggle->text_active     = table[NK_COLOR_TEXT];
14393     toggle->padding         = nk_vec2(3.0f, 3.0f);
14394     toggle->touch_padding   = nk_vec2(0,0);
14395     toggle->border_color    = nk_rgba(0,0,0,0);
14396     toggle->border          = 0.0f;
14397     toggle->spacing         = 4;
14398 
14399     /* selectable */
14400     select = &style->selectable;
14401     nk_zero_struct(*select);
14402     select->normal          = nk_style_item_color(table[NK_COLOR_SELECT]);
14403     select->hover           = nk_style_item_color(table[NK_COLOR_SELECT]);
14404     select->pressed         = nk_style_item_color(table[NK_COLOR_SELECT]);
14405     select->normal_active   = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
14406     select->hover_active    = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
14407     select->pressed_active  = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
14408     select->text_normal     = table[NK_COLOR_TEXT];
14409     select->text_hover      = table[NK_COLOR_TEXT];
14410     select->text_pressed    = table[NK_COLOR_TEXT];
14411     select->text_normal_active  = table[NK_COLOR_TEXT];
14412     select->text_hover_active   = table[NK_COLOR_TEXT];
14413     select->text_pressed_active = table[NK_COLOR_TEXT];
14414     select->padding         = nk_vec2(2.0f,2.0f);
14415     select->image_padding   = nk_vec2(2.0f,2.0f);
14416     select->touch_padding   = nk_vec2(0,0);
14417     select->userdata        = nk_handle_ptr(0);
14418     select->rounding        = 0.0f;
14419     select->draw_begin      = 0;
14420     select->draw_end        = 0;
14421 
14422     /* slider */
14423     slider = &style->slider;
14424     nk_zero_struct(*slider);
14425     slider->normal          = nk_style_item_hide();
14426     slider->hover           = nk_style_item_hide();
14427     slider->active          = nk_style_item_hide();
14428     slider->bar_normal      = table[NK_COLOR_SLIDER];
14429     slider->bar_hover       = table[NK_COLOR_SLIDER];
14430     slider->bar_active      = table[NK_COLOR_SLIDER];
14431     slider->bar_filled      = table[NK_COLOR_SLIDER_CURSOR];
14432     slider->cursor_normal   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
14433     slider->cursor_hover    = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
14434     slider->cursor_active   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
14435     slider->inc_symbol      = NK_SYMBOL_TRIANGLE_RIGHT;
14436     slider->dec_symbol      = NK_SYMBOL_TRIANGLE_LEFT;
14437     slider->cursor_size     = nk_vec2(16,16);
14438     slider->padding         = nk_vec2(2,2);
14439     slider->spacing         = nk_vec2(2,2);
14440     slider->userdata        = nk_handle_ptr(0);
14441     slider->show_buttons    = nk_false;
14442     slider->bar_height      = 8;
14443     slider->rounding        = 0;
14444     slider->draw_begin      = 0;
14445     slider->draw_end        = 0;
14446 
14447     /* slider buttons */
14448     button = &style->slider.inc_button;
14449     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
14450     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
14451     button->active          = nk_style_item_color(nk_rgb(44,44,44));
14452     button->border_color    = nk_rgb(65,65,65);
14453     button->text_background = nk_rgb(40,40,40);
14454     button->text_normal     = nk_rgb(175,175,175);
14455     button->text_hover      = nk_rgb(175,175,175);
14456     button->text_active     = nk_rgb(175,175,175);
14457     button->padding         = nk_vec2(8.0f,8.0f);
14458     button->touch_padding   = nk_vec2(0.0f,0.0f);
14459     button->userdata        = nk_handle_ptr(0);
14460     button->text_alignment  = NK_TEXT_CENTERED;
14461     button->border          = 1.0f;
14462     button->rounding        = 0.0f;
14463     button->draw_begin      = 0;
14464     button->draw_end        = 0;
14465     style->slider.dec_button = style->slider.inc_button;
14466 
14467     /* progressbar */
14468     prog = &style->progress;
14469     nk_zero_struct(*prog);
14470     prog->normal            = nk_style_item_color(table[NK_COLOR_SLIDER]);
14471     prog->hover             = nk_style_item_color(table[NK_COLOR_SLIDER]);
14472     prog->active            = nk_style_item_color(table[NK_COLOR_SLIDER]);
14473     prog->cursor_normal     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
14474     prog->cursor_hover      = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
14475     prog->cursor_active     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
14476     prog->border_color      = nk_rgba(0,0,0,0);
14477     prog->cursor_border_color = nk_rgba(0,0,0,0);
14478     prog->userdata          = nk_handle_ptr(0);
14479     prog->padding           = nk_vec2(4,4);
14480     prog->rounding          = 0;
14481     prog->border            = 0;
14482     prog->cursor_rounding   = 0;
14483     prog->cursor_border     = 0;
14484     prog->draw_begin        = 0;
14485     prog->draw_end          = 0;
14486 
14487     /* scrollbars */
14488     scroll = &style->scrollh;
14489     nk_zero_struct(*scroll);
14490     scroll->normal          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
14491     scroll->hover           = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
14492     scroll->active          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
14493     scroll->cursor_normal   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]);
14494     scroll->cursor_hover    = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]);
14495     scroll->cursor_active   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]);
14496     scroll->dec_symbol      = NK_SYMBOL_CIRCLE_SOLID;
14497     scroll->inc_symbol      = NK_SYMBOL_CIRCLE_SOLID;
14498     scroll->userdata        = nk_handle_ptr(0);
14499     scroll->border_color    = table[NK_COLOR_SCROLLBAR];
14500     scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
14501     scroll->padding         = nk_vec2(0,0);
14502     scroll->show_buttons    = nk_false;
14503     scroll->border          = 0;
14504     scroll->rounding        = 0;
14505     scroll->border_cursor   = 0;
14506     scroll->rounding_cursor = 0;
14507     scroll->draw_begin      = 0;
14508     scroll->draw_end        = 0;
14509     style->scrollv = style->scrollh;
14510 
14511     /* scrollbars buttons */
14512     button = &style->scrollh.inc_button;
14513     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
14514     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
14515     button->active          = nk_style_item_color(nk_rgb(44,44,44));
14516     button->border_color    = nk_rgb(65,65,65);
14517     button->text_background = nk_rgb(40,40,40);
14518     button->text_normal     = nk_rgb(175,175,175);
14519     button->text_hover      = nk_rgb(175,175,175);
14520     button->text_active     = nk_rgb(175,175,175);
14521     button->padding         = nk_vec2(4.0f,4.0f);
14522     button->touch_padding   = nk_vec2(0.0f,0.0f);
14523     button->userdata        = nk_handle_ptr(0);
14524     button->text_alignment  = NK_TEXT_CENTERED;
14525     button->border          = 1.0f;
14526     button->rounding        = 0.0f;
14527     button->draw_begin      = 0;
14528     button->draw_end        = 0;
14529     style->scrollh.dec_button = style->scrollh.inc_button;
14530     style->scrollv.inc_button = style->scrollh.inc_button;
14531     style->scrollv.dec_button = style->scrollh.inc_button;
14532 
14533     /* edit */
14534     edit = &style->edit;
14535     nk_zero_struct(*edit);
14536     edit->normal            = nk_style_item_color(table[NK_COLOR_EDIT]);
14537     edit->hover             = nk_style_item_color(table[NK_COLOR_EDIT]);
14538     edit->active            = nk_style_item_color(table[NK_COLOR_EDIT]);
14539     edit->cursor_normal     = table[NK_COLOR_TEXT];
14540     edit->cursor_hover      = table[NK_COLOR_TEXT];
14541     edit->cursor_text_normal= table[NK_COLOR_EDIT];
14542     edit->cursor_text_hover = table[NK_COLOR_EDIT];
14543     edit->border_color      = table[NK_COLOR_BORDER];
14544     edit->text_normal       = table[NK_COLOR_TEXT];
14545     edit->text_hover        = table[NK_COLOR_TEXT];
14546     edit->text_active       = table[NK_COLOR_TEXT];
14547     edit->selected_normal   = table[NK_COLOR_TEXT];
14548     edit->selected_hover    = table[NK_COLOR_TEXT];
14549     edit->selected_text_normal  = table[NK_COLOR_EDIT];
14550     edit->selected_text_hover   = table[NK_COLOR_EDIT];
14551     edit->scrollbar_size    = nk_vec2(10,10);
14552     edit->scrollbar         = style->scrollv;
14553     edit->padding           = nk_vec2(4,4);
14554     edit->row_padding       = 2;
14555     edit->cursor_size       = 4;
14556     edit->border            = 1;
14557     edit->rounding          = 0;
14558 
14559     /* property */
14560     property = &style->property;
14561     nk_zero_struct(*property);
14562     property->normal        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14563     property->hover         = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14564     property->active        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14565     property->border_color  = table[NK_COLOR_BORDER];
14566     property->label_normal  = table[NK_COLOR_TEXT];
14567     property->label_hover   = table[NK_COLOR_TEXT];
14568     property->label_active  = table[NK_COLOR_TEXT];
14569     property->sym_left      = NK_SYMBOL_TRIANGLE_LEFT;
14570     property->sym_right     = NK_SYMBOL_TRIANGLE_RIGHT;
14571     property->userdata      = nk_handle_ptr(0);
14572     property->padding       = nk_vec2(4,4);
14573     property->border        = 1;
14574     property->rounding      = 10;
14575     property->draw_begin    = 0;
14576     property->draw_end      = 0;
14577 
14578     /* property buttons */
14579     button = &style->property.dec_button;
14580     nk_zero_struct(*button);
14581     button->normal          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14582     button->hover           = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14583     button->active          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14584     button->border_color    = nk_rgba(0,0,0,0);
14585     button->text_background = table[NK_COLOR_PROPERTY];
14586     button->text_normal     = table[NK_COLOR_TEXT];
14587     button->text_hover      = table[NK_COLOR_TEXT];
14588     button->text_active     = table[NK_COLOR_TEXT];
14589     button->padding         = nk_vec2(0.0f,0.0f);
14590     button->touch_padding   = nk_vec2(0.0f,0.0f);
14591     button->userdata        = nk_handle_ptr(0);
14592     button->text_alignment  = NK_TEXT_CENTERED;
14593     button->border          = 0.0f;
14594     button->rounding        = 0.0f;
14595     button->draw_begin      = 0;
14596     button->draw_end        = 0;
14597     style->property.inc_button = style->property.dec_button;
14598 
14599     /* property edit */
14600     edit = &style->property.edit;
14601     nk_zero_struct(*edit);
14602     edit->normal            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14603     edit->hover             = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14604     edit->active            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
14605     edit->border_color      = nk_rgba(0,0,0,0);
14606     edit->cursor_normal     = table[NK_COLOR_TEXT];
14607     edit->cursor_hover      = table[NK_COLOR_TEXT];
14608     edit->cursor_text_normal= table[NK_COLOR_EDIT];
14609     edit->cursor_text_hover = table[NK_COLOR_EDIT];
14610     edit->text_normal       = table[NK_COLOR_TEXT];
14611     edit->text_hover        = table[NK_COLOR_TEXT];
14612     edit->text_active       = table[NK_COLOR_TEXT];
14613     edit->selected_normal   = table[NK_COLOR_TEXT];
14614     edit->selected_hover    = table[NK_COLOR_TEXT];
14615     edit->selected_text_normal  = table[NK_COLOR_EDIT];
14616     edit->selected_text_hover   = table[NK_COLOR_EDIT];
14617     edit->padding           = nk_vec2(0,0);
14618     edit->cursor_size       = 8;
14619     edit->border            = 0;
14620     edit->rounding          = 0;
14621 
14622     /* chart */
14623     chart = &style->chart;
14624     nk_zero_struct(*chart);
14625     chart->background       = nk_style_item_color(table[NK_COLOR_CHART]);
14626     chart->border_color     = table[NK_COLOR_BORDER];
14627     chart->selected_color   = table[NK_COLOR_CHART_COLOR_HIGHLIGHT];
14628     chart->color            = table[NK_COLOR_CHART_COLOR];
14629     chart->padding          = nk_vec2(4,4);
14630     chart->border           = 0;
14631     chart->rounding         = 0;
14632 
14633     /* combo */
14634     combo = &style->combo;
14635     combo->normal           = nk_style_item_color(table[NK_COLOR_COMBO]);
14636     combo->hover            = nk_style_item_color(table[NK_COLOR_COMBO]);
14637     combo->active           = nk_style_item_color(table[NK_COLOR_COMBO]);
14638     combo->border_color     = table[NK_COLOR_BORDER];
14639     combo->label_normal     = table[NK_COLOR_TEXT];
14640     combo->label_hover      = table[NK_COLOR_TEXT];
14641     combo->label_active     = table[NK_COLOR_TEXT];
14642     combo->sym_normal       = NK_SYMBOL_TRIANGLE_DOWN;
14643     combo->sym_hover        = NK_SYMBOL_TRIANGLE_DOWN;
14644     combo->sym_active       = NK_SYMBOL_TRIANGLE_DOWN;
14645     combo->content_padding  = nk_vec2(4,4);
14646     combo->button_padding   = nk_vec2(0,4);
14647     combo->spacing          = nk_vec2(4,0);
14648     combo->border           = 1;
14649     combo->rounding         = 0;
14650 
14651     /* combo button */
14652     button = &style->combo.button;
14653     nk_zero_struct(*button);
14654     button->normal          = nk_style_item_color(table[NK_COLOR_COMBO]);
14655     button->hover           = nk_style_item_color(table[NK_COLOR_COMBO]);
14656     button->active          = nk_style_item_color(table[NK_COLOR_COMBO]);
14657     button->border_color    = nk_rgba(0,0,0,0);
14658     button->text_background = table[NK_COLOR_COMBO];
14659     button->text_normal     = table[NK_COLOR_TEXT];
14660     button->text_hover      = table[NK_COLOR_TEXT];
14661     button->text_active     = table[NK_COLOR_TEXT];
14662     button->padding         = nk_vec2(2.0f,2.0f);
14663     button->touch_padding   = nk_vec2(0.0f,0.0f);
14664     button->userdata        = nk_handle_ptr(0);
14665     button->text_alignment  = NK_TEXT_CENTERED;
14666     button->border          = 0.0f;
14667     button->rounding        = 0.0f;
14668     button->draw_begin      = 0;
14669     button->draw_end        = 0;
14670 
14671     /* tab */
14672     tab = &style->tab;
14673     tab->background         = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
14674     tab->border_color       = table[NK_COLOR_BORDER];
14675     tab->text               = table[NK_COLOR_TEXT];
14676     tab->sym_minimize       = NK_SYMBOL_TRIANGLE_RIGHT;
14677     tab->sym_maximize       = NK_SYMBOL_TRIANGLE_DOWN;
14678     tab->padding            = nk_vec2(4,4);
14679     tab->spacing            = nk_vec2(4,4);
14680     tab->indent             = 10.0f;
14681     tab->border             = 1;
14682     tab->rounding           = 0;
14683 
14684     /* tab button */
14685     button = &style->tab.tab_minimize_button;
14686     nk_zero_struct(*button);
14687     button->normal          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
14688     button->hover           = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
14689     button->active          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
14690     button->border_color    = nk_rgba(0,0,0,0);
14691     button->text_background = table[NK_COLOR_TAB_HEADER];
14692     button->text_normal     = table[NK_COLOR_TEXT];
14693     button->text_hover      = table[NK_COLOR_TEXT];
14694     button->text_active     = table[NK_COLOR_TEXT];
14695     button->padding         = nk_vec2(2.0f,2.0f);
14696     button->touch_padding   = nk_vec2(0.0f,0.0f);
14697     button->userdata        = nk_handle_ptr(0);
14698     button->text_alignment  = NK_TEXT_CENTERED;
14699     button->border          = 0.0f;
14700     button->rounding        = 0.0f;
14701     button->draw_begin      = 0;
14702     button->draw_end        = 0;
14703     style->tab.tab_maximize_button =*button;
14704 
14705     /* node button */
14706     button = &style->tab.node_minimize_button;
14707     nk_zero_struct(*button);
14708     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
14709     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
14710     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
14711     button->border_color    = nk_rgba(0,0,0,0);
14712     button->text_background = table[NK_COLOR_TAB_HEADER];
14713     button->text_normal     = table[NK_COLOR_TEXT];
14714     button->text_hover      = table[NK_COLOR_TEXT];
14715     button->text_active     = table[NK_COLOR_TEXT];
14716     button->padding         = nk_vec2(2.0f,2.0f);
14717     button->touch_padding   = nk_vec2(0.0f,0.0f);
14718     button->userdata        = nk_handle_ptr(0);
14719     button->text_alignment  = NK_TEXT_CENTERED;
14720     button->border          = 0.0f;
14721     button->rounding        = 0.0f;
14722     button->draw_begin      = 0;
14723     button->draw_end        = 0;
14724     style->tab.node_maximize_button =*button;
14725 
14726     /* window header */
14727     win = &style->window;
14728     win->header.align = NK_HEADER_RIGHT;
14729     win->header.close_symbol = NK_SYMBOL_X;
14730     win->header.minimize_symbol = NK_SYMBOL_MINUS;
14731     win->header.maximize_symbol = NK_SYMBOL_PLUS;
14732     win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]);
14733     win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]);
14734     win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]);
14735     win->header.label_normal = table[NK_COLOR_TEXT];
14736     win->header.label_hover = table[NK_COLOR_TEXT];
14737     win->header.label_active = table[NK_COLOR_TEXT];
14738     win->header.label_padding = nk_vec2(4,4);
14739     win->header.padding = nk_vec2(4,4);
14740     win->header.spacing = nk_vec2(0,0);
14741 
14742     /* window header close button */
14743     button = &style->window.header.close_button;
14744     nk_zero_struct(*button);
14745     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
14746     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
14747     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
14748     button->border_color    = nk_rgba(0,0,0,0);
14749     button->text_background = table[NK_COLOR_HEADER];
14750     button->text_normal     = table[NK_COLOR_TEXT];
14751     button->text_hover      = table[NK_COLOR_TEXT];
14752     button->text_active     = table[NK_COLOR_TEXT];
14753     button->padding         = nk_vec2(0.0f,0.0f);
14754     button->touch_padding   = nk_vec2(0.0f,0.0f);
14755     button->userdata        = nk_handle_ptr(0);
14756     button->text_alignment  = NK_TEXT_CENTERED;
14757     button->border          = 0.0f;
14758     button->rounding        = 0.0f;
14759     button->draw_begin      = 0;
14760     button->draw_end        = 0;
14761 
14762     /* window header minimize button */
14763     button = &style->window.header.minimize_button;
14764     nk_zero_struct(*button);
14765     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
14766     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
14767     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
14768     button->border_color    = nk_rgba(0,0,0,0);
14769     button->text_background = table[NK_COLOR_HEADER];
14770     button->text_normal     = table[NK_COLOR_TEXT];
14771     button->text_hover      = table[NK_COLOR_TEXT];
14772     button->text_active     = table[NK_COLOR_TEXT];
14773     button->padding         = nk_vec2(0.0f,0.0f);
14774     button->touch_padding   = nk_vec2(0.0f,0.0f);
14775     button->userdata        = nk_handle_ptr(0);
14776     button->text_alignment  = NK_TEXT_CENTERED;
14777     button->border          = 0.0f;
14778     button->rounding        = 0.0f;
14779     button->draw_begin      = 0;
14780     button->draw_end        = 0;
14781 
14782     /* window */
14783     win->background = table[NK_COLOR_WINDOW];
14784     win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]);
14785     win->border_color = table[NK_COLOR_BORDER];
14786     win->popup_border_color = table[NK_COLOR_BORDER];
14787     win->combo_border_color = table[NK_COLOR_BORDER];
14788     win->contextual_border_color = table[NK_COLOR_BORDER];
14789     win->menu_border_color = table[NK_COLOR_BORDER];
14790     win->group_border_color = table[NK_COLOR_BORDER];
14791     win->tooltip_border_color = table[NK_COLOR_BORDER];
14792     win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
14793 
14794     win->rounding = 0.0f;
14795     win->spacing = nk_vec2(4,4);
14796     win->scrollbar_size = nk_vec2(10,10);
14797     win->min_size = nk_vec2(64,64);
14798 
14799     win->combo_border = 1.0f;
14800     win->contextual_border = 1.0f;
14801     win->menu_border = 1.0f;
14802     win->group_border = 1.0f;
14803     win->tooltip_border = 1.0f;
14804     win->popup_border = 1.0f;
14805     win->border = 2.0f;
14806     win->min_row_height_padding = 8;
14807 
14808     win->padding = nk_vec2(4,4);
14809     win->group_padding = nk_vec2(4,4);
14810     win->popup_padding = nk_vec2(4,4);
14811     win->combo_padding = nk_vec2(4,4);
14812     win->contextual_padding = nk_vec2(4,4);
14813     win->menu_padding = nk_vec2(4,4);
14814     win->tooltip_padding = nk_vec2(4,4);
14815 }
14816 NK_API void
14817 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
14818 {
14819     struct nk_style *style;
14820     NK_ASSERT(ctx);
14821 
14822     if (!ctx) return;
14823     style = &ctx->style;
14824     style->font = font;
14825     ctx->stacks.fonts.head = 0;
14826     if (ctx->current)
14827         nk_layout_reset_min_row_height(ctx);
14828 }
14829 NK_API int
14830 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
14831 {
14832     struct nk_config_stack_user_font *font_stack;
14833     struct nk_config_stack_user_font_element *element;
14834 
14835     NK_ASSERT(ctx);
14836     if (!ctx) return 0;
14837 
14838     font_stack = &ctx->stacks.fonts;
14839     NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
14840     if (font_stack->head >= (int)NK_LEN(font_stack->elements))
14841         return 0;
14842 
14843     element = &font_stack->elements[font_stack->head++];
14844     element->address = &ctx->style.font;
14845     element->old_value = ctx->style.font;
14846     ctx->style.font = font;
14847     return 1;
14848 }
14849 NK_API int
14850 nk_style_pop_font(struct nk_context *ctx)
14851 {
14852     struct nk_config_stack_user_font *font_stack;
14853     struct nk_config_stack_user_font_element *element;
14854 
14855     NK_ASSERT(ctx);
14856     if (!ctx) return 0;
14857 
14858     font_stack = &ctx->stacks.fonts;
14859     NK_ASSERT(font_stack->head > 0);
14860     if (font_stack->head < 1)
14861         return 0;
14862 
14863     element = &font_stack->elements[--font_stack->head];
14864     *element->address = element->old_value;
14865     return 1;
14866 }
14867 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
14868 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
14869 {\
14870     struct nk_config_stack_##type * type_stack;\
14871     struct nk_config_stack_##type##_element *element;\
14872     NK_ASSERT(ctx);\
14873     if (!ctx) return 0;\
14874     type_stack = &ctx->stacks.stack;\
14875     NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
14876     if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
14877         return 0;\
14878     element = &type_stack->elements[type_stack->head++];\
14879     element->address = address;\
14880     element->old_value = *address;\
14881     *address = value;\
14882     return 1;\
14883 }
14884 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
14885 nk_style_pop_##type(struct nk_context *ctx)\
14886 {\
14887     struct nk_config_stack_##type *type_stack;\
14888     struct nk_config_stack_##type##_element *element;\
14889     NK_ASSERT(ctx);\
14890     if (!ctx) return 0;\
14891     type_stack = &ctx->stacks.stack;\
14892     NK_ASSERT(type_stack->head > 0);\
14893     if (type_stack->head < 1)\
14894         return 0;\
14895     element = &type_stack->elements[--type_stack->head];\
14896     *element->address = element->old_value;\
14897     return 1;\
14898 }
14899 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
14900 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
14901 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
14902 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
14903 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
14904 
14905 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
14906 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
14907 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
14908 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
14909 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
14910 
14911 NK_API int
14912 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
14913 {
14914     struct nk_style *style;
14915     NK_ASSERT(ctx);
14916     if (!ctx) return 0;
14917     style = &ctx->style;
14918     if (style->cursors[c]) {
14919         style->cursor_active = style->cursors[c];
14920         return 1;
14921     }
14922     return 0;
14923 }
14924 NK_API void
14925 nk_style_show_cursor(struct nk_context *ctx)
14926 {
14927     ctx->style.cursor_visible = nk_true;
14928 }
14929 NK_API void
14930 nk_style_hide_cursor(struct nk_context *ctx)
14931 {
14932     ctx->style.cursor_visible = nk_false;
14933 }
14934 NK_API void
14935 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
14936     const struct nk_cursor *c)
14937 {
14938     struct nk_style *style;
14939     NK_ASSERT(ctx);
14940     if (!ctx) return;
14941     style = &ctx->style;
14942     style->cursors[cursor] = c;
14943 }
14944 NK_API void
14945 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors)
14946 {
14947     int i = 0;
14948     struct nk_style *style;
14949     NK_ASSERT(ctx);
14950     if (!ctx) return;
14951     style = &ctx->style;
14952     for (i = 0; i < NK_CURSOR_COUNT; ++i)
14953         style->cursors[i] = &cursors[i];
14954     style->cursor_visible = nk_true;
14955 }
14956 
14957 
14958 
14959 
14960 
14961 /* ==============================================================
14962  *
14963  *                          CONTEXT
14964  *
14965  * ===============================================================*/
14966 NK_INTERN void
14967 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
14968 {
14969     NK_ASSERT(ctx);
14970     if (!ctx) return;
14971     nk_zero_struct(*ctx);
14972     nk_style_default(ctx);
14973     ctx->seq = 1;
14974     if (font) ctx->style.font = font;
14975 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
14976     nk_draw_list_init(&ctx->draw_list);
14977 #endif
14978 }
14979 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
14980 NK_API int
14981 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
14982 {
14983     struct nk_allocator alloc;
14984     alloc.userdata.ptr = 0;
14985     alloc.alloc = nk_malloc;
14986     alloc.free = nk_mfree;
14987     return nk_init(ctx, &alloc, font);
14988 }
14989 #endif
14990 NK_API int
14991 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
14992     const struct nk_user_font *font)
14993 {
14994     NK_ASSERT(memory);
14995     if (!memory) return 0;
14996     nk_setup(ctx, font);
14997     nk_buffer_init_fixed(&ctx->memory, memory, size);
14998     ctx->use_pool = nk_false;
14999     return 1;
15000 }
15001 NK_API int
15002 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
15003     struct nk_buffer *pool, const struct nk_user_font *font)
15004 {
15005     NK_ASSERT(cmds);
15006     NK_ASSERT(pool);
15007     if (!cmds || !pool) return 0;
15008 
15009     nk_setup(ctx, font);
15010     ctx->memory = *cmds;
15011     if (pool->type == NK_BUFFER_FIXED) {
15012         /* take memory from buffer and alloc fixed pool */
15013         nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
15014     } else {
15015         /* create dynamic pool from buffer allocator */
15016         struct nk_allocator *alloc = &pool->pool;
15017         nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
15018     }
15019     ctx->use_pool = nk_true;
15020     return 1;
15021 }
15022 NK_API int
15023 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
15024     const struct nk_user_font *font)
15025 {
15026     NK_ASSERT(alloc);
15027     if (!alloc) return 0;
15028     nk_setup(ctx, font);
15029     nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
15030     nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
15031     ctx->use_pool = nk_true;
15032     return 1;
15033 }
15034 #ifdef NK_INCLUDE_COMMAND_USERDATA
15035 NK_API void
15036 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
15037 {
15038     if (!ctx) return;
15039     ctx->userdata = handle;
15040     if (ctx->current)
15041         ctx->current->buffer.userdata = handle;
15042 }
15043 #endif
15044 NK_API void
15045 nk_free(struct nk_context *ctx)
15046 {
15047     NK_ASSERT(ctx);
15048     if (!ctx) return;
15049     nk_buffer_free(&ctx->memory);
15050     if (ctx->use_pool)
15051         nk_pool_free(&ctx->pool);
15052 
15053     nk_zero(&ctx->input, sizeof(ctx->input));
15054     nk_zero(&ctx->style, sizeof(ctx->style));
15055     nk_zero(&ctx->memory, sizeof(ctx->memory));
15056 
15057     ctx->seq = 0;
15058     ctx->build = 0;
15059     ctx->begin = 0;
15060     ctx->end = 0;
15061     ctx->active = 0;
15062     ctx->current = 0;
15063     ctx->freelist = 0;
15064     ctx->count = 0;
15065 }
15066 NK_API void
15067 nk_clear(struct nk_context *ctx)
15068 {
15069     struct nk_window *iter;
15070     struct nk_window *next;
15071     NK_ASSERT(ctx);
15072 
15073     if (!ctx) return;
15074     if (ctx->use_pool)
15075         nk_buffer_clear(&ctx->memory);
15076     else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
15077 
15078     ctx->build = 0;
15079     ctx->memory.calls = 0;
15080     ctx->last_widget_state = 0;
15081     ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
15082     NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
15083 
15084     /* garbage collector */
15085     iter = ctx->begin;
15086     while (iter) {
15087         /* make sure valid minimized windows do not get removed */
15088         if ((iter->flags & NK_WINDOW_MINIMIZED) &&
15089             !(iter->flags & NK_WINDOW_CLOSED) &&
15090             iter->seq == ctx->seq) {
15091             iter = iter->next;
15092             continue;
15093         }
15094         /* remove hotness from hidden or closed windows*/
15095         if (((iter->flags & NK_WINDOW_HIDDEN) ||
15096             (iter->flags & NK_WINDOW_CLOSED)) &&
15097             iter == ctx->active) {
15098             ctx->active = iter->prev;
15099             ctx->end = iter->prev;
15100             if (!ctx->end)
15101                 ctx->begin = 0;
15102             if (ctx->active)
15103                 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
15104         }
15105         /* free unused popup windows */
15106         if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
15107             nk_free_window(ctx, iter->popup.win);
15108             iter->popup.win = 0;
15109         }
15110         /* remove unused window state tables */
15111         {struct nk_table *n, *it = iter->tables;
15112         while (it) {
15113             n = it->next;
15114             if (it->seq != ctx->seq) {
15115                 nk_remove_table(iter, it);
15116                 nk_zero(it, sizeof(union nk_page_data));
15117                 nk_free_table(ctx, it);
15118                 if (it == iter->tables)
15119                     iter->tables = n;
15120             } it = n;
15121         }}
15122         /* window itself is not used anymore so free */
15123         if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
15124             next = iter->next;
15125             nk_remove_window(ctx, iter);
15126             nk_free_window(ctx, iter);
15127             iter = next;
15128         } else iter = iter->next;
15129     }
15130     ctx->seq++;
15131 }
15132 NK_LIB void
15133 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
15134 {
15135     NK_ASSERT(ctx);
15136     NK_ASSERT(buffer);
15137     if (!ctx || !buffer) return;
15138     buffer->begin = ctx->memory.allocated;
15139     buffer->end = buffer->begin;
15140     buffer->last = buffer->begin;
15141     buffer->clip = nk_null_rect;
15142 }
15143 NK_LIB void
15144 nk_start(struct nk_context *ctx, struct nk_window *win)
15145 {
15146     NK_ASSERT(ctx);
15147     NK_ASSERT(win);
15148     nk_start_buffer(ctx, &win->buffer);
15149 }
15150 NK_LIB void
15151 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
15152 {
15153     struct nk_popup_buffer *buf;
15154     NK_ASSERT(ctx);
15155     NK_ASSERT(win);
15156     if (!ctx || !win) return;
15157 
15158     /* save buffer fill state for popup */
15159     buf = &win->popup.buf;
15160     buf->begin = win->buffer.end;
15161     buf->end = win->buffer.end;
15162     buf->parent = win->buffer.last;
15163     buf->last = buf->begin;
15164     buf->active = nk_true;
15165 }
15166 NK_LIB void
15167 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
15168 {
15169     struct nk_popup_buffer *buf;
15170     NK_ASSERT(ctx);
15171     NK_ASSERT(win);
15172     if (!ctx || !win) return;
15173 
15174     buf = &win->popup.buf;
15175     buf->last = win->buffer.last;
15176     buf->end = win->buffer.end;
15177 }
15178 NK_LIB void
15179 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
15180 {
15181     NK_ASSERT(ctx);
15182     NK_ASSERT(buffer);
15183     if (!ctx || !buffer) return;
15184     buffer->end = ctx->memory.allocated;
15185 }
15186 NK_LIB void
15187 nk_finish(struct nk_context *ctx, struct nk_window *win)
15188 {
15189     struct nk_popup_buffer *buf;
15190     struct nk_command *parent_last;
15191     void *memory;
15192 
15193     NK_ASSERT(ctx);
15194     NK_ASSERT(win);
15195     if (!ctx || !win) return;
15196     nk_finish_buffer(ctx, &win->buffer);
15197     if (!win->popup.buf.active) return;
15198 
15199     buf = &win->popup.buf;
15200     memory = ctx->memory.memory.ptr;
15201     parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
15202     parent_last->next = buf->end;
15203 }
15204 NK_LIB void
15205 nk_build(struct nk_context *ctx)
15206 {
15207     struct nk_window *it = 0;
15208     struct nk_command *cmd = 0;
15209     nk_byte *buffer = 0;
15210 
15211     /* draw cursor overlay */
15212     if (!ctx->style.cursor_active)
15213         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
15214     if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
15215         struct nk_rect mouse_bounds;
15216         const struct nk_cursor *cursor = ctx->style.cursor_active;
15217         nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
15218         nk_start_buffer(ctx, &ctx->overlay);
15219 
15220         mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
15221         mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
15222         mouse_bounds.w = cursor->size.x;
15223         mouse_bounds.h = cursor->size.y;
15224 
15225         nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
15226         nk_finish_buffer(ctx, &ctx->overlay);
15227     }
15228     /* build one big draw command list out of all window buffers */
15229     it = ctx->begin;
15230     buffer = (nk_byte*)ctx->memory.memory.ptr;
15231     while (it != 0) {
15232         struct nk_window *next = it->next;
15233         if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
15234             it->seq != ctx->seq)
15235             goto cont;
15236 
15237         cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
15238         while (next && ((next->buffer.last == next->buffer.begin) ||
15239             (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
15240             next = next->next; /* skip empty command buffers */
15241 
15242         if (next) cmd->next = next->buffer.begin;
15243         cont: it = next;
15244     }
15245     /* append all popup draw commands into lists */
15246     it = ctx->begin;
15247     while (it != 0) {
15248         struct nk_window *next = it->next;
15249         struct nk_popup_buffer *buf;
15250         if (!it->popup.buf.active)
15251             goto skip;
15252 
15253         buf = &it->popup.buf;
15254         cmd->next = buf->begin;
15255         cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
15256         buf->active = nk_false;
15257         skip: it = next;
15258     }
15259     if (cmd) {
15260         /* append overlay commands */
15261         if (ctx->overlay.end != ctx->overlay.begin)
15262             cmd->next = ctx->overlay.begin;
15263         else cmd->next = ctx->memory.allocated;
15264     }
15265 }
15266 NK_API const struct nk_command*
15267 nk__begin(struct nk_context *ctx)
15268 {
15269     struct nk_window *iter;
15270     nk_byte *buffer;
15271     NK_ASSERT(ctx);
15272     if (!ctx) return 0;
15273     if (!ctx->count) return 0;
15274 
15275     buffer = (nk_byte*)ctx->memory.memory.ptr;
15276     if (!ctx->build) {
15277         nk_build(ctx);
15278         ctx->build = nk_true;
15279     }
15280     iter = ctx->begin;
15281     while (iter && ((iter->buffer.begin == iter->buffer.end) ||
15282         (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
15283         iter = iter->next;
15284     if (!iter) return 0;
15285     return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
15286 }
15287 
15288 NK_API const struct nk_command*
15289 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
15290 {
15291     nk_byte *buffer;
15292     const struct nk_command *next;
15293     NK_ASSERT(ctx);
15294     if (!ctx || !cmd || !ctx->count) return 0;
15295     if (cmd->next >= ctx->memory.allocated) return 0;
15296     buffer = (nk_byte*)ctx->memory.memory.ptr;
15297     next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
15298     return next;
15299 }
15300 
15301 
15302 
15303 
15304 
15305 
15306 /* ===============================================================
15307  *
15308  *                              POOL
15309  *
15310  * ===============================================================*/
15311 NK_LIB void
15312 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
15313     unsigned int capacity)
15314 {
15315     nk_zero(pool, sizeof(*pool));
15316     pool->alloc = *alloc;
15317     pool->capacity = capacity;
15318     pool->type = NK_BUFFER_DYNAMIC;
15319     pool->pages = 0;
15320 }
15321 NK_LIB void
15322 nk_pool_free(struct nk_pool *pool)
15323 {
15324     struct nk_page *iter = pool->pages;
15325     if (!pool) return;
15326     if (pool->type == NK_BUFFER_FIXED) return;
15327     while (iter) {
15328         struct nk_page *next = iter->next;
15329         pool->alloc.free(pool->alloc.userdata, iter);
15330         iter = next;
15331     }
15332 }
15333 NK_LIB void
15334 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
15335 {
15336     nk_zero(pool, sizeof(*pool));
15337     NK_ASSERT(size >= sizeof(struct nk_page));
15338     if (size < sizeof(struct nk_page)) return;
15339     pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
15340     pool->pages = (struct nk_page*)memory;
15341     pool->type = NK_BUFFER_FIXED;
15342     pool->size = size;
15343 }
15344 NK_LIB struct nk_page_element*
15345 nk_pool_alloc(struct nk_pool *pool)
15346 {
15347     if (!pool->pages || pool->pages->size >= pool->capacity) {
15348         /* allocate new page */
15349         struct nk_page *page;
15350         if (pool->type == NK_BUFFER_FIXED) {
15351             NK_ASSERT(pool->pages);
15352             if (!pool->pages) return 0;
15353             NK_ASSERT(pool->pages->size < pool->capacity);
15354             return 0;
15355         } else {
15356             nk_size size = sizeof(struct nk_page);
15357             size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
15358             page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
15359             page->next = pool->pages;
15360             pool->pages = page;
15361             page->size = 0;
15362         }
15363     } return &pool->pages->win[pool->pages->size++];
15364 }
15365 
15366 
15367 
15368 
15369 
15370 /* ===============================================================
15371  *
15372  *                          PAGE ELEMENT
15373  *
15374  * ===============================================================*/
15375 NK_LIB struct nk_page_element*
15376 nk_create_page_element(struct nk_context *ctx)
15377 {
15378     struct nk_page_element *elem;
15379     if (ctx->freelist) {
15380         /* unlink page element from free list */
15381         elem = ctx->freelist;
15382         ctx->freelist = elem->next;
15383     } else if (ctx->use_pool) {
15384         /* allocate page element from memory pool */
15385         elem = nk_pool_alloc(&ctx->pool);
15386         NK_ASSERT(elem);
15387         if (!elem) return 0;
15388     } else {
15389         /* allocate new page element from back of fixed size memory buffer */
15390         NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
15391         NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
15392         elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
15393         NK_ASSERT(elem);
15394         if (!elem) return 0;
15395     }
15396     nk_zero_struct(*elem);
15397     elem->next = 0;
15398     elem->prev = 0;
15399     return elem;
15400 }
15401 NK_LIB void
15402 nk_link_page_element_into_freelist(struct nk_context *ctx,
15403     struct nk_page_element *elem)
15404 {
15405     /* link table into freelist */
15406     if (!ctx->freelist) {
15407         ctx->freelist = elem;
15408     } else {
15409         elem->next = ctx->freelist;
15410         ctx->freelist = elem;
15411     }
15412 }
15413 NK_LIB void
15414 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
15415 {
15416     /* we have a pool so just add to free list */
15417     if (ctx->use_pool) {
15418         nk_link_page_element_into_freelist(ctx, elem);
15419         return;
15420     }
15421     /* if possible remove last element from back of fixed memory buffer */
15422     {void *elem_end = (void*)(elem + 1);
15423     void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
15424     if (elem_end == buffer_end)
15425         ctx->memory.size -= sizeof(struct nk_page_element);
15426     else nk_link_page_element_into_freelist(ctx, elem);}
15427 }
15428 
15429 
15430 
15431 
15432 
15433 /* ===============================================================
15434  *
15435  *                              TABLE
15436  *
15437  * ===============================================================*/
15438 NK_LIB struct nk_table*
15439 nk_create_table(struct nk_context *ctx)
15440 {
15441     struct nk_page_element *elem;
15442     elem = nk_create_page_element(ctx);
15443     if (!elem) return 0;
15444     nk_zero_struct(*elem);
15445     return &elem->data.tbl;
15446 }
15447 NK_LIB void
15448 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
15449 {
15450     union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
15451     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
15452     nk_free_page_element(ctx, pe);
15453 }
15454 NK_LIB void
15455 nk_push_table(struct nk_window *win, struct nk_table *tbl)
15456 {
15457     if (!win->tables) {
15458         win->tables = tbl;
15459         tbl->next = 0;
15460         tbl->prev = 0;
15461         tbl->size = 0;
15462         win->table_count = 1;
15463         return;
15464     }
15465     win->tables->prev = tbl;
15466     tbl->next = win->tables;
15467     tbl->prev = 0;
15468     tbl->size = 0;
15469     win->tables = tbl;
15470     win->table_count++;
15471 }
15472 NK_LIB void
15473 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
15474 {
15475     if (win->tables == tbl)
15476         win->tables = tbl->next;
15477     if (tbl->next)
15478         tbl->next->prev = tbl->prev;
15479     if (tbl->prev)
15480         tbl->prev->next = tbl->next;
15481     tbl->next = 0;
15482     tbl->prev = 0;
15483 }
15484 NK_LIB nk_uint*
15485 nk_add_value(struct nk_context *ctx, struct nk_window *win,
15486             nk_hash name, nk_uint value)
15487 {
15488     NK_ASSERT(ctx);
15489     NK_ASSERT(win);
15490     if (!win || !ctx) return 0;
15491     if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
15492         struct nk_table *tbl = nk_create_table(ctx);
15493         NK_ASSERT(tbl);
15494         if (!tbl) return 0;
15495         nk_push_table(win, tbl);
15496     }
15497     win->tables->seq = win->seq;
15498     win->tables->keys[win->tables->size] = name;
15499     win->tables->values[win->tables->size] = value;
15500     return &win->tables->values[win->tables->size++];
15501 }
15502 NK_LIB nk_uint*
15503 nk_find_value(struct nk_window *win, nk_hash name)
15504 {
15505     struct nk_table *iter = win->tables;
15506     while (iter) {
15507         unsigned int i = 0;
15508         unsigned int size = iter->size;
15509         for (i = 0; i < size; ++i) {
15510             if (iter->keys[i] == name) {
15511                 iter->seq = win->seq;
15512                 return &iter->values[i];
15513             }
15514         } size = NK_VALUE_PAGE_CAPACITY;
15515         iter = iter->next;
15516     }
15517     return 0;
15518 }
15519 
15520 
15521 
15522 
15523 
15524 /* ===============================================================
15525  *
15526  *                              PANEL
15527  *
15528  * ===============================================================*/
15529 NK_LIB void*
15530 nk_create_panel(struct nk_context *ctx)
15531 {
15532     struct nk_page_element *elem;
15533     elem = nk_create_page_element(ctx);
15534     if (!elem) return 0;
15535     nk_zero_struct(*elem);
15536     return &elem->data.pan;
15537 }
15538 NK_LIB void
15539 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
15540 {
15541     union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
15542     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
15543     nk_free_page_element(ctx, pe);
15544 }
15545 NK_LIB int
15546 nk_panel_has_header(nk_flags flags, const char *title)
15547 {
15548     int active = 0;
15549     active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
15550     active = active || (flags & NK_WINDOW_TITLE);
15551     active = active && !(flags & NK_WINDOW_HIDDEN) && title;
15552     return active;
15553 }
15554 NK_LIB struct nk_vec2
15555 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
15556 {
15557     switch (type) {
15558     default:
15559     case NK_PANEL_WINDOW: return style->window.padding;
15560     case NK_PANEL_GROUP: return style->window.group_padding;
15561     case NK_PANEL_POPUP: return style->window.popup_padding;
15562     case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
15563     case NK_PANEL_COMBO: return style->window.combo_padding;
15564     case NK_PANEL_MENU: return style->window.menu_padding;
15565     case NK_PANEL_TOOLTIP: return style->window.menu_padding;}
15566 }
15567 NK_LIB float
15568 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
15569     enum nk_panel_type type)
15570 {
15571     if (flags & NK_WINDOW_BORDER) {
15572         switch (type) {
15573         default:
15574         case NK_PANEL_WINDOW: return style->window.border;
15575         case NK_PANEL_GROUP: return style->window.group_border;
15576         case NK_PANEL_POPUP: return style->window.popup_border;
15577         case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
15578         case NK_PANEL_COMBO: return style->window.combo_border;
15579         case NK_PANEL_MENU: return style->window.menu_border;
15580         case NK_PANEL_TOOLTIP: return style->window.menu_border;
15581     }} else return 0;
15582 }
15583 NK_LIB struct nk_color
15584 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
15585 {
15586     switch (type) {
15587     default:
15588     case NK_PANEL_WINDOW: return style->window.border_color;
15589     case NK_PANEL_GROUP: return style->window.group_border_color;
15590     case NK_PANEL_POPUP: return style->window.popup_border_color;
15591     case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
15592     case NK_PANEL_COMBO: return style->window.combo_border_color;
15593     case NK_PANEL_MENU: return style->window.menu_border_color;
15594     case NK_PANEL_TOOLTIP: return style->window.menu_border_color;}
15595 }
15596 NK_LIB int
15597 nk_panel_is_sub(enum nk_panel_type type)
15598 {
15599     return (type & NK_PANEL_SET_SUB)?1:0;
15600 }
15601 NK_LIB int
15602 nk_panel_is_nonblock(enum nk_panel_type type)
15603 {
15604     return (type & NK_PANEL_SET_NONBLOCK)?1:0;
15605 }
15606 NK_LIB int
15607 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
15608 {
15609     struct nk_input *in;
15610     struct nk_window *win;
15611     struct nk_panel *layout;
15612     struct nk_command_buffer *out;
15613     const struct nk_style *style;
15614     const struct nk_user_font *font;
15615 
15616     struct nk_vec2 scrollbar_size;
15617     struct nk_vec2 panel_padding;
15618 
15619     NK_ASSERT(ctx);
15620     NK_ASSERT(ctx->current);
15621     NK_ASSERT(ctx->current->layout);
15622     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
15623     nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
15624     if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
15625         nk_zero(ctx->current->layout, sizeof(struct nk_panel));
15626         ctx->current->layout->type = panel_type;
15627         return 0;
15628     }
15629     /* pull state into local stack */
15630     style = &ctx->style;
15631     font = style->font;
15632     win = ctx->current;
15633     layout = win->layout;
15634     out = &win->buffer;
15635     in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
15636 #ifdef NK_INCLUDE_COMMAND_USERDATA
15637     win->buffer.userdata = ctx->userdata;
15638 #endif
15639     /* pull style configuration into local stack */
15640     scrollbar_size = style->window.scrollbar_size;
15641     panel_padding = nk_panel_get_padding(style, panel_type);
15642 
15643     /* window movement */
15644     if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
15645         int left_mouse_down;
15646         int left_mouse_clicked;
15647         int left_mouse_click_in_cursor;
15648 
15649         /* calculate draggable window space */
15650         struct nk_rect header;
15651         header.x = win->bounds.x;
15652         header.y = win->bounds.y;
15653         header.w = win->bounds.w;
15654         if (nk_panel_has_header(win->flags, title)) {
15655             header.h = font->height + 2.0f * style->window.header.padding.y;
15656             header.h += 2.0f * style->window.header.label_padding.y;
15657         } else header.h = panel_padding.y;
15658 
15659         /* window movement by dragging */
15660         left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
15661         left_mouse_clicked = (int)in->mouse.buttons[NK_BUTTON_LEFT].clicked;
15662         left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
15663             NK_BUTTON_LEFT, header, nk_true);
15664         if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
15665             win->bounds.x = win->bounds.x + in->mouse.delta.x;
15666             win->bounds.y = win->bounds.y + in->mouse.delta.y;
15667             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
15668             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
15669             ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
15670         }
15671     }
15672 
15673     /* setup panel */
15674     layout->type = panel_type;
15675     layout->flags = win->flags;
15676     layout->bounds = win->bounds;
15677     layout->bounds.x += panel_padding.x;
15678     layout->bounds.w -= 2*panel_padding.x;
15679     if (win->flags & NK_WINDOW_BORDER) {
15680         layout->border = nk_panel_get_border(style, win->flags, panel_type);
15681         layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
15682     } else layout->border = 0;
15683     layout->at_y = layout->bounds.y;
15684     layout->at_x = layout->bounds.x;
15685     layout->max_x = 0;
15686     layout->header_height = 0;
15687     layout->footer_height = 0;
15688     nk_layout_reset_min_row_height(ctx);
15689     layout->row.index = 0;
15690     layout->row.columns = 0;
15691     layout->row.ratio = 0;
15692     layout->row.item_width = 0;
15693     layout->row.tree_depth = 0;
15694     layout->row.height = panel_padding.y;
15695     layout->has_scrolling = nk_true;
15696     if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
15697         layout->bounds.w -= scrollbar_size.x;
15698     if (!nk_panel_is_nonblock(panel_type)) {
15699         layout->footer_height = 0;
15700         if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
15701             layout->footer_height = scrollbar_size.y;
15702         layout->bounds.h -= layout->footer_height;
15703     }
15704 
15705     /* panel header */
15706     if (nk_panel_has_header(win->flags, title))
15707     {
15708         struct nk_text text;
15709         struct nk_rect header;
15710         const struct nk_style_item *background = 0;
15711 
15712         /* calculate header bounds */
15713         header.x = win->bounds.x;
15714         header.y = win->bounds.y;
15715         header.w = win->bounds.w;
15716         header.h = font->height + 2.0f * style->window.header.padding.y;
15717         header.h += (2.0f * style->window.header.label_padding.y);
15718 
15719         /* shrink panel by header */
15720         layout->header_height = header.h;
15721         layout->bounds.y += header.h;
15722         layout->bounds.h -= header.h;
15723         layout->at_y += header.h;
15724 
15725         /* select correct header background and text color */
15726         if (ctx->active == win) {
15727             background = &style->window.header.active;
15728             text.text = style->window.header.label_active;
15729         } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
15730             background = &style->window.header.hover;
15731             text.text = style->window.header.label_hover;
15732         } else {
15733             background = &style->window.header.normal;
15734             text.text = style->window.header.label_normal;
15735         }
15736 
15737         /* draw header background */
15738         header.h += 1.0f;
15739         if (background->type == NK_STYLE_ITEM_IMAGE) {
15740             text.background = nk_rgba(0,0,0,0);
15741             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
15742         } else {
15743             text.background = background->data.color;
15744             nk_fill_rect(out, header, 0, background->data.color);
15745         }
15746 
15747         /* window close button */
15748         {struct nk_rect button;
15749         button.y = header.y + style->window.header.padding.y;
15750         button.h = header.h - 2 * style->window.header.padding.y;
15751         button.w = button.h;
15752         if (win->flags & NK_WINDOW_CLOSABLE) {
15753             nk_flags ws = 0;
15754             if (style->window.header.align == NK_HEADER_RIGHT) {
15755                 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
15756                 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
15757             } else {
15758                 button.x = header.x + style->window.header.padding.x;
15759                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
15760             }
15761 
15762             if (nk_do_button_symbol(&ws, &win->buffer, button,
15763                 style->window.header.close_symbol, NK_BUTTON_DEFAULT,
15764                 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
15765             {
15766                 layout->flags |= NK_WINDOW_HIDDEN;
15767                 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
15768             }
15769         }
15770 
15771         /* window minimize button */
15772         if (win->flags & NK_WINDOW_MINIMIZABLE) {
15773             nk_flags ws = 0;
15774             if (style->window.header.align == NK_HEADER_RIGHT) {
15775                 button.x = (header.w + header.x) - button.w;
15776                 if (!(win->flags & NK_WINDOW_CLOSABLE)) {
15777                     button.x -= style->window.header.padding.x;
15778                     header.w -= style->window.header.padding.x;
15779                 }
15780                 header.w -= button.w + style->window.header.spacing.x;
15781             } else {
15782                 button.x = header.x;
15783                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
15784             }
15785             if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
15786                 style->window.header.maximize_symbol: style->window.header.minimize_symbol,
15787                 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
15788                 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
15789                     layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
15790                     layout->flags | NK_WINDOW_MINIMIZED;
15791         }}
15792 
15793         {/* window header title */
15794         int text_len = nk_strlen(title);
15795         struct nk_rect label = {0,0,0,0};
15796         float t = font->width(font->userdata, font->height, title, text_len);
15797         text.padding = nk_vec2(0,0);
15798 
15799         label.x = header.x + style->window.header.padding.x;
15800         label.x += style->window.header.label_padding.x;
15801         label.y = header.y + style->window.header.label_padding.y;
15802         label.h = font->height + 2 * style->window.header.label_padding.y;
15803         label.w = t + 2 * style->window.header.spacing.x;
15804         label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
15805         nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
15806     }
15807 
15808     /* draw window background */
15809     if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
15810         struct nk_rect body;
15811         body.x = win->bounds.x;
15812         body.w = win->bounds.w;
15813         body.y = (win->bounds.y + layout->header_height);
15814         body.h = (win->bounds.h - layout->header_height);
15815         if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE)
15816             nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
15817         else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
15818     }
15819 
15820     /* set clipping rectangle */
15821     {struct nk_rect clip;
15822     layout->clip = layout->bounds;
15823     nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
15824         layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
15825     nk_push_scissor(out, clip);
15826     layout->clip = clip;}
15827     return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
15828 }
15829 NK_LIB void
15830 nk_panel_end(struct nk_context *ctx)
15831 {
15832     struct nk_input *in;
15833     struct nk_window *window;
15834     struct nk_panel *layout;
15835     const struct nk_style *style;
15836     struct nk_command_buffer *out;
15837 
15838     struct nk_vec2 scrollbar_size;
15839     struct nk_vec2 panel_padding;
15840 
15841     NK_ASSERT(ctx);
15842     NK_ASSERT(ctx->current);
15843     NK_ASSERT(ctx->current->layout);
15844     if (!ctx || !ctx->current || !ctx->current->layout)
15845         return;
15846 
15847     window = ctx->current;
15848     layout = window->layout;
15849     style = &ctx->style;
15850     out = &window->buffer;
15851     in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
15852     if (!nk_panel_is_sub(layout->type))
15853         nk_push_scissor(out, nk_null_rect);
15854 
15855     /* cache configuration data */
15856     scrollbar_size = style->window.scrollbar_size;
15857     panel_padding = nk_panel_get_padding(style, layout->type);
15858 
15859     /* update the current cursor Y-position to point over the last added widget */
15860     layout->at_y += layout->row.height;
15861 
15862     /* dynamic panels */
15863     if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
15864     {
15865         /* update panel height to fit dynamic growth */
15866         struct nk_rect empty_space;
15867         if (layout->at_y < (layout->bounds.y + layout->bounds.h))
15868             layout->bounds.h = layout->at_y - layout->bounds.y;
15869 
15870         /* fill top empty space */
15871         empty_space.x = window->bounds.x;
15872         empty_space.y = layout->bounds.y;
15873         empty_space.h = panel_padding.y;
15874         empty_space.w = window->bounds.w;
15875         nk_fill_rect(out, empty_space, 0, style->window.background);
15876 
15877         /* fill left empty space */
15878         empty_space.x = window->bounds.x;
15879         empty_space.y = layout->bounds.y;
15880         empty_space.w = panel_padding.x + layout->border;
15881         empty_space.h = layout->bounds.h;
15882         nk_fill_rect(out, empty_space, 0, style->window.background);
15883 
15884         /* fill right empty space */
15885         empty_space.x = layout->bounds.x + layout->bounds.w;
15886         empty_space.y = layout->bounds.y;
15887         empty_space.w = panel_padding.x + layout->border;
15888         empty_space.h = layout->bounds.h;
15889         if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
15890             empty_space.w += scrollbar_size.x;
15891         nk_fill_rect(out, empty_space, 0, style->window.background);
15892 
15893         /* fill bottom empty space */
15894         if (layout->footer_height > 0) {
15895             empty_space.x = window->bounds.x;
15896             empty_space.y = layout->bounds.y + layout->bounds.h;
15897             empty_space.w = window->bounds.w;
15898             empty_space.h = layout->footer_height;
15899             nk_fill_rect(out, empty_space, 0, style->window.background);
15900         }
15901     }
15902 
15903     /* scrollbars */
15904     if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
15905         !(layout->flags & NK_WINDOW_MINIMIZED) &&
15906         window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
15907     {
15908         struct nk_rect scroll;
15909         int scroll_has_scrolling;
15910         float scroll_target;
15911         float scroll_offset;
15912         float scroll_step;
15913         float scroll_inc;
15914 
15915         /* mouse wheel scrolling */
15916         if (nk_panel_is_sub(layout->type))
15917         {
15918             /* sub-window mouse wheel scrolling */
15919             struct nk_window *root_window = window;
15920             struct nk_panel *root_panel = window->layout;
15921             while (root_panel->parent)
15922                 root_panel = root_panel->parent;
15923             while (root_window->parent)
15924                 root_window = root_window->parent;
15925 
15926             /* only allow scrolling if parent window is active */
15927             scroll_has_scrolling = 0;
15928             if ((root_window == ctx->active) && layout->has_scrolling) {
15929                 /* and panel is being hovered and inside clip rect*/
15930                 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
15931                     NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
15932                         root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
15933                 {
15934                     /* deactivate all parent scrolling */
15935                     root_panel = window->layout;
15936                     while (root_panel->parent) {
15937                         root_panel->has_scrolling = nk_false;
15938                         root_panel = root_panel->parent;
15939                     }
15940                     root_panel->has_scrolling = nk_false;
15941                     scroll_has_scrolling = nk_true;
15942                 }
15943             }
15944         } else if (!nk_panel_is_sub(layout->type)) {
15945             /* window mouse wheel scrolling */
15946             scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
15947             if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
15948                 window->scrolled = nk_true;
15949             else window->scrolled = nk_false;
15950         } else scroll_has_scrolling = nk_false;
15951 
15952         {
15953             /* vertical scrollbar */
15954             nk_flags state = 0;
15955             scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
15956             scroll.y = layout->bounds.y;
15957             scroll.w = scrollbar_size.x;
15958             scroll.h = layout->bounds.h;
15959 
15960             scroll_offset = (float)*layout->offset_y;
15961             scroll_step = scroll.h * 0.10f;
15962             scroll_inc = scroll.h * 0.01f;
15963             scroll_target = (float)(int)(layout->at_y - scroll.y);
15964             scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
15965                 scroll_offset, scroll_target, scroll_step, scroll_inc,
15966                 &ctx->style.scrollv, in, style->font);
15967             *layout->offset_y = (nk_uint)scroll_offset;
15968             if (in && scroll_has_scrolling)
15969                 in->mouse.scroll_delta.y = 0;
15970         }
15971         {
15972             /* horizontal scrollbar */
15973             nk_flags state = 0;
15974             scroll.x = layout->bounds.x;
15975             scroll.y = layout->bounds.y + layout->bounds.h;
15976             scroll.w = layout->bounds.w;
15977             scroll.h = scrollbar_size.y;
15978 
15979             scroll_offset = (float)*layout->offset_x;
15980             scroll_target = (float)(int)(layout->max_x - scroll.x);
15981             scroll_step = layout->max_x * 0.05f;
15982             scroll_inc = layout->max_x * 0.005f;
15983             scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
15984                 scroll_offset, scroll_target, scroll_step, scroll_inc,
15985                 &ctx->style.scrollh, in, style->font);
15986             *layout->offset_x = (nk_uint)scroll_offset;
15987         }
15988     }
15989 
15990     /* hide scroll if no user input */
15991     if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
15992         int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
15993         int is_window_hovered = nk_window_is_hovered(ctx);
15994         int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
15995         if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
15996             window->scrollbar_hiding_timer += ctx->delta_time_seconds;
15997         else window->scrollbar_hiding_timer = 0;
15998     } else window->scrollbar_hiding_timer = 0;
15999 
16000     /* window border */
16001     if (layout->flags & NK_WINDOW_BORDER)
16002     {
16003         struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
16004         const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED)
16005             ? (style->window.border + window->bounds.y + layout->header_height)
16006             : ((layout->flags & NK_WINDOW_DYNAMIC)
16007                 ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
16008                 : (window->bounds.y + window->bounds.h));
16009         struct nk_rect b = window->bounds;
16010         b.h = padding_y - window->bounds.y;
16011         nk_stroke_rect(out, b, 0, layout->border, border_color);
16012     }
16013 
16014     /* scaler */
16015     if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
16016     {
16017         /* calculate scaler bounds */
16018         struct nk_rect scaler;
16019         scaler.w = scrollbar_size.x;
16020         scaler.h = scrollbar_size.y;
16021         scaler.y = layout->bounds.y + layout->bounds.h;
16022         if (layout->flags & NK_WINDOW_SCALE_LEFT)
16023             scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
16024         else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
16025         if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
16026             scaler.x -= scaler.w;
16027 
16028         /* draw scaler */
16029         {const struct nk_style_item *item = &style->window.scaler;
16030         if (item->type == NK_STYLE_ITEM_IMAGE)
16031             nk_draw_image(out, scaler, &item->data.image, nk_white);
16032         else {
16033             if (layout->flags & NK_WINDOW_SCALE_LEFT) {
16034                 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
16035                     scaler.y + scaler.h, scaler.x + scaler.w,
16036                     scaler.y + scaler.h, item->data.color);
16037             } else {
16038                 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
16039                     scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
16040             }
16041         }}
16042 
16043         /* do window scaling */
16044         if (!(window->flags & NK_WINDOW_ROM)) {
16045             struct nk_vec2 window_size = style->window.min_size;
16046             int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
16047             int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
16048                     NK_BUTTON_LEFT, scaler, nk_true);
16049 
16050             if (left_mouse_down && left_mouse_click_in_scaler) {
16051                 float delta_x = in->mouse.delta.x;
16052                 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
16053                     delta_x = -delta_x;
16054                     window->bounds.x += in->mouse.delta.x;
16055                 }
16056                 /* dragging in x-direction  */
16057                 if (window->bounds.w + delta_x >= window_size.x) {
16058                     if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
16059                         window->bounds.w = window->bounds.w + delta_x;
16060                         scaler.x += in->mouse.delta.x;
16061                     }
16062                 }
16063                 /* dragging in y-direction (only possible if static window) */
16064                 if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
16065                     if (window_size.y < window->bounds.h + in->mouse.delta.y) {
16066                         if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
16067                             window->bounds.h = window->bounds.h + in->mouse.delta.y;
16068                             scaler.y += in->mouse.delta.y;
16069                         }
16070                     }
16071                 }
16072                 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
16073                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
16074                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
16075             }
16076         }
16077     }
16078     if (!nk_panel_is_sub(layout->type)) {
16079         /* window is hidden so clear command buffer  */
16080         if (layout->flags & NK_WINDOW_HIDDEN)
16081             nk_command_buffer_reset(&window->buffer);
16082         /* window is visible and not tab */
16083         else nk_finish(ctx, window);
16084     }
16085 
16086     /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
16087     if (layout->flags & NK_WINDOW_REMOVE_ROM) {
16088         layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
16089         layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
16090     }
16091     window->flags = layout->flags;
16092 
16093     /* property garbage collector */
16094     if (window->property.active && window->property.old != window->property.seq &&
16095         window->property.active == window->property.prev) {
16096         nk_zero(&window->property, sizeof(window->property));
16097     } else {
16098         window->property.old = window->property.seq;
16099         window->property.prev = window->property.active;
16100         window->property.seq = 0;
16101     }
16102     /* edit garbage collector */
16103     if (window->edit.active && window->edit.old != window->edit.seq &&
16104        window->edit.active == window->edit.prev) {
16105         nk_zero(&window->edit, sizeof(window->edit));
16106     } else {
16107         window->edit.old = window->edit.seq;
16108         window->edit.prev = window->edit.active;
16109         window->edit.seq = 0;
16110     }
16111     /* contextual garbage collector */
16112     if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
16113         window->popup.con_count = 0;
16114         window->popup.con_old = 0;
16115         window->popup.active_con = 0;
16116     } else {
16117         window->popup.con_old = window->popup.con_count;
16118         window->popup.con_count = 0;
16119     }
16120     window->popup.combo_count = 0;
16121     /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
16122     NK_ASSERT(!layout->row.tree_depth);
16123 }
16124 
16125 
16126 
16127 
16128 
16129 /* ===============================================================
16130  *
16131  *                              WINDOW
16132  *
16133  * ===============================================================*/
16134 NK_LIB void*
16135 nk_create_window(struct nk_context *ctx)
16136 {
16137     struct nk_page_element *elem;
16138     elem = nk_create_page_element(ctx);
16139     if (!elem) return 0;
16140     elem->data.win.seq = ctx->seq;
16141     return &elem->data.win;
16142 }
16143 NK_LIB void
16144 nk_free_window(struct nk_context *ctx, struct nk_window *win)
16145 {
16146     /* unlink windows from list */
16147     struct nk_table *it = win->tables;
16148     if (win->popup.win) {
16149         nk_free_window(ctx, win->popup.win);
16150         win->popup.win = 0;
16151     }
16152     win->next = 0;
16153     win->prev = 0;
16154 
16155     while (it) {
16156         /*free window state tables */
16157         struct nk_table *n = it->next;
16158         nk_remove_table(win, it);
16159         nk_free_table(ctx, it);
16160         if (it == win->tables)
16161             win->tables = n;
16162         it = n;
16163     }
16164 
16165     /* link windows into freelist */
16166     {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
16167     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
16168     nk_free_page_element(ctx, pe);}
16169 }
16170 NK_LIB struct nk_window*
16171 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
16172 {
16173     struct nk_window *iter;
16174     iter = ctx->begin;
16175     while (iter) {
16176         NK_ASSERT(iter != iter->next);
16177         if (iter->name == hash) {
16178             int max_len = nk_strlen(iter->name_string);
16179             if (!nk_stricmpn(iter->name_string, name, max_len))
16180                 return iter;
16181         }
16182         iter = iter->next;
16183     }
16184     return 0;
16185 }
16186 NK_LIB void
16187 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
16188     enum nk_window_insert_location loc)
16189 {
16190     const struct nk_window *iter;
16191     NK_ASSERT(ctx);
16192     NK_ASSERT(win);
16193     if (!win || !ctx) return;
16194 
16195     iter = ctx->begin;
16196     while (iter) {
16197         NK_ASSERT(iter != iter->next);
16198         NK_ASSERT(iter != win);
16199         if (iter == win) return;
16200         iter = iter->next;
16201     }
16202 
16203     if (!ctx->begin) {
16204         win->next = 0;
16205         win->prev = 0;
16206         ctx->begin = win;
16207         ctx->end = win;
16208         ctx->count = 1;
16209         return;
16210     }
16211     if (loc == NK_INSERT_BACK) {
16212         struct nk_window *end;
16213         end = ctx->end;
16214         end->flags |= NK_WINDOW_ROM;
16215         end->next = win;
16216         win->prev = ctx->end;
16217         win->next = 0;
16218         ctx->end = win;
16219         ctx->active = ctx->end;
16220         ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
16221     } else {
16222         /*ctx->end->flags |= NK_WINDOW_ROM;*/
16223         ctx->begin->prev = win;
16224         win->next = ctx->begin;
16225         win->prev = 0;
16226         ctx->begin = win;
16227         ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
16228     }
16229     ctx->count++;
16230 }
16231 NK_LIB void
16232 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
16233 {
16234     if (win == ctx->begin || win == ctx->end) {
16235         if (win == ctx->begin) {
16236             ctx->begin = win->next;
16237             if (win->next)
16238                 win->next->prev = 0;
16239         }
16240         if (win == ctx->end) {
16241             ctx->end = win->prev;
16242             if (win->prev)
16243                 win->prev->next = 0;
16244         }
16245     } else {
16246         if (win->next)
16247             win->next->prev = win->prev;
16248         if (win->prev)
16249             win->prev->next = win->next;
16250     }
16251     if (win == ctx->active || !ctx->active) {
16252         ctx->active = ctx->end;
16253         if (ctx->end)
16254             ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
16255     }
16256     win->next = 0;
16257     win->prev = 0;
16258     ctx->count--;
16259 }
16260 NK_API int
16261 nk_begin(struct nk_context *ctx, const char *title,
16262     struct nk_rect bounds, nk_flags flags)
16263 {
16264     return nk_begin_titled(ctx, title, title, bounds, flags);
16265 }
16266 NK_API int
16267 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
16268     struct nk_rect bounds, nk_flags flags)
16269 {
16270     struct nk_window *win;
16271     struct nk_style *style;
16272     nk_hash name_hash;
16273     int name_len;
16274     int ret = 0;
16275 
16276     NK_ASSERT(ctx);
16277     NK_ASSERT(name);
16278     NK_ASSERT(title);
16279     NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
16280     NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
16281     if (!ctx || ctx->current || !title || !name)
16282         return 0;
16283 
16284     /* find or create window */
16285     style = &ctx->style;
16286     name_len = (int)nk_strlen(name);
16287     name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE);
16288     win = nk_find_window(ctx, name_hash, name);
16289     if (!win) {
16290         /* create new window */
16291         nk_size name_length = (nk_size)name_len;
16292         win = (struct nk_window*)nk_create_window(ctx);
16293         NK_ASSERT(win);
16294         if (!win) return 0;
16295 
16296         if (flags & NK_WINDOW_BACKGROUND)
16297             nk_insert_window(ctx, win, NK_INSERT_FRONT);
16298         else nk_insert_window(ctx, win, NK_INSERT_BACK);
16299         nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
16300 
16301         win->flags = flags;
16302         win->bounds = bounds;
16303         win->name = name_hash;
16304         name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
16305         NK_MEMCPY(win->name_string, name, name_length);
16306         win->name_string[name_length] = 0;
16307         win->popup.win = 0;
16308         if (!ctx->active)
16309             ctx->active = win;
16310     } else {
16311         /* update window */
16312         win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
16313         win->flags |= flags;
16314         if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
16315             win->bounds = bounds;
16316         /* If this assert triggers you either:
16317          *
16318          * I.) Have more than one window with the same name or
16319          * II.) You forgot to actually draw the window.
16320          *      More specific you did not call `nk_clear` (nk_clear will be
16321          *      automatically called for you if you are using one of the
16322          *      provided demo backends). */
16323         NK_ASSERT(win->seq != ctx->seq);
16324         win->seq = ctx->seq;
16325         if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
16326             ctx->active = win;
16327             ctx->end = win;
16328         }
16329     }
16330     if (win->flags & NK_WINDOW_HIDDEN) {
16331         ctx->current = win;
16332         win->layout = 0;
16333         return 0;
16334     } else nk_start(ctx, win);
16335 
16336     /* window overlapping */
16337     if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
16338     {
16339         int inpanel, ishovered;
16340         struct nk_window *iter = win;
16341         float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
16342             (2.0f * style->window.header.label_padding.y);
16343         struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
16344             win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
16345 
16346         /* activate window if hovered and no other window is overlapping this window */
16347         inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
16348         inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
16349         ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
16350         if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
16351             iter = win->next;
16352             while (iter) {
16353                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
16354                     iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
16355                 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16356                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
16357                     (!(iter->flags & NK_WINDOW_HIDDEN)))
16358                     break;
16359 
16360                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
16361                     NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16362                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
16363                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
16364                     break;
16365                 iter = iter->next;
16366             }
16367         }
16368 
16369         /* activate window if clicked */
16370         if (iter && inpanel && (win != ctx->end)) {
16371             iter = win->next;
16372             while (iter) {
16373                 /* try to find a panel with higher priority in the same position */
16374                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
16375                 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
16376                 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
16377                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
16378                     !(iter->flags & NK_WINDOW_HIDDEN))
16379                     break;
16380                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
16381                     NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
16382                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
16383                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
16384                     break;
16385                 iter = iter->next;
16386             }
16387         }
16388         if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
16389             win->flags |= (nk_flags)NK_WINDOW_ROM;
16390             iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
16391             ctx->active = iter;
16392             if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
16393                 /* current window is active in that position so transfer to top
16394                  * at the highest priority in stack */
16395                 nk_remove_window(ctx, iter);
16396                 nk_insert_window(ctx, iter, NK_INSERT_BACK);
16397             }
16398         } else {
16399             if (!iter && ctx->end != win) {
16400                 if (!(win->flags & NK_WINDOW_BACKGROUND)) {
16401                     /* current window is active in that position so transfer to top
16402                      * at the highest priority in stack */
16403                     nk_remove_window(ctx, win);
16404                     nk_insert_window(ctx, win, NK_INSERT_BACK);
16405                 }
16406                 win->flags &= ~(nk_flags)NK_WINDOW_ROM;
16407                 ctx->active = win;
16408             }
16409             if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
16410                 win->flags |= NK_WINDOW_ROM;
16411         }
16412     }
16413     win->layout = (struct nk_panel*)nk_create_panel(ctx);
16414     ctx->current = win;
16415     ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
16416     win->layout->offset_x = &win->scrollbar.x;
16417     win->layout->offset_y = &win->scrollbar.y;
16418     return ret;
16419 }
16420 NK_API void
16421 nk_end(struct nk_context *ctx)
16422 {
16423     struct nk_panel *layout;
16424     NK_ASSERT(ctx);
16425     NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
16426     if (!ctx || !ctx->current)
16427         return;
16428 
16429     layout = ctx->current->layout;
16430     if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
16431         ctx->current = 0;
16432         return;
16433     }
16434     nk_panel_end(ctx);
16435     nk_free_panel(ctx, ctx->current->layout);
16436     ctx->current = 0;
16437 }
16438 NK_API struct nk_rect
16439 nk_window_get_bounds(const struct nk_context *ctx)
16440 {
16441     NK_ASSERT(ctx);
16442     NK_ASSERT(ctx->current);
16443     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
16444     return ctx->current->bounds;
16445 }
16446 NK_API struct nk_vec2
16447 nk_window_get_position(const struct nk_context *ctx)
16448 {
16449     NK_ASSERT(ctx);
16450     NK_ASSERT(ctx->current);
16451     if (!ctx || !ctx->current) return nk_vec2(0,0);
16452     return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
16453 }
16454 NK_API struct nk_vec2
16455 nk_window_get_size(const struct nk_context *ctx)
16456 {
16457     NK_ASSERT(ctx);
16458     NK_ASSERT(ctx->current);
16459     if (!ctx || !ctx->current) return nk_vec2(0,0);
16460     return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
16461 }
16462 NK_API float
16463 nk_window_get_width(const struct nk_context *ctx)
16464 {
16465     NK_ASSERT(ctx);
16466     NK_ASSERT(ctx->current);
16467     if (!ctx || !ctx->current) return 0;
16468     return ctx->current->bounds.w;
16469 }
16470 NK_API float
16471 nk_window_get_height(const struct nk_context *ctx)
16472 {
16473     NK_ASSERT(ctx);
16474     NK_ASSERT(ctx->current);
16475     if (!ctx || !ctx->current) return 0;
16476     return ctx->current->bounds.h;
16477 }
16478 NK_API struct nk_rect
16479 nk_window_get_content_region(struct nk_context *ctx)
16480 {
16481     NK_ASSERT(ctx);
16482     NK_ASSERT(ctx->current);
16483     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
16484     return ctx->current->layout->clip;
16485 }
16486 NK_API struct nk_vec2
16487 nk_window_get_content_region_min(struct nk_context *ctx)
16488 {
16489     NK_ASSERT(ctx);
16490     NK_ASSERT(ctx->current);
16491     NK_ASSERT(ctx->current->layout);
16492     if (!ctx || !ctx->current) return nk_vec2(0,0);
16493     return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
16494 }
16495 NK_API struct nk_vec2
16496 nk_window_get_content_region_max(struct nk_context *ctx)
16497 {
16498     NK_ASSERT(ctx);
16499     NK_ASSERT(ctx->current);
16500     NK_ASSERT(ctx->current->layout);
16501     if (!ctx || !ctx->current) return nk_vec2(0,0);
16502     return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
16503         ctx->current->layout->clip.y + ctx->current->layout->clip.h);
16504 }
16505 NK_API struct nk_vec2
16506 nk_window_get_content_region_size(struct nk_context *ctx)
16507 {
16508     NK_ASSERT(ctx);
16509     NK_ASSERT(ctx->current);
16510     NK_ASSERT(ctx->current->layout);
16511     if (!ctx || !ctx->current) return nk_vec2(0,0);
16512     return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
16513 }
16514 NK_API struct nk_command_buffer*
16515 nk_window_get_canvas(struct nk_context *ctx)
16516 {
16517     NK_ASSERT(ctx);
16518     NK_ASSERT(ctx->current);
16519     NK_ASSERT(ctx->current->layout);
16520     if (!ctx || !ctx->current) return 0;
16521     return &ctx->current->buffer;
16522 }
16523 NK_API struct nk_panel*
16524 nk_window_get_panel(struct nk_context *ctx)
16525 {
16526     NK_ASSERT(ctx);
16527     NK_ASSERT(ctx->current);
16528     if (!ctx || !ctx->current) return 0;
16529     return ctx->current->layout;
16530 }
16531 NK_API void
16532 nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
16533 {
16534     struct nk_window *win;
16535     NK_ASSERT(ctx);
16536     NK_ASSERT(ctx->current);
16537     if (!ctx || !ctx->current)
16538         return ;
16539     win = ctx->current;
16540     if (offset_x)
16541       *offset_x = win->scrollbar.x;
16542     if (offset_y)
16543       *offset_y = win->scrollbar.y;
16544 }
16545 NK_API int
16546 nk_window_has_focus(const struct nk_context *ctx)
16547 {
16548     NK_ASSERT(ctx);
16549     NK_ASSERT(ctx->current);
16550     NK_ASSERT(ctx->current->layout);
16551     if (!ctx || !ctx->current) return 0;
16552     return ctx->current == ctx->active;
16553 }
16554 NK_API int
16555 nk_window_is_hovered(struct nk_context *ctx)
16556 {
16557     NK_ASSERT(ctx);
16558     NK_ASSERT(ctx->current);
16559     if (!ctx || !ctx->current) return 0;
16560     if(ctx->current->flags & NK_WINDOW_HIDDEN)
16561         return 0;
16562     return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
16563 }
16564 NK_API int
16565 nk_window_is_any_hovered(struct nk_context *ctx)
16566 {
16567     struct nk_window *iter;
16568     NK_ASSERT(ctx);
16569     if (!ctx) return 0;
16570     iter = ctx->begin;
16571     while (iter) {
16572         /* check if window is being hovered */
16573         if(!(iter->flags & NK_WINDOW_HIDDEN)) {
16574             /* check if window popup is being hovered */
16575             if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
16576                 return 1;
16577 
16578             if (iter->flags & NK_WINDOW_MINIMIZED) {
16579                 struct nk_rect header = iter->bounds;
16580                 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
16581                 if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
16582                     return 1;
16583             } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
16584                 return 1;
16585             }
16586         }
16587         iter = iter->next;
16588     }
16589     return 0;
16590 }
16591 NK_API int
16592 nk_item_is_any_active(struct nk_context *ctx)
16593 {
16594     int any_hovered = nk_window_is_any_hovered(ctx);
16595     int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
16596     return any_hovered || any_active;
16597 }
16598 NK_API int
16599 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
16600 {
16601     int title_len;
16602     nk_hash title_hash;
16603     struct nk_window *win;
16604     NK_ASSERT(ctx);
16605     if (!ctx) return 0;
16606 
16607     title_len = (int)nk_strlen(name);
16608     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16609     win = nk_find_window(ctx, title_hash, name);
16610     if (!win) return 0;
16611     return win->flags & NK_WINDOW_MINIMIZED;
16612 }
16613 NK_API int
16614 nk_window_is_closed(struct nk_context *ctx, const char *name)
16615 {
16616     int title_len;
16617     nk_hash title_hash;
16618     struct nk_window *win;
16619     NK_ASSERT(ctx);
16620     if (!ctx) return 1;
16621 
16622     title_len = (int)nk_strlen(name);
16623     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16624     win = nk_find_window(ctx, title_hash, name);
16625     if (!win) return 1;
16626     return (win->flags & NK_WINDOW_CLOSED);
16627 }
16628 NK_API int
16629 nk_window_is_hidden(struct nk_context *ctx, const char *name)
16630 {
16631     int title_len;
16632     nk_hash title_hash;
16633     struct nk_window *win;
16634     NK_ASSERT(ctx);
16635     if (!ctx) return 1;
16636 
16637     title_len = (int)nk_strlen(name);
16638     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16639     win = nk_find_window(ctx, title_hash, name);
16640     if (!win) return 1;
16641     return (win->flags & NK_WINDOW_HIDDEN);
16642 }
16643 NK_API int
16644 nk_window_is_active(struct nk_context *ctx, const char *name)
16645 {
16646     int title_len;
16647     nk_hash title_hash;
16648     struct nk_window *win;
16649     NK_ASSERT(ctx);
16650     if (!ctx) return 0;
16651 
16652     title_len = (int)nk_strlen(name);
16653     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16654     win = nk_find_window(ctx, title_hash, name);
16655     if (!win) return 0;
16656     return win == ctx->active;
16657 }
16658 NK_API struct nk_window*
16659 nk_window_find(struct nk_context *ctx, const char *name)
16660 {
16661     int title_len;
16662     nk_hash title_hash;
16663     title_len = (int)nk_strlen(name);
16664     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16665     return nk_find_window(ctx, title_hash, name);
16666 }
16667 NK_API void
16668 nk_window_close(struct nk_context *ctx, const char *name)
16669 {
16670     struct nk_window *win;
16671     NK_ASSERT(ctx);
16672     if (!ctx) return;
16673     win = nk_window_find(ctx, name);
16674     if (!win) return;
16675     NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
16676     if (ctx->current == win) return;
16677     win->flags |= NK_WINDOW_HIDDEN;
16678     win->flags |= NK_WINDOW_CLOSED;
16679 }
16680 NK_API void
16681 nk_window_set_bounds(struct nk_context *ctx,
16682     const char *name, struct nk_rect bounds)
16683 {
16684     struct nk_window *win;
16685     NK_ASSERT(ctx);
16686     if (!ctx) return;
16687     win = nk_window_find(ctx, name);
16688     if (!win) return;
16689     NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
16690     win->bounds = bounds;
16691 }
16692 NK_API void
16693 nk_window_set_position(struct nk_context *ctx,
16694     const char *name, struct nk_vec2 pos)
16695 {
16696     struct nk_window *win = nk_window_find(ctx, name);
16697     if (!win) return;
16698     win->bounds.x = pos.x;
16699     win->bounds.y = pos.y;
16700 }
16701 NK_API void
16702 nk_window_set_size(struct nk_context *ctx,
16703     const char *name, struct nk_vec2 size)
16704 {
16705     struct nk_window *win = nk_window_find(ctx, name);
16706     if (!win) return;
16707     win->bounds.w = size.x;
16708     win->bounds.h = size.y;
16709 }
16710 NK_API void
16711 nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
16712 {
16713     struct nk_window *win;
16714     NK_ASSERT(ctx);
16715     NK_ASSERT(ctx->current);
16716     if (!ctx || !ctx->current)
16717         return;
16718     win = ctx->current;
16719     win->scrollbar.x = offset_x;
16720     win->scrollbar.y = offset_y;
16721 }
16722 NK_API void
16723 nk_window_collapse(struct nk_context *ctx, const char *name,
16724                     enum nk_collapse_states c)
16725 {
16726     int title_len;
16727     nk_hash title_hash;
16728     struct nk_window *win;
16729     NK_ASSERT(ctx);
16730     if (!ctx) return;
16731 
16732     title_len = (int)nk_strlen(name);
16733     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16734     win = nk_find_window(ctx, title_hash, name);
16735     if (!win) return;
16736     if (c == NK_MINIMIZED)
16737         win->flags |= NK_WINDOW_MINIMIZED;
16738     else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
16739 }
16740 NK_API void
16741 nk_window_collapse_if(struct nk_context *ctx, const char *name,
16742     enum nk_collapse_states c, int cond)
16743 {
16744     NK_ASSERT(ctx);
16745     if (!ctx || !cond) return;
16746     nk_window_collapse(ctx, name, c);
16747 }
16748 NK_API void
16749 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
16750 {
16751     int title_len;
16752     nk_hash title_hash;
16753     struct nk_window *win;
16754     NK_ASSERT(ctx);
16755     if (!ctx) return;
16756 
16757     title_len = (int)nk_strlen(name);
16758     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16759     win = nk_find_window(ctx, title_hash, name);
16760     if (!win) return;
16761     if (s == NK_HIDDEN) {
16762         win->flags |= NK_WINDOW_HIDDEN;
16763     } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
16764 }
16765 NK_API void
16766 nk_window_show_if(struct nk_context *ctx, const char *name,
16767     enum nk_show_states s, int cond)
16768 {
16769     NK_ASSERT(ctx);
16770     if (!ctx || !cond) return;
16771     nk_window_show(ctx, name, s);
16772 }
16773 
16774 NK_API void
16775 nk_window_set_focus(struct nk_context *ctx, const char *name)
16776 {
16777     int title_len;
16778     nk_hash title_hash;
16779     struct nk_window *win;
16780     NK_ASSERT(ctx);
16781     if (!ctx) return;
16782 
16783     title_len = (int)nk_strlen(name);
16784     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
16785     win = nk_find_window(ctx, title_hash, name);
16786     if (win && ctx->end != win) {
16787         nk_remove_window(ctx, win);
16788         nk_insert_window(ctx, win, NK_INSERT_BACK);
16789     }
16790     ctx->active = win;
16791 }
16792 
16793 
16794 
16795 
16796 /* ===============================================================
16797  *
16798  *                              POPUP
16799  *
16800  * ===============================================================*/
16801 NK_API int
16802 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
16803     const char *title, nk_flags flags, struct nk_rect rect)
16804 {
16805     struct nk_window *popup;
16806     struct nk_window *win;
16807     struct nk_panel *panel;
16808 
16809     int title_len;
16810     nk_hash title_hash;
16811     nk_size allocated;
16812 
16813     NK_ASSERT(ctx);
16814     NK_ASSERT(title);
16815     NK_ASSERT(ctx->current);
16816     NK_ASSERT(ctx->current->layout);
16817     if (!ctx || !ctx->current || !ctx->current->layout)
16818         return 0;
16819 
16820     win = ctx->current;
16821     panel = win->layout;
16822     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
16823     (void)panel;
16824     title_len = (int)nk_strlen(title);
16825     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
16826 
16827     popup = win->popup.win;
16828     if (!popup) {
16829         popup = (struct nk_window*)nk_create_window(ctx);
16830         popup->parent = win;
16831         win->popup.win = popup;
16832         win->popup.active = 0;
16833         win->popup.type = NK_PANEL_POPUP;
16834     }
16835 
16836     /* make sure we have correct popup */
16837     if (win->popup.name != title_hash) {
16838         if (!win->popup.active) {
16839             nk_zero(popup, sizeof(*popup));
16840             win->popup.name = title_hash;
16841             win->popup.active = 1;
16842             win->popup.type = NK_PANEL_POPUP;
16843         } else return 0;
16844     }
16845 
16846     /* popup position is local to window */
16847     ctx->current = popup;
16848     rect.x += win->layout->clip.x;
16849     rect.y += win->layout->clip.y;
16850 
16851     /* setup popup data */
16852     popup->parent = win;
16853     popup->bounds = rect;
16854     popup->seq = ctx->seq;
16855     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
16856     popup->flags = flags;
16857     popup->flags |= NK_WINDOW_BORDER;
16858     if (type == NK_POPUP_DYNAMIC)
16859         popup->flags |= NK_WINDOW_DYNAMIC;
16860 
16861     popup->buffer = win->buffer;
16862     nk_start_popup(ctx, win);
16863     allocated = ctx->memory.allocated;
16864     nk_push_scissor(&popup->buffer, nk_null_rect);
16865 
16866     if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
16867         /* popup is running therefore invalidate parent panels */
16868         struct nk_panel *root;
16869         root = win->layout;
16870         while (root) {
16871             root->flags |= NK_WINDOW_ROM;
16872             root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
16873             root = root->parent;
16874         }
16875         win->popup.active = 1;
16876         popup->layout->offset_x = &popup->scrollbar.x;
16877         popup->layout->offset_y = &popup->scrollbar.y;
16878         popup->layout->parent = win->layout;
16879         return 1;
16880     } else {
16881         /* popup was closed/is invalid so cleanup */
16882         struct nk_panel *root;
16883         root = win->layout;
16884         while (root) {
16885             root->flags |= NK_WINDOW_REMOVE_ROM;
16886             root = root->parent;
16887         }
16888         win->popup.buf.active = 0;
16889         win->popup.active = 0;
16890         ctx->memory.allocated = allocated;
16891         ctx->current = win;
16892         nk_free_panel(ctx, popup->layout);
16893         popup->layout = 0;
16894         return 0;
16895     }
16896 }
16897 NK_LIB int
16898 nk_nonblock_begin(struct nk_context *ctx,
16899     nk_flags flags, struct nk_rect body, struct nk_rect header,
16900     enum nk_panel_type panel_type)
16901 {
16902     struct nk_window *popup;
16903     struct nk_window *win;
16904     struct nk_panel *panel;
16905     int is_active = nk_true;
16906 
16907     NK_ASSERT(ctx);
16908     NK_ASSERT(ctx->current);
16909     NK_ASSERT(ctx->current->layout);
16910     if (!ctx || !ctx->current || !ctx->current->layout)
16911         return 0;
16912 
16913     /* popups cannot have popups */
16914     win = ctx->current;
16915     panel = win->layout;
16916     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
16917     (void)panel;
16918     popup = win->popup.win;
16919     if (!popup) {
16920         /* create window for nonblocking popup */
16921         popup = (struct nk_window*)nk_create_window(ctx);
16922         popup->parent = win;
16923         win->popup.win = popup;
16924         win->popup.type = panel_type;
16925         nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
16926     } else {
16927         /* close the popup if user pressed outside or in the header */
16928         int pressed, in_body, in_header;
16929 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
16930         pressed = nk_input_is_mouse_released(&ctx->input, NK_BUTTON_LEFT);
16931 #else
16932         pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
16933 #endif
16934         in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
16935         in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
16936         if (pressed && (!in_body || in_header))
16937             is_active = nk_false;
16938     }
16939     win->popup.header = header;
16940 
16941     if (!is_active) {
16942         /* remove read only mode from all parent panels */
16943         struct nk_panel *root = win->layout;
16944         while (root) {
16945             root->flags |= NK_WINDOW_REMOVE_ROM;
16946             root = root->parent;
16947         }
16948         return is_active;
16949     }
16950     popup->bounds = body;
16951     popup->parent = win;
16952     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
16953     popup->flags = flags;
16954     popup->flags |= NK_WINDOW_BORDER;
16955     popup->flags |= NK_WINDOW_DYNAMIC;
16956     popup->seq = ctx->seq;
16957     win->popup.active = 1;
16958     NK_ASSERT(popup->layout);
16959 
16960     nk_start_popup(ctx, win);
16961     popup->buffer = win->buffer;
16962     nk_push_scissor(&popup->buffer, nk_null_rect);
16963     ctx->current = popup;
16964 
16965     nk_panel_begin(ctx, 0, panel_type);
16966     win->buffer = popup->buffer;
16967     popup->layout->parent = win->layout;
16968     popup->layout->offset_x = &popup->scrollbar.x;
16969     popup->layout->offset_y = &popup->scrollbar.y;
16970 
16971     /* set read only mode to all parent panels */
16972     {struct nk_panel *root;
16973     root = win->layout;
16974     while (root) {
16975         root->flags |= NK_WINDOW_ROM;
16976         root = root->parent;
16977     }}
16978     return is_active;
16979 }
16980 NK_API void
16981 nk_popup_close(struct nk_context *ctx)
16982 {
16983     struct nk_window *popup;
16984     NK_ASSERT(ctx);
16985     if (!ctx || !ctx->current) return;
16986 
16987     popup = ctx->current;
16988     NK_ASSERT(popup->parent);
16989     NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
16990     popup->flags |= NK_WINDOW_HIDDEN;
16991 }
16992 NK_API void
16993 nk_popup_end(struct nk_context *ctx)
16994 {
16995     struct nk_window *win;
16996     struct nk_window *popup;
16997 
16998     NK_ASSERT(ctx);
16999     NK_ASSERT(ctx->current);
17000     NK_ASSERT(ctx->current->layout);
17001     if (!ctx || !ctx->current || !ctx->current->layout)
17002         return;
17003 
17004     popup = ctx->current;
17005     if (!popup->parent) return;
17006     win = popup->parent;
17007     if (popup->flags & NK_WINDOW_HIDDEN) {
17008         struct nk_panel *root;
17009         root = win->layout;
17010         while (root) {
17011             root->flags |= NK_WINDOW_REMOVE_ROM;
17012             root = root->parent;
17013         }
17014         win->popup.active = 0;
17015     }
17016     nk_push_scissor(&popup->buffer, nk_null_rect);
17017     nk_end(ctx);
17018 
17019     win->buffer = popup->buffer;
17020     nk_finish_popup(ctx, win);
17021     ctx->current = win;
17022     nk_push_scissor(&win->buffer, win->layout->clip);
17023 }
17024 NK_API void
17025 nk_popup_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
17026 {
17027     struct nk_window *popup;
17028 
17029     NK_ASSERT(ctx);
17030     NK_ASSERT(ctx->current);
17031     NK_ASSERT(ctx->current->layout);
17032     if (!ctx || !ctx->current || !ctx->current->layout)
17033         return;
17034 
17035     popup = ctx->current;
17036     if (offset_x)
17037       *offset_x = popup->scrollbar.x;
17038     if (offset_y)
17039       *offset_y = popup->scrollbar.y;
17040 }
17041 NK_API void
17042 nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
17043 {
17044     struct nk_window *popup;
17045 
17046     NK_ASSERT(ctx);
17047     NK_ASSERT(ctx->current);
17048     NK_ASSERT(ctx->current->layout);
17049     if (!ctx || !ctx->current || !ctx->current->layout)
17050         return;
17051 
17052     popup = ctx->current;
17053     popup->scrollbar.x = offset_x;
17054     popup->scrollbar.y = offset_y;
17055 }
17056 
17057 
17058 
17059 
17060 /* ==============================================================
17061  *
17062  *                          CONTEXTUAL
17063  *
17064  * ===============================================================*/
17065 NK_API int
17066 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
17067     struct nk_rect trigger_bounds)
17068 {
17069     struct nk_window *win;
17070     struct nk_window *popup;
17071     struct nk_rect body;
17072 
17073     NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0};
17074     int is_clicked = 0;
17075     int is_open = 0;
17076     int ret = 0;
17077 
17078     NK_ASSERT(ctx);
17079     NK_ASSERT(ctx->current);
17080     NK_ASSERT(ctx->current->layout);
17081     if (!ctx || !ctx->current || !ctx->current->layout)
17082         return 0;
17083 
17084     win = ctx->current;
17085     ++win->popup.con_count;
17086     if (ctx->current != ctx->active)
17087         return 0;
17088 
17089     /* check if currently active contextual is active */
17090     popup = win->popup.win;
17091     is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
17092     is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
17093     if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
17094         return 0;
17095     if (!is_open && win->popup.active_con)
17096         win->popup.active_con = 0;
17097     if ((!is_open && !is_clicked))
17098         return 0;
17099 
17100     /* calculate contextual position on click */
17101     win->popup.active_con = win->popup.con_count;
17102     if (is_clicked) {
17103         body.x = ctx->input.mouse.pos.x;
17104         body.y = ctx->input.mouse.pos.y;
17105     } else {
17106         body.x = popup->bounds.x;
17107         body.y = popup->bounds.y;
17108     }
17109     body.w = size.x;
17110     body.h = size.y;
17111 
17112     /* start nonblocking contextual popup */
17113     ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
17114             null_rect, NK_PANEL_CONTEXTUAL);
17115     if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
17116     else {
17117         win->popup.active_con = 0;
17118         win->popup.type = NK_PANEL_NONE;
17119         if (win->popup.win)
17120             win->popup.win->flags = 0;
17121     }
17122     return ret;
17123 }
17124 NK_API int
17125 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
17126     nk_flags alignment)
17127 {
17128     struct nk_window *win;
17129     const struct nk_input *in;
17130     const struct nk_style *style;
17131 
17132     struct nk_rect bounds;
17133     enum nk_widget_layout_states state;
17134 
17135     NK_ASSERT(ctx);
17136     NK_ASSERT(ctx->current);
17137     NK_ASSERT(ctx->current->layout);
17138     if (!ctx || !ctx->current || !ctx->current->layout)
17139         return 0;
17140 
17141     win = ctx->current;
17142     style = &ctx->style;
17143     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
17144     if (!state) return nk_false;
17145 
17146     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17147     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
17148         text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
17149         nk_contextual_close(ctx);
17150         return nk_true;
17151     }
17152     return nk_false;
17153 }
17154 NK_API int
17155 nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
17156 {
17157     return nk_contextual_item_text(ctx, label, nk_strlen(label), align);
17158 }
17159 NK_API int
17160 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
17161     const char *text, int len, nk_flags align)
17162 {
17163     struct nk_window *win;
17164     const struct nk_input *in;
17165     const struct nk_style *style;
17166 
17167     struct nk_rect bounds;
17168     enum nk_widget_layout_states state;
17169 
17170     NK_ASSERT(ctx);
17171     NK_ASSERT(ctx->current);
17172     NK_ASSERT(ctx->current->layout);
17173     if (!ctx || !ctx->current || !ctx->current->layout)
17174         return 0;
17175 
17176     win = ctx->current;
17177     style = &ctx->style;
17178     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
17179     if (!state) return nk_false;
17180 
17181     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17182     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
17183         img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
17184         nk_contextual_close(ctx);
17185         return nk_true;
17186     }
17187     return nk_false;
17188 }
17189 NK_API int
17190 nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
17191     const char *label, nk_flags align)
17192 {
17193     return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);
17194 }
17195 NK_API int
17196 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
17197     const char *text, int len, nk_flags align)
17198 {
17199     struct nk_window *win;
17200     const struct nk_input *in;
17201     const struct nk_style *style;
17202 
17203     struct nk_rect bounds;
17204     enum nk_widget_layout_states state;
17205 
17206     NK_ASSERT(ctx);
17207     NK_ASSERT(ctx->current);
17208     NK_ASSERT(ctx->current->layout);
17209     if (!ctx || !ctx->current || !ctx->current->layout)
17210         return 0;
17211 
17212     win = ctx->current;
17213     style = &ctx->style;
17214     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
17215     if (!state) return nk_false;
17216 
17217     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17218     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
17219         symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
17220         nk_contextual_close(ctx);
17221         return nk_true;
17222     }
17223     return nk_false;
17224 }
17225 NK_API int
17226 nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
17227     const char *text, nk_flags align)
17228 {
17229     return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);
17230 }
17231 NK_API void
17232 nk_contextual_close(struct nk_context *ctx)
17233 {
17234     NK_ASSERT(ctx);
17235     NK_ASSERT(ctx->current);
17236     NK_ASSERT(ctx->current->layout);
17237     if (!ctx || !ctx->current || !ctx->current->layout) return;
17238     nk_popup_close(ctx);
17239 }
17240 NK_API void
17241 nk_contextual_end(struct nk_context *ctx)
17242 {
17243     struct nk_window *popup;
17244     struct nk_panel *panel;
17245     NK_ASSERT(ctx);
17246     NK_ASSERT(ctx->current);
17247     if (!ctx || !ctx->current) return;
17248 
17249     popup = ctx->current;
17250     panel = popup->layout;
17251     NK_ASSERT(popup->parent);
17252     NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
17253     if (panel->flags & NK_WINDOW_DYNAMIC) {
17254         /* Close behavior
17255         This is a bit of a hack solution since we do not know before we end our popup
17256         how big it will be. We therefore do not directly know when a
17257         click outside the non-blocking popup must close it at that direct frame.
17258         Instead it will be closed in the next frame.*/
17259         struct nk_rect body = {0,0,0,0};
17260         if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
17261             struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
17262             body = panel->bounds;
17263             body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
17264             body.h = (panel->bounds.y + panel->bounds.h) - body.y;
17265         }
17266         {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
17267         int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
17268         if (pressed && in_body)
17269             popup->flags |= NK_WINDOW_HIDDEN;
17270         }
17271     }
17272     if (popup->flags & NK_WINDOW_HIDDEN)
17273         popup->seq = 0;
17274     nk_popup_end(ctx);
17275     return;
17276 }
17277 
17278 
17279 
17280 
17281 
17282 /* ===============================================================
17283  *
17284  *                              MENU
17285  *
17286  * ===============================================================*/
17287 NK_API void
17288 nk_menubar_begin(struct nk_context *ctx)
17289 {
17290     struct nk_panel *layout;
17291     NK_ASSERT(ctx);
17292     NK_ASSERT(ctx->current);
17293     NK_ASSERT(ctx->current->layout);
17294     if (!ctx || !ctx->current || !ctx->current->layout)
17295         return;
17296 
17297     layout = ctx->current->layout;
17298     NK_ASSERT(layout->at_y == layout->bounds.y);
17299     /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
17300     If you want a menubar the first nuklear function after `nk_begin` has to be a
17301     `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
17302     widgets (also supports multiple rows).
17303     Example:
17304         if (nk_begin(...)) {
17305             nk_menubar_begin(...);
17306                 nk_layout_xxxx(...);
17307                 nk_button(...);
17308                 nk_layout_xxxx(...);
17309                 nk_button(...);
17310             nk_menubar_end(...);
17311         }
17312         nk_end(...);
17313     */
17314     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
17315         return;
17316 
17317     layout->menu.x = layout->at_x;
17318     layout->menu.y = layout->at_y + layout->row.height;
17319     layout->menu.w = layout->bounds.w;
17320     layout->menu.offset.x = *layout->offset_x;
17321     layout->menu.offset.y = *layout->offset_y;
17322     *layout->offset_y = 0;
17323 }
17324 NK_API void
17325 nk_menubar_end(struct nk_context *ctx)
17326 {
17327     struct nk_window *win;
17328     struct nk_panel *layout;
17329     struct nk_command_buffer *out;
17330 
17331     NK_ASSERT(ctx);
17332     NK_ASSERT(ctx->current);
17333     NK_ASSERT(ctx->current->layout);
17334     if (!ctx || !ctx->current || !ctx->current->layout)
17335         return;
17336 
17337     win = ctx->current;
17338     out = &win->buffer;
17339     layout = win->layout;
17340     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
17341         return;
17342 
17343     layout->menu.h = layout->at_y - layout->menu.y;
17344     layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
17345     layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
17346 
17347     *layout->offset_x = layout->menu.offset.x;
17348     *layout->offset_y = layout->menu.offset.y;
17349     layout->at_y = layout->bounds.y - layout->row.height;
17350 
17351     layout->clip.y = layout->bounds.y;
17352     layout->clip.h = layout->bounds.h;
17353     nk_push_scissor(out, layout->clip);
17354 }
17355 NK_INTERN int
17356 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
17357     const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
17358 {
17359     int is_open = 0;
17360     int is_active = 0;
17361     struct nk_rect body;
17362     struct nk_window *popup;
17363     nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
17364 
17365     NK_ASSERT(ctx);
17366     NK_ASSERT(ctx->current);
17367     NK_ASSERT(ctx->current->layout);
17368     if (!ctx || !ctx->current || !ctx->current->layout)
17369         return 0;
17370 
17371     body.x = header.x;
17372     body.w = size.x;
17373     body.y = header.y + header.h;
17374     body.h = size.y;
17375 
17376     popup = win->popup.win;
17377     is_open = popup ? nk_true : nk_false;
17378     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
17379     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
17380         (!is_open && !is_active && !is_clicked)) return 0;
17381     if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
17382         return 0;
17383 
17384     win->popup.type = NK_PANEL_MENU;
17385     win->popup.name = hash;
17386     return 1;
17387 }
17388 NK_API int
17389 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
17390     nk_flags align, struct nk_vec2 size)
17391 {
17392     struct nk_window *win;
17393     const struct nk_input *in;
17394     struct nk_rect header;
17395     int is_clicked = nk_false;
17396     nk_flags state;
17397 
17398     NK_ASSERT(ctx);
17399     NK_ASSERT(ctx->current);
17400     NK_ASSERT(ctx->current->layout);
17401     if (!ctx || !ctx->current || !ctx->current->layout)
17402         return 0;
17403 
17404     win = ctx->current;
17405     state = nk_widget(&header, ctx);
17406     if (!state) return 0;
17407     in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17408     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
17409         title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
17410         is_clicked = nk_true;
17411     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17412 }
17413 NK_API int nk_menu_begin_label(struct nk_context *ctx,
17414     const char *text, nk_flags align, struct nk_vec2 size)
17415 {
17416     return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);
17417 }
17418 NK_API int
17419 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
17420     struct nk_vec2 size)
17421 {
17422     struct nk_window *win;
17423     struct nk_rect header;
17424     const struct nk_input *in;
17425     int is_clicked = nk_false;
17426     nk_flags state;
17427 
17428     NK_ASSERT(ctx);
17429     NK_ASSERT(ctx->current);
17430     NK_ASSERT(ctx->current->layout);
17431     if (!ctx || !ctx->current || !ctx->current->layout)
17432         return 0;
17433 
17434     win = ctx->current;
17435     state = nk_widget(&header, ctx);
17436     if (!state) return 0;
17437     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17438     if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
17439         img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
17440         is_clicked = nk_true;
17441     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
17442 }
17443 NK_API int
17444 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
17445     enum nk_symbol_type sym, struct nk_vec2 size)
17446 {
17447     struct nk_window *win;
17448     const struct nk_input *in;
17449     struct nk_rect header;
17450     int is_clicked = nk_false;
17451     nk_flags state;
17452 
17453     NK_ASSERT(ctx);
17454     NK_ASSERT(ctx->current);
17455     NK_ASSERT(ctx->current->layout);
17456     if (!ctx || !ctx->current || !ctx->current->layout)
17457         return 0;
17458 
17459     win = ctx->current;
17460     state = nk_widget(&header, ctx);
17461     if (!state) return 0;
17462     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17463     if (nk_do_button_symbol(&ctx->last_widget_state,  &win->buffer, header,
17464         sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
17465         is_clicked = nk_true;
17466     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
17467 }
17468 NK_API int
17469 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
17470     nk_flags align, struct nk_image img, struct nk_vec2 size)
17471 {
17472     struct nk_window *win;
17473     struct nk_rect header;
17474     const struct nk_input *in;
17475     int is_clicked = nk_false;
17476     nk_flags state;
17477 
17478     NK_ASSERT(ctx);
17479     NK_ASSERT(ctx->current);
17480     NK_ASSERT(ctx->current->layout);
17481     if (!ctx || !ctx->current || !ctx->current->layout)
17482         return 0;
17483 
17484     win = ctx->current;
17485     state = nk_widget(&header, ctx);
17486     if (!state) return 0;
17487     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17488     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
17489         header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
17490         ctx->style.font, in))
17491         is_clicked = nk_true;
17492     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17493 }
17494 NK_API int
17495 nk_menu_begin_image_label(struct nk_context *ctx,
17496     const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
17497 {
17498     return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);
17499 }
17500 NK_API int
17501 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
17502     nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
17503 {
17504     struct nk_window *win;
17505     struct nk_rect header;
17506     const struct nk_input *in;
17507     int is_clicked = nk_false;
17508     nk_flags state;
17509 
17510     NK_ASSERT(ctx);
17511     NK_ASSERT(ctx->current);
17512     NK_ASSERT(ctx->current->layout);
17513     if (!ctx || !ctx->current || !ctx->current->layout)
17514         return 0;
17515 
17516     win = ctx->current;
17517     state = nk_widget(&header, ctx);
17518     if (!state) return 0;
17519 
17520     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
17521     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
17522         header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
17523         ctx->style.font, in)) is_clicked = nk_true;
17524     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
17525 }
17526 NK_API int
17527 nk_menu_begin_symbol_label(struct nk_context *ctx,
17528     const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
17529 {
17530     return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);
17531 }
17532 NK_API int
17533 nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
17534 {
17535     return nk_contextual_item_text(ctx, title, len, align);
17536 }
17537 NK_API int
17538 nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
17539 {
17540     return nk_contextual_item_label(ctx, label, align);
17541 }
17542 NK_API int
17543 nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
17544     const char *label, nk_flags align)
17545 {
17546     return nk_contextual_item_image_label(ctx, img, label, align);
17547 }
17548 NK_API int
17549 nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
17550     const char *text, int len, nk_flags align)
17551 {
17552     return nk_contextual_item_image_text(ctx, img, text, len, align);
17553 }
17554 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
17555     const char *text, int len, nk_flags align)
17556 {
17557     return nk_contextual_item_symbol_text(ctx, sym, text, len, align);
17558 }
17559 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
17560     const char *label, nk_flags align)
17561 {
17562     return nk_contextual_item_symbol_label(ctx, sym, label, align);
17563 }
17564 NK_API void nk_menu_close(struct nk_context *ctx)
17565 {
17566     nk_contextual_close(ctx);
17567 }
17568 NK_API void
17569 nk_menu_end(struct nk_context *ctx)
17570 {
17571     nk_contextual_end(ctx);
17572 }
17573 
17574 
17575 
17576 
17577 
17578 /* ===============================================================
17579  *
17580  *                          LAYOUT
17581  *
17582  * ===============================================================*/
17583 NK_API void
17584 nk_layout_set_min_row_height(struct nk_context *ctx, float height)
17585 {
17586     struct nk_window *win;
17587     struct nk_panel *layout;
17588 
17589     NK_ASSERT(ctx);
17590     NK_ASSERT(ctx->current);
17591     NK_ASSERT(ctx->current->layout);
17592     if (!ctx || !ctx->current || !ctx->current->layout)
17593         return;
17594 
17595     win = ctx->current;
17596     layout = win->layout;
17597     layout->row.min_height = height;
17598 }
17599 NK_API void
17600 nk_layout_reset_min_row_height(struct nk_context *ctx)
17601 {
17602     struct nk_window *win;
17603     struct nk_panel *layout;
17604 
17605     NK_ASSERT(ctx);
17606     NK_ASSERT(ctx->current);
17607     NK_ASSERT(ctx->current->layout);
17608     if (!ctx || !ctx->current || !ctx->current->layout)
17609         return;
17610 
17611     win = ctx->current;
17612     layout = win->layout;
17613     layout->row.min_height = ctx->style.font->height;
17614     layout->row.min_height += ctx->style.text.padding.y*2;
17615     layout->row.min_height += ctx->style.window.min_row_height_padding*2;
17616 }
17617 NK_LIB float
17618 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
17619     float total_space, int columns)
17620 {
17621     float panel_padding;
17622     float panel_spacing;
17623     float panel_space;
17624 
17625     struct nk_vec2 spacing;
17626     struct nk_vec2 padding;
17627 
17628     spacing = style->window.spacing;
17629     padding = nk_panel_get_padding(style, type);
17630 
17631     /* calculate the usable panel space */
17632     panel_padding = 2 * padding.x;
17633     panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
17634     panel_space  = total_space - panel_padding - panel_spacing;
17635     return panel_space;
17636 }
17637 NK_LIB void
17638 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
17639     float height, int cols)
17640 {
17641     struct nk_panel *layout;
17642     const struct nk_style *style;
17643     struct nk_command_buffer *out;
17644 
17645     struct nk_vec2 item_spacing;
17646     struct nk_color color;
17647 
17648     NK_ASSERT(ctx);
17649     NK_ASSERT(ctx->current);
17650     NK_ASSERT(ctx->current->layout);
17651     if (!ctx || !ctx->current || !ctx->current->layout)
17652         return;
17653 
17654     /* prefetch some configuration data */
17655     layout = win->layout;
17656     style = &ctx->style;
17657     out = &win->buffer;
17658     color = style->window.background;
17659     item_spacing = style->window.spacing;
17660 
17661     /*  if one of these triggers you forgot to add an `if` condition around either
17662         a window, group, popup, combobox or contextual menu `begin` and `end` block.
17663         Example:
17664             if (nk_begin(...) {...} nk_end(...); or
17665             if (nk_group_begin(...) { nk_group_end(...);} */
17666     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
17667     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
17668     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
17669 
17670     /* update the current row and set the current row layout */
17671     layout->row.index = 0;
17672     layout->at_y += layout->row.height;
17673     layout->row.columns = cols;
17674     if (height == 0.0f)
17675         layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
17676     else layout->row.height = height + item_spacing.y;
17677 
17678     layout->row.item_offset = 0;
17679     if (layout->flags & NK_WINDOW_DYNAMIC) {
17680         /* draw background for dynamic panels */
17681         struct nk_rect background;
17682         background.x = win->bounds.x;
17683         background.w = win->bounds.w;
17684         background.y = layout->at_y - 1.0f;
17685         background.h = layout->row.height + 1.0f;
17686         nk_fill_rect(out, background, 0, color);
17687     }
17688 }
17689 NK_LIB void
17690 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
17691     float height, int cols, int width)
17692 {
17693     /* update the current row and set the current row layout */
17694     struct nk_window *win;
17695     NK_ASSERT(ctx);
17696     NK_ASSERT(ctx->current);
17697     NK_ASSERT(ctx->current->layout);
17698     if (!ctx || !ctx->current || !ctx->current->layout)
17699         return;
17700 
17701     win = ctx->current;
17702     nk_panel_layout(ctx, win, height, cols);
17703     if (fmt == NK_DYNAMIC)
17704         win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED;
17705     else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
17706 
17707     win->layout->row.ratio = 0;
17708     win->layout->row.filled = 0;
17709     win->layout->row.item_offset = 0;
17710     win->layout->row.item_width = (float)width;
17711 }
17712 NK_API float
17713 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
17714 {
17715     struct nk_window *win;
17716     NK_ASSERT(ctx);
17717     NK_ASSERT(pixel_width);
17718     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
17719     win = ctx->current;
17720     return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
17721 }
17722 NK_API void
17723 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
17724 {
17725     nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
17726 }
17727 NK_API void
17728 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
17729 {
17730     nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
17731 }
17732 NK_API void
17733 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
17734     float row_height, int cols)
17735 {
17736     struct nk_window *win;
17737     struct nk_panel *layout;
17738 
17739     NK_ASSERT(ctx);
17740     NK_ASSERT(ctx->current);
17741     NK_ASSERT(ctx->current->layout);
17742     if (!ctx || !ctx->current || !ctx->current->layout)
17743         return;
17744 
17745     win = ctx->current;
17746     layout = win->layout;
17747     nk_panel_layout(ctx, win, row_height, cols);
17748     if (fmt == NK_DYNAMIC)
17749         layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
17750     else layout->row.type = NK_LAYOUT_STATIC_ROW;
17751 
17752     layout->row.ratio = 0;
17753     layout->row.filled = 0;
17754     layout->row.item_width = 0;
17755     layout->row.item_offset = 0;
17756     layout->row.columns = cols;
17757 }
17758 NK_API void
17759 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
17760 {
17761     struct nk_window *win;
17762     struct nk_panel *layout;
17763 
17764     NK_ASSERT(ctx);
17765     NK_ASSERT(ctx->current);
17766     NK_ASSERT(ctx->current->layout);
17767     if (!ctx || !ctx->current || !ctx->current->layout)
17768         return;
17769 
17770     win = ctx->current;
17771     layout = win->layout;
17772     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
17773     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
17774         return;
17775 
17776     if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
17777         float ratio = ratio_or_width;
17778         if ((ratio + layout->row.filled) > 1.0f) return;
17779         if (ratio > 0.0f)
17780             layout->row.item_width = NK_SATURATE(ratio);
17781         else layout->row.item_width = 1.0f - layout->row.filled;
17782     } else layout->row.item_width = ratio_or_width;
17783 }
17784 NK_API void
17785 nk_layout_row_end(struct nk_context *ctx)
17786 {
17787     struct nk_window *win;
17788     struct nk_panel *layout;
17789 
17790     NK_ASSERT(ctx);
17791     NK_ASSERT(ctx->current);
17792     NK_ASSERT(ctx->current->layout);
17793     if (!ctx || !ctx->current || !ctx->current->layout)
17794         return;
17795 
17796     win = ctx->current;
17797     layout = win->layout;
17798     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
17799     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
17800         return;
17801     layout->row.item_width = 0;
17802     layout->row.item_offset = 0;
17803 }
17804 NK_API void
17805 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
17806     float height, int cols, const float *ratio)
17807 {
17808     int i;
17809     int n_undef = 0;
17810     struct nk_window *win;
17811     struct nk_panel *layout;
17812 
17813     NK_ASSERT(ctx);
17814     NK_ASSERT(ctx->current);
17815     NK_ASSERT(ctx->current->layout);
17816     if (!ctx || !ctx->current || !ctx->current->layout)
17817         return;
17818 
17819     win = ctx->current;
17820     layout = win->layout;
17821     nk_panel_layout(ctx, win, height, cols);
17822     if (fmt == NK_DYNAMIC) {
17823         /* calculate width of undefined widget ratios */
17824         float r = 0;
17825         layout->row.ratio = ratio;
17826         for (i = 0; i < cols; ++i) {
17827             if (ratio[i] < 0.0f)
17828                 n_undef++;
17829             else r += ratio[i];
17830         }
17831         r = NK_SATURATE(1.0f - r);
17832         layout->row.type = NK_LAYOUT_DYNAMIC;
17833         layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
17834     } else {
17835         layout->row.ratio = ratio;
17836         layout->row.type = NK_LAYOUT_STATIC;
17837         layout->row.item_width = 0;
17838         layout->row.item_offset = 0;
17839     }
17840     layout->row.item_offset = 0;
17841     layout->row.filled = 0;
17842 }
17843 NK_API void
17844 nk_layout_row_template_begin(struct nk_context *ctx, float height)
17845 {
17846     struct nk_window *win;
17847     struct nk_panel *layout;
17848 
17849     NK_ASSERT(ctx);
17850     NK_ASSERT(ctx->current);
17851     NK_ASSERT(ctx->current->layout);
17852     if (!ctx || !ctx->current || !ctx->current->layout)
17853         return;
17854 
17855     win = ctx->current;
17856     layout = win->layout;
17857     nk_panel_layout(ctx, win, height, 1);
17858     layout->row.type = NK_LAYOUT_TEMPLATE;
17859     layout->row.columns = 0;
17860     layout->row.ratio = 0;
17861     layout->row.item_width = 0;
17862     layout->row.item_height = 0;
17863     layout->row.item_offset = 0;
17864     layout->row.filled = 0;
17865     layout->row.item.x = 0;
17866     layout->row.item.y = 0;
17867     layout->row.item.w = 0;
17868     layout->row.item.h = 0;
17869 }
17870 NK_API void
17871 nk_layout_row_template_push_dynamic(struct nk_context *ctx)
17872 {
17873     struct nk_window *win;
17874     struct nk_panel *layout;
17875 
17876     NK_ASSERT(ctx);
17877     NK_ASSERT(ctx->current);
17878     NK_ASSERT(ctx->current->layout);
17879     if (!ctx || !ctx->current || !ctx->current->layout)
17880         return;
17881 
17882     win = ctx->current;
17883     layout = win->layout;
17884     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17885     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17886     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17887     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17888     layout->row.templates[layout->row.columns++] = -1.0f;
17889 }
17890 NK_API void
17891 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
17892 {
17893     struct nk_window *win;
17894     struct nk_panel *layout;
17895 
17896     NK_ASSERT(ctx);
17897     NK_ASSERT(ctx->current);
17898     NK_ASSERT(ctx->current->layout);
17899     if (!ctx || !ctx->current || !ctx->current->layout)
17900         return;
17901 
17902     win = ctx->current;
17903     layout = win->layout;
17904     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17905     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17906     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17907     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17908     layout->row.templates[layout->row.columns++] = -min_width;
17909 }
17910 NK_API void
17911 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
17912 {
17913     struct nk_window *win;
17914     struct nk_panel *layout;
17915 
17916     NK_ASSERT(ctx);
17917     NK_ASSERT(ctx->current);
17918     NK_ASSERT(ctx->current->layout);
17919     if (!ctx || !ctx->current || !ctx->current->layout)
17920         return;
17921 
17922     win = ctx->current;
17923     layout = win->layout;
17924     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17925     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
17926     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17927     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
17928     layout->row.templates[layout->row.columns++] = width;
17929 }
17930 NK_API void
17931 nk_layout_row_template_end(struct nk_context *ctx)
17932 {
17933     struct nk_window *win;
17934     struct nk_panel *layout;
17935 
17936     int i = 0;
17937     int variable_count = 0;
17938     int min_variable_count = 0;
17939     float min_fixed_width = 0.0f;
17940     float total_fixed_width = 0.0f;
17941     float max_variable_width = 0.0f;
17942 
17943     NK_ASSERT(ctx);
17944     NK_ASSERT(ctx->current);
17945     NK_ASSERT(ctx->current->layout);
17946     if (!ctx || !ctx->current || !ctx->current->layout)
17947         return;
17948 
17949     win = ctx->current;
17950     layout = win->layout;
17951     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
17952     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
17953     for (i = 0; i < layout->row.columns; ++i) {
17954         float width = layout->row.templates[i];
17955         if (width >= 0.0f) {
17956             total_fixed_width += width;
17957             min_fixed_width += width;
17958         } else if (width < -1.0f) {
17959             width = -width;
17960             total_fixed_width += width;
17961             max_variable_width = NK_MAX(max_variable_width, width);
17962             variable_count++;
17963         } else {
17964             min_variable_count++;
17965             variable_count++;
17966         }
17967     }
17968     if (variable_count) {
17969         float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
17970                             layout->bounds.w, layout->row.columns);
17971         float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
17972         int enough_space = var_width >= max_variable_width;
17973         if (!enough_space)
17974             var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
17975         for (i = 0; i < layout->row.columns; ++i) {
17976             float *width = &layout->row.templates[i];
17977             *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
17978         }
17979     }
17980 }
17981 NK_API void
17982 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
17983     float height, int widget_count)
17984 {
17985     struct nk_window *win;
17986     struct nk_panel *layout;
17987 
17988     NK_ASSERT(ctx);
17989     NK_ASSERT(ctx->current);
17990     NK_ASSERT(ctx->current->layout);
17991     if (!ctx || !ctx->current || !ctx->current->layout)
17992         return;
17993 
17994     win = ctx->current;
17995     layout = win->layout;
17996     nk_panel_layout(ctx, win, height, widget_count);
17997     if (fmt == NK_STATIC)
17998         layout->row.type = NK_LAYOUT_STATIC_FREE;
17999     else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
18000 
18001     layout->row.ratio = 0;
18002     layout->row.filled = 0;
18003     layout->row.item_width = 0;
18004     layout->row.item_offset = 0;
18005 }
18006 NK_API void
18007 nk_layout_space_end(struct nk_context *ctx)
18008 {
18009     struct nk_window *win;
18010     struct nk_panel *layout;
18011 
18012     NK_ASSERT(ctx);
18013     NK_ASSERT(ctx->current);
18014     NK_ASSERT(ctx->current->layout);
18015     if (!ctx || !ctx->current || !ctx->current->layout)
18016         return;
18017 
18018     win = ctx->current;
18019     layout = win->layout;
18020     layout->row.item_width = 0;
18021     layout->row.item_height = 0;
18022     layout->row.item_offset = 0;
18023     nk_zero(&layout->row.item, sizeof(layout->row.item));
18024 }
18025 NK_API void
18026 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
18027 {
18028     struct nk_window *win;
18029     struct nk_panel *layout;
18030 
18031     NK_ASSERT(ctx);
18032     NK_ASSERT(ctx->current);
18033     NK_ASSERT(ctx->current->layout);
18034     if (!ctx || !ctx->current || !ctx->current->layout)
18035         return;
18036 
18037     win = ctx->current;
18038     layout = win->layout;
18039     layout->row.item = rect;
18040 }
18041 NK_API struct nk_rect
18042 nk_layout_space_bounds(struct nk_context *ctx)
18043 {
18044     struct nk_rect ret;
18045     struct nk_window *win;
18046     struct nk_panel *layout;
18047 
18048     NK_ASSERT(ctx);
18049     NK_ASSERT(ctx->current);
18050     NK_ASSERT(ctx->current->layout);
18051     win = ctx->current;
18052     layout = win->layout;
18053 
18054     ret.x = layout->clip.x;
18055     ret.y = layout->clip.y;
18056     ret.w = layout->clip.w;
18057     ret.h = layout->row.height;
18058     return ret;
18059 }
18060 NK_API struct nk_rect
18061 nk_layout_widget_bounds(struct nk_context *ctx)
18062 {
18063     struct nk_rect ret;
18064     struct nk_window *win;
18065     struct nk_panel *layout;
18066 
18067     NK_ASSERT(ctx);
18068     NK_ASSERT(ctx->current);
18069     NK_ASSERT(ctx->current->layout);
18070     win = ctx->current;
18071     layout = win->layout;
18072 
18073     ret.x = layout->at_x;
18074     ret.y = layout->at_y;
18075     ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
18076     ret.h = layout->row.height;
18077     return ret;
18078 }
18079 NK_API struct nk_vec2
18080 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
18081 {
18082     struct nk_window *win;
18083     struct nk_panel *layout;
18084 
18085     NK_ASSERT(ctx);
18086     NK_ASSERT(ctx->current);
18087     NK_ASSERT(ctx->current->layout);
18088     win = ctx->current;
18089     layout = win->layout;
18090 
18091     ret.x += layout->at_x - (float)*layout->offset_x;
18092     ret.y += layout->at_y - (float)*layout->offset_y;
18093     return ret;
18094 }
18095 NK_API struct nk_vec2
18096 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
18097 {
18098     struct nk_window *win;
18099     struct nk_panel *layout;
18100 
18101     NK_ASSERT(ctx);
18102     NK_ASSERT(ctx->current);
18103     NK_ASSERT(ctx->current->layout);
18104     win = ctx->current;
18105     layout = win->layout;
18106 
18107     ret.x += -layout->at_x + (float)*layout->offset_x;
18108     ret.y += -layout->at_y + (float)*layout->offset_y;
18109     return ret;
18110 }
18111 NK_API struct nk_rect
18112 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret)
18113 {
18114     struct nk_window *win;
18115     struct nk_panel *layout;
18116 
18117     NK_ASSERT(ctx);
18118     NK_ASSERT(ctx->current);
18119     NK_ASSERT(ctx->current->layout);
18120     win = ctx->current;
18121     layout = win->layout;
18122 
18123     ret.x += layout->at_x - (float)*layout->offset_x;
18124     ret.y += layout->at_y - (float)*layout->offset_y;
18125     return ret;
18126 }
18127 NK_API struct nk_rect
18128 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret)
18129 {
18130     struct nk_window *win;
18131     struct nk_panel *layout;
18132 
18133     NK_ASSERT(ctx);
18134     NK_ASSERT(ctx->current);
18135     NK_ASSERT(ctx->current->layout);
18136     win = ctx->current;
18137     layout = win->layout;
18138 
18139     ret.x += -layout->at_x + (float)*layout->offset_x;
18140     ret.y += -layout->at_y + (float)*layout->offset_y;
18141     return ret;
18142 }
18143 NK_LIB void
18144 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
18145 {
18146     struct nk_panel *layout = win->layout;
18147     struct nk_vec2 spacing = ctx->style.window.spacing;
18148     const float row_height = layout->row.height - spacing.y;
18149     nk_panel_layout(ctx, win, row_height, layout->row.columns);
18150 }
18151 NK_LIB void
18152 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
18153     struct nk_window *win, int modify)
18154 {
18155     struct nk_panel *layout;
18156     const struct nk_style *style;
18157 
18158     struct nk_vec2 spacing;
18159     struct nk_vec2 padding;
18160 
18161     float item_offset = 0;
18162     float item_width = 0;
18163     float item_spacing = 0;
18164     float panel_space = 0;
18165 
18166     NK_ASSERT(ctx);
18167     NK_ASSERT(ctx->current);
18168     NK_ASSERT(ctx->current->layout);
18169     if (!ctx || !ctx->current || !ctx->current->layout)
18170         return;
18171 
18172     win = ctx->current;
18173     layout = win->layout;
18174     style = &ctx->style;
18175     NK_ASSERT(bounds);
18176 
18177     spacing = style->window.spacing;
18178     padding = nk_panel_get_padding(style, layout->type);
18179     panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
18180                                             layout->bounds.w, layout->row.columns);
18181 
18182     #define NK_FRAC(x) (x - (int)x) /* will be used to remove fookin gaps */
18183     /* calculate the width of one item inside the current layout space */
18184     switch (layout->row.type) {
18185     case NK_LAYOUT_DYNAMIC_FIXED: {
18186         /* scaling fixed size widgets item width */
18187         float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns;
18188         item_offset = (float)layout->row.index * w;
18189         item_width = w + NK_FRAC(item_offset);
18190         item_spacing = (float)layout->row.index * spacing.x;
18191     } break;
18192     case NK_LAYOUT_DYNAMIC_ROW: {
18193         /* scaling single ratio widget width */
18194         float w = layout->row.item_width * panel_space;
18195         item_offset = layout->row.item_offset;
18196         item_width = w + NK_FRAC(item_offset);
18197         item_spacing = 0;
18198 
18199         if (modify) {
18200             layout->row.item_offset += w + spacing.x;
18201             layout->row.filled += layout->row.item_width;
18202             layout->row.index = 0;
18203         }
18204     } break;
18205     case NK_LAYOUT_DYNAMIC_FREE: {
18206         /* panel width depended free widget placing */
18207         bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
18208         bounds->x -= (float)*layout->offset_x;
18209         bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
18210         bounds->y -= (float)*layout->offset_y;
18211         bounds->w = layout->bounds.w  * layout->row.item.w + NK_FRAC(bounds->x);
18212         bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y);
18213         return;
18214     }
18215     case NK_LAYOUT_DYNAMIC: {
18216         /* scaling arrays of panel width ratios for every widget */
18217         float ratio, w;
18218         NK_ASSERT(layout->row.ratio);
18219         ratio = (layout->row.ratio[layout->row.index] < 0) ?
18220             layout->row.item_width : layout->row.ratio[layout->row.index];
18221 
18222         w = (ratio * panel_space);
18223         item_spacing = (float)layout->row.index * spacing.x;
18224         item_offset = layout->row.item_offset;
18225         item_width = w + NK_FRAC(item_offset);
18226 
18227         if (modify) {
18228             layout->row.item_offset += w;
18229             layout->row.filled += ratio;
18230         }
18231     } break;
18232     case NK_LAYOUT_STATIC_FIXED: {
18233         /* non-scaling fixed widgets item width */
18234         item_width = layout->row.item_width;
18235         item_offset = (float)layout->row.index * item_width;
18236         item_spacing = (float)layout->row.index * spacing.x;
18237     } break;
18238     case NK_LAYOUT_STATIC_ROW: {
18239         /* scaling single ratio widget width */
18240         item_width = layout->row.item_width;
18241         item_offset = layout->row.item_offset;
18242         item_spacing = (float)layout->row.index * spacing.x;
18243         if (modify) layout->row.item_offset += item_width;
18244     } break;
18245     case NK_LAYOUT_STATIC_FREE: {
18246         /* free widget placing */
18247         bounds->x = layout->at_x + layout->row.item.x;
18248         bounds->w = layout->row.item.w;
18249         if (((bounds->x + bounds->w) > layout->max_x) && modify)
18250             layout->max_x = (bounds->x + bounds->w);
18251         bounds->x -= (float)*layout->offset_x;
18252         bounds->y = layout->at_y + layout->row.item.y;
18253         bounds->y -= (float)*layout->offset_y;
18254         bounds->h = layout->row.item.h;
18255         return;
18256     }
18257     case NK_LAYOUT_STATIC: {
18258         /* non-scaling array of panel pixel width for every widget */
18259         item_spacing = (float)layout->row.index * spacing.x;
18260         item_width = layout->row.ratio[layout->row.index];
18261         item_offset = layout->row.item_offset;
18262         if (modify) layout->row.item_offset += item_width;
18263     } break;
18264     case NK_LAYOUT_TEMPLATE: {
18265         /* stretchy row layout with combined dynamic/static widget width*/
18266         float w;
18267         NK_ASSERT(layout->row.index < layout->row.columns);
18268         NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
18269         w = layout->row.templates[layout->row.index];
18270         item_offset = layout->row.item_offset;
18271         item_width = w + NK_FRAC(item_offset);
18272         item_spacing = (float)layout->row.index * spacing.x;
18273         if (modify) layout->row.item_offset += w;
18274     } break;
18275     #undef NK_FRAC
18276     default: NK_ASSERT(0); break;
18277     };
18278 
18279     /* set the bounds of the newly allocated widget */
18280     bounds->w = item_width;
18281     bounds->h = layout->row.height - spacing.y;
18282     bounds->y = layout->at_y - (float)*layout->offset_y;
18283     bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
18284     if (((bounds->x + bounds->w) > layout->max_x) && modify)
18285         layout->max_x = bounds->x + bounds->w;
18286     bounds->x -= (float)*layout->offset_x;
18287 }
18288 NK_LIB void
18289 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
18290 {
18291     struct nk_window *win;
18292     struct nk_panel *layout;
18293 
18294     NK_ASSERT(ctx);
18295     NK_ASSERT(ctx->current);
18296     NK_ASSERT(ctx->current->layout);
18297     if (!ctx || !ctx->current || !ctx->current->layout)
18298         return;
18299 
18300     /* check if the end of the row has been hit and begin new row if so */
18301     win = ctx->current;
18302     layout = win->layout;
18303     if (layout->row.index >= layout->row.columns)
18304         nk_panel_alloc_row(ctx, win);
18305 
18306     /* calculate widget position and size */
18307     nk_layout_widget_space(bounds, ctx, win, nk_true);
18308     layout->row.index++;
18309 }
18310 NK_LIB void
18311 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
18312 {
18313     float y;
18314     int index;
18315     struct nk_window *win;
18316     struct nk_panel *layout;
18317 
18318     NK_ASSERT(ctx);
18319     NK_ASSERT(ctx->current);
18320     NK_ASSERT(ctx->current->layout);
18321     if (!ctx || !ctx->current || !ctx->current->layout)
18322         return;
18323 
18324     win = ctx->current;
18325     layout = win->layout;
18326     y = layout->at_y;
18327     index = layout->row.index;
18328     if (layout->row.index >= layout->row.columns) {
18329         layout->at_y += layout->row.height;
18330         layout->row.index = 0;
18331     }
18332     nk_layout_widget_space(bounds, ctx, win, nk_false);
18333     if (!layout->row.index) {
18334         bounds->x -= layout->row.item_offset;
18335     }
18336     layout->at_y = y;
18337     layout->row.index = index;
18338 }
18339 
18340 
18341 
18342 
18343 
18344 /* ===============================================================
18345  *
18346  *                              TREE
18347  *
18348  * ===============================================================*/
18349 NK_INTERN int
18350 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
18351     struct nk_image *img, const char *title, enum nk_collapse_states *state)
18352 {
18353     struct nk_window *win;
18354     struct nk_panel *layout;
18355     const struct nk_style *style;
18356     struct nk_command_buffer *out;
18357     const struct nk_input *in;
18358     const struct nk_style_button *button;
18359     enum nk_symbol_type symbol;
18360     float row_height;
18361 
18362     struct nk_vec2 item_spacing;
18363     struct nk_rect header = {0,0,0,0};
18364     struct nk_rect sym = {0,0,0,0};
18365     struct nk_text text;
18366 
18367     nk_flags ws = 0;
18368     enum nk_widget_layout_states widget_state;
18369 
18370     NK_ASSERT(ctx);
18371     NK_ASSERT(ctx->current);
18372     NK_ASSERT(ctx->current->layout);
18373     if (!ctx || !ctx->current || !ctx->current->layout)
18374         return 0;
18375 
18376     /* cache some data */
18377     win = ctx->current;
18378     layout = win->layout;
18379     out = &win->buffer;
18380     style = &ctx->style;
18381     item_spacing = style->window.spacing;
18382 
18383     /* calculate header bounds and draw background */
18384     row_height = style->font->height + 2 * style->tab.padding.y;
18385     nk_layout_set_min_row_height(ctx, row_height);
18386     nk_layout_row_dynamic(ctx, row_height, 1);
18387     nk_layout_reset_min_row_height(ctx);
18388 
18389     widget_state = nk_widget(&header, ctx);
18390     if (type == NK_TREE_TAB) {
18391         const struct nk_style_item *background = &style->tab.background;
18392         if (background->type == NK_STYLE_ITEM_IMAGE) {
18393             nk_draw_image(out, header, &background->data.image, nk_white);
18394             text.background = nk_rgba(0,0,0,0);
18395         } else {
18396             text.background = background->data.color;
18397             nk_fill_rect(out, header, 0, style->tab.border_color);
18398             nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
18399                 style->tab.rounding, background->data.color);
18400         }
18401     } else text.background = style->window.background;
18402 
18403     /* update node state */
18404     in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
18405     in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
18406     if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
18407         *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
18408 
18409     /* select correct button style */
18410     if (*state == NK_MAXIMIZED) {
18411         symbol = style->tab.sym_maximize;
18412         if (type == NK_TREE_TAB)
18413             button = &style->tab.tab_maximize_button;
18414         else button = &style->tab.node_maximize_button;
18415     } else {
18416         symbol = style->tab.sym_minimize;
18417         if (type == NK_TREE_TAB)
18418             button = &style->tab.tab_minimize_button;
18419         else button = &style->tab.node_minimize_button;
18420     }
18421 
18422     {/* draw triangle button */
18423     sym.w = sym.h = style->font->height;
18424     sym.y = header.y + style->tab.padding.y;
18425     sym.x = header.x + style->tab.padding.x;
18426     nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
18427         button, 0, style->font);
18428 
18429     if (img) {
18430         /* draw optional image icon */
18431         sym.x = sym.x + sym.w + 4 * item_spacing.x;
18432         nk_draw_image(&win->buffer, sym, img, nk_white);
18433         sym.w = style->font->height + style->tab.spacing.x;}
18434     }
18435 
18436     {/* draw label */
18437     struct nk_rect label;
18438     header.w = NK_MAX(header.w, sym.w + item_spacing.x);
18439     label.x = sym.x + sym.w + item_spacing.x;
18440     label.y = sym.y;
18441     label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
18442     label.h = style->font->height;
18443     text.text = style->tab.text;
18444     text.padding = nk_vec2(0,0);
18445     nk_widget_text(out, label, title, nk_strlen(title), &text,
18446         NK_TEXT_LEFT, style->font);}
18447 
18448     /* increase x-axis cursor widget position pointer */
18449     if (*state == NK_MAXIMIZED) {
18450         layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
18451         layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
18452         layout->bounds.w -= (style->tab.indent + style->window.padding.x);
18453         layout->row.tree_depth++;
18454         return nk_true;
18455     } else return nk_false;
18456 }
18457 NK_INTERN int
18458 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
18459     struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
18460     const char *hash, int len, int line)
18461 {
18462     struct nk_window *win = ctx->current;
18463     int title_len = 0;
18464     nk_hash tree_hash = 0;
18465     nk_uint *state = 0;
18466 
18467     /* retrieve tree state from internal widget state tables */
18468     if (!hash) {
18469         title_len = (int)nk_strlen(title);
18470         tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
18471     } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
18472     state = nk_find_value(win, tree_hash);
18473     if (!state) {
18474         state = nk_add_value(ctx, win, tree_hash, 0);
18475         *state = initial_state;
18476     }
18477     return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
18478 }
18479 NK_API int
18480 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
18481     const char *title, enum nk_collapse_states *state)
18482 {
18483     return nk_tree_state_base(ctx, type, 0, title, state);
18484 }
18485 NK_API int
18486 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
18487     struct nk_image img, const char *title, enum nk_collapse_states *state)
18488 {
18489     return nk_tree_state_base(ctx, type, &img, title, state);
18490 }
18491 NK_API void
18492 nk_tree_state_pop(struct nk_context *ctx)
18493 {
18494     struct nk_window *win = 0;
18495     struct nk_panel *layout = 0;
18496 
18497     NK_ASSERT(ctx);
18498     NK_ASSERT(ctx->current);
18499     NK_ASSERT(ctx->current->layout);
18500     if (!ctx || !ctx->current || !ctx->current->layout)
18501         return;
18502 
18503     win = ctx->current;
18504     layout = win->layout;
18505     layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
18506     layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
18507     NK_ASSERT(layout->row.tree_depth);
18508     layout->row.tree_depth--;
18509 }
18510 NK_API int
18511 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
18512     const char *title, enum nk_collapse_states initial_state,
18513     const char *hash, int len, int line)
18514 {
18515     return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);
18516 }
18517 NK_API int
18518 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
18519     struct nk_image img, const char *title, enum nk_collapse_states initial_state,
18520     const char *hash, int len,int seed)
18521 {
18522     return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);
18523 }
18524 NK_API void
18525 nk_tree_pop(struct nk_context *ctx)
18526 {
18527     nk_tree_state_pop(ctx);
18528 }
18529 NK_INTERN int
18530 nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type,
18531     struct nk_image *img, const char *title, int title_len,
18532     enum nk_collapse_states *state, int *selected)
18533 {
18534     struct nk_window *win;
18535     struct nk_panel *layout;
18536     const struct nk_style *style;
18537     struct nk_command_buffer *out;
18538     const struct nk_input *in;
18539     const struct nk_style_button *button;
18540     enum nk_symbol_type symbol;
18541     float row_height;
18542     struct nk_vec2 padding;
18543 
18544     int text_len;
18545     float text_width;
18546 
18547     struct nk_vec2 item_spacing;
18548     struct nk_rect header = {0,0,0,0};
18549     struct nk_rect sym = {0,0,0,0};
18550     struct nk_text text;
18551 
18552     nk_flags ws = 0;
18553     enum nk_widget_layout_states widget_state;
18554 
18555     NK_ASSERT(ctx);
18556     NK_ASSERT(ctx->current);
18557     NK_ASSERT(ctx->current->layout);
18558     if (!ctx || !ctx->current || !ctx->current->layout)
18559         return 0;
18560 
18561     /* cache some data */
18562     win = ctx->current;
18563     layout = win->layout;
18564     out = &win->buffer;
18565     style = &ctx->style;
18566     item_spacing = style->window.spacing;
18567     padding = style->selectable.padding;
18568 
18569     /* calculate header bounds and draw background */
18570     row_height = style->font->height + 2 * style->tab.padding.y;
18571     nk_layout_set_min_row_height(ctx, row_height);
18572     nk_layout_row_dynamic(ctx, row_height, 1);
18573     nk_layout_reset_min_row_height(ctx);
18574 
18575     widget_state = nk_widget(&header, ctx);
18576     if (type == NK_TREE_TAB) {
18577         const struct nk_style_item *background = &style->tab.background;
18578         if (background->type == NK_STYLE_ITEM_IMAGE) {
18579             nk_draw_image(out, header, &background->data.image, nk_white);
18580             text.background = nk_rgba(0,0,0,0);
18581         } else {
18582             text.background = background->data.color;
18583             nk_fill_rect(out, header, 0, style->tab.border_color);
18584             nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
18585                 style->tab.rounding, background->data.color);
18586         }
18587     } else text.background = style->window.background;
18588 
18589     in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
18590     in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
18591 
18592     /* select correct button style */
18593     if (*state == NK_MAXIMIZED) {
18594         symbol = style->tab.sym_maximize;
18595         if (type == NK_TREE_TAB)
18596             button = &style->tab.tab_maximize_button;
18597         else button = &style->tab.node_maximize_button;
18598     } else {
18599         symbol = style->tab.sym_minimize;
18600         if (type == NK_TREE_TAB)
18601             button = &style->tab.tab_minimize_button;
18602         else button = &style->tab.node_minimize_button;
18603     }
18604     {/* draw triangle button */
18605     sym.w = sym.h = style->font->height;
18606     sym.y = header.y + style->tab.padding.y;
18607     sym.x = header.x + style->tab.padding.x;
18608     if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font))
18609         *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;}
18610 
18611     /* draw label */
18612     {nk_flags dummy = 0;
18613     struct nk_rect label;
18614     /* calculate size of the text and tooltip */
18615     text_len = nk_strlen(title);
18616     text_width = style->font->width(style->font->userdata, style->font->height, title, text_len);
18617     text_width += (4 * padding.x);
18618 
18619     header.w = NK_MAX(header.w, sym.w + item_spacing.x);
18620     label.x = sym.x + sym.w + item_spacing.x;
18621     label.y = sym.y;
18622     label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width);
18623     label.h = style->font->height;
18624 
18625     if (img) {
18626         nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
18627             selected, img, &style->selectable, in, style->font);
18628     } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
18629             selected, &style->selectable, in, style->font);
18630     }
18631     /* increase x-axis cursor widget position pointer */
18632     if (*state == NK_MAXIMIZED) {
18633         layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
18634         layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
18635         layout->bounds.w -= (style->tab.indent + style->window.padding.x);
18636         layout->row.tree_depth++;
18637         return nk_true;
18638     } else return nk_false;
18639 }
18640 NK_INTERN int
18641 nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type,
18642     struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
18643     int *selected, const char *hash, int len, int line)
18644 {
18645     struct nk_window *win = ctx->current;
18646     int title_len = 0;
18647     nk_hash tree_hash = 0;
18648     nk_uint *state = 0;
18649 
18650     /* retrieve tree state from internal widget state tables */
18651     if (!hash) {
18652         title_len = (int)nk_strlen(title);
18653         tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
18654     } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
18655     state = nk_find_value(win, tree_hash);
18656     if (!state) {
18657         state = nk_add_value(ctx, win, tree_hash, 0);
18658         *state = initial_state;
18659     } return nk_tree_element_image_push_hashed_base(ctx, type, img, title,
18660         nk_strlen(title), (enum nk_collapse_states*)state, selected);
18661 }
18662 NK_API int
18663 nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
18664     const char *title, enum nk_collapse_states initial_state,
18665     int *selected, const char *hash, int len, int seed)
18666 {
18667     return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed);
18668 }
18669 NK_API int
18670 nk_tree_element_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
18671     struct nk_image img, const char *title, enum nk_collapse_states initial_state,
18672     int *selected, const char *hash, int len,int seed)
18673 {
18674     return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed);
18675 }
18676 NK_API void
18677 nk_tree_element_pop(struct nk_context *ctx)
18678 {
18679     nk_tree_state_pop(ctx);
18680 }
18681 
18682 
18683 
18684 
18685 
18686 /* ===============================================================
18687  *
18688  *                          GROUP
18689  *
18690  * ===============================================================*/
18691 NK_API int
18692 nk_group_scrolled_offset_begin(struct nk_context *ctx,
18693     nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
18694 {
18695     struct nk_rect bounds;
18696     struct nk_window panel;
18697     struct nk_window *win;
18698 
18699     win = ctx->current;
18700     nk_panel_alloc_space(&bounds, ctx);
18701     {const struct nk_rect *c = &win->layout->clip;
18702     if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
18703         !(flags & NK_WINDOW_MOVABLE)) {
18704         return 0;
18705     }}
18706     if (win->flags & NK_WINDOW_ROM)
18707         flags |= NK_WINDOW_ROM;
18708 
18709     /* initialize a fake window to create the panel from */
18710     nk_zero(&panel, sizeof(panel));
18711     panel.bounds = bounds;
18712     panel.flags = flags;
18713     panel.scrollbar.x = *x_offset;
18714     panel.scrollbar.y = *y_offset;
18715     panel.buffer = win->buffer;
18716     panel.layout = (struct nk_panel*)nk_create_panel(ctx);
18717     ctx->current = &panel;
18718     nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
18719 
18720     win->buffer = panel.buffer;
18721     win->buffer.clip = panel.layout->clip;
18722     panel.layout->offset_x = x_offset;
18723     panel.layout->offset_y = y_offset;
18724     panel.layout->parent = win->layout;
18725     win->layout = panel.layout;
18726 
18727     ctx->current = win;
18728     if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
18729         (panel.layout->flags & NK_WINDOW_MINIMIZED))
18730     {
18731         nk_flags f = panel.layout->flags;
18732         nk_group_scrolled_end(ctx);
18733         if (f & NK_WINDOW_CLOSED)
18734             return NK_WINDOW_CLOSED;
18735         if (f & NK_WINDOW_MINIMIZED)
18736             return NK_WINDOW_MINIMIZED;
18737     }
18738     return 1;
18739 }
18740 NK_API void
18741 nk_group_scrolled_end(struct nk_context *ctx)
18742 {
18743     struct nk_window *win;
18744     struct nk_panel *parent;
18745     struct nk_panel *g;
18746 
18747     struct nk_rect clip;
18748     struct nk_window pan;
18749     struct nk_vec2 panel_padding;
18750 
18751     NK_ASSERT(ctx);
18752     NK_ASSERT(ctx->current);
18753     if (!ctx || !ctx->current)
18754         return;
18755 
18756     /* make sure nk_group_begin was called correctly */
18757     NK_ASSERT(ctx->current);
18758     win = ctx->current;
18759     NK_ASSERT(win->layout);
18760     g = win->layout;
18761     NK_ASSERT(g->parent);
18762     parent = g->parent;
18763 
18764     /* dummy window */
18765     nk_zero_struct(pan);
18766     panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
18767     pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
18768     pan.bounds.x = g->bounds.x - panel_padding.x;
18769     pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
18770     pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
18771     if (g->flags & NK_WINDOW_BORDER) {
18772         pan.bounds.x -= g->border;
18773         pan.bounds.y -= g->border;
18774         pan.bounds.w += 2*g->border;
18775         pan.bounds.h += 2*g->border;
18776     }
18777     if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
18778         pan.bounds.w += ctx->style.window.scrollbar_size.x;
18779         pan.bounds.h += ctx->style.window.scrollbar_size.y;
18780     }
18781     pan.scrollbar.x = *g->offset_x;
18782     pan.scrollbar.y = *g->offset_y;
18783     pan.flags = g->flags;
18784     pan.buffer = win->buffer;
18785     pan.layout = g;
18786     pan.parent = win;
18787     ctx->current = &pan;
18788 
18789     /* make sure group has correct clipping rectangle */
18790     nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
18791         pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
18792     nk_push_scissor(&pan.buffer, clip);
18793     nk_end(ctx);
18794 
18795     win->buffer = pan.buffer;
18796     nk_push_scissor(&win->buffer, parent->clip);
18797     ctx->current = win;
18798     win->layout = parent;
18799     g->bounds = pan.bounds;
18800     return;
18801 }
18802 NK_API int
18803 nk_group_scrolled_begin(struct nk_context *ctx,
18804     struct nk_scroll *scroll, const char *title, nk_flags flags)
18805 {
18806     return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);
18807 }
18808 NK_API int
18809 nk_group_begin_titled(struct nk_context *ctx, const char *id,
18810     const char *title, nk_flags flags)
18811 {
18812     int id_len;
18813     nk_hash id_hash;
18814     struct nk_window *win;
18815     nk_uint *x_offset;
18816     nk_uint *y_offset;
18817 
18818     NK_ASSERT(ctx);
18819     NK_ASSERT(id);
18820     NK_ASSERT(ctx->current);
18821     NK_ASSERT(ctx->current->layout);
18822     if (!ctx || !ctx->current || !ctx->current->layout || !id)
18823         return 0;
18824 
18825     /* find persistent group scrollbar value */
18826     win = ctx->current;
18827     id_len = (int)nk_strlen(id);
18828     id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
18829     x_offset = nk_find_value(win, id_hash);
18830     if (!x_offset) {
18831         x_offset = nk_add_value(ctx, win, id_hash, 0);
18832         y_offset = nk_add_value(ctx, win, id_hash+1, 0);
18833 
18834         NK_ASSERT(x_offset);
18835         NK_ASSERT(y_offset);
18836         if (!x_offset || !y_offset) return 0;
18837         *x_offset = *y_offset = 0;
18838     } else y_offset = nk_find_value(win, id_hash+1);
18839     return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
18840 }
18841 NK_API int
18842 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
18843 {
18844     return nk_group_begin_titled(ctx, title, title, flags);
18845 }
18846 NK_API void
18847 nk_group_end(struct nk_context *ctx)
18848 {
18849     nk_group_scrolled_end(ctx);
18850 }
18851 NK_API void
18852 nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset)
18853 {
18854     int id_len;
18855     nk_hash id_hash;
18856     struct nk_window *win;
18857     nk_uint *x_offset_ptr;
18858     nk_uint *y_offset_ptr;
18859 
18860     NK_ASSERT(ctx);
18861     NK_ASSERT(id);
18862     NK_ASSERT(ctx->current);
18863     NK_ASSERT(ctx->current->layout);
18864     if (!ctx || !ctx->current || !ctx->current->layout || !id)
18865         return;
18866 
18867     /* find persistent group scrollbar value */
18868     win = ctx->current;
18869     id_len = (int)nk_strlen(id);
18870     id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
18871     x_offset_ptr = nk_find_value(win, id_hash);
18872     if (!x_offset_ptr) {
18873         x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
18874         y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
18875 
18876         NK_ASSERT(x_offset_ptr);
18877         NK_ASSERT(y_offset_ptr);
18878         if (!x_offset_ptr || !y_offset_ptr) return;
18879         *x_offset_ptr = *y_offset_ptr = 0;
18880     } else y_offset_ptr = nk_find_value(win, id_hash+1);
18881     if (x_offset)
18882       *x_offset = *x_offset_ptr;
18883     if (y_offset)
18884       *y_offset = *y_offset_ptr;
18885 }
18886 NK_API void
18887 nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset)
18888 {
18889     int id_len;
18890     nk_hash id_hash;
18891     struct nk_window *win;
18892     nk_uint *x_offset_ptr;
18893     nk_uint *y_offset_ptr;
18894 
18895     NK_ASSERT(ctx);
18896     NK_ASSERT(id);
18897     NK_ASSERT(ctx->current);
18898     NK_ASSERT(ctx->current->layout);
18899     if (!ctx || !ctx->current || !ctx->current->layout || !id)
18900         return;
18901 
18902     /* find persistent group scrollbar value */
18903     win = ctx->current;
18904     id_len = (int)nk_strlen(id);
18905     id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
18906     x_offset_ptr = nk_find_value(win, id_hash);
18907     if (!x_offset_ptr) {
18908         x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
18909         y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
18910 
18911         NK_ASSERT(x_offset_ptr);
18912         NK_ASSERT(y_offset_ptr);
18913         if (!x_offset_ptr || !y_offset_ptr) return;
18914         *x_offset_ptr = *y_offset_ptr = 0;
18915     } else y_offset_ptr = nk_find_value(win, id_hash+1);
18916     *x_offset_ptr = x_offset;
18917     *y_offset_ptr = y_offset;
18918 }
18919 
18920 
18921 
18922 
18923 /* ===============================================================
18924  *
18925  *                          LIST VIEW
18926  *
18927  * ===============================================================*/
18928 NK_API int
18929 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
18930     const char *title, nk_flags flags, int row_height, int row_count)
18931 {
18932     int title_len;
18933     nk_hash title_hash;
18934     nk_uint *x_offset;
18935     nk_uint *y_offset;
18936 
18937     int result;
18938     struct nk_window *win;
18939     struct nk_panel *layout;
18940     const struct nk_style *style;
18941     struct nk_vec2 item_spacing;
18942 
18943     NK_ASSERT(ctx);
18944     NK_ASSERT(view);
18945     NK_ASSERT(title);
18946     if (!ctx || !view || !title) return 0;
18947 
18948     win = ctx->current;
18949     style = &ctx->style;
18950     item_spacing = style->window.spacing;
18951     row_height += NK_MAX(0, (int)item_spacing.y);
18952 
18953     /* find persistent list view scrollbar offset */
18954     title_len = (int)nk_strlen(title);
18955     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
18956     x_offset = nk_find_value(win, title_hash);
18957     if (!x_offset) {
18958         x_offset = nk_add_value(ctx, win, title_hash, 0);
18959         y_offset = nk_add_value(ctx, win, title_hash+1, 0);
18960 
18961         NK_ASSERT(x_offset);
18962         NK_ASSERT(y_offset);
18963         if (!x_offset || !y_offset) return 0;
18964         *x_offset = *y_offset = 0;
18965     } else y_offset = nk_find_value(win, title_hash+1);
18966     view->scroll_value = *y_offset;
18967     view->scroll_pointer = y_offset;
18968 
18969     *y_offset = 0;
18970     result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
18971     win = ctx->current;
18972     layout = win->layout;
18973 
18974     view->total_height = row_height * NK_MAX(row_count,1);
18975     view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
18976     view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0);
18977     view->count = NK_MIN(view->count, row_count - view->begin);
18978     view->end = view->begin + view->count;
18979     view->ctx = ctx;
18980     return result;
18981 }
18982 NK_API void
18983 nk_list_view_end(struct nk_list_view *view)
18984 {
18985     struct nk_context *ctx;
18986     struct nk_window *win;
18987     struct nk_panel *layout;
18988 
18989     NK_ASSERT(view);
18990     NK_ASSERT(view->ctx);
18991     NK_ASSERT(view->scroll_pointer);
18992     if (!view || !view->ctx) return;
18993 
18994     ctx = view->ctx;
18995     win = ctx->current;
18996     layout = win->layout;
18997     layout->at_y = layout->bounds.y + (float)view->total_height;
18998     *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
18999     nk_group_end(view->ctx);
19000 }
19001 
19002 
19003 
19004 
19005 
19006 /* ===============================================================
19007  *
19008  *                              WIDGET
19009  *
19010  * ===============================================================*/
19011 NK_API struct nk_rect
19012 nk_widget_bounds(struct nk_context *ctx)
19013 {
19014     struct nk_rect bounds;
19015     NK_ASSERT(ctx);
19016     NK_ASSERT(ctx->current);
19017     if (!ctx || !ctx->current)
19018         return nk_rect(0,0,0,0);
19019     nk_layout_peek(&bounds, ctx);
19020     return bounds;
19021 }
19022 NK_API struct nk_vec2
19023 nk_widget_position(struct nk_context *ctx)
19024 {
19025     struct nk_rect bounds;
19026     NK_ASSERT(ctx);
19027     NK_ASSERT(ctx->current);
19028     if (!ctx || !ctx->current)
19029         return nk_vec2(0,0);
19030 
19031     nk_layout_peek(&bounds, ctx);
19032     return nk_vec2(bounds.x, bounds.y);
19033 }
19034 NK_API struct nk_vec2
19035 nk_widget_size(struct nk_context *ctx)
19036 {
19037     struct nk_rect bounds;
19038     NK_ASSERT(ctx);
19039     NK_ASSERT(ctx->current);
19040     if (!ctx || !ctx->current)
19041         return nk_vec2(0,0);
19042 
19043     nk_layout_peek(&bounds, ctx);
19044     return nk_vec2(bounds.w, bounds.h);
19045 }
19046 NK_API float
19047 nk_widget_width(struct nk_context *ctx)
19048 {
19049     struct nk_rect bounds;
19050     NK_ASSERT(ctx);
19051     NK_ASSERT(ctx->current);
19052     if (!ctx || !ctx->current)
19053         return 0;
19054 
19055     nk_layout_peek(&bounds, ctx);
19056     return bounds.w;
19057 }
19058 NK_API float
19059 nk_widget_height(struct nk_context *ctx)
19060 {
19061     struct nk_rect bounds;
19062     NK_ASSERT(ctx);
19063     NK_ASSERT(ctx->current);
19064     if (!ctx || !ctx->current)
19065         return 0;
19066 
19067     nk_layout_peek(&bounds, ctx);
19068     return bounds.h;
19069 }
19070 NK_API int
19071 nk_widget_is_hovered(struct nk_context *ctx)
19072 {
19073     struct nk_rect c, v;
19074     struct nk_rect bounds;
19075     NK_ASSERT(ctx);
19076     NK_ASSERT(ctx->current);
19077     if (!ctx || !ctx->current || ctx->active != ctx->current)
19078         return 0;
19079 
19080     c = ctx->current->layout->clip;
19081     c.x = (float)((int)c.x);
19082     c.y = (float)((int)c.y);
19083     c.w = (float)((int)c.w);
19084     c.h = (float)((int)c.h);
19085 
19086     nk_layout_peek(&bounds, ctx);
19087     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
19088     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
19089         return 0;
19090     return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
19091 }
19092 NK_API int
19093 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
19094 {
19095     struct nk_rect c, v;
19096     struct nk_rect bounds;
19097     NK_ASSERT(ctx);
19098     NK_ASSERT(ctx->current);
19099     if (!ctx || !ctx->current || ctx->active != ctx->current)
19100         return 0;
19101 
19102     c = ctx->current->layout->clip;
19103     c.x = (float)((int)c.x);
19104     c.y = (float)((int)c.y);
19105     c.w = (float)((int)c.w);
19106     c.h = (float)((int)c.h);
19107 
19108     nk_layout_peek(&bounds, ctx);
19109     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
19110     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
19111         return 0;
19112     return nk_input_mouse_clicked(&ctx->input, btn, bounds);
19113 }
19114 NK_API int
19115 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
19116 {
19117     struct nk_rect c, v;
19118     struct nk_rect bounds;
19119     NK_ASSERT(ctx);
19120     NK_ASSERT(ctx->current);
19121     if (!ctx || !ctx->current || ctx->active != ctx->current)
19122         return 0;
19123 
19124     c = ctx->current->layout->clip;
19125     c.x = (float)((int)c.x);
19126     c.y = (float)((int)c.y);
19127     c.w = (float)((int)c.w);
19128     c.h = (float)((int)c.h);
19129 
19130     nk_layout_peek(&bounds, ctx);
19131     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
19132     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
19133         return 0;
19134     return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
19135 }
19136 NK_API enum nk_widget_layout_states
19137 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
19138 {
19139     struct nk_rect c, v;
19140     struct nk_window *win;
19141     struct nk_panel *layout;
19142     const struct nk_input *in;
19143 
19144     NK_ASSERT(ctx);
19145     NK_ASSERT(ctx->current);
19146     NK_ASSERT(ctx->current->layout);
19147     if (!ctx || !ctx->current || !ctx->current->layout)
19148         return NK_WIDGET_INVALID;
19149 
19150     /* allocate space and check if the widget needs to be updated and drawn */
19151     nk_panel_alloc_space(bounds, ctx);
19152     win = ctx->current;
19153     layout = win->layout;
19154     in = &ctx->input;
19155     c = layout->clip;
19156 
19157     /*  if one of these triggers you forgot to add an `if` condition around either
19158         a window, group, popup, combobox or contextual menu `begin` and `end` block.
19159         Example:
19160             if (nk_begin(...) {...} nk_end(...); or
19161             if (nk_group_begin(...) { nk_group_end(...);} */
19162     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
19163     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
19164     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
19165 
19166     /* need to convert to int here to remove floating point errors */
19167     bounds->x = (float)((int)bounds->x);
19168     bounds->y = (float)((int)bounds->y);
19169     bounds->w = (float)((int)bounds->w);
19170     bounds->h = (float)((int)bounds->h);
19171 
19172     c.x = (float)((int)c.x);
19173     c.y = (float)((int)c.y);
19174     c.w = (float)((int)c.w);
19175     c.h = (float)((int)c.h);
19176 
19177     nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
19178     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
19179         return NK_WIDGET_INVALID;
19180     if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
19181         return NK_WIDGET_ROM;
19182     return NK_WIDGET_VALID;
19183 }
19184 NK_API enum nk_widget_layout_states
19185 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
19186     struct nk_vec2 item_padding)
19187 {
19188     /* update the bounds to stand without padding  */
19189     struct nk_window *win;
19190     struct nk_style *style;
19191     struct nk_panel *layout;
19192     enum nk_widget_layout_states state;
19193     struct nk_vec2 panel_padding;
19194 
19195     NK_ASSERT(ctx);
19196     NK_ASSERT(ctx->current);
19197     NK_ASSERT(ctx->current->layout);
19198     if (!ctx || !ctx->current || !ctx->current->layout)
19199         return NK_WIDGET_INVALID;
19200 
19201     win = ctx->current;
19202     style = &ctx->style;
19203     layout = win->layout;
19204     state = nk_widget(bounds, ctx);
19205 
19206     panel_padding = nk_panel_get_padding(style, layout->type);
19207     if (layout->row.index == 1) {
19208         bounds->w += panel_padding.x;
19209         bounds->x -= panel_padding.x;
19210     } else bounds->x -= item_padding.x;
19211 
19212     if (layout->row.index == layout->row.columns)
19213         bounds->w += panel_padding.x;
19214     else bounds->w += item_padding.x;
19215     return state;
19216 }
19217 NK_API void
19218 nk_spacing(struct nk_context *ctx, int cols)
19219 {
19220     struct nk_window *win;
19221     struct nk_panel *layout;
19222     struct nk_rect none;
19223     int i, index, rows;
19224 
19225     NK_ASSERT(ctx);
19226     NK_ASSERT(ctx->current);
19227     NK_ASSERT(ctx->current->layout);
19228     if (!ctx || !ctx->current || !ctx->current->layout)
19229         return;
19230 
19231     /* spacing over row boundaries */
19232     win = ctx->current;
19233     layout = win->layout;
19234     index = (layout->row.index + cols) % layout->row.columns;
19235     rows = (layout->row.index + cols) / layout->row.columns;
19236     if (rows) {
19237         for (i = 0; i < rows; ++i)
19238             nk_panel_alloc_row(ctx, win);
19239         cols = index;
19240     }
19241     /* non table layout need to allocate space */
19242     if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
19243         layout->row.type != NK_LAYOUT_STATIC_FIXED) {
19244         for (i = 0; i < cols; ++i)
19245             nk_panel_alloc_space(&none, ctx);
19246     } layout->row.index = index;
19247 }
19248 
19249 
19250 
19251 
19252 
19253 /* ===============================================================
19254  *
19255  *                              TEXT
19256  *
19257  * ===============================================================*/
19258 NK_LIB void
19259 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
19260     const char *string, int len, const struct nk_text *t,
19261     nk_flags a, const struct nk_user_font *f)
19262 {
19263     struct nk_rect label;
19264     float text_width;
19265 
19266     NK_ASSERT(o);
19267     NK_ASSERT(t);
19268     if (!o || !t) return;
19269 
19270     b.h = NK_MAX(b.h, 2 * t->padding.y);
19271     label.x = 0; label.w = 0;
19272     label.y = b.y + t->padding.y;
19273     label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
19274 
19275     text_width = f->width(f->userdata, f->height, (const char*)string, len);
19276     text_width += (2.0f * t->padding.x);
19277 
19278     /* align in x-axis */
19279     if (a & NK_TEXT_ALIGN_LEFT) {
19280         label.x = b.x + t->padding.x;
19281         label.w = NK_MAX(0, b.w - 2 * t->padding.x);
19282     } else if (a & NK_TEXT_ALIGN_CENTERED) {
19283         label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
19284         label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
19285         label.x = NK_MAX(b.x + t->padding.x, label.x);
19286         label.w = NK_MIN(b.x + b.w, label.x + label.w);
19287         if (label.w >= label.x) label.w -= label.x;
19288     } else if (a & NK_TEXT_ALIGN_RIGHT) {
19289         label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
19290         label.w = (float)text_width + 2 * t->padding.x;
19291     } else return;
19292 
19293     /* align in y-axis */
19294     if (a & NK_TEXT_ALIGN_MIDDLE) {
19295         label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
19296         label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
19297     } else if (a & NK_TEXT_ALIGN_BOTTOM) {
19298         label.y = b.y + b.h - f->height;
19299         label.h = f->height;
19300     }
19301     nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text);
19302 }
19303 NK_LIB void
19304 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
19305     const char *string, int len, const struct nk_text *t,
19306     const struct nk_user_font *f)
19307 {
19308     float width;
19309     int glyphs = 0;
19310     int fitting = 0;
19311     int done = 0;
19312     struct nk_rect line;
19313     struct nk_text text;
19314     NK_INTERN nk_rune seperator[] = {' '};
19315 
19316     NK_ASSERT(o);
19317     NK_ASSERT(t);
19318     if (!o || !t) return;
19319 
19320     text.padding = nk_vec2(0,0);
19321     text.background = t->background;
19322     text.text = t->text;
19323 
19324     b.w = NK_MAX(b.w, 2 * t->padding.x);
19325     b.h = NK_MAX(b.h, 2 * t->padding.y);
19326     b.h = b.h - 2 * t->padding.y;
19327 
19328     line.x = b.x + t->padding.x;
19329     line.y = b.y + t->padding.y;
19330     line.w = b.w - 2 * t->padding.x;
19331     line.h = 2 * t->padding.y + f->height;
19332 
19333     fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
19334     while (done < len) {
19335         if (!fitting || line.y + line.h >= (b.y + b.h)) break;
19336         nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
19337         done += fitting;
19338         line.y += f->height + 2 * t->padding.y;
19339         fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
19340     }
19341 }
19342 NK_API void
19343 nk_text_colored(struct nk_context *ctx, const char *str, int len,
19344     nk_flags alignment, struct nk_color color)
19345 {
19346     struct nk_window *win;
19347     const struct nk_style *style;
19348 
19349     struct nk_vec2 item_padding;
19350     struct nk_rect bounds;
19351     struct nk_text text;
19352 
19353     NK_ASSERT(ctx);
19354     NK_ASSERT(ctx->current);
19355     NK_ASSERT(ctx->current->layout);
19356     if (!ctx || !ctx->current || !ctx->current->layout) return;
19357 
19358     win = ctx->current;
19359     style = &ctx->style;
19360     nk_panel_alloc_space(&bounds, ctx);
19361     item_padding = style->text.padding;
19362 
19363     text.padding.x = item_padding.x;
19364     text.padding.y = item_padding.y;
19365     text.background = style->window.background;
19366     text.text = color;
19367     nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
19368 }
19369 NK_API void
19370 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
19371     int len, struct nk_color color)
19372 {
19373     struct nk_window *win;
19374     const struct nk_style *style;
19375 
19376     struct nk_vec2 item_padding;
19377     struct nk_rect bounds;
19378     struct nk_text text;
19379 
19380     NK_ASSERT(ctx);
19381     NK_ASSERT(ctx->current);
19382     NK_ASSERT(ctx->current->layout);
19383     if (!ctx || !ctx->current || !ctx->current->layout) return;
19384 
19385     win = ctx->current;
19386     style = &ctx->style;
19387     nk_panel_alloc_space(&bounds, ctx);
19388     item_padding = style->text.padding;
19389 
19390     text.padding.x = item_padding.x;
19391     text.padding.y = item_padding.y;
19392     text.background = style->window.background;
19393     text.text = color;
19394     nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
19395 }
19396 #ifdef NK_INCLUDE_STANDARD_VARARGS
19397 NK_API void
19398 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
19399     struct nk_color color, const char *fmt, ...)
19400 {
19401     va_list args;
19402     va_start(args, fmt);
19403     nk_labelfv_colored(ctx, flags, color, fmt, args);
19404     va_end(args);
19405 }
19406 NK_API void
19407 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
19408     const char *fmt, ...)
19409 {
19410     va_list args;
19411     va_start(args, fmt);
19412     nk_labelfv_colored_wrap(ctx, color, fmt, args);
19413     va_end(args);
19414 }
19415 NK_API void
19416 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
19417 {
19418     va_list args;
19419     va_start(args, fmt);
19420     nk_labelfv(ctx, flags, fmt, args);
19421     va_end(args);
19422 }
19423 NK_API void
19424 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
19425 {
19426     va_list args;
19427     va_start(args, fmt);
19428     nk_labelfv_wrap(ctx, fmt, args);
19429     va_end(args);
19430 }
19431 NK_API void
19432 nk_labelfv_colored(struct nk_context *ctx, nk_flags flags,
19433     struct nk_color color, const char *fmt, va_list args)
19434 {
19435     char buf[256];
19436     nk_strfmt(buf, NK_LEN(buf), fmt, args);
19437     nk_label_colored(ctx, buf, flags, color);
19438 }
19439 
19440 NK_API void
19441 nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color,
19442     const char *fmt, va_list args)
19443 {
19444     char buf[256];
19445     nk_strfmt(buf, NK_LEN(buf), fmt, args);
19446     nk_label_colored_wrap(ctx, buf, color);
19447 }
19448 
19449 NK_API void
19450 nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args)
19451 {
19452     char buf[256];
19453     nk_strfmt(buf, NK_LEN(buf), fmt, args);
19454     nk_label(ctx, buf, flags);
19455 }
19456 
19457 NK_API void
19458 nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args)
19459 {
19460     char buf[256];
19461     nk_strfmt(buf, NK_LEN(buf), fmt, args);
19462     nk_label_wrap(ctx, buf);
19463 }
19464 
19465 NK_API void
19466 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
19467 {
19468     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));
19469 }
19470 NK_API void
19471 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
19472 {
19473     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);
19474 }
19475 NK_API void
19476 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
19477 {
19478     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);
19479 }
19480 NK_API void
19481 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
19482 {
19483     double double_value = (double)value;
19484     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
19485 }
19486 NK_API void
19487 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
19488 {
19489     nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);
19490 }
19491 NK_API void
19492 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
19493 {
19494     double c[4]; nk_color_dv(c, color);
19495     nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
19496         p, c[0], c[1], c[2], c[3]);
19497 }
19498 NK_API void
19499 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
19500 {
19501     char hex[16];
19502     nk_color_hex_rgba(hex, color);
19503     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
19504 }
19505 #endif
19506 NK_API void
19507 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
19508 {
19509     NK_ASSERT(ctx);
19510     if (!ctx) return;
19511     nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
19512 }
19513 NK_API void
19514 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
19515 {
19516     NK_ASSERT(ctx);
19517     if (!ctx) return;
19518     nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
19519 }
19520 NK_API void
19521 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
19522 {
19523     nk_text(ctx, str, nk_strlen(str), alignment);
19524 }
19525 NK_API void
19526 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
19527     struct nk_color color)
19528 {
19529     nk_text_colored(ctx, str, nk_strlen(str), align, color);
19530 }
19531 NK_API void
19532 nk_label_wrap(struct nk_context *ctx, const char *str)
19533 {
19534     nk_text_wrap(ctx, str, nk_strlen(str));
19535 }
19536 NK_API void
19537 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
19538 {
19539     nk_text_wrap_colored(ctx, str, nk_strlen(str), color);
19540 }
19541 
19542 
19543 
19544 
19545 
19546 /* ===============================================================
19547  *
19548  *                          IMAGE
19549  *
19550  * ===============================================================*/
19551 NK_API nk_handle
19552 nk_handle_ptr(void *ptr)
19553 {
19554     nk_handle handle = {0};
19555     handle.ptr = ptr;
19556     return handle;
19557 }
19558 NK_API nk_handle
19559 nk_handle_id(int id)
19560 {
19561     nk_handle handle;
19562     nk_zero_struct(handle);
19563     handle.id = id;
19564     return handle;
19565 }
19566 NK_API struct nk_image
19567 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
19568 {
19569     struct nk_image s;
19570     nk_zero(&s, sizeof(s));
19571     s.handle.ptr = ptr;
19572     s.w = w; s.h = h;
19573     s.region[0] = (unsigned short)r.x;
19574     s.region[1] = (unsigned short)r.y;
19575     s.region[2] = (unsigned short)r.w;
19576     s.region[3] = (unsigned short)r.h;
19577     return s;
19578 }
19579 NK_API struct nk_image
19580 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
19581 {
19582     struct nk_image s;
19583     nk_zero(&s, sizeof(s));
19584     s.handle.id = id;
19585     s.w = w; s.h = h;
19586     s.region[0] = (unsigned short)r.x;
19587     s.region[1] = (unsigned short)r.y;
19588     s.region[2] = (unsigned short)r.w;
19589     s.region[3] = (unsigned short)r.h;
19590     return s;
19591 }
19592 NK_API struct nk_image
19593 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
19594     struct nk_rect r)
19595 {
19596     struct nk_image s;
19597     nk_zero(&s, sizeof(s));
19598     s.handle = handle;
19599     s.w = w; s.h = h;
19600     s.region[0] = (unsigned short)r.x;
19601     s.region[1] = (unsigned short)r.y;
19602     s.region[2] = (unsigned short)r.w;
19603     s.region[3] = (unsigned short)r.h;
19604     return s;
19605 }
19606 NK_API struct nk_image
19607 nk_image_handle(nk_handle handle)
19608 {
19609     struct nk_image s;
19610     nk_zero(&s, sizeof(s));
19611     s.handle = handle;
19612     s.w = 0; s.h = 0;
19613     s.region[0] = 0;
19614     s.region[1] = 0;
19615     s.region[2] = 0;
19616     s.region[3] = 0;
19617     return s;
19618 }
19619 NK_API struct nk_image
19620 nk_image_ptr(void *ptr)
19621 {
19622     struct nk_image s;
19623     nk_zero(&s, sizeof(s));
19624     NK_ASSERT(ptr);
19625     s.handle.ptr = ptr;
19626     s.w = 0; s.h = 0;
19627     s.region[0] = 0;
19628     s.region[1] = 0;
19629     s.region[2] = 0;
19630     s.region[3] = 0;
19631     return s;
19632 }
19633 NK_API struct nk_image
19634 nk_image_id(int id)
19635 {
19636     struct nk_image s;
19637     nk_zero(&s, sizeof(s));
19638     s.handle.id = id;
19639     s.w = 0; s.h = 0;
19640     s.region[0] = 0;
19641     s.region[1] = 0;
19642     s.region[2] = 0;
19643     s.region[3] = 0;
19644     return s;
19645 }
19646 NK_API int
19647 nk_image_is_subimage(const struct nk_image* img)
19648 {
19649     NK_ASSERT(img);
19650     return !(img->w == 0 && img->h == 0);
19651 }
19652 NK_API void
19653 nk_image(struct nk_context *ctx, struct nk_image img)
19654 {
19655     struct nk_window *win;
19656     struct nk_rect bounds;
19657 
19658     NK_ASSERT(ctx);
19659     NK_ASSERT(ctx->current);
19660     NK_ASSERT(ctx->current->layout);
19661     if (!ctx || !ctx->current || !ctx->current->layout) return;
19662 
19663     win = ctx->current;
19664     if (!nk_widget(&bounds, ctx)) return;
19665     nk_draw_image(&win->buffer, bounds, &img, nk_white);
19666 }
19667 NK_API void
19668 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col)
19669 {
19670     struct nk_window *win;
19671     struct nk_rect bounds;
19672 
19673     NK_ASSERT(ctx);
19674     NK_ASSERT(ctx->current);
19675     NK_ASSERT(ctx->current->layout);
19676     if (!ctx || !ctx->current || !ctx->current->layout) return;
19677 
19678     win = ctx->current;
19679     if (!nk_widget(&bounds, ctx)) return;
19680     nk_draw_image(&win->buffer, bounds, &img, col);
19681 }
19682 
19683 
19684 
19685 
19686 
19687 /* ==============================================================
19688  *
19689  *                          BUTTON
19690  *
19691  * ===============================================================*/
19692 NK_LIB void
19693 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
19694     struct nk_rect content, struct nk_color background, struct nk_color foreground,
19695     float border_width, const struct nk_user_font *font)
19696 {
19697     switch (type) {
19698     case NK_SYMBOL_X:
19699     case NK_SYMBOL_UNDERSCORE:
19700     case NK_SYMBOL_PLUS:
19701     case NK_SYMBOL_MINUS: {
19702         /* single character text symbol */
19703         const char *X = (type == NK_SYMBOL_X) ? "x":
19704             (type == NK_SYMBOL_UNDERSCORE) ? "_":
19705             (type == NK_SYMBOL_PLUS) ? "+": "-";
19706         struct nk_text text;
19707         text.padding = nk_vec2(0,0);
19708         text.background = background;
19709         text.text = foreground;
19710         nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
19711     } break;
19712     case NK_SYMBOL_CIRCLE_SOLID:
19713     case NK_SYMBOL_CIRCLE_OUTLINE:
19714     case NK_SYMBOL_RECT_SOLID:
19715     case NK_SYMBOL_RECT_OUTLINE: {
19716         /* simple empty/filled shapes */
19717         if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
19718             nk_fill_rect(out, content,  0, foreground);
19719             if (type == NK_SYMBOL_RECT_OUTLINE)
19720                 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
19721         } else {
19722             nk_fill_circle(out, content, foreground);
19723             if (type == NK_SYMBOL_CIRCLE_OUTLINE)
19724                 nk_fill_circle(out, nk_shrink_rect(content, 1), background);
19725         }
19726     } break;
19727     case NK_SYMBOL_TRIANGLE_UP:
19728     case NK_SYMBOL_TRIANGLE_DOWN:
19729     case NK_SYMBOL_TRIANGLE_LEFT:
19730     case NK_SYMBOL_TRIANGLE_RIGHT: {
19731         enum nk_heading heading;
19732         struct nk_vec2 points[3];
19733         heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
19734             (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
19735             (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
19736         nk_triangle_from_direction(points, content, 0, 0, heading);
19737         nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
19738             points[2].x, points[2].y, foreground);
19739     } break;
19740     default:
19741     case NK_SYMBOL_NONE:
19742     case NK_SYMBOL_MAX: break;
19743     }
19744 }
19745 NK_LIB int
19746 nk_button_behavior(nk_flags *state, struct nk_rect r,
19747     const struct nk_input *i, enum nk_button_behavior behavior)
19748 {
19749     int ret = 0;
19750     nk_widget_state_reset(state);
19751     if (!i) return 0;
19752     if (nk_input_is_mouse_hovering_rect(i, r)) {
19753         *state = NK_WIDGET_STATE_HOVERED;
19754         if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT))
19755             *state = NK_WIDGET_STATE_ACTIVE;
19756         if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) {
19757             ret = (behavior != NK_BUTTON_DEFAULT) ?
19758                 nk_input_is_mouse_down(i, NK_BUTTON_LEFT):
19759 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
19760                 nk_input_is_mouse_released(i, NK_BUTTON_LEFT);
19761 #else
19762                 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT);
19763 #endif
19764         }
19765     }
19766     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r))
19767         *state |= NK_WIDGET_STATE_ENTERED;
19768     else if (nk_input_is_mouse_prev_hovering_rect(i, r))
19769         *state |= NK_WIDGET_STATE_LEFT;
19770     return ret;
19771 }
19772 NK_LIB const struct nk_style_item*
19773 nk_draw_button(struct nk_command_buffer *out,
19774     const struct nk_rect *bounds, nk_flags state,
19775     const struct nk_style_button *style)
19776 {
19777     const struct nk_style_item *background;
19778     if (state & NK_WIDGET_STATE_HOVER)
19779         background = &style->hover;
19780     else if (state & NK_WIDGET_STATE_ACTIVED)
19781         background = &style->active;
19782     else background = &style->normal;
19783 
19784     if (background->type == NK_STYLE_ITEM_IMAGE) {
19785         nk_draw_image(out, *bounds, &background->data.image, nk_white);
19786     } else {
19787         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
19788         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
19789     }
19790     return background;
19791 }
19792 NK_LIB int
19793 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
19794     const struct nk_style_button *style, const struct nk_input *in,
19795     enum nk_button_behavior behavior, struct nk_rect *content)
19796 {
19797     struct nk_rect bounds;
19798     NK_ASSERT(style);
19799     NK_ASSERT(state);
19800     NK_ASSERT(out);
19801     if (!out || !style)
19802         return nk_false;
19803 
19804     /* calculate button content space */
19805     content->x = r.x + style->padding.x + style->border + style->rounding;
19806     content->y = r.y + style->padding.y + style->border + style->rounding;
19807     content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
19808     content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
19809 
19810     /* execute button behavior */
19811     bounds.x = r.x - style->touch_padding.x;
19812     bounds.y = r.y - style->touch_padding.y;
19813     bounds.w = r.w + 2 * style->touch_padding.x;
19814     bounds.h = r.h + 2 * style->touch_padding.y;
19815     return nk_button_behavior(state, bounds, in, behavior);
19816 }
19817 NK_LIB void
19818 nk_draw_button_text(struct nk_command_buffer *out,
19819     const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
19820     const struct nk_style_button *style, const char *txt, int len,
19821     nk_flags text_alignment, const struct nk_user_font *font)
19822 {
19823     struct nk_text text;
19824     const struct nk_style_item *background;
19825     background = nk_draw_button(out, bounds, state, style);
19826 
19827     /* select correct colors/images */
19828     if (background->type == NK_STYLE_ITEM_COLOR)
19829         text.background = background->data.color;
19830     else text.background = style->text_background;
19831     if (state & NK_WIDGET_STATE_HOVER)
19832         text.text = style->text_hover;
19833     else if (state & NK_WIDGET_STATE_ACTIVED)
19834         text.text = style->text_active;
19835     else text.text = style->text_normal;
19836 
19837     text.padding = nk_vec2(0,0);
19838     nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
19839 }
19840 NK_LIB int
19841 nk_do_button_text(nk_flags *state,
19842     struct nk_command_buffer *out, struct nk_rect bounds,
19843     const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
19844     const struct nk_style_button *style, const struct nk_input *in,
19845     const struct nk_user_font *font)
19846 {
19847     struct nk_rect content;
19848     int ret = nk_false;
19849 
19850     NK_ASSERT(state);
19851     NK_ASSERT(style);
19852     NK_ASSERT(out);
19853     NK_ASSERT(string);
19854     NK_ASSERT(font);
19855     if (!out || !style || !font || !string)
19856         return nk_false;
19857 
19858     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19859     if (style->draw_begin) style->draw_begin(out, style->userdata);
19860     nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
19861     if (style->draw_end) style->draw_end(out, style->userdata);
19862     return ret;
19863 }
19864 NK_LIB void
19865 nk_draw_button_symbol(struct nk_command_buffer *out,
19866     const struct nk_rect *bounds, const struct nk_rect *content,
19867     nk_flags state, const struct nk_style_button *style,
19868     enum nk_symbol_type type, const struct nk_user_font *font)
19869 {
19870     struct nk_color sym, bg;
19871     const struct nk_style_item *background;
19872 
19873     /* select correct colors/images */
19874     background = nk_draw_button(out, bounds, state, style);
19875     if (background->type == NK_STYLE_ITEM_COLOR)
19876         bg = background->data.color;
19877     else bg = style->text_background;
19878 
19879     if (state & NK_WIDGET_STATE_HOVER)
19880         sym = style->text_hover;
19881     else if (state & NK_WIDGET_STATE_ACTIVED)
19882         sym = style->text_active;
19883     else sym = style->text_normal;
19884     nk_draw_symbol(out, type, *content, bg, sym, 1, font);
19885 }
19886 NK_LIB int
19887 nk_do_button_symbol(nk_flags *state,
19888     struct nk_command_buffer *out, struct nk_rect bounds,
19889     enum nk_symbol_type symbol, enum nk_button_behavior behavior,
19890     const struct nk_style_button *style, const struct nk_input *in,
19891     const struct nk_user_font *font)
19892 {
19893     int ret;
19894     struct nk_rect content;
19895 
19896     NK_ASSERT(state);
19897     NK_ASSERT(style);
19898     NK_ASSERT(font);
19899     NK_ASSERT(out);
19900     if (!out || !style || !font || !state)
19901         return nk_false;
19902 
19903     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19904     if (style->draw_begin) style->draw_begin(out, style->userdata);
19905     nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
19906     if (style->draw_end) style->draw_end(out, style->userdata);
19907     return ret;
19908 }
19909 NK_LIB void
19910 nk_draw_button_image(struct nk_command_buffer *out,
19911     const struct nk_rect *bounds, const struct nk_rect *content,
19912     nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
19913 {
19914     nk_draw_button(out, bounds, state, style);
19915     nk_draw_image(out, *content, img, nk_white);
19916 }
19917 NK_LIB int
19918 nk_do_button_image(nk_flags *state,
19919     struct nk_command_buffer *out, struct nk_rect bounds,
19920     struct nk_image img, enum nk_button_behavior b,
19921     const struct nk_style_button *style, const struct nk_input *in)
19922 {
19923     int ret;
19924     struct nk_rect content;
19925 
19926     NK_ASSERT(state);
19927     NK_ASSERT(style);
19928     NK_ASSERT(out);
19929     if (!out || !style || !state)
19930         return nk_false;
19931 
19932     ret = nk_do_button(state, out, bounds, style, in, b, &content);
19933     content.x += style->image_padding.x;
19934     content.y += style->image_padding.y;
19935     content.w -= 2 * style->image_padding.x;
19936     content.h -= 2 * style->image_padding.y;
19937 
19938     if (style->draw_begin) style->draw_begin(out, style->userdata);
19939     nk_draw_button_image(out, &bounds, &content, *state, style, &img);
19940     if (style->draw_end) style->draw_end(out, style->userdata);
19941     return ret;
19942 }
19943 NK_LIB void
19944 nk_draw_button_text_symbol(struct nk_command_buffer *out,
19945     const struct nk_rect *bounds, const struct nk_rect *label,
19946     const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
19947     const char *str, int len, enum nk_symbol_type type,
19948     const struct nk_user_font *font)
19949 {
19950     struct nk_color sym;
19951     struct nk_text text;
19952     const struct nk_style_item *background;
19953 
19954     /* select correct background colors/images */
19955     background = nk_draw_button(out, bounds, state, style);
19956     if (background->type == NK_STYLE_ITEM_COLOR)
19957         text.background = background->data.color;
19958     else text.background = style->text_background;
19959 
19960     /* select correct text colors */
19961     if (state & NK_WIDGET_STATE_HOVER) {
19962         sym = style->text_hover;
19963         text.text = style->text_hover;
19964     } else if (state & NK_WIDGET_STATE_ACTIVED) {
19965         sym = style->text_active;
19966         text.text = style->text_active;
19967     } else {
19968         sym = style->text_normal;
19969         text.text = style->text_normal;
19970     }
19971 
19972     text.padding = nk_vec2(0,0);
19973     nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
19974     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
19975 }
19976 NK_LIB int
19977 nk_do_button_text_symbol(nk_flags *state,
19978     struct nk_command_buffer *out, struct nk_rect bounds,
19979     enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
19980     enum nk_button_behavior behavior, const struct nk_style_button *style,
19981     const struct nk_user_font *font, const struct nk_input *in)
19982 {
19983     int ret;
19984     struct nk_rect tri = {0,0,0,0};
19985     struct nk_rect content;
19986 
19987     NK_ASSERT(style);
19988     NK_ASSERT(out);
19989     NK_ASSERT(font);
19990     if (!out || !style || !font)
19991         return nk_false;
19992 
19993     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
19994     tri.y = content.y + (content.h/2) - font->height/2;
19995     tri.w = font->height; tri.h = font->height;
19996     if (align & NK_TEXT_ALIGN_LEFT) {
19997         tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
19998         tri.x = NK_MAX(tri.x, 0);
19999     } else tri.x = content.x + 2 * style->padding.x;
20000 
20001     /* draw button */
20002     if (style->draw_begin) style->draw_begin(out, style->userdata);
20003     nk_draw_button_text_symbol(out, &bounds, &content, &tri,
20004         *state, style, str, len, symbol, font);
20005     if (style->draw_end) style->draw_end(out, style->userdata);
20006     return ret;
20007 }
20008 NK_LIB void
20009 nk_draw_button_text_image(struct nk_command_buffer *out,
20010     const struct nk_rect *bounds, const struct nk_rect *label,
20011     const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
20012     const char *str, int len, const struct nk_user_font *font,
20013     const struct nk_image *img)
20014 {
20015     struct nk_text text;
20016     const struct nk_style_item *background;
20017     background = nk_draw_button(out, bounds, state, style);
20018 
20019     /* select correct colors */
20020     if (background->type == NK_STYLE_ITEM_COLOR)
20021         text.background = background->data.color;
20022     else text.background = style->text_background;
20023     if (state & NK_WIDGET_STATE_HOVER)
20024         text.text = style->text_hover;
20025     else if (state & NK_WIDGET_STATE_ACTIVED)
20026         text.text = style->text_active;
20027     else text.text = style->text_normal;
20028 
20029     text.padding = nk_vec2(0,0);
20030     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
20031     nk_draw_image(out, *image, img, nk_white);
20032 }
20033 NK_LIB int
20034 nk_do_button_text_image(nk_flags *state,
20035     struct nk_command_buffer *out, struct nk_rect bounds,
20036     struct nk_image img, const char* str, int len, nk_flags align,
20037     enum nk_button_behavior behavior, const struct nk_style_button *style,
20038     const struct nk_user_font *font, const struct nk_input *in)
20039 {
20040     int ret;
20041     struct nk_rect icon;
20042     struct nk_rect content;
20043 
20044     NK_ASSERT(style);
20045     NK_ASSERT(state);
20046     NK_ASSERT(font);
20047     NK_ASSERT(out);
20048     if (!out || !font || !style || !str)
20049         return nk_false;
20050 
20051     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
20052     icon.y = bounds.y + style->padding.y;
20053     icon.w = icon.h = bounds.h - 2 * style->padding.y;
20054     if (align & NK_TEXT_ALIGN_LEFT) {
20055         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
20056         icon.x = NK_MAX(icon.x, 0);
20057     } else icon.x = bounds.x + 2 * style->padding.x;
20058 
20059     icon.x += style->image_padding.x;
20060     icon.y += style->image_padding.y;
20061     icon.w -= 2 * style->image_padding.x;
20062     icon.h -= 2 * style->image_padding.y;
20063 
20064     if (style->draw_begin) style->draw_begin(out, style->userdata);
20065     nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
20066     if (style->draw_end) style->draw_end(out, style->userdata);
20067     return ret;
20068 }
20069 NK_API void
20070 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20071 {
20072     NK_ASSERT(ctx);
20073     if (!ctx) return;
20074     ctx->button_behavior = behavior;
20075 }
20076 NK_API int
20077 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20078 {
20079     struct nk_config_stack_button_behavior *button_stack;
20080     struct nk_config_stack_button_behavior_element *element;
20081 
20082     NK_ASSERT(ctx);
20083     if (!ctx) return 0;
20084 
20085     button_stack = &ctx->stacks.button_behaviors;
20086     NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
20087     if (button_stack->head >= (int)NK_LEN(button_stack->elements))
20088         return 0;
20089 
20090     element = &button_stack->elements[button_stack->head++];
20091     element->address = &ctx->button_behavior;
20092     element->old_value = ctx->button_behavior;
20093     ctx->button_behavior = behavior;
20094     return 1;
20095 }
20096 NK_API int
20097 nk_button_pop_behavior(struct nk_context *ctx)
20098 {
20099     struct nk_config_stack_button_behavior *button_stack;
20100     struct nk_config_stack_button_behavior_element *element;
20101 
20102     NK_ASSERT(ctx);
20103     if (!ctx) return 0;
20104 
20105     button_stack = &ctx->stacks.button_behaviors;
20106     NK_ASSERT(button_stack->head > 0);
20107     if (button_stack->head < 1)
20108         return 0;
20109 
20110     element = &button_stack->elements[--button_stack->head];
20111     *element->address = element->old_value;
20112     return 1;
20113 }
20114 NK_API int
20115 nk_button_text_styled(struct nk_context *ctx,
20116     const struct nk_style_button *style, const char *title, int len)
20117 {
20118     struct nk_window *win;
20119     struct nk_panel *layout;
20120     const struct nk_input *in;
20121 
20122     struct nk_rect bounds;
20123     enum nk_widget_layout_states state;
20124 
20125     NK_ASSERT(ctx);
20126     NK_ASSERT(style);
20127     NK_ASSERT(ctx->current);
20128     NK_ASSERT(ctx->current->layout);
20129     if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
20130 
20131     win = ctx->current;
20132     layout = win->layout;
20133     state = nk_widget(&bounds, ctx);
20134 
20135     if (!state) return 0;
20136     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20137     return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
20138                     title, len, style->text_alignment, ctx->button_behavior,
20139                     style, in, ctx->style.font);
20140 }
20141 NK_API int
20142 nk_button_text(struct nk_context *ctx, const char *title, int len)
20143 {
20144     NK_ASSERT(ctx);
20145     if (!ctx) return 0;
20146     return nk_button_text_styled(ctx, &ctx->style.button, title, len);
20147 }
20148 NK_API int nk_button_label_styled(struct nk_context *ctx,
20149     const struct nk_style_button *style, const char *title)
20150 {
20151     return nk_button_text_styled(ctx, style, title, nk_strlen(title));
20152 }
20153 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
20154 {
20155     return nk_button_text(ctx, title, nk_strlen(title));
20156 }
20157 NK_API int
20158 nk_button_color(struct nk_context *ctx, struct nk_color color)
20159 {
20160     struct nk_window *win;
20161     struct nk_panel *layout;
20162     const struct nk_input *in;
20163     struct nk_style_button button;
20164 
20165     int ret = 0;
20166     struct nk_rect bounds;
20167     struct nk_rect content;
20168     enum nk_widget_layout_states state;
20169 
20170     NK_ASSERT(ctx);
20171     NK_ASSERT(ctx->current);
20172     NK_ASSERT(ctx->current->layout);
20173     if (!ctx || !ctx->current || !ctx->current->layout)
20174         return 0;
20175 
20176     win = ctx->current;
20177     layout = win->layout;
20178 
20179     state = nk_widget(&bounds, ctx);
20180     if (!state) return 0;
20181     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20182 
20183     button = ctx->style.button;
20184     button.normal = nk_style_item_color(color);
20185     button.hover = nk_style_item_color(color);
20186     button.active = nk_style_item_color(color);
20187     ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
20188                 &button, in, ctx->button_behavior, &content);
20189     nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
20190     return ret;
20191 }
20192 NK_API int
20193 nk_button_symbol_styled(struct nk_context *ctx,
20194     const struct nk_style_button *style, enum nk_symbol_type symbol)
20195 {
20196     struct nk_window *win;
20197     struct nk_panel *layout;
20198     const struct nk_input *in;
20199 
20200     struct nk_rect bounds;
20201     enum nk_widget_layout_states state;
20202 
20203     NK_ASSERT(ctx);
20204     NK_ASSERT(ctx->current);
20205     NK_ASSERT(ctx->current->layout);
20206     if (!ctx || !ctx->current || !ctx->current->layout)
20207         return 0;
20208 
20209     win = ctx->current;
20210     layout = win->layout;
20211     state = nk_widget(&bounds, ctx);
20212     if (!state) return 0;
20213     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20214     return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20215             symbol, ctx->button_behavior, style, in, ctx->style.font);
20216 }
20217 NK_API int
20218 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
20219 {
20220     NK_ASSERT(ctx);
20221     if (!ctx) return 0;
20222     return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
20223 }
20224 NK_API int
20225 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
20226     struct nk_image img)
20227 {
20228     struct nk_window *win;
20229     struct nk_panel *layout;
20230     const struct nk_input *in;
20231 
20232     struct nk_rect bounds;
20233     enum nk_widget_layout_states state;
20234 
20235     NK_ASSERT(ctx);
20236     NK_ASSERT(ctx->current);
20237     NK_ASSERT(ctx->current->layout);
20238     if (!ctx || !ctx->current || !ctx->current->layout)
20239         return 0;
20240 
20241     win = ctx->current;
20242     layout = win->layout;
20243 
20244     state = nk_widget(&bounds, ctx);
20245     if (!state) return 0;
20246     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20247     return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
20248                 img, ctx->button_behavior, style, in);
20249 }
20250 NK_API int
20251 nk_button_image(struct nk_context *ctx, struct nk_image img)
20252 {
20253     NK_ASSERT(ctx);
20254     if (!ctx) return 0;
20255     return nk_button_image_styled(ctx, &ctx->style.button, img);
20256 }
20257 NK_API int
20258 nk_button_symbol_text_styled(struct nk_context *ctx,
20259     const struct nk_style_button *style, enum nk_symbol_type symbol,
20260     const char *text, int len, nk_flags align)
20261 {
20262     struct nk_window *win;
20263     struct nk_panel *layout;
20264     const struct nk_input *in;
20265 
20266     struct nk_rect bounds;
20267     enum nk_widget_layout_states state;
20268 
20269     NK_ASSERT(ctx);
20270     NK_ASSERT(ctx->current);
20271     NK_ASSERT(ctx->current->layout);
20272     if (!ctx || !ctx->current || !ctx->current->layout)
20273         return 0;
20274 
20275     win = ctx->current;
20276     layout = win->layout;
20277 
20278     state = nk_widget(&bounds, ctx);
20279     if (!state) return 0;
20280     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20281     return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20282                 symbol, text, len, align, ctx->button_behavior,
20283                 style, ctx->style.font, in);
20284 }
20285 NK_API int
20286 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
20287     const char* text, int len, nk_flags align)
20288 {
20289     NK_ASSERT(ctx);
20290     if (!ctx) return 0;
20291     return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
20292 }
20293 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
20294     const char *label, nk_flags align)
20295 {
20296     return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);
20297 }
20298 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx,
20299     const struct nk_style_button *style, enum nk_symbol_type symbol,
20300     const char *title, nk_flags align)
20301 {
20302     return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);
20303 }
20304 NK_API int
20305 nk_button_image_text_styled(struct nk_context *ctx,
20306     const struct nk_style_button *style, struct nk_image img, const char *text,
20307     int len, nk_flags align)
20308 {
20309     struct nk_window *win;
20310     struct nk_panel *layout;
20311     const struct nk_input *in;
20312 
20313     struct nk_rect bounds;
20314     enum nk_widget_layout_states state;
20315 
20316     NK_ASSERT(ctx);
20317     NK_ASSERT(ctx->current);
20318     NK_ASSERT(ctx->current->layout);
20319     if (!ctx || !ctx->current || !ctx->current->layout)
20320         return 0;
20321 
20322     win = ctx->current;
20323     layout = win->layout;
20324 
20325     state = nk_widget(&bounds, ctx);
20326     if (!state) return 0;
20327     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20328     return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
20329             bounds, img, text, len, align, ctx->button_behavior,
20330             style, ctx->style.font, in);
20331 }
20332 NK_API int
20333 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
20334     const char *text, int len, nk_flags align)
20335 {
20336     return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);
20337 }
20338 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
20339     const char *label, nk_flags align)
20340 {
20341     return nk_button_image_text(ctx, img, label, nk_strlen(label), align);
20342 }
20343 NK_API int nk_button_image_label_styled(struct nk_context *ctx,
20344     const struct nk_style_button *style, struct nk_image img,
20345     const char *label, nk_flags text_alignment)
20346 {
20347     return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);
20348 }
20349 
20350 
20351 
20352 
20353 
20354 /* ===============================================================
20355  *
20356  *                              TOGGLE
20357  *
20358  * ===============================================================*/
20359 NK_LIB int
20360 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
20361     nk_flags *state, int active)
20362 {
20363     nk_widget_state_reset(state);
20364     if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
20365         *state = NK_WIDGET_STATE_ACTIVE;
20366         active = !active;
20367     }
20368     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
20369         *state |= NK_WIDGET_STATE_ENTERED;
20370     else if (nk_input_is_mouse_prev_hovering_rect(in, select))
20371         *state |= NK_WIDGET_STATE_LEFT;
20372     return active;
20373 }
20374 NK_LIB void
20375 nk_draw_checkbox(struct nk_command_buffer *out,
20376     nk_flags state, const struct nk_style_toggle *style, int active,
20377     const struct nk_rect *label, const struct nk_rect *selector,
20378     const struct nk_rect *cursors, const char *string, int len,
20379     const struct nk_user_font *font)
20380 {
20381     const struct nk_style_item *background;
20382     const struct nk_style_item *cursor;
20383     struct nk_text text;
20384 
20385     /* select correct colors/images */
20386     if (state & NK_WIDGET_STATE_HOVER) {
20387         background = &style->hover;
20388         cursor = &style->cursor_hover;
20389         text.text = style->text_hover;
20390     } else if (state & NK_WIDGET_STATE_ACTIVED) {
20391         background = &style->hover;
20392         cursor = &style->cursor_hover;
20393         text.text = style->text_active;
20394     } else {
20395         background = &style->normal;
20396         cursor = &style->cursor_normal;
20397         text.text = style->text_normal;
20398     }
20399 
20400     /* draw background and cursor */
20401     if (background->type == NK_STYLE_ITEM_COLOR) {
20402         nk_fill_rect(out, *selector, 0, style->border_color);
20403         nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
20404     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
20405     if (active) {
20406         if (cursor->type == NK_STYLE_ITEM_IMAGE)
20407             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
20408         else nk_fill_rect(out, *cursors, 0, cursor->data.color);
20409     }
20410 
20411     text.padding.x = 0;
20412     text.padding.y = 0;
20413     text.background = style->text_background;
20414     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
20415 }
20416 NK_LIB void
20417 nk_draw_option(struct nk_command_buffer *out,
20418     nk_flags state, const struct nk_style_toggle *style, int active,
20419     const struct nk_rect *label, const struct nk_rect *selector,
20420     const struct nk_rect *cursors, const char *string, int len,
20421     const struct nk_user_font *font)
20422 {
20423     const struct nk_style_item *background;
20424     const struct nk_style_item *cursor;
20425     struct nk_text text;
20426 
20427     /* select correct colors/images */
20428     if (state & NK_WIDGET_STATE_HOVER) {
20429         background = &style->hover;
20430         cursor = &style->cursor_hover;
20431         text.text = style->text_hover;
20432     } else if (state & NK_WIDGET_STATE_ACTIVED) {
20433         background = &style->hover;
20434         cursor = &style->cursor_hover;
20435         text.text = style->text_active;
20436     } else {
20437         background = &style->normal;
20438         cursor = &style->cursor_normal;
20439         text.text = style->text_normal;
20440     }
20441 
20442     /* draw background and cursor */
20443     if (background->type == NK_STYLE_ITEM_COLOR) {
20444         nk_fill_circle(out, *selector, style->border_color);
20445         nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
20446     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
20447     if (active) {
20448         if (cursor->type == NK_STYLE_ITEM_IMAGE)
20449             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
20450         else nk_fill_circle(out, *cursors, cursor->data.color);
20451     }
20452 
20453     text.padding.x = 0;
20454     text.padding.y = 0;
20455     text.background = style->text_background;
20456     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
20457 }
20458 NK_LIB int
20459 nk_do_toggle(nk_flags *state,
20460     struct nk_command_buffer *out, struct nk_rect r,
20461     int *active, const char *str, int len, enum nk_toggle_type type,
20462     const struct nk_style_toggle *style, const struct nk_input *in,
20463     const struct nk_user_font *font)
20464 {
20465     int was_active;
20466     struct nk_rect bounds;
20467     struct nk_rect select;
20468     struct nk_rect cursor;
20469     struct nk_rect label;
20470 
20471     NK_ASSERT(style);
20472     NK_ASSERT(out);
20473     NK_ASSERT(font);
20474     if (!out || !style || !font || !active)
20475         return 0;
20476 
20477     r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
20478     r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
20479 
20480     /* add additional touch padding for touch screen devices */
20481     bounds.x = r.x - style->touch_padding.x;
20482     bounds.y = r.y - style->touch_padding.y;
20483     bounds.w = r.w + 2 * style->touch_padding.x;
20484     bounds.h = r.h + 2 * style->touch_padding.y;
20485 
20486     /* calculate the selector space */
20487     select.w = font->height;
20488     select.h = select.w;
20489     select.y = r.y + r.h/2.0f - select.h/2.0f;
20490     select.x = r.x;
20491 
20492     /* calculate the bounds of the cursor inside the selector */
20493     cursor.x = select.x + style->padding.x + style->border;
20494     cursor.y = select.y + style->padding.y + style->border;
20495     cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
20496     cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
20497 
20498     /* label behind the selector */
20499     label.x = select.x + select.w + style->spacing;
20500     label.y = select.y;
20501     label.w = NK_MAX(r.x + r.w, label.x) - label.x;
20502     label.h = select.w;
20503 
20504     /* update selector */
20505     was_active = *active;
20506     *active = nk_toggle_behavior(in, bounds, state, *active);
20507 
20508     /* draw selector */
20509     if (style->draw_begin)
20510         style->draw_begin(out, style->userdata);
20511     if (type == NK_TOGGLE_CHECK) {
20512         nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
20513     } else {
20514         nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
20515     }
20516     if (style->draw_end)
20517         style->draw_end(out, style->userdata);
20518     return (was_active != *active);
20519 }
20520 /*----------------------------------------------------------------
20521  *
20522  *                          CHECKBOX
20523  *
20524  * --------------------------------------------------------------*/
20525 NK_API int
20526 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
20527 {
20528     struct nk_window *win;
20529     struct nk_panel *layout;
20530     const struct nk_input *in;
20531     const struct nk_style *style;
20532 
20533     struct nk_rect bounds;
20534     enum nk_widget_layout_states state;
20535 
20536     NK_ASSERT(ctx);
20537     NK_ASSERT(ctx->current);
20538     NK_ASSERT(ctx->current->layout);
20539     if (!ctx || !ctx->current || !ctx->current->layout)
20540         return active;
20541 
20542     win = ctx->current;
20543     style = &ctx->style;
20544     layout = win->layout;
20545 
20546     state = nk_widget(&bounds, ctx);
20547     if (!state) return active;
20548     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20549     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
20550         text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
20551     return active;
20552 }
20553 NK_API unsigned int
20554 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
20555     unsigned int flags, unsigned int value)
20556 {
20557     int old_active;
20558     NK_ASSERT(ctx);
20559     NK_ASSERT(text);
20560     if (!ctx || !text) return flags;
20561     old_active = (int)((flags & value) & value);
20562     if (nk_check_text(ctx, text, len, old_active))
20563         flags |= value;
20564     else flags &= ~value;
20565     return flags;
20566 }
20567 NK_API int
20568 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
20569 {
20570     int old_val;
20571     NK_ASSERT(ctx);
20572     NK_ASSERT(text);
20573     NK_ASSERT(active);
20574     if (!ctx || !text || !active) return 0;
20575     old_val = *active;
20576     *active = nk_check_text(ctx, text, len, *active);
20577     return old_val != *active;
20578 }
20579 NK_API int
20580 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
20581     unsigned int *flags, unsigned int value)
20582 {
20583     int active;
20584     NK_ASSERT(ctx);
20585     NK_ASSERT(text);
20586     NK_ASSERT(flags);
20587     if (!ctx || !text || !flags) return 0;
20588 
20589     active = (int)((*flags & value) & value);
20590     if (nk_checkbox_text(ctx, text, len, &active)) {
20591         if (active) *flags |= value;
20592         else *flags &= ~value;
20593         return 1;
20594     }
20595     return 0;
20596 }
20597 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
20598 {
20599     return nk_check_text(ctx, label, nk_strlen(label), active);
20600 }
20601 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
20602     unsigned int flags, unsigned int value)
20603 {
20604     return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);
20605 }
20606 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
20607 {
20608     return nk_checkbox_text(ctx, label, nk_strlen(label), active);
20609 }
20610 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
20611     unsigned int *flags, unsigned int value)
20612 {
20613     return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);
20614 }
20615 /*----------------------------------------------------------------
20616  *
20617  *                          OPTION
20618  *
20619  * --------------------------------------------------------------*/
20620 NK_API int
20621 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
20622 {
20623     struct nk_window *win;
20624     struct nk_panel *layout;
20625     const struct nk_input *in;
20626     const struct nk_style *style;
20627 
20628     struct nk_rect bounds;
20629     enum nk_widget_layout_states state;
20630 
20631     NK_ASSERT(ctx);
20632     NK_ASSERT(ctx->current);
20633     NK_ASSERT(ctx->current->layout);
20634     if (!ctx || !ctx->current || !ctx->current->layout)
20635         return is_active;
20636 
20637     win = ctx->current;
20638     style = &ctx->style;
20639     layout = win->layout;
20640 
20641     state = nk_widget(&bounds, ctx);
20642     if (!state) return (int)state;
20643     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20644     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
20645         text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
20646     return is_active;
20647 }
20648 NK_API int
20649 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
20650 {
20651     int old_value;
20652     NK_ASSERT(ctx);
20653     NK_ASSERT(text);
20654     NK_ASSERT(active);
20655     if (!ctx || !text || !active) return 0;
20656     old_value = *active;
20657     *active = nk_option_text(ctx, text, len, old_value);
20658     return old_value != *active;
20659 }
20660 NK_API int
20661 nk_option_label(struct nk_context *ctx, const char *label, int active)
20662 {
20663     return nk_option_text(ctx, label, nk_strlen(label), active);
20664 }
20665 NK_API int
20666 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
20667 {
20668     return nk_radio_text(ctx, label, nk_strlen(label), active);
20669 }
20670 
20671 
20672 
20673 
20674 
20675 /* ===============================================================
20676  *
20677  *                              SELECTABLE
20678  *
20679  * ===============================================================*/
20680 NK_LIB void
20681 nk_draw_selectable(struct nk_command_buffer *out,
20682     nk_flags state, const struct nk_style_selectable *style, int active,
20683     const struct nk_rect *bounds,
20684     const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym,
20685     const char *string, int len, nk_flags align, const struct nk_user_font *font)
20686 {
20687     const struct nk_style_item *background;
20688     struct nk_text text;
20689     text.padding = style->padding;
20690 
20691     /* select correct colors/images */
20692     if (!active) {
20693         if (state & NK_WIDGET_STATE_ACTIVED) {
20694             background = &style->pressed;
20695             text.text = style->text_pressed;
20696         } else if (state & NK_WIDGET_STATE_HOVER) {
20697             background = &style->hover;
20698             text.text = style->text_hover;
20699         } else {
20700             background = &style->normal;
20701             text.text = style->text_normal;
20702         }
20703     } else {
20704         if (state & NK_WIDGET_STATE_ACTIVED) {
20705             background = &style->pressed_active;
20706             text.text = style->text_pressed_active;
20707         } else if (state & NK_WIDGET_STATE_HOVER) {
20708             background = &style->hover_active;
20709             text.text = style->text_hover_active;
20710         } else {
20711             background = &style->normal_active;
20712             text.text = style->text_normal_active;
20713         }
20714     }
20715     /* draw selectable background and text */
20716     if (background->type == NK_STYLE_ITEM_IMAGE) {
20717         nk_draw_image(out, *bounds, &background->data.image, nk_white);
20718         text.background = nk_rgba(0,0,0,0);
20719     } else {
20720         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
20721         text.background = background->data.color;
20722     }
20723     if (icon) {
20724         if (img) nk_draw_image(out, *icon, img, nk_white);
20725         else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font);
20726     }
20727     nk_widget_text(out, *bounds, string, len, &text, align, font);
20728 }
20729 NK_LIB int
20730 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
20731     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20732     const struct nk_style_selectable *style, const struct nk_input *in,
20733     const struct nk_user_font *font)
20734 {
20735     int old_value;
20736     struct nk_rect touch;
20737 
20738     NK_ASSERT(state);
20739     NK_ASSERT(out);
20740     NK_ASSERT(str);
20741     NK_ASSERT(len);
20742     NK_ASSERT(value);
20743     NK_ASSERT(style);
20744     NK_ASSERT(font);
20745 
20746     if (!state || !out || !str || !len || !value || !style || !font) return 0;
20747     old_value = *value;
20748 
20749     /* remove padding */
20750     touch.x = bounds.x - style->touch_padding.x;
20751     touch.y = bounds.y - style->touch_padding.y;
20752     touch.w = bounds.w + style->touch_padding.x * 2;
20753     touch.h = bounds.h + style->touch_padding.y * 2;
20754 
20755     /* update button */
20756     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20757         *value = !(*value);
20758 
20759     /* draw selectable */
20760     if (style->draw_begin) style->draw_begin(out, style->userdata);
20761     nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font);
20762     if (style->draw_end) style->draw_end(out, style->userdata);
20763     return old_value != *value;
20764 }
20765 NK_LIB int
20766 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
20767     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20768     const struct nk_image *img, const struct nk_style_selectable *style,
20769     const struct nk_input *in, const struct nk_user_font *font)
20770 {
20771     int old_value;
20772     struct nk_rect touch;
20773     struct nk_rect icon;
20774 
20775     NK_ASSERT(state);
20776     NK_ASSERT(out);
20777     NK_ASSERT(str);
20778     NK_ASSERT(len);
20779     NK_ASSERT(value);
20780     NK_ASSERT(style);
20781     NK_ASSERT(font);
20782 
20783     if (!state || !out || !str || !len || !value || !style || !font) return 0;
20784     old_value = *value;
20785 
20786     /* toggle behavior */
20787     touch.x = bounds.x - style->touch_padding.x;
20788     touch.y = bounds.y - style->touch_padding.y;
20789     touch.w = bounds.w + style->touch_padding.x * 2;
20790     touch.h = bounds.h + style->touch_padding.y * 2;
20791     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20792         *value = !(*value);
20793 
20794     icon.y = bounds.y + style->padding.y;
20795     icon.w = icon.h = bounds.h - 2 * style->padding.y;
20796     if (align & NK_TEXT_ALIGN_LEFT) {
20797         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
20798         icon.x = NK_MAX(icon.x, 0);
20799     } else icon.x = bounds.x + 2 * style->padding.x;
20800 
20801     icon.x += style->image_padding.x;
20802     icon.y += style->image_padding.y;
20803     icon.w -= 2 * style->image_padding.x;
20804     icon.h -= 2 * style->image_padding.y;
20805 
20806     /* draw selectable */
20807     if (style->draw_begin) style->draw_begin(out, style->userdata);
20808     nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font);
20809     if (style->draw_end) style->draw_end(out, style->userdata);
20810     return old_value != *value;
20811 }
20812 NK_LIB int
20813 nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out,
20814     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
20815     enum nk_symbol_type sym, const struct nk_style_selectable *style,
20816     const struct nk_input *in, const struct nk_user_font *font)
20817 {
20818     int old_value;
20819     struct nk_rect touch;
20820     struct nk_rect icon;
20821 
20822     NK_ASSERT(state);
20823     NK_ASSERT(out);
20824     NK_ASSERT(str);
20825     NK_ASSERT(len);
20826     NK_ASSERT(value);
20827     NK_ASSERT(style);
20828     NK_ASSERT(font);
20829 
20830     if (!state || !out || !str || !len || !value || !style || !font) return 0;
20831     old_value = *value;
20832 
20833     /* toggle behavior */
20834     touch.x = bounds.x - style->touch_padding.x;
20835     touch.y = bounds.y - style->touch_padding.y;
20836     touch.w = bounds.w + style->touch_padding.x * 2;
20837     touch.h = bounds.h + style->touch_padding.y * 2;
20838     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
20839         *value = !(*value);
20840 
20841     icon.y = bounds.y + style->padding.y;
20842     icon.w = icon.h = bounds.h - 2 * style->padding.y;
20843     if (align & NK_TEXT_ALIGN_LEFT) {
20844         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
20845         icon.x = NK_MAX(icon.x, 0);
20846     } else icon.x = bounds.x + 2 * style->padding.x;
20847 
20848     icon.x += style->image_padding.x;
20849     icon.y += style->image_padding.y;
20850     icon.w -= 2 * style->image_padding.x;
20851     icon.h -= 2 * style->image_padding.y;
20852 
20853     /* draw selectable */
20854     if (style->draw_begin) style->draw_begin(out, style->userdata);
20855     nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font);
20856     if (style->draw_end) style->draw_end(out, style->userdata);
20857     return old_value != *value;
20858 }
20859 
20860 NK_API int
20861 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
20862     nk_flags align, int *value)
20863 {
20864     struct nk_window *win;
20865     struct nk_panel *layout;
20866     const struct nk_input *in;
20867     const struct nk_style *style;
20868 
20869     enum nk_widget_layout_states state;
20870     struct nk_rect bounds;
20871 
20872     NK_ASSERT(ctx);
20873     NK_ASSERT(value);
20874     NK_ASSERT(ctx->current);
20875     NK_ASSERT(ctx->current->layout);
20876     if (!ctx || !ctx->current || !ctx->current->layout || !value)
20877         return 0;
20878 
20879     win = ctx->current;
20880     layout = win->layout;
20881     style = &ctx->style;
20882 
20883     state = nk_widget(&bounds, ctx);
20884     if (!state) return 0;
20885     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20886     return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
20887                 str, len, align, value, &style->selectable, in, style->font);
20888 }
20889 NK_API int
20890 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
20891     const char *str, int len, nk_flags align, int *value)
20892 {
20893     struct nk_window *win;
20894     struct nk_panel *layout;
20895     const struct nk_input *in;
20896     const struct nk_style *style;
20897 
20898     enum nk_widget_layout_states state;
20899     struct nk_rect bounds;
20900 
20901     NK_ASSERT(ctx);
20902     NK_ASSERT(value);
20903     NK_ASSERT(ctx->current);
20904     NK_ASSERT(ctx->current->layout);
20905     if (!ctx || !ctx->current || !ctx->current->layout || !value)
20906         return 0;
20907 
20908     win = ctx->current;
20909     layout = win->layout;
20910     style = &ctx->style;
20911 
20912     state = nk_widget(&bounds, ctx);
20913     if (!state) return 0;
20914     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20915     return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
20916                 str, len, align, value, &img, &style->selectable, in, style->font);
20917 }
20918 NK_API int
20919 nk_selectable_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
20920     const char *str, int len, nk_flags align, int *value)
20921 {
20922     struct nk_window *win;
20923     struct nk_panel *layout;
20924     const struct nk_input *in;
20925     const struct nk_style *style;
20926 
20927     enum nk_widget_layout_states state;
20928     struct nk_rect bounds;
20929 
20930     NK_ASSERT(ctx);
20931     NK_ASSERT(value);
20932     NK_ASSERT(ctx->current);
20933     NK_ASSERT(ctx->current->layout);
20934     if (!ctx || !ctx->current || !ctx->current->layout || !value)
20935         return 0;
20936 
20937     win = ctx->current;
20938     layout = win->layout;
20939     style = &ctx->style;
20940 
20941     state = nk_widget(&bounds, ctx);
20942     if (!state) return 0;
20943     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20944     return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20945                 str, len, align, value, sym, &style->selectable, in, style->font);
20946 }
20947 NK_API int
20948 nk_selectable_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
20949     const char *title, nk_flags align, int *value)
20950 {
20951     return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
20952 }
20953 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
20954     nk_flags align, int value)
20955 {
20956     nk_selectable_text(ctx, str, len, align, &value);return value;
20957 }
20958 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
20959 {
20960     return nk_selectable_text(ctx, str, nk_strlen(str), align, value);
20961 }
20962 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
20963     const char *str, nk_flags align, int *value)
20964 {
20965     return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);
20966 }
20967 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
20968 {
20969     nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;
20970 }
20971 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
20972     const char *str, nk_flags align, int value)
20973 {
20974     nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;
20975 }
20976 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
20977     const char *str, int len, nk_flags align, int value)
20978 {
20979     nk_selectable_image_text(ctx, img, str, len, align, &value);return value;
20980 }
20981 NK_API int
20982 nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
20983     const char *title, int title_len, nk_flags align, int value)
20984 {
20985     nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value;
20986 }
20987 NK_API int
20988 nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
20989     const char *title, nk_flags align, int value)
20990 {
20991     return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
20992 }
20993 
20994 
20995 
20996 
20997 
20998 /* ===============================================================
20999  *
21000  *                              SLIDER
21001  *
21002  * ===============================================================*/
21003 NK_LIB float
21004 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
21005     struct nk_rect *visual_cursor, struct nk_input *in,
21006     struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
21007     float slider_step, float slider_steps)
21008 {
21009     int left_mouse_down;
21010     int left_mouse_click_in_cursor;
21011 
21012     /* check if visual cursor is being dragged */
21013     nk_widget_state_reset(state);
21014     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
21015     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
21016             NK_BUTTON_LEFT, *visual_cursor, nk_true);
21017 
21018     if (left_mouse_down && left_mouse_click_in_cursor) {
21019         float ratio = 0;
21020         const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
21021         const float pxstep = bounds.w / slider_steps;
21022 
21023         /* only update value if the next slider step is reached */
21024         *state = NK_WIDGET_STATE_ACTIVE;
21025         if (NK_ABS(d) >= pxstep) {
21026             const float steps = (float)((int)(NK_ABS(d) / pxstep));
21027             slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
21028             slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
21029             ratio = (slider_value - slider_min)/slider_step;
21030             logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
21031             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
21032         }
21033     }
21034 
21035     /* slider widget state */
21036     if (nk_input_is_mouse_hovering_rect(in, bounds))
21037         *state = NK_WIDGET_STATE_HOVERED;
21038     if (*state & NK_WIDGET_STATE_HOVER &&
21039         !nk_input_is_mouse_prev_hovering_rect(in, bounds))
21040         *state |= NK_WIDGET_STATE_ENTERED;
21041     else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
21042         *state |= NK_WIDGET_STATE_LEFT;
21043     return slider_value;
21044 }
21045 NK_LIB void
21046 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
21047     const struct nk_style_slider *style, const struct nk_rect *bounds,
21048     const struct nk_rect *visual_cursor, float min, float value, float max)
21049 {
21050     struct nk_rect fill;
21051     struct nk_rect bar;
21052     const struct nk_style_item *background;
21053 
21054     /* select correct slider images/colors */
21055     struct nk_color bar_color;
21056     const struct nk_style_item *cursor;
21057 
21058     NK_UNUSED(min);
21059     NK_UNUSED(max);
21060     NK_UNUSED(value);
21061 
21062     if (state & NK_WIDGET_STATE_ACTIVED) {
21063         background = &style->active;
21064         bar_color = style->bar_active;
21065         cursor = &style->cursor_active;
21066     } else if (state & NK_WIDGET_STATE_HOVER) {
21067         background = &style->hover;
21068         bar_color = style->bar_hover;
21069         cursor = &style->cursor_hover;
21070     } else {
21071         background = &style->normal;
21072         bar_color = style->bar_normal;
21073         cursor = &style->cursor_normal;
21074     }
21075     /* calculate slider background bar */
21076     bar.x = bounds->x;
21077     bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
21078     bar.w = bounds->w;
21079     bar.h = bounds->h/6;
21080 
21081     /* filled background bar style */
21082     fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
21083     fill.x = bar.x;
21084     fill.y = bar.y;
21085     fill.h = bar.h;
21086 
21087     /* draw background */
21088     if (background->type == NK_STYLE_ITEM_IMAGE) {
21089         nk_draw_image(out, *bounds, &background->data.image, nk_white);
21090     } else {
21091         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
21092         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
21093     }
21094 
21095     /* draw slider bar */
21096     nk_fill_rect(out, bar, style->rounding, bar_color);
21097     nk_fill_rect(out, fill, style->rounding, style->bar_filled);
21098 
21099     /* draw cursor */
21100     if (cursor->type == NK_STYLE_ITEM_IMAGE)
21101         nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
21102     else nk_fill_circle(out, *visual_cursor, cursor->data.color);
21103 }
21104 NK_LIB float
21105 nk_do_slider(nk_flags *state,
21106     struct nk_command_buffer *out, struct nk_rect bounds,
21107     float min, float val, float max, float step,
21108     const struct nk_style_slider *style, struct nk_input *in,
21109     const struct nk_user_font *font)
21110 {
21111     float slider_range;
21112     float slider_min;
21113     float slider_max;
21114     float slider_value;
21115     float slider_steps;
21116     float cursor_offset;
21117 
21118     struct nk_rect visual_cursor;
21119     struct nk_rect logical_cursor;
21120 
21121     NK_ASSERT(style);
21122     NK_ASSERT(out);
21123     if (!out || !style)
21124         return 0;
21125 
21126     /* remove padding from slider bounds */
21127     bounds.x = bounds.x + style->padding.x;
21128     bounds.y = bounds.y + style->padding.y;
21129     bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
21130     bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
21131     bounds.w -= 2 * style->padding.x;
21132     bounds.h -= 2 * style->padding.y;
21133 
21134     /* optional buttons */
21135     if (style->show_buttons) {
21136         nk_flags ws;
21137         struct nk_rect button;
21138         button.y = bounds.y;
21139         button.w = bounds.h;
21140         button.h = bounds.h;
21141 
21142         /* decrement button */
21143         button.x = bounds.x;
21144         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
21145             &style->dec_button, in, font))
21146             val -= step;
21147 
21148         /* increment button */
21149         button.x = (bounds.x + bounds.w) - button.w;
21150         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
21151             &style->inc_button, in, font))
21152             val += step;
21153 
21154         bounds.x = bounds.x + button.w + style->spacing.x;
21155         bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
21156     }
21157 
21158     /* remove one cursor size to support visual cursor */
21159     bounds.x += style->cursor_size.x*0.5f;
21160     bounds.w -= style->cursor_size.x;
21161 
21162     /* make sure the provided values are correct */
21163     slider_max = NK_MAX(min, max);
21164     slider_min = NK_MIN(min, max);
21165     slider_value = NK_CLAMP(slider_min, val, slider_max);
21166     slider_range = slider_max - slider_min;
21167     slider_steps = slider_range / step;
21168     cursor_offset = (slider_value - slider_min) / step;
21169 
21170     /* calculate cursor
21171     Basically you have two cursors. One for visual representation and interaction
21172     and one for updating the actual cursor value. */
21173     logical_cursor.h = bounds.h;
21174     logical_cursor.w = bounds.w / slider_steps;
21175     logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
21176     logical_cursor.y = bounds.y;
21177 
21178     visual_cursor.h = style->cursor_size.y;
21179     visual_cursor.w = style->cursor_size.x;
21180     visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
21181     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
21182 
21183     slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
21184         in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
21185     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
21186 
21187     /* draw slider */
21188     if (style->draw_begin) style->draw_begin(out, style->userdata);
21189     nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
21190     if (style->draw_end) style->draw_end(out, style->userdata);
21191     return slider_value;
21192 }
21193 NK_API int
21194 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
21195     float value_step)
21196 {
21197     struct nk_window *win;
21198     struct nk_panel *layout;
21199     struct nk_input *in;
21200     const struct nk_style *style;
21201 
21202     int ret = 0;
21203     float old_value;
21204     struct nk_rect bounds;
21205     enum nk_widget_layout_states state;
21206 
21207     NK_ASSERT(ctx);
21208     NK_ASSERT(ctx->current);
21209     NK_ASSERT(ctx->current->layout);
21210     NK_ASSERT(value);
21211     if (!ctx || !ctx->current || !ctx->current->layout || !value)
21212         return ret;
21213 
21214     win = ctx->current;
21215     style = &ctx->style;
21216     layout = win->layout;
21217 
21218     state = nk_widget(&bounds, ctx);
21219     if (!state) return ret;
21220     in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21221 
21222     old_value = *value;
21223     *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
21224                 old_value, max_value, value_step, &style->slider, in, style->font);
21225     return (old_value > *value || old_value < *value);
21226 }
21227 NK_API float
21228 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
21229 {
21230     nk_slider_float(ctx, min, &val, max, step); return val;
21231 }
21232 NK_API int
21233 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
21234 {
21235     float value = (float)val;
21236     nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21237     return (int)value;
21238 }
21239 NK_API int
21240 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
21241 {
21242     int ret;
21243     float value = (float)*val;
21244     ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21245     *val =  (int)value;
21246     return ret;
21247 }
21248 
21249 
21250 
21251 
21252 
21253 /* ===============================================================
21254  *
21255  *                          PROGRESS
21256  *
21257  * ===============================================================*/
21258 NK_LIB nk_size
21259 nk_progress_behavior(nk_flags *state, struct nk_input *in,
21260     struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable)
21261 {
21262     int left_mouse_down = 0;
21263     int left_mouse_click_in_cursor = 0;
21264 
21265     nk_widget_state_reset(state);
21266     if (!in || !modifiable) return value;
21267     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
21268     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
21269             NK_BUTTON_LEFT, cursor, nk_true);
21270     if (nk_input_is_mouse_hovering_rect(in, r))
21271         *state = NK_WIDGET_STATE_HOVERED;
21272 
21273     if (in && left_mouse_down && left_mouse_click_in_cursor) {
21274         if (left_mouse_down && left_mouse_click_in_cursor) {
21275             float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w;
21276             value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max);
21277             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f;
21278             *state |= NK_WIDGET_STATE_ACTIVE;
21279         }
21280     }
21281     /* set progressbar widget state */
21282     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
21283         *state |= NK_WIDGET_STATE_ENTERED;
21284     else if (nk_input_is_mouse_prev_hovering_rect(in, r))
21285         *state |= NK_WIDGET_STATE_LEFT;
21286     return value;
21287 }
21288 NK_LIB void
21289 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
21290     const struct nk_style_progress *style, const struct nk_rect *bounds,
21291     const struct nk_rect *scursor, nk_size value, nk_size max)
21292 {
21293     const struct nk_style_item *background;
21294     const struct nk_style_item *cursor;
21295 
21296     NK_UNUSED(max);
21297     NK_UNUSED(value);
21298 
21299     /* select correct colors/images to draw */
21300     if (state & NK_WIDGET_STATE_ACTIVED) {
21301         background = &style->active;
21302         cursor = &style->cursor_active;
21303     } else if (state & NK_WIDGET_STATE_HOVER){
21304         background = &style->hover;
21305         cursor = &style->cursor_hover;
21306     } else {
21307         background = &style->normal;
21308         cursor = &style->cursor_normal;
21309     }
21310 
21311     /* draw background */
21312     if (background->type == NK_STYLE_ITEM_COLOR) {
21313         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
21314         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
21315     } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
21316 
21317     /* draw cursor */
21318     if (cursor->type == NK_STYLE_ITEM_COLOR) {
21319         nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
21320         nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
21321     } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
21322 }
21323 NK_LIB nk_size
21324 nk_do_progress(nk_flags *state,
21325     struct nk_command_buffer *out, struct nk_rect bounds,
21326     nk_size value, nk_size max, int modifiable,
21327     const struct nk_style_progress *style, struct nk_input *in)
21328 {
21329     float prog_scale;
21330     nk_size prog_value;
21331     struct nk_rect cursor;
21332 
21333     NK_ASSERT(style);
21334     NK_ASSERT(out);
21335     if (!out || !style) return 0;
21336 
21337     /* calculate progressbar cursor */
21338     cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
21339     cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
21340     cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
21341     prog_scale = (float)value / (float)max;
21342 
21343     /* update progressbar */
21344     prog_value = NK_MIN(value, max);
21345     prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable);
21346     cursor.w = cursor.w * prog_scale;
21347 
21348     /* draw progressbar */
21349     if (style->draw_begin) style->draw_begin(out, style->userdata);
21350     nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
21351     if (style->draw_end) style->draw_end(out, style->userdata);
21352     return prog_value;
21353 }
21354 NK_API int
21355 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
21356 {
21357     struct nk_window *win;
21358     struct nk_panel *layout;
21359     const struct nk_style *style;
21360     struct nk_input *in;
21361 
21362     struct nk_rect bounds;
21363     enum nk_widget_layout_states state;
21364     nk_size old_value;
21365 
21366     NK_ASSERT(ctx);
21367     NK_ASSERT(cur);
21368     NK_ASSERT(ctx->current);
21369     NK_ASSERT(ctx->current->layout);
21370     if (!ctx || !ctx->current || !ctx->current->layout || !cur)
21371         return 0;
21372 
21373     win = ctx->current;
21374     style = &ctx->style;
21375     layout = win->layout;
21376     state = nk_widget(&bounds, ctx);
21377     if (!state) return 0;
21378 
21379     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21380     old_value = *cur;
21381     *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
21382             *cur, max, is_modifyable, &style->progress, in);
21383     return (*cur != old_value);
21384 }
21385 NK_API nk_size
21386 nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
21387 {
21388     nk_progress(ctx, &cur, max, modifyable);
21389     return cur;
21390 }
21391 
21392 
21393 
21394 
21395 
21396 /* ===============================================================
21397  *
21398  *                              SCROLLBAR
21399  *
21400  * ===============================================================*/
21401 NK_LIB float
21402 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
21403     int has_scrolling, const struct nk_rect *scroll,
21404     const struct nk_rect *cursor, const struct nk_rect *empty0,
21405     const struct nk_rect *empty1, float scroll_offset,
21406     float target, float scroll_step, enum nk_orientation o)
21407 {
21408     nk_flags ws = 0;
21409     int left_mouse_down;
21410     int left_mouse_clicked;
21411     int left_mouse_click_in_cursor;
21412     float scroll_delta;
21413 
21414     nk_widget_state_reset(state);
21415     if (!in) return scroll_offset;
21416 
21417     left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
21418     left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked;
21419     left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
21420         NK_BUTTON_LEFT, *cursor, nk_true);
21421     if (nk_input_is_mouse_hovering_rect(in, *scroll))
21422         *state = NK_WIDGET_STATE_HOVERED;
21423 
21424     scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
21425     if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
21426         /* update cursor by mouse dragging */
21427         float pixel, delta;
21428         *state = NK_WIDGET_STATE_ACTIVE;
21429         if (o == NK_VERTICAL) {
21430             float cursor_y;
21431             pixel = in->mouse.delta.y;
21432             delta = (pixel / scroll->h) * target;
21433             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
21434             cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
21435             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
21436         } else {
21437             float cursor_x;
21438             pixel = in->mouse.delta.x;
21439             delta = (pixel / scroll->w) * target;
21440             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
21441             cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
21442             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
21443         }
21444     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
21445             nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
21446         /* scroll page up by click on empty space or shortcut */
21447         if (o == NK_VERTICAL)
21448             scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
21449         else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
21450     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
21451         nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
21452         /* scroll page down by click on empty space or shortcut */
21453         if (o == NK_VERTICAL)
21454             scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
21455         else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
21456     } else if (has_scrolling) {
21457         if ((scroll_delta < 0 || (scroll_delta > 0))) {
21458             /* update cursor by mouse scrolling */
21459             scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
21460             if (o == NK_VERTICAL)
21461                 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
21462             else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
21463         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
21464             /* update cursor to the beginning  */
21465             if (o == NK_VERTICAL) scroll_offset = 0;
21466         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
21467             /* update cursor to the end */
21468             if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
21469         }
21470     }
21471     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
21472         *state |= NK_WIDGET_STATE_ENTERED;
21473     else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
21474         *state |= NK_WIDGET_STATE_LEFT;
21475     return scroll_offset;
21476 }
21477 NK_LIB void
21478 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
21479     const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
21480     const struct nk_rect *scroll)
21481 {
21482     const struct nk_style_item *background;
21483     const struct nk_style_item *cursor;
21484 
21485     /* select correct colors/images to draw */
21486     if (state & NK_WIDGET_STATE_ACTIVED) {
21487         background = &style->active;
21488         cursor = &style->cursor_active;
21489     } else if (state & NK_WIDGET_STATE_HOVER) {
21490         background = &style->hover;
21491         cursor = &style->cursor_hover;
21492     } else {
21493         background = &style->normal;
21494         cursor = &style->cursor_normal;
21495     }
21496 
21497     /* draw background */
21498     if (background->type == NK_STYLE_ITEM_COLOR) {
21499         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
21500         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
21501     } else {
21502         nk_draw_image(out, *bounds, &background->data.image, nk_white);
21503     }
21504 
21505     /* draw cursor */
21506     if (cursor->type == NK_STYLE_ITEM_COLOR) {
21507         nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
21508         nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
21509     } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
21510 }
21511 NK_LIB float
21512 nk_do_scrollbarv(nk_flags *state,
21513     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
21514     float offset, float target, float step, float button_pixel_inc,
21515     const struct nk_style_scrollbar *style, struct nk_input *in,
21516     const struct nk_user_font *font)
21517 {
21518     struct nk_rect empty_north;
21519     struct nk_rect empty_south;
21520     struct nk_rect cursor;
21521 
21522     float scroll_step;
21523     float scroll_offset;
21524     float scroll_off;
21525     float scroll_ratio;
21526 
21527     NK_ASSERT(out);
21528     NK_ASSERT(style);
21529     NK_ASSERT(state);
21530     if (!out || !style) return 0;
21531 
21532     scroll.w = NK_MAX(scroll.w, 1);
21533     scroll.h = NK_MAX(scroll.h, 0);
21534     if (target <= scroll.h) return 0;
21535 
21536     /* optional scrollbar buttons */
21537     if (style->show_buttons) {
21538         nk_flags ws;
21539         float scroll_h;
21540         struct nk_rect button;
21541 
21542         button.x = scroll.x;
21543         button.w = scroll.w;
21544         button.h = scroll.w;
21545 
21546         scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
21547         scroll_step = NK_MIN(step, button_pixel_inc);
21548 
21549         /* decrement button */
21550         button.y = scroll.y;
21551         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
21552             NK_BUTTON_REPEATER, &style->dec_button, in, font))
21553             offset = offset - scroll_step;
21554 
21555         /* increment button */
21556         button.y = scroll.y + scroll.h - button.h;
21557         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
21558             NK_BUTTON_REPEATER, &style->inc_button, in, font))
21559             offset = offset + scroll_step;
21560 
21561         scroll.y = scroll.y + button.h;
21562         scroll.h = scroll_h;
21563     }
21564 
21565     /* calculate scrollbar constants */
21566     scroll_step = NK_MIN(step, scroll.h);
21567     scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
21568     scroll_ratio = scroll.h / target;
21569     scroll_off = scroll_offset / target;
21570 
21571     /* calculate scrollbar cursor bounds */
21572     cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
21573     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
21574     cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
21575     cursor.x = scroll.x + style->border + style->padding.x;
21576 
21577     /* calculate empty space around cursor */
21578     empty_north.x = scroll.x;
21579     empty_north.y = scroll.y;
21580     empty_north.w = scroll.w;
21581     empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
21582 
21583     empty_south.x = scroll.x;
21584     empty_south.y = cursor.y + cursor.h;
21585     empty_south.w = scroll.w;
21586     empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
21587 
21588     /* update scrollbar */
21589     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
21590         &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
21591     scroll_off = scroll_offset / target;
21592     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
21593 
21594     /* draw scrollbar */
21595     if (style->draw_begin) style->draw_begin(out, style->userdata);
21596     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
21597     if (style->draw_end) style->draw_end(out, style->userdata);
21598     return scroll_offset;
21599 }
21600 NK_LIB float
21601 nk_do_scrollbarh(nk_flags *state,
21602     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
21603     float offset, float target, float step, float button_pixel_inc,
21604     const struct nk_style_scrollbar *style, struct nk_input *in,
21605     const struct nk_user_font *font)
21606 {
21607     struct nk_rect cursor;
21608     struct nk_rect empty_west;
21609     struct nk_rect empty_east;
21610 
21611     float scroll_step;
21612     float scroll_offset;
21613     float scroll_off;
21614     float scroll_ratio;
21615 
21616     NK_ASSERT(out);
21617     NK_ASSERT(style);
21618     if (!out || !style) return 0;
21619 
21620     /* scrollbar background */
21621     scroll.h = NK_MAX(scroll.h, 1);
21622     scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
21623     if (target <= scroll.w) return 0;
21624 
21625     /* optional scrollbar buttons */
21626     if (style->show_buttons) {
21627         nk_flags ws;
21628         float scroll_w;
21629         struct nk_rect button;
21630         button.y = scroll.y;
21631         button.w = scroll.h;
21632         button.h = scroll.h;
21633 
21634         scroll_w = scroll.w - 2 * button.w;
21635         scroll_step = NK_MIN(step, button_pixel_inc);
21636 
21637         /* decrement button */
21638         button.x = scroll.x;
21639         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
21640             NK_BUTTON_REPEATER, &style->dec_button, in, font))
21641             offset = offset - scroll_step;
21642 
21643         /* increment button */
21644         button.x = scroll.x + scroll.w - button.w;
21645         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
21646             NK_BUTTON_REPEATER, &style->inc_button, in, font))
21647             offset = offset + scroll_step;
21648 
21649         scroll.x = scroll.x + button.w;
21650         scroll.w = scroll_w;
21651     }
21652 
21653     /* calculate scrollbar constants */
21654     scroll_step = NK_MIN(step, scroll.w);
21655     scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
21656     scroll_ratio = scroll.w / target;
21657     scroll_off = scroll_offset / target;
21658 
21659     /* calculate cursor bounds */
21660     cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
21661     cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
21662     cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
21663     cursor.y = scroll.y + style->border + style->padding.y;
21664 
21665     /* calculate empty space around cursor */
21666     empty_west.x = scroll.x;
21667     empty_west.y = scroll.y;
21668     empty_west.w = cursor.x - scroll.x;
21669     empty_west.h = scroll.h;
21670 
21671     empty_east.x = cursor.x + cursor.w;
21672     empty_east.y = scroll.y;
21673     empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
21674     empty_east.h = scroll.h;
21675 
21676     /* update scrollbar */
21677     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
21678         &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
21679     scroll_off = scroll_offset / target;
21680     cursor.x = scroll.x + (scroll_off * scroll.w);
21681 
21682     /* draw scrollbar */
21683     if (style->draw_begin) style->draw_begin(out, style->userdata);
21684     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
21685     if (style->draw_end) style->draw_end(out, style->userdata);
21686     return scroll_offset;
21687 }
21688 
21689 
21690 
21691 
21692 
21693 /* ===============================================================
21694  *
21695  *                          TEXT EDITOR
21696  *
21697  * ===============================================================*/
21698 /* stb_textedit.h - v1.8  - public domain - Sean Barrett */
21699 struct nk_text_find {
21700    float x,y;    /* position of n'th character */
21701    float height; /* height of line */
21702    int first_char, length; /* first char of row, and length */
21703    int prev_first;  /*_ first char of previous row */
21704 };
21705 
21706 struct nk_text_edit_row {
21707    float x0,x1;
21708    /* starting x location, end x location (allows for align=right, etc) */
21709    float baseline_y_delta;
21710    /* position of baseline relative to previous row's baseline*/
21711    float ymin,ymax;
21712    /* height of row above and below baseline */
21713    int num_chars;
21714 };
21715 
21716 /* forward declarations */
21717 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
21718 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
21719 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
21720 #define NK_TEXT_HAS_SELECTION(s)   ((s)->select_start != (s)->select_end)
21721 
21722 NK_INTERN float
21723 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
21724     const struct nk_user_font *font)
21725 {
21726     int len = 0;
21727     nk_rune unicode = 0;
21728     const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
21729     return font->width(font->userdata, font->height, str, len);
21730 }
21731 NK_INTERN void
21732 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
21733     int line_start_id, float row_height, const struct nk_user_font *font)
21734 {
21735     int l;
21736     int glyphs = 0;
21737     nk_rune unicode;
21738     const char *remaining;
21739     int len = nk_str_len_char(&edit->string);
21740     const char *end = nk_str_get_const(&edit->string) + len;
21741     const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
21742     const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
21743         text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
21744 
21745     r->x0 = 0.0f;
21746     r->x1 = size.x;
21747     r->baseline_y_delta = size.y;
21748     r->ymin = 0.0f;
21749     r->ymax = size.y;
21750     r->num_chars = glyphs;
21751 }
21752 NK_INTERN int
21753 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
21754     const struct nk_user_font *font, float row_height)
21755 {
21756     struct nk_text_edit_row r;
21757     int n = edit->string.len;
21758     float base_y = 0, prev_x;
21759     int i=0, k;
21760 
21761     r.x0 = r.x1 = 0;
21762     r.ymin = r.ymax = 0;
21763     r.num_chars = 0;
21764 
21765     /* search rows to find one that straddles 'y' */
21766     while (i < n) {
21767         nk_textedit_layout_row(&r, edit, i, row_height, font);
21768         if (r.num_chars <= 0)
21769             return n;
21770 
21771         if (i==0 && y < base_y + r.ymin)
21772             return 0;
21773 
21774         if (y < base_y + r.ymax)
21775             break;
21776 
21777         i += r.num_chars;
21778         base_y += r.baseline_y_delta;
21779     }
21780 
21781     /* below all text, return 'after' last character */
21782     if (i >= n)
21783         return n;
21784 
21785     /* check if it's before the beginning of the line */
21786     if (x < r.x0)
21787         return i;
21788 
21789     /* check if it's before the end of the line */
21790     if (x < r.x1) {
21791         /* search characters in row for one that straddles 'x' */
21792         k = i;
21793         prev_x = r.x0;
21794         for (i=0; i < r.num_chars; ++i) {
21795             float w = nk_textedit_get_width(edit, k, i, font);
21796             if (x < prev_x+w) {
21797                 if (x < prev_x+w/2)
21798                     return k+i;
21799                 else return k+i+1;
21800             }
21801             prev_x += w;
21802         }
21803         /* shouldn't happen, but if it does, fall through to end-of-line case */
21804     }
21805 
21806     /* if the last character is a newline, return that.
21807      * otherwise return 'after' the last character */
21808     if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
21809         return i+r.num_chars-1;
21810     else return i+r.num_chars;
21811 }
21812 NK_LIB void
21813 nk_textedit_click(struct nk_text_edit *state, float x, float y,
21814     const struct nk_user_font *font, float row_height)
21815 {
21816     /* API click: on mouse down, move the cursor to the clicked location,
21817      * and reset the selection */
21818     state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
21819     state->select_start = state->cursor;
21820     state->select_end = state->cursor;
21821     state->has_preferred_x = 0;
21822 }
21823 NK_LIB void
21824 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
21825     const struct nk_user_font *font, float row_height)
21826 {
21827     /* API drag: on mouse drag, move the cursor and selection endpoint
21828      * to the clicked location */
21829     int p = nk_textedit_locate_coord(state, x, y, font, row_height);
21830     if (state->select_start == state->select_end)
21831         state->select_start = state->cursor;
21832     state->cursor = state->select_end = p;
21833 }
21834 NK_INTERN void
21835 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
21836     int n, int single_line, const struct nk_user_font *font, float row_height)
21837 {
21838     /* find the x/y location of a character, and remember info about the previous
21839      * row in case we get a move-up event (for page up, we'll have to rescan) */
21840     struct nk_text_edit_row r;
21841     int prev_start = 0;
21842     int z = state->string.len;
21843     int i=0, first;
21844 
21845     nk_zero_struct(r);
21846     if (n == z) {
21847         /* if it's at the end, then find the last line -- simpler than trying to
21848         explicitly handle this case in the regular code */
21849         nk_textedit_layout_row(&r, state, 0, row_height, font);
21850         if (single_line) {
21851             find->first_char = 0;
21852             find->length = z;
21853         } else {
21854             while (i < z) {
21855                 prev_start = i;
21856                 i += r.num_chars;
21857                 nk_textedit_layout_row(&r, state, i, row_height, font);
21858             }
21859 
21860             find->first_char = i;
21861             find->length = r.num_chars;
21862         }
21863         find->x = r.x1;
21864         find->y = r.ymin;
21865         find->height = r.ymax - r.ymin;
21866         find->prev_first = prev_start;
21867         return;
21868     }
21869 
21870     /* search rows to find the one that straddles character n */
21871     find->y = 0;
21872 
21873     for(;;) {
21874         nk_textedit_layout_row(&r, state, i, row_height, font);
21875         if (n < i + r.num_chars) break;
21876         prev_start = i;
21877         i += r.num_chars;
21878         find->y += r.baseline_y_delta;
21879     }
21880 
21881     find->first_char = first = i;
21882     find->length = r.num_chars;
21883     find->height = r.ymax - r.ymin;
21884     find->prev_first = prev_start;
21885 
21886     /* now scan to find xpos */
21887     find->x = r.x0;
21888     for (i=0; first+i < n; ++i)
21889         find->x += nk_textedit_get_width(state, first, i, font);
21890 }
21891 NK_INTERN void
21892 nk_textedit_clamp(struct nk_text_edit *state)
21893 {
21894     /* make the selection/cursor state valid if client altered the string */
21895     int n = state->string.len;
21896     if (NK_TEXT_HAS_SELECTION(state)) {
21897         if (state->select_start > n) state->select_start = n;
21898         if (state->select_end   > n) state->select_end = n;
21899         /* if clamping forced them to be equal, move the cursor to match */
21900         if (state->select_start == state->select_end)
21901             state->cursor = state->select_start;
21902     }
21903     if (state->cursor > n) state->cursor = n;
21904 }
21905 NK_API void
21906 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
21907 {
21908     /* delete characters while updating undo */
21909     nk_textedit_makeundo_delete(state, where, len);
21910     nk_str_delete_runes(&state->string, where, len);
21911     state->has_preferred_x = 0;
21912 }
21913 NK_API void
21914 nk_textedit_delete_selection(struct nk_text_edit *state)
21915 {
21916     /* delete the section */
21917     nk_textedit_clamp(state);
21918     if (NK_TEXT_HAS_SELECTION(state)) {
21919         if (state->select_start < state->select_end) {
21920             nk_textedit_delete(state, state->select_start,
21921                 state->select_end - state->select_start);
21922             state->select_end = state->cursor = state->select_start;
21923         } else {
21924             nk_textedit_delete(state, state->select_end,
21925                 state->select_start - state->select_end);
21926             state->select_start = state->cursor = state->select_end;
21927         }
21928         state->has_preferred_x = 0;
21929     }
21930 }
21931 NK_INTERN void
21932 nk_textedit_sortselection(struct nk_text_edit *state)
21933 {
21934     /* canonicalize the selection so start <= end */
21935     if (state->select_end < state->select_start) {
21936         int temp = state->select_end;
21937         state->select_end = state->select_start;
21938         state->select_start = temp;
21939     }
21940 }
21941 NK_INTERN void
21942 nk_textedit_move_to_first(struct nk_text_edit *state)
21943 {
21944     /* move cursor to first character of selection */
21945     if (NK_TEXT_HAS_SELECTION(state)) {
21946         nk_textedit_sortselection(state);
21947         state->cursor = state->select_start;
21948         state->select_end = state->select_start;
21949         state->has_preferred_x = 0;
21950     }
21951 }
21952 NK_INTERN void
21953 nk_textedit_move_to_last(struct nk_text_edit *state)
21954 {
21955     /* move cursor to last character of selection */
21956     if (NK_TEXT_HAS_SELECTION(state)) {
21957         nk_textedit_sortselection(state);
21958         nk_textedit_clamp(state);
21959         state->cursor = state->select_end;
21960         state->select_start = state->select_end;
21961         state->has_preferred_x = 0;
21962     }
21963 }
21964 NK_INTERN int
21965 nk_is_word_boundary( struct nk_text_edit *state, int idx)
21966 {
21967     int len;
21968     nk_rune c;
21969     if (idx <= 0) return 1;
21970     if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
21971     return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
21972             c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
21973             c == '|');
21974 }
21975 NK_INTERN int
21976 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
21977 {
21978    int c = state->cursor - 1;
21979    while( c >= 0 && !nk_is_word_boundary(state, c))
21980       --c;
21981 
21982    if( c < 0 )
21983       c = 0;
21984 
21985    return c;
21986 }
21987 NK_INTERN int
21988 nk_textedit_move_to_word_next(struct nk_text_edit *state)
21989 {
21990    const int len = state->string.len;
21991    int c = state->cursor+1;
21992    while( c < len && !nk_is_word_boundary(state, c))
21993       ++c;
21994 
21995    if( c > len )
21996       c = len;
21997 
21998    return c;
21999 }
22000 NK_INTERN void
22001 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
22002 {
22003     /* update selection and cursor to match each other */
22004     if (!NK_TEXT_HAS_SELECTION(state))
22005         state->select_start = state->select_end = state->cursor;
22006     else state->cursor = state->select_end;
22007 }
22008 NK_API int
22009 nk_textedit_cut(struct nk_text_edit *state)
22010 {
22011     /* API cut: delete selection */
22012     if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22013         return 0;
22014     if (NK_TEXT_HAS_SELECTION(state)) {
22015         nk_textedit_delete_selection(state); /* implicitly clamps */
22016         state->has_preferred_x = 0;
22017         return 1;
22018     }
22019    return 0;
22020 }
22021 NK_API int
22022 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
22023 {
22024     /* API paste: replace existing selection with passed-in text */
22025     int glyphs;
22026     const char *text = (const char *) ctext;
22027     if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
22028 
22029     /* if there's a selection, the paste should delete it */
22030     nk_textedit_clamp(state);
22031     nk_textedit_delete_selection(state);
22032 
22033     /* try to insert the characters */
22034     glyphs = nk_utf_len(ctext, len);
22035     if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
22036         nk_textedit_makeundo_insert(state, state->cursor, glyphs);
22037         state->cursor += len;
22038         state->has_preferred_x = 0;
22039         return 1;
22040     }
22041     /* remove the undo since we didn't actually insert the characters */
22042     if (state->undo.undo_point)
22043         --state->undo.undo_point;
22044     return 0;
22045 }
22046 NK_API void
22047 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
22048 {
22049     nk_rune unicode;
22050     int glyph_len;
22051     int text_len = 0;
22052 
22053     NK_ASSERT(state);
22054     NK_ASSERT(text);
22055     if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
22056 
22057     glyph_len = nk_utf_decode(text, &unicode, total_len);
22058     while ((text_len < total_len) && glyph_len)
22059     {
22060         /* don't insert a backward delete, just process the event */
22061         if (unicode == 127) goto next;
22062         /* can't add newline in single-line mode */
22063         if (unicode == '\n' && state->single_line) goto next;
22064         /* filter incoming text */
22065         if (state->filter && !state->filter(state, unicode)) goto next;
22066 
22067         if (!NK_TEXT_HAS_SELECTION(state) &&
22068             state->cursor < state->string.len)
22069         {
22070             if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
22071                 nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
22072                 nk_str_delete_runes(&state->string, state->cursor, 1);
22073             }
22074             if (nk_str_insert_text_utf8(&state->string, state->cursor,
22075                                         text+text_len, 1))
22076             {
22077                 ++state->cursor;
22078                 state->has_preferred_x = 0;
22079             }
22080         } else {
22081             nk_textedit_delete_selection(state); /* implicitly clamps */
22082             if (nk_str_insert_text_utf8(&state->string, state->cursor,
22083                                         text+text_len, 1))
22084             {
22085                 nk_textedit_makeundo_insert(state, state->cursor, 1);
22086                 ++state->cursor;
22087                 state->has_preferred_x = 0;
22088             }
22089         }
22090         next:
22091         text_len += glyph_len;
22092         glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
22093     }
22094 }
22095 NK_LIB void
22096 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
22097     const struct nk_user_font *font, float row_height)
22098 {
22099 retry:
22100     switch (key)
22101     {
22102     case NK_KEY_NONE:
22103     case NK_KEY_CTRL:
22104     case NK_KEY_ENTER:
22105     case NK_KEY_SHIFT:
22106     case NK_KEY_TAB:
22107     case NK_KEY_COPY:
22108     case NK_KEY_CUT:
22109     case NK_KEY_PASTE:
22110     case NK_KEY_MAX:
22111     default: break;
22112     case NK_KEY_TEXT_UNDO:
22113          nk_textedit_undo(state);
22114          state->has_preferred_x = 0;
22115          break;
22116 
22117     case NK_KEY_TEXT_REDO:
22118         nk_textedit_redo(state);
22119         state->has_preferred_x = 0;
22120         break;
22121 
22122     case NK_KEY_TEXT_SELECT_ALL:
22123         nk_textedit_select_all(state);
22124         state->has_preferred_x = 0;
22125         break;
22126 
22127     case NK_KEY_TEXT_INSERT_MODE:
22128         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22129             state->mode = NK_TEXT_EDIT_MODE_INSERT;
22130         break;
22131     case NK_KEY_TEXT_REPLACE_MODE:
22132         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22133             state->mode = NK_TEXT_EDIT_MODE_REPLACE;
22134         break;
22135     case NK_KEY_TEXT_RESET_MODE:
22136         if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
22137             state->mode == NK_TEXT_EDIT_MODE_REPLACE)
22138             state->mode = NK_TEXT_EDIT_MODE_VIEW;
22139         break;
22140 
22141     case NK_KEY_LEFT:
22142         if (shift_mod) {
22143             nk_textedit_clamp(state);
22144             nk_textedit_prep_selection_at_cursor(state);
22145             /* move selection left */
22146             if (state->select_end > 0)
22147                 --state->select_end;
22148             state->cursor = state->select_end;
22149             state->has_preferred_x = 0;
22150         } else {
22151             /* if currently there's a selection,
22152              * move cursor to start of selection */
22153             if (NK_TEXT_HAS_SELECTION(state))
22154                 nk_textedit_move_to_first(state);
22155             else if (state->cursor > 0)
22156                --state->cursor;
22157             state->has_preferred_x = 0;
22158         } break;
22159 
22160     case NK_KEY_RIGHT:
22161         if (shift_mod) {
22162             nk_textedit_prep_selection_at_cursor(state);
22163             /* move selection right */
22164             ++state->select_end;
22165             nk_textedit_clamp(state);
22166             state->cursor = state->select_end;
22167             state->has_preferred_x = 0;
22168         } else {
22169             /* if currently there's a selection,
22170              * move cursor to end of selection */
22171             if (NK_TEXT_HAS_SELECTION(state))
22172                 nk_textedit_move_to_last(state);
22173             else ++state->cursor;
22174             nk_textedit_clamp(state);
22175             state->has_preferred_x = 0;
22176         } break;
22177 
22178     case NK_KEY_TEXT_WORD_LEFT:
22179         if (shift_mod) {
22180             if( !NK_TEXT_HAS_SELECTION( state ) )
22181             nk_textedit_prep_selection_at_cursor(state);
22182             state->cursor = nk_textedit_move_to_word_previous(state);
22183             state->select_end = state->cursor;
22184             nk_textedit_clamp(state );
22185         } else {
22186             if (NK_TEXT_HAS_SELECTION(state))
22187                 nk_textedit_move_to_first(state);
22188             else {
22189                 state->cursor = nk_textedit_move_to_word_previous(state);
22190                 nk_textedit_clamp(state );
22191             }
22192         } break;
22193 
22194     case NK_KEY_TEXT_WORD_RIGHT:
22195         if (shift_mod) {
22196             if( !NK_TEXT_HAS_SELECTION( state ) )
22197                 nk_textedit_prep_selection_at_cursor(state);
22198             state->cursor = nk_textedit_move_to_word_next(state);
22199             state->select_end = state->cursor;
22200             nk_textedit_clamp(state);
22201         } else {
22202             if (NK_TEXT_HAS_SELECTION(state))
22203                 nk_textedit_move_to_last(state);
22204             else {
22205                 state->cursor = nk_textedit_move_to_word_next(state);
22206                 nk_textedit_clamp(state );
22207             }
22208         } break;
22209 
22210     case NK_KEY_DOWN: {
22211         struct nk_text_find find;
22212         struct nk_text_edit_row row;
22213         int i, sel = shift_mod;
22214 
22215         if (state->single_line) {
22216             /* on windows, up&down in single-line behave like left&right */
22217             key = NK_KEY_RIGHT;
22218             goto retry;
22219         }
22220 
22221         if (sel)
22222             nk_textedit_prep_selection_at_cursor(state);
22223         else if (NK_TEXT_HAS_SELECTION(state))
22224             nk_textedit_move_to_last(state);
22225 
22226         /* compute current position of cursor point */
22227         nk_textedit_clamp(state);
22228         nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22229             font, row_height);
22230 
22231         /* now find character position down a row */
22232         if (find.length)
22233         {
22234             float x;
22235             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
22236             int start = find.first_char + find.length;
22237 
22238             state->cursor = start;
22239             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
22240             x = row.x0;
22241 
22242             for (i=0; i < row.num_chars && x < row.x1; ++i) {
22243                 float dx = nk_textedit_get_width(state, start, i, font);
22244                 x += dx;
22245                 if (x > goal_x)
22246                     break;
22247                 ++state->cursor;
22248             }
22249             nk_textedit_clamp(state);
22250 
22251             state->has_preferred_x = 1;
22252             state->preferred_x = goal_x;
22253             if (sel)
22254                 state->select_end = state->cursor;
22255         }
22256     } break;
22257 
22258     case NK_KEY_UP: {
22259         struct nk_text_find find;
22260         struct nk_text_edit_row row;
22261         int i, sel = shift_mod;
22262 
22263         if (state->single_line) {
22264             /* on windows, up&down become left&right */
22265             key = NK_KEY_LEFT;
22266             goto retry;
22267         }
22268 
22269         if (sel)
22270             nk_textedit_prep_selection_at_cursor(state);
22271         else if (NK_TEXT_HAS_SELECTION(state))
22272             nk_textedit_move_to_first(state);
22273 
22274          /* compute current position of cursor point */
22275          nk_textedit_clamp(state);
22276          nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22277                 font, row_height);
22278 
22279          /* can only go up if there's a previous row */
22280          if (find.prev_first != find.first_char) {
22281             /* now find character position up a row */
22282             float x;
22283             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
22284 
22285             state->cursor = find.prev_first;
22286             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
22287             x = row.x0;
22288 
22289             for (i=0; i < row.num_chars && x < row.x1; ++i) {
22290                 float dx = nk_textedit_get_width(state, find.prev_first, i, font);
22291                 x += dx;
22292                 if (x > goal_x)
22293                     break;
22294                 ++state->cursor;
22295             }
22296             nk_textedit_clamp(state);
22297 
22298             state->has_preferred_x = 1;
22299             state->preferred_x = goal_x;
22300             if (sel) state->select_end = state->cursor;
22301          }
22302       } break;
22303 
22304     case NK_KEY_DEL:
22305         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22306             break;
22307         if (NK_TEXT_HAS_SELECTION(state))
22308             nk_textedit_delete_selection(state);
22309         else {
22310             int n = state->string.len;
22311             if (state->cursor < n)
22312                 nk_textedit_delete(state, state->cursor, 1);
22313          }
22314          state->has_preferred_x = 0;
22315          break;
22316 
22317     case NK_KEY_BACKSPACE:
22318         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
22319             break;
22320         if (NK_TEXT_HAS_SELECTION(state))
22321             nk_textedit_delete_selection(state);
22322         else {
22323             nk_textedit_clamp(state);
22324             if (state->cursor > 0) {
22325                 nk_textedit_delete(state, state->cursor-1, 1);
22326                 --state->cursor;
22327             }
22328          }
22329          state->has_preferred_x = 0;
22330          break;
22331 
22332     case NK_KEY_TEXT_START:
22333          if (shift_mod) {
22334             nk_textedit_prep_selection_at_cursor(state);
22335             state->cursor = state->select_end = 0;
22336             state->has_preferred_x = 0;
22337          } else {
22338             state->cursor = state->select_start = state->select_end = 0;
22339             state->has_preferred_x = 0;
22340          }
22341          break;
22342 
22343     case NK_KEY_TEXT_END:
22344          if (shift_mod) {
22345             nk_textedit_prep_selection_at_cursor(state);
22346             state->cursor = state->select_end = state->string.len;
22347             state->has_preferred_x = 0;
22348          } else {
22349             state->cursor = state->string.len;
22350             state->select_start = state->select_end = 0;
22351             state->has_preferred_x = 0;
22352          }
22353          break;
22354 
22355     case NK_KEY_TEXT_LINE_START: {
22356         if (shift_mod) {
22357             struct nk_text_find find;
22358            nk_textedit_clamp(state);
22359             nk_textedit_prep_selection_at_cursor(state);
22360             if (state->string.len && state->cursor == state->string.len)
22361                 --state->cursor;
22362             nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
22363                 font, row_height);
22364             state->cursor = state->select_end = find.first_char;
22365             state->has_preferred_x = 0;
22366         } else {
22367             struct nk_text_find find;
22368             if (state->string.len && state->cursor == state->string.len)
22369                 --state->cursor;
22370             nk_textedit_clamp(state);
22371             nk_textedit_move_to_first(state);
22372             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22373                 font, row_height);
22374             state->cursor = find.first_char;
22375             state->has_preferred_x = 0;
22376         }
22377       } break;
22378 
22379     case NK_KEY_TEXT_LINE_END: {
22380         if (shift_mod) {
22381             struct nk_text_find find;
22382             nk_textedit_clamp(state);
22383             nk_textedit_prep_selection_at_cursor(state);
22384             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22385                 font, row_height);
22386             state->has_preferred_x = 0;
22387             state->cursor = find.first_char + find.length;
22388             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
22389                 --state->cursor;
22390             state->select_end = state->cursor;
22391         } else {
22392             struct nk_text_find find;
22393             nk_textedit_clamp(state);
22394             nk_textedit_move_to_first(state);
22395             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
22396                 font, row_height);
22397 
22398             state->has_preferred_x = 0;
22399             state->cursor = find.first_char + find.length;
22400             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
22401                 --state->cursor;
22402         }} break;
22403     }
22404 }
22405 NK_INTERN void
22406 nk_textedit_flush_redo(struct nk_text_undo_state *state)
22407 {
22408     state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
22409     state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
22410 }
22411 NK_INTERN void
22412 nk_textedit_discard_undo(struct nk_text_undo_state *state)
22413 {
22414     /* discard the oldest entry in the undo list */
22415     if (state->undo_point > 0) {
22416         /* if the 0th undo state has characters, clean those up */
22417         if (state->undo_rec[0].char_storage >= 0) {
22418             int n = state->undo_rec[0].insert_length, i;
22419             /* delete n characters from all other records */
22420             state->undo_char_point = (short)(state->undo_char_point - n);
22421             NK_MEMCPY(state->undo_char, state->undo_char + n,
22422                 (nk_size)state->undo_char_point*sizeof(nk_rune));
22423             for (i=0; i < state->undo_point; ++i) {
22424                 if (state->undo_rec[i].char_storage >= 0)
22425                 state->undo_rec[i].char_storage = (short)
22426                     (state->undo_rec[i].char_storage - n);
22427             }
22428         }
22429         --state->undo_point;
22430         NK_MEMCPY(state->undo_rec, state->undo_rec+1,
22431             (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
22432     }
22433 }
22434 NK_INTERN void
22435 nk_textedit_discard_redo(struct nk_text_undo_state *state)
22436 {
22437 /*  discard the oldest entry in the redo list--it's bad if this
22438     ever happens, but because undo & redo have to store the actual
22439     characters in different cases, the redo character buffer can
22440     fill up even though the undo buffer didn't */
22441     nk_size num;
22442     int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
22443     if (state->redo_point <= k) {
22444         /* if the k'th undo state has characters, clean those up */
22445         if (state->undo_rec[k].char_storage >= 0) {
22446             int n = state->undo_rec[k].insert_length, i;
22447             /* delete n characters from all other records */
22448             state->redo_char_point = (short)(state->redo_char_point + n);
22449             num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point);
22450             NK_MEMCPY(state->undo_char + state->redo_char_point,
22451                 state->undo_char + state->redo_char_point-n, num * sizeof(char));
22452             for (i = state->redo_point; i < k; ++i) {
22453                 if (state->undo_rec[i].char_storage >= 0) {
22454                     state->undo_rec[i].char_storage = (short)
22455                         (state->undo_rec[i].char_storage + n);
22456                 }
22457             }
22458         }
22459         ++state->redo_point;
22460         num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
22461         if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
22462             state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
22463     }
22464 }
22465 NK_INTERN struct nk_text_undo_record*
22466 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
22467 {
22468     /* any time we create a new undo record, we discard redo*/
22469     nk_textedit_flush_redo(state);
22470 
22471     /* if we have no free records, we have to make room,
22472      * by sliding the existing records down */
22473     if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
22474         nk_textedit_discard_undo(state);
22475 
22476     /* if the characters to store won't possibly fit in the buffer,
22477      * we can't undo */
22478     if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
22479         state->undo_point = 0;
22480         state->undo_char_point = 0;
22481         return 0;
22482     }
22483 
22484     /* if we don't have enough free characters in the buffer,
22485      * we have to make room */
22486     while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
22487         nk_textedit_discard_undo(state);
22488     return &state->undo_rec[state->undo_point++];
22489 }
22490 NK_INTERN nk_rune*
22491 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
22492     int insert_len, int delete_len)
22493 {
22494     struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
22495     if (r == 0)
22496         return 0;
22497 
22498     r->where = pos;
22499     r->insert_length = (short) insert_len;
22500     r->delete_length = (short) delete_len;
22501 
22502     if (insert_len == 0) {
22503         r->char_storage = -1;
22504         return 0;
22505     } else {
22506         r->char_storage = state->undo_char_point;
22507         state->undo_char_point = (short)(state->undo_char_point +  insert_len);
22508         return &state->undo_char[r->char_storage];
22509     }
22510 }
22511 NK_API void
22512 nk_textedit_undo(struct nk_text_edit *state)
22513 {
22514     struct nk_text_undo_state *s = &state->undo;
22515     struct nk_text_undo_record u, *r;
22516     if (s->undo_point == 0)
22517         return;
22518 
22519     /* we need to do two things: apply the undo record, and create a redo record */
22520     u = s->undo_rec[s->undo_point-1];
22521     r = &s->undo_rec[s->redo_point-1];
22522     r->char_storage = -1;
22523 
22524     r->insert_length = u.delete_length;
22525     r->delete_length = u.insert_length;
22526     r->where = u.where;
22527 
22528     if (u.delete_length)
22529     {
22530        /*   if the undo record says to delete characters, then the redo record will
22531             need to re-insert the characters that get deleted, so we need to store
22532             them.
22533             there are three cases:
22534                 - there's enough room to store the characters
22535                 - characters stored for *redoing* don't leave room for redo
22536                 - characters stored for *undoing* don't leave room for redo
22537             if the last is true, we have to bail */
22538         if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
22539             /* the undo records take up too much character space; there's no space
22540             * to store the redo characters */
22541             r->insert_length = 0;
22542         } else {
22543             int i;
22544             /* there's definitely room to store the characters eventually */
22545             while (s->undo_char_point + u.delete_length > s->redo_char_point) {
22546                 /* there's currently not enough room, so discard a redo record */
22547                 nk_textedit_discard_redo(s);
22548                 /* should never happen: */
22549                 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
22550                     return;
22551             }
22552 
22553             r = &s->undo_rec[s->redo_point-1];
22554             r->char_storage = (short)(s->redo_char_point - u.delete_length);
22555             s->redo_char_point = (short)(s->redo_char_point -  u.delete_length);
22556 
22557             /* now save the characters */
22558             for (i=0; i < u.delete_length; ++i)
22559                 s->undo_char[r->char_storage + i] =
22560                     nk_str_rune_at(&state->string, u.where + i);
22561         }
22562         /* now we can carry out the deletion */
22563         nk_str_delete_runes(&state->string, u.where, u.delete_length);
22564     }
22565 
22566     /* check type of recorded action: */
22567     if (u.insert_length) {
22568         /* easy case: was a deletion, so we need to insert n characters */
22569         nk_str_insert_text_runes(&state->string, u.where,
22570             &s->undo_char[u.char_storage], u.insert_length);
22571         s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
22572     }
22573     state->cursor = (short)(u.where + u.insert_length);
22574 
22575     s->undo_point--;
22576     s->redo_point--;
22577 }
22578 NK_API void
22579 nk_textedit_redo(struct nk_text_edit *state)
22580 {
22581     struct nk_text_undo_state *s = &state->undo;
22582     struct nk_text_undo_record *u, r;
22583     if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
22584         return;
22585 
22586     /* we need to do two things: apply the redo record, and create an undo record */
22587     u = &s->undo_rec[s->undo_point];
22588     r = s->undo_rec[s->redo_point];
22589 
22590     /* we KNOW there must be room for the undo record, because the redo record
22591     was derived from an undo record */
22592     u->delete_length = r.insert_length;
22593     u->insert_length = r.delete_length;
22594     u->where = r.where;
22595     u->char_storage = -1;
22596 
22597     if (r.delete_length) {
22598         /* the redo record requires us to delete characters, so the undo record
22599         needs to store the characters */
22600         if (s->undo_char_point + u->insert_length > s->redo_char_point) {
22601             u->insert_length = 0;
22602             u->delete_length = 0;
22603         } else {
22604             int i;
22605             u->char_storage = s->undo_char_point;
22606             s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
22607 
22608             /* now save the characters */
22609             for (i=0; i < u->insert_length; ++i) {
22610                 s->undo_char[u->char_storage + i] =
22611                     nk_str_rune_at(&state->string, u->where + i);
22612             }
22613         }
22614         nk_str_delete_runes(&state->string, r.where, r.delete_length);
22615     }
22616 
22617     if (r.insert_length) {
22618         /* easy case: need to insert n characters */
22619         nk_str_insert_text_runes(&state->string, r.where,
22620             &s->undo_char[r.char_storage], r.insert_length);
22621     }
22622     state->cursor = r.where + r.insert_length;
22623 
22624     s->undo_point++;
22625     s->redo_point++;
22626 }
22627 NK_INTERN void
22628 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
22629 {
22630     nk_textedit_createundo(&state->undo, where, 0, length);
22631 }
22632 NK_INTERN void
22633 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
22634 {
22635     int i;
22636     nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
22637     if (p) {
22638         for (i=0; i < length; ++i)
22639             p[i] = nk_str_rune_at(&state->string, where+i);
22640     }
22641 }
22642 NK_INTERN void
22643 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
22644     int old_length, int new_length)
22645 {
22646     int i;
22647     nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
22648     if (p) {
22649         for (i=0; i < old_length; ++i)
22650             p[i] = nk_str_rune_at(&state->string, where+i);
22651     }
22652 }
22653 NK_LIB void
22654 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
22655     nk_plugin_filter filter)
22656 {
22657     /* reset the state to default */
22658    state->undo.undo_point = 0;
22659    state->undo.undo_char_point = 0;
22660    state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
22661    state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
22662    state->select_end = state->select_start = 0;
22663    state->cursor = 0;
22664    state->has_preferred_x = 0;
22665    state->preferred_x = 0;
22666    state->cursor_at_end_of_line = 0;
22667    state->initialized = 1;
22668    state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
22669    state->mode = NK_TEXT_EDIT_MODE_VIEW;
22670    state->filter = filter;
22671    state->scrollbar = nk_vec2(0,0);
22672 }
22673 NK_API void
22674 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
22675 {
22676     NK_ASSERT(state);
22677     NK_ASSERT(memory);
22678     if (!state || !memory || !size) return;
22679     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22680     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22681     nk_str_init_fixed(&state->string, memory, size);
22682 }
22683 NK_API void
22684 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
22685 {
22686     NK_ASSERT(state);
22687     NK_ASSERT(alloc);
22688     if (!state || !alloc) return;
22689     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22690     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22691     nk_str_init(&state->string, alloc, size);
22692 }
22693 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
22694 NK_API void
22695 nk_textedit_init_default(struct nk_text_edit *state)
22696 {
22697     NK_ASSERT(state);
22698     if (!state) return;
22699     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
22700     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
22701     nk_str_init_default(&state->string);
22702 }
22703 #endif
22704 NK_API void
22705 nk_textedit_select_all(struct nk_text_edit *state)
22706 {
22707     NK_ASSERT(state);
22708     state->select_start = 0;
22709     state->select_end = state->string.len;
22710 }
22711 NK_API void
22712 nk_textedit_free(struct nk_text_edit *state)
22713 {
22714     NK_ASSERT(state);
22715     if (!state) return;
22716     nk_str_free(&state->string);
22717 }
22718 
22719 
22720 
22721 
22722 
22723 /* ===============================================================
22724  *
22725  *                          FILTER
22726  *
22727  * ===============================================================*/
22728 NK_API int
22729 nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
22730 {
22731     NK_UNUSED(unicode);
22732     NK_UNUSED(box);
22733     return nk_true;
22734 }
22735 NK_API int
22736 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
22737 {
22738     NK_UNUSED(box);
22739     if (unicode > 128) return nk_false;
22740     else return nk_true;
22741 }
22742 NK_API int
22743 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
22744 {
22745     NK_UNUSED(box);
22746     if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
22747         return nk_false;
22748     else return nk_true;
22749 }
22750 NK_API int
22751 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
22752 {
22753     NK_UNUSED(box);
22754     if ((unicode < '0' || unicode > '9') && unicode != '-')
22755         return nk_false;
22756     else return nk_true;
22757 }
22758 NK_API int
22759 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
22760 {
22761     NK_UNUSED(box);
22762     if ((unicode < '0' || unicode > '9') &&
22763         (unicode < 'a' || unicode > 'f') &&
22764         (unicode < 'A' || unicode > 'F'))
22765         return nk_false;
22766     else return nk_true;
22767 }
22768 NK_API int
22769 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
22770 {
22771     NK_UNUSED(box);
22772     if (unicode < '0' || unicode > '7')
22773         return nk_false;
22774     else return nk_true;
22775 }
22776 NK_API int
22777 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
22778 {
22779     NK_UNUSED(box);
22780     if (unicode != '0' && unicode != '1')
22781         return nk_false;
22782     else return nk_true;
22783 }
22784 
22785 /* ===============================================================
22786  *
22787  *                          EDIT
22788  *
22789  * ===============================================================*/
22790 NK_LIB void
22791 nk_edit_draw_text(struct nk_command_buffer *out,
22792     const struct nk_style_edit *style, float pos_x, float pos_y,
22793     float x_offset, const char *text, int byte_len, float row_height,
22794     const struct nk_user_font *font, struct nk_color background,
22795     struct nk_color foreground, int is_selected)
22796 {
22797     NK_ASSERT(out);
22798     NK_ASSERT(font);
22799     NK_ASSERT(style);
22800     if (!text || !byte_len || !out || !style) return;
22801 
22802     {int glyph_len = 0;
22803     nk_rune unicode = 0;
22804     int text_len = 0;
22805     float line_width = 0;
22806     float glyph_width;
22807     const char *line = text;
22808     float line_offset = 0;
22809     int line_count = 0;
22810 
22811     struct nk_text txt;
22812     txt.padding = nk_vec2(0,0);
22813     txt.background = background;
22814     txt.text = foreground;
22815 
22816     glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
22817     if (!glyph_len) return;
22818     while ((text_len < byte_len) && glyph_len)
22819     {
22820         if (unicode == '\n') {
22821             /* new line separator so draw previous line */
22822             struct nk_rect label;
22823             label.y = pos_y + line_offset;
22824             label.h = row_height;
22825             label.w = line_width;
22826             label.x = pos_x;
22827             if (!line_count)
22828                 label.x += x_offset;
22829 
22830             if (is_selected) /* selection needs to draw different background color */
22831                 nk_fill_rect(out, label, 0, background);
22832             nk_widget_text(out, label, line, (int)((text + text_len) - line),
22833                 &txt, NK_TEXT_CENTERED, font);
22834 
22835             text_len++;
22836             line_count++;
22837             line_width = 0;
22838             line = text + text_len;
22839             line_offset += row_height;
22840             glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
22841             continue;
22842         }
22843         if (unicode == '\r') {
22844             text_len++;
22845             glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
22846             continue;
22847         }
22848         glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
22849         line_width += (float)glyph_width;
22850         text_len += glyph_len;
22851         glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
22852         continue;
22853     }
22854     if (line_width > 0) {
22855         /* draw last line */
22856         struct nk_rect label;
22857         label.y = pos_y + line_offset;
22858         label.h = row_height;
22859         label.w = line_width;
22860         label.x = pos_x;
22861         if (!line_count)
22862             label.x += x_offset;
22863 
22864         if (is_selected)
22865             nk_fill_rect(out, label, 0, background);
22866         nk_widget_text(out, label, line, (int)((text + text_len) - line),
22867             &txt, NK_TEXT_LEFT, font);
22868     }}
22869 }
22870 NK_LIB nk_flags
22871 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
22872     struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
22873     struct nk_text_edit *edit, const struct nk_style_edit *style,
22874     struct nk_input *in, const struct nk_user_font *font)
22875 {
22876     struct nk_rect area;
22877     nk_flags ret = 0;
22878     float row_height;
22879     char prev_state = 0;
22880     char is_hovered = 0;
22881     char select_all = 0;
22882     char cursor_follow = 0;
22883     struct nk_rect old_clip;
22884     struct nk_rect clip;
22885 
22886     NK_ASSERT(state);
22887     NK_ASSERT(out);
22888     NK_ASSERT(style);
22889     if (!state || !out || !style)
22890         return ret;
22891 
22892     /* visible text area calculation */
22893     area.x = bounds.x + style->padding.x + style->border;
22894     area.y = bounds.y + style->padding.y + style->border;
22895     area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
22896     area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
22897     if (flags & NK_EDIT_MULTILINE)
22898         area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
22899     row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
22900 
22901     /* calculate clipping rectangle */
22902     old_clip = out->clip;
22903     nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
22904 
22905     /* update edit state */
22906     prev_state = (char)edit->active;
22907     is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
22908     if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) {
22909         edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
22910                                 bounds.x, bounds.y, bounds.w, bounds.h);
22911     }
22912 
22913     /* (de)activate text editor */
22914     if (!prev_state && edit->active) {
22915         const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
22916             NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE;
22917         nk_textedit_clear_state(edit, type, filter);
22918         if (flags & NK_EDIT_AUTO_SELECT)
22919             select_all = nk_true;
22920         if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
22921             edit->cursor = edit->string.len;
22922             in = 0;
22923         }
22924     } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
22925     if (flags & NK_EDIT_READ_ONLY)
22926         edit->mode = NK_TEXT_EDIT_MODE_VIEW;
22927     else if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
22928         edit->mode = NK_TEXT_EDIT_MODE_INSERT;
22929 
22930     ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
22931     if (prev_state != edit->active)
22932         ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
22933 
22934     /* handle user input */
22935     if (edit->active && in)
22936     {
22937         int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
22938         const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
22939         const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
22940 
22941         /* mouse click handler */
22942         is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
22943         if (select_all) {
22944             nk_textedit_select_all(edit);
22945         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
22946             in->mouse.buttons[NK_BUTTON_LEFT].clicked) {
22947             nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
22948         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
22949             (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
22950             nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
22951             cursor_follow = nk_true;
22952         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
22953             in->mouse.buttons[NK_BUTTON_RIGHT].down) {
22954             nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
22955             nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
22956             cursor_follow = nk_true;
22957         }
22958 
22959         {int i; /* keyboard input */
22960         int old_mode = edit->mode;
22961         for (i = 0; i < NK_KEY_MAX; ++i) {
22962             if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
22963             if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
22964                 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
22965                 cursor_follow = nk_true;
22966             }
22967         }
22968         if (old_mode != edit->mode) {
22969             in->keyboard.text_len = 0;
22970         }}
22971 
22972         /* text input */
22973         edit->filter = filter;
22974         if (in->keyboard.text_len) {
22975             nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
22976             cursor_follow = nk_true;
22977             in->keyboard.text_len = 0;
22978         }
22979 
22980         /* enter key handler */
22981         if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) {
22982             cursor_follow = nk_true;
22983             if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
22984                 nk_textedit_text(edit, "\n", 1);
22985             else if (flags & NK_EDIT_SIG_ENTER)
22986                 ret |= NK_EDIT_COMMITED;
22987             else nk_textedit_text(edit, "\n", 1);
22988         }
22989 
22990         /* cut & copy handler */
22991         {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
22992         int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
22993         if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
22994         {
22995             int glyph_len;
22996             nk_rune unicode;
22997             const char *text;
22998             int b = edit->select_start;
22999             int e = edit->select_end;
23000 
23001             int begin = NK_MIN(b, e);
23002             int end = NK_MAX(b, e);
23003             text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
23004             if (edit->clip.copy)
23005                 edit->clip.copy(edit->clip.userdata, text, end - begin);
23006             if (cut && !(flags & NK_EDIT_READ_ONLY)){
23007                 nk_textedit_cut(edit);
23008                 cursor_follow = nk_true;
23009             }
23010         }}
23011 
23012         /* paste handler */
23013         {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
23014         if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
23015             edit->clip.paste(edit->clip.userdata, edit);
23016             cursor_follow = nk_true;
23017         }}
23018 
23019         /* tab handler */
23020         {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
23021         if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
23022             nk_textedit_text(edit, "    ", 4);
23023             cursor_follow = nk_true;
23024         }}
23025     }
23026 
23027     /* set widget state */
23028     if (edit->active)
23029         *state = NK_WIDGET_STATE_ACTIVE;
23030     else nk_widget_state_reset(state);
23031 
23032     if (is_hovered)
23033         *state |= NK_WIDGET_STATE_HOVERED;
23034 
23035     /* DRAW EDIT */
23036     {const char *text = nk_str_get_const(&edit->string);
23037     int len = nk_str_len_char(&edit->string);
23038 
23039     {/* select background colors/images  */
23040     const struct nk_style_item *background;
23041     if (*state & NK_WIDGET_STATE_ACTIVED)
23042         background = &style->active;
23043     else if (*state & NK_WIDGET_STATE_HOVER)
23044         background = &style->hover;
23045     else background = &style->normal;
23046 
23047     /* draw background frame */
23048     if (background->type == NK_STYLE_ITEM_COLOR) {
23049         nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
23050         nk_fill_rect(out, bounds, style->rounding, background->data.color);
23051     } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
23052 
23053     area.w = NK_MAX(0, area.w - style->cursor_size);
23054     if (edit->active)
23055     {
23056         int total_lines = 1;
23057         struct nk_vec2 text_size = nk_vec2(0,0);
23058 
23059         /* text pointer positions */
23060         const char *cursor_ptr = 0;
23061         const char *select_begin_ptr = 0;
23062         const char *select_end_ptr = 0;
23063 
23064         /* 2D pixel positions */
23065         struct nk_vec2 cursor_pos = nk_vec2(0,0);
23066         struct nk_vec2 selection_offset_start = nk_vec2(0,0);
23067         struct nk_vec2 selection_offset_end = nk_vec2(0,0);
23068 
23069         int selection_begin = NK_MIN(edit->select_start, edit->select_end);
23070         int selection_end = NK_MAX(edit->select_start, edit->select_end);
23071 
23072         /* calculate total line count + total space + cursor/selection position */
23073         float line_width = 0.0f;
23074         if (text && len)
23075         {
23076             /* utf8 encoding */
23077             float glyph_width;
23078             int glyph_len = 0;
23079             nk_rune unicode = 0;
23080             int text_len = 0;
23081             int glyphs = 0;
23082             int row_begin = 0;
23083 
23084             glyph_len = nk_utf_decode(text, &unicode, len);
23085             glyph_width = font->width(font->userdata, font->height, text, glyph_len);
23086             line_width = 0;
23087 
23088             /* iterate all lines */
23089             while ((text_len < len) && glyph_len)
23090             {
23091                 /* set cursor 2D position and line */
23092                 if (!cursor_ptr && glyphs == edit->cursor)
23093                 {
23094                     int glyph_offset;
23095                     struct nk_vec2 out_offset;
23096                     struct nk_vec2 row_size;
23097                     const char *remaining;
23098 
23099                     /* calculate 2d position */
23100                     cursor_pos.y = (float)(total_lines-1) * row_height;
23101                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
23102                                 text_len-row_begin, row_height, &remaining,
23103                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
23104                     cursor_pos.x = row_size.x;
23105                     cursor_ptr = text + text_len;
23106                 }
23107 
23108                 /* set start selection 2D position and line */
23109                 if (!select_begin_ptr && edit->select_start != edit->select_end &&
23110                     glyphs == selection_begin)
23111                 {
23112                     int glyph_offset;
23113                     struct nk_vec2 out_offset;
23114                     struct nk_vec2 row_size;
23115                     const char *remaining;
23116 
23117                     /* calculate 2d position */
23118                     selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
23119                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
23120                                 text_len-row_begin, row_height, &remaining,
23121                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
23122                     selection_offset_start.x = row_size.x;
23123                     select_begin_ptr = text + text_len;
23124                 }
23125 
23126                 /* set end selection 2D position and line */
23127                 if (!select_end_ptr && edit->select_start != edit->select_end &&
23128                     glyphs == selection_end)
23129                 {
23130                     int glyph_offset;
23131                     struct nk_vec2 out_offset;
23132                     struct nk_vec2 row_size;
23133                     const char *remaining;
23134 
23135                     /* calculate 2d position */
23136                     selection_offset_end.y = (float)(total_lines-1) * row_height;
23137                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
23138                                 text_len-row_begin, row_height, &remaining,
23139                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
23140                     selection_offset_end.x = row_size.x;
23141                     select_end_ptr = text + text_len;
23142                 }
23143                 if (unicode == '\n') {
23144                     text_size.x = NK_MAX(text_size.x, line_width);
23145                     total_lines++;
23146                     line_width = 0;
23147                     text_len++;
23148                     glyphs++;
23149                     row_begin = text_len;
23150                     glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
23151                     glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
23152                     continue;
23153                 }
23154 
23155                 glyphs++;
23156                 text_len += glyph_len;
23157                 line_width += (float)glyph_width;
23158 
23159                 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
23160                 glyph_width = font->width(font->userdata, font->height,
23161                     text+text_len, glyph_len);
23162                 continue;
23163             }
23164             text_size.y = (float)total_lines * row_height;
23165 
23166             /* handle case when cursor is at end of text buffer */
23167             if (!cursor_ptr && edit->cursor == edit->string.len) {
23168                 cursor_pos.x = line_width;
23169                 cursor_pos.y = text_size.y - row_height;
23170             }
23171         }
23172         {
23173             /* scrollbar */
23174             if (cursor_follow)
23175             {
23176                 /* update scrollbar to follow cursor */
23177                 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
23178                     /* horizontal scroll */
23179                     const float scroll_increment = area.w * 0.25f;
23180                     if (cursor_pos.x < edit->scrollbar.x)
23181                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
23182                     if (cursor_pos.x >= edit->scrollbar.x + area.w)
23183                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, edit->scrollbar.x + scroll_increment);
23184                 } else edit->scrollbar.x = 0;
23185 
23186                 if (flags & NK_EDIT_MULTILINE) {
23187                     /* vertical scroll */
23188                     if (cursor_pos.y < edit->scrollbar.y)
23189                         edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
23190                     if (cursor_pos.y >= edit->scrollbar.y + area.h)
23191                         edit->scrollbar.y = edit->scrollbar.y + row_height;
23192                 } else edit->scrollbar.y = 0;
23193             }
23194 
23195             /* scrollbar widget */
23196             if (flags & NK_EDIT_MULTILINE)
23197             {
23198                 nk_flags ws;
23199                 struct nk_rect scroll;
23200                 float scroll_target;
23201                 float scroll_offset;
23202                 float scroll_step;
23203                 float scroll_inc;
23204 
23205                 scroll = area;
23206                 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
23207                 scroll.w = style->scrollbar_size.x;
23208 
23209                 scroll_offset = edit->scrollbar.y;
23210                 scroll_step = scroll.h * 0.10f;
23211                 scroll_inc = scroll.h * 0.01f;
23212                 scroll_target = text_size.y;
23213                 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
23214                         scroll_offset, scroll_target, scroll_step, scroll_inc,
23215                         &style->scrollbar, in, font);
23216             }
23217         }
23218 
23219         /* draw text */
23220         {struct nk_color background_color;
23221         struct nk_color text_color;
23222         struct nk_color sel_background_color;
23223         struct nk_color sel_text_color;
23224         struct nk_color cursor_color;
23225         struct nk_color cursor_text_color;
23226         const struct nk_style_item *background;
23227         nk_push_scissor(out, clip);
23228 
23229         /* select correct colors to draw */
23230         if (*state & NK_WIDGET_STATE_ACTIVED) {
23231             background = &style->active;
23232             text_color = style->text_active;
23233             sel_text_color = style->selected_text_hover;
23234             sel_background_color = style->selected_hover;
23235             cursor_color = style->cursor_hover;
23236             cursor_text_color = style->cursor_text_hover;
23237         } else if (*state & NK_WIDGET_STATE_HOVER) {
23238             background = &style->hover;
23239             text_color = style->text_hover;
23240             sel_text_color = style->selected_text_hover;
23241             sel_background_color = style->selected_hover;
23242             cursor_text_color = style->cursor_text_hover;
23243             cursor_color = style->cursor_hover;
23244         } else {
23245             background = &style->normal;
23246             text_color = style->text_normal;
23247             sel_text_color = style->selected_text_normal;
23248             sel_background_color = style->selected_normal;
23249             cursor_color = style->cursor_normal;
23250             cursor_text_color = style->cursor_text_normal;
23251         }
23252         if (background->type == NK_STYLE_ITEM_IMAGE)
23253             background_color = nk_rgba(0,0,0,0);
23254         else background_color = background->data.color;
23255 
23256 
23257         if (edit->select_start == edit->select_end) {
23258             /* no selection so just draw the complete text */
23259             const char *begin = nk_str_get_const(&edit->string);
23260             int l = nk_str_len_char(&edit->string);
23261             nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23262                 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
23263                 background_color, text_color, nk_false);
23264         } else {
23265             /* edit has selection so draw 1-3 text chunks */
23266             if (edit->select_start != edit->select_end && selection_begin > 0){
23267                 /* draw unselected text before selection */
23268                 const char *begin = nk_str_get_const(&edit->string);
23269                 NK_ASSERT(select_begin_ptr);
23270                 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23271                     area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
23272                     row_height, font, background_color, text_color, nk_false);
23273             }
23274             if (edit->select_start != edit->select_end) {
23275                 /* draw selected text */
23276                 NK_ASSERT(select_begin_ptr);
23277                 if (!select_end_ptr) {
23278                     const char *begin = nk_str_get_const(&edit->string);
23279                     select_end_ptr = begin + nk_str_len_char(&edit->string);
23280                 }
23281                 nk_edit_draw_text(out, style,
23282                     area.x - edit->scrollbar.x,
23283                     area.y + selection_offset_start.y - edit->scrollbar.y,
23284                     selection_offset_start.x,
23285                     select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
23286                     row_height, font, sel_background_color, sel_text_color, nk_true);
23287             }
23288             if ((edit->select_start != edit->select_end &&
23289                 selection_end < edit->string.len))
23290             {
23291                 /* draw unselected text after selected text */
23292                 const char *begin = select_end_ptr;
23293                 const char *end = nk_str_get_const(&edit->string) +
23294                                     nk_str_len_char(&edit->string);
23295                 NK_ASSERT(select_end_ptr);
23296                 nk_edit_draw_text(out, style,
23297                     area.x - edit->scrollbar.x,
23298                     area.y + selection_offset_end.y - edit->scrollbar.y,
23299                     selection_offset_end.x,
23300                     begin, (int)(end - begin), row_height, font,
23301                     background_color, text_color, nk_true);
23302             }
23303         }
23304 
23305         /* cursor */
23306         if (edit->select_start == edit->select_end)
23307         {
23308             if (edit->cursor >= nk_str_len(&edit->string) ||
23309                 (cursor_ptr && *cursor_ptr == '\n')) {
23310                 /* draw cursor at end of line */
23311                 struct nk_rect cursor;
23312                 cursor.w = style->cursor_size;
23313                 cursor.h = font->height;
23314                 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
23315                 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
23316                 cursor.y -= edit->scrollbar.y;
23317                 nk_fill_rect(out, cursor, 0, cursor_color);
23318             } else {
23319                 /* draw cursor inside text */
23320                 int glyph_len;
23321                 struct nk_rect label;
23322                 struct nk_text txt;
23323 
23324                 nk_rune unicode;
23325                 NK_ASSERT(cursor_ptr);
23326                 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
23327 
23328                 label.x = area.x + cursor_pos.x - edit->scrollbar.x;
23329                 label.y = area.y + cursor_pos.y - edit->scrollbar.y;
23330                 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
23331                 label.h = row_height;
23332 
23333                 txt.padding = nk_vec2(0,0);
23334                 txt.background = cursor_color;;
23335                 txt.text = cursor_text_color;
23336                 nk_fill_rect(out, label, 0, cursor_color);
23337                 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
23338             }
23339         }}
23340     } else {
23341         /* not active so just draw text */
23342         int l = nk_str_len_char(&edit->string);
23343         const char *begin = nk_str_get_const(&edit->string);
23344 
23345         const struct nk_style_item *background;
23346         struct nk_color background_color;
23347         struct nk_color text_color;
23348         nk_push_scissor(out, clip);
23349         if (*state & NK_WIDGET_STATE_ACTIVED) {
23350             background = &style->active;
23351             text_color = style->text_active;
23352         } else if (*state & NK_WIDGET_STATE_HOVER) {
23353             background = &style->hover;
23354             text_color = style->text_hover;
23355         } else {
23356             background = &style->normal;
23357             text_color = style->text_normal;
23358         }
23359         if (background->type == NK_STYLE_ITEM_IMAGE)
23360             background_color = nk_rgba(0,0,0,0);
23361         else background_color = background->data.color;
23362         nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
23363             area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
23364             background_color, text_color, nk_false);
23365     }
23366     nk_push_scissor(out, old_clip);}
23367     return ret;
23368 }
23369 NK_API void
23370 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
23371 {
23372     nk_hash hash;
23373     struct nk_window *win;
23374 
23375     NK_ASSERT(ctx);
23376     NK_ASSERT(ctx->current);
23377     if (!ctx || !ctx->current) return;
23378 
23379     win = ctx->current;
23380     hash = win->edit.seq;
23381     win->edit.active = nk_true;
23382     win->edit.name = hash;
23383     if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
23384         win->edit.mode = NK_TEXT_EDIT_MODE_INSERT;
23385 }
23386 NK_API void
23387 nk_edit_unfocus(struct nk_context *ctx)
23388 {
23389     struct nk_window *win;
23390     NK_ASSERT(ctx);
23391     NK_ASSERT(ctx->current);
23392     if (!ctx || !ctx->current) return;
23393 
23394     win = ctx->current;
23395     win->edit.active = nk_false;
23396     win->edit.name = 0;
23397 }
23398 NK_API nk_flags
23399 nk_edit_string(struct nk_context *ctx, nk_flags flags,
23400     char *memory, int *len, int max, nk_plugin_filter filter)
23401 {
23402     nk_hash hash;
23403     nk_flags state;
23404     struct nk_text_edit *edit;
23405     struct nk_window *win;
23406 
23407     NK_ASSERT(ctx);
23408     NK_ASSERT(memory);
23409     NK_ASSERT(len);
23410     if (!ctx || !memory || !len)
23411         return 0;
23412 
23413     filter = (!filter) ? nk_filter_default: filter;
23414     win = ctx->current;
23415     hash = win->edit.seq;
23416     edit = &ctx->text_edit;
23417     nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
23418         NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter);
23419 
23420     if (win->edit.active && hash == win->edit.name) {
23421         if (flags & NK_EDIT_NO_CURSOR)
23422             edit->cursor = nk_utf_len(memory, *len);
23423         else edit->cursor = win->edit.cursor;
23424         if (!(flags & NK_EDIT_SELECTABLE)) {
23425             edit->select_start = win->edit.cursor;
23426             edit->select_end = win->edit.cursor;
23427         } else {
23428             edit->select_start = win->edit.sel_start;
23429             edit->select_end = win->edit.sel_end;
23430         }
23431         edit->mode = win->edit.mode;
23432         edit->scrollbar.x = (float)win->edit.scrollbar.x;
23433         edit->scrollbar.y = (float)win->edit.scrollbar.y;
23434         edit->active = nk_true;
23435     } else edit->active = nk_false;
23436 
23437     max = NK_MAX(1, max);
23438     *len = NK_MIN(*len, max-1);
23439     nk_str_init_fixed(&edit->string, memory, (nk_size)max);
23440     edit->string.buffer.allocated = (nk_size)*len;
23441     edit->string.len = nk_utf_len(memory, *len);
23442     state = nk_edit_buffer(ctx, flags, edit, filter);
23443     *len = (int)edit->string.buffer.allocated;
23444 
23445     if (edit->active) {
23446         win->edit.cursor = edit->cursor;
23447         win->edit.sel_start = edit->select_start;
23448         win->edit.sel_end = edit->select_end;
23449         win->edit.mode = edit->mode;
23450         win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x;
23451         win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y;
23452     } return state;
23453 }
23454 NK_API nk_flags
23455 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
23456     struct nk_text_edit *edit, nk_plugin_filter filter)
23457 {
23458     struct nk_window *win;
23459     struct nk_style *style;
23460     struct nk_input *in;
23461 
23462     enum nk_widget_layout_states state;
23463     struct nk_rect bounds;
23464 
23465     nk_flags ret_flags = 0;
23466     unsigned char prev_state;
23467     nk_hash hash;
23468 
23469     /* make sure correct values */
23470     NK_ASSERT(ctx);
23471     NK_ASSERT(edit);
23472     NK_ASSERT(ctx->current);
23473     NK_ASSERT(ctx->current->layout);
23474     if (!ctx || !ctx->current || !ctx->current->layout)
23475         return 0;
23476 
23477     win = ctx->current;
23478     style = &ctx->style;
23479     state = nk_widget(&bounds, ctx);
23480     if (!state) return state;
23481     in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23482 
23483     /* check if edit is currently hot item */
23484     hash = win->edit.seq++;
23485     if (win->edit.active && hash == win->edit.name) {
23486         if (flags & NK_EDIT_NO_CURSOR)
23487             edit->cursor = edit->string.len;
23488         if (!(flags & NK_EDIT_SELECTABLE)) {
23489             edit->select_start = edit->cursor;
23490             edit->select_end = edit->cursor;
23491         }
23492         if (flags & NK_EDIT_CLIPBOARD)
23493             edit->clip = ctx->clip;
23494         edit->active = (unsigned char)win->edit.active;
23495     } else edit->active = nk_false;
23496     edit->mode = win->edit.mode;
23497 
23498     filter = (!filter) ? nk_filter_default: filter;
23499     prev_state = (unsigned char)edit->active;
23500     in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
23501     ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
23502                     filter, edit, &style->edit, in, style->font);
23503 
23504     if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23505         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT];
23506     if (edit->active && prev_state != edit->active) {
23507         /* current edit is now hot */
23508         win->edit.active = nk_true;
23509         win->edit.name = hash;
23510     } else if (prev_state && !edit->active) {
23511         /* current edit is now cold */
23512         win->edit.active = nk_false;
23513     } return ret_flags;
23514 }
23515 NK_API nk_flags
23516 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
23517     char *buffer, int max, nk_plugin_filter filter)
23518 {
23519     nk_flags result;
23520     int len = nk_strlen(buffer);
23521     result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
23522     buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
23523     return result;
23524 }
23525 
23526 
23527 
23528 
23529 
23530 /* ===============================================================
23531  *
23532  *                              PROPERTY
23533  *
23534  * ===============================================================*/
23535 NK_LIB void
23536 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
23537     struct nk_rect drag, struct nk_property_variant *variant,
23538     float inc_per_pixel)
23539 {
23540     int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
23541     int left_mouse_click_in_cursor = in &&
23542         nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true);
23543 
23544     nk_widget_state_reset(state);
23545     if (nk_input_is_mouse_hovering_rect(in, drag))
23546         *state = NK_WIDGET_STATE_HOVERED;
23547 
23548     if (left_mouse_down && left_mouse_click_in_cursor) {
23549         float delta, pixels;
23550         pixels = in->mouse.delta.x;
23551         delta = pixels * inc_per_pixel;
23552         switch (variant->kind) {
23553         default: break;
23554         case NK_PROPERTY_INT:
23555             variant->value.i = variant->value.i + (int)delta;
23556             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
23557             break;
23558         case NK_PROPERTY_FLOAT:
23559             variant->value.f = variant->value.f + (float)delta;
23560             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
23561             break;
23562         case NK_PROPERTY_DOUBLE:
23563             variant->value.d = variant->value.d + (double)delta;
23564             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
23565             break;
23566         }
23567         *state = NK_WIDGET_STATE_ACTIVE;
23568     }
23569     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
23570         *state |= NK_WIDGET_STATE_ENTERED;
23571     else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
23572         *state |= NK_WIDGET_STATE_LEFT;
23573 }
23574 NK_LIB void
23575 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
23576     struct nk_rect property,  struct nk_rect label, struct nk_rect edit,
23577     struct nk_rect empty, int *state, struct nk_property_variant *variant,
23578     float inc_per_pixel)
23579 {
23580     if (in && *state == NK_PROPERTY_DEFAULT) {
23581         if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
23582             *state = NK_PROPERTY_EDIT;
23583         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true))
23584             *state = NK_PROPERTY_DRAG;
23585         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true))
23586             *state = NK_PROPERTY_DRAG;
23587     }
23588     if (*state == NK_PROPERTY_DRAG) {
23589         nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
23590         if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
23591     }
23592 }
23593 NK_LIB void
23594 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
23595     const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
23596     const char *name, int len, const struct nk_user_font *font)
23597 {
23598     struct nk_text text;
23599     const struct nk_style_item *background;
23600 
23601     /* select correct background and text color */
23602     if (state & NK_WIDGET_STATE_ACTIVED) {
23603         background = &style->active;
23604         text.text = style->label_active;
23605     } else if (state & NK_WIDGET_STATE_HOVER) {
23606         background = &style->hover;
23607         text.text = style->label_hover;
23608     } else {
23609         background = &style->normal;
23610         text.text = style->label_normal;
23611     }
23612 
23613     /* draw background */
23614     if (background->type == NK_STYLE_ITEM_IMAGE) {
23615         nk_draw_image(out, *bounds, &background->data.image, nk_white);
23616         text.background = nk_rgba(0,0,0,0);
23617     } else {
23618         text.background = background->data.color;
23619         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
23620         nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
23621     }
23622 
23623     /* draw label */
23624     text.padding = nk_vec2(0,0);
23625     nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
23626 }
23627 NK_LIB void
23628 nk_do_property(nk_flags *ws,
23629     struct nk_command_buffer *out, struct nk_rect property,
23630     const char *name, struct nk_property_variant *variant,
23631     float inc_per_pixel, char *buffer, int *len,
23632     int *state, int *cursor, int *select_begin, int *select_end,
23633     const struct nk_style_property *style,
23634     enum nk_property_filter filter, struct nk_input *in,
23635     const struct nk_user_font *font, struct nk_text_edit *text_edit,
23636     enum nk_button_behavior behavior)
23637 {
23638     const nk_plugin_filter filters[] = {
23639         nk_filter_decimal,
23640         nk_filter_float
23641     };
23642     int active, old;
23643     int num_len, name_len;
23644     char string[NK_MAX_NUMBER_BUFFER];
23645     float size;
23646 
23647     char *dst = 0;
23648     int *length;
23649 
23650     struct nk_rect left;
23651     struct nk_rect right;
23652     struct nk_rect label;
23653     struct nk_rect edit;
23654     struct nk_rect empty;
23655 
23656     /* left decrement button */
23657     left.h = font->height/2;
23658     left.w = left.h;
23659     left.x = property.x + style->border + style->padding.x;
23660     left.y = property.y + style->border + property.h/2.0f - left.h/2;
23661 
23662     /* text label */
23663     name_len = nk_strlen(name);
23664     size = font->width(font->userdata, font->height, name, name_len);
23665     label.x = left.x + left.w + style->padding.x;
23666     label.w = (float)size + 2 * style->padding.x;
23667     label.y = property.y + style->border + style->padding.y;
23668     label.h = property.h - (2 * style->border + 2 * style->padding.y);
23669 
23670     /* right increment button */
23671     right.y = left.y;
23672     right.w = left.w;
23673     right.h = left.h;
23674     right.x = property.x + property.w - (right.w + style->padding.x);
23675 
23676     /* edit */
23677     if (*state == NK_PROPERTY_EDIT) {
23678         size = font->width(font->userdata, font->height, buffer, *len);
23679         size += style->edit.cursor_size;
23680         length = len;
23681         dst = buffer;
23682     } else {
23683         switch (variant->kind) {
23684         default: break;
23685         case NK_PROPERTY_INT:
23686             nk_itoa(string, variant->value.i);
23687             num_len = nk_strlen(string);
23688             break;
23689         case NK_PROPERTY_FLOAT:
23690             NK_DTOA(string, (double)variant->value.f);
23691             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
23692             break;
23693         case NK_PROPERTY_DOUBLE:
23694             NK_DTOA(string, variant->value.d);
23695             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
23696             break;
23697         }
23698         size = font->width(font->userdata, font->height, string, num_len);
23699         dst = string;
23700         length = &num_len;
23701     }
23702 
23703     edit.w =  (float)size + 2 * style->padding.x;
23704     edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
23705     edit.x = right.x - (edit.w + style->padding.x);
23706     edit.y = property.y + style->border;
23707     edit.h = property.h - (2 * style->border);
23708 
23709     /* empty left space activator */
23710     empty.w = edit.x - (label.x + label.w);
23711     empty.x = label.x + label.w;
23712     empty.y = property.y;
23713     empty.h = property.h;
23714 
23715     /* update property */
23716     old = (*state == NK_PROPERTY_EDIT);
23717     nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
23718 
23719     /* draw property */
23720     if (style->draw_begin) style->draw_begin(out, style->userdata);
23721     nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
23722     if (style->draw_end) style->draw_end(out, style->userdata);
23723 
23724     /* execute right button  */
23725     if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
23726         switch (variant->kind) {
23727         default: break;
23728         case NK_PROPERTY_INT:
23729             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
23730         case NK_PROPERTY_FLOAT:
23731             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
23732         case NK_PROPERTY_DOUBLE:
23733             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
23734         }
23735     }
23736     /* execute left button  */
23737     if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
23738         switch (variant->kind) {
23739         default: break;
23740         case NK_PROPERTY_INT:
23741             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
23742         case NK_PROPERTY_FLOAT:
23743             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
23744         case NK_PROPERTY_DOUBLE:
23745             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
23746         }
23747     }
23748     if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
23749         /* property has been activated so setup buffer */
23750         NK_MEMCPY(buffer, dst, (nk_size)*length);
23751         *cursor = nk_utf_len(buffer, *length);
23752         *len = *length;
23753         length = len;
23754         dst = buffer;
23755         active = 0;
23756     } else active = (*state == NK_PROPERTY_EDIT);
23757 
23758     /* execute and run text edit field */
23759     nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
23760     text_edit->active = (unsigned char)active;
23761     text_edit->string.len = *length;
23762     text_edit->cursor = NK_CLAMP(0, *cursor, *length);
23763     text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
23764     text_edit->select_end = NK_CLAMP(0,*select_end, *length);
23765     text_edit->string.buffer.allocated = (nk_size)*length;
23766     text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER;
23767     text_edit->string.buffer.memory.ptr = dst;
23768     text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
23769     text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
23770     nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
23771         filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
23772 
23773     *length = text_edit->string.len;
23774     *cursor = text_edit->cursor;
23775     *select_begin = text_edit->select_start;
23776     *select_end = text_edit->select_end;
23777     if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
23778         text_edit->active = nk_false;
23779 
23780     if (active && !text_edit->active) {
23781         /* property is now not active so convert edit text to value*/
23782         *state = NK_PROPERTY_DEFAULT;
23783         buffer[*len] = '\0';
23784         switch (variant->kind) {
23785         default: break;
23786         case NK_PROPERTY_INT:
23787             variant->value.i = nk_strtoi(buffer, 0);
23788             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
23789             break;
23790         case NK_PROPERTY_FLOAT:
23791             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
23792             variant->value.f = nk_strtof(buffer, 0);
23793             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
23794             break;
23795         case NK_PROPERTY_DOUBLE:
23796             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
23797             variant->value.d = nk_strtod(buffer, 0);
23798             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
23799             break;
23800         }
23801     }
23802 }
23803 NK_LIB struct nk_property_variant
23804 nk_property_variant_int(int value, int min_value, int max_value, int step)
23805 {
23806     struct nk_property_variant result;
23807     result.kind = NK_PROPERTY_INT;
23808     result.value.i = value;
23809     result.min_value.i = min_value;
23810     result.max_value.i = max_value;
23811     result.step.i = step;
23812     return result;
23813 }
23814 NK_LIB struct nk_property_variant
23815 nk_property_variant_float(float value, float min_value, float max_value, float step)
23816 {
23817     struct nk_property_variant result;
23818     result.kind = NK_PROPERTY_FLOAT;
23819     result.value.f = value;
23820     result.min_value.f = min_value;
23821     result.max_value.f = max_value;
23822     result.step.f = step;
23823     return result;
23824 }
23825 NK_LIB struct nk_property_variant
23826 nk_property_variant_double(double value, double min_value, double max_value,
23827     double step)
23828 {
23829     struct nk_property_variant result;
23830     result.kind = NK_PROPERTY_DOUBLE;
23831     result.value.d = value;
23832     result.min_value.d = min_value;
23833     result.max_value.d = max_value;
23834     result.step.d = step;
23835     return result;
23836 }
23837 NK_LIB void
23838 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
23839     float inc_per_pixel, const enum nk_property_filter filter)
23840 {
23841     struct nk_window *win;
23842     struct nk_panel *layout;
23843     struct nk_input *in;
23844     const struct nk_style *style;
23845 
23846     struct nk_rect bounds;
23847     enum nk_widget_layout_states s;
23848 
23849     int *state = 0;
23850     nk_hash hash = 0;
23851     char *buffer = 0;
23852     int *len = 0;
23853     int *cursor = 0;
23854     int *select_begin = 0;
23855     int *select_end = 0;
23856     int old_state;
23857 
23858     char dummy_buffer[NK_MAX_NUMBER_BUFFER];
23859     int dummy_state = NK_PROPERTY_DEFAULT;
23860     int dummy_length = 0;
23861     int dummy_cursor = 0;
23862     int dummy_select_begin = 0;
23863     int dummy_select_end = 0;
23864 
23865     NK_ASSERT(ctx);
23866     NK_ASSERT(ctx->current);
23867     NK_ASSERT(ctx->current->layout);
23868     if (!ctx || !ctx->current || !ctx->current->layout)
23869         return;
23870 
23871     win = ctx->current;
23872     layout = win->layout;
23873     style = &ctx->style;
23874     s = nk_widget(&bounds, ctx);
23875     if (!s) return;
23876 
23877     /* calculate hash from name */
23878     if (name[0] == '#') {
23879         hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
23880         name++; /* special number hash */
23881     } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
23882 
23883     /* check if property is currently hot item */
23884     if (win->property.active && hash == win->property.name) {
23885         buffer = win->property.buffer;
23886         len = &win->property.length;
23887         cursor = &win->property.cursor;
23888         state = &win->property.state;
23889         select_begin = &win->property.select_start;
23890         select_end = &win->property.select_end;
23891     } else {
23892         buffer = dummy_buffer;
23893         len = &dummy_length;
23894         cursor = &dummy_cursor;
23895         state = &dummy_state;
23896         select_begin =  &dummy_select_begin;
23897         select_end = &dummy_select_end;
23898     }
23899 
23900     /* execute property widget */
23901     old_state = *state;
23902     ctx->text_edit.clip = ctx->clip;
23903     in = ((s == NK_WIDGET_ROM && !win->property.active) ||
23904         layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23905     nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
23906         variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
23907         select_end, &style->property, filter, in, style->font, &ctx->text_edit,
23908         ctx->button_behavior);
23909 
23910     if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
23911         /* current property is now hot */
23912         win->property.active = 1;
23913         NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
23914         win->property.length = *len;
23915         win->property.cursor = *cursor;
23916         win->property.state = *state;
23917         win->property.name = hash;
23918         win->property.select_start = *select_begin;
23919         win->property.select_end = *select_end;
23920         if (*state == NK_PROPERTY_DRAG) {
23921             ctx->input.mouse.grab = nk_true;
23922             ctx->input.mouse.grabbed = nk_true;
23923         }
23924     }
23925     /* check if previously active property is now inactive */
23926     if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
23927         if (old_state == NK_PROPERTY_DRAG) {
23928             ctx->input.mouse.grab = nk_false;
23929             ctx->input.mouse.grabbed = nk_false;
23930             ctx->input.mouse.ungrab = nk_true;
23931         }
23932         win->property.select_start = 0;
23933         win->property.select_end = 0;
23934         win->property.active = 0;
23935     }
23936 }
23937 NK_API void
23938 nk_property_int(struct nk_context *ctx, const char *name,
23939     int min, int *val, int max, int step, float inc_per_pixel)
23940 {
23941     struct nk_property_variant variant;
23942     NK_ASSERT(ctx);
23943     NK_ASSERT(name);
23944     NK_ASSERT(val);
23945 
23946     if (!ctx || !ctx->current || !name || !val) return;
23947     variant = nk_property_variant_int(*val, min, max, step);
23948     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
23949     *val = variant.value.i;
23950 }
23951 NK_API void
23952 nk_property_float(struct nk_context *ctx, const char *name,
23953     float min, float *val, float max, float step, float inc_per_pixel)
23954 {
23955     struct nk_property_variant variant;
23956     NK_ASSERT(ctx);
23957     NK_ASSERT(name);
23958     NK_ASSERT(val);
23959 
23960     if (!ctx || !ctx->current || !name || !val) return;
23961     variant = nk_property_variant_float(*val, min, max, step);
23962     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23963     *val = variant.value.f;
23964 }
23965 NK_API void
23966 nk_property_double(struct nk_context *ctx, const char *name,
23967     double min, double *val, double max, double step, float inc_per_pixel)
23968 {
23969     struct nk_property_variant variant;
23970     NK_ASSERT(ctx);
23971     NK_ASSERT(name);
23972     NK_ASSERT(val);
23973 
23974     if (!ctx || !ctx->current || !name || !val) return;
23975     variant = nk_property_variant_double(*val, min, max, step);
23976     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
23977     *val = variant.value.d;
23978 }
23979 NK_API int
23980 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
23981     int max, int step, float inc_per_pixel)
23982 {
23983     struct nk_property_variant variant;
23984     NK_ASSERT(ctx);
23985     NK_ASSERT(name);
23986 
23987     if (!ctx || !ctx->current || !name) return val;
23988     variant = nk_property_variant_int(val, min, max, step);
23989     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
23990     val = variant.value.i;
23991     return val;
23992 }
23993 NK_API float
23994 nk_propertyf(struct nk_context *ctx, const char *name, float min,
23995     float val, float max, float step, float inc_per_pixel)
23996 {
23997     struct nk_property_variant variant;
23998     NK_ASSERT(ctx);
23999     NK_ASSERT(name);
24000 
24001     if (!ctx || !ctx->current || !name) return val;
24002     variant = nk_property_variant_float(val, min, max, step);
24003     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
24004     val = variant.value.f;
24005     return val;
24006 }
24007 NK_API double
24008 nk_propertyd(struct nk_context *ctx, const char *name, double min,
24009     double val, double max, double step, float inc_per_pixel)
24010 {
24011     struct nk_property_variant variant;
24012     NK_ASSERT(ctx);
24013     NK_ASSERT(name);
24014 
24015     if (!ctx || !ctx->current || !name) return val;
24016     variant = nk_property_variant_double(val, min, max, step);
24017     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
24018     val = variant.value.d;
24019     return val;
24020 }
24021 
24022 
24023 
24024 
24025 
24026 /* ==============================================================
24027  *
24028  *                          CHART
24029  *
24030  * ===============================================================*/
24031 NK_API int
24032 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
24033     struct nk_color color, struct nk_color highlight,
24034     int count, float min_value, float max_value)
24035 {
24036     struct nk_window *win;
24037     struct nk_chart *chart;
24038     const struct nk_style *config;
24039     const struct nk_style_chart *style;
24040 
24041     const struct nk_style_item *background;
24042     struct nk_rect bounds = {0, 0, 0, 0};
24043 
24044     NK_ASSERT(ctx);
24045     NK_ASSERT(ctx->current);
24046     NK_ASSERT(ctx->current->layout);
24047 
24048     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
24049     if (!nk_widget(&bounds, ctx)) {
24050         chart = &ctx->current->layout->chart;
24051         nk_zero(chart, sizeof(*chart));
24052         return 0;
24053     }
24054 
24055     win = ctx->current;
24056     config = &ctx->style;
24057     chart = &win->layout->chart;
24058     style = &config->chart;
24059 
24060     /* setup basic generic chart  */
24061     nk_zero(chart, sizeof(*chart));
24062     chart->x = bounds.x + style->padding.x;
24063     chart->y = bounds.y + style->padding.y;
24064     chart->w = bounds.w - 2 * style->padding.x;
24065     chart->h = bounds.h - 2 * style->padding.y;
24066     chart->w = NK_MAX(chart->w, 2 * style->padding.x);
24067     chart->h = NK_MAX(chart->h, 2 * style->padding.y);
24068 
24069     /* add first slot into chart */
24070     {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
24071     slot->type = type;
24072     slot->count = count;
24073     slot->color = color;
24074     slot->highlight = highlight;
24075     slot->min = NK_MIN(min_value, max_value);
24076     slot->max = NK_MAX(min_value, max_value);
24077     slot->range = slot->max - slot->min;}
24078 
24079     /* draw chart background */
24080     background = &style->background;
24081     if (background->type == NK_STYLE_ITEM_IMAGE) {
24082         nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
24083     } else {
24084         nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
24085         nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
24086             style->rounding, style->background.data.color);
24087     }
24088     return 1;
24089 }
24090 NK_API int
24091 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
24092     int count, float min_value, float max_value)
24093 {
24094     return nk_chart_begin_colored(ctx, type, ctx->style.chart.color,
24095                 ctx->style.chart.selected_color, count, min_value, max_value);
24096 }
24097 NK_API void
24098 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
24099     struct nk_color color, struct nk_color highlight,
24100     int count, float min_value, float max_value)
24101 {
24102     NK_ASSERT(ctx);
24103     NK_ASSERT(ctx->current);
24104     NK_ASSERT(ctx->current->layout);
24105     NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
24106     if (!ctx || !ctx->current || !ctx->current->layout) return;
24107     if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
24108 
24109     /* add another slot into the graph */
24110     {struct nk_chart *chart = &ctx->current->layout->chart;
24111     struct nk_chart_slot *slot = &chart->slots[chart->slot++];
24112     slot->type = type;
24113     slot->count = count;
24114     slot->color = color;
24115     slot->highlight = highlight;
24116     slot->min = NK_MIN(min_value, max_value);
24117     slot->max = NK_MAX(min_value, max_value);
24118     slot->range = slot->max - slot->min;}
24119 }
24120 NK_API void
24121 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
24122     int count, float min_value, float max_value)
24123 {
24124     nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color,
24125         ctx->style.chart.selected_color, count, min_value, max_value);
24126 }
24127 NK_INTERN nk_flags
24128 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
24129     struct nk_chart *g, float value, int slot)
24130 {
24131     struct nk_panel *layout = win->layout;
24132     const struct nk_input *i = &ctx->input;
24133     struct nk_command_buffer *out = &win->buffer;
24134 
24135     nk_flags ret = 0;
24136     struct nk_vec2 cur;
24137     struct nk_rect bounds;
24138     struct nk_color color;
24139     float step;
24140     float range;
24141     float ratio;
24142 
24143     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
24144     step = g->w / (float)g->slots[slot].count;
24145     range = g->slots[slot].max - g->slots[slot].min;
24146     ratio = (value - g->slots[slot].min) / range;
24147 
24148     if (g->slots[slot].index == 0) {
24149         /* first data point does not have a connection */
24150         g->slots[slot].last.x = g->x;
24151         g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
24152 
24153         bounds.x = g->slots[slot].last.x - 2;
24154         bounds.y = g->slots[slot].last.y - 2;
24155         bounds.w = bounds.h = 4;
24156 
24157         color = g->slots[slot].color;
24158         if (!(layout->flags & NK_WINDOW_ROM) &&
24159             NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
24160             ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
24161             ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
24162                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
24163             color = g->slots[slot].highlight;
24164         }
24165         nk_fill_rect(out, bounds, 0, color);
24166         g->slots[slot].index += 1;
24167         return ret;
24168     }
24169 
24170     /* draw a line between the last data point and the new one */
24171     color = g->slots[slot].color;
24172     cur.x = g->x + (float)(step * (float)g->slots[slot].index);
24173     cur.y = (g->y + g->h) - (ratio * (float)g->h);
24174     nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
24175 
24176     bounds.x = cur.x - 3;
24177     bounds.y = cur.y - 3;
24178     bounds.w = bounds.h = 6;
24179 
24180     /* user selection of current data point */
24181     if (!(layout->flags & NK_WINDOW_ROM)) {
24182         if (nk_input_is_mouse_hovering_rect(i, bounds)) {
24183             ret = NK_CHART_HOVERING;
24184             ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
24185                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
24186             color = g->slots[slot].highlight;
24187         }
24188     }
24189     nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
24190 
24191     /* save current data point position */
24192     g->slots[slot].last.x = cur.x;
24193     g->slots[slot].last.y = cur.y;
24194     g->slots[slot].index  += 1;
24195     return ret;
24196 }
24197 NK_INTERN nk_flags
24198 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
24199     struct nk_chart *chart, float value, int slot)
24200 {
24201     struct nk_command_buffer *out = &win->buffer;
24202     const struct nk_input *in = &ctx->input;
24203     struct nk_panel *layout = win->layout;
24204 
24205     float ratio;
24206     nk_flags ret = 0;
24207     struct nk_color color;
24208     struct nk_rect item = {0,0,0,0};
24209 
24210     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
24211     if (chart->slots[slot].index  >= chart->slots[slot].count)
24212         return nk_false;
24213     if (chart->slots[slot].count) {
24214         float padding = (float)(chart->slots[slot].count-1);
24215         item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
24216     }
24217 
24218     /* calculate bounds of current bar chart entry */
24219     color = chart->slots[slot].color;;
24220     item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
24221     if (value >= 0) {
24222         ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
24223         item.y = (chart->y + chart->h) - chart->h * ratio;
24224     } else {
24225         ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
24226         item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
24227     }
24228     item.x = chart->x + ((float)chart->slots[slot].index * item.w);
24229     item.x = item.x + ((float)chart->slots[slot].index);
24230 
24231     /* user chart bar selection */
24232     if (!(layout->flags & NK_WINDOW_ROM) &&
24233         NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
24234         ret = NK_CHART_HOVERING;
24235         ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
24236                 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
24237         color = chart->slots[slot].highlight;
24238     }
24239     nk_fill_rect(out, item, 0, color);
24240     chart->slots[slot].index += 1;
24241     return ret;
24242 }
24243 NK_API nk_flags
24244 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
24245 {
24246     nk_flags flags;
24247     struct nk_window *win;
24248 
24249     NK_ASSERT(ctx);
24250     NK_ASSERT(ctx->current);
24251     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
24252     NK_ASSERT(slot < ctx->current->layout->chart.slot);
24253     if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
24254     if (slot >= ctx->current->layout->chart.slot) return nk_false;
24255 
24256     win = ctx->current;
24257     if (win->layout->chart.slot < slot) return nk_false;
24258     switch (win->layout->chart.slots[slot].type) {
24259     case NK_CHART_LINES:
24260         flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
24261     case NK_CHART_COLUMN:
24262         flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
24263     default:
24264     case NK_CHART_MAX:
24265         flags = 0;
24266     }
24267     return flags;
24268 }
24269 NK_API nk_flags
24270 nk_chart_push(struct nk_context *ctx, float value)
24271 {
24272     return nk_chart_push_slot(ctx, value, 0);
24273 }
24274 NK_API void
24275 nk_chart_end(struct nk_context *ctx)
24276 {
24277     struct nk_window *win;
24278     struct nk_chart *chart;
24279 
24280     NK_ASSERT(ctx);
24281     NK_ASSERT(ctx->current);
24282     if (!ctx || !ctx->current)
24283         return;
24284 
24285     win = ctx->current;
24286     chart = &win->layout->chart;
24287     NK_MEMSET(chart, 0, sizeof(*chart));
24288     return;
24289 }
24290 NK_API void
24291 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
24292     int count, int offset)
24293 {
24294     int i = 0;
24295     float min_value;
24296     float max_value;
24297 
24298     NK_ASSERT(ctx);
24299     NK_ASSERT(values);
24300     if (!ctx || !values || !count) return;
24301 
24302     min_value = values[offset];
24303     max_value = values[offset];
24304     for (i = 0; i < count; ++i) {
24305         min_value = NK_MIN(values[i + offset], min_value);
24306         max_value = NK_MAX(values[i + offset], max_value);
24307     }
24308 
24309     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
24310         for (i = 0; i < count; ++i)
24311             nk_chart_push(ctx, values[i + offset]);
24312         nk_chart_end(ctx);
24313     }
24314 }
24315 NK_API void
24316 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
24317     float(*value_getter)(void* user, int index), int count, int offset)
24318 {
24319     int i = 0;
24320     float min_value;
24321     float max_value;
24322 
24323     NK_ASSERT(ctx);
24324     NK_ASSERT(value_getter);
24325     if (!ctx || !value_getter || !count) return;
24326 
24327     max_value = min_value = value_getter(userdata, offset);
24328     for (i = 0; i < count; ++i) {
24329         float value = value_getter(userdata, i + offset);
24330         min_value = NK_MIN(value, min_value);
24331         max_value = NK_MAX(value, max_value);
24332     }
24333 
24334     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
24335         for (i = 0; i < count; ++i)
24336             nk_chart_push(ctx, value_getter(userdata, i + offset));
24337         nk_chart_end(ctx);
24338     }
24339 }
24340 
24341 
24342 
24343 
24344 
24345 /* ==============================================================
24346  *
24347  *                          COLOR PICKER
24348  *
24349  * ===============================================================*/
24350 NK_LIB int
24351 nk_color_picker_behavior(nk_flags *state,
24352     const struct nk_rect *bounds, const struct nk_rect *matrix,
24353     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
24354     struct nk_colorf *color, const struct nk_input *in)
24355 {
24356     float hsva[4];
24357     int value_changed = 0;
24358     int hsv_changed = 0;
24359 
24360     NK_ASSERT(state);
24361     NK_ASSERT(matrix);
24362     NK_ASSERT(hue_bar);
24363     NK_ASSERT(color);
24364 
24365     /* color matrix */
24366     nk_colorf_hsva_fv(hsva, *color);
24367     if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
24368         hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
24369         hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
24370         value_changed = hsv_changed = 1;
24371     }
24372     /* hue bar */
24373     if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
24374         hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
24375         value_changed = hsv_changed = 1;
24376     }
24377     /* alpha bar */
24378     if (alpha_bar) {
24379         if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
24380             hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
24381             value_changed = 1;
24382         }
24383     }
24384     nk_widget_state_reset(state);
24385     if (hsv_changed) {
24386         *color = nk_hsva_colorfv(hsva);
24387         *state = NK_WIDGET_STATE_ACTIVE;
24388     }
24389     if (value_changed) {
24390         color->a = hsva[3];
24391         *state = NK_WIDGET_STATE_ACTIVE;
24392     }
24393     /* set color picker widget state */
24394     if (nk_input_is_mouse_hovering_rect(in, *bounds))
24395         *state = NK_WIDGET_STATE_HOVERED;
24396     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
24397         *state |= NK_WIDGET_STATE_ENTERED;
24398     else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
24399         *state |= NK_WIDGET_STATE_LEFT;
24400     return value_changed;
24401 }
24402 NK_LIB void
24403 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
24404     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
24405     struct nk_colorf col)
24406 {
24407     NK_STORAGE const struct nk_color black = {0,0,0,255};
24408     NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
24409     NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
24410 
24411     const float crosshair_size = 7.0f;
24412     struct nk_color temp;
24413     float hsva[4];
24414     float line_y;
24415     int i;
24416 
24417     NK_ASSERT(o);
24418     NK_ASSERT(matrix);
24419     NK_ASSERT(hue_bar);
24420 
24421     /* draw hue bar */
24422     nk_colorf_hsva_fv(hsva, col);
24423     for (i = 0; i < 6; ++i) {
24424         NK_GLOBAL const struct nk_color hue_colors[] = {
24425             {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255},
24426             {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}
24427         };
24428         nk_fill_rect_multi_color(o,
24429             nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
24430                 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
24431                 hue_colors[i+1], hue_colors[i+1]);
24432     }
24433     line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
24434     nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
24435         line_y, 1, nk_rgb(255,255,255));
24436 
24437     /* draw alpha bar */
24438     if (alpha_bar) {
24439         float alpha = NK_SATURATE(col.a);
24440         line_y = (float)(int)(alpha_bar->y +  (1.0f - alpha) * matrix->h + 0.5f);
24441 
24442         nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
24443         nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
24444             line_y, 1, nk_rgb(255,255,255));
24445     }
24446 
24447     /* draw color matrix */
24448     temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
24449     nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
24450     nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
24451 
24452     /* draw cross-hair */
24453     {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
24454     p.x = (float)(int)(matrix->x + S * matrix->w);
24455     p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
24456     nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
24457     nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
24458     nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
24459     nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
24460 }
24461 NK_LIB int
24462 nk_do_color_picker(nk_flags *state,
24463     struct nk_command_buffer *out, struct nk_colorf *col,
24464     enum nk_color_format fmt, struct nk_rect bounds,
24465     struct nk_vec2 padding, const struct nk_input *in,
24466     const struct nk_user_font *font)
24467 {
24468     int ret = 0;
24469     struct nk_rect matrix;
24470     struct nk_rect hue_bar;
24471     struct nk_rect alpha_bar;
24472     float bar_w;
24473 
24474     NK_ASSERT(out);
24475     NK_ASSERT(col);
24476     NK_ASSERT(state);
24477     NK_ASSERT(font);
24478     if (!out || !col || !state || !font)
24479         return ret;
24480 
24481     bar_w = font->height;
24482     bounds.x += padding.x;
24483     bounds.y += padding.x;
24484     bounds.w -= 2 * padding.x;
24485     bounds.h -= 2 * padding.y;
24486 
24487     matrix.x = bounds.x;
24488     matrix.y = bounds.y;
24489     matrix.h = bounds.h;
24490     matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
24491 
24492     hue_bar.w = bar_w;
24493     hue_bar.y = bounds.y;
24494     hue_bar.h = matrix.h;
24495     hue_bar.x = matrix.x + matrix.w + padding.x;
24496 
24497     alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
24498     alpha_bar.y = bounds.y;
24499     alpha_bar.w = bar_w;
24500     alpha_bar.h = matrix.h;
24501 
24502     ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
24503         (fmt == NK_RGBA) ? &alpha_bar:0, col, in);
24504     nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col);
24505     return ret;
24506 }
24507 NK_API int
24508 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color,
24509     enum nk_color_format fmt)
24510 {
24511     struct nk_window *win;
24512     struct nk_panel *layout;
24513     const struct nk_style *config;
24514     const struct nk_input *in;
24515 
24516     enum nk_widget_layout_states state;
24517     struct nk_rect bounds;
24518 
24519     NK_ASSERT(ctx);
24520     NK_ASSERT(color);
24521     NK_ASSERT(ctx->current);
24522     NK_ASSERT(ctx->current->layout);
24523     if (!ctx || !ctx->current || !ctx->current->layout || !color)
24524         return 0;
24525 
24526     win = ctx->current;
24527     config = &ctx->style;
24528     layout = win->layout;
24529     state = nk_widget(&bounds, ctx);
24530     if (!state) return 0;
24531     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
24532     return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
24533                 nk_vec2(0,0), in, config->font);
24534 }
24535 NK_API struct nk_colorf
24536 nk_color_picker(struct nk_context *ctx, struct nk_colorf color,
24537     enum nk_color_format fmt)
24538 {
24539     nk_color_pick(ctx, &color, fmt);
24540     return color;
24541 }
24542 
24543 
24544 
24545 
24546 
24547 /* ==============================================================
24548  *
24549  *                          COMBO
24550  *
24551  * ===============================================================*/
24552 NK_INTERN int
24553 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
24554     struct nk_vec2 size, int is_clicked, struct nk_rect header)
24555 {
24556     struct nk_window *popup;
24557     int is_open = 0;
24558     int is_active = 0;
24559     struct nk_rect body;
24560     nk_hash hash;
24561 
24562     NK_ASSERT(ctx);
24563     NK_ASSERT(ctx->current);
24564     NK_ASSERT(ctx->current->layout);
24565     if (!ctx || !ctx->current || !ctx->current->layout)
24566         return 0;
24567 
24568     popup = win->popup.win;
24569     body.x = header.x;
24570     body.w = size.x;
24571     body.y = header.y + header.h-ctx->style.window.combo_border;
24572     body.h = size.y;
24573 
24574     hash = win->popup.combo_count++;
24575     is_open = (popup) ? nk_true:nk_false;
24576     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
24577     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
24578         (!is_open && !is_active && !is_clicked)) return 0;
24579     if (!nk_nonblock_begin(ctx, 0, body,
24580         (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
24581 
24582     win->popup.type = NK_PANEL_COMBO;
24583     win->popup.name = hash;
24584     return 1;
24585 }
24586 NK_API int
24587 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
24588     struct nk_vec2 size)
24589 {
24590     const struct nk_input *in;
24591     struct nk_window *win;
24592     struct nk_style *style;
24593 
24594     enum nk_widget_layout_states s;
24595     int is_clicked = nk_false;
24596     struct nk_rect header;
24597     const struct nk_style_item *background;
24598     struct nk_text text;
24599 
24600     NK_ASSERT(ctx);
24601     NK_ASSERT(selected);
24602     NK_ASSERT(ctx->current);
24603     NK_ASSERT(ctx->current->layout);
24604     if (!ctx || !ctx->current || !ctx->current->layout || !selected)
24605         return 0;
24606 
24607     win = ctx->current;
24608     style = &ctx->style;
24609     s = nk_widget(&header, ctx);
24610     if (s == NK_WIDGET_INVALID)
24611         return 0;
24612 
24613     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24614     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24615         is_clicked = nk_true;
24616 
24617     /* draw combo box header background and border */
24618     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
24619         background = &style->combo.active;
24620         text.text = style->combo.label_active;
24621     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24622         background = &style->combo.hover;
24623         text.text = style->combo.label_hover;
24624     } else {
24625         background = &style->combo.normal;
24626         text.text = style->combo.label_normal;
24627     }
24628     if (background->type == NK_STYLE_ITEM_IMAGE) {
24629         text.background = nk_rgba(0,0,0,0);
24630         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24631     } else {
24632         text.background = background->data.color;
24633         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24634         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24635     }
24636     {
24637         /* print currently selected text item */
24638         struct nk_rect label;
24639         struct nk_rect button;
24640         struct nk_rect content;
24641 
24642         enum nk_symbol_type sym;
24643         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24644             sym = style->combo.sym_hover;
24645         else if (is_clicked)
24646             sym = style->combo.sym_active;
24647         else sym = style->combo.sym_normal;
24648 
24649         /* calculate button */
24650         button.w = header.h - 2 * style->combo.button_padding.y;
24651         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24652         button.y = header.y + style->combo.button_padding.y;
24653         button.h = button.w;
24654 
24655         content.x = button.x + style->combo.button.padding.x;
24656         content.y = button.y + style->combo.button.padding.y;
24657         content.w = button.w - 2 * style->combo.button.padding.x;
24658         content.h = button.h - 2 * style->combo.button.padding.y;
24659 
24660         /* draw selected label */
24661         text.padding = nk_vec2(0,0);
24662         label.x = header.x + style->combo.content_padding.x;
24663         label.y = header.y + style->combo.content_padding.y;
24664         label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
24665         label.h = header.h - 2 * style->combo.content_padding.y;
24666         nk_widget_text(&win->buffer, label, selected, len, &text,
24667             NK_TEXT_LEFT, ctx->style.font);
24668 
24669         /* draw open/close button */
24670         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24671             &ctx->style.combo.button, sym, style->font);
24672     }
24673     return nk_combo_begin(ctx, win, size, is_clicked, header);
24674 }
24675 NK_API int
24676 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
24677 {
24678     return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);
24679 }
24680 NK_API int
24681 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
24682 {
24683     struct nk_window *win;
24684     struct nk_style *style;
24685     const struct nk_input *in;
24686 
24687     struct nk_rect header;
24688     int is_clicked = nk_false;
24689     enum nk_widget_layout_states s;
24690     const struct nk_style_item *background;
24691 
24692     NK_ASSERT(ctx);
24693     NK_ASSERT(ctx->current);
24694     NK_ASSERT(ctx->current->layout);
24695     if (!ctx || !ctx->current || !ctx->current->layout)
24696         return 0;
24697 
24698     win = ctx->current;
24699     style = &ctx->style;
24700     s = nk_widget(&header, ctx);
24701     if (s == NK_WIDGET_INVALID)
24702         return 0;
24703 
24704     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24705     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24706         is_clicked = nk_true;
24707 
24708     /* draw combo box header background and border */
24709     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
24710         background = &style->combo.active;
24711     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24712         background = &style->combo.hover;
24713     else background = &style->combo.normal;
24714 
24715     if (background->type == NK_STYLE_ITEM_IMAGE) {
24716         nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
24717     } else {
24718         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24719         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24720     }
24721     {
24722         struct nk_rect content;
24723         struct nk_rect button;
24724         struct nk_rect bounds;
24725 
24726         enum nk_symbol_type sym;
24727         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24728             sym = style->combo.sym_hover;
24729         else if (is_clicked)
24730             sym = style->combo.sym_active;
24731         else sym = style->combo.sym_normal;
24732 
24733         /* calculate button */
24734         button.w = header.h - 2 * style->combo.button_padding.y;
24735         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24736         button.y = header.y + style->combo.button_padding.y;
24737         button.h = button.w;
24738 
24739         content.x = button.x + style->combo.button.padding.x;
24740         content.y = button.y + style->combo.button.padding.y;
24741         content.w = button.w - 2 * style->combo.button.padding.x;
24742         content.h = button.h - 2 * style->combo.button.padding.y;
24743 
24744         /* draw color */
24745         bounds.h = header.h - 4 * style->combo.content_padding.y;
24746         bounds.y = header.y + 2 * style->combo.content_padding.y;
24747         bounds.x = header.x + 2 * style->combo.content_padding.x;
24748         bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
24749         nk_fill_rect(&win->buffer, bounds, 0, color);
24750 
24751         /* draw open/close button */
24752         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24753             &ctx->style.combo.button, sym, style->font);
24754     }
24755     return nk_combo_begin(ctx, win, size, is_clicked, header);
24756 }
24757 NK_API int
24758 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
24759 {
24760     struct nk_window *win;
24761     struct nk_style *style;
24762     const struct nk_input *in;
24763 
24764     struct nk_rect header;
24765     int is_clicked = nk_false;
24766     enum nk_widget_layout_states s;
24767     const struct nk_style_item *background;
24768     struct nk_color sym_background;
24769     struct nk_color symbol_color;
24770 
24771     NK_ASSERT(ctx);
24772     NK_ASSERT(ctx->current);
24773     NK_ASSERT(ctx->current->layout);
24774     if (!ctx || !ctx->current || !ctx->current->layout)
24775         return 0;
24776 
24777     win = ctx->current;
24778     style = &ctx->style;
24779     s = nk_widget(&header, ctx);
24780     if (s == NK_WIDGET_INVALID)
24781         return 0;
24782 
24783     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24784     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24785         is_clicked = nk_true;
24786 
24787     /* draw combo box header background and border */
24788     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
24789         background = &style->combo.active;
24790         symbol_color = style->combo.symbol_active;
24791     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24792         background = &style->combo.hover;
24793         symbol_color = style->combo.symbol_hover;
24794     } else {
24795         background = &style->combo.normal;
24796         symbol_color = style->combo.symbol_hover;
24797     }
24798 
24799     if (background->type == NK_STYLE_ITEM_IMAGE) {
24800         sym_background = nk_rgba(0,0,0,0);
24801         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24802     } else {
24803         sym_background = background->data.color;
24804         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24805         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24806     }
24807     {
24808         struct nk_rect bounds = {0,0,0,0};
24809         struct nk_rect content;
24810         struct nk_rect button;
24811 
24812         enum nk_symbol_type sym;
24813         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24814             sym = style->combo.sym_hover;
24815         else if (is_clicked)
24816             sym = style->combo.sym_active;
24817         else sym = style->combo.sym_normal;
24818 
24819         /* calculate button */
24820         button.w = header.h - 2 * style->combo.button_padding.y;
24821         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
24822         button.y = header.y + style->combo.button_padding.y;
24823         button.h = button.w;
24824 
24825         content.x = button.x + style->combo.button.padding.x;
24826         content.y = button.y + style->combo.button.padding.y;
24827         content.w = button.w - 2 * style->combo.button.padding.x;
24828         content.h = button.h - 2 * style->combo.button.padding.y;
24829 
24830         /* draw symbol */
24831         bounds.h = header.h - 2 * style->combo.content_padding.y;
24832         bounds.y = header.y + style->combo.content_padding.y;
24833         bounds.x = header.x + style->combo.content_padding.x;
24834         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
24835         nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
24836             1.0f, style->font);
24837 
24838         /* draw open/close button */
24839         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
24840             &ctx->style.combo.button, sym, style->font);
24841     }
24842     return nk_combo_begin(ctx, win, size, is_clicked, header);
24843 }
24844 NK_API int
24845 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
24846     enum nk_symbol_type symbol, struct nk_vec2 size)
24847 {
24848     struct nk_window *win;
24849     struct nk_style *style;
24850     struct nk_input *in;
24851 
24852     struct nk_rect header;
24853     int is_clicked = nk_false;
24854     enum nk_widget_layout_states s;
24855     const struct nk_style_item *background;
24856     struct nk_color symbol_color;
24857     struct nk_text text;
24858 
24859     NK_ASSERT(ctx);
24860     NK_ASSERT(ctx->current);
24861     NK_ASSERT(ctx->current->layout);
24862     if (!ctx || !ctx->current || !ctx->current->layout)
24863         return 0;
24864 
24865     win = ctx->current;
24866     style = &ctx->style;
24867     s = nk_widget(&header, ctx);
24868     if (!s) return 0;
24869 
24870     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24871     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24872         is_clicked = nk_true;
24873 
24874     /* draw combo box header background and border */
24875     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
24876         background = &style->combo.active;
24877         symbol_color = style->combo.symbol_active;
24878         text.text = style->combo.label_active;
24879     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
24880         background = &style->combo.hover;
24881         symbol_color = style->combo.symbol_hover;
24882         text.text = style->combo.label_hover;
24883     } else {
24884         background = &style->combo.normal;
24885         symbol_color = style->combo.symbol_normal;
24886         text.text = style->combo.label_normal;
24887     }
24888     if (background->type == NK_STYLE_ITEM_IMAGE) {
24889         text.background = nk_rgba(0,0,0,0);
24890         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24891     } else {
24892         text.background = background->data.color;
24893         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24894         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24895     }
24896     {
24897         struct nk_rect content;
24898         struct nk_rect button;
24899         struct nk_rect label;
24900         struct nk_rect image;
24901 
24902         enum nk_symbol_type sym;
24903         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24904             sym = style->combo.sym_hover;
24905         else if (is_clicked)
24906             sym = style->combo.sym_active;
24907         else sym = style->combo.sym_normal;
24908 
24909         /* calculate button */
24910         button.w = header.h - 2 * style->combo.button_padding.y;
24911         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
24912         button.y = header.y + style->combo.button_padding.y;
24913         button.h = button.w;
24914 
24915         content.x = button.x + style->combo.button.padding.x;
24916         content.y = button.y + style->combo.button.padding.y;
24917         content.w = button.w - 2 * style->combo.button.padding.x;
24918         content.h = button.h - 2 * style->combo.button.padding.y;
24919         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
24920             &ctx->style.combo.button, sym, style->font);
24921 
24922         /* draw symbol */
24923         image.x = header.x + style->combo.content_padding.x;
24924         image.y = header.y + style->combo.content_padding.y;
24925         image.h = header.h - 2 * style->combo.content_padding.y;
24926         image.w = image.h;
24927         nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
24928             1.0f, style->font);
24929 
24930         /* draw label */
24931         text.padding = nk_vec2(0,0);
24932         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
24933         label.y = header.y + style->combo.content_padding.y;
24934         label.w = (button.x - style->combo.content_padding.x) - label.x;
24935         label.h = header.h - 2 * style->combo.content_padding.y;
24936         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
24937     }
24938     return nk_combo_begin(ctx, win, size, is_clicked, header);
24939 }
24940 NK_API int
24941 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
24942 {
24943     struct nk_window *win;
24944     struct nk_style *style;
24945     const struct nk_input *in;
24946 
24947     struct nk_rect header;
24948     int is_clicked = nk_false;
24949     enum nk_widget_layout_states s;
24950     const struct nk_style_item *background;
24951 
24952     NK_ASSERT(ctx);
24953     NK_ASSERT(ctx->current);
24954     NK_ASSERT(ctx->current->layout);
24955     if (!ctx || !ctx->current || !ctx->current->layout)
24956         return 0;
24957 
24958     win = ctx->current;
24959     style = &ctx->style;
24960     s = nk_widget(&header, ctx);
24961     if (s == NK_WIDGET_INVALID)
24962         return 0;
24963 
24964     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
24965     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
24966         is_clicked = nk_true;
24967 
24968     /* draw combo box header background and border */
24969     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
24970         background = &style->combo.active;
24971     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24972         background = &style->combo.hover;
24973     else background = &style->combo.normal;
24974 
24975     if (background->type == NK_STYLE_ITEM_IMAGE) {
24976         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
24977     } else {
24978         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
24979         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
24980     }
24981     {
24982         struct nk_rect bounds = {0,0,0,0};
24983         struct nk_rect content;
24984         struct nk_rect button;
24985 
24986         enum nk_symbol_type sym;
24987         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
24988             sym = style->combo.sym_hover;
24989         else if (is_clicked)
24990             sym = style->combo.sym_active;
24991         else sym = style->combo.sym_normal;
24992 
24993         /* calculate button */
24994         button.w = header.h - 2 * style->combo.button_padding.y;
24995         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
24996         button.y = header.y + style->combo.button_padding.y;
24997         button.h = button.w;
24998 
24999         content.x = button.x + style->combo.button.padding.x;
25000         content.y = button.y + style->combo.button.padding.y;
25001         content.w = button.w - 2 * style->combo.button.padding.x;
25002         content.h = button.h - 2 * style->combo.button.padding.y;
25003 
25004         /* draw image */
25005         bounds.h = header.h - 2 * style->combo.content_padding.y;
25006         bounds.y = header.y + style->combo.content_padding.y;
25007         bounds.x = header.x + style->combo.content_padding.x;
25008         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
25009         nk_draw_image(&win->buffer, bounds, &img, nk_white);
25010 
25011         /* draw open/close button */
25012         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
25013             &ctx->style.combo.button, sym, style->font);
25014     }
25015     return nk_combo_begin(ctx, win, size, is_clicked, header);
25016 }
25017 NK_API int
25018 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
25019     struct nk_image img, struct nk_vec2 size)
25020 {
25021     struct nk_window *win;
25022     struct nk_style *style;
25023     struct nk_input *in;
25024 
25025     struct nk_rect header;
25026     int is_clicked = nk_false;
25027     enum nk_widget_layout_states s;
25028     const struct nk_style_item *background;
25029     struct nk_text text;
25030 
25031     NK_ASSERT(ctx);
25032     NK_ASSERT(ctx->current);
25033     NK_ASSERT(ctx->current->layout);
25034     if (!ctx || !ctx->current || !ctx->current->layout)
25035         return 0;
25036 
25037     win = ctx->current;
25038     style = &ctx->style;
25039     s = nk_widget(&header, ctx);
25040     if (!s) return 0;
25041 
25042     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
25043     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
25044         is_clicked = nk_true;
25045 
25046     /* draw combo box header background and border */
25047     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
25048         background = &style->combo.active;
25049         text.text = style->combo.label_active;
25050     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
25051         background = &style->combo.hover;
25052         text.text = style->combo.label_hover;
25053     } else {
25054         background = &style->combo.normal;
25055         text.text = style->combo.label_normal;
25056     }
25057     if (background->type == NK_STYLE_ITEM_IMAGE) {
25058         text.background = nk_rgba(0,0,0,0);
25059         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
25060     } else {
25061         text.background = background->data.color;
25062         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
25063         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
25064     }
25065     {
25066         struct nk_rect content;
25067         struct nk_rect button;
25068         struct nk_rect label;
25069         struct nk_rect image;
25070 
25071         enum nk_symbol_type sym;
25072         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
25073             sym = style->combo.sym_hover;
25074         else if (is_clicked)
25075             sym = style->combo.sym_active;
25076         else sym = style->combo.sym_normal;
25077 
25078         /* calculate button */
25079         button.w = header.h - 2 * style->combo.button_padding.y;
25080         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
25081         button.y = header.y + style->combo.button_padding.y;
25082         button.h = button.w;
25083 
25084         content.x = button.x + style->combo.button.padding.x;
25085         content.y = button.y + style->combo.button.padding.y;
25086         content.w = button.w - 2 * style->combo.button.padding.x;
25087         content.h = button.h - 2 * style->combo.button.padding.y;
25088         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
25089             &ctx->style.combo.button, sym, style->font);
25090 
25091         /* draw image */
25092         image.x = header.x + style->combo.content_padding.x;
25093         image.y = header.y + style->combo.content_padding.y;
25094         image.h = header.h - 2 * style->combo.content_padding.y;
25095         image.w = image.h;
25096         nk_draw_image(&win->buffer, image, &img, nk_white);
25097 
25098         /* draw label */
25099         text.padding = nk_vec2(0,0);
25100         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
25101         label.y = header.y + style->combo.content_padding.y;
25102         label.w = (button.x - style->combo.content_padding.x) - label.x;
25103         label.h = header.h - 2 * style->combo.content_padding.y;
25104         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
25105     }
25106     return nk_combo_begin(ctx, win, size, is_clicked, header);
25107 }
25108 NK_API int
25109 nk_combo_begin_symbol_label(struct nk_context *ctx,
25110     const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
25111 {
25112     return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);
25113 }
25114 NK_API int
25115 nk_combo_begin_image_label(struct nk_context *ctx,
25116     const char *selected, struct nk_image img, struct nk_vec2 size)
25117 {
25118     return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);
25119 }
25120 NK_API int
25121 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
25122 {
25123     return nk_contextual_item_text(ctx, text, len, align);
25124 }
25125 NK_API int
25126 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
25127 {
25128     return nk_contextual_item_label(ctx, label, align);
25129 }
25130 NK_API int
25131 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
25132     int len, nk_flags alignment)
25133 {
25134     return nk_contextual_item_image_text(ctx, img, text, len, alignment);
25135 }
25136 NK_API int
25137 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
25138     const char *text, nk_flags alignment)
25139 {
25140     return nk_contextual_item_image_label(ctx, img, text, alignment);
25141 }
25142 NK_API int
25143 nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
25144     const char *text, int len, nk_flags alignment)
25145 {
25146     return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);
25147 }
25148 NK_API int
25149 nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
25150     const char *label, nk_flags alignment)
25151 {
25152     return nk_contextual_item_symbol_label(ctx, sym, label, alignment);
25153 }
25154 NK_API void nk_combo_end(struct nk_context *ctx)
25155 {
25156     nk_contextual_end(ctx);
25157 }
25158 NK_API void nk_combo_close(struct nk_context *ctx)
25159 {
25160     nk_contextual_close(ctx);
25161 }
25162 NK_API int
25163 nk_combo(struct nk_context *ctx, const char **items, int count,
25164     int selected, int item_height, struct nk_vec2 size)
25165 {
25166     int i = 0;
25167     int max_height;
25168     struct nk_vec2 item_spacing;
25169     struct nk_vec2 window_padding;
25170 
25171     NK_ASSERT(ctx);
25172     NK_ASSERT(items);
25173     NK_ASSERT(ctx->current);
25174     if (!ctx || !items ||!count)
25175         return selected;
25176 
25177     item_spacing = ctx->style.window.spacing;
25178     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
25179     max_height = count * item_height + count * (int)item_spacing.y;
25180     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
25181     size.y = NK_MIN(size.y, (float)max_height);
25182     if (nk_combo_begin_label(ctx, items[selected], size)) {
25183         nk_layout_row_dynamic(ctx, (float)item_height, 1);
25184         for (i = 0; i < count; ++i) {
25185             if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
25186                 selected = i;
25187         }
25188         nk_combo_end(ctx);
25189     }
25190     return selected;
25191 }
25192 NK_API int
25193 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
25194     int separator, int selected, int count, int item_height, struct nk_vec2 size)
25195 {
25196     int i;
25197     int max_height;
25198     struct nk_vec2 item_spacing;
25199     struct nk_vec2 window_padding;
25200     const char *current_item;
25201     const char *iter;
25202     int length = 0;
25203 
25204     NK_ASSERT(ctx);
25205     NK_ASSERT(items_separated_by_separator);
25206     if (!ctx || !items_separated_by_separator)
25207         return selected;
25208 
25209     /* calculate popup window */
25210     item_spacing = ctx->style.window.spacing;
25211     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
25212     max_height = count * item_height + count * (int)item_spacing.y;
25213     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
25214     size.y = NK_MIN(size.y, (float)max_height);
25215 
25216     /* find selected item */
25217     current_item = items_separated_by_separator;
25218     for (i = 0; i < count; ++i) {
25219         iter = current_item;
25220         while (*iter && *iter != separator) iter++;
25221         length = (int)(iter - current_item);
25222         if (i == selected) break;
25223         current_item = iter + 1;
25224     }
25225 
25226     if (nk_combo_begin_text(ctx, current_item, length, size)) {
25227         current_item = items_separated_by_separator;
25228         nk_layout_row_dynamic(ctx, (float)item_height, 1);
25229         for (i = 0; i < count; ++i) {
25230             iter = current_item;
25231             while (*iter && *iter != separator) iter++;
25232             length = (int)(iter - current_item);
25233             if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
25234                 selected = i;
25235             current_item = current_item + length + 1;
25236         }
25237         nk_combo_end(ctx);
25238     }
25239     return selected;
25240 }
25241 NK_API int
25242 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
25243     int selected, int count, int item_height, struct nk_vec2 size)
25244 {
25245     return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);
25246 }
25247 NK_API int
25248 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
25249     void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
25250 {
25251     int i;
25252     int max_height;
25253     struct nk_vec2 item_spacing;
25254     struct nk_vec2 window_padding;
25255     const char *item;
25256 
25257     NK_ASSERT(ctx);
25258     NK_ASSERT(item_getter);
25259     if (!ctx || !item_getter)
25260         return selected;
25261 
25262     /* calculate popup window */
25263     item_spacing = ctx->style.window.spacing;
25264     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
25265     max_height = count * item_height + count * (int)item_spacing.y;
25266     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
25267     size.y = NK_MIN(size.y, (float)max_height);
25268 
25269     item_getter(userdata, selected, &item);
25270     if (nk_combo_begin_label(ctx, item, size)) {
25271         nk_layout_row_dynamic(ctx, (float)item_height, 1);
25272         for (i = 0; i < count; ++i) {
25273             item_getter(userdata, i, &item);
25274             if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
25275                 selected = i;
25276         }
25277         nk_combo_end(ctx);
25278     } return selected;
25279 }
25280 NK_API void
25281 nk_combobox(struct nk_context *ctx, const char **items, int count,
25282     int *selected, int item_height, struct nk_vec2 size)
25283 {
25284     *selected = nk_combo(ctx, items, count, *selected, item_height, size);
25285 }
25286 NK_API void
25287 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
25288     int *selected, int count, int item_height, struct nk_vec2 size)
25289 {
25290     *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);
25291 }
25292 NK_API void
25293 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
25294     int separator,int *selected, int count, int item_height, struct nk_vec2 size)
25295 {
25296     *selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
25297                                     *selected, count, item_height, size);
25298 }
25299 NK_API void
25300 nk_combobox_callback(struct nk_context *ctx,
25301     void(*item_getter)(void* data, int id, const char **out_text),
25302     void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
25303 {
25304     *selected = nk_combo_callback(ctx, item_getter, userdata,  *selected, count, item_height, size);
25305 }
25306 
25307 
25308 
25309 
25310 
25311 /* ===============================================================
25312  *
25313  *                              TOOLTIP
25314  *
25315  * ===============================================================*/
25316 NK_API int
25317 nk_tooltip_begin(struct nk_context *ctx, float width)
25318 {
25319     int x,y,w,h;
25320     struct nk_window *win;
25321     const struct nk_input *in;
25322     struct nk_rect bounds;
25323     int ret;
25324 
25325     NK_ASSERT(ctx);
25326     NK_ASSERT(ctx->current);
25327     NK_ASSERT(ctx->current->layout);
25328     if (!ctx || !ctx->current || !ctx->current->layout)
25329         return 0;
25330 
25331     /* make sure that no nonblocking popup is currently active */
25332     win = ctx->current;
25333     in = &ctx->input;
25334     if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
25335         return 0;
25336 
25337     w = nk_iceilf(width);
25338     h = nk_iceilf(nk_null_rect.h);
25339     x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x;
25340     y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y;
25341 
25342     bounds.x = (float)x;
25343     bounds.y = (float)y;
25344     bounds.w = (float)w;
25345     bounds.h = (float)h;
25346 
25347     ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
25348         "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
25349     if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
25350     win->popup.type = NK_PANEL_TOOLTIP;
25351     ctx->current->layout->type = NK_PANEL_TOOLTIP;
25352     return ret;
25353 }
25354 
25355 NK_API void
25356 nk_tooltip_end(struct nk_context *ctx)
25357 {
25358     NK_ASSERT(ctx);
25359     NK_ASSERT(ctx->current);
25360     if (!ctx || !ctx->current) return;
25361     ctx->current->seq--;
25362     nk_popup_close(ctx);
25363     nk_popup_end(ctx);
25364 }
25365 NK_API void
25366 nk_tooltip(struct nk_context *ctx, const char *text)
25367 {
25368     const struct nk_style *style;
25369     struct nk_vec2 padding;
25370 
25371     int text_len;
25372     float text_width;
25373     float text_height;
25374 
25375     NK_ASSERT(ctx);
25376     NK_ASSERT(ctx->current);
25377     NK_ASSERT(ctx->current->layout);
25378     NK_ASSERT(text);
25379     if (!ctx || !ctx->current || !ctx->current->layout || !text)
25380         return;
25381 
25382     /* fetch configuration data */
25383     style = &ctx->style;
25384     padding = style->window.padding;
25385 
25386     /* calculate size of the text and tooltip */
25387     text_len = nk_strlen(text);
25388     text_width = style->font->width(style->font->userdata,
25389                     style->font->height, text, text_len);
25390     text_width += (4 * padding.x);
25391     text_height = (style->font->height + 2 * padding.y);
25392 
25393     /* execute tooltip and fill with text */
25394     if (nk_tooltip_begin(ctx, (float)text_width)) {
25395         nk_layout_row_dynamic(ctx, (float)text_height, 1);
25396         nk_text(ctx, text, text_len, NK_TEXT_LEFT);
25397         nk_tooltip_end(ctx);
25398     }
25399 }
25400 #ifdef NK_INCLUDE_STANDARD_VARARGS
25401 NK_API void
25402 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...)
25403 {
25404     va_list args;
25405     va_start(args, fmt);
25406     nk_tooltipfv(ctx, fmt, args);
25407     va_end(args);
25408 }
25409 NK_API void
25410 nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
25411 {
25412     char buf[256];
25413     nk_strfmt(buf, NK_LEN(buf), fmt, args);
25414     nk_tooltip(ctx, buf);
25415 }
25416 #endif
25417 
25418 
25419 
25420 #endif /* NK_IMPLEMENTATION */
25421 
25422 /*
25423 /// ## License
25424 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
25425 ///    ------------------------------------------------------------------------------
25426 ///    This software is available under 2 licenses -- choose whichever you prefer.
25427 ///    ------------------------------------------------------------------------------
25428 ///    ALTERNATIVE A - MIT License
25429 ///    Copyright (c) 2016-2018 Micha Mettke
25430 ///    Permission is hereby granted, free of charge, to any person obtaining a copy of
25431 ///    this software and associated documentation files (the "Software"), to deal in
25432 ///    the Software without restriction, including without limitation the rights to
25433 ///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
25434 ///    of the Software, and to permit persons to whom the Software is furnished to do
25435 ///    so, subject to the following conditions:
25436 ///    The above copyright notice and this permission notice shall be included in all
25437 ///    copies or substantial portions of the Software.
25438 ///    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25439 ///    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25440 ///    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25441 ///    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25442 ///    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25443 ///    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25444 ///    SOFTWARE.
25445 ///    ------------------------------------------------------------------------------
25446 ///    ALTERNATIVE B - Public Domain (www.unlicense.org)
25447 ///    This is free and unencumbered software released into the public domain.
25448 ///    Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
25449 ///    software, either in source code form or as a compiled binary, for any purpose,
25450 ///    commercial or non-commercial, and by any means.
25451 ///    In jurisdictions that recognize copyright laws, the author or authors of this
25452 ///    software dedicate any and all copyright interest in the software to the public
25453 ///    domain. We make this dedication for the benefit of the public at large and to
25454 ///    the detriment of our heirs and successors. We intend this dedication to be an
25455 ///    overt act of relinquishment in perpetuity of all present and future rights to
25456 ///    this software under copyright law.
25457 ///    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25458 ///    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25459 ///    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25460 ///    AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25461 ///    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25462 ///    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25463 ///    ------------------------------------------------------------------------------
25464 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25465 
25466 /// ## Changelog
25467 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
25468 /// [date][x.yy.zz]-[description]
25469 /// -[date]: date on which the change has been pushed
25470 /// -[x.yy.zz]: Numerical version string representation. Each version number on the right
25471 ///             resets back to zero if version on the left is incremented.
25472 ///    - [x]: Major version with API and library breaking changes
25473 ///    - [yy]: Minor version with non-breaking API and library changes
25474 ///    - [zz]: Bug fix version with no direct changes to API
25475 ///
25476 /// - 2019/09/20 (4.01.3) - Fixed a bug wherein combobox cannot be closed by clicking the header
25477 ///                        when NK_BUTTON_TRIGGER_ON_RELEASE is defined.
25478 /// - 2019/09/10 (4.01.2) - Fixed the nk_cos function, which deviated significantly.
25479 /// - 2019/09/08 (4.01.1) - Fixed a bug wherein re-baking of fonts caused a segmentation
25480 ///                        fault due to dst_font->glyph_count not being zeroed on subsequent
25481 ///                        bakes of the same set of fonts.
25482 /// - 2019/06/23 (4.01.0) - Added nk_***_get_scroll and nk_***_set_scroll for groups, windows, and popups.
25483 /// - 2019/06/12 (4.00.3) - Fix panel background drawing bug.
25484 /// - 2018/10/31 (4.00.2) - Added NK_KEYSTATE_BASED_INPUT to "fix" state based backends
25485 ///                        like GLFW without breaking key repeat behavior on event based.
25486 /// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame.
25487 /// - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to
25488 ///                        clear provided buffers. So make sure to either free
25489 ///                        or clear each passed buffer after calling nk_convert.
25490 /// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior.
25491 /// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process.
25492 /// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype.
25493 /// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug.
25494 /// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separed group identifier and title.
25495 /// - 2018/01/07 (3.00.1) - Started to change documentation style.
25496 /// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken
25497 ///                        because of conversions between float and byte color representation.
25498 ///                        Color pickers now use floating point values to represent
25499 ///                        HSV values. To get back the old behavior I added some additional
25500 ///                        color conversion functions to cast between nk_color and
25501 ///                        nk_colorf.
25502 /// - 2017/12/23 (2.00.7) - Fixed small warning.
25503 /// - 2017/12/23 (2.00.7) - Fixed `nk_edit_buffer` behavior if activated to allow input.
25504 /// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior.
25505 /// - 2017/12/04 (2.00.6) - Added formated string tooltip widget.
25506 /// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag `NK_WINDOW_NO_INPUT`.
25507 /// - 2017/11/15 (2.00.4) - Fixed font merging.
25508 /// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions.
25509 /// - 2017/09/14 (2.00.2) - Fixed `nk_edit_buffer` and `nk_edit_focus` behavior.
25510 /// - 2017/09/14 (2.00.1) - Fixed window closing behavior.
25511 /// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifing window position and size funtions now
25512 ///                        require the name of the window and must happen outside the window
25513 ///                        building process (between function call nk_begin and nk_end).
25514 /// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last.
25515 /// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows.
25516 /// - 2017/08/27 (1.40.7) - Fixed window background flag.
25517 /// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked
25518 ///                        query for widgets.
25519 /// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked
25520 ///                        and filled rectangles.
25521 /// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in
25522 ///                        process of being destroyed.
25523 /// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in
25524 ///                        window instead of directly in table.
25525 /// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro.
25526 /// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero.
25527 /// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only
25528 ///                        comes in effect if you pass in zero was row height argument.
25529 /// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change
25530 ///                        how layouting works. From now there will be an internal minimum
25531 ///                        row height derived from font height. If you need a row smaller than
25532 ///                        that you can directly set it by `nk_layout_set_min_row_height` and
25533 ///                        reset the value back by calling `nk_layout_reset_min_row_height.
25534 /// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix.
25535 /// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a `nk_layout_xxx` function.
25536 /// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer.
25537 /// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped.
25538 /// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundries.
25539 /// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space.
25540 /// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size.
25541 /// - 2017/05/06 (1.38.0) - Added platform double-click support.
25542 /// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends.
25543 /// - 2017/04/20 (1.37.0) - Extended properties with selection and clipboard support.
25544 /// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing.
25545 /// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error.
25546 /// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags.
25547 /// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption.
25548 /// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows.
25549 /// - 2017/03/25 (1.35.1) - Fixed windows closing behavior.
25550 /// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377.
25551 /// - 2017/03/18 (1.34.3) - Fixed long window header titles.
25552 /// - 2017/03/04 (1.34.2) - Fixed text edit filtering.
25553 /// - 2017/03/04 (1.34.1) - Fixed group closable flag.
25554 /// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support.
25555 /// - 2017/01/24 (1.33.0) - Added programatic way of remove edit focus.
25556 /// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows.
25557 /// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows.
25558 /// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing.
25559 /// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner.
25560 /// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both
25561 ///                        dynamic and static widgets.
25562 /// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit.
25563 /// - 2016/12/31 (1.29.2) - Fixed closing window bug of minimized windows.
25564 /// - 2016/12/03 (1.29.1) - Fixed wrapped text with no seperator and C89 error.
25565 /// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters.
25566 /// - 2016/11/22 (1.28.6) - Fixed window minimized closing bug.
25567 /// - 2016/11/19 (1.28.5) - Fixed abstract combo box closing behavior.
25568 /// - 2016/11/19 (1.28.4) - Fixed tooltip flickering.
25569 /// - 2016/11/19 (1.28.3) - Fixed memory leak caused by popup repeated closing.
25570 /// - 2016/11/18 (1.28.2) - Fixed memory leak caused by popup panel allocation.
25571 /// - 2016/11/10 (1.28.1) - Fixed some warnings and C++ error.
25572 /// - 2016/11/10 (1.28.0) - Added additional `nk_button` versions which allows to directly
25573 ///                        pass in a style struct to change buttons visual.
25574 /// - 2016/11/10 (1.27.0) - Added additional `nk_tree` versions to support external state
25575 ///                        storage. Just like last the `nk_group` commit the main
25576 ///                        advantage is that you optionally can minimize nuklears runtime
25577 ///                        memory consumption or handle hash collisions.
25578 /// - 2016/11/09 (1.26.0) - Added additional `nk_group` version to support external scrollbar
25579 ///                        offset storage. Main advantage is that you can externalize
25580 ///                        the memory management for the offset. It could also be helpful
25581 ///                        if you have a hash collision in `nk_group_begin` but really
25582 ///                        want the name. In addition I added `nk_list_view` which allows
25583 ///                        to draw big lists inside a group without actually having to
25584 ///                        commit the whole list to nuklear (issue #269).
25585 /// - 2016/10/30 (1.25.1) - Fixed clipping rectangle bug inside `nk_draw_list`.
25586 /// - 2016/10/29 (1.25.0) - Pulled `nk_panel` memory management into nuklear and out of
25587 ///                        the hands of the user. From now on users don't have to care
25588 ///                        about panels unless they care about some information. If you
25589 ///                        still need the panel just call `nk_window_get_panel`.
25590 /// - 2016/10/21 (1.24.0) - Changed widget border drawing to stroked rectangle from filled
25591 ///                        rectangle for less overdraw and widget background transparency.
25592 /// - 2016/10/18 (1.23.0) - Added `nk_edit_focus` for manually edit widget focus control.
25593 /// - 2016/09/29 (1.22.7) - Fixed deduction of basic type in non `<stdint.h>` compilation.
25594 /// - 2016/09/29 (1.22.6) - Fixed edit widget UTF-8 text cursor drawing bug.
25595 /// - 2016/09/28 (1.22.5) - Fixed edit widget UTF-8 text appending/inserting/removing.
25596 /// - 2016/09/28 (1.22.4) - Fixed drawing bug inside edit widgets which offset all text
25597 ///                        text in every edit widget if one of them is scrolled.
25598 /// - 2016/09/28 (1.22.3) - Fixed small bug in edit widgets if not active. The wrong
25599 ///                        text length is passed. It should have been in bytes but
25600 ///                        was passed as glyphes.
25601 /// - 2016/09/20 (1.22.2) - Fixed color button size calculation.
25602 /// - 2016/09/20 (1.22.1) - Fixed some `nk_vsnprintf` behavior bugs and removed `<stdio.h>`
25603 ///                        again from `NK_INCLUDE_STANDARD_VARARGS`.
25604 /// - 2016/09/18 (1.22.0) - C89 does not support vsnprintf only C99 and newer as well
25605 ///                        as C++11 and newer. In addition to use vsnprintf you have
25606 ///                        to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS`
25607 ///                        is not enough. That behavior is now fixed. By default if
25608 ///                        both varargs as well as stdio is selected I try to use
25609 ///                        vsnprintf if not possible I will revert to vsprintf. If
25610 ///                        varargs but not stdio was defined I will use my own function.
25611 /// - 2016/09/15 (1.21.2) - Fixed panel `close` behavior for deeper panel levels.
25612 /// - 2016/09/15 (1.21.1) - Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`.
25613 /// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo,
25614 ///                        and contextual which prevented closing in y-direction if
25615 ///                        popup did not reach max height.
25616 ///                        In addition the height parameter was changed into vec2
25617 ///                        for width and height to have more control over the popup size.
25618 /// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection.
25619 /// - 2016/09/13 (1.20.2) - Fixed slider behavior hopefully for the last time. This time
25620 ///                        all calculation are correct so no more hackery.
25621 /// - 2016/09/13 (1.20.1) - Internal change to divide window/panel flags into panel flags and types.
25622 ///                        Suprisinly spend years in C and still happened to confuse types
25623 ///                        with flags. Probably something to take note.
25624 /// - 2016/09/08 (1.20.0) - Added additional helper function to make it easier to just
25625 ///                        take the produced buffers from `nk_convert` and unplug the
25626 ///                        iteration process from `nk_context`. So now you can
25627 ///                        just use the vertex,element and command buffer + two pointer
25628 ///                        inside the command buffer retrieved by calls `nk__draw_begin`
25629 ///                        and `nk__draw_end` and macro `nk_draw_foreach_bounded`.
25630 /// - 2016/09/08 (1.19.0) - Added additional asserts to make sure every `nk_xxx_begin` call
25631 ///                        for windows, popups, combobox, menu and contextual is guarded by
25632 ///                        `if` condition and does not produce false drawing output.
25633 /// - 2016/09/08 (1.18.0) - Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT`
25634 ///                        to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and
25635 ///                        `NK_SYMBOL_RECT_OUTLINE`.
25636 /// - 2016/09/08 (1.17.0) - Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE`
25637 ///                        to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and
25638 ///                        `NK_SYMBOL_CIRCLE_OUTLINE`.
25639 /// - 2016/09/08 (1.16.0) - Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES`
25640 ///                        is not defined by supporting the biggest compiler GCC, clang and MSVC.
25641 /// - 2016/09/07 (1.15.3) - Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error.
25642 /// - 2016/09/04 (1.15.2) - Fixed wrong combobox height calculation.
25643 /// - 2016/09/03 (1.15.1) - Fixed gaps inside combo boxes in OpenGL.
25644 /// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and
25645 ///                        instead made it user provided. The range of types to convert
25646 ///                        to is quite limited at the moment, but I would be more than
25647 ///                        happy to accept PRs to add additional.
25648 /// - 2016/08/30 (1.14.2) - Removed unused variables.
25649 /// - 2016/08/30 (1.14.1) - Fixed C++ build errors.
25650 /// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly.
25651 /// - 2016/08/30 (1.13.4) - Tweaked some default styling variables.
25652 /// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would
25653 ///                        refrain from using slider with a big number of steps.
25654 /// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the
25655 ///                        window was in Read Only Mode.
25656 /// - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just
25657 ///                        a hack for combo box and menu.
25658 /// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since
25659 ///                        it is bugged and causes issues in window selection.
25660 /// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now
25661 ///                        determined by the scrollbar size.
25662 /// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11.0.
25663 /// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection.
25664 /// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code
25665 ///                        handling panel padding and panel border.
25666 /// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`.
25667 /// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups.
25668 /// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes.
25669 /// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for
25670 ///                        hash collisions. Currently limited to `NK_WINDOW_MAX_NAME`
25671 ///                        which in term can be redefined if not big enough.
25672 /// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code.
25673 /// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released'
25674 ///                        to account for key press and release happening in one frame.
25675 /// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate.
25676 /// - 2016/08/17 (1.09.6) - Removed invalid check for value zero in `nk_propertyx`.
25677 /// - 2016/08/16 (1.09.5) - Fixed ROM mode for deeper levels of popup windows parents.
25678 /// - 2016/08/15 (1.09.4) - Editbox are now still active if enter was pressed with flag
25679 ///                        `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep
25680 ///                        typing after commiting.
25681 /// - 2016/08/15 (1.09.4) - Removed redundant code.
25682 /// - 2016/08/15 (1.09.4) - Fixed negative numbers in `nk_strtoi` and remove unused variable.
25683 /// - 2016/08/15 (1.09.3) - Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background
25684 ///                        window only as selected by hovering and not by clicking.
25685 /// - 2016/08/14 (1.09.2) - Fixed a bug in font atlas which caused wrong loading
25686 ///                        of glyphes for font with multiple ranges.
25687 /// - 2016/08/12 (1.09.1) - Added additional function to check if window is currently
25688 ///                        hidden and therefore not visible.
25689 /// - 2016/08/12 (1.09.1) - nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED`
25690 ///                        instead of the old flag `NK_WINDOW_HIDDEN`.
25691 /// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed
25692 ///                        the underlying implementation to not cast to float and instead
25693 ///                        work directly on the given values.
25694 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
25695 ///                        floating pointer number to string conversion for additional
25696 ///                        precision.
25697 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
25698 ///                        string to floating point number conversion for additional
25699 ///                        precision.
25700 /// - 2016/08/08 (1.07.2) - Fixed compiling error without define `NK_INCLUDE_FIXED_TYPE`.
25701 /// - 2016/08/08 (1.07.1) - Fixed possible floating point error inside `nk_widget` leading
25702 ///                        to wrong wiget width calculation which results in widgets falsly
25703 ///                        becomming tagged as not inside window and cannot be accessed.
25704 /// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and
25705 ///                        closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown
25706 ///                        by using `nk_window_show` and closed by either clicking the close
25707 ///                        icon in a window or by calling `nk_window_close`. Only closed
25708 ///                        windows get removed at the end of the frame while hidden windows
25709 ///                        remain.
25710 /// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to
25711 ///                        `nk_edit_string` which takes, edits and outputs a '\0' terminated string.
25712 /// - 2016/08/08 (1.05.4) - Fixed scrollbar auto hiding behavior.
25713 /// - 2016/08/08 (1.05.3) - Fixed wrong panel padding selection in `nk_layout_widget_space`.
25714 /// - 2016/08/07 (1.05.2) - Fixed old bug in dynamic immediate mode layout API, calculating
25715 ///                        wrong item spacing and panel width.
25716 /// - 2016/08/07 (1.05.1) - Hopefully finally fixed combobox popup drawing bug.
25717 /// - 2016/08/07 (1.05.0) - Split varargs away from `NK_INCLUDE_STANDARD_IO` into own
25718 ///                        define `NK_INCLUDE_STANDARD_VARARGS` to allow more fine
25719 ///                        grained controlled over library includes.
25720 /// - 2016/08/06 (1.04.5) - Changed memset calls to `NK_MEMSET`.
25721 /// - 2016/08/04 (1.04.4) - Fixed fast window scaling behavior.
25722 /// - 2016/08/04 (1.04.3) - Fixed window scaling, movement bug which appears if you
25723 ///                        move/scale a window and another window is behind it.
25724 ///                        If you are fast enough then the window behind gets activated
25725 ///                        and the operation is blocked. I now require activating
25726 ///                        by hovering only if mouse is not pressed.
25727 /// - 2016/08/04 (1.04.2) - Fixed changing fonts.
25728 /// - 2016/08/03 (1.04.1) - Fixed `NK_WINDOW_BACKGROUND` behavior.
25729 /// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`.
25730 /// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for
25731 ///                        sub windows (combo, menu, ...).
25732 /// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor.
25733 /// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window
25734 ///                        to be always in the background of the screen.
25735 /// - 2016/08/03 (1.03.2) - Removed invalid assert macro for NK_RGB color picker.
25736 /// - 2016/08/01 (1.03.1) - Added helper macros into header include guard.
25737 /// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to
25738 ///                        simplify memory management by removing the need to
25739 ///                        allocate the pool.
25740 /// - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled
25741 ///                        will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT
25742 ///                        seconds without window interaction. To make it work
25743 ///                        you have to also set a delta time inside the `nk_context`.
25744 /// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs.
25745 /// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`.
25746 /// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument.
25747 /// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified
25748 ///                        font atlas memory management by converting pointer
25749 ///                        arrays for fonts and font configurations to lists.
25750 /// - 2016/07/15 (1.00.0) - Changed button API to use context dependend button
25751 ///                        behavior instead of passing it for every function call.
25752 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25753 /// ## Gallery
25754 /// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png)
25755 /// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png)
25756 /// ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png)
25757 /// ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png)
25758 /// ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png)
25759 /// ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png)
25760 /// ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif)
25761 /// ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png)
25762 /// ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png)
25763 ///
25764 /// ## Credits
25765 /// Developed by Micha Mettke and every direct or indirect github contributor. <br /><br />
25766 ///
25767 /// 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 />
25768 /// Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from r-lyeh@github.com for documentation generation <br /><br />
25769 /// Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br />
25770 ///
25771 /// Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and
25772 /// giving me the inspiration for this library, Casey Muratori for handmade hero
25773 /// and his original immediate mode graphical user interface idea and Sean
25774 /// Barret for his amazing single header libraries which restored my faith
25775 /// in libraries and brought me to create some of my own. Finally Apoorva Joshi
25776 /// for his single header file packer.
25777 */
25778 
25779