1 /*
2  Nuklear - 2.00.4 - public domain
3  no warranty implied; use at your own risk.
4  authored from 2015-2017 by Micha Mettke
5 
6 ABOUT:
7     This is a minimal state graphical user interface single header toolkit
8     written in ANSI C and licensed under public domain.
9     It was designed as a simple embeddable user interface for application and does
10     not have any dependencies, a default renderbackend or OS window and input handling
11     but instead provides a very modular library approach by using simple input state
12     for input and draw commands describing primitive shapes as output.
13     So instead of providing a layered library that tries to abstract over a number
14     of platform and render backends it only focuses on the actual UI.
15 
16 VALUES:
17     - Graphical user interface toolkit
18     - Single header library
19     - Written in C89 (a.k.a. ANSI C or ISO C90)
20     - Small codebase (~18kLOC)
21     - Focus on portability, efficiency and simplicity
22     - No dependencies (not even the standard library if not wanted)
23     - Fully skinnable and customizable
24     - Low memory footprint with total memory control if needed or wanted
25     - UTF-8 support
26     - No global or hidden state
27     - Customizable library modules (you can compile and use only what you need)
28     - Optional font baker and vertex buffer output
29 
30 USAGE:
31     This library is self contained in one single header file and can be used either
32     in header only mode or in implementation mode. The header only mode is used
33     by default when included and allows including this header in other headers
34     and does not contain the actual implementation.
35 
36     The implementation mode requires to define  the preprocessor macro
37     NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.:
38 
39         #define NK_IMPLEMENTATION
40         #include "nuklear.h"
41 
42     Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
43     below in header and implementation mode if you want to use additional functionality
44     or need more control over the library.
45     IMPORTANT:  Every time you include "nuklear.h" you have to define the same flags.
46                 This is very important not doing it either leads to compiler errors
47                 or even worse stack corruptions.
48 
49 FEATURES:
50     - Absolutely no platform dependent code
51     - Memory management control ranging from/to
52         - Ease of use by allocating everything from standard library
53         - Control every byte of memory inside the library
54     - Font handling control ranging from/to
55         - Use your own font implementation for everything
56         - Use this libraries internal font baking and handling API
57     - Drawing output control ranging from/to
58         - Simple shapes for more high level APIs which already have drawing capabilities
59         - Hardware accessible anti-aliased vertex buffer output
60     - Customizable colors and properties ranging from/to
61         - Simple changes to color by filling a simple color table
62         - Complete control with ability to use skinning to decorate widgets
63     - Bendable UI library with widget ranging from/to
64         - Basic widgets like buttons, checkboxes, slider, ...
65         - Advanced widget like abstract comboboxes, contextual menus,...
66     - Compile time configuration to only compile what you need
67         - Subset which can be used if you do not want to link or use the standard library
68     - Can be easily modified to only update on user input instead of frame updates
69 
70 OPTIONAL DEFINES:
71     NK_PRIVATE
72         If defined declares all functions as static, so they can only be accessed
73         inside the file that contains the implementation
74 
75     NK_INCLUDE_FIXED_TYPES
76         If defined it will include header <stdint.h> for fixed sized types
77         otherwise nuklear tries to select the correct type. If that fails it will
78         throw a compiler error and you have to select the correct types yourself.
79         <!> If used needs to be defined for implementation and header <!>
80 
81     NK_INCLUDE_DEFAULT_ALLOCATOR
82         if defined it will include header <stdlib.h> and provide additional functions
83         to use this library without caring for memory allocation control and therefore
84         ease memory management.
85         <!> Adds the standard library with malloc and free so don't define if you
86             don't want to link to the standard library <!>
87         <!> If used needs to be defined for implementation and header <!>
88 
89     NK_INCLUDE_STANDARD_IO
90         if defined it will include header <stdio.h> and provide
91         additional functions depending on file loading.
92         <!> Adds the standard library with fopen, fclose,... so don't define this
93             if you don't want to link to the standard library <!>
94         <!> If used needs to be defined for implementation and header <!>
95 
96     NK_INCLUDE_STANDARD_VARARGS
97         if defined it will include header <stdarg.h> and provide
98         additional functions depending on variable arguments
99         <!> Adds the standard library with va_list and  so don't define this if
100             you don't want to link to the standard library<!>
101         <!> If used needs to be defined for implementation and header <!>
102 
103     NK_INCLUDE_VERTEX_BUFFER_OUTPUT
104         Defining this adds a vertex draw command list backend to this
105         library, which allows you to convert queue commands into vertex draw commands.
106         This is mainly if you need a hardware accessible format for OpenGL, DirectX,
107         Vulkan, Metal,...
108         <!> If used needs to be defined for implementation and header <!>
109 
110     NK_INCLUDE_FONT_BAKING
111         Defining this adds `stb_truetype` and `stb_rect_pack` implementation
112         to this library and provides font baking and rendering.
113         If you already have font handling or do not want to use this font handler
114         you don't have to define it.
115         <!> If used needs to be defined for implementation and header <!>
116 
117     NK_INCLUDE_DEFAULT_FONT
118         Defining this adds the default font: ProggyClean.ttf into this library
119         which can be loaded into a font atlas and allows using this library without
120         having a truetype font
121         <!> Enabling this adds ~12kb to global stack memory <!>
122         <!> If used needs to be defined for implementation and header <!>
123 
124     NK_INCLUDE_COMMAND_USERDATA
125         Defining this adds a userdata pointer into each command. Can be useful for
126         example if you want to provide custom shaders depending on the used widget.
127         Can be combined with the style structures.
128         <!> If used needs to be defined for implementation and header <!>
129 
130     NK_BUTTON_TRIGGER_ON_RELEASE
131         Different platforms require button clicks occurring either on buttons being
132         pressed (up to down) or released (down to up).
133         By default this library will react on buttons being pressed, but if you
134         define this it will only trigger if a button is released.
135         <!> If used it is only required to be defined for the implementation part <!>
136 
137     NK_ZERO_COMMAND_MEMORY
138         Defining this will zero out memory for each drawing command added to a
139         drawing queue (inside nk_command_buffer_push). Zeroing command memory
140         is very useful for fast checking (using memcmp) if command buffers are
141         equal and avoid drawing frames when nothing on screen has changed since
142         previous frame.
143 
144     NK_ASSERT
145         If you don't define this, nuklear will use <assert.h> with assert().
146         <!> Adds the standard library so define to nothing of not wanted <!>
147         <!> If used needs to be defined for implementation and header <!>
148 
149     NK_BUFFER_DEFAULT_INITIAL_SIZE
150         Initial buffer size allocated by all buffers while using the default allocator
151         functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't
152         want to allocate the default 4k memory then redefine it.
153         <!> If used needs to be defined for implementation and header <!>
154 
155     NK_MAX_NUMBER_BUFFER
156         Maximum buffer size for the conversion buffer between float and string
157         Under normal circumstances this should be more than sufficient.
158         <!> If used needs to be defined for implementation and header <!>
159 
160     NK_INPUT_MAX
161         Defines the max number of bytes which can be added as text input in one frame.
162         Under normal circumstances this should be more than sufficient.
163         <!> If used it is only required to be defined for the implementation part <!>
164 
165     NK_MEMSET
166         You can define this to 'memset' or your own memset implementation
167         replacement. If not nuklear will use its own version.
168         <!> If used it is only required to be defined for the implementation part <!>
169 
170     NK_MEMCPY
171         You can define this to 'memcpy' or your own memcpy implementation
172         replacement. If not nuklear will use its own version.
173         <!> If used it is only required to be defined for the implementation part <!>
174 
175     NK_SQRT
176         You can define this to 'sqrt' or your own sqrt implementation
177         replacement. If not nuklear will use its own slow and not highly
178         accurate version.
179         <!> If used it is only required to be defined for the implementation part <!>
180 
181     NK_SIN
182         You can define this to 'sinf' or your own sine implementation
183         replacement. If not nuklear will use its own approximation implementation.
184         <!> If used it is only required to be defined for the implementation part <!>
185 
186     NK_COS
187         You can define this to 'cosf' or your own cosine implementation
188         replacement. If not nuklear will use its own approximation implementation.
189         <!> If used it is only required to be defined for the implementation part <!>
190 
191     NK_STRTOD
192         You can define this to `strtod` or your own string to double conversion
193         implementation replacement. If not defined nuklear will use its own
194         imprecise and possibly unsafe version (does not handle nan or infinity!).
195         <!> If used it is only required to be defined for the implementation part <!>
196 
197     NK_DTOA
198         You can define this to `dtoa` or your own double to string conversion
199         implementation replacement. If not defined nuklear will use its own
200         imprecise and possibly unsafe version (does not handle nan or infinity!).
201         <!> If used it is only required to be defined for the implementation part <!>
202 
203     NK_VSNPRINTF
204         If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO`
205         and want to be safe define this to `vsnprintf` on compilers supporting
206         later versions of C or C++. By default nuklear will check for your stdlib version
207         in C as well as compiler version in C++. if `vsnprintf` is available
208         it will define it to `vsnprintf` directly. If not defined and if you have
209         older versions of C or C++ it will be defined to `vsprintf` which is unsafe.
210         <!> If used it is only required to be defined for the implementation part <!>
211 
212     NK_BYTE
213     NK_INT16
214     NK_UINT16
215     NK_INT32
216     NK_UINT32
217     NK_SIZE_TYPE
218     NK_POINTER_TYPE
219         If you compile without NK_USE_FIXED_TYPE then a number of standard types
220         will be selected and compile time validated. If they are incorrect you can
221         define the correct types by overloading these type defines.
222 
223 CREDITS:
224     Developed by Micha Mettke and every direct or indirect contributor.
225 
226     Embeds stb_texedit, stb_truetype and stb_rectpack by Sean Barret (public domain)
227     Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license).
228 
229     Big thank you to Omar Cornut (ocornut@github) for his imgui library and
230     giving me the inspiration for this library, Casey Muratori for handmade hero
231     and his original immediate mode graphical user interface idea and Sean
232     Barret for his amazing single header libraries which restored my faith
233     in libraries and brought me to create some of my own.
234 
235 LICENSE:
236     This software is dual-licensed to the public domain and under the following
237     license: you are granted a perpetual, irrevocable license to copy, modify,
238     publish and distribute this file as you see fit.
239 */
240 #ifndef NK_NUKLEAR_H_
241 #define NK_NUKLEAR_H_
242 
243 #ifdef __cplusplus
244 extern "C" {
245 #endif
246 /*
247  * ==============================================================
248  *
249  *                          CONSTANTS
250  *
251  * ===============================================================
252  */
253 #define NK_UNDEFINED (-1.0f)
254 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
255 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
256 #ifndef NK_INPUT_MAX
257 #define NK_INPUT_MAX 16
258 #endif
259 #ifndef NK_MAX_NUMBER_BUFFER
260 #define NK_MAX_NUMBER_BUFFER 64
261 #endif
262 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
263 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
264 #endif
265 /*
266  * ==============================================================
267  *
268  *                          HELPER
269  *
270  * ===============================================================
271  */
272 #ifndef NK_API
273   #ifdef NK_PRIVATE
274     #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
275       #define NK_API static inline
276     #elif defined(__cplusplus)
277       #define NK_API static inline
278     #else
279       #define NK_API static
280     #endif
281   #else
282     #define NK_API extern
283   #endif
284 #endif
285 
286 #define NK_INTERN static
287 #define NK_STORAGE static
288 #define NK_GLOBAL static
289 
290 #define NK_FLAG(x) (1 << (x))
291 #define NK_STRINGIFY(x) #x
292 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
293 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
294 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
295 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
296 
297 #ifdef _MSC_VER
298 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
299 #else
300 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
301 #endif
302 
303 #ifndef NK_STATIC_ASSERT
304 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
305 #endif
306 
307 #ifndef NK_FILE_LINE
308 #ifdef _MSC_VER
309 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
310 #else
311 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
312 #endif
313 #endif
314 
315 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
316 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
317 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
318 /*
319  * ===============================================================
320  *
321  *                          BASIC
322  *
323  * ===============================================================
324  */
325 #ifdef NK_INCLUDE_FIXED_TYPES
326  #include <stdint.h>
327  #define NK_INT8 int8_t
328  #define NK_UINT8 uint8_t
329  #define NK_INT16 int16_t
330  #define NK_UINT16 uint16_t
331  #define NK_INT32 int32_t
332  #define NK_UINT32 uint32_t
333  #define NK_SIZE_TYPE uintptr_t
334  #define NK_POINTER_TYPE uintptr_t
335 #else
336   #ifndef NK_INT8
337     #define NK_INT8 char
338   #endif
339   #ifndef NK_UINT8
340     #define NK_UINT8 unsigned char
341   #endif
342   #ifndef NK_INT16
343     #define NK_INT16 signed short
344   #endif
345   #ifndef NK_UINT16
346     #define NK_UINT16 unsigned short
347   #endif
348   #ifndef NK_INT32
349     #if defined(_MSC_VER)
350       #define NK_INT32 __int32
351     #else
352       #define NK_INT32 signed int
353     #endif
354   #endif
355   #ifndef NK_UINT32
356     #if defined(_MSC_VER)
357       #define NK_UINT32 unsigned __int32
358     #else
359       #define NK_UINT32 unsigned int
360     #endif
361   #endif
362   #ifndef NK_SIZE_TYPE
363     #if defined(_WIN64) && defined(_MSC_VER)
364       #define NK_SIZE_TYPE unsigned __int64
365     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
366       #define NK_SIZE_TYPE unsigned __int32
367     #elif defined(__GNUC__) || defined(__clang__)
368       #if defined(__x86_64__) || defined(__ppc64__)
369         #define NK_SIZE_TYPE unsigned long
370       #else
371         #define NK_SIZE_TYPE unsigned int
372       #endif
373     #else
374       #define NK_SIZE_TYPE unsigned long
375     #endif
376   #endif
377   #ifndef NK_POINTER_TYPE
378     #if defined(_WIN64) && defined(_MSC_VER)
379       #define NK_POINTER_TYPE unsigned __int64
380     #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
381       #define NK_POINTER_TYPE unsigned __int32
382     #elif defined(__GNUC__) || defined(__clang__)
383       #if defined(__x86_64__) || defined(__ppc64__)
384         #define NK_POINTER_TYPE unsigned long
385       #else
386         #define NK_POINTER_TYPE unsigned int
387       #endif
388     #else
389       #define NK_POINTER_TYPE unsigned long
390     #endif
391   #endif
392 #endif
393 
394 typedef NK_INT8 nk_char;
395 typedef NK_UINT8 nk_uchar;
396 typedef NK_UINT8 nk_byte;
397 typedef NK_INT16 nk_short;
398 typedef NK_UINT16 nk_ushort;
399 typedef NK_INT32 nk_int;
400 typedef NK_UINT32 nk_uint;
401 typedef NK_SIZE_TYPE nk_size;
402 typedef NK_POINTER_TYPE nk_ptr;
403 
404 typedef nk_uint nk_hash;
405 typedef nk_uint nk_flags;
406 typedef nk_uint nk_rune;
407 
408 /* Make sure correct type size:
409  * This will fire with a negative subscript error if the type sizes
410  * are set incorrectly by the compiler, and compile out if not */
411 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
412 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
413 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
414 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
415 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
416 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
417 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
418 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
419 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
420 
421 /* ============================================================================
422  *
423  *                                  API
424  *
425  * =========================================================================== */
426 struct nk_buffer;
427 struct nk_allocator;
428 struct nk_command_buffer;
429 struct nk_draw_command;
430 struct nk_convert_config;
431 struct nk_style_item;
432 struct nk_text_edit;
433 struct nk_draw_list;
434 struct nk_user_font;
435 struct nk_panel;
436 struct nk_context;
437 struct nk_draw_vertex_layout_element;
438 struct nk_style_button;
439 struct nk_style_toggle;
440 struct nk_style_selectable;
441 struct nk_style_slide;
442 struct nk_style_progress;
443 struct nk_style_scrollbar;
444 struct nk_style_edit;
445 struct nk_style_property;
446 struct nk_style_chart;
447 struct nk_style_combo;
448 struct nk_style_tab;
449 struct nk_style_window_header;
450 struct nk_style_window;
451 
452 enum {nk_false, nk_true};
453 struct nk_color {nk_byte r,g,b,a;};
454 struct nk_colorf {float r,g,b,a;};
455 struct nk_vec2 {float x,y;};
456 struct nk_vec2i {short x, y;};
457 struct nk_rect {float x,y,w,h;};
458 struct nk_recti {short x,y,w,h;};
459 typedef char nk_glyph[NK_UTF_SIZE];
460 typedef union {void *ptr; int id;} nk_handle;
461 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
462 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
463 struct nk_scroll {nk_uint x, y;};
464 
465 enum nk_heading         {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
466 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
467 enum nk_modify          {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
468 enum nk_orientation     {NK_VERTICAL, NK_HORIZONTAL};
469 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true};
470 enum nk_show_states     {NK_HIDDEN = nk_false, NK_SHOWN = nk_true};
471 enum nk_chart_type      {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX};
472 enum nk_chart_event     {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02};
473 enum nk_color_format    {NK_RGB, NK_RGBA};
474 enum nk_popup_type      {NK_POPUP_STATIC, NK_POPUP_DYNAMIC};
475 enum nk_layout_format   {NK_DYNAMIC, NK_STATIC};
476 enum nk_tree_type       {NK_TREE_NODE, NK_TREE_TAB};
477 
478 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
479 typedef void (*nk_plugin_free)(nk_handle, void *old);
480 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
481 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
482 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
483 
484 struct nk_allocator {
485     nk_handle userdata;
486     nk_plugin_alloc alloc;
487     nk_plugin_free free;
488 };
489 enum nk_symbol_type {
490     NK_SYMBOL_NONE,
491     NK_SYMBOL_X,
492     NK_SYMBOL_UNDERSCORE,
493     NK_SYMBOL_CIRCLE_SOLID,
494     NK_SYMBOL_CIRCLE_OUTLINE,
495     NK_SYMBOL_RECT_SOLID,
496     NK_SYMBOL_RECT_OUTLINE,
497     NK_SYMBOL_TRIANGLE_UP,
498     NK_SYMBOL_TRIANGLE_DOWN,
499     NK_SYMBOL_TRIANGLE_LEFT,
500     NK_SYMBOL_TRIANGLE_RIGHT,
501     NK_SYMBOL_PLUS,
502     NK_SYMBOL_MINUS,
503     NK_SYMBOL_MAX
504 };
505 /* =============================================================================
506  *
507  *                                  CONTEXT
508  *
509  * =============================================================================*/
510 /*  Contexts are the main entry point and the majestro of nuklear and contain all required state.
511  *  They are used for window, memory, input, style, stack, commands and time management and need
512  *  to be passed into all nuklear GUI specific functions.
513  *
514  *  Usage
515  *  -------------------
516  *  To use a context it first has to be initialized which can be achieved by calling
517  *  one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
518  *  Each takes in a font handle and a specific way of handling memory. Memory control
519  *  hereby ranges from standard library to just specifying a fixed sized block of memory
520  *  which nuklear has to manage itself from.
521  *
522  *      struct nk_context ctx;
523  *      nk_init_xxx(&ctx, ...);
524  *      while (1) {
525  *          [...]
526  *          nk_clear(&ctx);
527  *      }
528  *      nk_free(&ctx);
529  *
530  *  Reference
531  *  -------------------
532  *  nk_init_default     - Initializes context with standard library memory allocation (malloc,free)
533  *  nk_init_fixed       - Initializes context from single fixed size memory block
534  *  nk_init             - Initializes context with memory allocator callbacks for alloc and free
535  *  nk_init_custom      - Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
536  *  nk_clear            - Called at the end of the frame to reset and prepare the context for the next frame
537  *  nk_free             - Shutdown and free all memory allocated inside the context
538  *  nk_set_user_data    - Utility function to pass user data to draw command
539  */
540 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
541 /*  nk_init_default - Initializes a `nk_context` struct with a default standard library allocator.
542  *  Should be used if you don't want to be bothered with memory management in nuklear.
543  *  Parameters:
544  *      @ctx must point to an either stack or heap allocated `nk_context` struct
545  *      @font must point to a previously initialized font handle for more info look at font documentation
546  *  Return values:
547  *      true(1) on success
548  *      false(0) on failure */
549 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
550 #endif
551 /*  nk_init_fixed - Initializes a `nk_context` struct from a single fixed size memory block
552  *  Should be used if you want complete control over nuklear's memory management.
553  *  Especially recommended for system with little memory or systems with virtual memory.
554  *  For the later case you can just allocate for example 16MB of virtual memory
555  *  and only the required amount of memory will actually be committed.
556  *  IMPORTANT: make sure the passed memory block is aligned correctly for `nk_draw_commands`
557  *  Parameters:
558  *      @ctx must point to an either stack or heap allocated `nk_context` struct
559  *      @memory must point to a previously allocated memory block
560  *      @size must contain the total size of @memory
561  *      @font must point to a previously initialized font handle for more info look at font documentation
562  *  Return values:
563  *      true(1) on success
564  *      false(0) on failure */
565 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
566 /*  nk_init - Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
567  *  memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
568  *  interface to nuklear. Can be useful for cases like monitoring memory consumption.
569  *  Parameters:
570  *      @ctx must point to an either stack or heap allocated `nk_context` struct
571  *      @alloc must point to a previously allocated memory allocator
572  *      @font must point to a previously initialized font handle for more info look at font documentation
573  *  Return values:
574  *      true(1) on success
575  *      false(0) on failure */
576 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
577 /*  nk_init_custom - Initializes a `nk_context` struct from two different either fixed or growing
578  *  buffers. The first buffer is for allocating draw commands while the second buffer is
579  *  used for allocating windows, panels and state tables.
580  *  Parameters:
581  *      @ctx must point to an either stack or heap allocated `nk_context` struct
582  *      @cmds must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
583  *      @pool must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
584  *      @font must point to a previously initialized font handle for more info look at font documentation
585  *  Return values:
586  *      true(1) on success
587  *      false(0) on failure */
588 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
589 /*  nk_clear - Resets the context state at the end of the frame. This includes mostly
590  *  garbage collector tasks like removing windows or table not called and therefore
591  *  used anymore.
592  *  Parameters:
593  *      @ctx must point to a previously initialized `nk_context` struct */
594 NK_API void nk_clear(struct nk_context*);
595 /*  nk_free - Frees all memory allocated by nuklear. Not needed if context was
596  *  initialized with `nk_init_fixed`.
597  *  Parameters:
598  *      @ctx must point to a previously initialized `nk_context` struct */
599 NK_API void nk_free(struct nk_context*);
600 #ifdef NK_INCLUDE_COMMAND_USERDATA
601 /*  nk_set_user_data - Sets the currently passed userdata passed down into each draw command.
602  *  Parameters:
603  *      @ctx must point to a previously initialized `nk_context` struct
604  *      @data handle with either pointer or index to be passed into every draw commands */
605 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
606 #endif
607 /* =============================================================================
608  *
609  *                                  INPUT
610  *
611  * =============================================================================*/
612 /*  The input API is responsible for holding the current input state composed of
613  *  mouse, key and text input states.
614  *  It is worth noting that no direct os or window handling is done in nuklear.
615  *  Instead all input state has to be provided by platform specific code. This in one hand
616  *  expects more work from the user and complicates usage but on the other hand
617  *  provides simple abstraction over a big number of platforms, libraries and other
618  *  already provided functionality.
619  *
620  *  Usage
621  *  -------------------
622  *  Input state needs to be provided to nuklear by first calling `nk_input_begin`
623  *  which resets internal state like delta mouse position and button transistions.
624  *  After `nk_input_begin` all current input state needs to be provided. This includes
625  *  mouse motion, button and key pressed and released, text input and scrolling.
626  *  Both event- or state-based input handling are supported by this API
627  *  and should work without problems. Finally after all input state has been
628  *  mirrored `nk_input_end` needs to be called to finish input process.
629  *
630  *      struct nk_context ctx;
631  *      nk_init_xxx(&ctx, ...);
632  *      while (1) {
633  *          Event evt;
634  *          nk_input_begin(&ctx);
635  *          while (GetEvent(&evt)) {
636  *              if (evt.type == MOUSE_MOVE)
637  *                  nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
638  *              else if (evt.type == ...) {
639  *                  ...
640  *              }
641  *          }
642  *          nk_input_end(&ctx);
643  *          [...]
644  *          nk_clear(&ctx);
645  *      }
646  *      nk_free(&ctx);
647  *
648  *  Reference
649  *  -------------------
650  *  nk_input_begin      - Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
651  *  nk_input_motion     - Mirrors mouse cursor position
652  *  nk_input_key        - Mirrors key state with either pressed or released
653  *  nk_input_button     - Mirrors mouse button state with either pressed or released
654  *  nk_input_scroll     - Mirrors mouse scroll values
655  *  nk_input_char       - Adds a single ASCII text character into an internal text buffer
656  *  nk_input_glyph      - Adds a single multi-byte UTF-8 character into an internal text buffer
657  *  nk_input_unicode    - Adds a single unicode rune into an internal text buffer
658  *  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
659  */
660 enum nk_keys {
661     NK_KEY_NONE,
662     NK_KEY_SHIFT,
663     NK_KEY_CTRL,
664     NK_KEY_DEL,
665     NK_KEY_ENTER,
666     NK_KEY_TAB,
667     NK_KEY_BACKSPACE,
668     NK_KEY_COPY,
669     NK_KEY_CUT,
670     NK_KEY_PASTE,
671     NK_KEY_UP,
672     NK_KEY_DOWN,
673     NK_KEY_LEFT,
674     NK_KEY_RIGHT,
675     /* Shortcuts: text field */
676     NK_KEY_TEXT_INSERT_MODE,
677     NK_KEY_TEXT_REPLACE_MODE,
678     NK_KEY_TEXT_RESET_MODE,
679     NK_KEY_TEXT_LINE_START,
680     NK_KEY_TEXT_LINE_END,
681     NK_KEY_TEXT_START,
682     NK_KEY_TEXT_END,
683     NK_KEY_TEXT_UNDO,
684     NK_KEY_TEXT_REDO,
685     NK_KEY_TEXT_SELECT_ALL,
686     NK_KEY_TEXT_WORD_LEFT,
687     NK_KEY_TEXT_WORD_RIGHT,
688     /* Shortcuts: scrollbar */
689     NK_KEY_SCROLL_START,
690     NK_KEY_SCROLL_END,
691     NK_KEY_SCROLL_DOWN,
692     NK_KEY_SCROLL_UP,
693     NK_KEY_MAX
694 };
695 enum nk_buttons {
696     NK_BUTTON_LEFT,
697     NK_BUTTON_MIDDLE,
698     NK_BUTTON_RIGHT,
699     NK_BUTTON_DOUBLE,
700     NK_BUTTON_MAX
701 };
702 /*  nk_input_begin - Begins the input mirroring process by resetting text, scroll
703  *  mouse previous mouse position and movement as well as key state transitions,
704  *  Parameters:
705  *      @ctx must point to an previously initialized `nk_context` struct */
706 NK_API void nk_input_begin(struct nk_context*);
707 /*  nk_input_motion - Mirrors current mouse position to nuklear
708  *  Parameters:
709  *      @ctx must point to an previously initialized `nk_context` struct
710  *      @x must contain an integer describing the current mouse cursor x-position
711  *      @y must contain an integer describing the current mouse cursor y-position */
712 NK_API void nk_input_motion(struct nk_context*, int x, int y);
713 /*  nk_input_key - Mirrors state of a specific key to nuklear
714  *  Parameters:
715  *      @ctx must point to an previously initialized `nk_context` struct
716  *      @key must be any value specified in enum `nk_keys` that needs to be mirrored
717  *      @down must be 0 for key is up and 1 for key is down */
718 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
719 /*  nk_input_button - Mirrors the state of a specific mouse button to nuklear
720  *  Parameters:
721  *      @ctx must point to an previously initialized `nk_context` struct
722  *      @nk_buttons must be any value specified in enum `nk_buttons` that needs to be mirrored
723  *      @x must contain an integer describing mouse cursor x-position on click up/down
724  *      @y must contain an integer describing mouse cursor y-position on click up/down
725  *      @down must be 0 for key is up and 1 for key is down */
726 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
727 /*  nk_input_scroll - Copies the last mouse scroll value to nuklear. Is generally
728  *  a  scroll value. So does not have to come from mouse and could also originate
729  *  from touch for example.
730  *  Parameters:
731  *      @ctx must point to an previously initialized `nk_context` struct
732  *      @val vector with both X- as well as Y-scroll value */
733 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
734 /*  nk_input_char - Copies a single ASCII character into an internal text buffer
735  *  This is basically a helper function to quickly push ASCII characters into
736  *  nuklear. Note that you can only push up to NK_INPUT_MAX bytes into
737  *  struct `nk_input` between `nk_input_begin` and `nk_input_end`.
738  *  Parameters:
739  *      @ctx must point to an previously initialized `nk_context` struct
740  *      @c must be a single ASCII character preferable one that can be printed */
741 NK_API void nk_input_char(struct nk_context*, char);
742 /*  nk_input_unicode - Converts a encoded unicode rune into UTF-8 and copies the result
743  *  into an internal text buffer.
744  *  Note that you can only push up to NK_INPUT_MAX bytes into
745  *  struct `nk_input` between `nk_input_begin` and `nk_input_end`.
746  *  Parameters:
747  *      @ctx must point to an previously initialized `nk_context` struct
748  *      @glyph UTF-32 unicode codepoint */
749 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
750 /*  nk_input_unicode - Converts a unicode rune into UTF-8 and copies the result
751  *  into an internal text buffer.
752  *  Note that you can only push up to NK_INPUT_MAX bytes into
753  *  struct `nk_input` between `nk_input_begin` and `nk_input_end`.
754  *  Parameters:
755  *      @ctx must point to an previously initialized `nk_context` struct
756  *      @glyph UTF-32 unicode codepoint */
757 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
758 /*  nk_input_end - End the input mirroring process by resetting mouse grabbing
759  *  state to ensure the mouse cursor is not grabbed indefinitely.
760  *  Parameters:
761  *      @ctx must point to an previously initialized `nk_context` struct */
762 NK_API void nk_input_end(struct nk_context*);
763 /* =============================================================================
764  *
765  *                                  DRAWING
766  *
767  * =============================================================================*/
768 /*  This library was designed to be render backend agnostic so it does
769  *  not draw anything to screen directly. Instead all drawn shapes, widgets
770  *  are made of, are buffered into memory and make up a command queue.
771  *  Each frame therefore fills the command buffer with draw commands
772  *  that then need to be executed by the user and his own render backend.
773  *  After that the command buffer needs to be cleared and a new frame can be
774  *  started. It is probably important to note that the command buffer is the main
775  *  drawing API and the optional vertex buffer API only takes this format and
776  *  converts it into a hardware accessible format.
777  *
778  *  Usage
779  *  -------------------
780  *  To draw all draw commands accumulated over a frame you need your own render
781  *  backend able to draw a number of 2D primitives. This includes at least
782  *  filled and stroked rectangles, circles, text, lines, triangles and scissors.
783  *  As soon as this criterion is met you can iterate over each draw command
784  *  and execute each draw command in a interpreter like fashion:
785  *
786  *      const struct nk_command *cmd = 0;
787  *      nk_foreach(cmd, &ctx) {
788  *      switch (cmd->type) {
789  *      case NK_COMMAND_LINE:
790  *          your_draw_line_function(...)
791  *          break;
792  *      case NK_COMMAND_RECT
793  *          your_draw_rect_function(...)
794  *          break;
795  *      case ...:
796  *          [...]
797  *      }
798  *
799  *  In program flow context draw commands need to be executed after input has been
800  *  gathered and the complete UI with windows and their contained widgets have
801  *  been executed and before calling `nk_clear` which frees all previously
802  *  allocated draw commands.
803  *
804  *      struct nk_context ctx;
805  *      nk_init_xxx(&ctx, ...);
806  *      while (1) {
807  *          Event evt;
808  *          nk_input_begin(&ctx);
809  *          while (GetEvent(&evt)) {
810  *              if (evt.type == MOUSE_MOVE)
811  *                  nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
812  *              else if (evt.type == [...]) {
813  *                  [...]
814  *              }
815  *          }
816  *          nk_input_end(&ctx);
817  *
818  *          [...]
819  *
820  *          const struct nk_command *cmd = 0;
821  *          nk_foreach(cmd, &ctx) {
822  *          switch (cmd->type) {
823  *          case NK_COMMAND_LINE:
824  *              your_draw_line_function(...)
825  *              break;
826  *          case NK_COMMAND_RECT
827  *              your_draw_rect_function(...)
828  *              break;
829  *          case ...:
830  *              [...]
831  *          }
832  *          nk_clear(&ctx);
833  *      }
834  *      nk_free(&ctx);
835  *
836  *  You probably noticed that you have to draw all of the UI each frame which is
837  *  quite wasteful. While the actual UI updating loop is quite fast rendering
838  *  without actually needing it is not. So there are multiple things you could do.
839  *
840  *  First is only update on input. This of course is only an option if your
841  *  application only depends on the UI and does not require any outside calculations.
842  *  If you actually only update on input make sure to update the UI two times each
843  *  frame and call `nk_clear` directly after the first pass and only draw in
844  *  the second pass. In addition it is recommended to also add additional timers
845  *  to make sure the UI is not drawn more than a fixed number of frames per second.
846  *
847  *      struct nk_context ctx;
848  *      nk_init_xxx(&ctx, ...);
849  *      while (1) {
850  *          [...wait for input ]
851  *
852  *          [...do two UI passes ...]
853  *          do_ui(...)
854  *          nk_clear(&ctx);
855  *          do_ui(...)
856  *
857  *          const struct nk_command *cmd = 0;
858  *          nk_foreach(cmd, &ctx) {
859  *          switch (cmd->type) {
860  *          case NK_COMMAND_LINE:
861  *              your_draw_line_function(...)
862  *              break;
863  *          case NK_COMMAND_RECT
864  *              your_draw_rect_function(...)
865  *              break;
866  *          case ...:
867  *              [...]
868  *          }
869  *          nk_clear(&ctx);
870  *      }
871  *      nk_free(&ctx);
872  *
873  *  The second probably more applicable trick is to only draw if anything changed.
874  *  It is not really useful for applications with continuous draw loop but
875  *  quite useful for desktop applications. To actually get nuklear to only
876  *  draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
877  *  allocate a memory buffer that will store each unique drawing output.
878  *  After each frame you compare the draw command memory inside the library
879  *  with your allocated buffer by memcmp. If memcmp detects differences
880  *  you have to copy the command buffer into the allocated buffer
881  *  and then draw like usual (this example uses fixed memory but you could
882  *  use dynamically allocated memory).
883  *
884  *      [... other defines ...]
885  *      #define NK_ZERO_COMMAND_MEMORY
886  *      #include "nuklear.h"
887  *
888  *      struct nk_context ctx;
889  *      void *last = calloc(1,64*1024);
890  *      void *buf = calloc(1,64*1024);
891  *      nk_init_fixed(&ctx, buf, 64*1024);
892  *      while (1) {
893  *          [...input...]
894  *          [...ui...]
895  *
896  *          void *cmds = nk_buffer_memory(&ctx.memory);
897  *          if (memcmp(cmds, last, ctx.memory.allocated)) {
898  *              memcpy(last,cmds,ctx.memory.allocated);
899  *              const struct nk_command *cmd = 0;
900  *              nk_foreach(cmd, &ctx) {
901  *                  switch (cmd->type) {
902  *                  case NK_COMMAND_LINE:
903  *                      your_draw_line_function(...)
904  *                      break;
905  *                  case NK_COMMAND_RECT
906  *                      your_draw_rect_function(...)
907  *                      break;
908  *                  case ...:
909  *                      [...]
910  *                  }
911  *              }
912  *          }
913  *          nk_clear(&ctx);
914  *      }
915  *      nk_free(&ctx);
916  *
917  *  Finally while using draw commands makes sense for higher abstracted platforms like
918  *  X11 and Win32 or drawing libraries it is often desirable to use graphics
919  *  hardware directly. Therefore it is possible to just define
920  *  `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
921  *  To access the vertex output you first have to convert all draw commands into
922  *  vertexes by calling `nk_convert` which takes in your preferred vertex format.
923  *  After successfully converting all draw commands just iterate over and execute all
924  *  vertex draw commands:
925  *
926  *      struct nk_convert_config cfg = {};
927  *      static const struct nk_draw_vertex_layout_element vertex_layout[] = {
928  *          {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
929  *          {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
930  *          {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
931  *          {NK_VERTEX_LAYOUT_END}
932  *      };
933  *      cfg.shape_AA = NK_ANTI_ALIASING_ON;
934  *      cfg.line_AA = NK_ANTI_ALIASING_ON;
935  *      cfg.vertex_layout = vertex_layout;
936  *      cfg.vertex_size = sizeof(struct your_vertex);
937  *      cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
938  *      cfg.circle_segment_count = 22;
939  *      cfg.curve_segment_count = 22;
940  *      cfg.arc_segment_count = 22;
941  *      cfg.global_alpha = 1.0f;
942  *      cfg.null = dev->null;
943  *
944  *      struct nk_buffer cmds, verts, idx;
945  *      nk_buffer_init_default(&cmds);
946  *      nk_buffer_init_default(&verts);
947  *      nk_buffer_init_default(&idx);
948  *      nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
949  *      nk_draw_foreach(cmd, &ctx, &cmds) {
950  *          if (!cmd->elem_count) continue;
951  *          [...]
952  *      }
953  *      nk_buffer_free(&cms);
954  *      nk_buffer_free(&verts);
955  *      nk_buffer_free(&idx);
956  *
957  *  Reference
958  *  -------------------
959  *  nk__begin           - Returns the first draw command in the context draw command list to be drawn
960  *  nk__next            - Increments the draw command iterator to the next command inside the context draw command list
961  *  nk_foreach          - Iterates over each draw command inside the context draw command list
962  *
963  *  nk_convert          - Converts from the abstract draw commands list into a hardware accessible vertex format
964  *  nk__draw_begin      - Returns the first vertex command in the context vertex draw list to be executed
965  *  nk__draw_next       - Increments the vertex command iterator to the next command inside the context vertex command list
966  *  nk__draw_end        - Returns the end of the vertex draw list
967  *  nk_draw_foreach     - Iterates over each vertex draw command inside the vertex draw list
968  */
969 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON};
970 enum nk_convert_result {
971     NK_CONVERT_SUCCESS = 0,
972     NK_CONVERT_INVALID_PARAM = 1,
973     NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1),
974     NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2),
975     NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3)
976 };
977 struct nk_draw_null_texture {
978     nk_handle texture; /* texture handle to a texture with a white pixel */
979     struct nk_vec2 uv; /* coordinates to a white pixel in the texture  */
980 };
981 struct nk_convert_config {
982     float global_alpha; /* global alpha value */
983     enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
984     enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
985     unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
986     unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
987     unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
988     struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
989     const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
990     nk_size vertex_size; /* sizeof one vertex for vertex packing */
991     nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
992 };
993 /*  nk__begin - Returns a draw command list iterator to iterate all draw
994  *  commands accumulated over one frame.
995  *  Parameters:
996  *      @ctx must point to an previously initialized `nk_context` struct at the end of a frame
997  *  Return values:
998  *      draw command pointer pointing to the first command inside the draw command list  */
999 NK_API const struct nk_command* nk__begin(struct nk_context*);
1000 /*  nk__next - Returns a draw command list iterator to iterate all draw
1001  *  Parameters:
1002  *      @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1003  *      @cmd must point to an previously a draw command either returned by `nk__begin` or `nk__next`
1004  *  Return values:
1005  *      draw command pointer pointing to the next command inside the draw command list  */
1006 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1007 /*  nk_foreach - Iterates over each draw command inside the context draw command list
1008  *  Parameters:
1009  *      @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1010  *      @cmd pointer initialized to NULL */
1011 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1012 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1013 /*  nk_convert - converts all internal draw command into vertex draw commands and fills
1014  *  three buffers with vertexes, vertex draw commands and vertex indices. The vertex format
1015  *  as well as some other configuration values have to be configured by filling out a
1016  *  `nk_convert_config` struct.
1017  *  Parameters:
1018  *      @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1019  *      @cmds must point to a previously initialized buffer to hold converted vertex draw commands
1020  *      @vertices must point to a previously initialized buffer to hold all produced vertices
1021  *      @elements must point to a previously initialized buffer to hold all produced vertex indices
1022  *      @config must point to a filled out `nk_config` struct to configure the conversion process
1023  *  Returns:
1024  *      returns NK_CONVERT_SUCCESS on success and a enum nk_convert_result error values if not */
1025 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*);
1026 /*  nk__draw_begin - Returns a draw vertex command buffer iterator to iterate each the vertex draw command buffer
1027  *  Parameters:
1028  *      @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1029  *      @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1030  *  Return values:
1031  *      vertex draw command pointer pointing to the first command inside the vertex draw command buffer  */
1032 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1033 /*  nk__draw_end - Returns the vertex draw command  at the end of the vertex draw command buffer
1034  *  Parameters:
1035  *      @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1036  *      @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1037  *  Return values:
1038  *      vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer  */
1039 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1040 /*  nk__draw_next - Increments the vertex draw command buffer iterator
1041  *  Parameters:
1042  *      @cmd must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
1043  *      @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1044  *      @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1045  *  Return values:
1046  *      vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer  */
1047 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1048 /*  nk_draw_foreach - Iterates over each vertex draw command inside a vertex draw command buffer
1049  *  Parameters:
1050  *      @cmd nk_draw_command pointer set to NULL
1051  *      @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1052  *      @ctx must point to an previously initialized `nk_context` struct at the end of a frame */
1053 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1054 #endif
1055 /* =============================================================================
1056  *
1057  *                                  WINDOW
1058  *
1059  * =============================================================================
1060  * Windows are the main persistent state used inside nuklear and are life time
1061  * controlled by simply "retouching" (i.e. calling) each window each frame.
1062  * All widgets inside nuklear can only be added inside function pair `nk_begin_xxx`
1063  * and `nk_end`. Calling any widgets outside these two functions will result in an
1064  * assert in debug or no state change in release mode.
1065  *
1066  * Each window holds frame persistent state like position, size, flags, state tables,
1067  * and some garbage collected internal persistent widget state. Each window
1068  * is linked into a window stack list which determines the drawing and overlapping
1069  * order. The topmost window thereby is the currently active window.
1070  *
1071  * To change window position inside the stack occurs either automatically by
1072  * user input by being clicked on or programmatically by calling `nk_window_focus`.
1073  * Windows by default are visible unless explicitly being defined with flag
1074  * `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
1075  * `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
1076  * `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.
1077  *
1078  * Usage
1079  * -------------------
1080  * To create and keep a window you have to call one of the two `nk_begin_xxx`
1081  * functions to start window declarations and `nk_end` at the end. Furthermore it
1082  * is recommended to check the return value of `nk_begin_xxx` and only process
1083  * widgets inside the window if the value is not 0. Either way you have to call
1084  * `nk_end` at the end of window declarations. Furthermore, do not attempt to
1085  * nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
1086  * in a segmentation fault.
1087  *
1088  *      if (nk_begin_xxx(...) {
1089  *          [... widgets ...]
1090  *      }
1091  *      nk_end(ctx);
1092  *
1093  * In the grand concept window and widget declarations need to occur after input
1094  * handling and before drawing to screen. Not doing so can result in higher
1095  * latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
1096  * is called at the end of the frame. While nuklear's default platform backends
1097  * already call `nk_clear` for you if you write your own backend not calling
1098  * `nk_clear` can cause asserts or even worse undefined behavior.
1099  *
1100  *      struct nk_context ctx;
1101  *      nk_init_xxx(&ctx, ...);
1102  *      while (1) {
1103  *          Event evt;
1104  *          nk_input_begin(&ctx);
1105  *          while (GetEvent(&evt)) {
1106  *              if (evt.type == MOUSE_MOVE)
1107  *                  nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
1108  *              else if (evt.type == [...]) {
1109  *                  nk_input_xxx(...);
1110  *              }
1111  *          }
1112  *          nk_input_end(&ctx);
1113  *
1114  *          if (nk_begin_xxx(...) {
1115  *              [...]
1116  *          }
1117  *          nk_end(ctx);
1118  *
1119  *          const struct nk_command *cmd = 0;
1120  *          nk_foreach(cmd, &ctx) {
1121  *          case NK_COMMAND_LINE:
1122  *              your_draw_line_function(...)
1123  *              break;
1124  *          case NK_COMMAND_RECT
1125  *              your_draw_rect_function(...)
1126  *              break;
1127  *          case ...:
1128  *              [...]
1129  *          }
1130  *          nk_clear(&ctx);
1131  *      }
1132  *      nk_free(&ctx);
1133  *
1134  *  Reference
1135  *  -------------------
1136  *  nk_begin                            - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1137  *  nk_begin_titled                     - extended window start with separated title and identifier to allow multiple windows with same name but not title
1138  *  nk_end                              - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
1139  *
1140  *  nk_window_find                      - finds and returns the window with give name
1141  *  nk_window_get_bounds                - returns a rectangle with screen position and size of the currently processed window.
1142  *  nk_window_get_position              - returns the position of the currently processed window
1143  *  nk_window_get_size                  - returns the size with width and height of the currently processed window
1144  *  nk_window_get_width                 - returns the width of the currently processed window
1145  *  nk_window_get_height                - returns the height of the currently processed window
1146  *  nk_window_get_panel                 - returns the underlying panel which contains all processing state of the current window
1147  *  nk_window_get_content_region        - returns the position and size of the currently visible and non-clipped space inside the currently processed window
1148  *  nk_window_get_content_region_min    - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1149  *  nk_window_get_content_region_max    - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1150  *  nk_window_get_content_region_size   - returns the size of the currently visible and non-clipped space inside the currently processed window
1151  *  nk_window_get_canvas                - returns the draw command buffer. Can be used to draw custom widgets
1152  *
1153  *  nk_window_has_focus                 - returns if the currently processed window is currently active
1154  *  nk_window_is_collapsed              - returns if the window with given name is currently minimized/collapsed
1155  *  nk_window_is_closed                 - returns if the currently processed window was closed
1156  *  nk_window_is_hidden                 - returns if the currently processed window was hidden
1157  *  nk_window_is_active                 - same as nk_window_has_focus for some reason
1158  *  nk_window_is_hovered                - returns if the currently processed window is currently being hovered by mouse
1159  *  nk_window_is_any_hovered            - return if any window currently hovered
1160  *  nk_item_is_any_active               - returns if any window or widgets is currently hovered or active
1161  *
1162  *  nk_window_set_bounds                - updates position and size of the currently processed window
1163  *  nk_window_set_position              - updates position of the currently process window
1164  *  nk_window_set_size                  - updates the size of the currently processed window
1165  *  nk_window_set_focus                 - set the currently processed window as active window
1166  *
1167  *  nk_window_close                     - closes the window with given window name which deletes the window at the end of the frame
1168  *  nk_window_collapse                  - collapses the window with given window name
1169  *  nk_window_collapse_if               - collapses the window with given window name if the given condition was met
1170  *  nk_window_show                      - hides a visible or reshows a hidden window
1171  *  nk_window_show_if                   - hides/shows a window depending on condition
1172  */
1173 enum nk_panel_flags {
1174     NK_WINDOW_BORDER            = NK_FLAG(0), /* Draws a border around the window to visually separate window from the background */
1175     NK_WINDOW_MOVABLE           = NK_FLAG(1), /* The movable flag indicates that a window can be moved by user input or by dragging the window header */
1176     NK_WINDOW_SCALABLE          = NK_FLAG(2), /* The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window */
1177     NK_WINDOW_CLOSABLE          = NK_FLAG(3), /* adds a closable icon into the header */
1178     NK_WINDOW_MINIMIZABLE       = NK_FLAG(4), /* adds a minimize icon into the header */
1179     NK_WINDOW_NO_SCROLLBAR      = NK_FLAG(5), /* Removes the scrollbar from the window */
1180     NK_WINDOW_TITLE             = NK_FLAG(6), /* Forces a header at the top at the window showing the title */
1181     NK_WINDOW_SCROLL_AUTO_HIDE  = NK_FLAG(7), /* Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame */
1182     NK_WINDOW_BACKGROUND        = NK_FLAG(8), /* Always keep window in the background */
1183     NK_WINDOW_SCALE_LEFT        = NK_FLAG(9), /* Puts window scaler in the left-ottom corner instead right-bottom*/
1184     NK_WINDOW_NO_INPUT          = NK_FLAG(10) /* Prevents window of scaling, moving or getting focus */
1185 };
1186 /*  nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1187  *  Parameters:
1188  *      @ctx must point to an previously initialized `nk_context` struct
1189  *      @title window title and identifier. Needs to be persistent over frames to identify the window
1190  *      @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
1191  *      @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1192  *  Return values:
1193  *      returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise for example if minimized `*/
1194 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1195 /*  nk_begin_titled - extended window start with separated title and identifier to allow multiple windows with same name but not title
1196  *  Parameters:
1197  *      @ctx must point to an previously initialized `nk_context` struct
1198  *      @name window identifier. Needs to be persistent over frames to identify the window
1199  *      @title window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
1200  *      @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
1201  *      @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1202  *  Return values:
1203  *      returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise `*/
1204 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1205 /*  nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
1206  *  All widget calls after this functions will result in asserts or no state changes
1207  *  Parameters:
1208  *      @ctx must point to an previously initialized `nk_context` struct */
1209 NK_API void nk_end(struct nk_context *ctx);
1210 /*  nk_window_find - finds and returns the window with give name
1211  *  Parameters:
1212  *      @ctx must point to an previously initialized `nk_context` struct
1213  *      @name window identifier
1214  *  Return values:
1215  *      returns a `nk_window` struct pointing to the identified window or 0 if no window with given name was found */
1216 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1217 /*  nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1218  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1219  *  Parameters:
1220  *      @ctx must point to an previously initialized `nk_context` struct
1221  *  Return values:
1222  *      returns a `nk_rect` struct with window upper left position and size */
1223 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
1224 /*  nk_window_get_position - returns the position of the currently processed window.
1225  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1226  *  Parameters:
1227  *      @ctx must point to an previously initialized `nk_context` struct
1228  *  Return values:
1229  *      returns a `nk_vec2` struct with window upper left position */
1230 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
1231 /*  nk_window_get_size - returns the size with width and height of the currently processed window.
1232  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1233  *  Parameters:
1234  *      @ctx must point to an previously initialized `nk_context` struct
1235  *  Return values:
1236  *      returns a `nk_vec2` struct with window size */
1237 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*);
1238 /*  nk_window_get_width - returns the width of the currently processed window.
1239  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1240  *  Parameters:
1241  *      @ctx must point to an previously initialized `nk_context` struct
1242  *  Return values:
1243  *      returns the window width */
1244 NK_API float nk_window_get_width(const struct nk_context*);
1245 /*  nk_window_get_height - returns the height of the currently processed window.
1246  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1247  *  Parameters:
1248  *      @ctx must point to an previously initialized `nk_context` struct
1249  *  Return values:
1250  *      returns the window height */
1251 NK_API float nk_window_get_height(const struct nk_context*);
1252 /*  nk_window_get_panel - returns the underlying panel which contains all processing state of the current window.
1253  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1254  *  Parameters:
1255  *      @ctx must point to an previously initialized `nk_context` struct
1256  *  Return values:
1257  *      returns a pointer to window internal `nk_panel` state. DO NOT keep this pointer around it is only valid until `nk_end` */
1258 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*);
1259 /*  nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window.
1260  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1261  *  Parameters:
1262  *      @ctx must point to an previously initialized `nk_context` struct
1263  *  Return values:
1264  *      returns `nk_rect` struct with screen position and size (no scrollbar offset) of the visible space inside the current window */
1265 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*);
1266 /*  nk_window_get_content_region_min - returns the upper left position of the currently visible and non-clipped space inside the currently processed window.
1267  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1268  *  Parameters:
1269  *      @ctx must point to an previously initialized `nk_context` struct
1270  *  Return values:
1271  *      returns `nk_vec2` struct with  upper left screen position (no scrollbar offset) of the visible space inside the current window */
1272 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*);
1273 /*  nk_window_get_content_region_max - returns the lower right screen position of the currently visible and non-clipped space inside the currently processed window.
1274  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1275  *  Parameters:
1276  *      @ctx must point to an previously initialized `nk_context` struct
1277  *  Return values:
1278  *      returns `nk_vec2` struct with lower right screen position (no scrollbar offset) of the visible space inside the current window */
1279 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*);
1280 /*  nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1281  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1282  *  Parameters:
1283  *      @ctx must point to an previously initialized `nk_context` struct
1284  *  Return values:
1285  *      returns `nk_vec2` struct with size the visible space inside the current window */
1286 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*);
1287 /*  nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1288  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1289  *  Parameters:
1290  *      @ctx must point to an previously initialized `nk_context` struct
1291  *  Return values:
1292  *      returns a pointer to window internal `nk_command_buffer` struct used as drawing canvas. Can be used to do custom drawing */
1293 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*);
1294 /*  nk_window_has_focus - returns if the currently processed window is currently active
1295  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1296  *  Parameters:
1297  *      @ctx must point to an previously initialized `nk_context` struct
1298  *  Return values:
1299  *      returns 0 if current window is not active or 1 if it is */
1300 NK_API int nk_window_has_focus(const struct nk_context*);
1301 /*  nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1302  *  Parameters:
1303  *      @ctx must point to an previously initialized `nk_context` struct
1304  *      @name of window you want to check is collapsed
1305  *  Return values:
1306  *      returns 1 if current window is minimized and 0 if window not found or is not minimized */
1307 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1308 /*  nk_window_is_closed - returns if the window with given name was closed by calling `nk_close`
1309  *  Parameters:
1310  *      @ctx must point to an previously initialized `nk_context` struct
1311  *      @name of window you want to check is closed
1312  *  Return values:
1313  *      returns 1 if current window was closed or 0 window not found or not closed */
1314 NK_API int nk_window_is_closed(struct nk_context*, const char*);
1315 /*  nk_window_is_hidden - returns if the window with given name is hidden
1316  *  Parameters:
1317  *      @ctx must point to an previously initialized `nk_context` struct
1318  *      @name of window you want to check is hidden
1319  *  Return values:
1320  *      returns 1 if current window is hidden or 0 window not found or visible */
1321 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1322 /*  nk_window_is_active - same as nk_window_has_focus for some reason
1323  *  Parameters:
1324  *      @ctx must point to an previously initialized `nk_context` struct
1325  *      @name of window you want to check is hidden
1326  *  Return values:
1327  *      returns 1 if current window is active or 0 window not found or not active */
1328 NK_API int nk_window_is_active(struct nk_context*, const char*);
1329 /*  nk_window_is_hovered - return if the current window is being hovered
1330  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1331  *  Parameters:
1332  *      @ctx must point to an previously initialized `nk_context` struct
1333  *  Return values:
1334  *      returns 1 if current window is hovered or 0 otherwise */
1335 NK_API int nk_window_is_hovered(struct nk_context*);
1336 /*  nk_window_is_any_hovered - returns if the any window is being hovered
1337  *  Parameters:
1338  *      @ctx must point to an previously initialized `nk_context` struct
1339  *  Return values:
1340  *      returns 1 if any window is hovered or 0 otherwise */
1341 NK_API int nk_window_is_any_hovered(struct nk_context*);
1342 /*  nk_item_is_any_active - returns if the any window is being hovered or any widget is currently active.
1343  *  Can be used to decide if input should be processed by UI or your specific input handling.
1344  *  Example could be UI and 3D camera to move inside a 3D space.
1345  *  Parameters:
1346  *      @ctx must point to an previously initialized `nk_context` struct
1347  *  Return values:
1348  *      returns 1 if any window is hovered or any item is active or 0 otherwise */
1349 NK_API int nk_item_is_any_active(struct nk_context*);
1350 /*  nk_window_set_bounds - updates position and size of the currently processed window
1351  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1352  *  Parameters:
1353  *      @ctx must point to an previously initialized `nk_context` struct
1354  *      @name of the window to modify both position and size
1355  *      @bounds points to a `nk_rect` struct with the new position and size of currently active window */
1356 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
1357 /*  nk_window_set_position - updates position of the currently processed window
1358  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1359  *  Parameters:
1360  *      @ctx must point to an previously initialized `nk_context` struct
1361  *      @name of the window to modify position of
1362  *      @pos points to a `nk_vec2` struct with the new position of currently active window */
1363 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
1364 /*  nk_window_set_size - updates size of the currently processed window
1365  *  IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1366  *  Parameters:
1367  *      @ctx must point to an previously initialized `nk_context` struct
1368  *      @name of the window to modify size of
1369  *      @size points to a `nk_vec2` struct with the new size of currently active window */
1370 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
1371 /*  nk_window_set_focus - sets the window with given name as active
1372  *  Parameters:
1373  *      @ctx must point to an previously initialized `nk_context` struct
1374  *      @name of the window to be set active */
1375 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1376 /*  nk_window_close - closed a window and marks it for being freed at the end of the frame
1377  *  Parameters:
1378  *      @ctx must point to an previously initialized `nk_context` struct
1379  *      @name of the window to be closed */
1380 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1381 /*  nk_window_collapse - updates collapse state of a window with given name
1382  *  Parameters:
1383  *      @ctx must point to an previously initialized `nk_context` struct
1384  *      @name of the window to be either collapse or maximize */
1385 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1386 /*  nk_window_collapse - updates collapse state of a window with given name if given condition is met
1387  *  Parameters:
1388  *      @ctx must point to an previously initialized `nk_context` struct
1389  *      @name of the window to be either collapse or maximize
1390  *      @state the window should be put into
1391  *      @condition that has to be true to actually commit the collapse state change */
1392 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1393 /*  nk_window_show - updates visibility state of a window with given name
1394  *  Parameters:
1395  *      @ctx must point to an previously initialized `nk_context` struct
1396  *      @name of the window to be either collapse or maximize
1397  *      @state with either visible or hidden to modify the window with */
1398 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1399 /*  nk_window_show_if - updates visibility state of a window with given name if a given condition is met
1400  *  Parameters:
1401  *      @ctx must point to an previously initialized `nk_context` struct
1402  *      @name of the window to be either collapse or maximize
1403  *      @state with either visible or hidden to modify the window with
1404  *      @condition that has to be true to actually commit the visible state change */
1405 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1406 /* =============================================================================
1407  *
1408  *                                  LAYOUT
1409  *
1410  * ============================================================================= */
1411 /*  Layouting in general describes placing widget inside a window with position and size.
1412  *  While in this particular implementation there are five different APIs for layouting
1413  *  each with different trade offs between control and ease of use.
1414  *
1415  *  All layouting methods in this library are based around the concept of a row.
1416  *  A row has a height the window content grows by and a number of columns and each
1417  *  layouting method specifies how each widget is placed inside the row.
1418  *  After a row has been allocated by calling a layouting functions and then
1419  *  filled with widgets will advance an internal pointer over the allocated row.
1420  *
1421  *  To actually define a layout you just call the appropriate layouting function
1422  *  and each subsequent widget call will place the widget as specified. Important
1423  *  here is that if you define more widgets then columns defined inside the layout
1424  *  functions it will allocate the next row without you having to make another layouting
1425  *  call.
1426  *
1427  *  Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
1428  *  is that you have to define the row height for each. However the row height
1429  *  often depends on the height of the font.
1430  *
1431  *  To fix that internally nuklear uses a minimum row height that is set to the
1432  *  height plus padding of currently active font and overwrites the row height
1433  *  value if zero.
1434  *
1435  *  If you manually want to change the minimum row height then
1436  *  use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to
1437  *  reset it back to be derived from font height.
1438  *
1439  *  Also if you change the font in nuklear it will automatically change the minimum
1440  *  row height for you and. This means if you change the font but still want
1441  *  a minimum row height smaller than the font you have to repush your value.
1442  *
1443  *  For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
1444  *  layouting method in combination with a cassowary constraint solver (there are
1445  *  some versions on github with permissive license model) to take over all control over widget
1446  *  layouting yourself. However for quick and dirty layouting using all the other layouting
1447  *  functions should be fine.
1448  *
1449  *  Usage
1450  *  -------------------
1451  *  1.) nk_layout_row_dynamic
1452  *  The easiest layouting function is `nk_layout_row_dynamic`. It provides each
1453  *  widgets with same horizontal space inside the row and dynamically grows
1454  *  if the owning window grows in width. So the number of columns dictates
1455  *  the size of each widget dynamically by formula:
1456  *
1457  *      widget_width = (window_width - padding - spacing) * (1/colum_count)
1458  *
1459  *  Just like all other layouting APIs if you define more widget than columns this
1460  *  library will allocate a new row and keep all layouting parameters previously
1461  *  defined.
1462  *
1463  *      if (nk_begin_xxx(...) {
1464  *          // first row with height: 30 composed of two widgets
1465  *          nk_layout_row_dynamic(&ctx, 30, 2);
1466  *          nk_widget(...);
1467  *          nk_widget(...);
1468  *
1469  *          // second row with same parameter as defined above
1470  *          nk_widget(...);
1471  *          nk_widget(...);
1472  *
1473  *          // third row uses 0 for height which will use auto layouting
1474  *          nk_layout_row_dynamic(&ctx, 0, 2);
1475  *          nk_widget(...);
1476  *          nk_widget(...);
1477  *      }
1478  *      nk_end(...);
1479  *
1480  *  2.) nk_layout_row_static
1481  *  Another easy layouting function is `nk_layout_row_static`. It provides each
1482  *  widget with same horizontal pixel width inside the row and does not grow
1483  *  if the owning window scales smaller or bigger.
1484  *
1485  *      if (nk_begin_xxx(...) {
1486  *          // first row with height: 30 composed of two widgets with width: 80
1487  *          nk_layout_row_static(&ctx, 30, 80, 2);
1488  *          nk_widget(...);
1489  *          nk_widget(...);
1490  *
1491  *          // second row with same parameter as defined above
1492  *          nk_widget(...);
1493  *          nk_widget(...);
1494  *
1495  *          // third row uses 0 for height which will use auto layouting
1496  *          nk_layout_row_static(&ctx, 0, 80, 2);
1497  *          nk_widget(...);
1498  *          nk_widget(...);
1499  *      }
1500  *      nk_end(...);
1501  *
1502  *  3.) nk_layout_row_xxx
1503  *  A little bit more advanced layouting API are functions `nk_layout_row_begin`,
1504  *  `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
1505  *  specify each column pixel or window ratio in a row. It supports either
1506  *  directly setting per column pixel width or widget window ratio but not
1507  *  both. Furthermore it is a immediate mode API so each value is directly
1508  *  pushed before calling a widget. Therefore the layout is not automatically
1509  *  repeating like the last two layouting functions.
1510  *
1511  *      if (nk_begin_xxx(...) {
1512  *          // first row with height: 25 composed of two widgets with width 60 and 40
1513  *          nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
1514  *          nk_layout_row_push(ctx, 60);
1515  *          nk_widget(...);
1516  *          nk_layout_row_push(ctx, 40);
1517  *          nk_widget(...);
1518  *          nk_layout_row_end(ctx);
1519  *
1520  *          // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
1521  *          nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
1522  *          nk_layout_row_push(ctx, 0.25f);
1523  *          nk_widget(...);
1524  *          nk_layout_row_push(ctx, 0.75f);
1525  *          nk_widget(...);
1526  *          nk_layout_row_end(ctx);
1527  *
1528  *          // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75
1529  *          nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
1530  *          nk_layout_row_push(ctx, 0.25f);
1531  *          nk_widget(...);
1532  *          nk_layout_row_push(ctx, 0.75f);
1533  *          nk_widget(...);
1534  *          nk_layout_row_end(ctx);
1535  *      }
1536  *      nk_end(...);
1537  *
1538  *  4.) nk_layout_row
1539  *  The array counterpart to API nk_layout_row_xxx is the single nk_layout_row
1540  *  functions. Instead of pushing either pixel or window ratio for every widget
1541  *  it allows to define it by array. The trade of for less control is that
1542  *  `nk_layout_row` is automatically repeating. Otherwise the behavior is the
1543  *  same.
1544  *
1545  *      if (nk_begin_xxx(...) {
1546  *          // two rows with height: 30 composed of two widgets with width 60 and 40
1547  *          const float size[] = {60,40};
1548  *          nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
1549  *          nk_widget(...);
1550  *          nk_widget(...);
1551  *          nk_widget(...);
1552  *          nk_widget(...);
1553  *
1554  *          // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
1555  *          const float ratio[] = {0.25, 0.75};
1556  *          nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
1557  *          nk_widget(...);
1558  *          nk_widget(...);
1559  *          nk_widget(...);
1560  *          nk_widget(...);
1561  *
1562  *          // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75
1563  *          const float ratio[] = {0.25, 0.75};
1564  *          nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
1565  *          nk_widget(...);
1566  *          nk_widget(...);
1567  *          nk_widget(...);
1568  *          nk_widget(...);
1569  *      }
1570  *      nk_end(...);
1571  *
1572  *  5.) nk_layout_row_template_xxx
1573  *  The most complex and second most flexible API is a simplified flexbox version without
1574  *  line wrapping and weights for dynamic widgets. It is an immediate mode API but
1575  *  unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
1576  *  before calling the templated widgets.
1577  *  The row template layout has three different per widget size specifier. The first
1578  *  one is the static widget size specifier with fixed widget pixel width. They do
1579  *  not grow if the row grows and will always stay the same. The second size
1580  *  specifier is nk_layout_row_template_push_variable which defines a
1581  *  minimum widget size but it also can grow if more space is available not taken
1582  *  by other widgets. Finally there are dynamic widgets which are completely flexible
1583  *  and unlike variable widgets can even shrink to zero if not enough space
1584  *  is provided.
1585  *
1586  *      if (nk_begin_xxx(...) {
1587  *          // two rows with height: 30 composed of three widgets
1588  *          nk_layout_row_template_begin(ctx, 30);
1589  *          nk_layout_row_template_push_dynamic(ctx);
1590  *          nk_layout_row_template_push_variable(ctx, 80);
1591  *          nk_layout_row_template_push_static(ctx, 80);
1592  *          nk_layout_row_template_end(ctx);
1593  *
1594  *          nk_widget(...); // dynamic widget can go to zero if not enough space
1595  *          nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
1596  *          nk_widget(...); // static widget with fixed 80 pixel width
1597  *
1598  *          // second row same layout
1599  *          nk_widget(...);
1600  *          nk_widget(...);
1601  *          nk_widget(...);
1602  *      }
1603  *      nk_end(...);
1604  *
1605  *  6.) nk_layout_space_xxx
1606  *  Finally the most flexible API directly allows you to place widgets inside the
1607  *  window. The space layout API is an immediate mode API which does not support
1608  *  row auto repeat and directly sets position and size of a widget. Position
1609  *  and size hereby can be either specified as ratio of allocated space or
1610  *  allocated space local position and pixel size. Since this API is quite
1611  *  powerful there are a number of utility functions to get the available space
1612  *  and convert between local allocated space and screen space.
1613  *
1614  *      if (nk_begin_xxx(...) {
1615  *          // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1616  *          nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
1617  *          nk_layout_space_push(ctx, nk_rect(0,0,150,200));
1618  *          nk_widget(...);
1619  *          nk_layout_space_push(ctx, nk_rect(200,200,100,200));
1620  *          nk_widget(...);
1621  *          nk_layout_space_end(ctx);
1622  *
1623  *          // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1624  *          nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
1625  *          nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
1626  *          nk_widget(...);
1627  *          nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
1628  *          nk_widget(...);
1629  *      }
1630  *      nk_end(...);
1631  *
1632  *  Reference
1633  *  -------------------
1634  *  nk_layout_set_min_row_height            - set the currently used minimum row height to a specified value
1635  *  nk_layout_reset_min_row_height          - resets the currently used minimum row height to font height
1636  *
1637  *  nk_layout_widget_bounds                 - calculates current width a static layout row can fit inside a window
1638  *  nk_layout_ratio_from_pixel              - utility functions to calculate window ratio from pixel size
1639  *
1640  *  nk_layout_row_dynamic                   - current layout is divided into n same sized growing columns
1641  *  nk_layout_row_static                    - current layout is divided into n same fixed sized columns
1642  *  nk_layout_row_begin                     - starts a new row with given height and number of columns
1643  *  nk_layout_row_push                      - pushes another column with given size or window ratio
1644  *  nk_layout_row_end                       - finished previously started row
1645  *  nk_layout_row                           - specifies row columns in array as either window ratio or size
1646  *
1647  *  nk_layout_row_template_begin            - begins the row template declaration
1648  *  nk_layout_row_template_push_dynamic     - adds a dynamic column that dynamically grows and can go to zero if not enough space
1649  *  nk_layout_row_template_push_variable    - adds a variable column that dynamically grows but does not shrink below specified pixel width
1650  *  nk_layout_row_template_push_static      - adds a static column that does not grow and will always have the same size
1651  *  nk_layout_row_template_end              - marks the end of the row template
1652  *
1653  *  nk_layout_space_begin                   - begins a new layouting space that allows to specify each widgets position and size
1654  *  nk_layout_space_push                    - pushes position and size of the next widget in own coordinate space either as pixel or ratio
1655  *  nk_layout_space_end                     - marks the end of the layouting space
1656  *
1657  *  nk_layout_space_bounds                  - callable after nk_layout_space_begin and returns total space allocated
1658  *  nk_layout_space_to_screen               - converts vector from nk_layout_space coordinate space into screen space
1659  *  nk_layout_space_to_local                - converts vector from screen space into nk_layout_space coordinates
1660  *  nk_layout_space_rect_to_screen          - converts rectangle from nk_layout_space coordinate space into screen space
1661  *  nk_layout_space_rect_to_local           - converts rectangle from screen space into nk_layout_space coordinates
1662  */
1663 /*  nk_layout_set_min_row_height - sets the currently used minimum row height.
1664  *  IMPORTANT: The passed height needs to include both your preferred row height
1665  *  as well as padding. No internal padding is added.
1666  *  Parameters:
1667  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1668  *      @height new minimum row height to be used for auto generating the row height */
1669 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height);
1670 /*  nk_layout_reset_min_row_height - Reset the currently used minimum row height
1671  *  back to font height + text padding + additional padding (style_window.min_row_height_padding)
1672  *  Parameters:
1673  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` */
1674 NK_API void nk_layout_reset_min_row_height(struct nk_context*);
1675 /*  nk_layout_widget_bounds - returns the width of the next row allocate by one of the layouting functions
1676  *  Parameters:
1677  *      @ctx must point to an previously initialized `nk_context` */
1678 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*);
1679 /*  nk_layout_ratio_from_pixel - utility functions to calculate window ratio from pixel size
1680  *  Parameters:
1681  *      @ctx must point to an previously initialized `nk_context`
1682  *      @pixel_width to convert to window ratio */
1683 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
1684 /*  nk_layout_row_dynamic - Sets current row layout to share horizontal space
1685  *  between @cols number of widgets evenly. Once called all subsequent widget
1686  *  calls greater than @cols will allocate a new row with same layout.
1687  *  Parameters:
1688  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1689  *      @row_height holds height of each widget in row or zero for auto layouting
1690  *      @cols number of widget inside row */
1691 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
1692 /*  nk_layout_row_static - Sets current row layout to fill @cols number of widgets
1693  *  in row with same @item_width horizontal size. Once called all subsequent widget
1694  *  calls greater than @cols will allocate a new row with same layout.
1695  *  Parameters:
1696  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1697  *      @height holds row height to allocate from panel for widget height
1698  *      @item_width holds width of each widget in row
1699  *      @cols number of widget inside row */
1700 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
1701 /*  nk_layout_row_begin - Starts a new dynamic or fixed row with given height and columns.
1702  *  Parameters:
1703  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1704  *      @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1705  *      @row_height holds height of each widget in row or zero for auto layouting
1706  *      @cols number of widget inside row */
1707 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
1708 /*  nk_layout_row_push - Specifies either window ratio or width of a single column
1709  *  Parameters:
1710  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin`
1711  *      @value either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call */
1712 NK_API void nk_layout_row_push(struct nk_context*, float value);
1713 /*  nk_layout_row_end - finished previously started row
1714  *  Parameters:
1715  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin` */
1716 NK_API void nk_layout_row_end(struct nk_context*);
1717 /*  nk_layout_row - specifies row columns in array as either window ratio or size
1718  *  Parameters:
1719  *      @ctx must point to an previously initialized `nk_context`
1720  *      @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1721  *      @row_height holds height of each widget in row or zero for auto layouting
1722  *      @cols number of widget inside row */
1723 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
1724 /*  nk_layout_row_template_begin - Begins the row template declaration
1725  *  Parameters:
1726  *      @ctx must point to an previously initialized `nk_context` struct
1727  *      @row_height holds height of each widget in row or zero for auto layouting */
1728 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
1729 /*  nk_layout_row_template_push_dynamic - adds a dynamic column that dynamically grows and can go to zero if not enough space
1730  *  Parameters:
1731  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` */
1732 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*);
1733 /*  nk_layout_row_template_push_variable - adds a variable column that dynamically grows but does not shrink below specified pixel width
1734  *  Parameters:
1735  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin`
1736  *      @min_width holds the minimum pixel width the next column must be */
1737 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
1738 /*  nk_layout_row_template_push_static - adds a static column that does not grow and will always have the same size
1739  *  Parameters:
1740  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin`
1741  *      @width holds the absolute pixel width value the next column must be */
1742 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
1743 /*  nk_layout_row_template_end - marks the end of the row template
1744  *  Parameters:
1745  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` */
1746 NK_API void nk_layout_row_template_end(struct nk_context*);
1747 /*  nk_layout_space_begin - begins a new layouting space that allows to specify each widgets position and size.
1748  *  Parameters:
1749  *      @ctx must point to an previously initialized `nk_context` struct
1750  *      @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1751  *      @row_height holds height of each widget in row or zero for auto layouting
1752  *      @widget_count number of widgets inside row */
1753 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
1754 /*  nk_layout_space_push - pushes position and size of the next widget in own coordinate space either as pixel or ratio
1755  *  Parameters:
1756  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1757  *      @bounds position and size in laoyut space local coordinates */
1758 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect);
1759 /*  nk_layout_space_end - marks the end of the layout space
1760  *  Parameters:
1761  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` */
1762 NK_API void nk_layout_space_end(struct nk_context*);
1763 /*  nk_layout_space_bounds - returns total space allocated for `nk_layout_space`
1764  *  Parameters:
1765  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` */
1766 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*);
1767 /*  nk_layout_space_to_screen - converts vector from nk_layout_space coordinate space into screen space
1768  *  Parameters:
1769  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1770  *      @vec position to convert from layout space into screen coordinate space */
1771 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
1772 /*  nk_layout_space_to_screen - converts vector from layout space into screen space
1773  *  Parameters:
1774  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1775  *      @vec position to convert from screen space into layout coordinate space */
1776 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
1777 /*  nk_layout_space_rect_to_screen - converts rectangle from screen space into layout space
1778  *  Parameters:
1779  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1780  *      @bounds rectangle to convert from layout space into screen space */
1781 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
1782 /*  nk_layout_space_rect_to_local - converts rectangle from layout space into screen space
1783  *  Parameters:
1784  *      @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1785  *      @bounds rectangle to convert from screen space into layout space */
1786 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
1787 /* =============================================================================
1788  *
1789  *                                  GROUP
1790  *
1791  * ============================================================================= */
1792 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
1793 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char*, nk_flags);
1794 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll*, const char *title, nk_flags);
1795 NK_API void nk_group_scrolled_end(struct nk_context*);
1796 NK_API void nk_group_end(struct nk_context*);
1797 /* =============================================================================
1798  *
1799  *                                  LIST VIEW
1800  *
1801  * ============================================================================= */
1802 struct nk_list_view {
1803 /* public: */
1804     int begin, end, count;
1805 /* private: */
1806     int total_height;
1807     struct nk_context *ctx;
1808     nk_uint *scroll_pointer;
1809     nk_uint scroll_value;
1810 };
1811 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);
1812 NK_API void nk_list_view_end(struct nk_list_view*);
1813 /* =============================================================================
1814  *
1815  *                                  TREE
1816  *
1817  * ============================================================================= */
1818 #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__)
1819 #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)
1820 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);
1821 #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__)
1822 #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)
1823 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);
1824 NK_API void nk_tree_pop(struct nk_context*);
1825 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
1826 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);
1827 NK_API void nk_tree_state_pop(struct nk_context*);
1828 /* =============================================================================
1829  *
1830  *                                  WIDGET
1831  *
1832  * ============================================================================= */
1833 enum nk_widget_layout_states {
1834     NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
1835     NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
1836     NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
1837 };
1838 enum nk_widget_states {
1839     NK_WIDGET_STATE_MODIFIED    = NK_FLAG(1),
1840     NK_WIDGET_STATE_INACTIVE    = NK_FLAG(2), /* widget is neither active nor hovered */
1841     NK_WIDGET_STATE_ENTERED     = NK_FLAG(3), /* widget has been hovered on the current frame */
1842     NK_WIDGET_STATE_HOVER       = NK_FLAG(4), /* widget is being hovered */
1843     NK_WIDGET_STATE_ACTIVED     = NK_FLAG(5),/* widget is currently activated */
1844     NK_WIDGET_STATE_LEFT        = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
1845     NK_WIDGET_STATE_HOVERED     = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */
1846     NK_WIDGET_STATE_ACTIVE      = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */
1847 };
1848 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
1849 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2);
1850 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
1851 NK_API struct nk_vec2 nk_widget_position(struct nk_context*);
1852 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
1853 NK_API float nk_widget_width(struct nk_context*);
1854 NK_API float nk_widget_height(struct nk_context*);
1855 NK_API int nk_widget_is_hovered(struct nk_context*);
1856 NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons);
1857 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
1858 NK_API void nk_spacing(struct nk_context*, int cols);
1859 /* =============================================================================
1860  *
1861  *                                  TEXT
1862  *
1863  * ============================================================================= */
1864 enum nk_text_align {
1865     NK_TEXT_ALIGN_LEFT        = 0x01,
1866     NK_TEXT_ALIGN_CENTERED    = 0x02,
1867     NK_TEXT_ALIGN_RIGHT       = 0x04,
1868     NK_TEXT_ALIGN_TOP         = 0x08,
1869     NK_TEXT_ALIGN_MIDDLE      = 0x10,
1870     NK_TEXT_ALIGN_BOTTOM      = 0x20
1871 };
1872 enum nk_text_alignment {
1873     NK_TEXT_LEFT        = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT,
1874     NK_TEXT_CENTERED    = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED,
1875     NK_TEXT_RIGHT       = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT
1876 };
1877 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
1878 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
1879 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
1880 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
1881 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
1882 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
1883 NK_API void nk_label_wrap(struct nk_context*, const char*);
1884 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
1885 NK_API void nk_image(struct nk_context*, struct nk_image);
1886 #ifdef NK_INCLUDE_STANDARD_VARARGS
1887 NK_API void nk_labelf(struct nk_context*, nk_flags, const char*, ...);
1888 NK_API void nk_labelf_colored(struct nk_context*, nk_flags align, struct nk_color, const char*,...);
1889 NK_API void nk_labelf_wrap(struct nk_context*, const char*,...);
1890 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, const char*,...);
1891 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
1892 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
1893 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
1894 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
1895 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
1896 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
1897 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
1898 #endif
1899 /* =============================================================================
1900  *
1901  *                                  BUTTON
1902  *
1903  * ============================================================================= */
1904 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
1905 NK_API int nk_button_label(struct nk_context*, const char *title);
1906 NK_API int nk_button_color(struct nk_context*, struct nk_color);
1907 NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type);
1908 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
1909 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
1910 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1911 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
1912 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
1913 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
1914 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
1915 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
1916 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
1917 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);
1918 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);
1919 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);
1920 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);
1921 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior);
1922 NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior);
1923 NK_API int nk_button_pop_behavior(struct nk_context*);
1924 /* =============================================================================
1925  *
1926  *                                  CHECKBOX
1927  *
1928  * ============================================================================= */
1929 NK_API int nk_check_label(struct nk_context*, const char*, int active);
1930 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
1931 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
1932 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
1933 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
1934 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
1935 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
1936 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
1937 /* =============================================================================
1938  *
1939  *                                  RADIO BUTTON
1940  *
1941  * ============================================================================= */
1942 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
1943 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
1944 NK_API int nk_option_label(struct nk_context*, const char*, int active);
1945 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
1946 /* =============================================================================
1947  *
1948  *                                  SELECTABLE
1949  *
1950  * ============================================================================= */
1951 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
1952 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
1953 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image,  const char*, nk_flags align, int *value);
1954 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
1955 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
1956 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
1957 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
1958 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
1959 /* =============================================================================
1960  *
1961  *                                  SLIDER
1962  *
1963  * ============================================================================= */
1964 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
1965 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
1966 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
1967 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
1968 /* =============================================================================
1969  *
1970  *                                  PROGRESSBAR
1971  *
1972  * ============================================================================= */
1973 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
1974 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
1975 
1976 /* =============================================================================
1977  *
1978  *                                  COLOR PICKER
1979  *
1980  * ============================================================================= */
1981 NK_API struct nk_color nk_color_picker(struct nk_context*, struct nk_color, enum nk_color_format);
1982 NK_API int nk_color_pick(struct nk_context*, struct nk_color*, enum nk_color_format);
1983 /* =============================================================================
1984  *
1985  *                                  PROPERTIES
1986  *
1987  * ============================================================================= */
1988 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
1989 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
1990 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
1991 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
1992 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
1993 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
1994 /* =============================================================================
1995  *
1996  *                                  TEXT EDIT
1997  *
1998  * ============================================================================= */
1999 enum nk_edit_flags {
2000     NK_EDIT_DEFAULT                 = 0,
2001     NK_EDIT_READ_ONLY               = NK_FLAG(0),
2002     NK_EDIT_AUTO_SELECT             = NK_FLAG(1),
2003     NK_EDIT_SIG_ENTER               = NK_FLAG(2),
2004     NK_EDIT_ALLOW_TAB               = NK_FLAG(3),
2005     NK_EDIT_NO_CURSOR               = NK_FLAG(4),
2006     NK_EDIT_SELECTABLE              = NK_FLAG(5),
2007     NK_EDIT_CLIPBOARD               = NK_FLAG(6),
2008     NK_EDIT_CTRL_ENTER_NEWLINE      = NK_FLAG(7),
2009     NK_EDIT_NO_HORIZONTAL_SCROLL    = NK_FLAG(8),
2010     NK_EDIT_ALWAYS_INSERT_MODE      = NK_FLAG(9),
2011     NK_EDIT_MULTILINE               = NK_FLAG(10),
2012     NK_EDIT_GOTO_END_ON_ACTIVATE    = NK_FLAG(11)
2013 };
2014 enum nk_edit_types {
2015     NK_EDIT_SIMPLE  = NK_EDIT_ALWAYS_INSERT_MODE,
2016     NK_EDIT_FIELD   = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD,
2017     NK_EDIT_BOX     = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD,
2018     NK_EDIT_EDITOR  = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD
2019 };
2020 enum nk_edit_events {
2021     NK_EDIT_ACTIVE      = NK_FLAG(0), /* edit widget is currently being modified */
2022     NK_EDIT_INACTIVE    = NK_FLAG(1), /* edit widget is not active and is not being modified */
2023     NK_EDIT_ACTIVATED   = NK_FLAG(2), /* edit widget went from state inactive to state active */
2024     NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
2025     NK_EDIT_COMMITED    = NK_FLAG(4) /* edit widget has received an enter and lost focus */
2026 };
2027 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
2028 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
2029 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
2030 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
2031 NK_API void nk_edit_unfocus(struct nk_context*);
2032 /* =============================================================================
2033  *
2034  *                                  CHART
2035  *
2036  * ============================================================================= */
2037 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
2038 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);
2039 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
2040 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);
2041 NK_API nk_flags nk_chart_push(struct nk_context*, float);
2042 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
2043 NK_API void nk_chart_end(struct nk_context*);
2044 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
2045 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);
2046 /* =============================================================================
2047  *
2048  *                                  POPUP
2049  *
2050  * ============================================================================= */
2051 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
2052 NK_API void nk_popup_close(struct nk_context*);
2053 NK_API void nk_popup_end(struct nk_context*);
2054 /* =============================================================================
2055  *
2056  *                                  COMBOBOX
2057  *
2058  * ============================================================================= */
2059 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
2060 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);
2061 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);
2062 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);
2063 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
2064 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);
2065 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);
2066 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);
2067 /* =============================================================================
2068  *
2069  *                                  ABSTRACT COMBOBOX
2070  *
2071  * ============================================================================= */
2072 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
2073 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
2074 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
2075 NK_API int nk_combo_begin_symbol(struct nk_context*,  enum nk_symbol_type,  struct nk_vec2 size);
2076 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
2077 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
2078 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img,  struct nk_vec2 size);
2079 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
2080 NK_API int nk_combo_begin_image_text(struct nk_context*,  const char *selected, int, struct nk_image, struct nk_vec2 size);
2081 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
2082 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
2083 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2084 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
2085 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2086 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2087 NK_API void nk_combo_close(struct nk_context*);
2088 NK_API void nk_combo_end(struct nk_context*);
2089 /* =============================================================================
2090  *
2091  *                                  CONTEXTUAL
2092  *
2093  * ============================================================================= */
2094 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
2095 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
2096 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
2097 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2098 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
2099 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2100 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2101 NK_API void nk_contextual_close(struct nk_context*);
2102 NK_API void nk_contextual_end(struct nk_context*);
2103 /* =============================================================================
2104  *
2105  *                                  TOOLTIP
2106  *
2107  * ============================================================================= */
2108 NK_API void nk_tooltip(struct nk_context*, const char*);
2109 #ifdef NK_INCLUDE_STANDARD_VARARGS
2110 NK_API void nk_tooltipf(struct nk_context*, const char*, ...);
2111 #endif
2112 NK_API int nk_tooltip_begin(struct nk_context*, float width);
2113 NK_API void nk_tooltip_end(struct nk_context*);
2114 /* =============================================================================
2115  *
2116  *                                  MENU
2117  *
2118  * ============================================================================= */
2119 NK_API void nk_menubar_begin(struct nk_context*);
2120 NK_API void nk_menubar_end(struct nk_context*);
2121 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
2122 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
2123 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
2124 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
2125 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
2126 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
2127 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);
2128 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2129 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
2130 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
2131 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2132 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
2133 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2134 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2135 NK_API void nk_menu_close(struct nk_context*);
2136 NK_API void nk_menu_end(struct nk_context*);
2137 /* =============================================================================
2138  *
2139  *                                  STYLE
2140  *
2141  * ============================================================================= */
2142 enum nk_style_colors {
2143     NK_COLOR_TEXT,
2144     NK_COLOR_WINDOW,
2145     NK_COLOR_HEADER,
2146     NK_COLOR_BORDER,
2147     NK_COLOR_BUTTON,
2148     NK_COLOR_BUTTON_HOVER,
2149     NK_COLOR_BUTTON_ACTIVE,
2150     NK_COLOR_TOGGLE,
2151     NK_COLOR_TOGGLE_HOVER,
2152     NK_COLOR_TOGGLE_CURSOR,
2153     NK_COLOR_SELECT,
2154     NK_COLOR_SELECT_ACTIVE,
2155     NK_COLOR_SLIDER,
2156     NK_COLOR_SLIDER_CURSOR,
2157     NK_COLOR_SLIDER_CURSOR_HOVER,
2158     NK_COLOR_SLIDER_CURSOR_ACTIVE,
2159     NK_COLOR_PROPERTY,
2160     NK_COLOR_EDIT,
2161     NK_COLOR_EDIT_CURSOR,
2162     NK_COLOR_COMBO,
2163     NK_COLOR_CHART,
2164     NK_COLOR_CHART_COLOR,
2165     NK_COLOR_CHART_COLOR_HIGHLIGHT,
2166     NK_COLOR_SCROLLBAR,
2167     NK_COLOR_SCROLLBAR_CURSOR,
2168     NK_COLOR_SCROLLBAR_CURSOR_HOVER,
2169     NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,
2170     NK_COLOR_TAB_HEADER,
2171     NK_COLOR_COUNT
2172 };
2173 enum nk_style_cursor {
2174     NK_CURSOR_ARROW,
2175     NK_CURSOR_TEXT,
2176     NK_CURSOR_MOVE,
2177     NK_CURSOR_RESIZE_VERTICAL,
2178     NK_CURSOR_RESIZE_HORIZONTAL,
2179     NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT,
2180     NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT,
2181     NK_CURSOR_COUNT
2182 };
2183 NK_API void nk_style_default(struct nk_context*);
2184 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
2185 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
2186 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
2187 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors);
2188 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
2189 NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor);
2190 NK_API void nk_style_show_cursor(struct nk_context*);
2191 NK_API void nk_style_hide_cursor(struct nk_context*);
2192 
2193 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*);
2194 NK_API int nk_style_push_float(struct nk_context*, float*, float);
2195 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
2196 NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item);
2197 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
2198 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
2199 
2200 NK_API int nk_style_pop_font(struct nk_context*);
2201 NK_API int nk_style_pop_float(struct nk_context*);
2202 NK_API int nk_style_pop_vec2(struct nk_context*);
2203 NK_API int nk_style_pop_style_item(struct nk_context*);
2204 NK_API int nk_style_pop_flags(struct nk_context*);
2205 NK_API int nk_style_pop_color(struct nk_context*);
2206 /* =============================================================================
2207  *
2208  *                                  COLOR
2209  *
2210  * ============================================================================= */
2211 NK_API struct nk_color nk_rgb(int r, int g, int b);
2212 NK_API struct nk_color nk_rgb_iv(const int *rgb);
2213 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
2214 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
2215 NK_API struct nk_color nk_rgb_fv(const float *rgb);
2216 NK_API struct nk_color nk_rgb_hex(const char *rgb);
2217 
2218 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
2219 NK_API struct nk_color nk_rgba_u32(nk_uint);
2220 NK_API struct nk_color nk_rgba_iv(const int *rgba);
2221 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
2222 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
2223 NK_API struct nk_color nk_rgba_fv(const float *rgba);
2224 NK_API struct nk_color nk_rgba_hex(const char *rgb);
2225 
2226 NK_API struct nk_color nk_hsv(int h, int s, int v);
2227 NK_API struct nk_color nk_hsv_iv(const int *hsv);
2228 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
2229 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
2230 NK_API struct nk_color nk_hsv_fv(const float *hsv);
2231 
2232 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
2233 NK_API struct nk_color nk_hsva_iv(const int *hsva);
2234 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
2235 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
2236 NK_API struct nk_color nk_hsva_fv(const float *hsva);
2237 
2238 /* color (conversion nuklear --> user) */
2239 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
2240 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
2241 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
2242 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
2243 
2244 NK_API nk_uint nk_color_u32(struct nk_color);
2245 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
2246 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
2247 
2248 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
2249 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
2250 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
2251 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
2252 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
2253 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
2254 
2255 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
2256 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
2257 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
2258 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
2259 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
2260 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
2261 /* =============================================================================
2262  *
2263  *                                  IMAGE
2264  *
2265  * ============================================================================= */
2266 NK_API nk_handle nk_handle_ptr(void*);
2267 NK_API nk_handle nk_handle_id(int);
2268 NK_API struct nk_image nk_image_handle(nk_handle);
2269 NK_API struct nk_image nk_image_ptr(void*);
2270 NK_API struct nk_image nk_image_id(int);
2271 NK_API int nk_image_is_subimage(const struct nk_image* img);
2272 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
2273 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
2274 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
2275 /* =============================================================================
2276  *
2277  *                                  MATH
2278  *
2279  * ============================================================================= */
2280 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
2281 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
2282 
2283 NK_API struct nk_vec2 nk_vec2(float x, float y);
2284 NK_API struct nk_vec2 nk_vec2i(int x, int y);
2285 NK_API struct nk_vec2 nk_vec2v(const float *xy);
2286 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
2287 
2288 NK_API struct nk_rect nk_get_null_rect(void);
2289 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
2290 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
2291 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
2292 NK_API struct nk_rect nk_rectv(const float *xywh);
2293 NK_API struct nk_rect nk_rectiv(const int *xywh);
2294 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
2295 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
2296 /* =============================================================================
2297  *
2298  *                                  STRING
2299  *
2300  * ============================================================================= */
2301 NK_API int nk_strlen(const char *str);
2302 NK_API int nk_stricmp(const char *s1, const char *s2);
2303 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
2304 NK_API int nk_strtoi(const char *str, const char **endptr);
2305 NK_API float nk_strtof(const char *str, const char **endptr);
2306 NK_API double nk_strtod(const char *str, const char **endptr);
2307 NK_API int nk_strfilter(const char *text, const char *regexp);
2308 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
2309 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
2310 /* =============================================================================
2311  *
2312  *                                  UTF-8
2313  *
2314  * ============================================================================= */
2315 NK_API int nk_utf_decode(const char*, nk_rune*, int);
2316 NK_API int nk_utf_encode(nk_rune, char*, int);
2317 NK_API int nk_utf_len(const char*, int byte_len);
2318 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
2319 /* ===============================================================
2320  *
2321  *                          FONT
2322  *
2323  * ===============================================================*/
2324 /*  Font handling in this library was designed to be quite customizable and lets
2325     you decide what you want to use and what you want to provide. There are three
2326     different ways to use the font atlas. The first two will use your font
2327     handling scheme and only requires essential data to run nuklear. The next
2328     slightly more advanced features is font handling with vertex buffer output.
2329     Finally the most complex API wise is using nuklear's font baking API.
2330 
2331     1.) Using your own implementation without vertex buffer output
2332     --------------------------------------------------------------
2333     So first up the easiest way to do font handling is by just providing a
2334     `nk_user_font` struct which only requires the height in pixel of the used
2335     font and a callback to calculate the width of a string. This way of handling
2336     fonts is best fitted for using the normal draw shape command API where you
2337     do all the text drawing yourself and the library does not require any kind
2338     of deeper knowledge about which font handling mechanism you use.
2339     IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
2340     over the complete life time! I know this sucks but it is currently the only
2341     way to switch between fonts.
2342 
2343         float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2344         {
2345             your_font_type *type = handle.ptr;
2346             float text_width = ...;
2347             return text_width;
2348         }
2349 
2350         struct nk_user_font font;
2351         font.userdata.ptr = &your_font_class_or_struct;
2352         font.height = your_font_height;
2353         font.width = your_text_width_calculation;
2354 
2355         struct nk_context ctx;
2356         nk_init_default(&ctx, &font);
2357 
2358     2.) Using your own implementation with vertex buffer output
2359     --------------------------------------------------------------
2360     While the first approach works fine if you don't want to use the optional
2361     vertex buffer output it is not enough if you do. To get font handling working
2362     for these cases you have to provide two additional parameters inside the
2363     `nk_user_font`. First a texture atlas handle used to draw text as subimages
2364     of a bigger font atlas texture and a callback to query a character's glyph
2365     information (offset, size, ...). So it is still possible to provide your own
2366     font and use the vertex buffer output.
2367 
2368         float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2369         {
2370             your_font_type *type = handle.ptr;
2371             float text_width = ...;
2372             return text_width;
2373         }
2374         void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
2375         {
2376             your_font_type *type = handle.ptr;
2377             glyph.width = ...;
2378             glyph.height = ...;
2379             glyph.xadvance = ...;
2380             glyph.uv[0].x = ...;
2381             glyph.uv[0].y = ...;
2382             glyph.uv[1].x = ...;
2383             glyph.uv[1].y = ...;
2384             glyph.offset.x = ...;
2385             glyph.offset.y = ...;
2386         }
2387 
2388         struct nk_user_font font;
2389         font.userdata.ptr = &your_font_class_or_struct;
2390         font.height = your_font_height;
2391         font.width = your_text_width_calculation;
2392         font.query = query_your_font_glyph;
2393         font.texture.id = your_font_texture;
2394 
2395         struct nk_context ctx;
2396         nk_init_default(&ctx, &font);
2397 
2398     3.) Nuklear font baker
2399     ------------------------------------
2400     The final approach if you do not have a font handling functionality or don't
2401     want to use it in this library is by using the optional font baker.
2402     The font baker APIs can be used to create a font plus font atlas texture
2403     and can be used with or without the vertex buffer output.
2404 
2405     It still uses the `nk_user_font` struct and the two different approaches
2406     previously stated still work. The font baker is not located inside
2407     `nk_context` like all other systems since it can be understood as more of
2408     an extension to nuklear and does not really depend on any `nk_context` state.
2409 
2410     Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
2411     functions. If you don't care about memory just call the default version
2412     `nk_font_atlas_init_default` which will allocate all memory from the standard library.
2413     If you want to control memory allocation but you don't care if the allocated
2414     memory is temporary and therefore can be freed directly after the baking process
2415     is over or permanent you can call `nk_font_atlas_init`.
2416 
2417     After successfully initializing the font baker you can add Truetype(.ttf) fonts from
2418     different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
2419     functions. Adding font will permanently store each font, font config and ttf memory block(!)
2420     inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
2421     the font baker by for example adding additional fonts you can call
2422     `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
2423 
2424     As soon as you added all fonts you wanted you can now start the baking process
2425     for every selected glyph to image by calling `nk_font_atlas_bake`.
2426     The baking process returns image memory, width and height which can be used to
2427     either create your own image object or upload it to any graphics library.
2428     No matter which case you finally have to call `nk_font_atlas_end` which
2429     will free all temporary memory including the font atlas image so make sure
2430     you created our texture beforehand. `nk_font_atlas_end` requires a handle
2431     to your font texture or object and optionally fills a `struct nk_draw_null_texture`
2432     which can be used for the optional vertex output. If you don't want it just
2433     set the argument to `NULL`.
2434 
2435     At this point you are done and if you don't want to reuse the font atlas you
2436     can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
2437     memory. Finally if you don't use the font atlas and any of it's fonts anymore
2438     you need to call `nk_font_atlas_clear` to free all memory still being used.
2439 
2440         struct nk_font_atlas atlas;
2441         nk_font_atlas_init_default(&atlas);
2442         nk_font_atlas_begin(&atlas);
2443         nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
2444         nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
2445         const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
2446         nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
2447 
2448         struct nk_context ctx;
2449         nk_init_default(&ctx, &font->handle);
2450         while (1) {
2451 
2452         }
2453         nk_font_atlas_clear(&atlas);
2454 
2455     The font baker API is probably the most complex API inside this library and
2456     I would suggest reading some of my examples `example/` to get a grip on how
2457     to use the font atlas. There are a number of details I left out. For example
2458     how to merge fonts, configure a font with `nk_font_config` to use other languages,
2459     use another texture coordinate format and a lot more:
2460 
2461         struct nk_font_config cfg = nk_font_config(font_pixel_height);
2462         cfg.merge_mode = nk_false or nk_true;
2463         cfg.range = nk_font_korean_glyph_ranges();
2464         cfg.coord_type = NK_COORD_PIXEL;
2465         nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
2466 
2467 */
2468 struct nk_user_font_glyph;
2469 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
2470 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
2471                                     struct nk_user_font_glyph *glyph,
2472                                     nk_rune codepoint, nk_rune next_codepoint);
2473 
2474 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT)
2475 struct nk_user_font_glyph {
2476     struct nk_vec2 uv[2];
2477     /* texture coordinates */
2478     struct nk_vec2 offset;
2479     /* offset between top left and glyph */
2480     float width, height;
2481     /* size of the glyph  */
2482     float xadvance;
2483     /* offset to the next glyph */
2484 };
2485 #endif
2486 
2487 struct nk_user_font {
2488     nk_handle userdata;
2489     /* user provided font handle */
2490     float height;
2491     /* max height of the font */
2492     nk_text_width_f width;
2493     /* font string width in pixel callback */
2494 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2495     nk_query_font_glyph_f query;
2496     /* font glyph callback to query drawing info */
2497     nk_handle texture;
2498     /* texture handle to the used font atlas or texture */
2499 #endif
2500 };
2501 
2502 #ifdef NK_INCLUDE_FONT_BAKING
2503 enum nk_font_coord_type {
2504     NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
2505     NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
2506 };
2507 
2508 struct nk_font;
2509 struct nk_baked_font {
2510     float height;
2511     /* height of the font  */
2512     float ascent, descent;
2513     /* font glyphs ascent and descent  */
2514     nk_rune glyph_offset;
2515     /* glyph array offset inside the font glyph baking output array  */
2516     nk_rune glyph_count;
2517     /* number of glyphs of this font inside the glyph baking array output */
2518     const nk_rune *ranges;
2519     /* font codepoint ranges as pairs of (from/to) and 0 as last element */
2520 };
2521 
2522 struct nk_font_config {
2523     struct nk_font_config *next;
2524     /* NOTE: only used internally */
2525     void *ttf_blob;
2526     /* pointer to loaded TTF file memory block.
2527      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2528     nk_size ttf_size;
2529     /* size of the loaded TTF file memory block
2530      * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2531 
2532     unsigned char ttf_data_owned_by_atlas;
2533     /* used inside font atlas: default to: 0*/
2534     unsigned char merge_mode;
2535     /* merges this font into the last font */
2536     unsigned char pixel_snap;
2537     /* align every character to pixel boundary (if true set oversample (1,1)) */
2538     unsigned char oversample_v, oversample_h;
2539     /* rasterize at hight quality for sub-pixel position */
2540     unsigned char padding[3];
2541 
2542     float size;
2543     /* baked pixel height of the font */
2544     enum nk_font_coord_type coord_type;
2545     /* texture coordinate format with either pixel or UV coordinates */
2546     struct nk_vec2 spacing;
2547     /* extra pixel spacing between glyphs  */
2548     const nk_rune *range;
2549     /* list of unicode ranges (2 values per range, zero terminated) */
2550     struct nk_baked_font *font;
2551     /* font to setup in the baking process: NOTE: not needed for font atlas */
2552     nk_rune fallback_glyph;
2553     /* fallback glyph to use if a given rune is not found */
2554     struct nk_font_config *n;
2555     struct nk_font_config *p;
2556 };
2557 
2558 struct nk_font_glyph {
2559     nk_rune codepoint;
2560     float xadvance;
2561     float x0, y0, x1, y1, w, h;
2562     float u0, v0, u1, v1;
2563 };
2564 
2565 struct nk_font {
2566     struct nk_font *next;
2567     struct nk_user_font handle;
2568     struct nk_baked_font info;
2569     float scale;
2570     struct nk_font_glyph *glyphs;
2571     const struct nk_font_glyph *fallback;
2572     nk_rune fallback_codepoint;
2573     nk_handle texture;
2574     struct nk_font_config *config;
2575 };
2576 
2577 enum nk_font_atlas_format {
2578     NK_FONT_ATLAS_ALPHA8,
2579     NK_FONT_ATLAS_RGBA32
2580 };
2581 
2582 struct nk_font_atlas {
2583     void *pixel;
2584     int tex_width;
2585     int tex_height;
2586 
2587     struct nk_allocator permanent;
2588     struct nk_allocator temporary;
2589 
2590     struct nk_recti custom;
2591     struct nk_cursor cursors[NK_CURSOR_COUNT];
2592 
2593     int glyph_count;
2594     struct nk_font_glyph *glyphs;
2595     struct nk_font *default_font;
2596     struct nk_font *fonts;
2597     struct nk_font_config *config;
2598     int font_num;
2599 };
2600 
2601 /* some language glyph codepoint ranges */
2602 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
2603 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
2604 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
2605 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
2606 
2607 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2608 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
2609 #endif
2610 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
2611 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
2612 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
2613 NK_API struct nk_font_config nk_font_config(float pixel_height);
2614 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
2615 #ifdef NK_INCLUDE_DEFAULT_FONT
2616 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
2617 #endif
2618 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);
2619 #ifdef NK_INCLUDE_STANDARD_IO
2620 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*);
2621 #endif
2622 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*);
2623 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);
2624 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
2625 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
2626 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
2627 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
2628 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
2629 
2630 #endif
2631 
2632 /* ==============================================================
2633  *
2634  *                          MEMORY BUFFER
2635  *
2636  * ===============================================================*/
2637 /*  A basic (double)-buffer with linear allocation and resetting as only
2638     freeing policy. The buffer's main purpose is to control all memory management
2639     inside the GUI toolkit and still leave memory control as much as possible in
2640     the hand of the user while also making sure the library is easy to use if
2641     not as much control is needed.
2642     In general all memory inside this library can be provided from the user in
2643     three different ways.
2644 
2645     The first way and the one providing most control is by just passing a fixed
2646     size memory block. In this case all control lies in the hand of the user
2647     since he can exactly control where the memory comes from and how much memory
2648     the library should consume. Of course using the fixed size API removes the
2649     ability to automatically resize a buffer if not enough memory is provided so
2650     you have to take over the resizing. While being a fixed sized buffer sounds
2651     quite limiting, it is very effective in this library since the actual memory
2652     consumption is quite stable and has a fixed upper bound for a lot of cases.
2653 
2654     If you don't want to think about how much memory the library should allocate
2655     at all time or have a very dynamic UI with unpredictable memory consumption
2656     habits but still want control over memory allocation you can use the dynamic
2657     allocator based API. The allocator consists of two callbacks for allocating
2658     and freeing memory and optional userdata so you can plugin your own allocator.
2659 
2660     The final and easiest way can be used by defining
2661     NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
2662     allocation functions malloc and free and takes over complete control over
2663     memory in this library.
2664 */
2665 struct nk_memory_status {
2666     void *memory;
2667     unsigned int type;
2668     nk_size size;
2669     nk_size allocated;
2670     nk_size needed;
2671     nk_size calls;
2672 };
2673 
2674 enum nk_allocation_type {
2675     NK_BUFFER_FIXED,
2676     NK_BUFFER_DYNAMIC
2677 };
2678 
2679 enum nk_buffer_allocation_type {
2680     NK_BUFFER_FRONT,
2681     NK_BUFFER_BACK,
2682     NK_BUFFER_MAX
2683 };
2684 
2685 struct nk_buffer_marker {
2686     int active;
2687     nk_size offset;
2688 };
2689 
2690 struct nk_memory {void *ptr;nk_size size;};
2691 struct nk_buffer {
2692     struct nk_buffer_marker marker[NK_BUFFER_MAX];
2693     /* buffer marker to free a buffer to a certain offset */
2694     struct nk_allocator pool;
2695     /* allocator callback for dynamic buffers */
2696     enum nk_allocation_type type;
2697     /* memory management type */
2698     struct nk_memory memory;
2699     /* memory and size of the current memory block */
2700     float grow_factor;
2701     /* growing factor for dynamic memory management */
2702     nk_size allocated;
2703     /* total amount of memory allocated */
2704     nk_size needed;
2705     /* totally consumed memory given that enough memory is present */
2706     nk_size calls;
2707     /* number of allocation calls */
2708     nk_size size;
2709     /* current size of the buffer */
2710 };
2711 
2712 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2713 NK_API void nk_buffer_init_default(struct nk_buffer*);
2714 #endif
2715 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
2716 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
2717 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
2718 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
2719 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
2720 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type);
2721 NK_API void nk_buffer_clear(struct nk_buffer*);
2722 NK_API void nk_buffer_free(struct nk_buffer*);
2723 NK_API void *nk_buffer_memory(struct nk_buffer*);
2724 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
2725 NK_API nk_size nk_buffer_total(struct nk_buffer*);
2726 
2727 /* ==============================================================
2728  *
2729  *                          STRING
2730  *
2731  * ===============================================================*/
2732 /*  Basic string buffer which is only used in context with the text editor
2733  *  to manage and manipulate dynamic or fixed size string content. This is _NOT_
2734  *  the default string handling method. The only instance you should have any contact
2735  *  with this API is if you interact with an `nk_text_edit` object inside one of the
2736  *  copy and paste functions and even there only for more advanced cases. */
2737 struct nk_str {
2738     struct nk_buffer buffer;
2739     int len; /* in codepoints/runes/glyphs */
2740 };
2741 
2742 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2743 NK_API void nk_str_init_default(struct nk_str*);
2744 #endif
2745 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
2746 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
2747 NK_API void nk_str_clear(struct nk_str*);
2748 NK_API void nk_str_free(struct nk_str*);
2749 
2750 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
2751 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
2752 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
2753 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
2754 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
2755 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
2756 
2757 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
2758 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
2759 
2760 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
2761 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
2762 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
2763 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
2764 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
2765 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
2766 
2767 NK_API void nk_str_remove_chars(struct nk_str*, int len);
2768 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
2769 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
2770 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
2771 
2772 NK_API char *nk_str_at_char(struct nk_str*, int pos);
2773 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
2774 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
2775 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
2776 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
2777 
2778 NK_API char *nk_str_get(struct nk_str*);
2779 NK_API const char *nk_str_get_const(const struct nk_str*);
2780 NK_API int nk_str_len(struct nk_str*);
2781 NK_API int nk_str_len_char(struct nk_str*);
2782 
2783 /*===============================================================
2784  *
2785  *                      TEXT EDITOR
2786  *
2787  * ===============================================================*/
2788 /* Editing text in this library is handled by either `nk_edit_string` or
2789  * `nk_edit_buffer`. But like almost everything in this library there are multiple
2790  * ways of doing it and a balance between control and ease of use with memory
2791  * as well as functionality controlled by flags.
2792  *
2793  * This library generally allows three different levels of memory control:
2794  * First of is the most basic way of just providing a simple char array with
2795  * string length. This method is probably the easiest way of handling simple
2796  * user text input. Main upside is complete control over memory while the biggest
2797  * downside in comparison with the other two approaches is missing undo/redo.
2798  *
2799  * For UIs that require undo/redo the second way was created. It is based on
2800  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
2801  * This is mainly useful if you want something more like a text editor but don't want
2802  * to have a dynamically growing buffer.
2803  *
2804  * The final way is using a dynamically growing nk_text_edit struct, which
2805  * has both a default version if you don't care where memory comes from and an
2806  * allocator version if you do. While the text editor is quite powerful for its
2807  * complexity I would not recommend editing gigabytes of data with it.
2808  * It is rather designed for uses cases which make sense for a GUI library not for
2809  * an full blown text editor.
2810  */
2811 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
2812 #define NK_TEXTEDIT_UNDOSTATECOUNT     99
2813 #endif
2814 
2815 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
2816 #define NK_TEXTEDIT_UNDOCHARCOUNT      999
2817 #endif
2818 
2819 struct nk_text_edit;
2820 struct nk_clipboard {
2821     nk_handle userdata;
2822     nk_plugin_paste paste;
2823     nk_plugin_copy copy;
2824 };
2825 
2826 struct nk_text_undo_record {
2827    int where;
2828    short insert_length;
2829    short delete_length;
2830    short char_storage;
2831 };
2832 
2833 struct nk_text_undo_state {
2834    struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT];
2835    nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT];
2836    short undo_point;
2837    short redo_point;
2838    short undo_char_point;
2839    short redo_char_point;
2840 };
2841 
2842 enum nk_text_edit_type {
2843     NK_TEXT_EDIT_SINGLE_LINE,
2844     NK_TEXT_EDIT_MULTI_LINE
2845 };
2846 
2847 enum nk_text_edit_mode {
2848     NK_TEXT_EDIT_MODE_VIEW,
2849     NK_TEXT_EDIT_MODE_INSERT,
2850     NK_TEXT_EDIT_MODE_REPLACE
2851 };
2852 
2853 struct nk_text_edit {
2854     struct nk_clipboard clip;
2855     struct nk_str string;
2856     nk_plugin_filter filter;
2857     struct nk_vec2 scrollbar;
2858 
2859     int cursor;
2860     int select_start;
2861     int select_end;
2862     unsigned char mode;
2863     unsigned char cursor_at_end_of_line;
2864     unsigned char initialized;
2865     unsigned char has_preferred_x;
2866     unsigned char single_line;
2867     unsigned char active;
2868     unsigned char padding1;
2869     float preferred_x;
2870     struct nk_text_undo_state undo;
2871 };
2872 
2873 /* filter function */
2874 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
2875 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
2876 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
2877 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
2878 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
2879 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
2880 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
2881 
2882 /* text editor */
2883 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2884 NK_API void nk_textedit_init_default(struct nk_text_edit*);
2885 #endif
2886 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
2887 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
2888 NK_API void nk_textedit_free(struct nk_text_edit*);
2889 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
2890 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
2891 NK_API void nk_textedit_delete_selection(struct nk_text_edit*);
2892 NK_API void nk_textedit_select_all(struct nk_text_edit*);
2893 NK_API int nk_textedit_cut(struct nk_text_edit*);
2894 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
2895 NK_API void nk_textedit_undo(struct nk_text_edit*);
2896 NK_API void nk_textedit_redo(struct nk_text_edit*);
2897 
2898 /* ===============================================================
2899  *
2900  *                          DRAWING
2901  *
2902  * ===============================================================*/
2903 /*  This library was designed to be render backend agnostic so it does
2904     not draw anything to screen. Instead all drawn shapes, widgets
2905     are made of, are buffered into memory and make up a command queue.
2906     Each frame therefore fills the command buffer with draw commands
2907     that then need to be executed by the user and his own render backend.
2908     After that the command buffer needs to be cleared and a new frame can be
2909     started. It is probably important to note that the command buffer is the main
2910     drawing API and the optional vertex buffer API only takes this format and
2911     converts it into a hardware accessible format.
2912 
2913     To use the command queue to draw your own widgets you can access the
2914     command buffer of each window by calling `nk_window_get_canvas` after
2915     previously having called `nk_begin`:
2916 
2917         void draw_red_rectangle_widget(struct nk_context *ctx)
2918         {
2919             struct nk_command_buffer *canvas;
2920             struct nk_input *input = &ctx->input;
2921             canvas = nk_window_get_canvas(ctx);
2922 
2923             struct nk_rect space;
2924             enum nk_widget_layout_states state;
2925             state = nk_widget(&space, ctx);
2926             if (!state) return;
2927 
2928             if (state != NK_WIDGET_ROM)
2929                 update_your_widget_by_user_input(...);
2930             nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
2931         }
2932 
2933         if (nk_begin(...)) {
2934             nk_layout_row_dynamic(ctx, 25, 1);
2935             draw_red_rectangle_widget(ctx);
2936         }
2937         nk_end(..)
2938 
2939     Important to know if you want to create your own widgets is the `nk_widget`
2940     call. It allocates space on the panel reserved for this widget to be used,
2941     but also returns the state of the widget space. If your widget is not seen and does
2942     not have to be updated it is '0' and you can just return. If it only has
2943     to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
2944     update and draw your widget. The reason for separating is to only draw and
2945     update what is actually necessary which is crucial for performance.
2946 */
2947 enum nk_command_type {
2948     NK_COMMAND_NOP,
2949     NK_COMMAND_SCISSOR,
2950     NK_COMMAND_LINE,
2951     NK_COMMAND_CURVE,
2952     NK_COMMAND_RECT,
2953     NK_COMMAND_RECT_FILLED,
2954     NK_COMMAND_RECT_MULTI_COLOR,
2955     NK_COMMAND_CIRCLE,
2956     NK_COMMAND_CIRCLE_FILLED,
2957     NK_COMMAND_ARC,
2958     NK_COMMAND_ARC_FILLED,
2959     NK_COMMAND_TRIANGLE,
2960     NK_COMMAND_TRIANGLE_FILLED,
2961     NK_COMMAND_POLYGON,
2962     NK_COMMAND_POLYGON_FILLED,
2963     NK_COMMAND_POLYLINE,
2964     NK_COMMAND_TEXT,
2965     NK_COMMAND_IMAGE,
2966     NK_COMMAND_CUSTOM
2967 };
2968 
2969 /* command base and header of every command inside the buffer */
2970 struct nk_command {
2971     enum nk_command_type type;
2972     nk_size next;
2973 #ifdef NK_INCLUDE_COMMAND_USERDATA
2974     nk_handle userdata;
2975 #endif
2976 };
2977 
2978 struct nk_command_scissor {
2979     struct nk_command header;
2980     short x, y;
2981     unsigned short w, h;
2982 };
2983 
2984 struct nk_command_line {
2985     struct nk_command header;
2986     unsigned short line_thickness;
2987     struct nk_vec2i begin;
2988     struct nk_vec2i end;
2989     struct nk_color color;
2990 };
2991 
2992 struct nk_command_curve {
2993     struct nk_command header;
2994     unsigned short line_thickness;
2995     struct nk_vec2i begin;
2996     struct nk_vec2i end;
2997     struct nk_vec2i ctrl[2];
2998     struct nk_color color;
2999 };
3000 
3001 struct nk_command_rect {
3002     struct nk_command header;
3003     unsigned short rounding;
3004     unsigned short line_thickness;
3005     short x, y;
3006     unsigned short w, h;
3007     struct nk_color color;
3008 };
3009 
3010 struct nk_command_rect_filled {
3011     struct nk_command header;
3012     unsigned short rounding;
3013     short x, y;
3014     unsigned short w, h;
3015     struct nk_color color;
3016 };
3017 
3018 struct nk_command_rect_multi_color {
3019     struct nk_command header;
3020     short x, y;
3021     unsigned short w, h;
3022     struct nk_color left;
3023     struct nk_color top;
3024     struct nk_color bottom;
3025     struct nk_color right;
3026 };
3027 
3028 struct nk_command_triangle {
3029     struct nk_command header;
3030     unsigned short line_thickness;
3031     struct nk_vec2i a;
3032     struct nk_vec2i b;
3033     struct nk_vec2i c;
3034     struct nk_color color;
3035 };
3036 
3037 struct nk_command_triangle_filled {
3038     struct nk_command header;
3039     struct nk_vec2i a;
3040     struct nk_vec2i b;
3041     struct nk_vec2i c;
3042     struct nk_color color;
3043 };
3044 
3045 struct nk_command_circle {
3046     struct nk_command header;
3047     short x, y;
3048     unsigned short line_thickness;
3049     unsigned short w, h;
3050     struct nk_color color;
3051 };
3052 
3053 struct nk_command_circle_filled {
3054     struct nk_command header;
3055     short x, y;
3056     unsigned short w, h;
3057     struct nk_color color;
3058 };
3059 
3060 struct nk_command_arc {
3061     struct nk_command header;
3062     short cx, cy;
3063     unsigned short r;
3064     unsigned short line_thickness;
3065     float a[2];
3066     struct nk_color color;
3067 };
3068 
3069 struct nk_command_arc_filled {
3070     struct nk_command header;
3071     short cx, cy;
3072     unsigned short r;
3073     float a[2];
3074     struct nk_color color;
3075 };
3076 
3077 struct nk_command_polygon {
3078     struct nk_command header;
3079     struct nk_color color;
3080     unsigned short line_thickness;
3081     unsigned short point_count;
3082     struct nk_vec2i points[1];
3083 };
3084 
3085 struct nk_command_polygon_filled {
3086     struct nk_command header;
3087     struct nk_color color;
3088     unsigned short point_count;
3089     struct nk_vec2i points[1];
3090 };
3091 
3092 struct nk_command_polyline {
3093     struct nk_command header;
3094     struct nk_color color;
3095     unsigned short line_thickness;
3096     unsigned short point_count;
3097     struct nk_vec2i points[1];
3098 };
3099 
3100 struct nk_command_image {
3101     struct nk_command header;
3102     short x, y;
3103     unsigned short w, h;
3104     struct nk_image img;
3105     struct nk_color col;
3106 };
3107 
3108 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
3109     unsigned short w, unsigned short h, nk_handle callback_data);
3110 struct nk_command_custom {
3111     struct nk_command header;
3112     short x, y;
3113     unsigned short w, h;
3114     nk_handle callback_data;
3115     nk_command_custom_callback callback;
3116 };
3117 
3118 struct nk_command_text {
3119     struct nk_command header;
3120     const struct nk_user_font *font;
3121     struct nk_color background;
3122     struct nk_color foreground;
3123     short x, y;
3124     unsigned short w, h;
3125     float height;
3126     int length;
3127     char string[1];
3128 };
3129 
3130 enum nk_command_clipping {
3131     NK_CLIPPING_OFF = nk_false,
3132     NK_CLIPPING_ON = nk_true
3133 };
3134 
3135 struct nk_command_buffer {
3136     struct nk_buffer *base;
3137     struct nk_rect clip;
3138     int use_clipping;
3139     nk_handle userdata;
3140     nk_size begin, end, last;
3141 };
3142 
3143 /* shape outlines */
3144 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);
3145 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
3146 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
3147 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
3148 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);
3149 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
3150 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
3151 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
3152 
3153 /* filled shades */
3154 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
3155 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);
3156 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
3157 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);
3158 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);
3159 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
3160 
3161 /* misc */
3162 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
3163 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);
3164 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
3165 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
3166 
3167 /* ===============================================================
3168  *
3169  *                          INPUT
3170  *
3171  * ===============================================================*/
3172 struct nk_mouse_button {
3173     int down;
3174     unsigned int clicked;
3175     struct nk_vec2 clicked_pos;
3176 };
3177 struct nk_mouse {
3178     struct nk_mouse_button buttons[NK_BUTTON_MAX];
3179     struct nk_vec2 pos;
3180     struct nk_vec2 prev;
3181     struct nk_vec2 delta;
3182     struct nk_vec2 scroll_delta;
3183     unsigned char grab;
3184     unsigned char grabbed;
3185     unsigned char ungrab;
3186 };
3187 
3188 struct nk_key {
3189     int down;
3190     unsigned int clicked;
3191 };
3192 struct nk_keyboard {
3193     struct nk_key keys[NK_KEY_MAX];
3194     char text[NK_INPUT_MAX];
3195     int text_len;
3196 };
3197 
3198 struct nk_input {
3199     struct nk_keyboard keyboard;
3200     struct nk_mouse mouse;
3201 };
3202 
3203 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
3204 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3205 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
3206 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3207 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);
3208 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
3209 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
3210 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
3211 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
3212 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
3213 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
3214 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
3215 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
3216 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
3217 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
3218 
3219 /* ===============================================================
3220  *
3221  *                          DRAW LIST
3222  *
3223  * ===============================================================*/
3224 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3225 /*  The optional vertex buffer draw list provides a 2D drawing context
3226     with antialiasing functionality which takes basic filled or outlined shapes
3227     or a path and outputs vertexes, elements and draw commands.
3228     The actual draw list API is not required to be used directly while using this
3229     library since converting the default library draw command output is done by
3230     just calling `nk_convert` but I decided to still make this library accessible
3231     since it can be useful.
3232 
3233     The draw list is based on a path buffering and polygon and polyline
3234     rendering API which allows a lot of ways to draw 2D content to screen.
3235     In fact it is probably more powerful than needed but allows even more crazy
3236     things than this library provides by default.
3237 */
3238 typedef nk_ushort nk_draw_index;
3239 enum nk_draw_list_stroke {
3240     NK_STROKE_OPEN = nk_false,
3241     /* build up path has no connection back to the beginning */
3242     NK_STROKE_CLOSED = nk_true
3243     /* build up path has a connection back to the beginning */
3244 };
3245 
3246 enum nk_draw_vertex_layout_attribute {
3247     NK_VERTEX_POSITION,
3248     NK_VERTEX_COLOR,
3249     NK_VERTEX_TEXCOORD,
3250     NK_VERTEX_ATTRIBUTE_COUNT
3251 };
3252 
3253 enum nk_draw_vertex_layout_format {
3254     NK_FORMAT_SCHAR,
3255     NK_FORMAT_SSHORT,
3256     NK_FORMAT_SINT,
3257     NK_FORMAT_UCHAR,
3258     NK_FORMAT_USHORT,
3259     NK_FORMAT_UINT,
3260     NK_FORMAT_FLOAT,
3261     NK_FORMAT_DOUBLE,
3262 
3263 NK_FORMAT_COLOR_BEGIN,
3264     NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
3265     NK_FORMAT_R16G15B16,
3266     NK_FORMAT_R32G32B32,
3267 
3268     NK_FORMAT_R8G8B8A8,
3269     NK_FORMAT_B8G8R8A8,
3270     NK_FORMAT_R16G15B16A16,
3271     NK_FORMAT_R32G32B32A32,
3272     NK_FORMAT_R32G32B32A32_FLOAT,
3273     NK_FORMAT_R32G32B32A32_DOUBLE,
3274 
3275     NK_FORMAT_RGB32,
3276     NK_FORMAT_RGBA32,
3277 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
3278     NK_FORMAT_COUNT
3279 };
3280 
3281 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
3282 struct nk_draw_vertex_layout_element {
3283     enum nk_draw_vertex_layout_attribute attribute;
3284     enum nk_draw_vertex_layout_format format;
3285     nk_size offset;
3286 };
3287 
3288 struct nk_draw_command {
3289     unsigned int elem_count;
3290     /* number of elements in the current draw batch */
3291     struct nk_rect clip_rect;
3292     /* current screen clipping rectangle */
3293     nk_handle texture;
3294     /* current texture to set */
3295 #ifdef NK_INCLUDE_COMMAND_USERDATA
3296     nk_handle userdata;
3297 #endif
3298 };
3299 
3300 struct nk_draw_list {
3301     struct nk_rect clip_rect;
3302     struct nk_vec2 circle_vtx[12];
3303     struct nk_convert_config config;
3304 
3305     struct nk_buffer *buffer;
3306     struct nk_buffer *vertices;
3307     struct nk_buffer *elements;
3308 
3309     unsigned int element_count;
3310     unsigned int vertex_count;
3311     unsigned int cmd_count;
3312     nk_size cmd_offset;
3313 
3314     unsigned int path_count;
3315     unsigned int path_offset;
3316 
3317     enum nk_anti_aliasing line_AA;
3318     enum nk_anti_aliasing shape_AA;
3319 
3320 #ifdef NK_INCLUDE_COMMAND_USERDATA
3321     nk_handle userdata;
3322 #endif
3323 };
3324 
3325 /* draw list */
3326 NK_API void nk_draw_list_init(struct nk_draw_list*);
3327 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);
3328 NK_API void nk_draw_list_clear(struct nk_draw_list*);
3329 
3330 /* drawing */
3331 #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))
3332 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
3333 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*);
3334 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
3335 NK_API void nk_draw_list_clear(struct nk_draw_list *list);
3336 
3337 /* path */
3338 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
3339 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
3340 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);
3341 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);
3342 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
3343 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);
3344 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
3345 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
3346 
3347 /* stroke */
3348 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);
3349 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
3350 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);
3351 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);
3352 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);
3353 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);
3354 
3355 /* fill */
3356 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
3357 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);
3358 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);
3359 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);
3360 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);
3361 
3362 /* misc */
3363 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
3364 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);
3365 #ifdef NK_INCLUDE_COMMAND_USERDATA
3366 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
3367 #endif
3368 
3369 #endif
3370 
3371 /* ===============================================================
3372  *
3373  *                          GUI
3374  *
3375  * ===============================================================*/
3376 enum nk_style_item_type {
3377     NK_STYLE_ITEM_COLOR,
3378     NK_STYLE_ITEM_IMAGE
3379 };
3380 
3381 union nk_style_item_data {
3382     struct nk_image image;
3383     struct nk_color color;
3384 };
3385 
3386 struct nk_style_item {
3387     enum nk_style_item_type type;
3388     union nk_style_item_data data;
3389 };
3390 
3391 struct nk_style_text {
3392     struct nk_color color;
3393     struct nk_vec2 padding;
3394 };
3395 
3396 struct nk_style_button {
3397     /* background */
3398     struct nk_style_item normal;
3399     struct nk_style_item hover;
3400     struct nk_style_item active;
3401     struct nk_color border_color;
3402 
3403     /* text */
3404     struct nk_color text_background;
3405     struct nk_color text_normal;
3406     struct nk_color text_hover;
3407     struct nk_color text_active;
3408     nk_flags text_alignment;
3409 
3410     /* properties */
3411     float border;
3412     float rounding;
3413     struct nk_vec2 padding;
3414     struct nk_vec2 image_padding;
3415     struct nk_vec2 touch_padding;
3416 
3417     /* optional user callbacks */
3418     nk_handle userdata;
3419     void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata);
3420     void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
3421 };
3422 
3423 struct nk_style_toggle {
3424     /* background */
3425     struct nk_style_item normal;
3426     struct nk_style_item hover;
3427     struct nk_style_item active;
3428     struct nk_color border_color;
3429 
3430     /* cursor */
3431     struct nk_style_item cursor_normal;
3432     struct nk_style_item cursor_hover;
3433 
3434     /* text */
3435     struct nk_color text_normal;
3436     struct nk_color text_hover;
3437     struct nk_color text_active;
3438     struct nk_color text_background;
3439     nk_flags text_alignment;
3440 
3441     /* properties */
3442     struct nk_vec2 padding;
3443     struct nk_vec2 touch_padding;
3444     float spacing;
3445     float border;
3446 
3447     /* optional user callbacks */
3448     nk_handle userdata;
3449     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3450     void(*draw_end)(struct nk_command_buffer*, nk_handle);
3451 };
3452 
3453 struct nk_style_selectable {
3454     /* background (inactive) */
3455     struct nk_style_item normal;
3456     struct nk_style_item hover;
3457     struct nk_style_item pressed;
3458 
3459     /* background (active) */
3460     struct nk_style_item normal_active;
3461     struct nk_style_item hover_active;
3462     struct nk_style_item pressed_active;
3463 
3464     /* text color (inactive) */
3465     struct nk_color text_normal;
3466     struct nk_color text_hover;
3467     struct nk_color text_pressed;
3468 
3469     /* text color (active) */
3470     struct nk_color text_normal_active;
3471     struct nk_color text_hover_active;
3472     struct nk_color text_pressed_active;
3473     struct nk_color text_background;
3474     nk_flags text_alignment;
3475 
3476     /* properties */
3477     float rounding;
3478     struct nk_vec2 padding;
3479     struct nk_vec2 touch_padding;
3480     struct nk_vec2 image_padding;
3481 
3482     /* optional user callbacks */
3483     nk_handle userdata;
3484     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3485     void(*draw_end)(struct nk_command_buffer*, nk_handle);
3486 };
3487 
3488 struct nk_style_slider {
3489     /* background */
3490     struct nk_style_item normal;
3491     struct nk_style_item hover;
3492     struct nk_style_item active;
3493     struct nk_color border_color;
3494 
3495     /* background bar */
3496     struct nk_color bar_normal;
3497     struct nk_color bar_hover;
3498     struct nk_color bar_active;
3499     struct nk_color bar_filled;
3500 
3501     /* cursor */
3502     struct nk_style_item cursor_normal;
3503     struct nk_style_item cursor_hover;
3504     struct nk_style_item cursor_active;
3505 
3506     /* properties */
3507     float border;
3508     float rounding;
3509     float bar_height;
3510     struct nk_vec2 padding;
3511     struct nk_vec2 spacing;
3512     struct nk_vec2 cursor_size;
3513 
3514     /* optional buttons */
3515     int show_buttons;
3516     struct nk_style_button inc_button;
3517     struct nk_style_button dec_button;
3518     enum nk_symbol_type inc_symbol;
3519     enum nk_symbol_type dec_symbol;
3520 
3521     /* optional user callbacks */
3522     nk_handle userdata;
3523     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3524     void(*draw_end)(struct nk_command_buffer*, nk_handle);
3525 };
3526 
3527 struct nk_style_progress {
3528     /* background */
3529     struct nk_style_item normal;
3530     struct nk_style_item hover;
3531     struct nk_style_item active;
3532     struct nk_color border_color;
3533 
3534     /* cursor */
3535     struct nk_style_item cursor_normal;
3536     struct nk_style_item cursor_hover;
3537     struct nk_style_item cursor_active;
3538     struct nk_color cursor_border_color;
3539 
3540     /* properties */
3541     float rounding;
3542     float border;
3543     float cursor_border;
3544     float cursor_rounding;
3545     struct nk_vec2 padding;
3546 
3547     /* optional user callbacks */
3548     nk_handle userdata;
3549     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3550     void(*draw_end)(struct nk_command_buffer*, nk_handle);
3551 };
3552 
3553 struct nk_style_scrollbar {
3554     /* background */
3555     struct nk_style_item normal;
3556     struct nk_style_item hover;
3557     struct nk_style_item active;
3558     struct nk_color border_color;
3559 
3560     /* cursor */
3561     struct nk_style_item cursor_normal;
3562     struct nk_style_item cursor_hover;
3563     struct nk_style_item cursor_active;
3564     struct nk_color cursor_border_color;
3565 
3566     /* properties */
3567     float border;
3568     float rounding;
3569     float border_cursor;
3570     float rounding_cursor;
3571     struct nk_vec2 padding;
3572 
3573     /* optional buttons */
3574     int show_buttons;
3575     struct nk_style_button inc_button;
3576     struct nk_style_button dec_button;
3577     enum nk_symbol_type inc_symbol;
3578     enum nk_symbol_type dec_symbol;
3579 
3580     /* optional user callbacks */
3581     nk_handle userdata;
3582     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3583     void(*draw_end)(struct nk_command_buffer*, nk_handle);
3584 };
3585 
3586 struct nk_style_edit {
3587     /* background */
3588     struct nk_style_item normal;
3589     struct nk_style_item hover;
3590     struct nk_style_item active;
3591     struct nk_color border_color;
3592     struct nk_style_scrollbar scrollbar;
3593 
3594     /* cursor  */
3595     struct nk_color cursor_normal;
3596     struct nk_color cursor_hover;
3597     struct nk_color cursor_text_normal;
3598     struct nk_color cursor_text_hover;
3599 
3600     /* text (unselected) */
3601     struct nk_color text_normal;
3602     struct nk_color text_hover;
3603     struct nk_color text_active;
3604 
3605     /* text (selected) */
3606     struct nk_color selected_normal;
3607     struct nk_color selected_hover;
3608     struct nk_color selected_text_normal;
3609     struct nk_color selected_text_hover;
3610 
3611     /* properties */
3612     float border;
3613     float rounding;
3614     float cursor_size;
3615     struct nk_vec2 scrollbar_size;
3616     struct nk_vec2 padding;
3617     float row_padding;
3618 };
3619 
3620 struct nk_style_property {
3621     /* background */
3622     struct nk_style_item normal;
3623     struct nk_style_item hover;
3624     struct nk_style_item active;
3625     struct nk_color border_color;
3626 
3627     /* text */
3628     struct nk_color label_normal;
3629     struct nk_color label_hover;
3630     struct nk_color label_active;
3631 
3632     /* symbols */
3633     enum nk_symbol_type sym_left;
3634     enum nk_symbol_type sym_right;
3635 
3636     /* properties */
3637     float border;
3638     float rounding;
3639     struct nk_vec2 padding;
3640 
3641     struct nk_style_edit edit;
3642     struct nk_style_button inc_button;
3643     struct nk_style_button dec_button;
3644 
3645     /* optional user callbacks */
3646     nk_handle userdata;
3647     void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3648     void(*draw_end)(struct nk_command_buffer*, nk_handle);
3649 };
3650 
3651 struct nk_style_chart {
3652     /* colors */
3653     struct nk_style_item background;
3654     struct nk_color border_color;
3655     struct nk_color selected_color;
3656     struct nk_color color;
3657 
3658     /* properties */
3659     float border;
3660     float rounding;
3661     struct nk_vec2 padding;
3662 };
3663 
3664 struct nk_style_combo {
3665     /* background */
3666     struct nk_style_item normal;
3667     struct nk_style_item hover;
3668     struct nk_style_item active;
3669     struct nk_color border_color;
3670 
3671     /* label */
3672     struct nk_color label_normal;
3673     struct nk_color label_hover;
3674     struct nk_color label_active;
3675 
3676     /* symbol */
3677     struct nk_color symbol_normal;
3678     struct nk_color symbol_hover;
3679     struct nk_color symbol_active;
3680 
3681     /* button */
3682     struct nk_style_button button;
3683     enum nk_symbol_type sym_normal;
3684     enum nk_symbol_type sym_hover;
3685     enum nk_symbol_type sym_active;
3686 
3687     /* properties */
3688     float border;
3689     float rounding;
3690     struct nk_vec2 content_padding;
3691     struct nk_vec2 button_padding;
3692     struct nk_vec2 spacing;
3693 };
3694 
3695 struct nk_style_tab {
3696     /* background */
3697     struct nk_style_item background;
3698     struct nk_color border_color;
3699     struct nk_color text;
3700 
3701     /* button */
3702     struct nk_style_button tab_maximize_button;
3703     struct nk_style_button tab_minimize_button;
3704     struct nk_style_button node_maximize_button;
3705     struct nk_style_button node_minimize_button;
3706     enum nk_symbol_type sym_minimize;
3707     enum nk_symbol_type sym_maximize;
3708 
3709     /* properties */
3710     float border;
3711     float rounding;
3712     float indent;
3713     struct nk_vec2 padding;
3714     struct nk_vec2 spacing;
3715 };
3716 
3717 enum nk_style_header_align {
3718     NK_HEADER_LEFT,
3719     NK_HEADER_RIGHT
3720 };
3721 struct nk_style_window_header {
3722     /* background */
3723     struct nk_style_item normal;
3724     struct nk_style_item hover;
3725     struct nk_style_item active;
3726 
3727     /* button */
3728     struct nk_style_button close_button;
3729     struct nk_style_button minimize_button;
3730     enum nk_symbol_type close_symbol;
3731     enum nk_symbol_type minimize_symbol;
3732     enum nk_symbol_type maximize_symbol;
3733 
3734     /* title */
3735     struct nk_color label_normal;
3736     struct nk_color label_hover;
3737     struct nk_color label_active;
3738 
3739     /* properties */
3740     enum nk_style_header_align align;
3741     struct nk_vec2 padding;
3742     struct nk_vec2 label_padding;
3743     struct nk_vec2 spacing;
3744 };
3745 
3746 struct nk_style_window {
3747     struct nk_style_window_header header;
3748     struct nk_style_item fixed_background;
3749     struct nk_color background;
3750 
3751     struct nk_color border_color;
3752     struct nk_color popup_border_color;
3753     struct nk_color combo_border_color;
3754     struct nk_color contextual_border_color;
3755     struct nk_color menu_border_color;
3756     struct nk_color group_border_color;
3757     struct nk_color tooltip_border_color;
3758     struct nk_style_item scaler;
3759 
3760     float border;
3761     float combo_border;
3762     float contextual_border;
3763     float menu_border;
3764     float group_border;
3765     float tooltip_border;
3766     float popup_border;
3767     float min_row_height_padding;
3768 
3769     float rounding;
3770     struct nk_vec2 spacing;
3771     struct nk_vec2 scrollbar_size;
3772     struct nk_vec2 min_size;
3773 
3774     struct nk_vec2 padding;
3775     struct nk_vec2 group_padding;
3776     struct nk_vec2 popup_padding;
3777     struct nk_vec2 combo_padding;
3778     struct nk_vec2 contextual_padding;
3779     struct nk_vec2 menu_padding;
3780     struct nk_vec2 tooltip_padding;
3781 };
3782 
3783 struct nk_style {
3784     const struct nk_user_font *font;
3785     const struct nk_cursor *cursors[NK_CURSOR_COUNT];
3786     const struct nk_cursor *cursor_active;
3787     struct nk_cursor *cursor_last;
3788     int cursor_visible;
3789 
3790     struct nk_style_text text;
3791     struct nk_style_button button;
3792     struct nk_style_button contextual_button;
3793     struct nk_style_button menu_button;
3794     struct nk_style_toggle option;
3795     struct nk_style_toggle checkbox;
3796     struct nk_style_selectable selectable;
3797     struct nk_style_slider slider;
3798     struct nk_style_progress progress;
3799     struct nk_style_property property;
3800     struct nk_style_edit edit;
3801     struct nk_style_chart chart;
3802     struct nk_style_scrollbar scrollh;
3803     struct nk_style_scrollbar scrollv;
3804     struct nk_style_tab tab;
3805     struct nk_style_combo combo;
3806     struct nk_style_window window;
3807 };
3808 
3809 NK_API struct nk_style_item nk_style_item_image(struct nk_image img);
3810 NK_API struct nk_style_item nk_style_item_color(struct nk_color);
3811 NK_API struct nk_style_item nk_style_item_hide(void);
3812 
3813 /*==============================================================
3814  *                          PANEL
3815  * =============================================================*/
3816 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
3817 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
3818 #endif
3819 #ifndef NK_CHART_MAX_SLOT
3820 #define NK_CHART_MAX_SLOT 4
3821 #endif
3822 
3823 enum nk_panel_type {
3824     NK_PANEL_WINDOW     = NK_FLAG(0),
3825     NK_PANEL_GROUP      = NK_FLAG(1),
3826     NK_PANEL_POPUP      = NK_FLAG(2),
3827     NK_PANEL_CONTEXTUAL = NK_FLAG(4),
3828     NK_PANEL_COMBO      = NK_FLAG(5),
3829     NK_PANEL_MENU       = NK_FLAG(6),
3830     NK_PANEL_TOOLTIP    = NK_FLAG(7)
3831 };
3832 enum nk_panel_set {
3833     NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP,
3834     NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP,
3835     NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP
3836 };
3837 
3838 struct nk_chart_slot {
3839     enum nk_chart_type type;
3840     struct nk_color color;
3841     struct nk_color highlight;
3842     float min, max, range;
3843     int count;
3844     struct nk_vec2 last;
3845     int index;
3846 };
3847 
3848 struct nk_chart {
3849     int slot;
3850     float x, y, w, h;
3851     struct nk_chart_slot slots[NK_CHART_MAX_SLOT];
3852 };
3853 
3854 enum nk_panel_row_layout_type {
3855     NK_LAYOUT_DYNAMIC_FIXED = 0,
3856     NK_LAYOUT_DYNAMIC_ROW,
3857     NK_LAYOUT_DYNAMIC_FREE,
3858     NK_LAYOUT_DYNAMIC,
3859     NK_LAYOUT_STATIC_FIXED,
3860     NK_LAYOUT_STATIC_ROW,
3861     NK_LAYOUT_STATIC_FREE,
3862     NK_LAYOUT_STATIC,
3863     NK_LAYOUT_TEMPLATE,
3864     NK_LAYOUT_COUNT
3865 };
3866 struct nk_row_layout {
3867     enum nk_panel_row_layout_type type;
3868     int index;
3869     float height;
3870     float min_height;
3871     int columns;
3872     const float *ratio;
3873     float item_width;
3874     float item_height;
3875     float item_offset;
3876     float filled;
3877     struct nk_rect item;
3878     int tree_depth;
3879     float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS];
3880 };
3881 
3882 struct nk_popup_buffer {
3883     nk_size begin;
3884     nk_size parent;
3885     nk_size last;
3886     nk_size end;
3887     int active;
3888 };
3889 
3890 struct nk_menu_state {
3891     float x, y, w, h;
3892     struct nk_scroll offset;
3893 };
3894 
3895 struct nk_panel {
3896     enum nk_panel_type type;
3897     nk_flags flags;
3898     struct nk_rect bounds;
3899     nk_uint *offset_x;
3900     nk_uint *offset_y;
3901     float at_x, at_y, max_x;
3902     float footer_height;
3903     float header_height;
3904     float border;
3905     unsigned int has_scrolling;
3906     struct nk_rect clip;
3907     struct nk_menu_state menu;
3908     struct nk_row_layout row;
3909     struct nk_chart chart;
3910     struct nk_command_buffer *buffer;
3911     struct nk_panel *parent;
3912 };
3913 
3914 /*==============================================================
3915  *                          WINDOW
3916  * =============================================================*/
3917 #ifndef NK_WINDOW_MAX_NAME
3918 #define NK_WINDOW_MAX_NAME 64
3919 #endif
3920 
3921 struct nk_table;
3922 enum nk_window_flags {
3923     NK_WINDOW_PRIVATE       = NK_FLAG(11),
3924     NK_WINDOW_DYNAMIC       = NK_WINDOW_PRIVATE,
3925     /* special window type growing up in height while being filled to a certain maximum height */
3926     NK_WINDOW_ROM           = NK_FLAG(12),
3927     /* sets window widgets into a read only mode and does not allow input changes */
3928     NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT,
3929     /* prevents all interaction caused by input to either window or widgets inside */
3930     NK_WINDOW_HIDDEN        = NK_FLAG(13),
3931     /* Hides window and stops any window interaction and drawing */
3932     NK_WINDOW_CLOSED        = NK_FLAG(14),
3933     /* Directly closes and frees the window at the end of the frame */
3934     NK_WINDOW_MINIMIZED     = NK_FLAG(15),
3935     /* marks the window as minimized */
3936     NK_WINDOW_REMOVE_ROM    = NK_FLAG(16)
3937     /* Removes read only mode at the end of the window */
3938 };
3939 
3940 struct nk_popup_state {
3941     struct nk_window *win;
3942     enum nk_panel_type type;
3943     struct nk_popup_buffer buf;
3944     nk_hash name;
3945     int active;
3946     unsigned combo_count;
3947     unsigned con_count, con_old;
3948     unsigned active_con;
3949     struct nk_rect header;
3950 };
3951 
3952 struct nk_edit_state {
3953     nk_hash name;
3954     unsigned int seq;
3955     unsigned int old;
3956     int active, prev;
3957     int cursor;
3958     int sel_start;
3959     int sel_end;
3960     struct nk_scroll scrollbar;
3961     unsigned char mode;
3962     unsigned char single_line;
3963 };
3964 
3965 struct nk_property_state {
3966     int active, prev;
3967     char buffer[NK_MAX_NUMBER_BUFFER];
3968     int length;
3969     int cursor;
3970     int select_start;
3971     int select_end;
3972     nk_hash name;
3973     unsigned int seq;
3974     unsigned int old;
3975     int state;
3976 };
3977 
3978 struct nk_window {
3979     unsigned int seq;
3980     nk_hash name;
3981     char name_string[NK_WINDOW_MAX_NAME];
3982     nk_flags flags;
3983 
3984     struct nk_rect bounds;
3985     struct nk_scroll scrollbar;
3986     struct nk_command_buffer buffer;
3987     struct nk_panel *layout;
3988     float scrollbar_hiding_timer;
3989 
3990     /* persistent widget state */
3991     struct nk_property_state property;
3992     struct nk_popup_state popup;
3993     struct nk_edit_state edit;
3994     unsigned int scrolled;
3995 
3996     struct nk_table *tables;
3997     unsigned int table_count;
3998 
3999     /* window list hooks */
4000     struct nk_window *next;
4001     struct nk_window *prev;
4002     struct nk_window *parent;
4003 };
4004 
4005 /*==============================================================
4006  *                          STACK
4007  * =============================================================*/
4008 /* The style modifier stack can be used to temporarily change a
4009  * property inside `nk_style`. For example if you want a special
4010  * red button you can temporarily push the old button color onto a stack
4011  * draw the button with a red color and then you just pop the old color
4012  * back from the stack:
4013  *
4014  *      nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
4015  *      nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
4016  *      nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
4017  *      nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
4018  *
4019  *      nk_button(...);
4020  *
4021  *      nk_style_pop_style_item(ctx);
4022  *      nk_style_pop_style_item(ctx);
4023  *      nk_style_pop_style_item(ctx);
4024  *      nk_style_pop_vec2(ctx);
4025  *
4026  * Nuklear has a stack for style_items, float properties, vector properties,
4027  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
4028  * which can be changed at compile time.
4029  */
4030 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
4031 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
4032 #endif
4033 
4034 #ifndef NK_FONT_STACK_SIZE
4035 #define NK_FONT_STACK_SIZE 8
4036 #endif
4037 
4038 #ifndef NK_STYLE_ITEM_STACK_SIZE
4039 #define NK_STYLE_ITEM_STACK_SIZE 16
4040 #endif
4041 
4042 #ifndef NK_FLOAT_STACK_SIZE
4043 #define NK_FLOAT_STACK_SIZE 32
4044 #endif
4045 
4046 #ifndef NK_VECTOR_STACK_SIZE
4047 #define NK_VECTOR_STACK_SIZE 16
4048 #endif
4049 
4050 #ifndef NK_FLAGS_STACK_SIZE
4051 #define NK_FLAGS_STACK_SIZE 32
4052 #endif
4053 
4054 #ifndef NK_COLOR_STACK_SIZE
4055 #define NK_COLOR_STACK_SIZE 32
4056 #endif
4057 
4058 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
4059     struct nk_config_stack_##name##_element {\
4060         prefix##_##type *address;\
4061         prefix##_##type old_value;\
4062     }
4063 #define NK_CONFIG_STACK(type,size)\
4064     struct nk_config_stack_##type {\
4065         int head;\
4066         struct nk_config_stack_##type##_element elements[size];\
4067     }
4068 
4069 #define nk_float float
4070 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
4071 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
4072 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
4073 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags);
4074 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
4075 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
4076 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
4077 
4078 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE);
4079 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE);
4080 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE);
4081 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE);
4082 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE);
4083 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE);
4084 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE);
4085 
4086 struct nk_configuration_stacks {
4087     struct nk_config_stack_style_item style_items;
4088     struct nk_config_stack_float floats;
4089     struct nk_config_stack_vec2 vectors;
4090     struct nk_config_stack_flags flags;
4091     struct nk_config_stack_color colors;
4092     struct nk_config_stack_user_font fonts;
4093     struct nk_config_stack_button_behavior button_behaviors;
4094 };
4095 
4096 /*==============================================================
4097  *                          CONTEXT
4098  * =============================================================*/
4099 #define NK_VALUE_PAGE_CAPACITY \
4100     (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
4101 
4102 struct nk_table {
4103     unsigned int seq;
4104     unsigned int size;
4105     nk_hash keys[NK_VALUE_PAGE_CAPACITY];
4106     nk_uint values[NK_VALUE_PAGE_CAPACITY];
4107     struct nk_table *next, *prev;
4108 };
4109 
4110 union nk_page_data {
4111     struct nk_table tbl;
4112     struct nk_panel pan;
4113     struct nk_window win;
4114 };
4115 
4116 struct nk_page_element {
4117     union nk_page_data data;
4118     struct nk_page_element *next;
4119     struct nk_page_element *prev;
4120 };
4121 
4122 struct nk_page {
4123     unsigned int size;
4124     struct nk_page *next;
4125     struct nk_page_element win[1];
4126 };
4127 
4128 struct nk_pool {
4129     struct nk_allocator alloc;
4130     enum nk_allocation_type type;
4131     unsigned int page_count;
4132     struct nk_page *pages;
4133     struct nk_page_element *freelist;
4134     unsigned capacity;
4135     nk_size size;
4136     nk_size cap;
4137 };
4138 
4139 struct nk_context {
4140 /* public: can be accessed freely */
4141     struct nk_input input;
4142     struct nk_style style;
4143     struct nk_buffer memory;
4144     struct nk_clipboard clip;
4145     nk_flags last_widget_state;
4146     enum nk_button_behavior button_behavior;
4147     struct nk_configuration_stacks stacks;
4148     float delta_time_seconds;
4149 
4150 /* private:
4151     should only be accessed if you
4152     know what you are doing */
4153 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4154     struct nk_draw_list draw_list;
4155 #endif
4156 #ifdef NK_INCLUDE_COMMAND_USERDATA
4157     nk_handle userdata;
4158 #endif
4159     /* text editor objects are quite big because of an internal
4160      * undo/redo stack. Therefore it does not make sense to have one for
4161      * each window for temporary use cases, so I only provide *one* instance
4162      * for all windows. This works because the content is cleared anyway */
4163     struct nk_text_edit text_edit;
4164     /* draw buffer used for overlay drawing operation like cursor */
4165     struct nk_command_buffer overlay;
4166 
4167     /* windows */
4168     int build;
4169     int use_pool;
4170     struct nk_pool pool;
4171     struct nk_window *begin;
4172     struct nk_window *end;
4173     struct nk_window *active;
4174     struct nk_window *current;
4175     struct nk_page_element *freelist;
4176     unsigned int count;
4177     unsigned int seq;
4178 };
4179 
4180 /* ==============================================================
4181  *                          MATH
4182  * =============================================================== */
4183 #define NK_PI 3.141592654f
4184 #define NK_UTF_INVALID 0xFFFD
4185 #define NK_MAX_FLOAT_PRECISION 2
4186 
4187 #define NK_UNUSED(x) ((void)(x))
4188 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
4189 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
4190 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
4191 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
4192 #define NK_INBOX(px, py, x, y, w, h)\
4193     (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
4194 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
4195     (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
4196 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
4197     (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
4198 
4199 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
4200 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
4201 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
4202 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
4203 
4204 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
4205 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
4206 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
4207 
4208 /* ==============================================================
4209  *                          ALIGNMENT
4210  * =============================================================== */
4211 /* Pointer to Integer type conversion for pointer alignment */
4212 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
4213 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
4214 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
4215 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
4216 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
4217 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
4218 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
4219 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
4220 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
4221 #else /* generates warning but works */
4222 # define NK_UINT_TO_PTR(x) ((void*)(x))
4223 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
4224 #endif
4225 
4226 #define NK_ALIGN_PTR(x, mask)\
4227     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
4228 #define NK_ALIGN_PTR_BACK(x, mask)\
4229     (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
4230 
4231 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
4232 #define NK_CONTAINER_OF(ptr,type,member)\
4233     (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
4234 
4235 #ifdef __cplusplus
4236 }
4237 #endif
4238 
4239 #ifdef __cplusplus
4240 template<typename T> struct nk_alignof;
4241 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
4242 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
4243 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
4244     diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
4245 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
4246 #elif defined(_MSC_VER)
4247 #define NK_ALIGNOF(t) (__alignof(t))
4248 #else
4249 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
4250 #endif
4251 
4252 #endif /* NK_NUKLEAR_H_ */
4253 /*
4254  * ==============================================================
4255  *
4256  *                          IMPLEMENTATION
4257  *
4258  * ===============================================================
4259  */
4260 #ifdef NK_IMPLEMENTATION
4261 
4262 #ifndef NK_POOL_DEFAULT_CAPACITY
4263 #define NK_POOL_DEFAULT_CAPACITY 16
4264 #endif
4265 
4266 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
4267 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
4268 #endif
4269 
4270 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
4271 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
4272 #endif
4273 
4274 /* standard library headers */
4275 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4276 #include <stdlib.h> /* malloc, free */
4277 #endif
4278 #ifdef NK_INCLUDE_STANDARD_IO
4279 #include <stdio.h> /* fopen, fclose,... */
4280 #endif
4281 #ifdef NK_INCLUDE_STANDARD_VARARGS
4282 #include <stdarg.h> /* valist, va_start, va_end, ... */
4283 #endif
4284 #ifndef NK_ASSERT
4285 #include <assert.h>
4286 #define NK_ASSERT(expr) assert(expr)
4287 #endif
4288 
4289 #ifndef NK_MEMSET
4290 #define NK_MEMSET nk_memset
4291 #endif
4292 #ifndef NK_MEMCPY
4293 #define NK_MEMCPY nk_memcopy
4294 #endif
4295 #ifndef NK_SQRT
4296 #define NK_SQRT nk_sqrt
4297 #endif
4298 #ifndef NK_SIN
4299 #define NK_SIN nk_sin
4300 #endif
4301 #ifndef NK_COS
4302 #define NK_COS nk_cos
4303 #endif
4304 #ifndef NK_STRTOD
4305 #define NK_STRTOD nk_strtod
4306 #endif
4307 #ifndef NK_DTOA
4308 #define NK_DTOA nk_dtoa
4309 #endif
4310 
4311 #define NK_DEFAULT (-1)
4312 
4313 #ifndef NK_VSNPRINTF
4314 /* If your compiler does support `vsnprintf` I would highly recommend
4315  * defining this to vsnprintf instead since `vsprintf` is basically
4316  * unbelievable unsafe and should *NEVER* be used. But I have to support
4317  * it since C89 only provides this unsafe version. */
4318   #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
4319       (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
4320       (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
4321       (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
4322        defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
4323       #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
4324   #else
4325     #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
4326   #endif
4327 #endif
4328 
4329 #define NK_SCHAR_MIN (-127)
4330 #define NK_SCHAR_MAX 127
4331 #define NK_UCHAR_MIN 0
4332 #define NK_UCHAR_MAX 256
4333 #define NK_SSHORT_MIN (-32767)
4334 #define NK_SSHORT_MAX 32767
4335 #define NK_USHORT_MIN 0
4336 #define NK_USHORT_MAX 65535
4337 #define NK_SINT_MIN (-2147483647)
4338 #define NK_SINT_MAX 2147483647
4339 #define NK_UINT_MIN 0
4340 #define NK_UINT_MAX 4294967295u
4341 
4342 /* Make sure correct type size:
4343  * This will fire with a negative subscript error if the type sizes
4344  * are set incorrectly by the compiler, and compile out if not */
4345 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
4346 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
4347 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
4348 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
4349 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
4350 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
4351 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
4352 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
4353 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
4354 
4355 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
4356 #define NK_FLOAT_PRECISION 0.00000000000001
4357 
4358 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
4359 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
4360 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
4361 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
4362 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
4363 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
4364 
4365 /*
4366  * ==============================================================
4367  *
4368  *                          MATH
4369  *
4370  * ===============================================================
4371  */
4372 /*  Since nuklear is supposed to work on all systems providing floating point
4373     math without any dependencies I also had to implement my own math functions
4374     for sqrt, sin and cos. Since the actual highly accurate implementations for
4375     the standard library functions are quite complex and I do not need high
4376     precision for my use cases I use approximations.
4377 
4378     Sqrt
4379     ----
4380     For square root nuklear uses the famous fast inverse square root:
4381     https://en.wikipedia.org/wiki/Fast_inverse_square_root with
4382     slightly tweaked magic constant. While on today's hardware it is
4383     probably not faster it is still fast and accurate enough for
4384     nuklear's use cases. IMPORTANT: this requires float format IEEE 754
4385 
4386     Sine/Cosine
4387     -----------
4388     All constants inside both function are generated Remez's minimax
4389     approximations for value range 0...2*PI. The reason why I decided to
4390     approximate exactly that range is that nuklear only needs sine and
4391     cosine to generate circles which only requires that exact range.
4392     In addition I used Remez instead of Taylor for additional precision:
4393     www.lolengine.net/blog/2011/12/21/better-function-approximations.
4394 
4395     The tool I used to generate constants for both sine and cosine
4396     (it can actually approximate a lot more functions) can be
4397     found here: www.lolengine.net/wiki/oss/lolremez
4398 */
4399 NK_INTERN float
4400 nk_inv_sqrt(float number)
4401 {
4402     float x2;
4403     const float threehalfs = 1.5f;
4404     union {nk_uint i; float f;} conv = {0};
4405     conv.f = number;
4406     x2 = number * 0.5f;
4407     conv.i = 0x5f375A84 - (conv.i >> 1);
4408     conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
4409     return conv.f;
4410 }
4411 
4412 NK_INTERN float
4413 nk_sqrt(float x)
4414 {
4415     return x * nk_inv_sqrt(x);
4416 }
4417 
4418 NK_INTERN float
4419 nk_sin(float x)
4420 {
4421     NK_STORAGE const float a0 = +1.91059300966915117e-31f;
4422     NK_STORAGE const float a1 = +1.00086760103908896f;
4423     NK_STORAGE const float a2 = -1.21276126894734565e-2f;
4424     NK_STORAGE const float a3 = -1.38078780785773762e-1f;
4425     NK_STORAGE const float a4 = -2.67353392911981221e-2f;
4426     NK_STORAGE const float a5 = +2.08026600266304389e-2f;
4427     NK_STORAGE const float a6 = -3.03996055049204407e-3f;
4428     NK_STORAGE const float a7 = +1.38235642404333740e-4f;
4429     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4430 }
4431 
4432 NK_INTERN float
4433 nk_cos(float x)
4434 {
4435     NK_STORAGE const float a0 = +1.00238601909309722f;
4436     NK_STORAGE const float a1 = -3.81919947353040024e-2f;
4437     NK_STORAGE const float a2 = -3.94382342128062756e-1f;
4438     NK_STORAGE const float a3 = -1.18134036025221444e-1f;
4439     NK_STORAGE const float a4 = +1.07123798512170878e-1f;
4440     NK_STORAGE const float a5 = -1.86637164165180873e-2f;
4441     NK_STORAGE const float a6 = +9.90140908664079833e-4f;
4442     NK_STORAGE const float a7 = -5.23022132118824778e-14f;
4443     return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4444 }
4445 
4446 NK_INTERN nk_uint
4447 nk_round_up_pow2(nk_uint v)
4448 {
4449     v--;
4450     v |= v >> 1;
4451     v |= v >> 2;
4452     v |= v >> 4;
4453     v |= v >> 8;
4454     v |= v >> 16;
4455     v++;
4456     return v;
4457 }
4458 
4459 NK_API struct nk_rect
4460 nk_get_null_rect(void)
4461 {
4462     return nk_null_rect;
4463 }
4464 
4465 NK_API struct nk_rect
4466 nk_rect(float x, float y, float w, float h)
4467 {
4468     struct nk_rect r;
4469     r.x = x; r.y = y;
4470     r.w = w; r.h = h;
4471     return r;
4472 }
4473 
4474 NK_API struct nk_rect
4475 nk_recti(int x, int y, int w, int h)
4476 {
4477     struct nk_rect r;
4478     r.x = (float)x;
4479     r.y = (float)y;
4480     r.w = (float)w;
4481     r.h = (float)h;
4482     return r;
4483 }
4484 
4485 NK_API struct nk_rect
4486 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
4487 {
4488     return nk_rect(pos.x, pos.y, size.x, size.y);
4489 }
4490 
4491 NK_API struct nk_rect
4492 nk_rectv(const float *r)
4493 {
4494     return nk_rect(r[0], r[1], r[2], r[3]);
4495 }
4496 
4497 NK_API struct nk_rect
4498 nk_rectiv(const int *r)
4499 {
4500     return nk_recti(r[0], r[1], r[2], r[3]);
4501 }
4502 
4503 NK_API struct nk_vec2
4504 nk_rect_pos(struct nk_rect r)
4505 {
4506     struct nk_vec2 ret;
4507     ret.x = r.x; ret.y = r.y;
4508     return ret;
4509 }
4510 
4511 NK_API struct nk_vec2
4512 nk_rect_size(struct nk_rect r)
4513 {
4514     struct nk_vec2 ret;
4515     ret.x = r.w; ret.y = r.h;
4516     return ret;
4517 }
4518 
4519 NK_INTERN struct nk_rect
4520 nk_shrink_rect(struct nk_rect r, float amount)
4521 {
4522     struct nk_rect res;
4523     r.w = NK_MAX(r.w, 2 * amount);
4524     r.h = NK_MAX(r.h, 2 * amount);
4525     res.x = r.x + amount;
4526     res.y = r.y + amount;
4527     res.w = r.w - 2 * amount;
4528     res.h = r.h - 2 * amount;
4529     return res;
4530 }
4531 
4532 NK_INTERN struct nk_rect
4533 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
4534 {
4535     r.w = NK_MAX(r.w, 2 * pad.x);
4536     r.h = NK_MAX(r.h, 2 * pad.y);
4537     r.x += pad.x; r.y += pad.y;
4538     r.w -= 2 * pad.x;
4539     r.h -= 2 * pad.y;
4540     return r;
4541 }
4542 
4543 NK_API struct nk_vec2
4544 nk_vec2(float x, float y)
4545 {
4546     struct nk_vec2 ret;
4547     ret.x = x; ret.y = y;
4548     return ret;
4549 }
4550 
4551 NK_API struct nk_vec2
4552 nk_vec2i(int x, int y)
4553 {
4554     struct nk_vec2 ret;
4555     ret.x = (float)x;
4556     ret.y = (float)y;
4557     return ret;
4558 }
4559 
4560 NK_API struct nk_vec2
4561 nk_vec2v(const float *v)
4562 {
4563     return nk_vec2(v[0], v[1]);
4564 }
4565 
4566 NK_API struct nk_vec2
4567 nk_vec2iv(const int *v)
4568 {
4569     return nk_vec2i(v[0], v[1]);
4570 }
4571 
4572 /*
4573  * ==============================================================
4574  *
4575  *                          UTIL
4576  *
4577  * ===============================================================
4578  */
4579 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
4580 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
4581 NK_INTERN int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
4582 NK_INTERN int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
4583 NK_INTERN int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
4584 NK_INTERN int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
4585 
4586 NK_INTERN void*
4587 nk_memcopy(void *dst0, const void *src0, nk_size length)
4588 {
4589     nk_ptr t;
4590     char *dst = (char*)dst0;
4591     const char *src = (const char*)src0;
4592     if (length == 0 || dst == src)
4593         goto done;
4594 
4595     #define nk_word int
4596     #define nk_wsize sizeof(nk_word)
4597     #define nk_wmask (nk_wsize-1)
4598     #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
4599     #define NK_TLOOP1(s) do { s; } while (--t)
4600 
4601     if (dst < src) {
4602         t = (nk_ptr)src; /* only need low bits */
4603         if ((t | (nk_ptr)dst) & nk_wmask) {
4604             if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
4605                 t = length;
4606             else
4607                 t = nk_wsize - (t & nk_wmask);
4608             length -= t;
4609             NK_TLOOP1(*dst++ = *src++);
4610         }
4611         t = length / nk_wsize;
4612         NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
4613             src += nk_wsize; dst += nk_wsize);
4614         t = length & nk_wmask;
4615         NK_TLOOP(*dst++ = *src++);
4616     } else {
4617         src += length;
4618         dst += length;
4619         t = (nk_ptr)src;
4620         if ((t | (nk_ptr)dst) & nk_wmask) {
4621             if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
4622                 t = length;
4623             else
4624                 t &= nk_wmask;
4625             length -= t;
4626             NK_TLOOP1(*--dst = *--src);
4627         }
4628         t = length / nk_wsize;
4629         NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
4630             *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
4631         t = length & nk_wmask;
4632         NK_TLOOP(*--dst = *--src);
4633     }
4634     #undef nk_word
4635     #undef nk_wsize
4636     #undef nk_wmask
4637     #undef NK_TLOOP
4638     #undef NK_TLOOP1
4639 done:
4640     return (dst0);
4641 }
4642 
4643 NK_INTERN void
4644 nk_memset(void *ptr, int c0, nk_size size)
4645 {
4646     #define nk_word unsigned
4647     #define nk_wsize sizeof(nk_word)
4648     #define nk_wmask (nk_wsize - 1)
4649     nk_byte *dst = (nk_byte*)ptr;
4650     unsigned c = 0;
4651     nk_size t = 0;
4652 
4653     if ((c = (nk_byte)c0) != 0) {
4654         c = (c << 8) | c; /* at least 16-bits  */
4655         if (sizeof(unsigned int) > 2)
4656             c = (c << 16) | c; /* at least 32-bits*/
4657     }
4658 
4659     /* too small of a word count */
4660     dst = (nk_byte*)ptr;
4661     if (size < 3 * nk_wsize) {
4662         while (size--) *dst++ = (nk_byte)c0;
4663         return;
4664     }
4665 
4666     /* align destination */
4667     if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
4668         t = nk_wsize -t;
4669         size -= t;
4670         do {
4671             *dst++ = (nk_byte)c0;
4672         } while (--t != 0);
4673     }
4674 
4675     /* fill word */
4676     t = size / nk_wsize;
4677     do {
4678         *(nk_word*)((void*)dst) = c;
4679         dst += nk_wsize;
4680     } while (--t != 0);
4681 
4682     /* fill trailing bytes */
4683     t = (size & nk_wmask);
4684     if (t != 0) {
4685         do {
4686             *dst++ = (nk_byte)c0;
4687         } while (--t != 0);
4688     }
4689 
4690     #undef nk_word
4691     #undef nk_wsize
4692     #undef nk_wmask
4693 }
4694 
4695 NK_INTERN void
4696 nk_zero(void *ptr, nk_size size)
4697 {
4698     NK_ASSERT(ptr);
4699     NK_MEMSET(ptr, 0, size);
4700 }
4701 
4702 NK_API int
4703 nk_strlen(const char *str)
4704 {
4705     int siz = 0;
4706     NK_ASSERT(str);
4707     while (str && *str++ != '\0') siz++;
4708     return siz;
4709 }
4710 
4711 NK_API int
4712 nk_strtoi(const char *str, const char **endptr)
4713 {
4714     int neg = 1;
4715     const char *p = str;
4716     int value = 0;
4717 
4718     NK_ASSERT(str);
4719     if (!str) return 0;
4720 
4721     /* skip whitespace */
4722     while (*p == ' ') p++;
4723     if (*p == '-') {
4724         neg = -1;
4725         p++;
4726     }
4727     while (*p && *p >= '0' && *p <= '9') {
4728         value = value * 10 + (int) (*p - '0');
4729         p++;
4730     }
4731     if (endptr)
4732         *endptr = p;
4733     return neg*value;
4734 }
4735 
4736 NK_API double
4737 nk_strtod(const char *str, const char **endptr)
4738 {
4739     double m;
4740     double neg = 1.0;
4741     const char *p = str;
4742     double value = 0;
4743     double number = 0;
4744 
4745     NK_ASSERT(str);
4746     if (!str) return 0;
4747 
4748     /* skip whitespace */
4749     while (*p == ' ') p++;
4750     if (*p == '-') {
4751         neg = -1.0;
4752         p++;
4753     }
4754 
4755     while (*p && *p != '.' && *p != 'e') {
4756         value = value * 10.0 + (double) (*p - '0');
4757         p++;
4758     }
4759 
4760     if (*p == '.') {
4761         p++;
4762         for(m = 0.1; *p && *p != 'e'; p++ ) {
4763             value = value + (double) (*p - '0') * m;
4764             m *= 0.1;
4765         }
4766     }
4767     if (*p == 'e') {
4768         int i, pow, div;
4769         p++;
4770         if (*p == '-') {
4771             div = nk_true;
4772             p++;
4773         } else if (*p == '+') {
4774             div = nk_false;
4775             p++;
4776         } else div = nk_false;
4777 
4778         for (pow = 0; *p; p++)
4779             pow = pow * 10 + (int) (*p - '0');
4780 
4781         for (m = 1.0, i = 0; i < pow; i++)
4782             m *= 10.0;
4783 
4784         if (div)
4785             value /= m;
4786         else value *= m;
4787     }
4788     number = value * neg;
4789     if (endptr)
4790         *endptr = p;
4791     return number;
4792 }
4793 
4794 NK_API float
4795 nk_strtof(const char *str, const char **endptr)
4796 {
4797     float float_value;
4798     double double_value;
4799     double_value = NK_STRTOD(str, endptr);
4800     float_value = (float)double_value;
4801     return float_value;
4802 }
4803 
4804 NK_API int
4805 nk_stricmp(const char *s1, const char *s2)
4806 {
4807     nk_int c1,c2,d;
4808     do {
4809         c1 = *s1++;
4810         c2 = *s2++;
4811         d = c1 - c2;
4812         while (d) {
4813             if (c1 <= 'Z' && c1 >= 'A') {
4814                 d += ('a' - 'A');
4815                 if (!d) break;
4816             }
4817             if (c2 <= 'Z' && c2 >= 'A') {
4818                 d -= ('a' - 'A');
4819                 if (!d) break;
4820             }
4821             return ((d >= 0) << 1) - 1;
4822         }
4823     } while (c1);
4824     return 0;
4825 }
4826 
4827 NK_API int
4828 nk_stricmpn(const char *s1, const char *s2, int n)
4829 {
4830     int c1,c2,d;
4831     NK_ASSERT(n >= 0);
4832     do {
4833         c1 = *s1++;
4834         c2 = *s2++;
4835         if (!n--) return 0;
4836 
4837         d = c1 - c2;
4838         while (d) {
4839             if (c1 <= 'Z' && c1 >= 'A') {
4840                 d += ('a' - 'A');
4841                 if (!d) break;
4842             }
4843             if (c2 <= 'Z' && c2 >= 'A') {
4844                 d -= ('a' - 'A');
4845                 if (!d) break;
4846             }
4847             return ((d >= 0) << 1) - 1;
4848         }
4849     } while (c1);
4850     return 0;
4851 }
4852 
4853 NK_INTERN int
4854 nk_str_match_here(const char *regexp, const char *text)
4855 {
4856     if (regexp[0] == '\0')
4857         return 1;
4858     if (regexp[1] == '*')
4859         return nk_str_match_star(regexp[0], regexp+2, text);
4860     if (regexp[0] == '$' && regexp[1] == '\0')
4861         return *text == '\0';
4862     if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
4863         return nk_str_match_here(regexp+1, text+1);
4864     return 0;
4865 }
4866 
4867 NK_INTERN int
4868 nk_str_match_star(int c, const char *regexp, const char *text)
4869 {
4870     do {/* a '* matches zero or more instances */
4871         if (nk_str_match_here(regexp, text))
4872             return 1;
4873     } while (*text != '\0' && (*text++ == c || c == '.'));
4874     return 0;
4875 }
4876 
4877 NK_API int
4878 nk_strfilter(const char *text, const char *regexp)
4879 {
4880     /*
4881     c    matches any literal character c
4882     .    matches any single character
4883     ^    matches the beginning of the input string
4884     $    matches the end of the input string
4885     *    matches zero or more occurrences of the previous character*/
4886     if (regexp[0] == '^')
4887         return nk_str_match_here(regexp+1, text);
4888     do {    /* must look even if string is empty */
4889         if (nk_str_match_here(regexp, text))
4890             return 1;
4891     } while (*text++ != '\0');
4892     return 0;
4893 }
4894 
4895 NK_API int
4896 nk_strmatch_fuzzy_text(const char *str, int str_len,
4897     const char *pattern, int *out_score)
4898 {
4899     /* Returns true if each character in pattern is found sequentially within str
4900      * if found then out_score is also set. Score value has no intrinsic meaning.
4901      * Range varies with pattern. Can only compare scores with same search pattern. */
4902 
4903     /* ------- scores --------- */
4904     /* bonus for adjacent matches */
4905     #define NK_ADJACENCY_BONUS 5
4906     /* bonus if match occurs after a separator */
4907     #define NK_SEPARATOR_BONUS 10
4908     /* bonus if match is uppercase and prev is lower */
4909     #define NK_CAMEL_BONUS 10
4910     /* penalty applied for every letter in str before the first match */
4911     #define NK_LEADING_LETTER_PENALTY (-3)
4912     /* maximum penalty for leading letters */
4913     #define NK_MAX_LEADING_LETTER_PENALTY (-9)
4914     /* penalty for every letter that doesn't matter */
4915     #define NK_UNMATCHED_LETTER_PENALTY (-1)
4916 
4917     /* loop variables */
4918     int score = 0;
4919     char const * pattern_iter = pattern;
4920     int str_iter = 0;
4921     int prev_matched = nk_false;
4922     int prev_lower = nk_false;
4923     /* true so if first letter match gets separator bonus*/
4924     int prev_separator = nk_true;
4925 
4926     /* use "best" matched letter if multiple string letters match the pattern */
4927     char const * best_letter = 0;
4928     int best_letter_score = 0;
4929 
4930     /* loop over strings */
4931     NK_ASSERT(str);
4932     NK_ASSERT(pattern);
4933     if (!str || !str_len || !pattern) return 0;
4934     while (str_iter < str_len)
4935     {
4936         const char pattern_letter = *pattern_iter;
4937         const char str_letter = str[str_iter];
4938 
4939         int next_match = *pattern_iter != '\0' &&
4940             nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
4941         int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
4942 
4943         int advanced = next_match && best_letter;
4944         int pattern_repeat = best_letter && *pattern_iter != '\0';
4945         pattern_repeat = pattern_repeat &&
4946             nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
4947 
4948         if (advanced || pattern_repeat) {
4949             score += best_letter_score;
4950             best_letter = 0;
4951             best_letter_score = 0;
4952         }
4953 
4954         if (next_match || rematch)
4955         {
4956             int new_score = 0;
4957             /* Apply penalty for each letter before the first pattern match */
4958             if (pattern_iter == pattern) {
4959                 int count = (int)(&str[str_iter] - str);
4960                 int penalty = NK_LEADING_LETTER_PENALTY * count;
4961                 if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
4962                     penalty = NK_MAX_LEADING_LETTER_PENALTY;
4963 
4964                 score += penalty;
4965             }
4966 
4967             /* apply bonus for consecutive bonuses */
4968             if (prev_matched)
4969                 new_score += NK_ADJACENCY_BONUS;
4970 
4971             /* apply bonus for matches after a separator */
4972             if (prev_separator)
4973                 new_score += NK_SEPARATOR_BONUS;
4974 
4975             /* apply bonus across camel case boundaries */
4976             if (prev_lower && nk_is_upper(str_letter))
4977                 new_score += NK_CAMEL_BONUS;
4978 
4979             /* update pattern iter IFF the next pattern letter was matched */
4980             if (next_match)
4981                 ++pattern_iter;
4982 
4983             /* update best letter in str which may be for a "next" letter or a rematch */
4984             if (new_score >= best_letter_score) {
4985                 /* apply penalty for now skipped letter */
4986                 if (best_letter != 0)
4987                     score += NK_UNMATCHED_LETTER_PENALTY;
4988 
4989                 best_letter = &str[str_iter];
4990                 best_letter_score = new_score;
4991             }
4992             prev_matched = nk_true;
4993         } else {
4994             score += NK_UNMATCHED_LETTER_PENALTY;
4995             prev_matched = nk_false;
4996         }
4997 
4998         /* separators should be more easily defined */
4999         prev_lower = nk_is_lower(str_letter) != 0;
5000         prev_separator = str_letter == '_' || str_letter == ' ';
5001 
5002         ++str_iter;
5003     }
5004 
5005     /* apply score for last match */
5006     if (best_letter)
5007         score += best_letter_score;
5008 
5009     /* did not match full pattern */
5010     if (*pattern_iter != '\0')
5011         return nk_false;
5012 
5013     if (out_score)
5014         *out_score = score;
5015     return nk_true;
5016 }
5017 
5018 NK_API int
5019 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
5020 {return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);}
5021 
5022 NK_INTERN int
5023 nk_string_float_limit(char *string, int prec)
5024 {
5025     int dot = 0;
5026     char *c = string;
5027     while (*c) {
5028         if (*c == '.') {
5029             dot = 1;
5030             c++;
5031             continue;
5032         }
5033         if (dot == (prec+1)) {
5034             *c = 0;
5035             break;
5036         }
5037         if (dot > 0) dot++;
5038         c++;
5039     }
5040     return (int)(c - string);
5041 }
5042 
5043 NK_INTERN double
5044 nk_pow(double x, int n)
5045 {
5046     /*  check the sign of n */
5047     double r = 1;
5048     int plus = n >= 0;
5049     n = (plus) ? n : -n;
5050     while (n > 0) {
5051         if ((n & 1) == 1)
5052             r *= x;
5053         n /= 2;
5054         x *= x;
5055     }
5056     return plus ? r : 1.0 / r;
5057 }
5058 
5059 NK_INTERN int
5060 nk_ifloord(double x)
5061 {
5062     x = (double)((int)x - ((x < 0.0) ? 1 : 0));
5063     return (int)x;
5064 }
5065 
5066 NK_INTERN int
5067 nk_ifloorf(float x)
5068 {
5069     x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
5070     return (int)x;
5071 }
5072 
5073 NK_INTERN int
5074 nk_iceilf(float x)
5075 {
5076     if (x >= 0) {
5077         int i = (int)x;
5078         return (x > i) ? i+1: i;
5079     } else {
5080         int t = (int)x;
5081         float r = x - (float)t;
5082         return (r > 0.0f) ? t+1: t;
5083     }
5084 }
5085 
5086 NK_INTERN int
5087 nk_log10(double n)
5088 {
5089     int neg;
5090     int ret;
5091     int exp = 0;
5092 
5093     neg = (n < 0) ? 1 : 0;
5094     ret = (neg) ? (int)-n : (int)n;
5095     while ((ret / 10) > 0) {
5096         ret /= 10;
5097         exp++;
5098     }
5099     if (neg) exp = -exp;
5100     return exp;
5101 }
5102 
5103 NK_INTERN void
5104 nk_strrev_ascii(char *s)
5105 {
5106     int len = nk_strlen(s);
5107     int end = len / 2;
5108     int i = 0;
5109     char t;
5110     for (; i < end; ++i) {
5111         t = s[i];
5112         s[i] = s[len - 1 - i];
5113         s[len -1 - i] = t;
5114     }
5115 }
5116 
5117 NK_INTERN char*
5118 nk_itoa(char *s, long n)
5119 {
5120     long i = 0;
5121     if (n == 0) {
5122         s[i++] = '0';
5123         s[i] = 0;
5124         return s;
5125     }
5126     if (n < 0) {
5127         s[i++] = '-';
5128         n = -n;
5129     }
5130     while (n > 0) {
5131         s[i++] = (char)('0' + (n % 10));
5132         n /= 10;
5133     }
5134     s[i] = 0;
5135     if (s[0] == '-')
5136         ++s;
5137 
5138     nk_strrev_ascii(s);
5139     return s;
5140 }
5141 
5142 NK_INTERN char*
5143 nk_dtoa(char *s, double n)
5144 {
5145     int useExp = 0;
5146     int digit = 0, m = 0, m1 = 0;
5147     char *c = s;
5148     int neg = 0;
5149 
5150     NK_ASSERT(s);
5151     if (!s) return 0;
5152 
5153     if (n == 0.0) {
5154         s[0] = '0'; s[1] = '\0';
5155         return s;
5156     }
5157 
5158     neg = (n < 0);
5159     if (neg) n = -n;
5160 
5161     /* calculate magnitude */
5162     m = nk_log10(n);
5163     useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
5164     if (neg) *(c++) = '-';
5165 
5166     /* set up for scientific notation */
5167     if (useExp) {
5168         if (m < 0)
5169            m -= 1;
5170         n = n / (double)nk_pow(10.0, m);
5171         m1 = m;
5172         m = 0;
5173     }
5174     if (m < 1.0) {
5175         m = 0;
5176     }
5177 
5178     /* convert the number */
5179     while (n > NK_FLOAT_PRECISION || m >= 0) {
5180         double weight = nk_pow(10.0, m);
5181         if (weight > 0) {
5182             double t = (double)n / weight;
5183             digit = nk_ifloord(t);
5184             n -= ((double)digit * weight);
5185             *(c++) = (char)('0' + (char)digit);
5186         }
5187         if (m == 0 && n > 0)
5188             *(c++) = '.';
5189         m--;
5190     }
5191 
5192     if (useExp) {
5193         /* convert the exponent */
5194         int i, j;
5195         *(c++) = 'e';
5196         if (m1 > 0) {
5197             *(c++) = '+';
5198         } else {
5199             *(c++) = '-';
5200             m1 = -m1;
5201         }
5202         m = 0;
5203         while (m1 > 0) {
5204             *(c++) = (char)('0' + (char)(m1 % 10));
5205             m1 /= 10;
5206             m++;
5207         }
5208         c -= m;
5209         for (i = 0, j = m-1; i<j; i++, j--) {
5210             /* swap without temporary */
5211             c[i] ^= c[j];
5212             c[j] ^= c[i];
5213             c[i] ^= c[j];
5214         }
5215         c += m;
5216     }
5217     *(c) = '\0';
5218     return s;
5219 }
5220 
5221 #ifdef NK_INCLUDE_STANDARD_VARARGS
5222 #ifndef NK_INCLUDE_STANDARD_IO
5223 static int
5224 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
5225 {
5226     enum nk_arg_type {
5227         NK_ARG_TYPE_CHAR,
5228         NK_ARG_TYPE_SHORT,
5229         NK_ARG_TYPE_DEFAULT,
5230         NK_ARG_TYPE_LONG
5231     };
5232     enum nk_arg_flags {
5233         NK_ARG_FLAG_LEFT = 0x01,
5234         NK_ARG_FLAG_PLUS = 0x02,
5235         NK_ARG_FLAG_SPACE = 0x04,
5236         NK_ARG_FLAG_NUM = 0x10,
5237         NK_ARG_FLAG_ZERO = 0x20
5238     };
5239 
5240     char number_buffer[NK_MAX_NUMBER_BUFFER];
5241     enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
5242     int precision = NK_DEFAULT;
5243     int width = NK_DEFAULT;
5244     nk_flags flag = 0;
5245 
5246     int len = 0;
5247     int result = -1;
5248     const char *iter = fmt;
5249 
5250     NK_ASSERT(buf);
5251     NK_ASSERT(buf_size);
5252     if (!buf || !buf_size || !fmt) return 0;
5253     for (iter = fmt; *iter && len < buf_size; iter++) {
5254         /* copy all non-format characters */
5255         while (*iter && (*iter != '%') && (len < buf_size))
5256             buf[len++] = *iter++;
5257         if (!(*iter) || len >= buf_size) break;
5258         iter++;
5259 
5260         /* flag arguments */
5261         while (*iter) {
5262             if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
5263             else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
5264             else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
5265             else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
5266             else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
5267             else break;
5268             iter++;
5269         }
5270 
5271         /* width argument */
5272         width = NK_DEFAULT;
5273         if (*iter >= '1' && *iter <= '9') {
5274             const char *end;
5275             width = nk_strtoi(iter, &end);
5276             if (end == iter)
5277                 width = -1;
5278             else iter = end;
5279         } else if (*iter == '*') {
5280             width = va_arg(args, int);
5281             iter++;
5282         }
5283 
5284         /* precision argument */
5285         precision = NK_DEFAULT;
5286         if (*iter == '.') {
5287             iter++;
5288             if (*iter == '*') {
5289                 precision = va_arg(args, int);
5290                 iter++;
5291             } else {
5292                 const char *end;
5293                 precision = nk_strtoi(iter, &end);
5294                 if (end == iter)
5295                     precision = -1;
5296                 else iter = end;
5297             }
5298         }
5299 
5300         /* length modifier */
5301         if (*iter == 'h') {
5302             if (*(iter+1) == 'h') {
5303                 arg_type = NK_ARG_TYPE_CHAR;
5304                 iter++;
5305             } else arg_type = NK_ARG_TYPE_SHORT;
5306             iter++;
5307         } else if (*iter == 'l') {
5308             arg_type = NK_ARG_TYPE_LONG;
5309             iter++;
5310         } else arg_type = NK_ARG_TYPE_DEFAULT;
5311 
5312         /* specifier */
5313         if (*iter == '%') {
5314             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5315             NK_ASSERT(precision == NK_DEFAULT);
5316             NK_ASSERT(width == NK_DEFAULT);
5317             if (len < buf_size)
5318                 buf[len++] = '%';
5319         } else if (*iter == 's') {
5320             /* string  */
5321             const char *str = va_arg(args, const char*);
5322             NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
5323             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5324             NK_ASSERT(precision == NK_DEFAULT);
5325             NK_ASSERT(width == NK_DEFAULT);
5326             if (str == buf) return -1;
5327             while (str && *str && len < buf_size)
5328                 buf[len++] = *str++;
5329         } else if (*iter == 'n') {
5330             /* current length callback */
5331             signed int *n = va_arg(args, int*);
5332             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5333             NK_ASSERT(precision == NK_DEFAULT);
5334             NK_ASSERT(width == NK_DEFAULT);
5335             if (n) *n = len;
5336         } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
5337             /* signed integer */
5338             long value = 0;
5339             const char *num_iter;
5340             int num_len, num_print, padding;
5341             int cur_precision = NK_MAX(precision, 1);
5342             int cur_width = NK_MAX(width, 0);
5343 
5344             /* retrieve correct value type */
5345             if (arg_type == NK_ARG_TYPE_CHAR)
5346                 value = (signed char)va_arg(args, int);
5347             else if (arg_type == NK_ARG_TYPE_SHORT)
5348                 value = (signed short)va_arg(args, int);
5349             else if (arg_type == NK_ARG_TYPE_LONG)
5350                 value = va_arg(args, signed long);
5351             else if (*iter == 'c')
5352                 value = (unsigned char)va_arg(args, int);
5353             else value = va_arg(args, signed int);
5354 
5355             /* convert number to string */
5356             nk_itoa(number_buffer, value);
5357             num_len = nk_strlen(number_buffer);
5358             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5359             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5360                 padding = NK_MAX(padding-1, 0);
5361 
5362             /* fill left padding up to a total of `width` characters */
5363             if (!(flag & NK_ARG_FLAG_LEFT)) {
5364                 while (padding-- > 0 && (len < buf_size)) {
5365                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5366                         buf[len++] = '0';
5367                     else buf[len++] = ' ';
5368                 }
5369             }
5370 
5371             /* copy string value representation into buffer */
5372             if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
5373                 buf[len++] = '+';
5374             else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
5375                 buf[len++] = ' ';
5376 
5377             /* fill up to precision number of digits with '0' */
5378             num_print = NK_MAX(cur_precision, num_len);
5379             while (precision && (num_print > num_len) && (len < buf_size)) {
5380                 buf[len++] = '0';
5381                 num_print--;
5382             }
5383 
5384             /* copy string value representation into buffer */
5385             num_iter = number_buffer;
5386             while (precision && *num_iter && len < buf_size)
5387                 buf[len++] = *num_iter++;
5388 
5389             /* fill right padding up to width characters */
5390             if (flag & NK_ARG_FLAG_LEFT) {
5391                 while ((padding-- > 0) && (len < buf_size))
5392                     buf[len++] = ' ';
5393             }
5394         } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
5395             /* unsigned integer */
5396             unsigned long value = 0;
5397             int num_len = 0, num_print, padding = 0;
5398             int cur_precision = NK_MAX(precision, 1);
5399             int cur_width = NK_MAX(width, 0);
5400             unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
5401 
5402             /* print oct/hex/dec value */
5403             const char *upper_output_format = "0123456789ABCDEF";
5404             const char *lower_output_format = "0123456789abcdef";
5405             const char *output_format = (*iter == 'x') ?
5406                 lower_output_format: upper_output_format;
5407 
5408             /* retrieve correct value type */
5409             if (arg_type == NK_ARG_TYPE_CHAR)
5410                 value = (unsigned char)va_arg(args, int);
5411             else if (arg_type == NK_ARG_TYPE_SHORT)
5412                 value = (unsigned short)va_arg(args, int);
5413             else if (arg_type == NK_ARG_TYPE_LONG)
5414                 value = va_arg(args, unsigned long);
5415             else value = va_arg(args, unsigned int);
5416 
5417             do {
5418                 /* convert decimal number into hex/oct number */
5419                 int digit = output_format[value % base];
5420                 if (num_len < NK_MAX_NUMBER_BUFFER)
5421                     number_buffer[num_len++] = (char)digit;
5422                 value /= base;
5423             } while (value > 0);
5424 
5425             num_print = NK_MAX(cur_precision, num_len);
5426             padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5427             if (flag & NK_ARG_FLAG_NUM)
5428                 padding = NK_MAX(padding-1, 0);
5429 
5430             /* fill left padding up to a total of `width` characters */
5431             if (!(flag & NK_ARG_FLAG_LEFT)) {
5432                 while ((padding-- > 0) && (len < buf_size)) {
5433                     if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5434                         buf[len++] = '0';
5435                     else buf[len++] = ' ';
5436                 }
5437             }
5438 
5439             /* fill up to precision number of digits */
5440             if (num_print && (flag & NK_ARG_FLAG_NUM)) {
5441                 if ((*iter == 'o') && (len < buf_size)) {
5442                     buf[len++] = '0';
5443                 } else if ((*iter == 'x') && ((len+1) < buf_size)) {
5444                     buf[len++] = '0';
5445                     buf[len++] = 'x';
5446                 } else if ((*iter == 'X') && ((len+1) < buf_size)) {
5447                     buf[len++] = '0';
5448                     buf[len++] = 'X';
5449                 }
5450             }
5451             while (precision && (num_print > num_len) && (len < buf_size)) {
5452                 buf[len++] = '0';
5453                 num_print--;
5454             }
5455 
5456             /* reverse number direction */
5457             while (num_len > 0) {
5458                 if (precision && (len < buf_size))
5459                     buf[len++] = number_buffer[num_len-1];
5460                 num_len--;
5461             }
5462 
5463             /* fill right padding up to width characters */
5464             if (flag & NK_ARG_FLAG_LEFT) {
5465                 while ((padding-- > 0) && (len < buf_size))
5466                     buf[len++] = ' ';
5467             }
5468         } else if (*iter == 'f') {
5469             /* floating point */
5470             const char *num_iter;
5471             int cur_precision = (precision < 0) ? 6: precision;
5472             int prefix, cur_width = NK_MAX(width, 0);
5473             double value = va_arg(args, double);
5474             int num_len = 0, frac_len = 0, dot = 0;
5475             int padding = 0;
5476 
5477             NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5478             NK_DTOA(number_buffer, value);
5479             num_len = nk_strlen(number_buffer);
5480 
5481             /* calculate padding */
5482             num_iter = number_buffer;
5483             while (*num_iter && *num_iter != '.')
5484                 num_iter++;
5485 
5486             prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
5487             padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
5488             if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5489                 padding = NK_MAX(padding-1, 0);
5490 
5491             /* fill left padding up to a total of `width` characters */
5492             if (!(flag & NK_ARG_FLAG_LEFT)) {
5493                 while (padding-- > 0 && (len < buf_size)) {
5494                     if (flag & NK_ARG_FLAG_ZERO)
5495                         buf[len++] = '0';
5496                     else buf[len++] = ' ';
5497                 }
5498             }
5499 
5500             /* copy string value representation into buffer */
5501             num_iter = number_buffer;
5502             if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
5503                 buf[len++] = '+';
5504             else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
5505                 buf[len++] = ' ';
5506             while (*num_iter) {
5507                 if (dot) frac_len++;
5508                 if (len < buf_size)
5509                     buf[len++] = *num_iter;
5510                 if (*num_iter == '.') dot = 1;
5511                 if (frac_len >= cur_precision) break;
5512                 num_iter++;
5513             }
5514 
5515             /* fill number up to precision */
5516             while (frac_len < cur_precision) {
5517                 if (!dot && len < buf_size) {
5518                     buf[len++] = '.';
5519                     dot = 1;
5520                 }
5521                 if (len < buf_size)
5522                     buf[len++] = '0';
5523                 frac_len++;
5524             }
5525 
5526             /* fill right padding up to width characters */
5527             if (flag & NK_ARG_FLAG_LEFT) {
5528                 while ((padding-- > 0) && (len < buf_size))
5529                     buf[len++] = ' ';
5530             }
5531         } else {
5532             /* Specifier not supported: g,G,e,E,p,z */
5533             NK_ASSERT(0 && "specifier is not supported!");
5534             return result;
5535         }
5536     }
5537     buf[(len >= buf_size)?(buf_size-1):len] = 0;
5538     result = (len >= buf_size)?-1:len;
5539     return result;
5540 }
5541 #endif
5542 
5543 NK_INTERN int
5544 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
5545 {
5546     int result = -1;
5547     NK_ASSERT(buf);
5548     NK_ASSERT(buf_size);
5549     if (!buf || !buf_size || !fmt) return 0;
5550 #ifdef NK_INCLUDE_STANDARD_IO
5551     result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
5552     result = (result >= buf_size) ? -1: result;
5553     buf[buf_size-1] = 0;
5554 #else
5555     result = nk_vsnprintf(buf, buf_size, fmt, args);
5556 #endif
5557     return result;
5558 }
5559 #endif
5560 
5561 NK_API nk_hash
5562 nk_murmur_hash(const void * key, int len, nk_hash seed)
5563 {
5564     /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
5565     #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
5566     union {const nk_uint *i; const nk_byte *b;} conv = {0};
5567     const nk_byte *data = (const nk_byte*)key;
5568     const int nblocks = len/4;
5569     nk_uint h1 = seed;
5570     const nk_uint c1 = 0xcc9e2d51;
5571     const nk_uint c2 = 0x1b873593;
5572     const nk_byte *tail;
5573     const nk_uint *blocks;
5574     nk_uint k1;
5575     int i;
5576 
5577     /* body */
5578     if (!key) return 0;
5579     conv.b = (data + nblocks*4);
5580     blocks = (const nk_uint*)conv.i;
5581     for (i = -nblocks; i; ++i) {
5582         k1 = blocks[i];
5583         k1 *= c1;
5584         k1 = NK_ROTL(k1,15);
5585         k1 *= c2;
5586 
5587         h1 ^= k1;
5588         h1 = NK_ROTL(h1,13);
5589         h1 = h1*5+0xe6546b64;
5590     }
5591 
5592     /* tail */
5593     tail = (const nk_byte*)(data + nblocks*4);
5594     k1 = 0;
5595     switch (len & 3) {
5596     case 3: k1 ^= (nk_uint)(tail[2] << 16);
5597     case 2: k1 ^= (nk_uint)(tail[1] << 8u);
5598     case 1: k1 ^= tail[0];
5599             k1 *= c1;
5600             k1 = NK_ROTL(k1,15);
5601             k1 *= c2;
5602             h1 ^= k1;
5603     default: break;
5604     }
5605 
5606     /* finalization */
5607     h1 ^= (nk_uint)len;
5608     /* fmix32 */
5609     h1 ^= h1 >> 16;
5610     h1 *= 0x85ebca6b;
5611     h1 ^= h1 >> 13;
5612     h1 *= 0xc2b2ae35;
5613     h1 ^= h1 >> 16;
5614 
5615     #undef NK_ROTL
5616     return h1;
5617 }
5618 
5619 #ifdef NK_INCLUDE_STANDARD_IO
5620 NK_INTERN char*
5621 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
5622 {
5623     char *buf;
5624     FILE *fd;
5625     long ret;
5626 
5627     NK_ASSERT(path);
5628     NK_ASSERT(siz);
5629     NK_ASSERT(alloc);
5630     if (!path || !siz || !alloc)
5631         return 0;
5632 
5633     fd = fopen(path, "rb");
5634     if (!fd) return 0;
5635     fseek(fd, 0, SEEK_END);
5636     ret = ftell(fd);
5637     if (ret < 0) {
5638         fclose(fd);
5639         return 0;
5640     }
5641     *siz = (nk_size)ret;
5642     fseek(fd, 0, SEEK_SET);
5643     buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
5644     NK_ASSERT(buf);
5645     if (!buf) {
5646         fclose(fd);
5647         return 0;
5648     }
5649     *siz = (nk_size)fread(buf, 1,*siz, fd);
5650     fclose(fd);
5651     return buf;
5652 }
5653 #endif
5654 
5655 /*
5656  * ==============================================================
5657  *
5658  *                          COLOR
5659  *
5660  * ===============================================================
5661  */
5662 NK_INTERN int
5663 nk_parse_hex(const char *p, int length)
5664 {
5665     int i = 0;
5666     int len = 0;
5667     while (len < length) {
5668         i <<= 4;
5669         if (p[len] >= 'a' && p[len] <= 'f')
5670             i += ((p[len] - 'a') + 10);
5671         else if (p[len] >= 'A' && p[len] <= 'F')
5672             i += ((p[len] - 'A') + 10);
5673         else i += (p[len] - '0');
5674         len++;
5675     }
5676     return i;
5677 }
5678 
5679 NK_API struct nk_color
5680 nk_rgba(int r, int g, int b, int a)
5681 {
5682     struct nk_color ret;
5683     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5684     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5685     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5686     ret.a = (nk_byte)NK_CLAMP(0, a, 255);
5687     return ret;
5688 }
5689 
5690 NK_API struct nk_color
5691 nk_rgb_hex(const char *rgb)
5692 {
5693     struct nk_color col;
5694     const char *c = rgb;
5695     if (*c == '#') c++;
5696     col.r = (nk_byte)nk_parse_hex(c, 2);
5697     col.g = (nk_byte)nk_parse_hex(c+2, 2);
5698     col.b = (nk_byte)nk_parse_hex(c+4, 2);
5699     col.a = 255;
5700     return col;
5701 }
5702 
5703 NK_API struct nk_color
5704 nk_rgba_hex(const char *rgb)
5705 {
5706     struct nk_color col;
5707     const char *c = rgb;
5708     if (*c == '#') c++;
5709     col.r = (nk_byte)nk_parse_hex(c, 2);
5710     col.g = (nk_byte)nk_parse_hex(c+2, 2);
5711     col.b = (nk_byte)nk_parse_hex(c+4, 2);
5712     col.a = (nk_byte)nk_parse_hex(c+6, 2);
5713     return col;
5714 }
5715 
5716 NK_API void
5717 nk_color_hex_rgba(char *output, struct nk_color col)
5718 {
5719     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5720     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5721     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5722     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5723     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5724     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5725     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5726     output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
5727     output[7] = (char)NK_TO_HEX((col.a & 0x0F));
5728     output[8] = '\0';
5729     #undef NK_TO_HEX
5730 }
5731 
5732 NK_API void
5733 nk_color_hex_rgb(char *output, struct nk_color col)
5734 {
5735     #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5736     output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5737     output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5738     output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5739     output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5740     output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5741     output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5742     output[6] = '\0';
5743     #undef NK_TO_HEX
5744 }
5745 
5746 NK_API struct nk_color
5747 nk_rgba_iv(const int *c)
5748 {
5749     return nk_rgba(c[0], c[1], c[2], c[3]);
5750 }
5751 
5752 NK_API struct nk_color
5753 nk_rgba_bv(const nk_byte *c)
5754 {
5755     return nk_rgba(c[0], c[1], c[2], c[3]);
5756 }
5757 
5758 NK_API struct nk_color
5759 nk_rgb(int r, int g, int b)
5760 {
5761     struct nk_color ret;
5762     ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5763     ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5764     ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5765     ret.a = (nk_byte)255;
5766     return ret;
5767 }
5768 
5769 NK_API struct nk_color
5770 nk_rgb_iv(const int *c)
5771 {
5772     return nk_rgb(c[0], c[1], c[2]);
5773 }
5774 
5775 NK_API struct nk_color
5776 nk_rgb_bv(const nk_byte* c)
5777 {
5778     return nk_rgb(c[0], c[1], c[2]);
5779 }
5780 
5781 NK_API struct nk_color
5782 nk_rgba_u32(nk_uint in)
5783 {
5784     struct nk_color ret;
5785     ret.r = (in & 0xFF);
5786     ret.g = ((in >> 8) & 0xFF);
5787     ret.b = ((in >> 16) & 0xFF);
5788     ret.a = (nk_byte)((in >> 24) & 0xFF);
5789     return ret;
5790 }
5791 
5792 NK_API struct nk_color
5793 nk_rgba_f(float r, float g, float b, float a)
5794 {
5795     struct nk_color ret;
5796     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5797     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5798     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5799     ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
5800     return ret;
5801 }
5802 
5803 NK_API struct nk_color
5804 nk_rgba_fv(const float *c)
5805 {
5806     return nk_rgba_f(c[0], c[1], c[2], c[3]);
5807 }
5808 
5809 NK_API struct nk_color
5810 nk_rgb_f(float r, float g, float b)
5811 {
5812     struct nk_color ret;
5813     ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5814     ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5815     ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5816     ret.a = 255;
5817     return ret;
5818 }
5819 
5820 NK_API struct nk_color
5821 nk_rgb_fv(const float *c)
5822 {
5823     return nk_rgb_f(c[0], c[1], c[2]);
5824 }
5825 
5826 NK_API struct nk_color
5827 nk_hsv(int h, int s, int v)
5828 {
5829     return nk_hsva(h, s, v, 255);
5830 }
5831 
5832 NK_API struct nk_color
5833 nk_hsv_iv(const int *c)
5834 {
5835     return nk_hsv(c[0], c[1], c[2]);
5836 }
5837 
5838 NK_API struct nk_color
5839 nk_hsv_bv(const nk_byte *c)
5840 {
5841     return nk_hsv(c[0], c[1], c[2]);
5842 }
5843 
5844 NK_API struct nk_color
5845 nk_hsv_f(float h, float s, float v)
5846 {
5847     return nk_hsva_f(h, s, v, 1.0f);
5848 }
5849 
5850 NK_API struct nk_color
5851 nk_hsv_fv(const float *c)
5852 {
5853     return nk_hsv_f(c[0], c[1], c[2]);
5854 }
5855 
5856 NK_API struct nk_color
5857 nk_hsva(int h, int s, int v, int a)
5858 {
5859     float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
5860     float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
5861     float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
5862     float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
5863     return nk_hsva_f(hf, sf, vf, af);
5864 }
5865 
5866 NK_API struct nk_color
5867 nk_hsva_iv(const int *c)
5868 {
5869     return nk_hsva(c[0], c[1], c[2], c[3]);
5870 }
5871 
5872 NK_API struct nk_color
5873 nk_hsva_bv(const nk_byte *c)
5874 {
5875     return nk_hsva(c[0], c[1], c[2], c[3]);
5876 }
5877 
5878 NK_API struct nk_color
5879 nk_hsva_f(float h, float s, float v, float a)
5880 {
5881     struct nk_colorf out = {0,0,0,0};
5882     float p, q, t, f;
5883     int i;
5884 
5885     if (s <= 0.0f) {
5886         out.r = v; out.g = v; out.b = v;
5887         return nk_rgb_f(out.r, out.g, out.b);
5888     }
5889 
5890     h = h / (60.0f/360.0f);
5891     i = (int)h;
5892     f = h - (float)i;
5893     p = v * (1.0f - s);
5894     q = v * (1.0f - (s * f));
5895     t = v * (1.0f - s * (1.0f - f));
5896 
5897     switch (i) {
5898     case 0: default: out.r = v; out.g = t; out.b = p; break;
5899     case 1: out.r = q; out.g = v; out.b = p; break;
5900     case 2: out.r = p; out.g = v; out.b = t; break;
5901     case 3: out.r = p; out.g = q; out.b = v; break;
5902     case 4: out.r = t; out.g = p; out.b = v; break;
5903     case 5: out.r = v; out.g = p; out.b = q; break;
5904     }
5905     return nk_rgba_f(out.r, out.g, out.b, a);
5906 }
5907 
5908 NK_API struct nk_color
5909 nk_hsva_fv(const float *c)
5910 {
5911     return nk_hsva_f(c[0], c[1], c[2], c[3]);
5912 }
5913 
5914 NK_API nk_uint
5915 nk_color_u32(struct nk_color in)
5916 {
5917     nk_uint out = (nk_uint)in.r;
5918     out |= ((nk_uint)in.g << 8);
5919     out |= ((nk_uint)in.b << 16);
5920     out |= ((nk_uint)in.a << 24);
5921     return out;
5922 }
5923 
5924 NK_API void
5925 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
5926 {
5927     NK_STORAGE const float s = 1.0f/255.0f;
5928     *r = (float)in.r * s;
5929     *g = (float)in.g * s;
5930     *b = (float)in.b * s;
5931     *a = (float)in.a * s;
5932 }
5933 
5934 NK_API void
5935 nk_color_fv(float *c, struct nk_color in)
5936 {
5937     nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
5938 }
5939 
5940 NK_API void
5941 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
5942 {
5943     NK_STORAGE const double s = 1.0/255.0;
5944     *r = (double)in.r * s;
5945     *g = (double)in.g * s;
5946     *b = (double)in.b * s;
5947     *a = (double)in.a * s;
5948 }
5949 
5950 NK_API void
5951 nk_color_dv(double *c, struct nk_color in)
5952 {
5953     nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
5954 }
5955 
5956 NK_API void
5957 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
5958 {
5959     float a;
5960     nk_color_hsva_f(out_h, out_s, out_v, &a, in);
5961 }
5962 
5963 NK_API void
5964 nk_color_hsv_fv(float *out, struct nk_color in)
5965 {
5966     float a;
5967     nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
5968 }
5969 
5970 NK_API void
5971 nk_color_hsva_f(float *out_h, float *out_s,
5972     float *out_v, float *out_a, struct nk_color in)
5973 {
5974     float chroma;
5975     float K = 0.0f;
5976     float r,g,b,a;
5977 
5978     nk_color_f(&r,&g,&b,&a, in);
5979     if (g < b) {
5980         const float t = g; g = b; b = t;
5981         K = -1.f;
5982     }
5983     if (r < g) {
5984         const float t = r; r = g; g = t;
5985         K = -2.f/6.0f - K;
5986     }
5987     chroma = r - ((g < b) ? g: b);
5988     *out_h = NK_ABS(K + (g - b)/(6.0f * chroma + 1e-20f));
5989     *out_s = chroma / (r + 1e-20f);
5990     *out_v = r;
5991     *out_a = (float)in.a / 255.0f;
5992 }
5993 
5994 NK_API void
5995 nk_color_hsva_fv(float *out, struct nk_color in)
5996 {
5997     nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
5998 }
5999 
6000 NK_API void
6001 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
6002                 int *out_a, struct nk_color in)
6003 {
6004     float h,s,v,a;
6005     nk_color_hsva_f(&h, &s, &v, &a, in);
6006     *out_h = (nk_byte)(h * 255.0f);
6007     *out_s = (nk_byte)(s * 255.0f);
6008     *out_v = (nk_byte)(v * 255.0f);
6009     *out_a = (nk_byte)(a * 255.0f);
6010 }
6011 
6012 NK_API void
6013 nk_color_hsva_iv(int *out, struct nk_color in)
6014 {
6015     nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
6016 }
6017 
6018 NK_API void
6019 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
6020 {
6021     int tmp[4];
6022     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6023     out[0] = (nk_byte)tmp[0];
6024     out[1] = (nk_byte)tmp[1];
6025     out[2] = (nk_byte)tmp[2];
6026     out[3] = (nk_byte)tmp[3];
6027 }
6028 
6029 NK_API void
6030 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
6031 {
6032     int tmp[4];
6033     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6034     *h = (nk_byte)tmp[0];
6035     *s = (nk_byte)tmp[1];
6036     *v = (nk_byte)tmp[2];
6037     *a = (nk_byte)tmp[3];
6038 }
6039 
6040 NK_API void
6041 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
6042 {
6043     int a;
6044     nk_color_hsva_i(out_h, out_s, out_v, &a, in);
6045 }
6046 
6047 NK_API void
6048 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
6049 {
6050     int tmp[4];
6051     nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6052     *out_h = (nk_byte)tmp[0];
6053     *out_s = (nk_byte)tmp[1];
6054     *out_v = (nk_byte)tmp[2];
6055 }
6056 
6057 NK_API void
6058 nk_color_hsv_iv(int *out, struct nk_color in)
6059 {
6060     nk_color_hsv_i(&out[0], &out[1], &out[2], in);
6061 }
6062 
6063 NK_API void
6064 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
6065 {
6066     int tmp[4];
6067     nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
6068     out[0] = (nk_byte)tmp[0];
6069     out[1] = (nk_byte)tmp[1];
6070     out[2] = (nk_byte)tmp[2];
6071 }
6072 /*
6073  * ==============================================================
6074  *
6075  *                          IMAGE
6076  *
6077  * ===============================================================
6078  */
6079 NK_API nk_handle
6080 nk_handle_ptr(void *ptr)
6081 {
6082     nk_handle handle = {0};
6083     handle.ptr = ptr;
6084     return handle;
6085 }
6086 
6087 NK_API nk_handle
6088 nk_handle_id(int id)
6089 {
6090     nk_handle handle;
6091     nk_zero_struct(handle);
6092     handle.id = id;
6093     return handle;
6094 }
6095 
6096 NK_API struct nk_image
6097 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
6098 {
6099     struct nk_image s;
6100     nk_zero(&s, sizeof(s));
6101     s.handle.ptr = ptr;
6102     s.w = w; s.h = h;
6103     s.region[0] = (unsigned short)r.x;
6104     s.region[1] = (unsigned short)r.y;
6105     s.region[2] = (unsigned short)r.w;
6106     s.region[3] = (unsigned short)r.h;
6107     return s;
6108 }
6109 
6110 NK_API struct nk_image
6111 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
6112 {
6113     struct nk_image s;
6114     nk_zero(&s, sizeof(s));
6115     s.handle.id = id;
6116     s.w = w; s.h = h;
6117     s.region[0] = (unsigned short)r.x;
6118     s.region[1] = (unsigned short)r.y;
6119     s.region[2] = (unsigned short)r.w;
6120     s.region[3] = (unsigned short)r.h;
6121     return s;
6122 }
6123 
6124 NK_API struct nk_image
6125 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
6126     struct nk_rect r)
6127 {
6128     struct nk_image s;
6129     nk_zero(&s, sizeof(s));
6130     s.handle = handle;
6131     s.w = w; s.h = h;
6132     s.region[0] = (unsigned short)r.x;
6133     s.region[1] = (unsigned short)r.y;
6134     s.region[2] = (unsigned short)r.w;
6135     s.region[3] = (unsigned short)r.h;
6136     return s;
6137 }
6138 
6139 NK_API struct nk_image
6140 nk_image_handle(nk_handle handle)
6141 {
6142     struct nk_image s;
6143     nk_zero(&s, sizeof(s));
6144     s.handle = handle;
6145     s.w = 0; s.h = 0;
6146     s.region[0] = 0;
6147     s.region[1] = 0;
6148     s.region[2] = 0;
6149     s.region[3] = 0;
6150     return s;
6151 }
6152 
6153 NK_API struct nk_image
6154 nk_image_ptr(void *ptr)
6155 {
6156     struct nk_image s;
6157     nk_zero(&s, sizeof(s));
6158     NK_ASSERT(ptr);
6159     s.handle.ptr = ptr;
6160     s.w = 0; s.h = 0;
6161     s.region[0] = 0;
6162     s.region[1] = 0;
6163     s.region[2] = 0;
6164     s.region[3] = 0;
6165     return s;
6166 }
6167 
6168 NK_API struct nk_image
6169 nk_image_id(int id)
6170 {
6171     struct nk_image s;
6172     nk_zero(&s, sizeof(s));
6173     s.handle.id = id;
6174     s.w = 0; s.h = 0;
6175     s.region[0] = 0;
6176     s.region[1] = 0;
6177     s.region[2] = 0;
6178     s.region[3] = 0;
6179     return s;
6180 }
6181 
6182 NK_API int
6183 nk_image_is_subimage(const struct nk_image* img)
6184 {
6185     NK_ASSERT(img);
6186     return !(img->w == 0 && img->h == 0);
6187 }
6188 
6189 NK_INTERN void
6190 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6191     float x1, float y1)
6192 {
6193     NK_ASSERT(a);
6194     NK_ASSERT(clip);
6195     clip->x = NK_MAX(a->x, x0);
6196     clip->y = NK_MAX(a->y, y0);
6197     clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6198     clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6199     clip->w = NK_MAX(0, clip->w);
6200     clip->h = NK_MAX(0, clip->h);
6201 }
6202 
6203 NK_API void
6204 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
6205     float pad_x, float pad_y, enum nk_heading direction)
6206 {
6207     float w_half, h_half;
6208     NK_ASSERT(result);
6209 
6210     r.w = NK_MAX(2 * pad_x, r.w);
6211     r.h = NK_MAX(2 * pad_y, r.h);
6212     r.w = r.w - 2 * pad_x;
6213     r.h = r.h - 2 * pad_y;
6214 
6215     r.x = r.x + pad_x;
6216     r.y = r.y + pad_y;
6217 
6218     w_half = r.w / 2.0f;
6219     h_half = r.h / 2.0f;
6220 
6221     if (direction == NK_UP) {
6222         result[0] = nk_vec2(r.x + w_half, r.y);
6223         result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6224         result[2] = nk_vec2(r.x, r.y + r.h);
6225     } else if (direction == NK_RIGHT) {
6226         result[0] = nk_vec2(r.x, r.y);
6227         result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6228         result[2] = nk_vec2(r.x, r.y + r.h);
6229     } else if (direction == NK_DOWN) {
6230         result[0] = nk_vec2(r.x, r.y);
6231         result[1] = nk_vec2(r.x + r.w, r.y);
6232         result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6233     } else {
6234         result[0] = nk_vec2(r.x, r.y + h_half);
6235         result[1] = nk_vec2(r.x + r.w, r.y);
6236         result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6237     }
6238 }
6239 
6240 NK_INTERN int
6241 nk_text_clamp(const struct nk_user_font *font, const char *text,
6242     int text_len, float space, int *glyphs, float *text_width,
6243     nk_rune *sep_list, int sep_count)
6244 {
6245     int i = 0;
6246     int glyph_len = 0;
6247     float last_width = 0;
6248     nk_rune unicode = 0;
6249     float width = 0;
6250     int len = 0;
6251     int g = 0;
6252     float s;
6253 
6254     int sep_len = 0;
6255     int sep_g = 0;
6256     float sep_width = 0;
6257     sep_count = NK_MAX(sep_count,0);
6258 
6259     glyph_len = nk_utf_decode(text, &unicode, text_len);
6260     while (glyph_len && (width < space) && (len < text_len)) {
6261         len += glyph_len;
6262         s = font->width(font->userdata, font->height, text, len);
6263         for (i = 0; i < sep_count; ++i) {
6264             if (unicode != sep_list[i]) continue;
6265             sep_width = last_width = width;
6266             sep_g = g+1;
6267             sep_len = len;
6268             break;
6269         }
6270         if (i == sep_count){
6271             last_width = sep_width = width;
6272             sep_g = g+1;
6273         }
6274         width = s;
6275         glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
6276         g++;
6277     }
6278     if (len >= text_len) {
6279         *glyphs = g;
6280         *text_width = last_width;
6281         return len;
6282     } else {
6283         *glyphs = sep_g;
6284         *text_width = sep_width;
6285         return (!sep_len) ? len: sep_len;
6286     }
6287 }
6288 
6289 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
6290 NK_INTERN struct nk_vec2
6291 nk_text_calculate_text_bounds(const struct nk_user_font *font,
6292     const char *begin, int byte_len, float row_height, const char **remaining,
6293     struct nk_vec2 *out_offset, int *glyphs, int op)
6294 {
6295     float line_height = row_height;
6296     struct nk_vec2 text_size = nk_vec2(0,0);
6297     float line_width = 0.0f;
6298 
6299     float glyph_width;
6300     int glyph_len = 0;
6301     nk_rune unicode = 0;
6302     int text_len = 0;
6303     if (!begin || byte_len <= 0 || !font)
6304         return nk_vec2(0,row_height);
6305 
6306     glyph_len = nk_utf_decode(begin, &unicode, byte_len);
6307     if (!glyph_len) return text_size;
6308     glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
6309 
6310     *glyphs = 0;
6311     while ((text_len < byte_len) && glyph_len) {
6312         if (unicode == '\n') {
6313             text_size.x = NK_MAX(text_size.x, line_width);
6314             text_size.y += line_height;
6315             line_width = 0;
6316             *glyphs+=1;
6317             if (op == NK_STOP_ON_NEW_LINE)
6318                 break;
6319 
6320             text_len++;
6321             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6322             continue;
6323         }
6324 
6325         if (unicode == '\r') {
6326             text_len++;
6327             *glyphs+=1;
6328             glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6329             continue;
6330         }
6331 
6332         *glyphs = *glyphs + 1;
6333         text_len += glyph_len;
6334         line_width += (float)glyph_width;
6335         glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6336         glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
6337         continue;
6338     }
6339 
6340     if (text_size.x < line_width)
6341         text_size.x = line_width;
6342     if (out_offset)
6343         *out_offset = nk_vec2(line_width, text_size.y + line_height);
6344     if (line_width > 0 || text_size.y == 0.0f)
6345         text_size.y += line_height;
6346     if (remaining)
6347         *remaining = begin+text_len;
6348     return text_size;
6349 }
6350 
6351 /* ==============================================================
6352  *
6353  *                          UTF-8
6354  *
6355  * ===============================================================*/
6356 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
6357 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
6358 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
6359 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
6360 
6361 NK_INTERN int
6362 nk_utf_validate(nk_rune *u, int i)
6363 {
6364     NK_ASSERT(u);
6365     if (!u) return 0;
6366     if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
6367          NK_BETWEEN(*u, 0xD800, 0xDFFF))
6368             *u = NK_UTF_INVALID;
6369     for (i = 1; *u > nk_utfmax[i]; ++i);
6370     return i;
6371 }
6372 
6373 NK_INTERN nk_rune
6374 nk_utf_decode_byte(char c, int *i)
6375 {
6376     NK_ASSERT(i);
6377     if (!i) return 0;
6378     for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
6379         if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
6380             return (nk_byte)(c & ~nk_utfmask[*i]);
6381     }
6382     return 0;
6383 }
6384 
6385 NK_API int
6386 nk_utf_decode(const char *c, nk_rune *u, int clen)
6387 {
6388     int i, j, len, type=0;
6389     nk_rune udecoded;
6390 
6391     NK_ASSERT(c);
6392     NK_ASSERT(u);
6393 
6394     if (!c || !u) return 0;
6395     if (!clen) return 0;
6396     *u = NK_UTF_INVALID;
6397 
6398     udecoded = nk_utf_decode_byte(c[0], &len);
6399     if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
6400         return 1;
6401 
6402     for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
6403         udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
6404         if (type != 0)
6405             return j;
6406     }
6407     if (j < len)
6408         return 0;
6409     *u = udecoded;
6410     nk_utf_validate(u, len);
6411     return len;
6412 }
6413 
6414 NK_INTERN char
6415 nk_utf_encode_byte(nk_rune u, int i)
6416 {
6417     return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
6418 }
6419 
6420 NK_API int
6421 nk_utf_encode(nk_rune u, char *c, int clen)
6422 {
6423     int len, i;
6424     len = nk_utf_validate(&u, 0);
6425     if (clen < len || !len || len > NK_UTF_SIZE)
6426         return 0;
6427 
6428     for (i = len - 1; i != 0; --i) {
6429         c[i] = nk_utf_encode_byte(u, 0);
6430         u >>= 6;
6431     }
6432     c[0] = nk_utf_encode_byte(u, len);
6433     return len;
6434 }
6435 
6436 NK_API int
6437 nk_utf_len(const char *str, int len)
6438 {
6439     const char *text;
6440     int glyphs = 0;
6441     int text_len;
6442     int glyph_len;
6443     int src_len = 0;
6444     nk_rune unicode;
6445 
6446     NK_ASSERT(str);
6447     if (!str || !len) return 0;
6448 
6449     text = str;
6450     text_len = len;
6451     glyph_len = nk_utf_decode(text, &unicode, text_len);
6452     while (glyph_len && src_len < len) {
6453         glyphs++;
6454         src_len = src_len + glyph_len;
6455         glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
6456     }
6457     return glyphs;
6458 }
6459 
6460 NK_API const char*
6461 nk_utf_at(const char *buffer, int length, int index,
6462     nk_rune *unicode, int *len)
6463 {
6464     int i = 0;
6465     int src_len = 0;
6466     int glyph_len = 0;
6467     const char *text;
6468     int text_len;
6469 
6470     NK_ASSERT(buffer);
6471     NK_ASSERT(unicode);
6472     NK_ASSERT(len);
6473 
6474     if (!buffer || !unicode || !len) return 0;
6475     if (index < 0) {
6476         *unicode = NK_UTF_INVALID;
6477         *len = 0;
6478         return 0;
6479     }
6480 
6481     text = buffer;
6482     text_len = length;
6483     glyph_len = nk_utf_decode(text, unicode, text_len);
6484     while (glyph_len) {
6485         if (i == index) {
6486             *len = glyph_len;
6487             break;
6488         }
6489 
6490         i++;
6491         src_len = src_len + glyph_len;
6492         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
6493     }
6494     if (i != index) return 0;
6495     return buffer + src_len;
6496 }
6497 
6498 /* ==============================================================
6499  *
6500  *                          BUFFER
6501  *
6502  * ===============================================================*/
6503 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6504 NK_INTERN void* nk_malloc(nk_handle unused, void *old,nk_size size)
6505 {NK_UNUSED(unused); NK_UNUSED(old); return malloc(size);}
6506 NK_INTERN void nk_mfree(nk_handle unused, void *ptr)
6507 {NK_UNUSED(unused); free(ptr);}
6508 
6509 NK_API void
6510 nk_buffer_init_default(struct nk_buffer *buffer)
6511 {
6512     struct nk_allocator alloc;
6513     alloc.userdata.ptr = 0;
6514     alloc.alloc = nk_malloc;
6515     alloc.free = nk_mfree;
6516     nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
6517 }
6518 #endif
6519 
6520 NK_API void
6521 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
6522     nk_size initial_size)
6523 {
6524     NK_ASSERT(b);
6525     NK_ASSERT(a);
6526     NK_ASSERT(initial_size);
6527     if (!b || !a || !initial_size) return;
6528 
6529     nk_zero(b, sizeof(*b));
6530     b->type = NK_BUFFER_DYNAMIC;
6531     b->memory.ptr = a->alloc(a->userdata,0, initial_size);
6532     b->memory.size = initial_size;
6533     b->size = initial_size;
6534     b->grow_factor = 2.0f;
6535     b->pool = *a;
6536 }
6537 
6538 NK_API void
6539 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
6540 {
6541     NK_ASSERT(b);
6542     NK_ASSERT(m);
6543     NK_ASSERT(size);
6544     if (!b || !m || !size) return;
6545 
6546     nk_zero(b, sizeof(*b));
6547     b->type = NK_BUFFER_FIXED;
6548     b->memory.ptr = m;
6549     b->memory.size = size;
6550     b->size = size;
6551 }
6552 
6553 NK_INTERN void*
6554 nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment,
6555     enum nk_buffer_allocation_type type)
6556 {
6557     void *memory = 0;
6558     switch (type) {
6559     default:
6560     case NK_BUFFER_MAX:
6561     case NK_BUFFER_FRONT:
6562         if (align) {
6563             memory = NK_ALIGN_PTR(unaligned, align);
6564             *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
6565         } else {
6566             memory = unaligned;
6567             *alignment = 0;
6568         }
6569         break;
6570     case NK_BUFFER_BACK:
6571         if (align) {
6572             memory = NK_ALIGN_PTR_BACK(unaligned, align);
6573             *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
6574         } else {
6575             memory = unaligned;
6576             *alignment = 0;
6577         }
6578         break;
6579     }
6580     return memory;
6581 }
6582 
6583 NK_INTERN void*
6584 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
6585 {
6586     void *temp;
6587     nk_size buffer_size;
6588 
6589     NK_ASSERT(b);
6590     NK_ASSERT(size);
6591     if (!b || !size || !b->pool.alloc || !b->pool.free)
6592         return 0;
6593 
6594     buffer_size = b->memory.size;
6595     temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
6596     NK_ASSERT(temp);
6597     if (!temp) return 0;
6598 
6599     *size = capacity;
6600     if (temp != b->memory.ptr) {
6601         NK_MEMCPY(temp, b->memory.ptr, buffer_size);
6602         b->pool.free(b->pool.userdata, b->memory.ptr);
6603     }
6604 
6605     if (b->size == buffer_size) {
6606         /* no back buffer so just set correct size */
6607         b->size = capacity;
6608         return temp;
6609     } else {
6610         /* copy back buffer to the end of the new buffer */
6611         void *dst, *src;
6612         nk_size back_size;
6613         back_size = buffer_size - b->size;
6614         dst = nk_ptr_add(void, temp, capacity - back_size);
6615         src = nk_ptr_add(void, temp, b->size);
6616         NK_MEMCPY(dst, src, back_size);
6617         b->size = capacity - back_size;
6618     }
6619     return temp;
6620 }
6621 
6622 NK_INTERN void*
6623 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
6624     nk_size size, nk_size align)
6625 {
6626     int full;
6627     nk_size alignment;
6628     void *unaligned;
6629     void *memory;
6630 
6631     NK_ASSERT(b);
6632     NK_ASSERT(size);
6633     if (!b || !size) return 0;
6634     b->needed += size;
6635 
6636     /* calculate total size with needed alignment + size */
6637     if (type == NK_BUFFER_FRONT)
6638         unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6639     else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6640     memory = nk_buffer_align(unaligned, align, &alignment, type);
6641 
6642     /* check if buffer has enough memory*/
6643     if (type == NK_BUFFER_FRONT)
6644         full = ((b->allocated + size + alignment) > b->size);
6645     else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
6646 
6647     if (full) {
6648         nk_size capacity;
6649         if (b->type != NK_BUFFER_DYNAMIC)
6650             return 0;
6651         NK_ASSERT(b->pool.alloc && b->pool.free);
6652         if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
6653             return 0;
6654 
6655         /* buffer is full so allocate bigger buffer if dynamic */
6656         capacity = (nk_size)((float)b->memory.size * b->grow_factor);
6657         capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
6658         b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
6659         if (!b->memory.ptr) return 0;
6660 
6661         /* align newly allocated pointer */
6662         if (type == NK_BUFFER_FRONT)
6663             unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6664         else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6665         memory = nk_buffer_align(unaligned, align, &alignment, type);
6666     }
6667     if (type == NK_BUFFER_FRONT)
6668         b->allocated += size + alignment;
6669     else b->size -= (size + alignment);
6670     b->needed += alignment;
6671     b->calls++;
6672     return memory;
6673 }
6674 
6675 NK_API void
6676 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type,
6677     const void *memory, nk_size size, nk_size align)
6678 {
6679     void *mem = nk_buffer_alloc(b, type, size, align);
6680     if (!mem) return;
6681     NK_MEMCPY(mem, memory, size);
6682 }
6683 
6684 NK_API void
6685 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
6686 {
6687     NK_ASSERT(buffer);
6688     if (!buffer) return;
6689     buffer->marker[type].active = nk_true;
6690     if (type == NK_BUFFER_BACK)
6691         buffer->marker[type].offset = buffer->size;
6692     else buffer->marker[type].offset = buffer->allocated;
6693 }
6694 
6695 NK_API void
6696 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
6697 {
6698     NK_ASSERT(buffer);
6699     if (!buffer) return;
6700     if (type == NK_BUFFER_BACK) {
6701         /* reset back buffer either back to marker or empty */
6702         buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
6703         if (buffer->marker[type].active)
6704             buffer->size = buffer->marker[type].offset;
6705         else buffer->size = buffer->memory.size;
6706         buffer->marker[type].active = nk_false;
6707     } else {
6708         /* reset front buffer either back to back marker or empty */
6709         buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
6710         if (buffer->marker[type].active)
6711             buffer->allocated = buffer->marker[type].offset;
6712         else buffer->allocated = 0;
6713         buffer->marker[type].active = nk_false;
6714     }
6715 }
6716 
6717 NK_API void
6718 nk_buffer_clear(struct nk_buffer *b)
6719 {
6720     NK_ASSERT(b);
6721     if (!b) return;
6722     b->allocated = 0;
6723     b->size = b->memory.size;
6724     b->calls = 0;
6725     b->needed = 0;
6726 }
6727 
6728 NK_API void
6729 nk_buffer_free(struct nk_buffer *b)
6730 {
6731     NK_ASSERT(b);
6732     if (!b || !b->memory.ptr) return;
6733     if (b->type == NK_BUFFER_FIXED) return;
6734     if (!b->pool.free) return;
6735     NK_ASSERT(b->pool.free);
6736     b->pool.free(b->pool.userdata, b->memory.ptr);
6737 }
6738 
6739 NK_API void
6740 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
6741 {
6742     NK_ASSERT(b);
6743     NK_ASSERT(s);
6744     if (!s || !b) return;
6745     s->allocated = b->allocated;
6746     s->size =  b->memory.size;
6747     s->needed = b->needed;
6748     s->memory = b->memory.ptr;
6749     s->calls = b->calls;
6750 }
6751 
6752 NK_API void*
6753 nk_buffer_memory(struct nk_buffer *buffer)
6754 {
6755     NK_ASSERT(buffer);
6756     if (!buffer) return 0;
6757     return buffer->memory.ptr;
6758 }
6759 
6760 NK_API const void*
6761 nk_buffer_memory_const(const struct nk_buffer *buffer)
6762 {
6763     NK_ASSERT(buffer);
6764     if (!buffer) return 0;
6765     return buffer->memory.ptr;
6766 }
6767 
6768 NK_API nk_size
6769 nk_buffer_total(struct nk_buffer *buffer)
6770 {
6771     NK_ASSERT(buffer);
6772     if (!buffer) return 0;
6773     return buffer->memory.size;
6774 }
6775 
6776 /*
6777  * ==============================================================
6778  *
6779  *                          STRING
6780  *
6781  * ===============================================================
6782  */
6783 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6784 NK_API void
6785 nk_str_init_default(struct nk_str *str)
6786 {
6787     struct nk_allocator alloc;
6788     alloc.userdata.ptr = 0;
6789     alloc.alloc = nk_malloc;
6790     alloc.free = nk_mfree;
6791     nk_buffer_init(&str->buffer, &alloc, 32);
6792     str->len = 0;
6793 }
6794 #endif
6795 
6796 NK_API void
6797 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
6798 {
6799     nk_buffer_init(&str->buffer, alloc, size);
6800     str->len = 0;
6801 }
6802 
6803 NK_API void
6804 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
6805 {
6806     nk_buffer_init_fixed(&str->buffer, memory, size);
6807     str->len = 0;
6808 }
6809 
6810 NK_API int
6811 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
6812 {
6813     char *mem;
6814     NK_ASSERT(s);
6815     NK_ASSERT(str);
6816     if (!s || !str || !len) return 0;
6817     mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6818     if (!mem) return 0;
6819     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6820     s->len += nk_utf_len(str, len);
6821     return len;
6822 }
6823 
6824 NK_API int
6825 nk_str_append_str_char(struct nk_str *s, const char *str)
6826 {
6827     return nk_str_append_text_char(s, str, nk_strlen(str));
6828 }
6829 
6830 NK_API int
6831 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
6832 {
6833     int i = 0;
6834     int byte_len = 0;
6835     nk_rune unicode;
6836     if (!str || !text || !len) return 0;
6837     for (i = 0; i < len; ++i)
6838         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6839     nk_str_append_text_char(str, text, byte_len);
6840     return len;
6841 }
6842 
6843 NK_API int
6844 nk_str_append_str_utf8(struct nk_str *str, const char *text)
6845 {
6846     int runes = 0;
6847     int byte_len = 0;
6848     int num_runes = 0;
6849     int glyph_len = 0;
6850     nk_rune unicode;
6851     if (!str || !text) return 0;
6852 
6853     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6854     while (unicode != '\0' && glyph_len) {
6855         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6856         byte_len += glyph_len;
6857         num_runes++;
6858     }
6859     nk_str_append_text_char(str, text, byte_len);
6860     return runes;
6861 }
6862 
6863 NK_API int
6864 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
6865 {
6866     int i = 0;
6867     int byte_len = 0;
6868     nk_glyph glyph;
6869 
6870     NK_ASSERT(str);
6871     if (!str || !text || !len) return 0;
6872     for (i = 0; i < len; ++i) {
6873         byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
6874         if (!byte_len) break;
6875         nk_str_append_text_char(str, glyph, byte_len);
6876     }
6877     return len;
6878 }
6879 
6880 NK_API int
6881 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
6882 {
6883     int i = 0;
6884     nk_glyph glyph;
6885     int byte_len;
6886     NK_ASSERT(str);
6887     if (!str || !runes) return 0;
6888     while (runes[i] != '\0') {
6889         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6890         nk_str_append_text_char(str, glyph, byte_len);
6891         i++;
6892     }
6893     return i;
6894 }
6895 
6896 NK_API int
6897 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
6898 {
6899     int i;
6900     void *mem;
6901     char *src;
6902     char *dst;
6903 
6904     int copylen;
6905     NK_ASSERT(s);
6906     NK_ASSERT(str);
6907     NK_ASSERT(len >= 0);
6908     if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
6909     if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
6910         (s->buffer.type == NK_BUFFER_FIXED)) return 0;
6911 
6912     copylen = (int)s->buffer.allocated - pos;
6913     if (!copylen) {
6914         nk_str_append_text_char(s, str, len);
6915         return 1;
6916     }
6917     mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6918     if (!mem) return 0;
6919 
6920     /* memmove */
6921     NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
6922     NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
6923     dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
6924     src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
6925     for (i = 0; i < copylen; ++i) *dst-- = *src--;
6926     mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
6927     NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6928     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6929     return 1;
6930 }
6931 
6932 NK_API int
6933 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
6934 {
6935     int glyph_len;
6936     nk_rune unicode;
6937     const char *begin;
6938     const char *buffer;
6939 
6940     NK_ASSERT(str);
6941     NK_ASSERT(cstr);
6942     NK_ASSERT(len);
6943     if (!str || !cstr || !len) return 0;
6944     begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
6945     if (!str->len)
6946         return nk_str_append_text_char(str, cstr, len);
6947     buffer = nk_str_get_const(str);
6948     if (!begin) return 0;
6949     return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
6950 }
6951 
6952 NK_API int
6953 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
6954 {
6955     return nk_str_insert_text_utf8(str, pos, text, len);
6956 }
6957 
6958 NK_API int
6959 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
6960 {
6961     return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
6962 }
6963 
6964 NK_API int
6965 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
6966 {
6967     int i = 0;
6968     int byte_len = 0;
6969     nk_rune unicode;
6970 
6971     NK_ASSERT(str);
6972     NK_ASSERT(text);
6973     if (!str || !text || !len) return 0;
6974     for (i = 0; i < len; ++i)
6975         byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6976     nk_str_insert_at_rune(str, pos, text, byte_len);
6977     return len;
6978 }
6979 
6980 NK_API int
6981 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
6982 {
6983     int runes = 0;
6984     int byte_len = 0;
6985     int num_runes = 0;
6986     int glyph_len = 0;
6987     nk_rune unicode;
6988     if (!str || !text) return 0;
6989 
6990     glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6991     while (unicode != '\0' && glyph_len) {
6992         glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6993         byte_len += glyph_len;
6994         num_runes++;
6995     }
6996     nk_str_insert_at_rune(str, pos, text, byte_len);
6997     return runes;
6998 }
6999 
7000 NK_API int
7001 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
7002 {
7003     int i = 0;
7004     int byte_len = 0;
7005     nk_glyph glyph;
7006 
7007     NK_ASSERT(str);
7008     if (!str || !runes || !len) return 0;
7009     for (i = 0; i < len; ++i) {
7010         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
7011         if (!byte_len) break;
7012         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
7013     }
7014     return len;
7015 }
7016 
7017 NK_API int
7018 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
7019 {
7020     int i = 0;
7021     nk_glyph glyph;
7022     int byte_len;
7023     NK_ASSERT(str);
7024     if (!str || !runes) return 0;
7025     while (runes[i] != '\0') {
7026         byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
7027         nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
7028         i++;
7029     }
7030     return i;
7031 }
7032 
7033 NK_API void
7034 nk_str_remove_chars(struct nk_str *s, int len)
7035 {
7036     NK_ASSERT(s);
7037     NK_ASSERT(len >= 0);
7038     if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
7039     NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
7040     s->buffer.allocated -= (nk_size)len;
7041     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
7042 }
7043 
7044 NK_API void
7045 nk_str_remove_runes(struct nk_str *str, int len)
7046 {
7047     int index;
7048     const char *begin;
7049     const char *end;
7050     nk_rune unicode;
7051 
7052     NK_ASSERT(str);
7053     NK_ASSERT(len >= 0);
7054     if (!str || len < 0) return;
7055     if (len >= str->len) {
7056         str->len = 0;
7057         return;
7058     }
7059 
7060     index = str->len - len;
7061     begin = nk_str_at_rune(str, index, &unicode, &len);
7062     end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
7063     nk_str_remove_chars(str, (int)(end-begin)+1);
7064 }
7065 
7066 NK_API void
7067 nk_str_delete_chars(struct nk_str *s, int pos, int len)
7068 {
7069     NK_ASSERT(s);
7070     if (!s || !len || (nk_size)pos > s->buffer.allocated ||
7071         (nk_size)(pos + len) > s->buffer.allocated) return;
7072 
7073     if ((nk_size)(pos + len) < s->buffer.allocated) {
7074         /* memmove */
7075         char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
7076         char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
7077         NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
7078         NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
7079         s->buffer.allocated -= (nk_size)len;
7080     } else nk_str_remove_chars(s, len);
7081     s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
7082 }
7083 
7084 NK_API void
7085 nk_str_delete_runes(struct nk_str *s, int pos, int len)
7086 {
7087     char *temp;
7088     nk_rune unicode;
7089     char *begin;
7090     char *end;
7091     int unused;
7092 
7093     NK_ASSERT(s);
7094     NK_ASSERT(s->len >= pos + len);
7095     if (s->len < pos + len)
7096         len = NK_CLAMP(0, (s->len - pos), s->len);
7097     if (!len) return;
7098 
7099     temp = (char *)s->buffer.memory.ptr;
7100     begin = nk_str_at_rune(s, pos, &unicode, &unused);
7101     if (!begin) return;
7102     s->buffer.memory.ptr = begin;
7103     end = nk_str_at_rune(s, len, &unicode, &unused);
7104     s->buffer.memory.ptr = temp;
7105     if (!end) return;
7106     nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
7107 }
7108 
7109 NK_API char*
7110 nk_str_at_char(struct nk_str *s, int pos)
7111 {
7112     NK_ASSERT(s);
7113     if (!s || pos > (int)s->buffer.allocated) return 0;
7114     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
7115 }
7116 
7117 NK_API char*
7118 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
7119 {
7120     int i = 0;
7121     int src_len = 0;
7122     int glyph_len = 0;
7123     char *text;
7124     int text_len;
7125 
7126     NK_ASSERT(str);
7127     NK_ASSERT(unicode);
7128     NK_ASSERT(len);
7129 
7130     if (!str || !unicode || !len) return 0;
7131     if (pos < 0) {
7132         *unicode = 0;
7133         *len = 0;
7134         return 0;
7135     }
7136 
7137     text = (char*)str->buffer.memory.ptr;
7138     text_len = (int)str->buffer.allocated;
7139     glyph_len = nk_utf_decode(text, unicode, text_len);
7140     while (glyph_len) {
7141         if (i == pos) {
7142             *len = glyph_len;
7143             break;
7144         }
7145 
7146         i++;
7147         src_len = src_len + glyph_len;
7148         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7149     }
7150     if (i != pos) return 0;
7151     return text + src_len;
7152 }
7153 
7154 NK_API const char*
7155 nk_str_at_char_const(const struct nk_str *s, int pos)
7156 {
7157     NK_ASSERT(s);
7158     if (!s || pos > (int)s->buffer.allocated) return 0;
7159     return nk_ptr_add(char, s->buffer.memory.ptr, pos);
7160 }
7161 
7162 NK_API const char*
7163 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
7164 {
7165     int i = 0;
7166     int src_len = 0;
7167     int glyph_len = 0;
7168     char *text;
7169     int text_len;
7170 
7171     NK_ASSERT(str);
7172     NK_ASSERT(unicode);
7173     NK_ASSERT(len);
7174 
7175     if (!str || !unicode || !len) return 0;
7176     if (pos < 0) {
7177         *unicode = 0;
7178         *len = 0;
7179         return 0;
7180     }
7181 
7182     text = (char*)str->buffer.memory.ptr;
7183     text_len = (int)str->buffer.allocated;
7184     glyph_len = nk_utf_decode(text, unicode, text_len);
7185     while (glyph_len) {
7186         if (i == pos) {
7187             *len = glyph_len;
7188             break;
7189         }
7190 
7191         i++;
7192         src_len = src_len + glyph_len;
7193         glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7194     }
7195     if (i != pos) return 0;
7196     return text + src_len;
7197 }
7198 
7199 NK_API nk_rune
7200 nk_str_rune_at(const struct nk_str *str, int pos)
7201 {
7202     int len;
7203     nk_rune unicode = 0;
7204     nk_str_at_const(str, pos, &unicode, &len);
7205     return unicode;
7206 }
7207 
7208 NK_API char*
7209 nk_str_get(struct nk_str *s)
7210 {
7211     NK_ASSERT(s);
7212     if (!s || !s->len || !s->buffer.allocated) return 0;
7213     return (char*)s->buffer.memory.ptr;
7214 }
7215 
7216 NK_API const char*
7217 nk_str_get_const(const struct nk_str *s)
7218 {
7219     NK_ASSERT(s);
7220     if (!s || !s->len || !s->buffer.allocated) return 0;
7221     return (const char*)s->buffer.memory.ptr;
7222 }
7223 
7224 NK_API int
7225 nk_str_len(struct nk_str *s)
7226 {
7227     NK_ASSERT(s);
7228     if (!s || !s->len || !s->buffer.allocated) return 0;
7229     return s->len;
7230 }
7231 
7232 NK_API int
7233 nk_str_len_char(struct nk_str *s)
7234 {
7235     NK_ASSERT(s);
7236     if (!s || !s->len || !s->buffer.allocated) return 0;
7237     return (int)s->buffer.allocated;
7238 }
7239 
7240 NK_API void
7241 nk_str_clear(struct nk_str *str)
7242 {
7243     NK_ASSERT(str);
7244     nk_buffer_clear(&str->buffer);
7245     str->len = 0;
7246 }
7247 
7248 NK_API void
7249 nk_str_free(struct nk_str *str)
7250 {
7251     NK_ASSERT(str);
7252     nk_buffer_free(&str->buffer);
7253     str->len = 0;
7254 }
7255 
7256 /*
7257  * ==============================================================
7258  *
7259  *                      Command buffer
7260  *
7261  * ===============================================================
7262 */
7263 NK_INTERN void
7264 nk_command_buffer_init(struct nk_command_buffer *cmdbuf,
7265     struct nk_buffer *buffer, enum nk_command_clipping clip)
7266 {
7267     NK_ASSERT(cmdbuf);
7268     NK_ASSERT(buffer);
7269     if (!cmdbuf || !buffer) return;
7270     cmdbuf->base = buffer;
7271     cmdbuf->use_clipping = clip;
7272     cmdbuf->begin = buffer->allocated;
7273     cmdbuf->end = buffer->allocated;
7274     cmdbuf->last = buffer->allocated;
7275 }
7276 
7277 NK_INTERN void
7278 nk_command_buffer_reset(struct nk_command_buffer *buffer)
7279 {
7280     NK_ASSERT(buffer);
7281     if (!buffer) return;
7282     buffer->begin = 0;
7283     buffer->end = 0;
7284     buffer->last = 0;
7285     buffer->clip = nk_null_rect;
7286 #ifdef NK_INCLUDE_COMMAND_USERDATA
7287     buffer->userdata.ptr = 0;
7288 #endif
7289 }
7290 
7291 NK_INTERN void*
7292 nk_command_buffer_push(struct nk_command_buffer* b,
7293     enum nk_command_type t, nk_size size)
7294 {
7295     NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
7296     struct nk_command *cmd;
7297     nk_size alignment;
7298     void *unaligned;
7299     void *memory;
7300 
7301     NK_ASSERT(b);
7302     NK_ASSERT(b->base);
7303     if (!b) return 0;
7304     cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
7305     if (!cmd) return 0;
7306 
7307     /* make sure the offset to the next command is aligned */
7308     b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
7309     unaligned = (nk_byte*)cmd + size;
7310     memory = NK_ALIGN_PTR(unaligned, align);
7311     alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
7312 #ifdef NK_ZERO_COMMAND_MEMORY
7313     NK_MEMSET(cmd, 0, size + alignment);
7314 #endif
7315 
7316     cmd->type = t;
7317     cmd->next = b->base->allocated + alignment;
7318 #ifdef NK_INCLUDE_COMMAND_USERDATA
7319     cmd->userdata = b->userdata;
7320 #endif
7321     b->end = cmd->next;
7322     return cmd;
7323 }
7324 
7325 NK_API void
7326 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
7327 {
7328     struct nk_command_scissor *cmd;
7329     NK_ASSERT(b);
7330     if (!b) return;
7331 
7332     b->clip.x = r.x;
7333     b->clip.y = r.y;
7334     b->clip.w = r.w;
7335     b->clip.h = r.h;
7336     cmd = (struct nk_command_scissor*)
7337         nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
7338 
7339     if (!cmd) return;
7340     cmd->x = (short)r.x;
7341     cmd->y = (short)r.y;
7342     cmd->w = (unsigned short)NK_MAX(0, r.w);
7343     cmd->h = (unsigned short)NK_MAX(0, r.h);
7344 }
7345 
7346 NK_API void
7347 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
7348     float x1, float y1, float line_thickness, struct nk_color c)
7349 {
7350     struct nk_command_line *cmd;
7351     NK_ASSERT(b);
7352     if (!b || line_thickness <= 0) return;
7353     cmd = (struct nk_command_line*)
7354         nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
7355     if (!cmd) return;
7356     cmd->line_thickness = (unsigned short)line_thickness;
7357     cmd->begin.x = (short)x0;
7358     cmd->begin.y = (short)y0;
7359     cmd->end.x = (short)x1;
7360     cmd->end.y = (short)y1;
7361     cmd->color = c;
7362 }
7363 
7364 NK_API void
7365 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
7366     float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
7367     float bx, float by, float line_thickness, struct nk_color col)
7368 {
7369     struct nk_command_curve *cmd;
7370     NK_ASSERT(b);
7371     if (!b || col.a == 0 || line_thickness <= 0) return;
7372 
7373     cmd = (struct nk_command_curve*)
7374         nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
7375     if (!cmd) return;
7376     cmd->line_thickness = (unsigned short)line_thickness;
7377     cmd->begin.x = (short)ax;
7378     cmd->begin.y = (short)ay;
7379     cmd->ctrl[0].x = (short)ctrl0x;
7380     cmd->ctrl[0].y = (short)ctrl0y;
7381     cmd->ctrl[1].x = (short)ctrl1x;
7382     cmd->ctrl[1].y = (short)ctrl1y;
7383     cmd->end.x = (short)bx;
7384     cmd->end.y = (short)by;
7385     cmd->color = col;
7386 }
7387 
7388 NK_API void
7389 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
7390     float rounding, float line_thickness, struct nk_color c)
7391 {
7392     struct nk_command_rect *cmd;
7393     NK_ASSERT(b);
7394     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
7395     if (b->use_clipping) {
7396         const struct nk_rect *clip = &b->clip;
7397         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7398             clip->x, clip->y, clip->w, clip->h)) return;
7399     }
7400     cmd = (struct nk_command_rect*)
7401         nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
7402     if (!cmd) return;
7403     cmd->rounding = (unsigned short)rounding;
7404     cmd->line_thickness = (unsigned short)line_thickness;
7405     cmd->x = (short)rect.x;
7406     cmd->y = (short)rect.y;
7407     cmd->w = (unsigned short)NK_MAX(0, rect.w);
7408     cmd->h = (unsigned short)NK_MAX(0, rect.h);
7409     cmd->color = c;
7410 }
7411 
7412 NK_API void
7413 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
7414     float rounding, struct nk_color c)
7415 {
7416     struct nk_command_rect_filled *cmd;
7417     NK_ASSERT(b);
7418     if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
7419     if (b->use_clipping) {
7420         const struct nk_rect *clip = &b->clip;
7421         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7422             clip->x, clip->y, clip->w, clip->h)) return;
7423     }
7424 
7425     cmd = (struct nk_command_rect_filled*)
7426         nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
7427     if (!cmd) return;
7428     cmd->rounding = (unsigned short)rounding;
7429     cmd->x = (short)rect.x;
7430     cmd->y = (short)rect.y;
7431     cmd->w = (unsigned short)NK_MAX(0, rect.w);
7432     cmd->h = (unsigned short)NK_MAX(0, rect.h);
7433     cmd->color = c;
7434 }
7435 
7436 NK_API void
7437 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
7438     struct nk_color left, struct nk_color top, struct nk_color right,
7439     struct nk_color bottom)
7440 {
7441     struct nk_command_rect_multi_color *cmd;
7442     NK_ASSERT(b);
7443     if (!b || rect.w == 0 || rect.h == 0) return;
7444     if (b->use_clipping) {
7445         const struct nk_rect *clip = &b->clip;
7446         if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7447             clip->x, clip->y, clip->w, clip->h)) return;
7448     }
7449 
7450     cmd = (struct nk_command_rect_multi_color*)
7451         nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
7452     if (!cmd) return;
7453     cmd->x = (short)rect.x;
7454     cmd->y = (short)rect.y;
7455     cmd->w = (unsigned short)NK_MAX(0, rect.w);
7456     cmd->h = (unsigned short)NK_MAX(0, rect.h);
7457     cmd->left = left;
7458     cmd->top = top;
7459     cmd->right = right;
7460     cmd->bottom = bottom;
7461 }
7462 
7463 NK_API void
7464 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
7465     float line_thickness, struct nk_color c)
7466 {
7467     struct nk_command_circle *cmd;
7468     if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
7469     if (b->use_clipping) {
7470         const struct nk_rect *clip = &b->clip;
7471         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7472             return;
7473     }
7474 
7475     cmd = (struct nk_command_circle*)
7476         nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
7477     if (!cmd) return;
7478     cmd->line_thickness = (unsigned short)line_thickness;
7479     cmd->x = (short)r.x;
7480     cmd->y = (short)r.y;
7481     cmd->w = (unsigned short)NK_MAX(r.w, 0);
7482     cmd->h = (unsigned short)NK_MAX(r.h, 0);
7483     cmd->color = c;
7484 }
7485 
7486 NK_API void
7487 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
7488 {
7489     struct nk_command_circle_filled *cmd;
7490     NK_ASSERT(b);
7491     if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
7492     if (b->use_clipping) {
7493         const struct nk_rect *clip = &b->clip;
7494         if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7495             return;
7496     }
7497 
7498     cmd = (struct nk_command_circle_filled*)
7499         nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
7500     if (!cmd) return;
7501     cmd->x = (short)r.x;
7502     cmd->y = (short)r.y;
7503     cmd->w = (unsigned short)NK_MAX(r.w, 0);
7504     cmd->h = (unsigned short)NK_MAX(r.h, 0);
7505     cmd->color = c;
7506 }
7507 
7508 NK_API void
7509 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7510     float a_min, float a_max, float line_thickness, struct nk_color c)
7511 {
7512     struct nk_command_arc *cmd;
7513     if (!b || c.a == 0 || line_thickness <= 0) return;
7514     cmd = (struct nk_command_arc*)
7515         nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
7516     if (!cmd) return;
7517     cmd->line_thickness = (unsigned short)line_thickness;
7518     cmd->cx = (short)cx;
7519     cmd->cy = (short)cy;
7520     cmd->r = (unsigned short)radius;
7521     cmd->a[0] = a_min;
7522     cmd->a[1] = a_max;
7523     cmd->color = c;
7524 }
7525 
7526 NK_API void
7527 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7528     float a_min, float a_max, struct nk_color c)
7529 {
7530     struct nk_command_arc_filled *cmd;
7531     NK_ASSERT(b);
7532     if (!b || c.a == 0) return;
7533     cmd = (struct nk_command_arc_filled*)
7534         nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
7535     if (!cmd) return;
7536     cmd->cx = (short)cx;
7537     cmd->cy = (short)cy;
7538     cmd->r = (unsigned short)radius;
7539     cmd->a[0] = a_min;
7540     cmd->a[1] = a_max;
7541     cmd->color = c;
7542 }
7543 
7544 NK_API void
7545 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7546     float y1, float x2, float y2, float line_thickness, struct nk_color c)
7547 {
7548     struct nk_command_triangle *cmd;
7549     NK_ASSERT(b);
7550     if (!b || c.a == 0 || line_thickness <= 0) return;
7551     if (b->use_clipping) {
7552         const struct nk_rect *clip = &b->clip;
7553         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7554             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7555             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7556             return;
7557     }
7558 
7559     cmd = (struct nk_command_triangle*)
7560         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
7561     if (!cmd) return;
7562     cmd->line_thickness = (unsigned short)line_thickness;
7563     cmd->a.x = (short)x0;
7564     cmd->a.y = (short)y0;
7565     cmd->b.x = (short)x1;
7566     cmd->b.y = (short)y1;
7567     cmd->c.x = (short)x2;
7568     cmd->c.y = (short)y2;
7569     cmd->color = c;
7570 }
7571 
7572 NK_API void
7573 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7574     float y1, float x2, float y2, struct nk_color c)
7575 {
7576     struct nk_command_triangle_filled *cmd;
7577     NK_ASSERT(b);
7578     if (!b || c.a == 0) return;
7579     if (!b) return;
7580     if (b->use_clipping) {
7581         const struct nk_rect *clip = &b->clip;
7582         if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7583             !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7584             !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7585             return;
7586     }
7587 
7588     cmd = (struct nk_command_triangle_filled*)
7589         nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
7590     if (!cmd) return;
7591     cmd->a.x = (short)x0;
7592     cmd->a.y = (short)y0;
7593     cmd->b.x = (short)x1;
7594     cmd->b.y = (short)y1;
7595     cmd->c.x = (short)x2;
7596     cmd->c.y = (short)y2;
7597     cmd->color = c;
7598 }
7599 
7600 NK_API void
7601 nk_stroke_polygon(struct nk_command_buffer *b,  float *points, int point_count,
7602     float line_thickness, struct nk_color col)
7603 {
7604     int i;
7605     nk_size size = 0;
7606     struct nk_command_polygon *cmd;
7607 
7608     NK_ASSERT(b);
7609     if (!b || col.a == 0 || line_thickness <= 0) return;
7610     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7611     cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
7612     if (!cmd) return;
7613     cmd->color = col;
7614     cmd->line_thickness = (unsigned short)line_thickness;
7615     cmd->point_count = (unsigned short)point_count;
7616     for (i = 0; i < point_count; ++i) {
7617         cmd->points[i].x = (short)points[i*2];
7618         cmd->points[i].y = (short)points[i*2+1];
7619     }
7620 }
7621 
7622 NK_API void
7623 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
7624     struct nk_color col)
7625 {
7626     int i;
7627     nk_size size = 0;
7628     struct nk_command_polygon_filled *cmd;
7629 
7630     NK_ASSERT(b);
7631     if (!b || col.a == 0) return;
7632     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7633     cmd = (struct nk_command_polygon_filled*)
7634         nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
7635     if (!cmd) return;
7636     cmd->color = col;
7637     cmd->point_count = (unsigned short)point_count;
7638     for (i = 0; i < point_count; ++i) {
7639         cmd->points[i].x = (short)points[i*2+0];
7640         cmd->points[i].y = (short)points[i*2+1];
7641     }
7642 }
7643 
7644 NK_API void
7645 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count,
7646     float line_thickness, struct nk_color col)
7647 {
7648     int i;
7649     nk_size size = 0;
7650     struct nk_command_polyline *cmd;
7651 
7652     NK_ASSERT(b);
7653     if (!b || col.a == 0 || line_thickness <= 0) return;
7654     size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7655     cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
7656     if (!cmd) return;
7657     cmd->color = col;
7658     cmd->point_count = (unsigned short)point_count;
7659     cmd->line_thickness = (unsigned short)line_thickness;
7660     for (i = 0; i < point_count; ++i) {
7661         cmd->points[i].x = (short)points[i*2];
7662         cmd->points[i].y = (short)points[i*2+1];
7663     }
7664 }
7665 
7666 NK_API void
7667 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
7668     const struct nk_image *img, struct nk_color col)
7669 {
7670     struct nk_command_image *cmd;
7671     NK_ASSERT(b);
7672     if (!b) return;
7673     if (b->use_clipping) {
7674         const struct nk_rect *c = &b->clip;
7675         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))
7676             return;
7677     }
7678 
7679     cmd = (struct nk_command_image*)
7680         nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
7681     if (!cmd) return;
7682     cmd->x = (short)r.x;
7683     cmd->y = (short)r.y;
7684     cmd->w = (unsigned short)NK_MAX(0, r.w);
7685     cmd->h = (unsigned short)NK_MAX(0, r.h);
7686     cmd->img = *img;
7687     cmd->col = col;
7688 }
7689 
7690 NK_API void
7691 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
7692     nk_command_custom_callback cb, nk_handle usr)
7693 {
7694     struct nk_command_custom *cmd;
7695     NK_ASSERT(b);
7696     if (!b) return;
7697     if (b->use_clipping) {
7698         const struct nk_rect *c = &b->clip;
7699         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))
7700             return;
7701     }
7702 
7703     cmd = (struct nk_command_custom*)
7704         nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
7705     if (!cmd) return;
7706     cmd->x = (short)r.x;
7707     cmd->y = (short)r.y;
7708     cmd->w = (unsigned short)NK_MAX(0, r.w);
7709     cmd->h = (unsigned short)NK_MAX(0, r.h);
7710     cmd->callback_data = usr;
7711     cmd->callback = cb;
7712 }
7713 
7714 NK_API void
7715 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
7716     const char *string, int length, const struct nk_user_font *font,
7717     struct nk_color bg, struct nk_color fg)
7718 {
7719     float text_width = 0;
7720     struct nk_command_text *cmd;
7721 
7722     NK_ASSERT(b);
7723     NK_ASSERT(font);
7724     if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
7725     if (b->use_clipping) {
7726         const struct nk_rect *c = &b->clip;
7727         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))
7728             return;
7729     }
7730 
7731     /* make sure text fits inside bounds */
7732     text_width = font->width(font->userdata, font->height, string, length);
7733     if (text_width > r.w){
7734         int glyphs = 0;
7735         float txt_width = (float)text_width;
7736         length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
7737     }
7738 
7739     if (!length) return;
7740     cmd = (struct nk_command_text*)
7741         nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
7742     if (!cmd) return;
7743     cmd->x = (short)r.x;
7744     cmd->y = (short)r.y;
7745     cmd->w = (unsigned short)r.w;
7746     cmd->h = (unsigned short)r.h;
7747     cmd->background = bg;
7748     cmd->foreground = fg;
7749     cmd->font = font;
7750     cmd->length = length;
7751     cmd->height = font->height;
7752     NK_MEMCPY(cmd->string, string, (nk_size)length);
7753     cmd->string[length] = '\0';
7754 }
7755 
7756 /* ==============================================================
7757  *
7758  *                          DRAW LIST
7759  *
7760  * ===============================================================*/
7761 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
7762 NK_API void
7763 nk_draw_list_init(struct nk_draw_list *list)
7764 {
7765     nk_size i = 0;
7766     NK_ASSERT(list);
7767     if (!list) return;
7768     nk_zero(list, sizeof(*list));
7769     for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
7770         const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
7771         list->circle_vtx[i].x = (float)NK_COS(a);
7772         list->circle_vtx[i].y = (float)NK_SIN(a);
7773     }
7774 }
7775 
7776 NK_API void
7777 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
7778     struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
7779     enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
7780 {
7781     NK_ASSERT(canvas);
7782     NK_ASSERT(config);
7783     NK_ASSERT(cmds);
7784     NK_ASSERT(vertices);
7785     NK_ASSERT(elements);
7786     if (!canvas || !config || !cmds || !vertices || !elements)
7787         return;
7788 
7789     canvas->buffer = cmds;
7790     canvas->config = *config;
7791     canvas->elements = elements;
7792     canvas->vertices = vertices;
7793     canvas->line_AA = line_aa;
7794     canvas->shape_AA = shape_aa;
7795     canvas->clip_rect = nk_null_rect;
7796 }
7797 
7798 NK_API const struct nk_draw_command*
7799 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7800 {
7801     nk_byte *memory;
7802     nk_size offset;
7803     const struct nk_draw_command *cmd;
7804 
7805     NK_ASSERT(buffer);
7806     if (!buffer || !buffer->size || !canvas->cmd_count)
7807         return 0;
7808 
7809     memory = (nk_byte*)buffer->memory.ptr;
7810     offset = buffer->memory.size - canvas->cmd_offset;
7811     cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
7812     return cmd;
7813 }
7814 
7815 NK_API const struct nk_draw_command*
7816 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7817 {
7818     nk_size size;
7819     nk_size offset;
7820     nk_byte *memory;
7821     const struct nk_draw_command *end;
7822 
7823     NK_ASSERT(buffer);
7824     NK_ASSERT(canvas);
7825     if (!buffer || !canvas)
7826         return 0;
7827 
7828     memory = (nk_byte*)buffer->memory.ptr;
7829     size = buffer->memory.size;
7830     offset = size - canvas->cmd_offset;
7831     end = nk_ptr_add(const struct nk_draw_command, memory, offset);
7832     end -= (canvas->cmd_count-1);
7833     return end;
7834 }
7835 
7836 NK_API const struct nk_draw_command*
7837 nk__draw_list_next(const struct nk_draw_command *cmd,
7838     const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
7839 {
7840     const struct nk_draw_command *end;
7841     NK_ASSERT(buffer);
7842     NK_ASSERT(canvas);
7843     if (!cmd || !buffer || !canvas)
7844         return 0;
7845 
7846     end = nk__draw_list_end(canvas, buffer);
7847     if (cmd <= end) return 0;
7848     return (cmd-1);
7849 }
7850 
7851 NK_API void
7852 nk_draw_list_clear(struct nk_draw_list *list)
7853 {
7854     NK_ASSERT(list);
7855     if (!list) return;
7856     if (list->buffer)
7857         nk_buffer_clear(list->buffer);
7858     if (list->vertices)
7859         nk_buffer_clear(list->vertices);
7860     if (list->elements)
7861         nk_buffer_clear(list->elements);
7862 
7863     list->element_count = 0;
7864     list->vertex_count = 0;
7865     list->cmd_offset = 0;
7866     list->cmd_count = 0;
7867     list->path_count = 0;
7868     list->vertices = 0;
7869     list->elements = 0;
7870     list->clip_rect = nk_null_rect;
7871 }
7872 
7873 NK_INTERN struct nk_vec2*
7874 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
7875 {
7876     struct nk_vec2 *points;
7877     NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
7878     NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
7879     points = (struct nk_vec2*)
7880         nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
7881                         point_size * (nk_size)count, point_align);
7882 
7883     if (!points) return 0;
7884     if (!list->path_offset) {
7885         void *memory = nk_buffer_memory(list->buffer);
7886         list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
7887     }
7888     list->path_count += (unsigned int)count;
7889     return points;
7890 }
7891 
7892 NK_INTERN struct nk_vec2
7893 nk_draw_list_path_last(struct nk_draw_list *list)
7894 {
7895     void *memory;
7896     struct nk_vec2 *point;
7897     NK_ASSERT(list->path_count);
7898     memory = nk_buffer_memory(list->buffer);
7899     point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
7900     point += (list->path_count-1);
7901     return *point;
7902 }
7903 
7904 NK_INTERN struct nk_draw_command*
7905 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
7906     nk_handle texture)
7907 {
7908     NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
7909     NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
7910     struct nk_draw_command *cmd;
7911 
7912     NK_ASSERT(list);
7913     cmd = (struct nk_draw_command*)
7914         nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
7915 
7916     if (!cmd) return 0;
7917     if (!list->cmd_count) {
7918         nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
7919         nk_size total = nk_buffer_total(list->buffer);
7920         memory = nk_ptr_add(nk_byte, memory, total);
7921         list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
7922     }
7923 
7924     cmd->elem_count = 0;
7925     cmd->clip_rect = clip;
7926     cmd->texture = texture;
7927 #ifdef NK_INCLUDE_COMMAND_USERDATA
7928     cmd->userdata = list->userdata;
7929 #endif
7930 
7931     list->cmd_count++;
7932     list->clip_rect = clip;
7933     return cmd;
7934 }
7935 
7936 NK_INTERN struct nk_draw_command*
7937 nk_draw_list_command_last(struct nk_draw_list *list)
7938 {
7939     void *memory;
7940     nk_size size;
7941     struct nk_draw_command *cmd;
7942     NK_ASSERT(list->cmd_count);
7943 
7944     memory = nk_buffer_memory(list->buffer);
7945     size = nk_buffer_total(list->buffer);
7946     cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
7947     return (cmd - (list->cmd_count-1));
7948 }
7949 
7950 NK_INTERN void
7951 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
7952 {
7953     NK_ASSERT(list);
7954     if (!list) return;
7955     if (!list->cmd_count) {
7956         nk_draw_list_push_command(list, rect, list->config.null.texture);
7957     } else {
7958         struct nk_draw_command *prev = nk_draw_list_command_last(list);
7959         if (prev->elem_count == 0)
7960             prev->clip_rect = rect;
7961         nk_draw_list_push_command(list, rect, prev->texture);
7962     }
7963 }
7964 
7965 NK_INTERN void
7966 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
7967 {
7968     NK_ASSERT(list);
7969     if (!list) return;
7970     if (!list->cmd_count) {
7971         nk_draw_list_push_command(list, nk_null_rect, texture);
7972     } else {
7973         struct nk_draw_command *prev = nk_draw_list_command_last(list);
7974         if (prev->elem_count == 0) {
7975             prev->texture = texture;
7976         #ifdef NK_INCLUDE_COMMAND_USERDATA
7977             prev->userdata = list->userdata;
7978         #endif
7979     } else if (prev->texture.id != texture.id
7980         #ifdef NK_INCLUDE_COMMAND_USERDATA
7981             || prev->userdata.id != list->userdata.id
7982         #endif
7983         ) nk_draw_list_push_command(list, prev->clip_rect, texture);
7984     }
7985 }
7986 
7987 #ifdef NK_INCLUDE_COMMAND_USERDATA
7988 NK_API void
7989 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
7990 {
7991     list->userdata = userdata;
7992 }
7993 #endif
7994 
7995 NK_INTERN void*
7996 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
7997 {
7998     void *vtx;
7999     NK_ASSERT(list);
8000     if (!list) return 0;
8001     vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
8002         list->config.vertex_size*count, list->config.vertex_alignment);
8003     if (!vtx) return 0;
8004     list->vertex_count += (unsigned int)count;
8005     return vtx;
8006 }
8007 
8008 NK_INTERN nk_draw_index*
8009 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
8010 {
8011     nk_draw_index *ids;
8012     struct nk_draw_command *cmd;
8013     NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
8014     NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
8015     NK_ASSERT(list);
8016     if (!list) return 0;
8017 
8018     ids = (nk_draw_index*)
8019         nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
8020     if (!ids) return 0;
8021     cmd = nk_draw_list_command_last(list);
8022     list->element_count += (unsigned int)count;
8023     cmd->elem_count += (unsigned int)count;
8024     return ids;
8025 }
8026 
8027 NK_INTERN int
8028 nk_draw_vertex_layout_element_is_end_of_layout(
8029     const struct nk_draw_vertex_layout_element *element)
8030 {
8031     return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
8032             element->format == NK_FORMAT_COUNT);
8033 }
8034 
8035 NK_INTERN void
8036 nk_draw_vertex_color(void *attribute, const float *values,
8037     enum nk_draw_vertex_layout_format format)
8038 {
8039     /* if this triggers you tried to provide a value format for a color */
8040     NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
8041     NK_ASSERT(format <= NK_FORMAT_COLOR_END);
8042     if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
8043 
8044     switch (format) {
8045     default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
8046     case NK_FORMAT_R8G8B8A8:
8047     case NK_FORMAT_R8G8B8: {
8048         struct nk_color col = nk_rgba_fv(values);
8049         NK_MEMCPY(attribute, &col.r, sizeof(col));
8050     } break;
8051     case NK_FORMAT_B8G8R8A8: {
8052         struct nk_color col = nk_rgba_fv(values);
8053         struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
8054         NK_MEMCPY(attribute, &bgra, sizeof(bgra));
8055     } break;
8056     case NK_FORMAT_R16G15B16: {
8057         nk_ushort col[3];
8058         col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
8059         col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
8060         col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
8061         NK_MEMCPY(attribute, col, sizeof(col));
8062     } break;
8063     case NK_FORMAT_R16G15B16A16: {
8064         nk_ushort col[4];
8065         col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
8066         col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
8067         col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
8068         col[3] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[3] * NK_USHORT_MAX, NK_USHORT_MAX);
8069         NK_MEMCPY(attribute, col, sizeof(col));
8070     } break;
8071     case NK_FORMAT_R32G32B32: {
8072         nk_uint col[3];
8073         col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
8074         col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
8075         col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
8076         NK_MEMCPY(attribute, col, sizeof(col));
8077     } break;
8078     case NK_FORMAT_R32G32B32A32: {
8079         nk_uint col[4];
8080         col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
8081         col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
8082         col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
8083         col[3] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[3] * NK_UINT_MAX, NK_UINT_MAX);
8084         NK_MEMCPY(attribute, col, sizeof(col));
8085     } break;
8086     case NK_FORMAT_R32G32B32A32_FLOAT:
8087         NK_MEMCPY(attribute, values, sizeof(float)*4);
8088         break;
8089     case NK_FORMAT_R32G32B32A32_DOUBLE: {
8090         double col[4];
8091         col[0] = (double)NK_SATURATE(values[0]);
8092         col[1] = (double)NK_SATURATE(values[1]);
8093         col[2] = (double)NK_SATURATE(values[2]);
8094         col[3] = (double)NK_SATURATE(values[3]);
8095         NK_MEMCPY(attribute, col, sizeof(col));
8096     } break;
8097     case NK_FORMAT_RGB32:
8098     case NK_FORMAT_RGBA32: {
8099         struct nk_color col = nk_rgba_fv(values);
8100         nk_uint color = nk_color_u32(col);
8101         NK_MEMCPY(attribute, &color, sizeof(color));
8102     } break;
8103     }
8104 }
8105 
8106 NK_INTERN void
8107 nk_draw_vertex_element(void *dst, const float *values, int value_count,
8108     enum nk_draw_vertex_layout_format format)
8109 {
8110     int value_index;
8111     void *attribute = dst;
8112     /* if this triggers you tried to provide a color format for a value */
8113     NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
8114     if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
8115     for (value_index = 0; value_index < value_count; ++value_index) {
8116         switch (format) {
8117         default: NK_ASSERT(0 && "invalid vertex layout format"); break;
8118         case NK_FORMAT_SCHAR: {
8119             char value = (char)NK_CLAMP(NK_SCHAR_MIN, values[value_index], NK_SCHAR_MAX);
8120             NK_MEMCPY(attribute, &value, sizeof(value));
8121             attribute = (void*)((char*)attribute + sizeof(char));
8122         } break;
8123         case NK_FORMAT_SSHORT: {
8124             nk_short value = (nk_short)NK_CLAMP(NK_SSHORT_MIN, values[value_index], NK_SSHORT_MAX);
8125             NK_MEMCPY(attribute, &value, sizeof(value));
8126             attribute = (void*)((char*)attribute + sizeof(value));
8127         } break;
8128         case NK_FORMAT_SINT: {
8129             nk_int value = (nk_int)NK_CLAMP(NK_SINT_MIN, values[value_index], NK_SINT_MAX);
8130             NK_MEMCPY(attribute, &value, sizeof(value));
8131             attribute = (void*)((char*)attribute + sizeof(nk_int));
8132         } break;
8133         case NK_FORMAT_UCHAR: {
8134             unsigned char value = (unsigned char)NK_CLAMP(NK_UCHAR_MIN, values[value_index], NK_UCHAR_MAX);
8135             NK_MEMCPY(attribute, &value, sizeof(value));
8136             attribute = (void*)((char*)attribute + sizeof(unsigned char));
8137         } break;
8138         case NK_FORMAT_USHORT: {
8139             nk_ushort value = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[value_index], NK_USHORT_MAX);
8140             NK_MEMCPY(attribute, &value, sizeof(value));
8141             attribute = (void*)((char*)attribute + sizeof(value));
8142             } break;
8143         case NK_FORMAT_UINT: {
8144             nk_uint value = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[value_index], NK_UINT_MAX);
8145             NK_MEMCPY(attribute, &value, sizeof(value));
8146             attribute = (void*)((char*)attribute + sizeof(nk_uint));
8147         } break;
8148         case NK_FORMAT_FLOAT:
8149             NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
8150             attribute = (void*)((char*)attribute + sizeof(float));
8151             break;
8152         case NK_FORMAT_DOUBLE: {
8153             double value = (double)values[value_index];
8154             NK_MEMCPY(attribute, &value, sizeof(value));
8155             attribute = (void*)((char*)attribute + sizeof(double));
8156             } break;
8157         }
8158     }
8159 }
8160 
8161 NK_INTERN void*
8162 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
8163     struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
8164 {
8165     void *result = (void*)((char*)dst + config->vertex_size);
8166     const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
8167     while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
8168         void *address = (void*)((char*)dst + elem_iter->offset);
8169         switch (elem_iter->attribute) {
8170         case NK_VERTEX_ATTRIBUTE_COUNT:
8171         default: NK_ASSERT(0 && "wrong element attribute");
8172         case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
8173         case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
8174         case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
8175         }
8176         elem_iter++;
8177     }
8178     return result;
8179 }
8180 
8181 NK_API void
8182 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
8183     const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
8184     float thickness, enum nk_anti_aliasing aliasing)
8185 {
8186     nk_size count;
8187     int thick_line;
8188     struct nk_colorf col;
8189     struct nk_colorf col_trans;
8190     NK_ASSERT(list);
8191     if (!list || points_count < 2) return;
8192 
8193     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8194     count = points_count;
8195     if (!closed) count = points_count-1;
8196     thick_line = thickness > 1.0f;
8197 
8198 #ifdef NK_INCLUDE_COMMAND_USERDATA
8199     nk_draw_list_push_userdata(list, list->userdata);
8200 #endif
8201 
8202     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8203     nk_color_fv(&col.r, color);
8204     col_trans = col;
8205     col_trans.a = 0;
8206 
8207     if (aliasing == NK_ANTI_ALIASING_ON) {
8208         /* ANTI-ALIASED STROKE */
8209         const float AA_SIZE = 1.0f;
8210         NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8211         NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8212 
8213         /* allocate vertices and elements  */
8214         nk_size i1 = 0;
8215         nk_size vertex_offset;
8216         nk_size index = list->vertex_count;
8217 
8218         const nk_size idx_count = (thick_line) ?  (count * 18) : (count * 12);
8219         const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
8220 
8221         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8222         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8223 
8224         nk_size size;
8225         struct nk_vec2 *normals, *temp;
8226         if (!vtx || !ids) return;
8227 
8228         /* temporary allocate normals + points */
8229         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8230         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8231         size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
8232         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8233         NK_ASSERT(normals);
8234         if (!normals) return;
8235         temp = normals + points_count;
8236 
8237         /* make sure vertex pointer is still correct */
8238         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8239 
8240         /* calculate normals */
8241         for (i1 = 0; i1 < count; ++i1) {
8242             const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8243             struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
8244             float len;
8245 
8246             /* vec2 inverted length  */
8247             len = nk_vec2_len_sqr(diff);
8248             if (len != 0.0f)
8249                 len = nk_inv_sqrt(len);
8250             else len = 1.0f;
8251 
8252             diff = nk_vec2_muls(diff, len);
8253             normals[i1].x = diff.y;
8254             normals[i1].y = -diff.x;
8255         }
8256 
8257         if (!closed)
8258             normals[points_count-1] = normals[points_count-2];
8259 
8260         if (!thick_line) {
8261             nk_size idx1, i;
8262             if (!closed) {
8263                 struct nk_vec2 d;
8264                 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8265                 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8266                 d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
8267                 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
8268                 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
8269             }
8270 
8271             /* fill elements */
8272             idx1 = index;
8273             for (i1 = 0; i1 < count; i1++) {
8274                 struct nk_vec2 dm;
8275                 float dmr2;
8276                 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8277                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
8278 
8279                 /* average normals */
8280                 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8281                 dmr2 = dm.x * dm.x + dm.y* dm.y;
8282                 if (dmr2 > 0.000001f) {
8283                     float scale = 1.0f/dmr2;
8284                     scale = NK_MIN(100.0f, scale);
8285                     dm = nk_vec2_muls(dm, scale);
8286                 }
8287 
8288                 dm = nk_vec2_muls(dm, AA_SIZE);
8289                 temp[i2*2+0] = nk_vec2_add(points[i2], dm);
8290                 temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
8291 
8292                 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
8293                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8294                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
8295                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8296                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8297                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
8298                 ids += 12;
8299                 idx1 = idx2;
8300             }
8301 
8302             /* fill vertices */
8303             for (i = 0; i < points_count; ++i) {
8304                 const struct nk_vec2 uv = list->config.null.uv;
8305                 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
8306                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
8307                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
8308             }
8309         } else {
8310             nk_size idx1, i;
8311             const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
8312             if (!closed) {
8313                 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
8314                 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
8315 
8316                 temp[0] = nk_vec2_add(points[0], d1);
8317                 temp[1] = nk_vec2_add(points[0], d2);
8318                 temp[2] = nk_vec2_sub(points[0], d2);
8319                 temp[3] = nk_vec2_sub(points[0], d1);
8320 
8321                 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
8322                 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
8323 
8324                 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
8325                 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
8326                 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
8327                 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
8328             }
8329 
8330             /* add all elements */
8331             idx1 = index;
8332             for (i1 = 0; i1 < count; ++i1) {
8333                 struct nk_vec2 dm_out, dm_in;
8334                 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
8335                 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
8336 
8337                 /* average normals */
8338                 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8339                 float dmr2 = dm.x * dm.x + dm.y* dm.y;
8340                 if (dmr2 > 0.000001f) {
8341                     float scale = 1.0f/dmr2;
8342                     scale = NK_MIN(100.0f, scale);
8343                     dm = nk_vec2_muls(dm, scale);
8344                 }
8345 
8346                 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
8347                 dm_in = nk_vec2_muls(dm, half_inner_thickness);
8348                 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
8349                 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
8350                 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
8351                 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
8352 
8353                 /* add indexes */
8354                 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
8355                 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8356                 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
8357                 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8358                 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8359                 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
8360                 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
8361                 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
8362                 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
8363                 ids += 18;
8364                 idx1 = idx2;
8365             }
8366 
8367             /* add vertices */
8368             for (i = 0; i < points_count; ++i) {
8369                 const struct nk_vec2 uv = list->config.null.uv;
8370                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
8371                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
8372                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
8373                 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
8374             }
8375         }
8376         /* free temporary normals + points */
8377         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8378     } else {
8379         /* NON ANTI-ALIASED STROKE */
8380         nk_size i1 = 0;
8381         nk_size idx = list->vertex_count;
8382         const nk_size idx_count = count * 6;
8383         const nk_size vtx_count = count * 4;
8384         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8385         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8386         if (!vtx || !ids) return;
8387 
8388         for (i1 = 0; i1 < count; ++i1) {
8389             float dx, dy;
8390             const struct nk_vec2 uv = list->config.null.uv;
8391             const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
8392             const struct nk_vec2 p1 = points[i1];
8393             const struct nk_vec2 p2 = points[i2];
8394             struct nk_vec2 diff = nk_vec2_sub(p2, p1);
8395             float len;
8396 
8397             /* vec2 inverted length  */
8398             len = nk_vec2_len_sqr(diff);
8399             if (len != 0.0f)
8400                 len = nk_inv_sqrt(len);
8401             else len = 1.0f;
8402             diff = nk_vec2_muls(diff, len);
8403 
8404             /* add vertices */
8405             dx = diff.x * (thickness * 0.5f);
8406             dy = diff.y * (thickness * 0.5f);
8407 
8408             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
8409             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
8410             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
8411             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
8412 
8413             ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
8414             ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
8415             ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
8416 
8417             ids += 6;
8418             idx += 4;
8419         }
8420     }
8421 }
8422 
8423 NK_API void
8424 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
8425     const struct nk_vec2 *points, const unsigned int points_count,
8426     struct nk_color color, enum nk_anti_aliasing aliasing)
8427 {
8428     struct nk_colorf col;
8429     struct nk_colorf col_trans;
8430 
8431     NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8432     NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8433     NK_ASSERT(list);
8434     if (!list || points_count < 3) return;
8435 
8436 #ifdef NK_INCLUDE_COMMAND_USERDATA
8437     nk_draw_list_push_userdata(list, list->userdata);
8438 #endif
8439 
8440     color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8441     nk_color_fv(&col.r, color);
8442     col_trans = col;
8443     col_trans.a = 0;
8444 
8445     if (aliasing == NK_ANTI_ALIASING_ON) {
8446         nk_size i = 0;
8447         nk_size i0 = 0;
8448         nk_size i1 = 0;
8449 
8450         const float AA_SIZE = 1.0f;
8451         nk_size vertex_offset = 0;
8452         nk_size index = list->vertex_count;
8453 
8454         const nk_size idx_count = (points_count-2)*3 + points_count*6;
8455         const nk_size vtx_count = (points_count*2);
8456 
8457         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8458         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8459 
8460         nk_size size = 0;
8461         struct nk_vec2 *normals = 0;
8462         unsigned int vtx_inner_idx = (unsigned int)(index + 0);
8463         unsigned int vtx_outer_idx = (unsigned int)(index + 1);
8464         if (!vtx || !ids) return;
8465 
8466         /* temporary allocate normals */
8467         vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8468         nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8469         size = pnt_size * points_count;
8470         normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8471         NK_ASSERT(normals);
8472         if (!normals) return;
8473         vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8474 
8475         /* add elements */
8476         for (i = 2; i < points_count; i++) {
8477             ids[0] = (nk_draw_index)(vtx_inner_idx);
8478             ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
8479             ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
8480             ids += 3;
8481         }
8482 
8483         /* compute normals */
8484         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8485             struct nk_vec2 p0 = points[i0];
8486             struct nk_vec2 p1 = points[i1];
8487             struct nk_vec2 diff = nk_vec2_sub(p1, p0);
8488 
8489             /* vec2 inverted length  */
8490             float len = nk_vec2_len_sqr(diff);
8491             if (len != 0.0f)
8492                 len = nk_inv_sqrt(len);
8493             else len = 1.0f;
8494             diff = nk_vec2_muls(diff, len);
8495 
8496             normals[i0].x = diff.y;
8497             normals[i0].y = -diff.x;
8498         }
8499 
8500         /* add vertices + indexes */
8501         for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8502             const struct nk_vec2 uv = list->config.null.uv;
8503             struct nk_vec2 n0 = normals[i0];
8504             struct nk_vec2 n1 = normals[i1];
8505             struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
8506             float dmr2 = dm.x*dm.x + dm.y*dm.y;
8507             if (dmr2 > 0.000001f) {
8508                 float scale = 1.0f / dmr2;
8509                 scale = NK_MIN(scale, 100.0f);
8510                 dm = nk_vec2_muls(dm, scale);
8511             }
8512             dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
8513 
8514             /* add vertices */
8515             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
8516             vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
8517 
8518             /* add indexes */
8519             ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8520             ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
8521             ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8522             ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8523             ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
8524             ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8525             ids += 6;
8526         }
8527         /* free temporary normals + points */
8528         nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8529     } else {
8530         nk_size i = 0;
8531         nk_size index = list->vertex_count;
8532         const nk_size idx_count = (points_count-2)*3;
8533         const nk_size vtx_count = points_count;
8534         void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8535         nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8536 
8537         if (!vtx || !ids) return;
8538         for (i = 0; i < vtx_count; ++i)
8539             vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
8540         for (i = 2; i < points_count; ++i) {
8541             ids[0] = (nk_draw_index)index;
8542             ids[1] = (nk_draw_index)(index+ i - 1);
8543             ids[2] = (nk_draw_index)(index+i);
8544             ids += 3;
8545         }
8546     }
8547 }
8548 
8549 NK_API void
8550 nk_draw_list_path_clear(struct nk_draw_list *list)
8551 {
8552     NK_ASSERT(list);
8553     if (!list) return;
8554     nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
8555     list->path_count = 0;
8556     list->path_offset = 0;
8557 }
8558 
8559 NK_API void
8560 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
8561 {
8562     struct nk_vec2 *points = 0;
8563     struct nk_draw_command *cmd = 0;
8564     NK_ASSERT(list);
8565     if (!list) return;
8566     if (!list->cmd_count)
8567         nk_draw_list_add_clip(list, nk_null_rect);
8568 
8569     cmd = nk_draw_list_command_last(list);
8570     if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
8571         nk_draw_list_push_image(list, list->config.null.texture);
8572 
8573     points = nk_draw_list_alloc_path(list, 1);
8574     if (!points) return;
8575     points[0] = pos;
8576 }
8577 
8578 NK_API void
8579 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
8580     float radius, int a_min, int a_max)
8581 {
8582     int a = 0;
8583     NK_ASSERT(list);
8584     if (!list) return;
8585     if (a_min <= a_max) {
8586         for (a = a_min; a <= a_max; a++) {
8587             const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
8588             const float x = center.x + c.x * radius;
8589             const float y = center.y + c.y * radius;
8590             nk_draw_list_path_line_to(list, nk_vec2(x, y));
8591         }
8592     }
8593 }
8594 
8595 NK_API void
8596 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
8597     float radius, float a_min, float a_max, unsigned int segments)
8598 {
8599     unsigned int i = 0;
8600     NK_ASSERT(list);
8601     if (!list) return;
8602     if (radius == 0.0f) return;
8603 
8604     /*  This algorithm for arc drawing relies on these two trigonometric identities[1]:
8605             sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
8606             cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
8607 
8608         Two coordinates (x, y) of a point on a circle centered on
8609         the origin can be written in polar form as:
8610             x = r * cos(a)
8611             y = r * sin(a)
8612         where r is the radius of the circle,
8613             a is the angle between (x, y) and the origin.
8614 
8615         This allows us to rotate the coordinates around the
8616         origin by an angle b using the following transformation:
8617             x' = r * cos(a + b) = x * cos(b) - y * sin(b)
8618             y' = r * sin(a + b) = y * cos(b) + x * sin(b)
8619 
8620         [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
8621     */
8622     {const float d_angle = (a_max - a_min) / (float)segments;
8623     const float sin_d = (float)NK_SIN(d_angle);
8624     const float cos_d = (float)NK_COS(d_angle);
8625 
8626     float cx = (float)NK_COS(a_min) * radius;
8627     float cy = (float)NK_SIN(a_min) * radius;
8628     for(i = 0; i <= segments; ++i) {
8629         float new_cx, new_cy;
8630         const float x = center.x + cx;
8631         const float y = center.y + cy;
8632         nk_draw_list_path_line_to(list, nk_vec2(x, y));
8633 
8634         new_cx = cx * cos_d - cy * sin_d;
8635         new_cy = cy * cos_d + cx * sin_d;
8636         cx = new_cx;
8637         cy = new_cy;
8638     }}
8639 }
8640 
8641 NK_API void
8642 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
8643     struct nk_vec2 b, float rounding)
8644 {
8645     float r;
8646     NK_ASSERT(list);
8647     if (!list) return;
8648     r = rounding;
8649     r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
8650     r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
8651 
8652     if (r == 0.0f) {
8653         nk_draw_list_path_line_to(list, a);
8654         nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
8655         nk_draw_list_path_line_to(list, b);
8656         nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
8657     } else {
8658         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
8659         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
8660         nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
8661         nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
8662     }
8663 }
8664 
8665 NK_API void
8666 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
8667     struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
8668 {
8669     float t_step;
8670     unsigned int i_step;
8671     struct nk_vec2 p1;
8672 
8673     NK_ASSERT(list);
8674     NK_ASSERT(list->path_count);
8675     if (!list || !list->path_count) return;
8676     num_segments = NK_MAX(num_segments, 1);
8677 
8678     p1 = nk_draw_list_path_last(list);
8679     t_step = 1.0f/(float)num_segments;
8680     for (i_step = 1; i_step <= num_segments; ++i_step) {
8681         float t = t_step * (float)i_step;
8682         float u = 1.0f - t;
8683         float w1 = u*u*u;
8684         float w2 = 3*u*u*t;
8685         float w3 = 3*u*t*t;
8686         float w4 = t * t *t;
8687         float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
8688         float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
8689         nk_draw_list_path_line_to(list, nk_vec2(x,y));
8690     }
8691 }
8692 
8693 NK_API void
8694 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
8695 {
8696     struct nk_vec2 *points;
8697     NK_ASSERT(list);
8698     if (!list) return;
8699     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8700     nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
8701     nk_draw_list_path_clear(list);
8702 }
8703 
8704 NK_API void
8705 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
8706     enum nk_draw_list_stroke closed, float thickness)
8707 {
8708     struct nk_vec2 *points;
8709     NK_ASSERT(list);
8710     if (!list) return;
8711     points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8712     nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
8713         closed, thickness, list->config.line_AA);
8714     nk_draw_list_path_clear(list);
8715 }
8716 
8717 NK_API void
8718 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
8719     struct nk_vec2 b, struct nk_color col, float thickness)
8720 {
8721     NK_ASSERT(list);
8722     if (!list || !col.a) return;
8723     if (list->line_AA == NK_ANTI_ALIASING_ON) {
8724         nk_draw_list_path_line_to(list, a);
8725         nk_draw_list_path_line_to(list, b);
8726     } else {
8727         nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
8728         nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
8729     }
8730     nk_draw_list_path_stroke(list,  col, NK_STROKE_OPEN, thickness);
8731 }
8732 
8733 NK_API void
8734 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
8735     struct nk_color col, float rounding)
8736 {
8737     NK_ASSERT(list);
8738     if (!list || !col.a) return;
8739 
8740     if (list->line_AA == NK_ANTI_ALIASING_ON) {
8741         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
8742             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8743     } else {
8744         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
8745             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8746     } nk_draw_list_path_fill(list,  col);
8747 }
8748 
8749 NK_API void
8750 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
8751     struct nk_color col, float rounding, float thickness)
8752 {
8753     NK_ASSERT(list);
8754     if (!list || !col.a) return;
8755     if (list->line_AA == NK_ANTI_ALIASING_ON) {
8756         nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
8757             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8758     } else {
8759         nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
8760             nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8761     } nk_draw_list_path_stroke(list,  col, NK_STROKE_CLOSED, thickness);
8762 }
8763 
8764 NK_API void
8765 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
8766     struct nk_color left, struct nk_color top, struct nk_color right,
8767     struct nk_color bottom)
8768 {
8769     void *vtx;
8770     struct nk_colorf col_left, col_top;
8771     struct nk_colorf col_right, col_bottom;
8772     nk_draw_index *idx;
8773     nk_draw_index index;
8774 
8775     nk_color_fv(&col_left.r, left);
8776     nk_color_fv(&col_right.r, right);
8777     nk_color_fv(&col_top.r, top);
8778     nk_color_fv(&col_bottom.r, bottom);
8779 
8780     NK_ASSERT(list);
8781     if (!list) return;
8782 
8783     nk_draw_list_push_image(list, list->config.null.texture);
8784     index = (nk_draw_index)list->vertex_count;
8785     vtx = nk_draw_list_alloc_vertices(list, 4);
8786     idx = nk_draw_list_alloc_elements(list, 6);
8787     if (!vtx || !idx) return;
8788 
8789     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8790     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8791     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8792 
8793     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
8794     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
8795     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
8796     vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
8797 }
8798 
8799 NK_API void
8800 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8801     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
8802 {
8803     NK_ASSERT(list);
8804     if (!list || !col.a) return;
8805     nk_draw_list_path_line_to(list, a);
8806     nk_draw_list_path_line_to(list, b);
8807     nk_draw_list_path_line_to(list, c);
8808     nk_draw_list_path_fill(list, col);
8809 }
8810 
8811 NK_API void
8812 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8813     struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
8814 {
8815     NK_ASSERT(list);
8816     if (!list || !col.a) return;
8817     nk_draw_list_path_line_to(list, a);
8818     nk_draw_list_path_line_to(list, b);
8819     nk_draw_list_path_line_to(list, c);
8820     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8821 }
8822 
8823 NK_API void
8824 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
8825     float radius, struct nk_color col, unsigned int segs)
8826 {
8827     float a_max;
8828     NK_ASSERT(list);
8829     if (!list || !col.a) return;
8830     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8831     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8832     nk_draw_list_path_fill(list, col);
8833 }
8834 
8835 NK_API void
8836 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
8837     float radius, struct nk_color col, unsigned int segs, float thickness)
8838 {
8839     float a_max;
8840     NK_ASSERT(list);
8841     if (!list || !col.a) return;
8842     a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8843     nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8844     nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8845 }
8846 
8847 NK_API void
8848 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
8849     struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
8850     struct nk_color col, unsigned int segments, float thickness)
8851 {
8852     NK_ASSERT(list);
8853     if (!list || !col.a) return;
8854     nk_draw_list_path_line_to(list, p0);
8855     nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
8856     nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8857 }
8858 
8859 NK_INTERN void
8860 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
8861     struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
8862     struct nk_color color)
8863 {
8864     void *vtx;
8865     struct nk_vec2 uvb;
8866     struct nk_vec2 uvd;
8867     struct nk_vec2 b;
8868     struct nk_vec2 d;
8869 
8870     struct nk_colorf col;
8871     nk_draw_index *idx;
8872     nk_draw_index index;
8873     NK_ASSERT(list);
8874     if (!list) return;
8875 
8876     nk_color_fv(&col.r, color);
8877     uvb = nk_vec2(uvc.x, uva.y);
8878     uvd = nk_vec2(uva.x, uvc.y);
8879     b = nk_vec2(c.x, a.y);
8880     d = nk_vec2(a.x, c.y);
8881 
8882     index = (nk_draw_index)list->vertex_count;
8883     vtx = nk_draw_list_alloc_vertices(list, 4);
8884     idx = nk_draw_list_alloc_elements(list, 6);
8885     if (!vtx || !idx) return;
8886 
8887     idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8888     idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8889     idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8890 
8891     vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
8892     vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
8893     vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
8894     vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
8895 }
8896 
8897 NK_API void
8898 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
8899     struct nk_rect rect, struct nk_color color)
8900 {
8901     NK_ASSERT(list);
8902     if (!list) return;
8903     /* push new command with given texture */
8904     nk_draw_list_push_image(list, texture.handle);
8905     if (nk_image_is_subimage(&texture)) {
8906         /* add region inside of the texture  */
8907         struct nk_vec2 uv[2];
8908         uv[0].x = (float)texture.region[0]/(float)texture.w;
8909         uv[0].y = (float)texture.region[1]/(float)texture.h;
8910         uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
8911         uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
8912         nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8913             nk_vec2(rect.x + rect.w, rect.y + rect.h),  uv[0], uv[1], color);
8914     } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8915             nk_vec2(rect.x + rect.w, rect.y + rect.h),
8916             nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
8917 }
8918 
8919 NK_API void
8920 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
8921     struct nk_rect rect, const char *text, int len, float font_height,
8922     struct nk_color fg)
8923 {
8924     float x = 0;
8925     int text_len = 0;
8926     nk_rune unicode = 0;
8927     nk_rune next = 0;
8928     int glyph_len = 0;
8929     int next_glyph_len = 0;
8930     struct nk_user_font_glyph g;
8931 
8932     NK_ASSERT(list);
8933     if (!list || !len || !text) return;
8934     if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8935         list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
8936 
8937     nk_draw_list_push_image(list, font->texture);
8938     x = rect.x;
8939     glyph_len = nk_utf_decode(text, &unicode, len);
8940     if (!glyph_len) return;
8941 
8942     /* draw every glyph image */
8943     fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
8944     while (text_len < len && glyph_len) {
8945         float gx, gy, gh, gw;
8946         float char_width = 0;
8947         if (unicode == NK_UTF_INVALID) break;
8948 
8949         /* query currently drawn glyph information */
8950         next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
8951         font->query(font->userdata, font_height, &g, unicode,
8952                     (next == NK_UTF_INVALID) ? '\0' : next);
8953 
8954         /* calculate and draw glyph drawing rectangle and image */
8955         gx = x + g.offset.x;
8956         gy = rect.y + g.offset.y;
8957         gw = g.width; gh = g.height;
8958         char_width = g.xadvance;
8959         nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
8960             g.uv[0], g.uv[1], fg);
8961 
8962         /* offset next glyph */
8963         text_len += glyph_len;
8964         x += char_width;
8965         glyph_len = next_glyph_len;
8966         unicode = next;
8967     }
8968 }
8969 
8970 NK_API nk_flags
8971 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
8972     struct nk_buffer *vertices, struct nk_buffer *elements,
8973     const struct nk_convert_config *config)
8974 {
8975     nk_flags res = NK_CONVERT_SUCCESS;
8976     const struct nk_command *cmd;
8977     NK_ASSERT(ctx);
8978     NK_ASSERT(cmds);
8979     NK_ASSERT(vertices);
8980     NK_ASSERT(elements);
8981     NK_ASSERT(config);
8982     NK_ASSERT(config->vertex_layout);
8983     NK_ASSERT(config->vertex_size);
8984     if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
8985         return NK_CONVERT_INVALID_PARAM;
8986 
8987     nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
8988         config->line_AA, config->shape_AA);
8989     nk_foreach(cmd, ctx)
8990     {
8991 #ifdef NK_INCLUDE_COMMAND_USERDATA
8992         ctx->draw_list.userdata = cmd->userdata;
8993 #endif
8994         switch (cmd->type) {
8995         case NK_COMMAND_NOP: break;
8996         case NK_COMMAND_SCISSOR: {
8997             const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
8998             nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
8999         } break;
9000         case NK_COMMAND_LINE: {
9001             const struct nk_command_line *l = (const struct nk_command_line*)cmd;
9002             nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
9003                 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
9004         } break;
9005         case NK_COMMAND_CURVE: {
9006             const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
9007             nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
9008                 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
9009                 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
9010                 config->curve_segment_count, q->line_thickness);
9011         } break;
9012         case NK_COMMAND_RECT: {
9013             const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
9014             nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9015                 r->color, (float)r->rounding, r->line_thickness);
9016         } break;
9017         case NK_COMMAND_RECT_FILLED: {
9018             const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
9019             nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9020                 r->color, (float)r->rounding);
9021         } break;
9022         case NK_COMMAND_RECT_MULTI_COLOR: {
9023             const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
9024             nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9025                 r->left, r->top, r->right, r->bottom);
9026         } break;
9027         case NK_COMMAND_CIRCLE: {
9028             const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
9029             nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
9030                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
9031                 config->circle_segment_count, c->line_thickness);
9032         } break;
9033         case NK_COMMAND_CIRCLE_FILLED: {
9034             const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
9035             nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
9036                 (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
9037                 config->circle_segment_count);
9038         } break;
9039         case NK_COMMAND_ARC: {
9040             const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
9041             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
9042             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
9043                 c->a[0], c->a[1], config->arc_segment_count);
9044             nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
9045         } break;
9046         case NK_COMMAND_ARC_FILLED: {
9047             const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
9048             nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
9049             nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
9050                 c->a[0], c->a[1], config->arc_segment_count);
9051             nk_draw_list_path_fill(&ctx->draw_list, c->color);
9052         } break;
9053         case NK_COMMAND_TRIANGLE: {
9054             const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
9055             nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
9056                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
9057                 t->line_thickness);
9058         } break;
9059         case NK_COMMAND_TRIANGLE_FILLED: {
9060             const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
9061             nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
9062                 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
9063         } break;
9064         case NK_COMMAND_POLYGON: {
9065             int i;
9066             const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
9067             for (i = 0; i < p->point_count; ++i) {
9068                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9069                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9070             }
9071             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
9072         } break;
9073         case NK_COMMAND_POLYGON_FILLED: {
9074             int i;
9075             const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
9076             for (i = 0; i < p->point_count; ++i) {
9077                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9078                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9079             }
9080             nk_draw_list_path_fill(&ctx->draw_list, p->color);
9081         } break;
9082         case NK_COMMAND_POLYLINE: {
9083             int i;
9084             const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
9085             for (i = 0; i < p->point_count; ++i) {
9086                 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9087                 nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9088             }
9089             nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
9090         } break;
9091         case NK_COMMAND_TEXT: {
9092             const struct nk_command_text *t = (const struct nk_command_text*)cmd;
9093             nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
9094                 t->string, t->length, t->height, t->foreground);
9095         } break;
9096         case NK_COMMAND_IMAGE: {
9097             const struct nk_command_image *i = (const struct nk_command_image*)cmd;
9098             nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
9099         } break;
9100         case NK_COMMAND_CUSTOM: {
9101             const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
9102             c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
9103         } break;
9104         default: break;
9105         }
9106     }
9107     res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
9108     res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
9109     res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
9110     return res;
9111 }
9112 NK_API const struct nk_draw_command*
9113 nk__draw_begin(const struct nk_context *ctx,
9114     const struct nk_buffer *buffer)
9115 {return nk__draw_list_begin(&ctx->draw_list, buffer);}
9116 
9117 NK_API const struct nk_draw_command*
9118 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
9119 {return nk__draw_list_end(&ctx->draw_list, buffer);}
9120 
9121 NK_API const struct nk_draw_command*
9122 nk__draw_next(const struct nk_draw_command *cmd,
9123     const struct nk_buffer *buffer, const struct nk_context *ctx)
9124 {return nk__draw_list_next(cmd, buffer, &ctx->draw_list);}
9125 
9126 #endif
9127 
9128 /*
9129  * ==============================================================
9130  *
9131  *                          FONT HANDLING
9132  *
9133  * ===============================================================
9134  */
9135 #ifdef NK_INCLUDE_FONT_BAKING
9136 /* -------------------------------------------------------------
9137  *
9138  *                          RECT PACK
9139  *
9140  * --------------------------------------------------------------*/
9141 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
9142 /* Sean Barrett 2014 */
9143 #define NK_RP__MAXVAL  0xffff
9144 typedef unsigned short nk_rp_coord;
9145 
9146 struct nk_rp_rect {
9147     /* reserved for your use: */
9148     int id;
9149     /* input: */
9150     nk_rp_coord w, h;
9151     /* output: */
9152     nk_rp_coord x, y;
9153     int was_packed;
9154     /* non-zero if valid packing */
9155 }; /* 16 bytes, nominally */
9156 
9157 struct nk_rp_node {
9158     nk_rp_coord  x,y;
9159     struct nk_rp_node  *next;
9160 };
9161 
9162 struct nk_rp_context {
9163     int width;
9164     int height;
9165     int align;
9166     int init_mode;
9167     int heuristic;
9168     int num_nodes;
9169     struct nk_rp_node *active_head;
9170     struct nk_rp_node *free_head;
9171     struct nk_rp_node extra[2];
9172     /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
9173 };
9174 
9175 struct nk_rp__findresult {
9176     int x,y;
9177     struct nk_rp_node **prev_link;
9178 };
9179 
9180 enum NK_RP_HEURISTIC {
9181     NK_RP_HEURISTIC_Skyline_default=0,
9182     NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
9183     NK_RP_HEURISTIC_Skyline_BF_sortHeight
9184 };
9185 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
9186 
9187 NK_INTERN void
9188 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
9189 {
9190     if (allow_out_of_mem)
9191         /* if it's ok to run out of memory, then don't bother aligning them; */
9192         /* this gives better packing, but may fail due to OOM (even though */
9193         /* the rectangles easily fit). @TODO a smarter approach would be to only */
9194         /* quantize once we've hit OOM, then we could get rid of this parameter. */
9195         context->align = 1;
9196     else {
9197         /* if it's not ok to run out of memory, then quantize the widths */
9198         /* so that num_nodes is always enough nodes. */
9199         /* */
9200         /* I.e. num_nodes * align >= width */
9201         /*                  align >= width / num_nodes */
9202         /*                  align = ceil(width/num_nodes) */
9203         context->align = (context->width + context->num_nodes-1) / context->num_nodes;
9204     }
9205 }
9206 
9207 NK_INTERN void
9208 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
9209     struct nk_rp_node *nodes, int num_nodes)
9210 {
9211     int i;
9212 #ifndef STBRP_LARGE_RECTS
9213     NK_ASSERT(width <= 0xffff && height <= 0xffff);
9214 #endif
9215 
9216     for (i=0; i < num_nodes-1; ++i)
9217         nodes[i].next = &nodes[i+1];
9218     nodes[i].next = 0;
9219     context->init_mode = NK_RP__INIT_skyline;
9220     context->heuristic = NK_RP_HEURISTIC_Skyline_default;
9221     context->free_head = &nodes[0];
9222     context->active_head = &context->extra[0];
9223     context->width = width;
9224     context->height = height;
9225     context->num_nodes = num_nodes;
9226     nk_rp_setup_allow_out_of_mem(context, 0);
9227 
9228     /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
9229     context->extra[0].x = 0;
9230     context->extra[0].y = 0;
9231     context->extra[0].next = &context->extra[1];
9232     context->extra[1].x = (nk_rp_coord) width;
9233     context->extra[1].y = 65535;
9234     context->extra[1].next = 0;
9235 }
9236 
9237 /* find minimum y position if it starts at x1 */
9238 NK_INTERN int
9239 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
9240     int x0, int width, int *pwaste)
9241 {
9242     struct nk_rp_node *node = first;
9243     int x1 = x0 + width;
9244     int min_y, visited_width, waste_area;
9245     NK_ASSERT(first->x <= x0);
9246     NK_UNUSED(c);
9247 
9248     NK_ASSERT(node->next->x > x0);
9249     /* we ended up handling this in the caller for efficiency */
9250     NK_ASSERT(node->x <= x0);
9251 
9252     min_y = 0;
9253     waste_area = 0;
9254     visited_width = 0;
9255     while (node->x < x1)
9256     {
9257         if (node->y > min_y) {
9258             /* raise min_y higher. */
9259             /* we've accounted for all waste up to min_y, */
9260             /* but we'll now add more waste for everything we've visited */
9261             waste_area += visited_width * (node->y - min_y);
9262             min_y = node->y;
9263             /* the first time through, visited_width might be reduced */
9264             if (node->x < x0)
9265             visited_width += node->next->x - x0;
9266             else
9267             visited_width += node->next->x - node->x;
9268         } else {
9269             /* add waste area */
9270             int under_width = node->next->x - node->x;
9271             if (under_width + visited_width > width)
9272             under_width = width - visited_width;
9273             waste_area += under_width * (min_y - node->y);
9274             visited_width += under_width;
9275         }
9276         node = node->next;
9277     }
9278     *pwaste = waste_area;
9279     return min_y;
9280 }
9281 
9282 NK_INTERN struct nk_rp__findresult
9283 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
9284 {
9285     int best_waste = (1<<30), best_x, best_y = (1 << 30);
9286     struct nk_rp__findresult fr;
9287     struct nk_rp_node **prev, *node, *tail, **best = 0;
9288 
9289     /* align to multiple of c->align */
9290     width = (width + c->align - 1);
9291     width -= width % c->align;
9292     NK_ASSERT(width % c->align == 0);
9293 
9294     node = c->active_head;
9295     prev = &c->active_head;
9296     while (node->x + width <= c->width) {
9297         int y,waste;
9298         y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
9299         /* actually just want to test BL */
9300         if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
9301             /* bottom left */
9302             if (y < best_y) {
9303             best_y = y;
9304             best = prev;
9305             }
9306         } else {
9307             /* best-fit */
9308             if (y + height <= c->height) {
9309                 /* can only use it if it first vertically */
9310                 if (y < best_y || (y == best_y && waste < best_waste)) {
9311                     best_y = y;
9312                     best_waste = waste;
9313                     best = prev;
9314                 }
9315             }
9316         }
9317         prev = &node->next;
9318         node = node->next;
9319     }
9320     best_x = (best == 0) ? 0 : (*best)->x;
9321 
9322     /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
9323     /* */
9324     /* e.g, if fitting */
9325     /* */
9326     /*     ____________________ */
9327     /*    |____________________| */
9328     /* */
9329     /*            into */
9330     /* */
9331     /*   |                         | */
9332     /*   |             ____________| */
9333     /*   |____________| */
9334     /* */
9335     /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
9336     /* */
9337     /* This makes BF take about 2x the time */
9338     if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
9339     {
9340         tail = c->active_head;
9341         node = c->active_head;
9342         prev = &c->active_head;
9343         /* find first node that's admissible */
9344         while (tail->x < width)
9345             tail = tail->next;
9346         while (tail)
9347         {
9348             int xpos = tail->x - width;
9349             int y,waste;
9350             NK_ASSERT(xpos >= 0);
9351             /* find the left position that matches this */
9352             while (node->next->x <= xpos) {
9353                 prev = &node->next;
9354                 node = node->next;
9355             }
9356             NK_ASSERT(node->next->x > xpos && node->x <= xpos);
9357             y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
9358             if (y + height < c->height) {
9359                 if (y <= best_y) {
9360                     if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
9361                         best_x = xpos;
9362                         NK_ASSERT(y <= best_y);
9363                         best_y = y;
9364                         best_waste = waste;
9365                         best = prev;
9366                     }
9367                 }
9368             }
9369             tail = tail->next;
9370         }
9371     }
9372     fr.prev_link = best;
9373     fr.x = best_x;
9374     fr.y = best_y;
9375     return fr;
9376 }
9377 
9378 NK_INTERN struct nk_rp__findresult
9379 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
9380 {
9381     /* find best position according to heuristic */
9382     struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
9383     struct nk_rp_node *node, *cur;
9384 
9385     /* bail if: */
9386     /*    1. it failed */
9387     /*    2. the best node doesn't fit (we don't always check this) */
9388     /*    3. we're out of memory */
9389     if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
9390         res.prev_link = 0;
9391         return res;
9392     }
9393 
9394     /* on success, create new node */
9395     node = context->free_head;
9396     node->x = (nk_rp_coord) res.x;
9397     node->y = (nk_rp_coord) (res.y + height);
9398 
9399     context->free_head = node->next;
9400 
9401     /* insert the new node into the right starting point, and */
9402     /* let 'cur' point to the remaining nodes needing to be */
9403     /* stitched back in */
9404     cur = *res.prev_link;
9405     if (cur->x < res.x) {
9406         /* preserve the existing one, so start testing with the next one */
9407         struct nk_rp_node *next = cur->next;
9408         cur->next = node;
9409         cur = next;
9410     } else {
9411         *res.prev_link = node;
9412     }
9413 
9414     /* from here, traverse cur and free the nodes, until we get to one */
9415     /* that shouldn't be freed */
9416     while (cur->next && cur->next->x <= res.x + width) {
9417         struct nk_rp_node *next = cur->next;
9418         /* move the current node to the free list */
9419         cur->next = context->free_head;
9420         context->free_head = cur;
9421         cur = next;
9422     }
9423     /* stitch the list back in */
9424     node->next = cur;
9425 
9426     if (cur->x < res.x + width)
9427         cur->x = (nk_rp_coord) (res.x + width);
9428     return res;
9429 }
9430 
9431 NK_INTERN int
9432 nk_rect_height_compare(const void *a, const void *b)
9433 {
9434     const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9435     const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9436     if (p->h > q->h)
9437         return -1;
9438     if (p->h < q->h)
9439         return  1;
9440     return (p->w > q->w) ? -1 : (p->w < q->w);
9441 }
9442 
9443 NK_INTERN int
9444 nk_rect_original_order(const void *a, const void *b)
9445 {
9446     const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9447     const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9448     return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
9449 }
9450 
9451 NK_INTERN void
9452 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
9453 {
9454     /* iterative quick sort */
9455     #define NK_MAX_SORT_STACK 64
9456     unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
9457     unsigned seed = len/2 * 69069+1;
9458     for (;;) {
9459         for (; left+1 < len; len++) {
9460             struct nk_rp_rect pivot, tmp;
9461             if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
9462             pivot = array[left+seed%(len-left)];
9463             seed = seed * 69069 + 1;
9464             stack[pos++] = len;
9465             for (right = left-1;;) {
9466                 while (cmp(&array[++right], &pivot) < 0);
9467                 while (cmp(&pivot, &array[--len]) < 0);
9468                 if (right >= len) break;
9469                 tmp = array[right];
9470                 array[right] = array[len];
9471                 array[len] = tmp;
9472             }
9473         }
9474         if (pos == 0) break;
9475         left = len;
9476         len = stack[--pos];
9477     }
9478     #undef NK_MAX_SORT_STACK
9479 }
9480 
9481 NK_INTERN void
9482 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
9483 {
9484     int i;
9485     /* we use the 'was_packed' field internally to allow sorting/unsorting */
9486     for (i=0; i < num_rects; ++i) {
9487         rects[i].was_packed = i;
9488     }
9489 
9490     /* sort according to heuristic */
9491     nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
9492 
9493     for (i=0; i < num_rects; ++i) {
9494         struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
9495         if (fr.prev_link) {
9496             rects[i].x = (nk_rp_coord) fr.x;
9497             rects[i].y = (nk_rp_coord) fr.y;
9498         } else {
9499             rects[i].x = rects[i].y = NK_RP__MAXVAL;
9500         }
9501     }
9502 
9503     /* unsort */
9504     nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
9505 
9506     /* set was_packed flags */
9507     for (i=0; i < num_rects; ++i)
9508         rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
9509 }
9510 
9511 /*
9512  * ==============================================================
9513  *
9514  *                          TRUETYPE
9515  *
9516  * ===============================================================
9517  */
9518 /* stb_truetype.h - v1.07 - public domain */
9519 #define NK_TT_MAX_OVERSAMPLE   8
9520 #define NK_TT__OVER_MASK  (NK_TT_MAX_OVERSAMPLE-1)
9521 
9522 struct nk_tt_bakedchar {
9523     unsigned short x0,y0,x1,y1;
9524     /* coordinates of bbox in bitmap */
9525     float xoff,yoff,xadvance;
9526 };
9527 
9528 struct nk_tt_aligned_quad{
9529     float x0,y0,s0,t0; /* top-left */
9530     float x1,y1,s1,t1; /* bottom-right */
9531 };
9532 
9533 struct nk_tt_packedchar {
9534     unsigned short x0,y0,x1,y1;
9535     /* coordinates of bbox in bitmap */
9536     float xoff,yoff,xadvance;
9537     float xoff2,yoff2;
9538 };
9539 
9540 struct nk_tt_pack_range {
9541     float font_size;
9542     int first_unicode_codepoint_in_range;
9543     /* if non-zero, then the chars are continuous, and this is the first codepoint */
9544     int *array_of_unicode_codepoints;
9545     /* if non-zero, then this is an array of unicode codepoints */
9546     int num_chars;
9547     struct nk_tt_packedchar *chardata_for_range; /* output */
9548     unsigned char h_oversample, v_oversample;
9549     /* don't set these, they're used internally */
9550 };
9551 
9552 struct nk_tt_pack_context {
9553     void *pack_info;
9554     int   width;
9555     int   height;
9556     int   stride_in_bytes;
9557     int   padding;
9558     unsigned int   h_oversample, v_oversample;
9559     unsigned char *pixels;
9560     void  *nodes;
9561 };
9562 
9563 struct nk_tt_fontinfo {
9564     const unsigned char* data; /* pointer to .ttf file */
9565     int fontstart;/* offset of start of font */
9566     int numGlyphs;/* number of glyphs, needed for range checking */
9567     int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
9568     int index_map; /* a cmap mapping for our chosen character encoding */
9569     int indexToLocFormat; /* format needed to map from glyph index to glyph */
9570 };
9571 
9572 enum {
9573   NK_TT_vmove=1,
9574   NK_TT_vline,
9575   NK_TT_vcurve
9576 };
9577 
9578 struct nk_tt_vertex {
9579     short x,y,cx,cy;
9580     unsigned char type,padding;
9581 };
9582 
9583 struct nk_tt__bitmap{
9584    int w,h,stride;
9585    unsigned char *pixels;
9586 };
9587 
9588 struct nk_tt__hheap_chunk {
9589     struct nk_tt__hheap_chunk *next;
9590 };
9591 struct nk_tt__hheap {
9592     struct nk_allocator alloc;
9593     struct nk_tt__hheap_chunk *head;
9594     void   *first_free;
9595     int    num_remaining_in_head_chunk;
9596 };
9597 
9598 struct nk_tt__edge {
9599     float x0,y0, x1,y1;
9600     int invert;
9601 };
9602 
9603 struct nk_tt__active_edge {
9604     struct nk_tt__active_edge *next;
9605     float fx,fdx,fdy;
9606     float direction;
9607     float sy;
9608     float ey;
9609 };
9610 struct nk_tt__point {float x,y;};
9611 
9612 #define NK_TT_MACSTYLE_DONTCARE     0
9613 #define NK_TT_MACSTYLE_BOLD         1
9614 #define NK_TT_MACSTYLE_ITALIC       2
9615 #define NK_TT_MACSTYLE_UNDERSCORE   4
9616 #define NK_TT_MACSTYLE_NONE         8
9617 /* <= not same as 0, this makes us check the bitfield is 0 */
9618 
9619 enum { /* platformID */
9620    NK_TT_PLATFORM_ID_UNICODE   =0,
9621    NK_TT_PLATFORM_ID_MAC       =1,
9622    NK_TT_PLATFORM_ID_ISO       =2,
9623    NK_TT_PLATFORM_ID_MICROSOFT =3
9624 };
9625 
9626 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
9627    NK_TT_UNICODE_EID_UNICODE_1_0    =0,
9628    NK_TT_UNICODE_EID_UNICODE_1_1    =1,
9629    NK_TT_UNICODE_EID_ISO_10646      =2,
9630    NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
9631    NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
9632 };
9633 
9634 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
9635    NK_TT_MS_EID_SYMBOL        =0,
9636    NK_TT_MS_EID_UNICODE_BMP   =1,
9637    NK_TT_MS_EID_SHIFTJIS      =2,
9638    NK_TT_MS_EID_UNICODE_FULL  =10
9639 };
9640 
9641 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
9642    NK_TT_MAC_EID_ROMAN        =0,   NK_TT_MAC_EID_ARABIC       =4,
9643    NK_TT_MAC_EID_JAPANESE     =1,   NK_TT_MAC_EID_HEBREW       =5,
9644    NK_TT_MAC_EID_CHINESE_TRAD =2,   NK_TT_MAC_EID_GREEK        =6,
9645    NK_TT_MAC_EID_KOREAN       =3,   NK_TT_MAC_EID_RUSSIAN      =7
9646 };
9647 
9648 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
9649        /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
9650    NK_TT_MS_LANG_ENGLISH     =0x0409,   NK_TT_MS_LANG_ITALIAN     =0x0410,
9651    NK_TT_MS_LANG_CHINESE     =0x0804,   NK_TT_MS_LANG_JAPANESE    =0x0411,
9652    NK_TT_MS_LANG_DUTCH       =0x0413,   NK_TT_MS_LANG_KOREAN      =0x0412,
9653    NK_TT_MS_LANG_FRENCH      =0x040c,   NK_TT_MS_LANG_RUSSIAN     =0x0419,
9654    NK_TT_MS_LANG_GERMAN      =0x0407,   NK_TT_MS_LANG_SPANISH     =0x0409,
9655    NK_TT_MS_LANG_HEBREW      =0x040d,   NK_TT_MS_LANG_SWEDISH     =0x041D
9656 };
9657 
9658 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
9659    NK_TT_MAC_LANG_ENGLISH      =0 ,   NK_TT_MAC_LANG_JAPANESE     =11,
9660    NK_TT_MAC_LANG_ARABIC       =12,   NK_TT_MAC_LANG_KOREAN       =23,
9661    NK_TT_MAC_LANG_DUTCH        =4 ,   NK_TT_MAC_LANG_RUSSIAN      =32,
9662    NK_TT_MAC_LANG_FRENCH       =1 ,   NK_TT_MAC_LANG_SPANISH      =6 ,
9663    NK_TT_MAC_LANG_GERMAN       =2 ,   NK_TT_MAC_LANG_SWEDISH      =5 ,
9664    NK_TT_MAC_LANG_HEBREW       =10,   NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
9665    NK_TT_MAC_LANG_ITALIAN      =3 ,   NK_TT_MAC_LANG_CHINESE_TRAD =19
9666 };
9667 
9668 #define nk_ttBYTE(p)     (* (const nk_byte *) (p))
9669 #define nk_ttCHAR(p)     (* (const char *) (p))
9670 
9671 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
9672    #define nk_ttUSHORT(p)   (* (nk_ushort *) (p))
9673    #define nk_ttSHORT(p)    (* (nk_short *) (p))
9674    #define nk_ttULONG(p)    (* (nk_uint *) (p))
9675    #define nk_ttLONG(p)     (* (nk_int *) (p))
9676 #else
9677     static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
9678     static nk_short nk_ttSHORT(const nk_byte *p)   { return (nk_short)(p[0]*256 + p[1]); }
9679     static nk_uint nk_ttULONG(const nk_byte *p)  { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
9680 #endif
9681 
9682 #define nk_tt_tag4(p,c0,c1,c2,c3)\
9683     ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
9684 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
9685 
9686 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9687                                 int glyph_index, struct nk_tt_vertex **pvertices);
9688 
9689 NK_INTERN nk_uint
9690 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
9691 {
9692     /* @OPTIMIZE: binary search */
9693     nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
9694     nk_uint tabledir = fontstart + 12;
9695     nk_int i;
9696     for (i = 0; i < num_tables; ++i) {
9697         nk_uint loc = tabledir + (nk_uint)(16*i);
9698         if (nk_tt_tag(data+loc+0, tag))
9699             return nk_ttULONG(data+loc+8);
9700     }
9701     return 0;
9702 }
9703 
9704 NK_INTERN int
9705 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
9706 {
9707     nk_uint cmap, t;
9708     nk_int i,numTables;
9709     const nk_byte *data = (const nk_byte *) data2;
9710 
9711     info->data = data;
9712     info->fontstart = fontstart;
9713 
9714     cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap");       /* required */
9715     info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
9716     info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
9717     info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
9718     info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
9719     info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
9720     info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
9721     if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
9722         return 0;
9723 
9724     t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
9725     if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
9726     else info->numGlyphs = 0xffff;
9727 
9728     /* find a cmap encoding table we understand *now* to avoid searching */
9729     /* later. (todo: could make this installable) */
9730     /* the same regardless of glyph. */
9731     numTables = nk_ttUSHORT(data + cmap + 2);
9732     info->index_map = 0;
9733     for (i=0; i < numTables; ++i)
9734     {
9735         nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
9736         /* find an encoding we understand: */
9737         switch(nk_ttUSHORT(data+encoding_record)) {
9738         case NK_TT_PLATFORM_ID_MICROSOFT:
9739             switch (nk_ttUSHORT(data+encoding_record+2)) {
9740             case NK_TT_MS_EID_UNICODE_BMP:
9741             case NK_TT_MS_EID_UNICODE_FULL:
9742                 /* MS/Unicode */
9743                 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9744                 break;
9745             default: break;
9746             } break;
9747         case NK_TT_PLATFORM_ID_UNICODE:
9748             /* Mac/iOS has these */
9749             /* all the encodingIDs are unicode, so we don't bother to check it */
9750             info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9751             break;
9752         default: break;
9753         }
9754     }
9755     if (info->index_map == 0)
9756         return 0;
9757     info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
9758     return 1;
9759 }
9760 
9761 NK_INTERN int
9762 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
9763 {
9764     const nk_byte *data = info->data;
9765     nk_uint index_map = (nk_uint)info->index_map;
9766 
9767     nk_ushort format = nk_ttUSHORT(data + index_map + 0);
9768     if (format == 0) { /* apple byte encoding */
9769         nk_int bytes = nk_ttUSHORT(data + index_map + 2);
9770         if (unicode_codepoint < bytes-6)
9771             return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
9772         return 0;
9773     } else if (format == 6) {
9774         nk_uint first = nk_ttUSHORT(data + index_map + 6);
9775         nk_uint count = nk_ttUSHORT(data + index_map + 8);
9776         if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
9777             return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
9778         return 0;
9779     } else if (format == 2) {
9780         NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
9781         return 0;
9782     } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
9783         nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
9784         nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
9785         nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
9786         nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
9787 
9788         /* do a binary search of the segments */
9789         nk_uint endCount = index_map + 14;
9790         nk_uint search = endCount;
9791 
9792         if (unicode_codepoint > 0xffff)
9793             return 0;
9794 
9795         /* they lie from endCount .. endCount + segCount */
9796         /* but searchRange is the nearest power of two, so... */
9797         if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
9798             search += (nk_uint)(rangeShift*2);
9799 
9800         /* now decrement to bias correctly to find smallest */
9801         search -= 2;
9802         while (entrySelector) {
9803             nk_ushort end;
9804             searchRange >>= 1;
9805             end = nk_ttUSHORT(data + search + searchRange*2);
9806             if (unicode_codepoint > end)
9807                 search += (nk_uint)(searchRange*2);
9808             --entrySelector;
9809         }
9810         search += 2;
9811 
9812       {
9813          nk_ushort offset, start;
9814          nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
9815 
9816          NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
9817          start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
9818          if (unicode_codepoint < start)
9819             return 0;
9820 
9821          offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
9822          if (offset == 0)
9823             return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
9824 
9825          return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
9826       }
9827    } else if (format == 12 || format == 13) {
9828         nk_uint ngroups = nk_ttULONG(data+index_map+12);
9829         nk_int low,high;
9830         low = 0; high = (nk_int)ngroups;
9831         /* Binary search the right group. */
9832         while (low < high) {
9833             nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
9834             nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
9835             nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
9836             if ((nk_uint) unicode_codepoint < start_char)
9837                 high = mid;
9838             else if ((nk_uint) unicode_codepoint > end_char)
9839                 low = mid+1;
9840             else {
9841                 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
9842                 if (format == 12)
9843                     return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
9844                 else /* format == 13 */
9845                     return (int)start_glyph;
9846             }
9847         }
9848         return 0; /* not found */
9849     }
9850     /* @TODO */
9851     NK_ASSERT(0);
9852     return 0;
9853 }
9854 
9855 NK_INTERN void
9856 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
9857 {
9858     v->type = type;
9859     v->x = (nk_short) x;
9860     v->y = (nk_short) y;
9861     v->cx = (nk_short) cx;
9862     v->cy = (nk_short) cy;
9863 }
9864 
9865 NK_INTERN int
9866 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
9867 {
9868     int g1,g2;
9869     if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
9870     if (info->indexToLocFormat >= 2)    return -1; /* unknown index->glyph map format */
9871 
9872     if (info->indexToLocFormat == 0) {
9873         g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
9874         g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
9875     } else {
9876         g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
9877         g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
9878     }
9879     return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
9880 }
9881 
9882 NK_INTERN int
9883 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
9884     int *x0, int *y0, int *x1, int *y1)
9885 {
9886     int g = nk_tt__GetGlyfOffset(info, glyph_index);
9887     if (g < 0) return 0;
9888 
9889     if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
9890     if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
9891     if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
9892     if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
9893     return 1;
9894 }
9895 
9896 NK_INTERN int
9897 stbtt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
9898     int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
9899 {
9900    if (start_off) {
9901       if (was_off)
9902          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
9903       nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
9904    } else {
9905       if (was_off)
9906          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
9907       else
9908          nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
9909    }
9910    return num_vertices;
9911 }
9912 
9913 NK_INTERN int
9914 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9915     int glyph_index, struct nk_tt_vertex **pvertices)
9916 {
9917     nk_short numberOfContours;
9918     const nk_byte *endPtsOfContours;
9919     const nk_byte *data = info->data;
9920     struct nk_tt_vertex *vertices=0;
9921     int num_vertices=0;
9922     int g = nk_tt__GetGlyfOffset(info, glyph_index);
9923     *pvertices = 0;
9924 
9925     if (g < 0) return 0;
9926     numberOfContours = nk_ttSHORT(data + g);
9927     if (numberOfContours > 0) {
9928         nk_byte flags=0,flagcount;
9929         nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
9930         nk_int x,y,cx,cy,sx,sy, scx,scy;
9931         const nk_byte *points;
9932         endPtsOfContours = (data + g + 10);
9933         ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
9934         points = data + g + 10 + numberOfContours * 2 + 2 + ins;
9935 
9936         n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
9937         m = n + 2*numberOfContours;  /* a loose bound on how many vertices we might need */
9938         vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
9939         if (vertices == 0)
9940             return 0;
9941 
9942         next_move = 0;
9943         flagcount=0;
9944 
9945         /* in first pass, we load uninterpreted data into the allocated array */
9946         /* above, shifted to the end of the array so we won't overwrite it when */
9947         /* we create our final data starting from the front */
9948         off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
9949 
9950         /* first load flags */
9951         for (i=0; i < n; ++i) {
9952             if (flagcount == 0) {
9953                 flags = *points++;
9954                 if (flags & 8)
9955                     flagcount = *points++;
9956             } else --flagcount;
9957             vertices[off+i].type = flags;
9958         }
9959 
9960         /* now load x coordinates */
9961         x=0;
9962         for (i=0; i < n; ++i) {
9963             flags = vertices[off+i].type;
9964             if (flags & 2) {
9965                 nk_short dx = *points++;
9966                 x += (flags & 16) ? dx : -dx; /* ??? */
9967             } else {
9968                 if (!(flags & 16)) {
9969                     x = x + (nk_short) (points[0]*256 + points[1]);
9970                     points += 2;
9971                 }
9972             }
9973             vertices[off+i].x = (nk_short) x;
9974         }
9975 
9976         /* now load y coordinates */
9977         y=0;
9978         for (i=0; i < n; ++i) {
9979             flags = vertices[off+i].type;
9980             if (flags & 4) {
9981                 nk_short dy = *points++;
9982                 y += (flags & 32) ? dy : -dy; /* ??? */
9983             } else {
9984                 if (!(flags & 32)) {
9985                     y = y + (nk_short) (points[0]*256 + points[1]);
9986                     points += 2;
9987                 }
9988             }
9989             vertices[off+i].y = (nk_short) y;
9990         }
9991 
9992         /* now convert them to our format */
9993         num_vertices=0;
9994         sx = sy = cx = cy = scx = scy = 0;
9995         for (i=0; i < n; ++i)
9996         {
9997             flags = vertices[off+i].type;
9998             x     = (nk_short) vertices[off+i].x;
9999             y     = (nk_short) vertices[off+i].y;
10000 
10001             if (next_move == i) {
10002                 if (i != 0)
10003                     num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
10004 
10005                 /* now start the new one                */
10006                 start_off = !(flags & 1);
10007                 if (start_off) {
10008                     /* if we start off with an off-curve point, then when we need to find a point on the curve */
10009                     /* where we can start, and we need to save some state for when we wraparound. */
10010                     scx = x;
10011                     scy = y;
10012                     if (!(vertices[off+i+1].type & 1)) {
10013                         /* next point is also a curve point, so interpolate an on-point curve */
10014                         sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
10015                         sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
10016                     } else {
10017                         /* otherwise just use the next point as our start point */
10018                         sx = (nk_int) vertices[off+i+1].x;
10019                         sy = (nk_int) vertices[off+i+1].y;
10020                         ++i; /* we're using point i+1 as the starting point, so skip it */
10021                     }
10022                 } else {
10023                     sx = x;
10024                     sy = y;
10025                 }
10026                 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
10027                 was_off = 0;
10028                 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
10029                 ++j;
10030             } else {
10031                 if (!(flags & 1))
10032                 { /* if it's a curve */
10033                     if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
10034                         nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
10035                     cx = x;
10036                     cy = y;
10037                     was_off = 1;
10038                 } else {
10039                     if (was_off)
10040                         nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
10041                     else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
10042                     was_off = 0;
10043                 }
10044             }
10045         }
10046         num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
10047     } else if (numberOfContours == -1) {
10048         /* Compound shapes. */
10049         int more = 1;
10050         const nk_byte *comp = data + g + 10;
10051         num_vertices = 0;
10052         vertices = 0;
10053 
10054         while (more)
10055         {
10056             nk_ushort flags, gidx;
10057             int comp_num_verts = 0, i;
10058             struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
10059             float mtx[6] = {1,0,0,1,0,0}, m, n;
10060 
10061             flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
10062             gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
10063 
10064             if (flags & 2) { /* XY values */
10065                 if (flags & 1) { /* shorts */
10066                     mtx[4] = nk_ttSHORT(comp); comp+=2;
10067                     mtx[5] = nk_ttSHORT(comp); comp+=2;
10068                 } else {
10069                     mtx[4] = nk_ttCHAR(comp); comp+=1;
10070                     mtx[5] = nk_ttCHAR(comp); comp+=1;
10071                 }
10072             } else {
10073                 /* @TODO handle matching point */
10074                 NK_ASSERT(0);
10075             }
10076             if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
10077                 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10078                 mtx[1] = mtx[2] = 0;
10079             } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
10080                 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10081                 mtx[1] = mtx[2] = 0;
10082                 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10083             } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
10084                 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10085                 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10086                 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10087                 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10088             }
10089 
10090              /* Find transformation scales. */
10091             m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
10092             n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
10093 
10094              /* Get indexed glyph. */
10095             comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
10096             if (comp_num_verts > 0)
10097             {
10098                 /* Transform vertices. */
10099                 for (i = 0; i < comp_num_verts; ++i) {
10100                     struct nk_tt_vertex* v = &comp_verts[i];
10101                     short x,y;
10102                     x=v->x; y=v->y;
10103                     v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
10104                     v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
10105                     x=v->cx; y=v->cy;
10106                     v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
10107                     v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
10108                 }
10109                 /* Append vertices. */
10110                 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
10111                     (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
10112                 if (!tmp) {
10113                     if (vertices) alloc->free(alloc->userdata, vertices);
10114                     if (comp_verts) alloc->free(alloc->userdata, comp_verts);
10115                     return 0;
10116                 }
10117                 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
10118                 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
10119                 if (vertices) alloc->free(alloc->userdata,vertices);
10120                 vertices = tmp;
10121                 alloc->free(alloc->userdata,comp_verts);
10122                 num_vertices += comp_num_verts;
10123             }
10124             /* More components ? */
10125             more = flags & (1<<5);
10126         }
10127     } else if (numberOfContours < 0) {
10128         /* @TODO other compound variations? */
10129         NK_ASSERT(0);
10130     } else {
10131         /* numberOfCounters == 0, do nothing */
10132     }
10133     *pvertices = vertices;
10134     return num_vertices;
10135 }
10136 
10137 NK_INTERN void
10138 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
10139     int *advanceWidth, int *leftSideBearing)
10140 {
10141     nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
10142     if (glyph_index < numOfLongHorMetrics) {
10143         if (advanceWidth)
10144             *advanceWidth    = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
10145         if (leftSideBearing)
10146             *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
10147     } else {
10148         if (advanceWidth)
10149             *advanceWidth    = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
10150         if (leftSideBearing)
10151             *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
10152     }
10153 }
10154 
10155 NK_INTERN void
10156 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
10157     int *ascent, int *descent, int *lineGap)
10158 {
10159    if (ascent ) *ascent  = nk_ttSHORT(info->data+info->hhea + 4);
10160    if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
10161    if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
10162 }
10163 
10164 NK_INTERN float
10165 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
10166 {
10167    int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
10168    return (float) height / (float)fheight;
10169 }
10170 
10171 NK_INTERN float
10172 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
10173 {
10174    int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
10175    return pixels / (float)unitsPerEm;
10176 }
10177 
10178 /*-------------------------------------------------------------
10179  *            antialiasing software rasterizer
10180  * --------------------------------------------------------------*/
10181 NK_INTERN void
10182 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
10183     int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
10184     int *ix0, int *iy0, int *ix1, int *iy1)
10185 {
10186     int x0,y0,x1,y1;
10187     if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
10188         /* e.g. space character */
10189         if (ix0) *ix0 = 0;
10190         if (iy0) *iy0 = 0;
10191         if (ix1) *ix1 = 0;
10192         if (iy1) *iy1 = 0;
10193     } else {
10194         /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
10195         if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
10196         if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
10197         if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
10198         if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
10199     }
10200 }
10201 
10202 NK_INTERN void
10203 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
10204     float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
10205 {
10206    nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
10207 }
10208 
10209 /*-------------------------------------------------------------
10210  *                          Rasterizer
10211  * --------------------------------------------------------------*/
10212 NK_INTERN void*
10213 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
10214 {
10215     if (hh->first_free) {
10216         void *p = hh->first_free;
10217         hh->first_free = * (void **) p;
10218         return p;
10219     } else {
10220         if (hh->num_remaining_in_head_chunk == 0) {
10221             int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
10222             struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
10223                 hh->alloc.alloc(hh->alloc.userdata, 0,
10224                 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
10225             if (c == 0) return 0;
10226             c->next = hh->head;
10227             hh->head = c;
10228             hh->num_remaining_in_head_chunk = count;
10229         }
10230         --hh->num_remaining_in_head_chunk;
10231         return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
10232     }
10233 }
10234 
10235 NK_INTERN void
10236 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
10237 {
10238     *(void **) p = hh->first_free;
10239     hh->first_free = p;
10240 }
10241 
10242 NK_INTERN void
10243 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
10244 {
10245     struct nk_tt__hheap_chunk *c = hh->head;
10246     while (c) {
10247         struct nk_tt__hheap_chunk *n = c->next;
10248         hh->alloc.free(hh->alloc.userdata, c);
10249         c = n;
10250     }
10251 }
10252 
10253 NK_INTERN struct nk_tt__active_edge*
10254 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
10255     int off_x, float start_point)
10256 {
10257     struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
10258         nk_tt__hheap_alloc(hh, sizeof(*z));
10259     float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
10260     /*STBTT_assert(e->y0 <= start_point); */
10261     if (!z) return z;
10262     z->fdx = dxdy;
10263     z->fdy = (dxdy != 0) ? (1/dxdy): 0;
10264     z->fx = e->x0 + dxdy * (start_point - e->y0);
10265     z->fx -= (float)off_x;
10266     z->direction = e->invert ? 1.0f : -1.0f;
10267     z->sy = e->y0;
10268     z->ey = e->y1;
10269     z->next = 0;
10270     return z;
10271 }
10272 
10273 NK_INTERN void
10274 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
10275     float x0, float y0, float x1, float y1)
10276 {
10277     if (y0 == y1) return;
10278     NK_ASSERT(y0 < y1);
10279     NK_ASSERT(e->sy <= e->ey);
10280     if (y0 > e->ey) return;
10281     if (y1 < e->sy) return;
10282     if (y0 < e->sy) {
10283         x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
10284         y0 = e->sy;
10285     }
10286     if (y1 > e->ey) {
10287         x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
10288         y1 = e->ey;
10289     }
10290 
10291     if (x0 == x) NK_ASSERT(x1 <= x+1);
10292     else if (x0 == x+1) NK_ASSERT(x1 >= x);
10293     else if (x0 <= x) NK_ASSERT(x1 <= x);
10294     else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
10295     else NK_ASSERT(x1 >= x && x1 <= x+1);
10296 
10297     if (x0 <= x && x1 <= x)
10298         scanline[x] += e->direction * (y1-y0);
10299     else if (x0 >= x+1 && x1 >= x+1);
10300     else {
10301         NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
10302         /* coverage = 1 - average x position */
10303         scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
10304     }
10305 }
10306 
10307 NK_INTERN void
10308 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
10309     struct nk_tt__active_edge *e, float y_top)
10310 {
10311     float y_bottom = y_top+1;
10312     while (e)
10313     {
10314         /* brute force every pixel */
10315         /* compute intersection points with top & bottom */
10316         NK_ASSERT(e->ey >= y_top);
10317         if (e->fdx == 0) {
10318             float x0 = e->fx;
10319             if (x0 < len) {
10320                 if (x0 >= 0) {
10321                     nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
10322                     nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
10323                 } else {
10324                     nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
10325                 }
10326             }
10327         } else {
10328             float x0 = e->fx;
10329             float dx = e->fdx;
10330             float xb = x0 + dx;
10331             float x_top, x_bottom;
10332             float y0,y1;
10333             float dy = e->fdy;
10334             NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
10335 
10336             /* compute endpoints of line segment clipped to this scanline (if the */
10337             /* line segment starts on this scanline. x0 is the intersection of the */
10338             /* line with y_top, but that may be off the line segment. */
10339             if (e->sy > y_top) {
10340                 x_top = x0 + dx * (e->sy - y_top);
10341                 y0 = e->sy;
10342             } else {
10343                 x_top = x0;
10344                 y0 = y_top;
10345             }
10346 
10347             if (e->ey < y_bottom) {
10348                 x_bottom = x0 + dx * (e->ey - y_top);
10349                 y1 = e->ey;
10350             } else {
10351                 x_bottom = xb;
10352                 y1 = y_bottom;
10353             }
10354 
10355             if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
10356             {
10357                 /* from here on, we don't have to range check x values */
10358                 if ((int) x_top == (int) x_bottom) {
10359                     float height;
10360                     /* simple case, only spans one pixel */
10361                     int x = (int) x_top;
10362                     height = y1 - y0;
10363                     NK_ASSERT(x >= 0 && x < len);
10364                     scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f)  * (float)height;
10365                     scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
10366                 } else {
10367                     int x,x1,x2;
10368                     float y_crossing, step, sign, area;
10369                     /* covers 2+ pixels */
10370                     if (x_top > x_bottom)
10371                     {
10372                         /* flip scanline vertically; signed area is the same */
10373                         float t;
10374                         y0 = y_bottom - (y0 - y_top);
10375                         y1 = y_bottom - (y1 - y_top);
10376                         t = y0; y0 = y1; y1 = t;
10377                         t = x_bottom; x_bottom = x_top; x_top = t;
10378                         dx = -dx;
10379                         dy = -dy;
10380                         t = x0; x0 = xb; xb = t;
10381                     }
10382 
10383                     x1 = (int) x_top;
10384                     x2 = (int) x_bottom;
10385                     /* compute intersection with y axis at x1+1 */
10386                     y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
10387 
10388                     sign = e->direction;
10389                     /* area of the rectangle covered from y0..y_crossing */
10390                     area = sign * (y_crossing-y0);
10391                     /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
10392                     scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
10393 
10394                     step = sign * dy;
10395                     for (x = x1+1; x < x2; ++x) {
10396                         scanline[x] += area + step/2;
10397                         area += step;
10398                     }
10399                     y_crossing += (float)dy * (float)(x2 - (x1+1));
10400 
10401                     scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
10402                     scanline_fill[x2] += sign * (y1-y0);
10403                 }
10404             }
10405             else
10406             {
10407                 /* if edge goes outside of box we're drawing, we require */
10408                 /* clipping logic. since this does not match the intended use */
10409                 /* of this library, we use a different, very slow brute */
10410                 /* force implementation */
10411                 int x;
10412                 for (x=0; x < len; ++x)
10413                 {
10414                     /* cases: */
10415                     /* */
10416                     /* there can be up to two intersections with the pixel. any intersection */
10417                     /* with left or right edges can be handled by splitting into two (or three) */
10418                     /* regions. intersections with top & bottom do not necessitate case-wise logic. */
10419                     /* */
10420                     /* the old way of doing this found the intersections with the left & right edges, */
10421                     /* then used some simple logic to produce up to three segments in sorted order */
10422                     /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
10423                     /* across the x border, then the corresponding y position might not be distinct */
10424                     /* from the other y segment, and it might ignored as an empty segment. to avoid */
10425                     /* that, we need to explicitly produce segments based on x positions. */
10426 
10427                     /* rename variables to clear pairs */
10428                     float ya = y_top;
10429                     float x1 = (float) (x);
10430                     float x2 = (float) (x+1);
10431                     float x3 = xb;
10432                     float y3 = y_bottom;
10433                     float yb,y2;
10434 
10435                     yb = ((float)x - x0) / dx + y_top;
10436                     y2 = ((float)x+1 - x0) / dx + y_top;
10437 
10438                     if (x0 < x1 && x3 > x2) {         /* three segments descending down-right */
10439                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10440                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
10441                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10442                     } else if (x3 < x1 && x0 > x2) {  /* three segments descending down-left */
10443                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10444                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
10445                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10446                     } else if (x0 < x1 && x3 > x1) {  /* two segments across x, down-right */
10447                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10448                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10449                     } else if (x3 < x1 && x0 > x1) {  /* two segments across x, down-left */
10450                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10451                         nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10452                     } else if (x0 < x2 && x3 > x2) {  /* two segments across x+1, down-right */
10453                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10454                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10455                     } else if (x3 < x2 && x0 > x2) {  /* two segments across x+1, down-left */
10456                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10457                         nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10458                     } else {  /* one segment */
10459                         nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
10460                     }
10461                 }
10462             }
10463         }
10464         e = e->next;
10465     }
10466 }
10467 
10468 /* directly AA rasterize edges w/o supersampling */
10469 NK_INTERN void
10470 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
10471     int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
10472 {
10473     struct nk_tt__hheap hh;
10474     struct nk_tt__active_edge *active = 0;
10475     int y,j=0, i;
10476     float scanline_data[129], *scanline, *scanline2;
10477 
10478     NK_UNUSED(vsubsample);
10479     nk_zero_struct(hh);
10480     hh.alloc = *alloc;
10481 
10482     if (result->w > 64)
10483         scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
10484     else scanline = scanline_data;
10485 
10486     scanline2 = scanline + result->w;
10487     y = off_y;
10488     e[n].y0 = (float) (off_y + result->h) + 1;
10489 
10490     while (j < result->h)
10491     {
10492         /* find center of pixel for this scanline */
10493         float scan_y_top    = (float)y + 0.0f;
10494         float scan_y_bottom = (float)y + 1.0f;
10495         struct nk_tt__active_edge **step = &active;
10496 
10497         NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
10498         NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
10499 
10500         /* update all active edges; */
10501         /* remove all active edges that terminate before the top of this scanline */
10502         while (*step) {
10503             struct nk_tt__active_edge * z = *step;
10504             if (z->ey <= scan_y_top) {
10505                 *step = z->next; /* delete from list */
10506                 NK_ASSERT(z->direction);
10507                 z->direction = 0;
10508                 nk_tt__hheap_free(&hh, z);
10509             } else {
10510                 step = &((*step)->next); /* advance through list */
10511             }
10512         }
10513 
10514         /* insert all edges that start before the bottom of this scanline */
10515         while (e->y0 <= scan_y_bottom) {
10516             if (e->y0 != e->y1) {
10517                 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
10518                 if (z != 0) {
10519                     NK_ASSERT(z->ey >= scan_y_top);
10520                     /* insert at front */
10521                     z->next = active;
10522                     active = z;
10523                 }
10524             }
10525             ++e;
10526         }
10527 
10528         /* now process all active edges */
10529         if (active)
10530             nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
10531 
10532         {
10533             float sum = 0;
10534             for (i=0; i < result->w; ++i) {
10535                 float k;
10536                 int m;
10537                 sum += scanline2[i];
10538                 k = scanline[i] + sum;
10539                 k = (float) NK_ABS(k) * 255.0f + 0.5f;
10540                 m = (int) k;
10541                 if (m > 255) m = 255;
10542                 result->pixels[j*result->stride + i] = (unsigned char) m;
10543             }
10544         }
10545         /* advance all the edges */
10546         step = &active;
10547         while (*step) {
10548             struct nk_tt__active_edge *z = *step;
10549             z->fx += z->fdx; /* advance to position for current scanline */
10550             step = &((*step)->next); /* advance through list */
10551         }
10552         ++y;
10553         ++j;
10554     }
10555     nk_tt__hheap_cleanup(&hh);
10556     if (scanline != scanline_data)
10557         alloc->free(alloc->userdata, scanline);
10558 }
10559 
10560 #define NK_TT__COMPARE(a,b)  ((a)->y0 < (b)->y0)
10561 NK_INTERN void
10562 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
10563 {
10564     int i,j;
10565     for (i=1; i < n; ++i) {
10566         struct nk_tt__edge t = p[i], *a = &t;
10567         j = i;
10568         while (j > 0) {
10569             struct nk_tt__edge *b = &p[j-1];
10570             int c = NK_TT__COMPARE(a,b);
10571             if (!c) break;
10572             p[j] = p[j-1];
10573             --j;
10574         }
10575         if (i != j)
10576             p[j] = t;
10577     }
10578 }
10579 
10580 NK_INTERN void
10581 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
10582 {
10583     /* threshold for transitioning to insertion sort */
10584     while (n > 12) {
10585         struct nk_tt__edge t;
10586         int c01,c12,c,m,i,j;
10587 
10588         /* compute median of three */
10589         m = n >> 1;
10590         c01 = NK_TT__COMPARE(&p[0],&p[m]);
10591         c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
10592 
10593         /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
10594         if (c01 != c12) {
10595             /* otherwise, we'll need to swap something else to middle */
10596             int z;
10597             c = NK_TT__COMPARE(&p[0],&p[n-1]);
10598             /* 0>mid && mid<n:  0>n => n; 0<n => 0 */
10599             /* 0<mid && mid>n:  0>n => 0; 0<n => n */
10600             z = (c == c12) ? 0 : n-1;
10601             t = p[z];
10602             p[z] = p[m];
10603             p[m] = t;
10604         }
10605 
10606         /* now p[m] is the median-of-three */
10607         /* swap it to the beginning so it won't move around */
10608         t = p[0];
10609         p[0] = p[m];
10610         p[m] = t;
10611 
10612         /* partition loop */
10613         i=1;
10614         j=n-1;
10615         for(;;) {
10616             /* handling of equality is crucial here */
10617             /* for sentinels & efficiency with duplicates */
10618             for (;;++i) {
10619                 if (!NK_TT__COMPARE(&p[i], &p[0])) break;
10620             }
10621             for (;;--j) {
10622                 if (!NK_TT__COMPARE(&p[0], &p[j])) break;
10623             }
10624 
10625             /* make sure we haven't crossed */
10626              if (i >= j) break;
10627              t = p[i];
10628              p[i] = p[j];
10629              p[j] = t;
10630 
10631             ++i;
10632             --j;
10633 
10634         }
10635 
10636         /* recurse on smaller side, iterate on larger */
10637         if (j < (n-i)) {
10638             nk_tt__sort_edges_quicksort(p,j);
10639             p = p+i;
10640             n = n-i;
10641         } else {
10642             nk_tt__sort_edges_quicksort(p+i, n-i);
10643             n = j;
10644         }
10645     }
10646 }
10647 
10648 NK_INTERN void
10649 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
10650 {
10651    nk_tt__sort_edges_quicksort(p, n);
10652    nk_tt__sort_edges_ins_sort(p, n);
10653 }
10654 
10655 NK_INTERN void
10656 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
10657     int *wcount, int windings, float scale_x, float scale_y,
10658     float shift_x, float shift_y, int off_x, int off_y, int invert,
10659     struct nk_allocator *alloc)
10660 {
10661     float y_scale_inv = invert ? -scale_y : scale_y;
10662     struct nk_tt__edge *e;
10663     int n,i,j,k,m;
10664     int vsubsample = 1;
10665     /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
10666 
10667     /* now we have to blow out the windings into explicit edge lists */
10668     n = 0;
10669     for (i=0; i < windings; ++i)
10670         n += wcount[i];
10671 
10672     e = (struct nk_tt__edge*)
10673        alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
10674     if (e == 0) return;
10675     n = 0;
10676 
10677     m=0;
10678     for (i=0; i < windings; ++i)
10679     {
10680         struct nk_tt__point *p = pts + m;
10681         m += wcount[i];
10682         j = wcount[i]-1;
10683         for (k=0; k < wcount[i]; j=k++) {
10684             int a=k,b=j;
10685             /* skip the edge if horizontal */
10686             if (p[j].y == p[k].y)
10687                 continue;
10688 
10689             /* add edge from j to k to the list */
10690             e[n].invert = 0;
10691             if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
10692                 e[n].invert = 1;
10693                 a=j,b=k;
10694             }
10695             e[n].x0 = p[a].x * scale_x + shift_x;
10696             e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
10697             e[n].x1 = p[b].x * scale_x + shift_x;
10698             e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
10699             ++n;
10700         }
10701     }
10702 
10703     /* now sort the edges by their highest point (should snap to integer, and then by x) */
10704     /*STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */
10705     nk_tt__sort_edges(e, n);
10706     /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
10707     nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
10708     alloc->free(alloc->userdata, e);
10709 }
10710 
10711 NK_INTERN void
10712 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
10713 {
10714     if (!points) return; /* during first pass, it's unallocated */
10715     points[n].x = x;
10716     points[n].y = y;
10717 }
10718 
10719 NK_INTERN int
10720 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
10721     float x0, float y0, float x1, float y1, float x2, float y2,
10722     float objspace_flatness_squared, int n)
10723 {
10724     /* tesselate until threshold p is happy...
10725      * @TODO warped to compensate for non-linear stretching */
10726     /* midpoint */
10727     float mx = (x0 + 2*x1 + x2)/4;
10728     float my = (y0 + 2*y1 + y2)/4;
10729     /* versus directly drawn line */
10730     float dx = (x0+x2)/2 - mx;
10731     float dy = (y0+y2)/2 - my;
10732     if (n > 16) /* 65536 segments on one curve better be enough! */
10733         return 1;
10734 
10735     /* half-pixel error allowed... need to be smaller if AA */
10736     if (dx*dx+dy*dy > objspace_flatness_squared) {
10737         nk_tt__tesselate_curve(points, num_points, x0,y0,
10738             (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
10739         nk_tt__tesselate_curve(points, num_points, mx,my,
10740             (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
10741     } else {
10742         nk_tt__add_point(points, *num_points,x2,y2);
10743         *num_points = *num_points+1;
10744     }
10745     return 1;
10746 }
10747 
10748 /* returns number of contours */
10749 NK_INTERN struct nk_tt__point*
10750 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
10751     float objspace_flatness, int **contour_lengths, int *num_contours,
10752     struct nk_allocator *alloc)
10753 {
10754     struct nk_tt__point *points=0;
10755     int num_points=0;
10756     float objspace_flatness_squared = objspace_flatness * objspace_flatness;
10757     int i;
10758     int n=0;
10759     int start=0;
10760     int pass;
10761 
10762     /* count how many "moves" there are to get the contour count */
10763     for (i=0; i < num_verts; ++i)
10764         if (vertices[i].type == NK_TT_vmove) ++n;
10765 
10766     *num_contours = n;
10767     if (n == 0) return 0;
10768 
10769     *contour_lengths = (int *)
10770         alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
10771     if (*contour_lengths == 0) {
10772         *num_contours = 0;
10773         return 0;
10774     }
10775 
10776     /* make two passes through the points so we don't need to realloc */
10777     for (pass=0; pass < 2; ++pass)
10778     {
10779         float x=0,y=0;
10780         if (pass == 1) {
10781             points = (struct nk_tt__point *)
10782                 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
10783             if (points == 0) goto error;
10784         }
10785         num_points = 0;
10786         n= -1;
10787 
10788         for (i=0; i < num_verts; ++i)
10789         {
10790             switch (vertices[i].type) {
10791             case NK_TT_vmove:
10792                 /* start the next contour */
10793                 if (n >= 0)
10794                 (*contour_lengths)[n] = num_points - start;
10795                 ++n;
10796                 start = num_points;
10797 
10798                 x = vertices[i].x, y = vertices[i].y;
10799                 nk_tt__add_point(points, num_points++, x,y);
10800                 break;
10801             case NK_TT_vline:
10802                x = vertices[i].x, y = vertices[i].y;
10803                nk_tt__add_point(points, num_points++, x, y);
10804                break;
10805             case NK_TT_vcurve:
10806                nk_tt__tesselate_curve(points, &num_points, x,y,
10807                                         vertices[i].cx, vertices[i].cy,
10808                                         vertices[i].x,  vertices[i].y,
10809                                         objspace_flatness_squared, 0);
10810                x = vertices[i].x, y = vertices[i].y;
10811                break;
10812             default: break;
10813          }
10814       }
10815       (*contour_lengths)[n] = num_points - start;
10816    }
10817    return points;
10818 
10819 error:
10820    alloc->free(alloc->userdata, points);
10821    alloc->free(alloc->userdata, *contour_lengths);
10822    *contour_lengths = 0;
10823    *num_contours = 0;
10824    return 0;
10825 }
10826 
10827 NK_INTERN void
10828 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
10829     struct nk_tt_vertex *vertices, int num_verts,
10830     float scale_x, float scale_y, float shift_x, float shift_y,
10831     int x_off, int y_off, int invert, struct nk_allocator *alloc)
10832 {
10833     float scale = scale_x > scale_y ? scale_y : scale_x;
10834     int winding_count, *winding_lengths;
10835     struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
10836         flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
10837 
10838     NK_ASSERT(alloc);
10839     if (windings) {
10840         nk_tt__rasterize(result, windings, winding_lengths, winding_count,
10841             scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
10842         alloc->free(alloc->userdata, winding_lengths);
10843         alloc->free(alloc->userdata, windings);
10844     }
10845 }
10846 
10847 NK_INTERN void
10848 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
10849     int out_w, int out_h, int out_stride, float scale_x, float scale_y,
10850     float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
10851 {
10852     int ix0,iy0;
10853     struct nk_tt_vertex *vertices;
10854     int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
10855     struct nk_tt__bitmap gbm;
10856 
10857     nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
10858         shift_y, &ix0,&iy0,0,0);
10859     gbm.pixels = output;
10860     gbm.w = out_w;
10861     gbm.h = out_h;
10862     gbm.stride = out_stride;
10863 
10864     if (gbm.w && gbm.h)
10865         nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
10866             shift_x, shift_y, ix0,iy0, 1, alloc);
10867     alloc->free(alloc->userdata, vertices);
10868 }
10869 
10870 /*-------------------------------------------------------------
10871  *                          Bitmap baking
10872  * --------------------------------------------------------------*/
10873 NK_INTERN int
10874 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
10875     int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
10876 {
10877     int num_nodes = pw - padding;
10878     struct nk_rp_context *context = (struct nk_rp_context *)
10879         alloc->alloc(alloc->userdata,0, sizeof(*context));
10880     struct nk_rp_node *nodes = (struct nk_rp_node*)
10881         alloc->alloc(alloc->userdata,0, (sizeof(*nodes  ) * (nk_size)num_nodes));
10882 
10883     if (context == 0 || nodes == 0) {
10884         if (context != 0) alloc->free(alloc->userdata, context);
10885         if (nodes   != 0) alloc->free(alloc->userdata, nodes);
10886         return 0;
10887     }
10888 
10889     spc->width = pw;
10890     spc->height = ph;
10891     spc->pixels = pixels;
10892     spc->pack_info = context;
10893     spc->nodes = nodes;
10894     spc->padding = padding;
10895     spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
10896     spc->h_oversample = 1;
10897     spc->v_oversample = 1;
10898 
10899     nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
10900     if (pixels)
10901         NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
10902     return 1;
10903 }
10904 
10905 NK_INTERN void
10906 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
10907 {
10908     alloc->free(alloc->userdata, spc->nodes);
10909     alloc->free(alloc->userdata, spc->pack_info);
10910 }
10911 
10912 NK_INTERN void
10913 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
10914     unsigned int h_oversample, unsigned int v_oversample)
10915 {
10916    NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
10917    NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
10918    if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
10919       spc->h_oversample = h_oversample;
10920    if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
10921       spc->v_oversample = v_oversample;
10922 }
10923 
10924 NK_INTERN void
10925 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10926     int kernel_width)
10927 {
10928     unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10929     int safe_w = w - kernel_width;
10930     int j;
10931 
10932     for (j=0; j < h; ++j)
10933     {
10934         int i;
10935         unsigned int total;
10936         NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10937 
10938         total = 0;
10939 
10940         /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10941         switch (kernel_width) {
10942         case 2:
10943             for (i=0; i <= safe_w; ++i) {
10944                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10945                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10946                 pixels[i] = (unsigned char) (total / 2);
10947             }
10948             break;
10949         case 3:
10950             for (i=0; i <= safe_w; ++i) {
10951                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10952                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10953                 pixels[i] = (unsigned char) (total / 3);
10954             }
10955             break;
10956         case 4:
10957             for (i=0; i <= safe_w; ++i) {
10958                 total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
10959                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10960                 pixels[i] = (unsigned char) (total / 4);
10961             }
10962             break;
10963         case 5:
10964             for (i=0; i <= safe_w; ++i) {
10965                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10966                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10967                 pixels[i] = (unsigned char) (total / 5);
10968             }
10969             break;
10970         default:
10971             for (i=0; i <= safe_w; ++i) {
10972                 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10973                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10974                 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10975             }
10976             break;
10977         }
10978 
10979         for (; i < w; ++i) {
10980             NK_ASSERT(pixels[i] == 0);
10981             total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
10982             pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10983         }
10984         pixels += stride_in_bytes;
10985     }
10986 }
10987 
10988 NK_INTERN void
10989 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10990     int kernel_width)
10991 {
10992     unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10993     int safe_h = h - kernel_width;
10994     int j;
10995 
10996     for (j=0; j < w; ++j)
10997     {
10998         int i;
10999         unsigned int total;
11000         NK_MEMSET(buffer, 0, (nk_size)kernel_width);
11001 
11002         total = 0;
11003 
11004         /* make kernel_width a constant in common cases so compiler can optimize out the divide */
11005         switch (kernel_width) {
11006         case 2:
11007             for (i=0; i <= safe_h; ++i) {
11008                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11009                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11010                 pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
11011             }
11012             break;
11013          case 3:
11014             for (i=0; i <= safe_h; ++i) {
11015                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11016                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11017                 pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
11018             }
11019             break;
11020          case 4:
11021             for (i=0; i <= safe_h; ++i) {
11022                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11023                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11024                 pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
11025             }
11026             break;
11027          case 5:
11028             for (i=0; i <= safe_h; ++i) {
11029                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11030                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11031                 pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
11032             }
11033             break;
11034          default:
11035             for (i=0; i <= safe_h; ++i) {
11036                 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11037                 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11038                 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
11039             }
11040             break;
11041         }
11042 
11043         for (; i < h; ++i) {
11044             NK_ASSERT(pixels[i*stride_in_bytes] == 0);
11045             total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
11046             pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
11047         }
11048         pixels += 1;
11049     }
11050 }
11051 
11052 NK_INTERN float
11053 nk_tt__oversample_shift(int oversample)
11054 {
11055     if (!oversample)
11056         return 0.0f;
11057 
11058     /* The prefilter is a box filter of width "oversample", */
11059     /* which shifts phase by (oversample - 1)/2 pixels in */
11060     /* oversampled space. We want to shift in the opposite */
11061     /* direction to counter this. */
11062     return (float)-(oversample - 1) / (2.0f * (float)oversample);
11063 }
11064 
11065 /* rects array must be big enough to accommodate all characters in the given ranges */
11066 NK_INTERN int
11067 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
11068     struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
11069     int num_ranges, struct nk_rp_rect *rects)
11070 {
11071     int i,j,k;
11072     k = 0;
11073 
11074     for (i=0; i < num_ranges; ++i) {
11075         float fh = ranges[i].font_size;
11076         float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
11077             nk_tt_ScaleForMappingEmToPixels(info, -fh);
11078         ranges[i].h_oversample = (unsigned char) spc->h_oversample;
11079         ranges[i].v_oversample = (unsigned char) spc->v_oversample;
11080         for (j=0; j < ranges[i].num_chars; ++j) {
11081             int x0,y0,x1,y1;
11082             int codepoint = ranges[i].first_unicode_codepoint_in_range ?
11083                 ranges[i].first_unicode_codepoint_in_range + j :
11084                 ranges[i].array_of_unicode_codepoints[j];
11085 
11086             int glyph = nk_tt_FindGlyphIndex(info, codepoint);
11087             nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
11088                 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
11089             rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
11090             rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
11091             ++k;
11092         }
11093     }
11094     return k;
11095 }
11096 
11097 NK_INTERN int
11098 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
11099     struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
11100     int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
11101 {
11102     int i,j,k, return_value = 1;
11103     /* save current values */
11104     int old_h_over = (int)spc->h_oversample;
11105     int old_v_over = (int)spc->v_oversample;
11106     /* rects array must be big enough to accommodate all characters in the given ranges */
11107 
11108     k = 0;
11109     for (i=0; i < num_ranges; ++i)
11110     {
11111         float fh = ranges[i].font_size;
11112         float recip_h,recip_v,sub_x,sub_y;
11113         float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
11114             nk_tt_ScaleForMappingEmToPixels(info, -fh);
11115 
11116         spc->h_oversample = ranges[i].h_oversample;
11117         spc->v_oversample = ranges[i].v_oversample;
11118 
11119         recip_h = 1.0f / (float)spc->h_oversample;
11120         recip_v = 1.0f / (float)spc->v_oversample;
11121 
11122         sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
11123         sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
11124 
11125         for (j=0; j < ranges[i].num_chars; ++j)
11126         {
11127             struct nk_rp_rect *r = &rects[k];
11128             if (r->was_packed)
11129             {
11130                 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
11131                 int advance, lsb, x0,y0,x1,y1;
11132                 int codepoint = ranges[i].first_unicode_codepoint_in_range ?
11133                     ranges[i].first_unicode_codepoint_in_range + j :
11134                     ranges[i].array_of_unicode_codepoints[j];
11135                 int glyph = nk_tt_FindGlyphIndex(info, codepoint);
11136                 nk_rp_coord pad = (nk_rp_coord) spc->padding;
11137 
11138                 /* pad on left and top */
11139                 r->x = (nk_rp_coord)((int)r->x + (int)pad);
11140                 r->y = (nk_rp_coord)((int)r->y + (int)pad);
11141                 r->w = (nk_rp_coord)((int)r->w - (int)pad);
11142                 r->h = (nk_rp_coord)((int)r->h - (int)pad);
11143 
11144                 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
11145                 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
11146                         (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
11147                 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
11148                     (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
11149                     spc->stride_in_bytes, scale * (float)spc->h_oversample,
11150                     scale * (float)spc->v_oversample, 0,0, glyph, alloc);
11151 
11152                 if (spc->h_oversample > 1)
11153                    nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
11154                         r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
11155 
11156                 if (spc->v_oversample > 1)
11157                    nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
11158                         r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
11159 
11160                 bc->x0       = (nk_ushort)  r->x;
11161                 bc->y0       = (nk_ushort)  r->y;
11162                 bc->x1       = (nk_ushort) (r->x + r->w);
11163                 bc->y1       = (nk_ushort) (r->y + r->h);
11164                 bc->xadvance = scale * (float)advance;
11165                 bc->xoff     = (float)  x0 * recip_h + sub_x;
11166                 bc->yoff     = (float)  y0 * recip_v + sub_y;
11167                 bc->xoff2    = ((float)x0 + r->w) * recip_h + sub_x;
11168                 bc->yoff2    = ((float)y0 + r->h) * recip_v + sub_y;
11169             } else {
11170                 return_value = 0; /* if any fail, report failure */
11171             }
11172             ++k;
11173         }
11174     }
11175     /* restore original values */
11176     spc->h_oversample = (unsigned int)old_h_over;
11177     spc->v_oversample = (unsigned int)old_v_over;
11178     return return_value;
11179 }
11180 
11181 NK_INTERN void
11182 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
11183     int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
11184     int align_to_integer)
11185 {
11186     float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
11187     struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
11188     if (align_to_integer) {
11189         int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
11190         int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
11191 
11192         float x = (float)tx;
11193         float y = (float)ty;
11194 
11195         q->x0 = x;
11196         q->y0 = y;
11197         q->x1 = x + b->xoff2 - b->xoff;
11198         q->y1 = y + b->yoff2 - b->yoff;
11199     } else {
11200         q->x0 = *xpos + b->xoff;
11201         q->y0 = *ypos + b->yoff;
11202         q->x1 = *xpos + b->xoff2;
11203         q->y1 = *ypos + b->yoff2;
11204     }
11205     q->s0 = b->x0 * ipw;
11206     q->t0 = b->y0 * iph;
11207     q->s1 = b->x1 * ipw;
11208     q->t1 = b->y1 * iph;
11209     *xpos += b->xadvance;
11210 }
11211 
11212 /* -------------------------------------------------------------
11213  *
11214  *                          FONT BAKING
11215  *
11216  * --------------------------------------------------------------*/
11217 struct nk_font_bake_data {
11218     struct nk_tt_fontinfo info;
11219     struct nk_rp_rect *rects;
11220     struct nk_tt_pack_range *ranges;
11221     nk_rune range_count;
11222 };
11223 
11224 struct nk_font_baker {
11225     struct nk_allocator alloc;
11226     struct nk_tt_pack_context spc;
11227     struct nk_font_bake_data *build;
11228     struct nk_tt_packedchar *packed_chars;
11229     struct nk_rp_rect *rects;
11230     struct nk_tt_pack_range *ranges;
11231 };
11232 
11233 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
11234 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
11235 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
11236 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
11237 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
11238 
11239 NK_INTERN int
11240 nk_range_count(const nk_rune *range)
11241 {
11242     const nk_rune *iter = range;
11243     NK_ASSERT(range);
11244     if (!range) return 0;
11245     while (*(iter++) != 0);
11246     return (iter == range) ? 0 : (int)((iter - range)/2);
11247 }
11248 
11249 NK_INTERN int
11250 nk_range_glyph_count(const nk_rune *range, int count)
11251 {
11252     int i = 0;
11253     int total_glyphs = 0;
11254     for (i = 0; i < count; ++i) {
11255         int diff;
11256         nk_rune f = range[(i*2)+0];
11257         nk_rune t = range[(i*2)+1];
11258         NK_ASSERT(t >= f);
11259         diff = (int)((t - f) + 1);
11260         total_glyphs += diff;
11261     }
11262     return total_glyphs;
11263 }
11264 
11265 NK_API const nk_rune*
11266 nk_font_default_glyph_ranges(void)
11267 {
11268     NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
11269     return ranges;
11270 }
11271 
11272 NK_API const nk_rune*
11273 nk_font_chinese_glyph_ranges(void)
11274 {
11275     NK_STORAGE const nk_rune ranges[] = {
11276         0x0020, 0x00FF,
11277         0x3000, 0x30FF,
11278         0x31F0, 0x31FF,
11279         0xFF00, 0xFFEF,
11280         0x4e00, 0x9FAF,
11281         0
11282     };
11283     return ranges;
11284 }
11285 
11286 NK_API const nk_rune*
11287 nk_font_cyrillic_glyph_ranges(void)
11288 {
11289     NK_STORAGE const nk_rune ranges[] = {
11290         0x0020, 0x00FF,
11291         0x0400, 0x052F,
11292         0x2DE0, 0x2DFF,
11293         0xA640, 0xA69F,
11294         0
11295     };
11296     return ranges;
11297 }
11298 
11299 NK_API const nk_rune*
11300 nk_font_korean_glyph_ranges(void)
11301 {
11302     NK_STORAGE const nk_rune ranges[] = {
11303         0x0020, 0x00FF,
11304         0x3131, 0x3163,
11305         0xAC00, 0xD79D,
11306         0
11307     };
11308     return ranges;
11309 }
11310 
11311 NK_INTERN void
11312 nk_font_baker_memory(nk_size *temp, int *glyph_count,
11313     struct nk_font_config *config_list, int count)
11314 {
11315     int range_count = 0;
11316     int total_range_count = 0;
11317     struct nk_font_config *iter, *i;
11318 
11319     NK_ASSERT(config_list);
11320     NK_ASSERT(glyph_count);
11321     if (!config_list) {
11322         *temp = 0;
11323         *glyph_count = 0;
11324         return;
11325     }
11326     *glyph_count = 0;
11327     for (iter = config_list; iter; iter = iter->next) {
11328         i = iter;
11329         do {if (!i->range) iter->range = nk_font_default_glyph_ranges();
11330             range_count = nk_range_count(i->range);
11331             total_range_count += range_count;
11332             *glyph_count += nk_range_glyph_count(i->range, range_count);
11333         } while ((i = i->n) != iter);
11334     }
11335     *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
11336     *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
11337     *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
11338     *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
11339     *temp += sizeof(struct nk_font_baker);
11340     *temp += nk_rect_align + nk_range_align + nk_char_align;
11341     *temp += nk_build_align + nk_baker_align;
11342 }
11343 
11344 NK_INTERN struct nk_font_baker*
11345 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
11346 {
11347     struct nk_font_baker *baker;
11348     if (!memory) return 0;
11349     /* setup baker inside a memory block  */
11350     baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
11351     baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
11352     baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
11353     baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
11354     baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
11355     baker->alloc = *alloc;
11356     return baker;
11357 }
11358 
11359 NK_INTERN int
11360 nk_font_bake_pack(struct nk_font_baker *baker,
11361     nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
11362     const struct nk_font_config *config_list, int count,
11363     struct nk_allocator *alloc)
11364 {
11365     NK_STORAGE const nk_size max_height = 1024 * 32;
11366     const struct nk_font_config *config_iter, *it;
11367     int total_glyph_count = 0;
11368     int total_range_count = 0;
11369     int range_count = 0;
11370     int i = 0;
11371 
11372     NK_ASSERT(image_memory);
11373     NK_ASSERT(width);
11374     NK_ASSERT(height);
11375     NK_ASSERT(config_list);
11376     NK_ASSERT(count);
11377     NK_ASSERT(alloc);
11378 
11379     if (!image_memory || !width || !height || !config_list || !count) return nk_false;
11380     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11381         it = config_iter;
11382         do {range_count = nk_range_count(it->range);
11383             total_range_count += range_count;
11384             total_glyph_count += nk_range_glyph_count(it->range, range_count);
11385         } while ((it = it->n) != config_iter);
11386     }
11387     /* setup font baker from temporary memory */
11388     for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11389         it = config_iter;
11390         do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0))
11391             return nk_false;
11392         } while ((it = it->n) != config_iter);
11393     }
11394     *height = 0;
11395     *width = (total_glyph_count > 1000) ? 1024 : 512;
11396     nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
11397     {
11398         int input_i = 0;
11399         int range_n = 0;
11400         int rect_n = 0;
11401         int char_n = 0;
11402 
11403         if (custom) {
11404             /* pack custom user data first so it will be in the upper left corner*/
11405             struct nk_rp_rect custom_space;
11406             nk_zero(&custom_space, sizeof(custom_space));
11407             custom_space.w = (nk_rp_coord)((custom->w * 2) + 1);
11408             custom_space.h = (nk_rp_coord)(custom->h + 1);
11409 
11410             nk_tt_PackSetOversampling(&baker->spc, 1, 1);
11411             nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
11412             *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
11413 
11414             custom->x = (short)custom_space.x;
11415             custom->y = (short)custom_space.y;
11416             custom->w = (short)custom_space.w;
11417             custom->h = (short)custom_space.h;
11418         }
11419 
11420         /* first font pass: pack all glyphs */
11421         for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
11422             config_iter = config_iter->next) {
11423             it = config_iter;
11424             do {int n = 0;
11425                 int glyph_count;
11426                 const nk_rune *in_range;
11427                 const struct nk_font_config *cfg = it;
11428                 struct nk_font_bake_data *tmp = &baker->build[input_i++];
11429 
11430                 /* count glyphs + ranges in current font */
11431                 glyph_count = 0; range_count = 0;
11432                 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
11433                     glyph_count += (int)(in_range[1] - in_range[0]) + 1;
11434                     range_count++;
11435                 }
11436 
11437                 /* setup ranges  */
11438                 tmp->ranges = baker->ranges + range_n;
11439                 tmp->range_count = (nk_rune)range_count;
11440                 range_n += range_count;
11441                 for (i = 0; i < range_count; ++i) {
11442                     in_range = &cfg->range[i * 2];
11443                     tmp->ranges[i].font_size = cfg->size;
11444                     tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
11445                     tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
11446                     tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
11447                     char_n += tmp->ranges[i].num_chars;
11448                 }
11449 
11450                 /* pack */
11451                 tmp->rects = baker->rects + rect_n;
11452                 rect_n += glyph_count;
11453                 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11454                 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
11455                     tmp->ranges, (int)tmp->range_count, tmp->rects);
11456                 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
11457 
11458                 /* texture height */
11459                 for (i = 0; i < n; ++i) {
11460                     if (tmp->rects[i].was_packed)
11461                         *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
11462                 }
11463             } while ((it = it->n) != config_iter);
11464         }
11465         NK_ASSERT(rect_n == total_glyph_count);
11466         NK_ASSERT(char_n == total_glyph_count);
11467         NK_ASSERT(range_n == total_range_count);
11468     }
11469     *height = (int)nk_round_up_pow2((nk_uint)*height);
11470     *image_memory = (nk_size)(*width) * (nk_size)(*height);
11471     return nk_true;
11472 }
11473 
11474 NK_INTERN void
11475 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
11476     struct nk_font_glyph *glyphs, int glyphs_count,
11477     const struct nk_font_config *config_list, int font_count)
11478 {
11479     int input_i = 0;
11480     nk_rune glyph_n = 0;
11481     const struct nk_font_config *config_iter;
11482     const struct nk_font_config *it;
11483 
11484     NK_ASSERT(image_memory);
11485     NK_ASSERT(width);
11486     NK_ASSERT(height);
11487     NK_ASSERT(config_list);
11488     NK_ASSERT(baker);
11489     NK_ASSERT(font_count);
11490     NK_ASSERT(glyphs_count);
11491     if (!image_memory || !width || !height || !config_list ||
11492         !font_count || !glyphs || !glyphs_count)
11493         return;
11494 
11495     /* second font pass: render glyphs */
11496     nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
11497     baker->spc.pixels = (unsigned char*)image_memory;
11498     baker->spc.height = (int)height;
11499     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11500         config_iter = config_iter->next) {
11501         it = config_iter;
11502         do {const struct nk_font_config *cfg = it;
11503             struct nk_font_bake_data *tmp = &baker->build[input_i++];
11504             nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11505             nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
11506                 (int)tmp->range_count, tmp->rects, &baker->alloc);
11507         } while ((it = it->n) != config_iter);
11508     } nk_tt_PackEnd(&baker->spc, &baker->alloc);
11509 
11510     /* third pass: setup font and glyphs */
11511     for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11512         config_iter = config_iter->next) {
11513         it = config_iter;
11514         do {nk_size i = 0;
11515             int char_idx = 0;
11516             nk_rune glyph_count = 0;
11517             const struct nk_font_config *cfg = it;
11518             struct nk_font_bake_data *tmp = &baker->build[input_i++];
11519             struct nk_baked_font *dst_font = cfg->font;
11520 
11521             float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
11522             int unscaled_ascent, unscaled_descent, unscaled_line_gap;
11523             nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
11524                                     &unscaled_line_gap);
11525 
11526             /* fill baked font */
11527             if (!cfg->merge_mode) {
11528                 dst_font->ranges = cfg->range;
11529                 dst_font->height = cfg->size;
11530                 dst_font->ascent = ((float)unscaled_ascent * font_scale);
11531                 dst_font->descent = ((float)unscaled_descent * font_scale);
11532                 dst_font->glyph_offset = glyph_n;
11533             }
11534 
11535             /* fill own baked font glyph array */
11536             for (i = 0; i < tmp->range_count; ++i) {
11537                 struct nk_tt_pack_range *range = &tmp->ranges[i];
11538                 for (char_idx = 0; char_idx < range->num_chars; char_idx++)
11539                 {
11540                     nk_rune codepoint = 0;
11541                     float dummy_x = 0, dummy_y = 0;
11542                     struct nk_tt_aligned_quad q;
11543                     struct nk_font_glyph *glyph;
11544 
11545                     /* query glyph bounds from stb_truetype */
11546                     const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
11547                     if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
11548                     codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
11549                     nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
11550                         (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
11551 
11552                     /* fill own glyph type with data */
11553                     glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count];
11554                     glyph->codepoint = codepoint;
11555                     glyph->x0 = q.x0; glyph->y0 = q.y0;
11556                     glyph->x1 = q.x1; glyph->y1 = q.y1;
11557                     glyph->y0 += (dst_font->ascent + 0.5f);
11558                     glyph->y1 += (dst_font->ascent + 0.5f);
11559                     glyph->w = glyph->x1 - glyph->x0 + 0.5f;
11560                     glyph->h = glyph->y1 - glyph->y0;
11561 
11562                     if (cfg->coord_type == NK_COORD_PIXEL) {
11563                         glyph->u0 = q.s0 * (float)width;
11564                         glyph->v0 = q.t0 * (float)height;
11565                         glyph->u1 = q.s1 * (float)width;
11566                         glyph->v1 = q.t1 * (float)height;
11567                     } else {
11568                         glyph->u0 = q.s0;
11569                         glyph->v0 = q.t0;
11570                         glyph->u1 = q.s1;
11571                         glyph->v1 = q.t1;
11572                     }
11573                     glyph->xadvance = (pc->xadvance + cfg->spacing.x);
11574                     if (cfg->pixel_snap)
11575                         glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
11576                     glyph_count++;
11577                 }
11578             }
11579             dst_font->glyph_count += glyph_count;
11580             glyph_n += glyph_count;
11581         } while ((it = it->n) != config_iter);
11582     }
11583 }
11584 
11585 NK_INTERN void
11586 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
11587     struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
11588     int tex_height, char white, char black)
11589 {
11590     nk_byte *pixels;
11591     int y = 0;
11592     int x = 0;
11593     int n = 0;
11594 
11595     NK_ASSERT(img_memory);
11596     NK_ASSERT(img_width);
11597     NK_ASSERT(img_height);
11598     NK_ASSERT(texture_data_mask);
11599     NK_UNUSED(tex_height);
11600     if (!img_memory || !img_width || !img_height || !texture_data_mask)
11601         return;
11602 
11603     pixels = (nk_byte*)img_memory;
11604     for (y = 0, n = 0; y < tex_height; ++y) {
11605         for (x = 0; x < tex_width; ++x, ++n) {
11606             const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
11607             const int off1 = off0 + 1 + tex_width;
11608             pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
11609             pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
11610         }
11611     }
11612 }
11613 
11614 NK_INTERN void
11615 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
11616     const void *in_memory)
11617 {
11618     int n = 0;
11619     nk_rune *dst;
11620     const nk_byte *src;
11621 
11622     NK_ASSERT(out_memory);
11623     NK_ASSERT(in_memory);
11624     NK_ASSERT(img_width);
11625     NK_ASSERT(img_height);
11626     if (!out_memory || !in_memory || !img_height || !img_width) return;
11627 
11628     dst = (nk_rune*)out_memory;
11629     src = (const nk_byte*)in_memory;
11630     for (n = (int)(img_width * img_height); n > 0; n--)
11631         *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
11632 }
11633 
11634 /* -------------------------------------------------------------
11635  *
11636  *                          FONT
11637  *
11638  * --------------------------------------------------------------*/
11639 NK_INTERN float
11640 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
11641 {
11642     nk_rune unicode;
11643     int text_len  = 0;
11644     float text_width = 0;
11645     int glyph_len = 0;
11646     float scale = 0;
11647 
11648     struct nk_font *font = (struct nk_font*)handle.ptr;
11649     NK_ASSERT(font);
11650     NK_ASSERT(font->glyphs);
11651     if (!font || !text || !len)
11652         return 0;
11653 
11654     scale = height/font->info.height;
11655     glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
11656     if (!glyph_len) return 0;
11657     while (text_len <= (int)len && glyph_len) {
11658         const struct nk_font_glyph *g;
11659         if (unicode == NK_UTF_INVALID) break;
11660 
11661         /* query currently drawn glyph information */
11662         g = nk_font_find_glyph(font, unicode);
11663         text_width += g->xadvance * scale;
11664 
11665         /* offset next glyph */
11666         glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
11667         text_len += glyph_len;
11668     }
11669     return text_width;
11670 }
11671 
11672 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11673 NK_INTERN void
11674 nk_font_query_font_glyph(nk_handle handle, float height,
11675     struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
11676 {
11677     float scale;
11678     const struct nk_font_glyph *g;
11679     struct nk_font *font;
11680 
11681     NK_ASSERT(glyph);
11682     NK_UNUSED(next_codepoint);
11683 
11684     font = (struct nk_font*)handle.ptr;
11685     NK_ASSERT(font);
11686     NK_ASSERT(font->glyphs);
11687     if (!font || !glyph)
11688         return;
11689 
11690     scale = height/font->info.height;
11691     g = nk_font_find_glyph(font, codepoint);
11692     glyph->width = (g->x1 - g->x0) * scale;
11693     glyph->height = (g->y1 - g->y0) * scale;
11694     glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
11695     glyph->xadvance = (g->xadvance * scale);
11696     glyph->uv[0] = nk_vec2(g->u0, g->v0);
11697     glyph->uv[1] = nk_vec2(g->u1, g->v1);
11698 }
11699 #endif
11700 
11701 NK_API const struct nk_font_glyph*
11702 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
11703 {
11704     int i = 0;
11705     int count;
11706     int total_glyphs = 0;
11707     const struct nk_font_glyph *glyph = 0;
11708     const struct nk_font_config *iter = 0;
11709 
11710     NK_ASSERT(font);
11711     NK_ASSERT(font->glyphs);
11712     NK_ASSERT(font->info.ranges);
11713     if (!font || !font->glyphs) return 0;
11714 
11715     glyph = font->fallback;
11716     iter = font->config;
11717     do {count = nk_range_count(iter->range);
11718         for (i = 0; i < count; ++i) {
11719             nk_rune f = iter->range[(i*2)+0];
11720             nk_rune t = iter->range[(i*2)+1];
11721             int diff = (int)((t - f) + 1);
11722             if (unicode >= f && unicode <= t)
11723                 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
11724             total_glyphs += diff;
11725         }
11726     } while ((iter = iter->n) != font->config);
11727     return glyph;
11728 }
11729 
11730 NK_INTERN void
11731 nk_font_init(struct nk_font *font, float pixel_height,
11732     nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
11733     const struct nk_baked_font *baked_font, nk_handle atlas)
11734 {
11735     struct nk_baked_font baked;
11736     NK_ASSERT(font);
11737     NK_ASSERT(glyphs);
11738     NK_ASSERT(baked_font);
11739     if (!font || !glyphs || !baked_font)
11740         return;
11741 
11742     baked = *baked_font;
11743     font->fallback = 0;
11744     font->info = baked;
11745     font->scale = (float)pixel_height / (float)font->info.height;
11746     font->glyphs = &glyphs[baked_font->glyph_offset];
11747     font->texture = atlas;
11748     font->fallback_codepoint = fallback_codepoint;
11749     font->fallback = nk_font_find_glyph(font, fallback_codepoint);
11750 
11751     font->handle.height = font->info.height * font->scale;
11752     font->handle.width = nk_font_text_width;
11753     font->handle.userdata.ptr = font;
11754 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11755     font->handle.query = nk_font_query_font_glyph;
11756     font->handle.texture = font->texture;
11757 #endif
11758 }
11759 
11760 /* ---------------------------------------------------------------------------
11761  *
11762  *                          DEFAULT FONT
11763  *
11764  * ProggyClean.ttf
11765  * Copyright (c) 2004, 2005 Tristan Grimmer
11766  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
11767  * Download and more information at http://upperbounds.net
11768  *-----------------------------------------------------------------------------*/
11769 #ifdef NK_INCLUDE_DEFAULT_FONT
11770 
11771  #ifdef __clang__
11772 #pragma clang diagnostic push
11773 
11774 #pragma clang diagnostic ignored "-Woverlength-strings"
11775 #elif defined(__GNUC__) || defined(__GNUG__)
11776 #pragma GCC diagnostic push
11777 #pragma GCC diagnostic ignored "-Woverlength-strings"
11778 #endif
11779 
11780 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
11781     "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
11782     "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#"
11783     "`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"
11784     "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"
11785     "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"
11786     "*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)"
11787     "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"
11788     "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."
11789     "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"
11790     "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(,)"
11791     "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#"
11792     "'/###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"
11793     "_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"
11794     "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/"
11795     "/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"
11796     "%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&#"
11797     "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)("
11798     "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"
11799     "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"
11800     "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^-"
11801     "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-"
11802     "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"
11803     "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%"
11804     "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]"
11805     "%(?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"
11806     "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:"
11807     "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("
11808     "$/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<"
11809     "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'?"
11810     "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/;"
11811     ")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"
11812     "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("
11813     "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"
11814     "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
11815     "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<-"
11816     "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"
11817     "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"
11818     ".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@@"
11819     "$&)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*"
11820     "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"
11821     "@-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&#"
11822     "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#"
11823     "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"
11824     "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"
11825     "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&#"
11826     "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"
11827     ":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+"
11828     "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*"
11829     "$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"
11830     ":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"
11831     "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"
11832     "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"
11833     "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"
11834     ":^#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@&]>"
11835     "_>@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%"
11836     "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;"
11837     "^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:"
11838     "+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%"
11839     "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-"
11840     "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*"
11841     "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"
11842     "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
11843     "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`"
11844     "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]%/"
11845     "+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"
11846     "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"
11847     "?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"
11848     "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"
11849     ">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'>"
11850     "[%$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"
11851     "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#"
11852     "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$"
11853     "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,)"
11854     "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"
11855     "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"
11856     "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"
11857     "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(#"
11858     ";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&>"
11859     "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#"
11860     "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"
11861     "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#"
11862     "/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-#"
11863     "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#"
11864     "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
11865     "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
11866     "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
11867 #endif /* NK_INCLUDE_DEFAULT_FONT */
11868 
11869 #define NK_CURSOR_DATA_W 90
11870 #define NK_CURSOR_DATA_H 27
11871 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
11872 {
11873     "..-         -XXXXXXX-    X    -           X           -XXXXXXX          -          XXXXXXX"
11874     "..-         -X.....X-   X.X   -          X.X          -X.....X          -          X.....X"
11875     "---         -XXX.XXX-  X...X  -         X...X         -X....X           -           X....X"
11876     "X           -  X.X  - X.....X -        X.....X        -X...X            -            X...X"
11877     "XX          -  X.X  -X.......X-       X.......X       -X..X.X           -           X.X..X"
11878     "X.X         -  X.X  -XXXX.XXXX-       XXXX.XXXX       -X.X X.X          -          X.X X.X"
11879     "X..X        -  X.X  -   X.X   -          X.X          -XX   X.X         -         X.X   XX"
11880     "X...X       -  X.X  -   X.X   -    XX    X.X    XX    -      X.X        -        X.X      "
11881     "X....X      -  X.X  -   X.X   -   X.X    X.X    X.X   -       X.X       -       X.X       "
11882     "X.....X     -  X.X  -   X.X   -  X..X    X.X    X..X  -        X.X      -      X.X        "
11883     "X......X    -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -         X.X   XX-XX   X.X         "
11884     "X.......X   -  X.X  -   X.X   -X.....................X-          X.X X.X-X.X X.X          "
11885     "X........X  -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -           X.X..X-X..X.X           "
11886     "X.........X -XXX.XXX-   X.X   -  X..X    X.X    X..X  -            X...X-X...X            "
11887     "X..........X-X.....X-   X.X   -   X.X    X.X    X.X   -           X....X-X....X           "
11888     "X......XXXXX-XXXXXXX-   X.X   -    XX    X.X    XX    -          X.....X-X.....X          "
11889     "X...X..X    ---------   X.X   -          X.X          -          XXXXXXX-XXXXXXX          "
11890     "X..X X..X   -       -XXXX.XXXX-       XXXX.XXXX       ------------------------------------"
11891     "X.X  X..X   -       -X.......X-       X.......X       -    XX           XX    -           "
11892     "XX    X..X  -       - X.....X -        X.....X        -   X.X           X.X   -           "
11893     "      X..X          -  X...X  -         X...X         -  X..X           X..X  -           "
11894     "       XX           -   X.X   -          X.X          - X...XXXXXXXXXXXXX...X -           "
11895     "------------        -    X    -           X           -X.....................X-           "
11896     "                    ----------------------------------- X...XXXXXXXXXXXXX...X -           "
11897     "                                                      -  X..X           X..X  -           "
11898     "                                                      -   X.X           X.X   -           "
11899     "                                                      -    XX           XX    -           "
11900 };
11901 
11902 #ifdef __clang__
11903 #pragma clang diagnostic pop
11904 #elif defined(__GNUC__) || defined(__GNUG__)
11905 #pragma GCC diagnostic pop
11906 #endif
11907 
11908 NK_INTERN unsigned int
11909 nk_decompress_length(unsigned char *input)
11910 {
11911     return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
11912 }
11913 
11914 NK_GLOBAL unsigned char *nk__barrier;
11915 NK_GLOBAL unsigned char *nk__barrier2;
11916 NK_GLOBAL unsigned char *nk__barrier3;
11917 NK_GLOBAL unsigned char *nk__barrier4;
11918 NK_GLOBAL unsigned char *nk__dout;
11919 
11920 NK_INTERN void
11921 nk__match(unsigned char *data, unsigned int length)
11922 {
11923     /* INVERSE of memmove... write each byte before copying the next...*/
11924     NK_ASSERT (nk__dout + length <= nk__barrier);
11925     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11926     if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
11927     while (length--) *nk__dout++ = *data++;
11928 }
11929 
11930 NK_INTERN void
11931 nk__lit(unsigned char *data, unsigned int length)
11932 {
11933     NK_ASSERT (nk__dout + length <= nk__barrier);
11934     if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11935     if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
11936     NK_MEMCPY(nk__dout, data, length);
11937     nk__dout += length;
11938 }
11939 
11940 #define nk__in2(x)   ((i[x] << 8) + i[(x)+1])
11941 #define nk__in3(x)   ((i[x] << 16) + nk__in2((x)+1))
11942 #define nk__in4(x)   ((i[x] << 24) + nk__in3((x)+1))
11943 
11944 NK_INTERN unsigned char*
11945 nk_decompress_token(unsigned char *i)
11946 {
11947     if (*i >= 0x20) { /* use fewer if's for cases that expand small */
11948         if (*i >= 0x80)       nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
11949         else if (*i >= 0x40)  nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
11950         else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
11951     } else { /* more ifs for cases that expand large, since overhead is amortized */
11952         if (*i >= 0x18)       nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
11953         else if (*i >= 0x10)  nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
11954         else if (*i >= 0x08)  nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
11955         else if (*i == 0x07)  nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
11956         else if (*i == 0x06)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
11957         else if (*i == 0x04)  nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
11958     }
11959     return i;
11960 }
11961 
11962 NK_INTERN unsigned int
11963 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
11964 {
11965     const unsigned long ADLER_MOD = 65521;
11966     unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
11967     unsigned long blocklen, i;
11968 
11969     blocklen = buflen % 5552;
11970     while (buflen) {
11971         for (i=0; i + 7 < blocklen; i += 8) {
11972             s1 += buffer[0]; s2 += s1;
11973             s1 += buffer[1]; s2 += s1;
11974             s1 += buffer[2]; s2 += s1;
11975             s1 += buffer[3]; s2 += s1;
11976             s1 += buffer[4]; s2 += s1;
11977             s1 += buffer[5]; s2 += s1;
11978             s1 += buffer[6]; s2 += s1;
11979             s1 += buffer[7]; s2 += s1;
11980             buffer += 8;
11981         }
11982         for (; i < blocklen; ++i) {
11983             s1 += *buffer++; s2 += s1;
11984         }
11985 
11986         s1 %= ADLER_MOD; s2 %= ADLER_MOD;
11987         buflen -= (unsigned int)blocklen;
11988         blocklen = 5552;
11989     }
11990     return (unsigned int)(s2 << 16) + (unsigned int)s1;
11991 }
11992 
11993 NK_INTERN unsigned int
11994 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
11995 {
11996     unsigned int olen;
11997     if (nk__in4(0) != 0x57bC0000) return 0;
11998     if (nk__in4(4) != 0)          return 0; /* error! stream is > 4GB */
11999     olen = nk_decompress_length(i);
12000     nk__barrier2 = i;
12001     nk__barrier3 = i+length;
12002     nk__barrier = output + olen;
12003     nk__barrier4 = output;
12004     i += 16;
12005 
12006     nk__dout = output;
12007     for (;;) {
12008         unsigned char *old_i = i;
12009         i = nk_decompress_token(i);
12010         if (i == old_i) {
12011             if (*i == 0x05 && i[1] == 0xfa) {
12012                 NK_ASSERT(nk__dout == output + olen);
12013                 if (nk__dout != output + olen) return 0;
12014                 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
12015                     return 0;
12016                 return olen;
12017             } else {
12018                 NK_ASSERT(0); /* NOTREACHED */
12019                 return 0;
12020             }
12021         }
12022         NK_ASSERT(nk__dout <= output + olen);
12023         if (nk__dout > output + olen)
12024             return 0;
12025     }
12026 }
12027 
12028 NK_INTERN unsigned int
12029 nk_decode_85_byte(char c)
12030 { return (unsigned int)((c >= '\\') ? c-36 : c-35); }
12031 
12032 NK_INTERN void
12033 nk_decode_85(unsigned char* dst, const unsigned char* src)
12034 {
12035     while (*src)
12036     {
12037         unsigned int tmp =
12038             nk_decode_85_byte((char)src[0]) +
12039             85 * (nk_decode_85_byte((char)src[1]) +
12040             85 * (nk_decode_85_byte((char)src[2]) +
12041             85 * (nk_decode_85_byte((char)src[3]) +
12042             85 * nk_decode_85_byte((char)src[4]))));
12043 
12044         /* we can't assume little-endianess. */
12045         dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
12046         dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
12047         dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
12048         dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
12049 
12050         src += 5;
12051         dst += 4;
12052     }
12053 }
12054 
12055 /* -------------------------------------------------------------
12056  *
12057  *                          FONT ATLAS
12058  *
12059  * --------------------------------------------------------------*/
12060 NK_API struct nk_font_config
12061 nk_font_config(float pixel_height)
12062 {
12063     struct nk_font_config cfg;
12064     nk_zero_struct(cfg);
12065     cfg.ttf_blob = 0;
12066     cfg.ttf_size = 0;
12067     cfg.ttf_data_owned_by_atlas = 0;
12068     cfg.size = pixel_height;
12069     cfg.oversample_h = 3;
12070     cfg.oversample_v = 1;
12071     cfg.pixel_snap = 0;
12072     cfg.coord_type = NK_COORD_UV;
12073     cfg.spacing = nk_vec2(0,0);
12074     cfg.range = nk_font_default_glyph_ranges();
12075     cfg.merge_mode = 0;
12076     cfg.fallback_glyph = '?';
12077     cfg.font = 0;
12078     cfg.n = 0;
12079     return cfg;
12080 }
12081 
12082 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
12083 NK_API void
12084 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
12085 {
12086     NK_ASSERT(atlas);
12087     if (!atlas) return;
12088     nk_zero_struct(*atlas);
12089     atlas->temporary.userdata.ptr = 0;
12090     atlas->temporary.alloc = nk_malloc;
12091     atlas->temporary.free = nk_mfree;
12092     atlas->permanent.userdata.ptr = 0;
12093     atlas->permanent.alloc = nk_malloc;
12094     atlas->permanent.free = nk_mfree;
12095 }
12096 #endif
12097 
12098 NK_API void
12099 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
12100 {
12101     NK_ASSERT(atlas);
12102     NK_ASSERT(alloc);
12103     if (!atlas || !alloc) return;
12104     nk_zero_struct(*atlas);
12105     atlas->permanent = *alloc;
12106     atlas->temporary = *alloc;
12107 }
12108 
12109 NK_API void
12110 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
12111     struct nk_allocator *permanent, struct nk_allocator *temporary)
12112 {
12113     NK_ASSERT(atlas);
12114     NK_ASSERT(permanent);
12115     NK_ASSERT(temporary);
12116     if (!atlas || !permanent || !temporary) return;
12117     nk_zero_struct(*atlas);
12118     atlas->permanent = *permanent;
12119     atlas->temporary = *temporary;
12120 }
12121 
12122 NK_API void
12123 nk_font_atlas_begin(struct nk_font_atlas *atlas)
12124 {
12125     NK_ASSERT(atlas);
12126     NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
12127     NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
12128     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
12129         !atlas->temporary.alloc || !atlas->temporary.free) return;
12130     if (atlas->glyphs) {
12131         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12132         atlas->glyphs = 0;
12133     }
12134     if (atlas->pixel) {
12135         atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
12136         atlas->pixel = 0;
12137     }
12138 }
12139 
12140 NK_API struct nk_font*
12141 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
12142 {
12143     struct nk_font *font = 0;
12144     struct nk_font_config *cfg;
12145 
12146     NK_ASSERT(atlas);
12147     NK_ASSERT(atlas->permanent.alloc);
12148     NK_ASSERT(atlas->permanent.free);
12149     NK_ASSERT(atlas->temporary.alloc);
12150     NK_ASSERT(atlas->temporary.free);
12151 
12152     NK_ASSERT(config);
12153     NK_ASSERT(config->ttf_blob);
12154     NK_ASSERT(config->ttf_size);
12155     NK_ASSERT(config->size > 0.0f);
12156 
12157     if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
12158         !atlas->permanent.alloc || !atlas->permanent.free ||
12159         !atlas->temporary.alloc || !atlas->temporary.free)
12160         return 0;
12161 
12162     /* allocate font config  */
12163     cfg = (struct nk_font_config*)
12164         atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
12165     NK_MEMCPY(cfg, config, sizeof(*config));
12166     cfg->n = cfg;
12167     cfg->p = cfg;
12168 
12169     if (!config->merge_mode) {
12170         /* insert font config into list */
12171         if (!atlas->config) {
12172             atlas->config = cfg;
12173             cfg->next = 0;
12174         } else {
12175             struct nk_font_config *i = atlas->config;
12176             while (i->next) i = i->next;
12177             i->next = cfg;
12178             cfg->next = 0;
12179         }
12180         /* allocate new font */
12181         font = (struct nk_font*)
12182             atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
12183         NK_ASSERT(font);
12184         nk_zero(font, sizeof(*font));
12185         if (!font) return 0;
12186         font->config = cfg;
12187 
12188         /* insert font into list */
12189         if (!atlas->fonts) {
12190             atlas->fonts = font;
12191             font->next = 0;
12192         } else {
12193             struct nk_font *i = atlas->fonts;
12194             while (i->next) i = i->next;
12195             i->next = font;
12196             font->next = 0;
12197         }
12198         cfg->font = &font->info;
12199     } else {
12200         /* extend previously added font */
12201         struct nk_font *f = 0;
12202         struct nk_font_config *c = 0;
12203         NK_ASSERT(atlas->font_num);
12204         f = atlas->fonts;
12205         c = f->config;
12206         cfg->font = &f->info;
12207 
12208         cfg->n = c;
12209         cfg->p = c->p;
12210         c->p->n = cfg;
12211         c->p = cfg;
12212     }
12213     /* create own copy of .TTF font blob */
12214     if (!config->ttf_data_owned_by_atlas) {
12215         cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
12216         NK_ASSERT(cfg->ttf_blob);
12217         if (!cfg->ttf_blob) {
12218             atlas->font_num++;
12219             return 0;
12220         }
12221         NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
12222         cfg->ttf_data_owned_by_atlas = 1;
12223     }
12224     atlas->font_num++;
12225     return font;
12226 }
12227 
12228 NK_API struct nk_font*
12229 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
12230     nk_size size, float height, const struct nk_font_config *config)
12231 {
12232     struct nk_font_config cfg;
12233     NK_ASSERT(memory);
12234     NK_ASSERT(size);
12235 
12236     NK_ASSERT(atlas);
12237     NK_ASSERT(atlas->temporary.alloc);
12238     NK_ASSERT(atlas->temporary.free);
12239     NK_ASSERT(atlas->permanent.alloc);
12240     NK_ASSERT(atlas->permanent.free);
12241     if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
12242         !atlas->permanent.alloc || !atlas->permanent.free)
12243         return 0;
12244 
12245     cfg = (config) ? *config: nk_font_config(height);
12246     cfg.ttf_blob = memory;
12247     cfg.ttf_size = size;
12248     cfg.size = height;
12249     cfg.ttf_data_owned_by_atlas = 0;
12250     return nk_font_atlas_add(atlas, &cfg);
12251 }
12252 
12253 #ifdef NK_INCLUDE_STANDARD_IO
12254 NK_API struct nk_font*
12255 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
12256     float height, const struct nk_font_config *config)
12257 {
12258     nk_size size;
12259     char *memory;
12260     struct nk_font_config cfg;
12261 
12262     NK_ASSERT(atlas);
12263     NK_ASSERT(atlas->temporary.alloc);
12264     NK_ASSERT(atlas->temporary.free);
12265     NK_ASSERT(atlas->permanent.alloc);
12266     NK_ASSERT(atlas->permanent.free);
12267 
12268     if (!atlas || !file_path) return 0;
12269     memory = nk_file_load(file_path, &size, &atlas->permanent);
12270     if (!memory) return 0;
12271 
12272     cfg = (config) ? *config: nk_font_config(height);
12273     cfg.ttf_blob = memory;
12274     cfg.ttf_size = size;
12275     cfg.size = height;
12276     cfg.ttf_data_owned_by_atlas = 1;
12277     return nk_font_atlas_add(atlas, &cfg);
12278 }
12279 #endif
12280 
12281 NK_API struct nk_font*
12282 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
12283     void *compressed_data, nk_size compressed_size, float height,
12284     const struct nk_font_config *config)
12285 {
12286     unsigned int decompressed_size;
12287     void *decompressed_data;
12288     struct nk_font_config cfg;
12289 
12290     NK_ASSERT(atlas);
12291     NK_ASSERT(atlas->temporary.alloc);
12292     NK_ASSERT(atlas->temporary.free);
12293     NK_ASSERT(atlas->permanent.alloc);
12294     NK_ASSERT(atlas->permanent.free);
12295 
12296     NK_ASSERT(compressed_data);
12297     NK_ASSERT(compressed_size);
12298     if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
12299         !atlas->permanent.alloc || !atlas->permanent.free)
12300         return 0;
12301 
12302     decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
12303     decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
12304     NK_ASSERT(decompressed_data);
12305     if (!decompressed_data) return 0;
12306     nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
12307         (unsigned int)compressed_size);
12308 
12309     cfg = (config) ? *config: nk_font_config(height);
12310     cfg.ttf_blob = decompressed_data;
12311     cfg.ttf_size = decompressed_size;
12312     cfg.size = height;
12313     cfg.ttf_data_owned_by_atlas = 1;
12314     return nk_font_atlas_add(atlas, &cfg);
12315 }
12316 
12317 NK_API struct nk_font*
12318 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
12319     const char *data_base85, float height, const struct nk_font_config *config)
12320 {
12321     int compressed_size;
12322     void *compressed_data;
12323     struct nk_font *font;
12324 
12325     NK_ASSERT(atlas);
12326     NK_ASSERT(atlas->temporary.alloc);
12327     NK_ASSERT(atlas->temporary.free);
12328     NK_ASSERT(atlas->permanent.alloc);
12329     NK_ASSERT(atlas->permanent.free);
12330 
12331     NK_ASSERT(data_base85);
12332     if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
12333         !atlas->permanent.alloc || !atlas->permanent.free)
12334         return 0;
12335 
12336     compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
12337     compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
12338     NK_ASSERT(compressed_data);
12339     if (!compressed_data) return 0;
12340     nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
12341     font = nk_font_atlas_add_compressed(atlas, compressed_data,
12342                     (nk_size)compressed_size, height, config);
12343     atlas->temporary.free(atlas->temporary.userdata, compressed_data);
12344     return font;
12345 }
12346 
12347 #ifdef NK_INCLUDE_DEFAULT_FONT
12348 NK_API struct nk_font*
12349 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
12350     float pixel_height, const struct nk_font_config *config)
12351 {
12352     NK_ASSERT(atlas);
12353     NK_ASSERT(atlas->temporary.alloc);
12354     NK_ASSERT(atlas->temporary.free);
12355     NK_ASSERT(atlas->permanent.alloc);
12356     NK_ASSERT(atlas->permanent.free);
12357     return nk_font_atlas_add_compressed_base85(atlas,
12358         nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
12359 }
12360 #endif
12361 
12362 NK_API const void*
12363 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
12364     enum nk_font_atlas_format fmt)
12365 {
12366     int i = 0;
12367     void *tmp = 0;
12368     nk_size tmp_size, img_size;
12369     struct nk_font *font_iter;
12370     struct nk_font_baker *baker;
12371 
12372     NK_ASSERT(atlas);
12373     NK_ASSERT(atlas->temporary.alloc);
12374     NK_ASSERT(atlas->temporary.free);
12375     NK_ASSERT(atlas->permanent.alloc);
12376     NK_ASSERT(atlas->permanent.free);
12377 
12378     NK_ASSERT(width);
12379     NK_ASSERT(height);
12380     if (!atlas || !width || !height ||
12381         !atlas->temporary.alloc || !atlas->temporary.free ||
12382         !atlas->permanent.alloc || !atlas->permanent.free)
12383         return 0;
12384 
12385 #ifdef NK_INCLUDE_DEFAULT_FONT
12386     /* no font added so just use default font */
12387     if (!atlas->font_num)
12388         atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
12389 #endif
12390     NK_ASSERT(atlas->font_num);
12391     if (!atlas->font_num) return 0;
12392 
12393     /* allocate temporary baker memory required for the baking process */
12394     nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
12395     tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
12396     NK_ASSERT(tmp);
12397     if (!tmp) goto failed;
12398 
12399     /* allocate glyph memory for all fonts */
12400     baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
12401     atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
12402         atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
12403     NK_ASSERT(atlas->glyphs);
12404     if (!atlas->glyphs)
12405         goto failed;
12406 
12407     /* pack all glyphs into a tight fit space */
12408     atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
12409     atlas->custom.h = NK_CURSOR_DATA_H + 1;
12410     if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
12411         atlas->config, atlas->font_num, &atlas->temporary))
12412         goto failed;
12413 
12414     /* allocate memory for the baked image font atlas */
12415     atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
12416     NK_ASSERT(atlas->pixel);
12417     if (!atlas->pixel)
12418         goto failed;
12419 
12420     /* bake glyphs and custom white pixel into image */
12421     nk_font_bake(baker, atlas->pixel, *width, *height,
12422         atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
12423     nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
12424             nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
12425 
12426     if (fmt == NK_FONT_ATLAS_RGBA32) {
12427         /* convert alpha8 image into rgba32 image */
12428         void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
12429                             (nk_size)(*width * *height * 4));
12430         NK_ASSERT(img_rgba);
12431         if (!img_rgba) goto failed;
12432         nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
12433         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12434         atlas->pixel = img_rgba;
12435     }
12436     atlas->tex_width = *width;
12437     atlas->tex_height = *height;
12438 
12439     /* initialize each font */
12440     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12441         struct nk_font *font = font_iter;
12442         struct nk_font_config *config = font->config;
12443         nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
12444             config->font, nk_handle_ptr(0));
12445     }
12446 
12447     /* initialize each cursor */
12448     {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
12449         /* Pos ----- Size ------- Offset --*/
12450         {{ 0, 3},   {12,19},    { 0, 0}},
12451         {{13, 0},   { 7,16},    { 4, 8}},
12452         {{31, 0},   {23,23},    {11,11}},
12453         {{21, 0},   { 9, 23},   { 5,11}},
12454         {{55,18},   {23, 9},    {11, 5}},
12455         {{73, 0},   {17,17},    { 9, 9}},
12456         {{55, 0},   {17,17},    { 9, 9}}
12457     };
12458     for (i = 0; i < NK_CURSOR_COUNT; ++i) {
12459         struct nk_cursor *cursor = &atlas->cursors[i];
12460         cursor->img.w = (unsigned short)*width;
12461         cursor->img.h = (unsigned short)*height;
12462         cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
12463         cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
12464         cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
12465         cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
12466         cursor->size = nk_cursor_data[i][1];
12467         cursor->offset = nk_cursor_data[i][2];
12468     }}
12469     /* free temporary memory */
12470     atlas->temporary.free(atlas->temporary.userdata, tmp);
12471     return atlas->pixel;
12472 
12473 failed:
12474     /* error so cleanup all memory */
12475     if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
12476     if (atlas->glyphs) {
12477         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12478         atlas->glyphs = 0;
12479     }
12480     if (atlas->pixel) {
12481         atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12482         atlas->pixel = 0;
12483     }
12484     return 0;
12485 }
12486 
12487 NK_API void
12488 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
12489     struct nk_draw_null_texture *null)
12490 {
12491     int i = 0;
12492     struct nk_font *font_iter;
12493     NK_ASSERT(atlas);
12494     if (!atlas) {
12495         if (!null) return;
12496         null->texture = texture;
12497         null->uv = nk_vec2(0.5f,0.5f);
12498     }
12499     if (null) {
12500         null->texture = texture;
12501         null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
12502         null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
12503     }
12504     for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12505         font_iter->texture = texture;
12506 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12507         font_iter->handle.texture = texture;
12508 #endif
12509     }
12510     for (i = 0; i < NK_CURSOR_COUNT; ++i)
12511         atlas->cursors[i].img.handle = texture;
12512 
12513     atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12514     atlas->pixel = 0;
12515     atlas->tex_width = 0;
12516     atlas->tex_height = 0;
12517     atlas->custom.x = 0;
12518     atlas->custom.y = 0;
12519     atlas->custom.w = 0;
12520     atlas->custom.h = 0;
12521 }
12522 
12523 NK_API void
12524 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
12525 {
12526     NK_ASSERT(atlas);
12527     NK_ASSERT(atlas->temporary.alloc);
12528     NK_ASSERT(atlas->temporary.free);
12529     NK_ASSERT(atlas->permanent.alloc);
12530     NK_ASSERT(atlas->permanent.free);
12531     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12532     if (atlas->config) {
12533         struct nk_font_config *iter;
12534         for (iter = atlas->config; iter; iter = iter->next) {
12535             struct nk_font_config *i;
12536             for (i = iter->n; i != iter; i = i->n) {
12537                 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
12538                 i->ttf_blob = 0;
12539             }
12540             atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
12541             iter->ttf_blob = 0;
12542         }
12543     }
12544 }
12545 
12546 NK_API void
12547 nk_font_atlas_clear(struct nk_font_atlas *atlas)
12548 {
12549     NK_ASSERT(atlas);
12550     NK_ASSERT(atlas->temporary.alloc);
12551     NK_ASSERT(atlas->temporary.free);
12552     NK_ASSERT(atlas->permanent.alloc);
12553     NK_ASSERT(atlas->permanent.free);
12554     if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12555 
12556     if (atlas->config) {
12557         struct nk_font_config *iter, *next;
12558         for (iter = atlas->config; iter; iter = next) {
12559             struct nk_font_config *i, *n;
12560             for (i = iter->n; i != iter; i = n) {
12561                 n = i->n;
12562                 if (i->ttf_blob)
12563                     atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
12564                 atlas->permanent.free(atlas->permanent.userdata, i);
12565             }
12566             next = iter->next;
12567             if (i->ttf_blob)
12568                 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
12569             atlas->permanent.free(atlas->permanent.userdata, iter);
12570         }
12571         atlas->config = 0;
12572     }
12573     if (atlas->fonts) {
12574         struct nk_font *iter, *next;
12575         for (iter = atlas->fonts; iter; iter = next) {
12576             next = iter->next;
12577             atlas->permanent.free(atlas->permanent.userdata, iter);
12578         }
12579         atlas->fonts = 0;
12580     }
12581     if (atlas->glyphs)
12582         atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12583     nk_zero_struct(*atlas);
12584 }
12585 #endif
12586 /* ==============================================================
12587  *
12588  *                          INPUT
12589  *
12590  * ===============================================================*/
12591 NK_API void
12592 nk_input_begin(struct nk_context *ctx)
12593 {
12594     int i;
12595     struct nk_input *in;
12596     NK_ASSERT(ctx);
12597     if (!ctx) return;
12598     in = &ctx->input;
12599     for (i = 0; i < NK_BUTTON_MAX; ++i)
12600         in->mouse.buttons[i].clicked = 0;
12601 
12602     in->keyboard.text_len = 0;
12603     in->mouse.scroll_delta = nk_vec2(0,0);
12604     in->mouse.prev.x = in->mouse.pos.x;
12605     in->mouse.prev.y = in->mouse.pos.y;
12606     in->mouse.delta.x = 0;
12607     in->mouse.delta.y = 0;
12608     for (i = 0; i < NK_KEY_MAX; i++)
12609         in->keyboard.keys[i].clicked = 0;
12610 }
12611 
12612 NK_API void
12613 nk_input_end(struct nk_context *ctx)
12614 {
12615     struct nk_input *in;
12616     NK_ASSERT(ctx);
12617     if (!ctx) return;
12618     in = &ctx->input;
12619     if (in->mouse.grab)
12620         in->mouse.grab = 0;
12621     if (in->mouse.ungrab) {
12622         in->mouse.grabbed = 0;
12623         in->mouse.ungrab = 0;
12624         in->mouse.grab = 0;
12625     }
12626 }
12627 
12628 NK_API void
12629 nk_input_motion(struct nk_context *ctx, int x, int y)
12630 {
12631     struct nk_input *in;
12632     NK_ASSERT(ctx);
12633     if (!ctx) return;
12634     in = &ctx->input;
12635     in->mouse.pos.x = (float)x;
12636     in->mouse.pos.y = (float)y;
12637     in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
12638     in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
12639 }
12640 
12641 NK_API void
12642 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
12643 {
12644     struct nk_input *in;
12645     NK_ASSERT(ctx);
12646     if (!ctx) return;
12647     in = &ctx->input;
12648     if (in->keyboard.keys[key].down != down)
12649         in->keyboard.keys[key].clicked++;
12650     in->keyboard.keys[key].down = down;
12651 }
12652 
12653 NK_API void
12654 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
12655 {
12656     struct nk_mouse_button *btn;
12657     struct nk_input *in;
12658     NK_ASSERT(ctx);
12659     if (!ctx) return;
12660     in = &ctx->input;
12661     if (in->mouse.buttons[id].down == down) return;
12662 
12663     btn = &in->mouse.buttons[id];
12664     btn->clicked_pos.x = (float)x;
12665     btn->clicked_pos.y = (float)y;
12666     btn->down = down;
12667     btn->clicked++;
12668 }
12669 
12670 NK_API void
12671 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
12672 {
12673     NK_ASSERT(ctx);
12674     if (!ctx) return;
12675     ctx->input.mouse.scroll_delta.x += val.x;
12676     ctx->input.mouse.scroll_delta.y += val.y;
12677 }
12678 
12679 NK_API void
12680 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
12681 {
12682     int len = 0;
12683     nk_rune unicode;
12684     struct nk_input *in;
12685 
12686     NK_ASSERT(ctx);
12687     if (!ctx) return;
12688     in = &ctx->input;
12689 
12690     len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
12691     if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
12692         nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
12693             NK_INPUT_MAX - in->keyboard.text_len);
12694         in->keyboard.text_len += len;
12695     }
12696 }
12697 
12698 NK_API void
12699 nk_input_char(struct nk_context *ctx, char c)
12700 {
12701     nk_glyph glyph;
12702     NK_ASSERT(ctx);
12703     if (!ctx) return;
12704     glyph[0] = c;
12705     nk_input_glyph(ctx, glyph);
12706 }
12707 
12708 NK_API void
12709 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
12710 {
12711     nk_glyph rune;
12712     NK_ASSERT(ctx);
12713     if (!ctx) return;
12714     nk_utf_encode(unicode, rune, NK_UTF_SIZE);
12715     nk_input_glyph(ctx, rune);
12716 }
12717 
12718 NK_API int
12719 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
12720 {
12721     const struct nk_mouse_button *btn;
12722     if (!i) return nk_false;
12723     btn = &i->mouse.buttons[id];
12724     return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
12725 }
12726 
12727 NK_API int
12728 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12729     struct nk_rect b)
12730 {
12731     const struct nk_mouse_button *btn;
12732     if (!i) return nk_false;
12733     btn = &i->mouse.buttons[id];
12734     if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
12735         return nk_false;
12736     return nk_true;
12737 }
12738 
12739 NK_API int
12740 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
12741     struct nk_rect b, int down)
12742 {
12743     const struct nk_mouse_button *btn;
12744     if (!i) return nk_false;
12745     btn = &i->mouse.buttons[id];
12746     return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
12747 }
12748 
12749 NK_API int
12750 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12751     struct nk_rect b)
12752 {
12753     const struct nk_mouse_button *btn;
12754     if (!i) return nk_false;
12755     btn = &i->mouse.buttons[id];
12756     return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
12757             btn->clicked) ? nk_true : nk_false;
12758 }
12759 
12760 NK_API int
12761 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
12762     struct nk_rect b, int down)
12763 {
12764     const struct nk_mouse_button *btn;
12765     if (!i) return nk_false;
12766     btn = &i->mouse.buttons[id];
12767     return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
12768             btn->clicked) ? nk_true : nk_false;
12769 }
12770 
12771 NK_API int
12772 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
12773 {
12774     int i, down = 0;
12775     for (i = 0; i < NK_BUTTON_MAX; ++i)
12776         down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
12777     return down;
12778 }
12779 
12780 NK_API int
12781 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12782 {
12783     if (!i) return nk_false;
12784     return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
12785 }
12786 
12787 NK_API int
12788 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12789 {
12790     if (!i) return nk_false;
12791     return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
12792 }
12793 
12794 NK_API int
12795 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
12796 {
12797     if (!i) return nk_false;
12798     if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
12799     return nk_input_is_mouse_click_in_rect(i, id, rect);
12800 }
12801 
12802 NK_API int
12803 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
12804 {
12805     if (!i) return nk_false;
12806     return i->mouse.buttons[id].down;
12807 }
12808 
12809 NK_API int
12810 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
12811 {
12812     const struct nk_mouse_button *b;
12813     if (!i) return nk_false;
12814     b = &i->mouse.buttons[id];
12815     if (b->down && b->clicked)
12816         return nk_true;
12817     return nk_false;
12818 }
12819 
12820 NK_API int
12821 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
12822 {
12823     if (!i) return nk_false;
12824     return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
12825 }
12826 
12827 NK_API int
12828 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
12829 {
12830     const struct nk_key *k;
12831     if (!i) return nk_false;
12832     k = &i->keyboard.keys[key];
12833     if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
12834         return nk_true;
12835     return nk_false;
12836 }
12837 
12838 NK_API int
12839 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
12840 {
12841     const struct nk_key *k;
12842     if (!i) return nk_false;
12843     k = &i->keyboard.keys[key];
12844     if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
12845         return nk_true;
12846     return nk_false;
12847 }
12848 
12849 NK_API int
12850 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
12851 {
12852     const struct nk_key *k;
12853     if (!i) return nk_false;
12854     k = &i->keyboard.keys[key];
12855     if (k->down) return nk_true;
12856     return nk_false;
12857 }
12858 
12859 /*
12860  * ==============================================================
12861  *
12862  *                          TEXT EDITOR
12863  *
12864  * ===============================================================
12865  */
12866 /* stb_textedit.h - v1.8  - public domain - Sean Barrett */
12867 struct nk_text_find {
12868    float x,y;    /* position of n'th character */
12869    float height; /* height of line */
12870    int first_char, length; /* first char of row, and length */
12871    int prev_first;  /*_ first char of previous row */
12872 };
12873 
12874 struct nk_text_edit_row {
12875    float x0,x1;
12876    /* starting x location, end x location (allows for align=right, etc) */
12877    float baseline_y_delta;
12878    /* position of baseline relative to previous row's baseline*/
12879    float ymin,ymax;
12880    /* height of row above and below baseline */
12881    int num_chars;
12882 };
12883 
12884 /* forward declarations */
12885 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
12886 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
12887 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
12888 #define NK_TEXT_HAS_SELECTION(s)   ((s)->select_start != (s)->select_end)
12889 
12890 NK_INTERN float
12891 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
12892     const struct nk_user_font *font)
12893 {
12894     int len = 0;
12895     nk_rune unicode = 0;
12896     const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
12897     return font->width(font->userdata, font->height, str, len);
12898 }
12899 
12900 NK_INTERN void
12901 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
12902     int line_start_id, float row_height, const struct nk_user_font *font)
12903 {
12904     int l;
12905     int glyphs = 0;
12906     nk_rune unicode;
12907     const char *remaining;
12908     int len = nk_str_len_char(&edit->string);
12909     const char *end = nk_str_get_const(&edit->string) + len;
12910     const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
12911     const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
12912         text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
12913 
12914     r->x0 = 0.0f;
12915     r->x1 = size.x;
12916     r->baseline_y_delta = size.y;
12917     r->ymin = 0.0f;
12918     r->ymax = size.y;
12919     r->num_chars = glyphs;
12920 }
12921 
12922 NK_INTERN int
12923 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
12924     const struct nk_user_font *font, float row_height)
12925 {
12926     struct nk_text_edit_row r;
12927     int n = edit->string.len;
12928     float base_y = 0, prev_x;
12929     int i=0, k;
12930 
12931     r.x0 = r.x1 = 0;
12932     r.ymin = r.ymax = 0;
12933     r.num_chars = 0;
12934 
12935     /* search rows to find one that straddles 'y' */
12936     while (i < n) {
12937         nk_textedit_layout_row(&r, edit, i, row_height, font);
12938         if (r.num_chars <= 0)
12939             return n;
12940 
12941         if (i==0 && y < base_y + r.ymin)
12942             return 0;
12943 
12944         if (y < base_y + r.ymax)
12945             break;
12946 
12947         i += r.num_chars;
12948         base_y += r.baseline_y_delta;
12949     }
12950 
12951     /* below all text, return 'after' last character */
12952     if (i >= n)
12953         return n;
12954 
12955     /* check if it's before the beginning of the line */
12956     if (x < r.x0)
12957         return i;
12958 
12959     /* check if it's before the end of the line */
12960     if (x < r.x1) {
12961         /* search characters in row for one that straddles 'x' */
12962         k = i;
12963         prev_x = r.x0;
12964         for (i=0; i < r.num_chars; ++i) {
12965             float w = nk_textedit_get_width(edit, k, i, font);
12966             if (x < prev_x+w) {
12967                 if (x < prev_x+w/2)
12968                     return k+i;
12969                 else return k+i+1;
12970             }
12971             prev_x += w;
12972         }
12973         /* shouldn't happen, but if it does, fall through to end-of-line case */
12974     }
12975 
12976     /* if the last character is a newline, return that.
12977      * otherwise return 'after' the last character */
12978     if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
12979         return i+r.num_chars-1;
12980     else return i+r.num_chars;
12981 }
12982 
12983 NK_INTERN void
12984 nk_textedit_click(struct nk_text_edit *state, float x, float y,
12985     const struct nk_user_font *font, float row_height)
12986 {
12987     /* API click: on mouse down, move the cursor to the clicked location,
12988      * and reset the selection */
12989     state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
12990     state->select_start = state->cursor;
12991     state->select_end = state->cursor;
12992     state->has_preferred_x = 0;
12993 }
12994 
12995 NK_INTERN void
12996 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
12997     const struct nk_user_font *font, float row_height)
12998 {
12999     /* API drag: on mouse drag, move the cursor and selection endpoint
13000      * to the clicked location */
13001     int p = nk_textedit_locate_coord(state, x, y, font, row_height);
13002     if (state->select_start == state->select_end)
13003         state->select_start = state->cursor;
13004     state->cursor = state->select_end = p;
13005 }
13006 
13007 NK_INTERN void
13008 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
13009     int n, int single_line, const struct nk_user_font *font, float row_height)
13010 {
13011     /* find the x/y location of a character, and remember info about the previous
13012      * row in case we get a move-up event (for page up, we'll have to rescan) */
13013     struct nk_text_edit_row r;
13014     int prev_start = 0;
13015     int z = state->string.len;
13016     int i=0, first;
13017 
13018     nk_zero_struct(r);
13019     if (n == z) {
13020         /* if it's at the end, then find the last line -- simpler than trying to
13021         explicitly handle this case in the regular code */
13022         nk_textedit_layout_row(&r, state, 0, row_height, font);
13023         if (single_line) {
13024             find->first_char = 0;
13025             find->length = z;
13026         } else {
13027             while (i < z) {
13028                 prev_start = i;
13029                 i += r.num_chars;
13030                 nk_textedit_layout_row(&r, state, i, row_height, font);
13031             }
13032 
13033             find->first_char = i;
13034             find->length = r.num_chars;
13035         }
13036         find->x = r.x1;
13037         find->y = r.ymin;
13038         find->height = r.ymax - r.ymin;
13039         find->prev_first = prev_start;
13040         return;
13041     }
13042 
13043     /* search rows to find the one that straddles character n */
13044     find->y = 0;
13045 
13046     for(;;) {
13047         nk_textedit_layout_row(&r, state, i, row_height, font);
13048         if (n < i + r.num_chars) break;
13049         prev_start = i;
13050         i += r.num_chars;
13051         find->y += r.baseline_y_delta;
13052     }
13053 
13054     find->first_char = first = i;
13055     find->length = r.num_chars;
13056     find->height = r.ymax - r.ymin;
13057     find->prev_first = prev_start;
13058 
13059     /* now scan to find xpos */
13060     find->x = r.x0;
13061     for (i=0; first+i < n; ++i)
13062         find->x += nk_textedit_get_width(state, first, i, font);
13063 }
13064 
13065 NK_INTERN void
13066 nk_textedit_clamp(struct nk_text_edit *state)
13067 {
13068     /* make the selection/cursor state valid if client altered the string */
13069     int n = state->string.len;
13070     if (NK_TEXT_HAS_SELECTION(state)) {
13071         if (state->select_start > n) state->select_start = n;
13072         if (state->select_end   > n) state->select_end = n;
13073         /* if clamping forced them to be equal, move the cursor to match */
13074         if (state->select_start == state->select_end)
13075             state->cursor = state->select_start;
13076     }
13077     if (state->cursor > n) state->cursor = n;
13078 }
13079 
13080 NK_API void
13081 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
13082 {
13083     /* delete characters while updating undo */
13084     nk_textedit_makeundo_delete(state, where, len);
13085     nk_str_delete_runes(&state->string, where, len);
13086     state->has_preferred_x = 0;
13087 }
13088 
13089 NK_API void
13090 nk_textedit_delete_selection(struct nk_text_edit *state)
13091 {
13092     /* delete the section */
13093     nk_textedit_clamp(state);
13094     if (NK_TEXT_HAS_SELECTION(state)) {
13095         if (state->select_start < state->select_end) {
13096             nk_textedit_delete(state, state->select_start,
13097                 state->select_end - state->select_start);
13098             state->select_end = state->cursor = state->select_start;
13099         } else {
13100             nk_textedit_delete(state, state->select_end,
13101                 state->select_start - state->select_end);
13102             state->select_start = state->cursor = state->select_end;
13103         }
13104         state->has_preferred_x = 0;
13105     }
13106 }
13107 
13108 NK_INTERN void
13109 nk_textedit_sortselection(struct nk_text_edit *state)
13110 {
13111     /* canonicalize the selection so start <= end */
13112     if (state->select_end < state->select_start) {
13113         int temp = state->select_end;
13114         state->select_end = state->select_start;
13115         state->select_start = temp;
13116     }
13117 }
13118 
13119 NK_INTERN void
13120 nk_textedit_move_to_first(struct nk_text_edit *state)
13121 {
13122     /* move cursor to first character of selection */
13123     if (NK_TEXT_HAS_SELECTION(state)) {
13124         nk_textedit_sortselection(state);
13125         state->cursor = state->select_start;
13126         state->select_end = state->select_start;
13127         state->has_preferred_x = 0;
13128     }
13129 }
13130 
13131 NK_INTERN void
13132 nk_textedit_move_to_last(struct nk_text_edit *state)
13133 {
13134     /* move cursor to last character of selection */
13135     if (NK_TEXT_HAS_SELECTION(state)) {
13136         nk_textedit_sortselection(state);
13137         nk_textedit_clamp(state);
13138         state->cursor = state->select_end;
13139         state->select_start = state->select_end;
13140         state->has_preferred_x = 0;
13141     }
13142 }
13143 
13144 NK_INTERN int
13145 nk_is_word_boundary( struct nk_text_edit *state, int idx)
13146 {
13147     int len;
13148     nk_rune c;
13149     if (idx <= 0) return 1;
13150     if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
13151     return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
13152             c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
13153             c == '|');
13154 }
13155 
13156 NK_INTERN int
13157 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
13158 {
13159    int c = state->cursor - 1;
13160    while( c >= 0 && !nk_is_word_boundary(state, c))
13161       --c;
13162 
13163    if( c < 0 )
13164       c = 0;
13165 
13166    return c;
13167 }
13168 
13169 NK_INTERN int
13170 nk_textedit_move_to_word_next(struct nk_text_edit *state)
13171 {
13172    const int len = state->string.len;
13173    int c = state->cursor+1;
13174    while( c < len && !nk_is_word_boundary(state, c))
13175       ++c;
13176 
13177    if( c > len )
13178       c = len;
13179 
13180    return c;
13181 }
13182 
13183 NK_INTERN void
13184 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
13185 {
13186     /* update selection and cursor to match each other */
13187     if (!NK_TEXT_HAS_SELECTION(state))
13188         state->select_start = state->select_end = state->cursor;
13189     else state->cursor = state->select_end;
13190 }
13191 
13192 NK_API int
13193 nk_textedit_cut(struct nk_text_edit *state)
13194 {
13195     /* API cut: delete selection */
13196     if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13197         return 0;
13198     if (NK_TEXT_HAS_SELECTION(state)) {
13199         nk_textedit_delete_selection(state); /* implicitly clamps */
13200         state->has_preferred_x = 0;
13201         return 1;
13202     }
13203    return 0;
13204 }
13205 
13206 NK_API int
13207 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
13208 {
13209     /* API paste: replace existing selection with passed-in text */
13210     int glyphs;
13211     const char *text = (const char *) ctext;
13212     if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
13213 
13214     /* if there's a selection, the paste should delete it */
13215     nk_textedit_clamp(state);
13216     nk_textedit_delete_selection(state);
13217 
13218     /* try to insert the characters */
13219     glyphs = nk_utf_len(ctext, len);
13220     if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
13221         nk_textedit_makeundo_insert(state, state->cursor, glyphs);
13222         state->cursor += len;
13223         state->has_preferred_x = 0;
13224         return 1;
13225     }
13226     /* remove the undo since we didn't actually insert the characters */
13227     if (state->undo.undo_point)
13228         --state->undo.undo_point;
13229     return 0;
13230 }
13231 
13232 NK_API void
13233 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
13234 {
13235     nk_rune unicode;
13236     int glyph_len;
13237     int text_len = 0;
13238 
13239     NK_ASSERT(state);
13240     NK_ASSERT(text);
13241     if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
13242 
13243     glyph_len = nk_utf_decode(text, &unicode, total_len);
13244     while ((text_len < total_len) && glyph_len)
13245     {
13246         /* don't insert a backward delete, just process the event */
13247         if (unicode == 127) goto next;
13248         /* can't add newline in single-line mode */
13249         if (unicode == '\n' && state->single_line) goto next;
13250         /* filter incoming text */
13251         if (state->filter && !state->filter(state, unicode)) goto next;
13252 
13253         if (!NK_TEXT_HAS_SELECTION(state) &&
13254             state->cursor < state->string.len)
13255         {
13256             if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
13257                 nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
13258                 nk_str_delete_runes(&state->string, state->cursor, 1);
13259             }
13260             if (nk_str_insert_text_utf8(&state->string, state->cursor,
13261                                         text+text_len, 1))
13262             {
13263                 ++state->cursor;
13264                 state->has_preferred_x = 0;
13265             }
13266         } else {
13267             nk_textedit_delete_selection(state); /* implicitly clamps */
13268             if (nk_str_insert_text_utf8(&state->string, state->cursor,
13269                                         text+text_len, 1))
13270             {
13271                 nk_textedit_makeundo_insert(state, state->cursor, 1);
13272                 ++state->cursor;
13273                 state->has_preferred_x = 0;
13274             }
13275         }
13276         next:
13277         text_len += glyph_len;
13278         glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
13279     }
13280 }
13281 
13282 NK_INTERN void
13283 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
13284     const struct nk_user_font *font, float row_height)
13285 {
13286 retry:
13287     switch (key)
13288     {
13289     case NK_KEY_NONE:
13290     case NK_KEY_CTRL:
13291     case NK_KEY_ENTER:
13292     case NK_KEY_SHIFT:
13293     case NK_KEY_TAB:
13294     case NK_KEY_COPY:
13295     case NK_KEY_CUT:
13296     case NK_KEY_PASTE:
13297     case NK_KEY_MAX:
13298     default: break;
13299     case NK_KEY_TEXT_UNDO:
13300          nk_textedit_undo(state);
13301          state->has_preferred_x = 0;
13302          break;
13303 
13304     case NK_KEY_TEXT_REDO:
13305         nk_textedit_redo(state);
13306         state->has_preferred_x = 0;
13307         break;
13308 
13309     case NK_KEY_TEXT_SELECT_ALL:
13310         nk_textedit_select_all(state);
13311         state->has_preferred_x = 0;
13312         break;
13313 
13314     case NK_KEY_TEXT_INSERT_MODE:
13315         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13316             state->mode = NK_TEXT_EDIT_MODE_INSERT;
13317         break;
13318     case NK_KEY_TEXT_REPLACE_MODE:
13319         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13320             state->mode = NK_TEXT_EDIT_MODE_REPLACE;
13321         break;
13322     case NK_KEY_TEXT_RESET_MODE:
13323         if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
13324             state->mode == NK_TEXT_EDIT_MODE_REPLACE)
13325             state->mode = NK_TEXT_EDIT_MODE_VIEW;
13326         break;
13327 
13328     case NK_KEY_LEFT:
13329         if (shift_mod) {
13330             nk_textedit_clamp(state);
13331             nk_textedit_prep_selection_at_cursor(state);
13332             /* move selection left */
13333             if (state->select_end > 0)
13334                 --state->select_end;
13335             state->cursor = state->select_end;
13336             state->has_preferred_x = 0;
13337         } else {
13338             /* if currently there's a selection,
13339              * move cursor to start of selection */
13340             if (NK_TEXT_HAS_SELECTION(state))
13341                 nk_textedit_move_to_first(state);
13342             else if (state->cursor > 0)
13343                --state->cursor;
13344             state->has_preferred_x = 0;
13345         } break;
13346 
13347     case NK_KEY_RIGHT:
13348         if (shift_mod) {
13349             nk_textedit_prep_selection_at_cursor(state);
13350             /* move selection right */
13351             ++state->select_end;
13352             nk_textedit_clamp(state);
13353             state->cursor = state->select_end;
13354             state->has_preferred_x = 0;
13355         } else {
13356             /* if currently there's a selection,
13357              * move cursor to end of selection */
13358             if (NK_TEXT_HAS_SELECTION(state))
13359                 nk_textedit_move_to_last(state);
13360             else ++state->cursor;
13361             nk_textedit_clamp(state);
13362             state->has_preferred_x = 0;
13363         } break;
13364 
13365     case NK_KEY_TEXT_WORD_LEFT:
13366         if (shift_mod) {
13367             if( !NK_TEXT_HAS_SELECTION( state ) )
13368             nk_textedit_prep_selection_at_cursor(state);
13369             state->cursor = nk_textedit_move_to_word_previous(state);
13370             state->select_end = state->cursor;
13371             nk_textedit_clamp(state );
13372         } else {
13373             if (NK_TEXT_HAS_SELECTION(state))
13374                 nk_textedit_move_to_first(state);
13375             else {
13376                 state->cursor = nk_textedit_move_to_word_previous(state);
13377                 nk_textedit_clamp(state );
13378             }
13379         } break;
13380 
13381     case NK_KEY_TEXT_WORD_RIGHT:
13382         if (shift_mod) {
13383             if( !NK_TEXT_HAS_SELECTION( state ) )
13384                 nk_textedit_prep_selection_at_cursor(state);
13385             state->cursor = nk_textedit_move_to_word_next(state);
13386             state->select_end = state->cursor;
13387             nk_textedit_clamp(state);
13388         } else {
13389             if (NK_TEXT_HAS_SELECTION(state))
13390                 nk_textedit_move_to_last(state);
13391             else {
13392                 state->cursor = nk_textedit_move_to_word_next(state);
13393                 nk_textedit_clamp(state );
13394             }
13395         } break;
13396 
13397     case NK_KEY_DOWN: {
13398         struct nk_text_find find;
13399         struct nk_text_edit_row row;
13400         int i, sel = shift_mod;
13401 
13402         if (state->single_line) {
13403             /* on windows, up&down in single-line behave like left&right */
13404             key = NK_KEY_RIGHT;
13405             goto retry;
13406         }
13407 
13408         if (sel)
13409             nk_textedit_prep_selection_at_cursor(state);
13410         else if (NK_TEXT_HAS_SELECTION(state))
13411             nk_textedit_move_to_last(state);
13412 
13413         /* compute current position of cursor point */
13414         nk_textedit_clamp(state);
13415         nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13416             font, row_height);
13417 
13418         /* now find character position down a row */
13419         if (find.length)
13420         {
13421             float x;
13422             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13423             int start = find.first_char + find.length;
13424 
13425             state->cursor = start;
13426             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13427             x = row.x0;
13428 
13429             for (i=0; i < row.num_chars && x < row.x1; ++i) {
13430                 float dx = nk_textedit_get_width(state, start, i, font);
13431                 x += dx;
13432                 if (x > goal_x)
13433                     break;
13434                 ++state->cursor;
13435             }
13436             nk_textedit_clamp(state);
13437 
13438             state->has_preferred_x = 1;
13439             state->preferred_x = goal_x;
13440             if (sel)
13441                 state->select_end = state->cursor;
13442         }
13443     } break;
13444 
13445     case NK_KEY_UP: {
13446         struct nk_text_find find;
13447         struct nk_text_edit_row row;
13448         int i, sel = shift_mod;
13449 
13450         if (state->single_line) {
13451             /* on windows, up&down become left&right */
13452             key = NK_KEY_LEFT;
13453             goto retry;
13454         }
13455 
13456         if (sel)
13457             nk_textedit_prep_selection_at_cursor(state);
13458         else if (NK_TEXT_HAS_SELECTION(state))
13459             nk_textedit_move_to_first(state);
13460 
13461          /* compute current position of cursor point */
13462          nk_textedit_clamp(state);
13463          nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13464                 font, row_height);
13465 
13466          /* can only go up if there's a previous row */
13467          if (find.prev_first != find.first_char) {
13468             /* now find character position up a row */
13469             float x;
13470             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13471 
13472             state->cursor = find.prev_first;
13473             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13474             x = row.x0;
13475 
13476             for (i=0; i < row.num_chars && x < row.x1; ++i) {
13477                 float dx = nk_textedit_get_width(state, find.prev_first, i, font);
13478                 x += dx;
13479                 if (x > goal_x)
13480                     break;
13481                 ++state->cursor;
13482             }
13483             nk_textedit_clamp(state);
13484 
13485             state->has_preferred_x = 1;
13486             state->preferred_x = goal_x;
13487             if (sel) state->select_end = state->cursor;
13488          }
13489       } break;
13490 
13491     case NK_KEY_DEL:
13492         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13493             break;
13494         if (NK_TEXT_HAS_SELECTION(state))
13495             nk_textedit_delete_selection(state);
13496         else {
13497             int n = state->string.len;
13498             if (state->cursor < n)
13499                 nk_textedit_delete(state, state->cursor, 1);
13500          }
13501          state->has_preferred_x = 0;
13502          break;
13503 
13504     case NK_KEY_BACKSPACE:
13505         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13506             break;
13507         if (NK_TEXT_HAS_SELECTION(state))
13508             nk_textedit_delete_selection(state);
13509         else {
13510             nk_textedit_clamp(state);
13511             if (state->cursor > 0) {
13512                 nk_textedit_delete(state, state->cursor-1, 1);
13513                 --state->cursor;
13514             }
13515          }
13516          state->has_preferred_x = 0;
13517          break;
13518 
13519     case NK_KEY_TEXT_START:
13520          if (shift_mod) {
13521             nk_textedit_prep_selection_at_cursor(state);
13522             state->cursor = state->select_end = 0;
13523             state->has_preferred_x = 0;
13524          } else {
13525             state->cursor = state->select_start = state->select_end = 0;
13526             state->has_preferred_x = 0;
13527          }
13528          break;
13529 
13530     case NK_KEY_TEXT_END:
13531          if (shift_mod) {
13532             nk_textedit_prep_selection_at_cursor(state);
13533             state->cursor = state->select_end = state->string.len;
13534             state->has_preferred_x = 0;
13535          } else {
13536             state->cursor = state->string.len;
13537             state->select_start = state->select_end = 0;
13538             state->has_preferred_x = 0;
13539          }
13540          break;
13541 
13542     case NK_KEY_TEXT_LINE_START: {
13543         if (shift_mod) {
13544             struct nk_text_find find;
13545            nk_textedit_clamp(state);
13546             nk_textedit_prep_selection_at_cursor(state);
13547             if (state->string.len && state->cursor == state->string.len)
13548                 --state->cursor;
13549             nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
13550                 font, row_height);
13551             state->cursor = state->select_end = find.first_char;
13552             state->has_preferred_x = 0;
13553         } else {
13554             struct nk_text_find find;
13555             if (state->string.len && state->cursor == state->string.len)
13556                 --state->cursor;
13557             nk_textedit_clamp(state);
13558             nk_textedit_move_to_first(state);
13559             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13560                 font, row_height);
13561             state->cursor = find.first_char;
13562             state->has_preferred_x = 0;
13563         }
13564       } break;
13565 
13566     case NK_KEY_TEXT_LINE_END: {
13567         if (shift_mod) {
13568             struct nk_text_find find;
13569             nk_textedit_clamp(state);
13570             nk_textedit_prep_selection_at_cursor(state);
13571             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13572                 font, row_height);
13573             state->has_preferred_x = 0;
13574             state->cursor = find.first_char + find.length;
13575             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13576                 --state->cursor;
13577             state->select_end = state->cursor;
13578         } else {
13579             struct nk_text_find find;
13580             nk_textedit_clamp(state);
13581             nk_textedit_move_to_first(state);
13582             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13583                 font, row_height);
13584 
13585             state->has_preferred_x = 0;
13586             state->cursor = find.first_char + find.length;
13587             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13588                 --state->cursor;
13589         }} break;
13590     }
13591 }
13592 
13593 NK_INTERN void
13594 nk_textedit_flush_redo(struct nk_text_undo_state *state)
13595 {
13596     state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
13597     state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
13598 }
13599 
13600 NK_INTERN void
13601 nk_textedit_discard_undo(struct nk_text_undo_state *state)
13602 {
13603     /* discard the oldest entry in the undo list */
13604     if (state->undo_point > 0) {
13605         /* if the 0th undo state has characters, clean those up */
13606         if (state->undo_rec[0].char_storage >= 0) {
13607             int n = state->undo_rec[0].insert_length, i;
13608             /* delete n characters from all other records */
13609             state->undo_char_point = (short)(state->undo_char_point - n);
13610             NK_MEMCPY(state->undo_char, state->undo_char + n,
13611                 (nk_size)state->undo_char_point*sizeof(nk_rune));
13612             for (i=0; i < state->undo_point; ++i) {
13613                 if (state->undo_rec[i].char_storage >= 0)
13614                 state->undo_rec[i].char_storage = (short)
13615                     (state->undo_rec[i].char_storage - n);
13616             }
13617         }
13618         --state->undo_point;
13619         NK_MEMCPY(state->undo_rec, state->undo_rec+1,
13620             (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
13621     }
13622 }
13623 
13624 NK_INTERN void
13625 nk_textedit_discard_redo(struct nk_text_undo_state *state)
13626 {
13627 /*  discard the oldest entry in the redo list--it's bad if this
13628     ever happens, but because undo & redo have to store the actual
13629     characters in different cases, the redo character buffer can
13630     fill up even though the undo buffer didn't */
13631     nk_size num;
13632     int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
13633     if (state->redo_point <= k) {
13634         /* if the k'th undo state has characters, clean those up */
13635         if (state->undo_rec[k].char_storage >= 0) {
13636             int n = state->undo_rec[k].insert_length, i;
13637             /* delete n characters from all other records */
13638             state->redo_char_point = (short)(state->redo_char_point + n);
13639             num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point);
13640             NK_MEMCPY(state->undo_char + state->redo_char_point,
13641                 state->undo_char + state->redo_char_point-n, num * sizeof(char));
13642             for (i = state->redo_point; i < k; ++i) {
13643                 if (state->undo_rec[i].char_storage >= 0) {
13644                     state->undo_rec[i].char_storage = (short)
13645                         (state->undo_rec[i].char_storage + n);
13646                 }
13647             }
13648         }
13649         ++state->redo_point;
13650         num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
13651         if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
13652             state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
13653     }
13654 }
13655 
13656 NK_INTERN struct nk_text_undo_record*
13657 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
13658 {
13659     /* any time we create a new undo record, we discard redo*/
13660     nk_textedit_flush_redo(state);
13661 
13662     /* if we have no free records, we have to make room,
13663      * by sliding the existing records down */
13664     if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13665         nk_textedit_discard_undo(state);
13666 
13667     /* if the characters to store won't possibly fit in the buffer,
13668      * we can't undo */
13669     if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
13670         state->undo_point = 0;
13671         state->undo_char_point = 0;
13672         return 0;
13673     }
13674 
13675     /* if we don't have enough free characters in the buffer,
13676      * we have to make room */
13677     while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
13678         nk_textedit_discard_undo(state);
13679     return &state->undo_rec[state->undo_point++];
13680 }
13681 
13682 NK_INTERN nk_rune*
13683 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
13684     int insert_len, int delete_len)
13685 {
13686     struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
13687     if (r == 0)
13688         return 0;
13689 
13690     r->where = pos;
13691     r->insert_length = (short) insert_len;
13692     r->delete_length = (short) delete_len;
13693 
13694     if (insert_len == 0) {
13695         r->char_storage = -1;
13696         return 0;
13697     } else {
13698         r->char_storage = state->undo_char_point;
13699         state->undo_char_point = (short)(state->undo_char_point +  insert_len);
13700         return &state->undo_char[r->char_storage];
13701     }
13702 }
13703 
13704 NK_API void
13705 nk_textedit_undo(struct nk_text_edit *state)
13706 {
13707     struct nk_text_undo_state *s = &state->undo;
13708     struct nk_text_undo_record u, *r;
13709     if (s->undo_point == 0)
13710         return;
13711 
13712     /* we need to do two things: apply the undo record, and create a redo record */
13713     u = s->undo_rec[s->undo_point-1];
13714     r = &s->undo_rec[s->redo_point-1];
13715     r->char_storage = -1;
13716 
13717     r->insert_length = u.delete_length;
13718     r->delete_length = u.insert_length;
13719     r->where = u.where;
13720 
13721     if (u.delete_length)
13722     {
13723        /*   if the undo record says to delete characters, then the redo record will
13724             need to re-insert the characters that get deleted, so we need to store
13725             them.
13726             there are three cases:
13727                 - there's enough room to store the characters
13728                 - characters stored for *redoing* don't leave room for redo
13729                 - characters stored for *undoing* don't leave room for redo
13730             if the last is true, we have to bail */
13731         if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
13732             /* the undo records take up too much character space; there's no space
13733             * to store the redo characters */
13734             r->insert_length = 0;
13735         } else {
13736             int i;
13737             /* there's definitely room to store the characters eventually */
13738             while (s->undo_char_point + u.delete_length > s->redo_char_point) {
13739                 /* there's currently not enough room, so discard a redo record */
13740                 nk_textedit_discard_redo(s);
13741                 /* should never happen: */
13742                 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13743                     return;
13744             }
13745 
13746             r = &s->undo_rec[s->redo_point-1];
13747             r->char_storage = (short)(s->redo_char_point - u.delete_length);
13748             s->redo_char_point = (short)(s->redo_char_point -  u.delete_length);
13749 
13750             /* now save the characters */
13751             for (i=0; i < u.delete_length; ++i)
13752                 s->undo_char[r->char_storage + i] =
13753                     nk_str_rune_at(&state->string, u.where + i);
13754         }
13755         /* now we can carry out the deletion */
13756         nk_str_delete_runes(&state->string, u.where, u.delete_length);
13757     }
13758 
13759     /* check type of recorded action: */
13760     if (u.insert_length) {
13761         /* easy case: was a deletion, so we need to insert n characters */
13762         nk_str_insert_text_runes(&state->string, u.where,
13763             &s->undo_char[u.char_storage], u.insert_length);
13764         s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
13765     }
13766     state->cursor = (short)(u.where + u.insert_length);
13767 
13768     s->undo_point--;
13769     s->redo_point--;
13770 }
13771 
13772 NK_API void
13773 nk_textedit_redo(struct nk_text_edit *state)
13774 {
13775     struct nk_text_undo_state *s = &state->undo;
13776     struct nk_text_undo_record *u, r;
13777     if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13778         return;
13779 
13780     /* we need to do two things: apply the redo record, and create an undo record */
13781     u = &s->undo_rec[s->undo_point];
13782     r = s->undo_rec[s->redo_point];
13783 
13784     /* we KNOW there must be room for the undo record, because the redo record
13785     was derived from an undo record */
13786     u->delete_length = r.insert_length;
13787     u->insert_length = r.delete_length;
13788     u->where = r.where;
13789     u->char_storage = -1;
13790 
13791     if (r.delete_length) {
13792         /* the redo record requires us to delete characters, so the undo record
13793         needs to store the characters */
13794         if (s->undo_char_point + u->insert_length > s->redo_char_point) {
13795             u->insert_length = 0;
13796             u->delete_length = 0;
13797         } else {
13798             int i;
13799             u->char_storage = s->undo_char_point;
13800             s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
13801 
13802             /* now save the characters */
13803             for (i=0; i < u->insert_length; ++i) {
13804                 s->undo_char[u->char_storage + i] =
13805                     nk_str_rune_at(&state->string, u->where + i);
13806             }
13807         }
13808         nk_str_delete_runes(&state->string, r.where, r.delete_length);
13809     }
13810 
13811     if (r.insert_length) {
13812         /* easy case: need to insert n characters */
13813         nk_str_insert_text_runes(&state->string, r.where,
13814             &s->undo_char[r.char_storage], r.insert_length);
13815     }
13816     state->cursor = r.where + r.insert_length;
13817 
13818     s->undo_point++;
13819     s->redo_point++;
13820 }
13821 
13822 NK_INTERN void
13823 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
13824 {
13825     nk_textedit_createundo(&state->undo, where, 0, length);
13826 }
13827 
13828 NK_INTERN void
13829 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
13830 {
13831     int i;
13832     nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
13833     if (p) {
13834         for (i=0; i < length; ++i)
13835             p[i] = nk_str_rune_at(&state->string, where+i);
13836     }
13837 }
13838 
13839 NK_INTERN void
13840 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
13841     int old_length, int new_length)
13842 {
13843     int i;
13844     nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
13845     if (p) {
13846         for (i=0; i < old_length; ++i)
13847             p[i] = nk_str_rune_at(&state->string, where+i);
13848     }
13849 }
13850 
13851 NK_INTERN void
13852 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
13853     nk_plugin_filter filter)
13854 {
13855     /* reset the state to default */
13856    state->undo.undo_point = 0;
13857    state->undo.undo_char_point = 0;
13858    state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
13859    state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
13860    state->select_end = state->select_start = 0;
13861    state->cursor = 0;
13862    state->has_preferred_x = 0;
13863    state->preferred_x = 0;
13864    state->cursor_at_end_of_line = 0;
13865    state->initialized = 1;
13866    state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
13867    state->mode = NK_TEXT_EDIT_MODE_VIEW;
13868    state->filter = filter;
13869    state->scrollbar = nk_vec2(0,0);
13870 }
13871 
13872 NK_API void
13873 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
13874 {
13875     NK_ASSERT(state);
13876     NK_ASSERT(memory);
13877     if (!state || !memory || !size) return;
13878     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13879     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13880     nk_str_init_fixed(&state->string, memory, size);
13881 }
13882 
13883 NK_API void
13884 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
13885 {
13886     NK_ASSERT(state);
13887     NK_ASSERT(alloc);
13888     if (!state || !alloc) return;
13889     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13890     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13891     nk_str_init(&state->string, alloc, size);
13892 }
13893 
13894 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13895 NK_API void
13896 nk_textedit_init_default(struct nk_text_edit *state)
13897 {
13898     NK_ASSERT(state);
13899     if (!state) return;
13900     NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13901     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13902     nk_str_init_default(&state->string);
13903 }
13904 #endif
13905 
13906 NK_API void
13907 nk_textedit_select_all(struct nk_text_edit *state)
13908 {
13909     NK_ASSERT(state);
13910     state->select_start = 0;
13911     state->select_end = state->string.len;
13912 }
13913 
13914 NK_API void
13915 nk_textedit_free(struct nk_text_edit *state)
13916 {
13917     NK_ASSERT(state);
13918     if (!state) return;
13919     nk_str_free(&state->string);
13920 }
13921 
13922 /* ===============================================================
13923  *
13924  *                          TEXT WIDGET
13925  *
13926  * ===============================================================*/
13927 #define nk_widget_state_reset(s)\
13928     if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
13929         (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
13930     else (*(s)) = NK_WIDGET_STATE_INACTIVE;
13931 
13932 struct nk_text {
13933     struct nk_vec2 padding;
13934     struct nk_color background;
13935     struct nk_color text;
13936 };
13937 
13938 NK_INTERN void
13939 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
13940     const char *string, int len, const struct nk_text *t,
13941     nk_flags a, const struct nk_user_font *f)
13942 {
13943     struct nk_rect label;
13944     float text_width;
13945 
13946     NK_ASSERT(o);
13947     NK_ASSERT(t);
13948     if (!o || !t) return;
13949 
13950     b.h = NK_MAX(b.h, 2 * t->padding.y);
13951     label.x = 0; label.w = 0;
13952     label.y = b.y + t->padding.y;
13953     label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
13954 
13955     text_width = f->width(f->userdata, f->height, (const char*)string, len);
13956     text_width += (2.0f * t->padding.x);
13957 
13958     /* align in x-axis */
13959     if (a & NK_TEXT_ALIGN_LEFT) {
13960         label.x = b.x + t->padding.x;
13961         label.w = NK_MAX(0, b.w - 2 * t->padding.x);
13962     } else if (a & NK_TEXT_ALIGN_CENTERED) {
13963         label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
13964         label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
13965         label.x = NK_MAX(b.x + t->padding.x, label.x);
13966         label.w = NK_MIN(b.x + b.w, label.x + label.w);
13967         if (label.w >= label.x) label.w -= label.x;
13968     } else if (a & NK_TEXT_ALIGN_RIGHT) {
13969         label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
13970         label.w = (float)text_width + 2 * t->padding.x;
13971     } else return;
13972 
13973     /* align in y-axis */
13974     if (a & NK_TEXT_ALIGN_MIDDLE) {
13975         label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
13976         label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
13977     } else if (a & NK_TEXT_ALIGN_BOTTOM) {
13978         label.y = b.y + b.h - f->height;
13979         label.h = f->height;
13980     }
13981     nk_draw_text(o, label, (const char*)string,
13982         len, f, t->background, t->text);
13983 }
13984 
13985 NK_INTERN void
13986 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
13987     const char *string, int len, const struct nk_text *t,
13988     const struct nk_user_font *f)
13989 {
13990     float width;
13991     int glyphs = 0;
13992     int fitting = 0;
13993     int done = 0;
13994     struct nk_rect line;
13995     struct nk_text text;
13996     NK_INTERN nk_rune seperator[] = {' '};
13997 
13998     NK_ASSERT(o);
13999     NK_ASSERT(t);
14000     if (!o || !t) return;
14001 
14002     text.padding = nk_vec2(0,0);
14003     text.background = t->background;
14004     text.text = t->text;
14005 
14006     b.w = NK_MAX(b.w, 2 * t->padding.x);
14007     b.h = NK_MAX(b.h, 2 * t->padding.y);
14008     b.h = b.h - 2 * t->padding.y;
14009 
14010     line.x = b.x + t->padding.x;
14011     line.y = b.y + t->padding.y;
14012     line.w = b.w - 2 * t->padding.x;
14013     line.h = 2 * t->padding.y + f->height;
14014 
14015     fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
14016     while (done < len) {
14017         if (!fitting || line.y + line.h >= (b.y + b.h)) break;
14018         nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
14019         done += fitting;
14020         line.y += f->height + 2 * t->padding.y;
14021         fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
14022     }
14023 }
14024 
14025 /* ===============================================================
14026  *
14027  *                          BUTTON
14028  *
14029  * ===============================================================*/
14030 NK_INTERN void
14031 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
14032     struct nk_rect content, struct nk_color background, struct nk_color foreground,
14033     float border_width, const struct nk_user_font *font)
14034 {
14035     switch (type) {
14036     case NK_SYMBOL_X:
14037     case NK_SYMBOL_UNDERSCORE:
14038     case NK_SYMBOL_PLUS:
14039     case NK_SYMBOL_MINUS: {
14040         /* single character text symbol */
14041         const char *X = (type == NK_SYMBOL_X) ? "x":
14042             (type == NK_SYMBOL_UNDERSCORE) ? "_":
14043             (type == NK_SYMBOL_PLUS) ? "+": "-";
14044         struct nk_text text;
14045         text.padding = nk_vec2(0,0);
14046         text.background = background;
14047         text.text = foreground;
14048         nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
14049     } break;
14050     case NK_SYMBOL_CIRCLE_SOLID:
14051     case NK_SYMBOL_CIRCLE_OUTLINE:
14052     case NK_SYMBOL_RECT_SOLID:
14053     case NK_SYMBOL_RECT_OUTLINE: {
14054         /* simple empty/filled shapes */
14055         if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
14056             nk_fill_rect(out, content,  0, foreground);
14057             if (type == NK_SYMBOL_RECT_OUTLINE)
14058                 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
14059         } else {
14060             nk_fill_circle(out, content, foreground);
14061             if (type == NK_SYMBOL_CIRCLE_OUTLINE)
14062                 nk_fill_circle(out, nk_shrink_rect(content, 1), background);
14063         }
14064     } break;
14065     case NK_SYMBOL_TRIANGLE_UP:
14066     case NK_SYMBOL_TRIANGLE_DOWN:
14067     case NK_SYMBOL_TRIANGLE_LEFT:
14068     case NK_SYMBOL_TRIANGLE_RIGHT: {
14069         enum nk_heading heading;
14070         struct nk_vec2 points[3];
14071         heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
14072             (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
14073             (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
14074         nk_triangle_from_direction(points, content, 0, 0, heading);
14075         nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
14076             points[2].x, points[2].y, foreground);
14077     } break;
14078     default:
14079     case NK_SYMBOL_NONE:
14080     case NK_SYMBOL_MAX: break;
14081     }
14082 }
14083 
14084 NK_INTERN int
14085 nk_button_behavior(nk_flags *state, struct nk_rect r,
14086     const struct nk_input *i, enum nk_button_behavior behavior)
14087 {
14088     int ret = 0;
14089     nk_widget_state_reset(state);
14090     if (!i) return 0;
14091     if (nk_input_is_mouse_hovering_rect(i, r)) {
14092         *state = NK_WIDGET_STATE_HOVERED;
14093         if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT))
14094             *state = NK_WIDGET_STATE_ACTIVE;
14095         if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) {
14096             ret = (behavior != NK_BUTTON_DEFAULT) ?
14097                 nk_input_is_mouse_down(i, NK_BUTTON_LEFT):
14098 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
14099                 nk_input_is_mouse_released(i, NK_BUTTON_LEFT);
14100 #else
14101                 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT);
14102 #endif
14103         }
14104     }
14105     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r))
14106         *state |= NK_WIDGET_STATE_ENTERED;
14107     else if (nk_input_is_mouse_prev_hovering_rect(i, r))
14108         *state |= NK_WIDGET_STATE_LEFT;
14109     return ret;
14110 }
14111 
14112 NK_INTERN const struct nk_style_item*
14113 nk_draw_button(struct nk_command_buffer *out,
14114     const struct nk_rect *bounds, nk_flags state,
14115     const struct nk_style_button *style)
14116 {
14117     const struct nk_style_item *background;
14118     if (state & NK_WIDGET_STATE_HOVER)
14119         background = &style->hover;
14120     else if (state & NK_WIDGET_STATE_ACTIVED)
14121         background = &style->active;
14122     else background = &style->normal;
14123 
14124     if (background->type == NK_STYLE_ITEM_IMAGE) {
14125         nk_draw_image(out, *bounds, &background->data.image, nk_white);
14126     } else {
14127         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14128         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14129     }
14130     return background;
14131 }
14132 
14133 NK_INTERN int
14134 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
14135     const struct nk_style_button *style, const struct nk_input *in,
14136     enum nk_button_behavior behavior, struct nk_rect *content)
14137 {
14138     struct nk_rect bounds;
14139     NK_ASSERT(style);
14140     NK_ASSERT(state);
14141     NK_ASSERT(out);
14142     if (!out || !style)
14143         return nk_false;
14144 
14145     /* calculate button content space */
14146     content->x = r.x + style->padding.x + style->border + style->rounding;
14147     content->y = r.y + style->padding.y + style->border + style->rounding;
14148     content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
14149     content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
14150 
14151     /* execute button behavior */
14152     bounds.x = r.x - style->touch_padding.x;
14153     bounds.y = r.y - style->touch_padding.y;
14154     bounds.w = r.w + 2 * style->touch_padding.x;
14155     bounds.h = r.h + 2 * style->touch_padding.y;
14156     return nk_button_behavior(state, bounds, in, behavior);
14157 }
14158 
14159 NK_INTERN void
14160 nk_draw_button_text(struct nk_command_buffer *out,
14161     const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
14162     const struct nk_style_button *style, const char *txt, int len,
14163     nk_flags text_alignment, const struct nk_user_font *font)
14164 {
14165     struct nk_text text;
14166     const struct nk_style_item *background;
14167     background = nk_draw_button(out, bounds, state, style);
14168 
14169     /* select correct colors/images */
14170     if (background->type == NK_STYLE_ITEM_COLOR)
14171         text.background = background->data.color;
14172     else text.background = style->text_background;
14173     if (state & NK_WIDGET_STATE_HOVER)
14174         text.text = style->text_hover;
14175     else if (state & NK_WIDGET_STATE_ACTIVED)
14176         text.text = style->text_active;
14177     else text.text = style->text_normal;
14178 
14179     text.padding = nk_vec2(0,0);
14180     nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
14181 }
14182 
14183 NK_INTERN int
14184 nk_do_button_text(nk_flags *state,
14185     struct nk_command_buffer *out, struct nk_rect bounds,
14186     const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
14187     const struct nk_style_button *style, const struct nk_input *in,
14188     const struct nk_user_font *font)
14189 {
14190     struct nk_rect content;
14191     int ret = nk_false;
14192 
14193     NK_ASSERT(state);
14194     NK_ASSERT(style);
14195     NK_ASSERT(out);
14196     NK_ASSERT(string);
14197     NK_ASSERT(font);
14198     if (!out || !style || !font || !string)
14199         return nk_false;
14200 
14201     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14202     if (style->draw_begin) style->draw_begin(out, style->userdata);
14203     nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
14204     if (style->draw_end) style->draw_end(out, style->userdata);
14205     return ret;
14206 }
14207 
14208 NK_INTERN void
14209 nk_draw_button_symbol(struct nk_command_buffer *out,
14210     const struct nk_rect *bounds, const struct nk_rect *content,
14211     nk_flags state, const struct nk_style_button *style,
14212     enum nk_symbol_type type, const struct nk_user_font *font)
14213 {
14214     struct nk_color sym, bg;
14215     const struct nk_style_item *background;
14216 
14217     /* select correct colors/images */
14218     background = nk_draw_button(out, bounds, state, style);
14219     if (background->type == NK_STYLE_ITEM_COLOR)
14220         bg = background->data.color;
14221     else bg = style->text_background;
14222 
14223     if (state & NK_WIDGET_STATE_HOVER)
14224         sym = style->text_hover;
14225     else if (state & NK_WIDGET_STATE_ACTIVED)
14226         sym = style->text_active;
14227     else sym = style->text_normal;
14228     nk_draw_symbol(out, type, *content, bg, sym, 1, font);
14229 }
14230 
14231 NK_INTERN int
14232 nk_do_button_symbol(nk_flags *state,
14233     struct nk_command_buffer *out, struct nk_rect bounds,
14234     enum nk_symbol_type symbol, enum nk_button_behavior behavior,
14235     const struct nk_style_button *style, const struct nk_input *in,
14236     const struct nk_user_font *font)
14237 {
14238     int ret;
14239     struct nk_rect content;
14240 
14241     NK_ASSERT(state);
14242     NK_ASSERT(style);
14243     NK_ASSERT(font);
14244     NK_ASSERT(out);
14245     if (!out || !style || !font || !state)
14246         return nk_false;
14247 
14248     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14249     if (style->draw_begin) style->draw_begin(out, style->userdata);
14250     nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
14251     if (style->draw_end) style->draw_end(out, style->userdata);
14252     return ret;
14253 }
14254 
14255 NK_INTERN void
14256 nk_draw_button_image(struct nk_command_buffer *out,
14257     const struct nk_rect *bounds, const struct nk_rect *content,
14258     nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
14259 {
14260     nk_draw_button(out, bounds, state, style);
14261     nk_draw_image(out, *content, img, nk_white);
14262 }
14263 
14264 NK_INTERN int
14265 nk_do_button_image(nk_flags *state,
14266     struct nk_command_buffer *out, struct nk_rect bounds,
14267     struct nk_image img, enum nk_button_behavior b,
14268     const struct nk_style_button *style, const struct nk_input *in)
14269 {
14270     int ret;
14271     struct nk_rect content;
14272 
14273     NK_ASSERT(state);
14274     NK_ASSERT(style);
14275     NK_ASSERT(out);
14276     if (!out || !style || !state)
14277         return nk_false;
14278 
14279     ret = nk_do_button(state, out, bounds, style, in, b, &content);
14280     content.x += style->image_padding.x;
14281     content.y += style->image_padding.y;
14282     content.w -= 2 * style->image_padding.x;
14283     content.h -= 2 * style->image_padding.y;
14284 
14285     if (style->draw_begin) style->draw_begin(out, style->userdata);
14286     nk_draw_button_image(out, &bounds, &content, *state, style, &img);
14287     if (style->draw_end) style->draw_end(out, style->userdata);
14288     return ret;
14289 }
14290 
14291 NK_INTERN void
14292 nk_draw_button_text_symbol(struct nk_command_buffer *out,
14293     const struct nk_rect *bounds, const struct nk_rect *label,
14294     const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
14295     const char *str, int len, enum nk_symbol_type type,
14296     const struct nk_user_font *font)
14297 {
14298     struct nk_color sym;
14299     struct nk_text text;
14300     const struct nk_style_item *background;
14301 
14302     /* select correct background colors/images */
14303     background = nk_draw_button(out, bounds, state, style);
14304     if (background->type == NK_STYLE_ITEM_COLOR)
14305         text.background = background->data.color;
14306     else text.background = style->text_background;
14307 
14308     /* select correct text colors */
14309     if (state & NK_WIDGET_STATE_HOVER) {
14310         sym = style->text_hover;
14311         text.text = style->text_hover;
14312     } else if (state & NK_WIDGET_STATE_ACTIVED) {
14313         sym = style->text_active;
14314         text.text = style->text_active;
14315     } else {
14316         sym = style->text_normal;
14317         text.text = style->text_normal;
14318     }
14319 
14320     text.padding = nk_vec2(0,0);
14321     nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
14322     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14323 }
14324 
14325 NK_INTERN int
14326 nk_do_button_text_symbol(nk_flags *state,
14327     struct nk_command_buffer *out, struct nk_rect bounds,
14328     enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
14329     enum nk_button_behavior behavior, const struct nk_style_button *style,
14330     const struct nk_user_font *font, const struct nk_input *in)
14331 {
14332     int ret;
14333     struct nk_rect tri = {0,0,0,0};
14334     struct nk_rect content;
14335 
14336     NK_ASSERT(style);
14337     NK_ASSERT(out);
14338     NK_ASSERT(font);
14339     if (!out || !style || !font)
14340         return nk_false;
14341 
14342     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14343     tri.y = content.y + (content.h/2) - font->height/2;
14344     tri.w = font->height; tri.h = font->height;
14345     if (align & NK_TEXT_ALIGN_LEFT) {
14346         tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
14347         tri.x = NK_MAX(tri.x, 0);
14348     } else tri.x = content.x + 2 * style->padding.x;
14349 
14350     /* draw button */
14351     if (style->draw_begin) style->draw_begin(out, style->userdata);
14352     nk_draw_button_text_symbol(out, &bounds, &content, &tri,
14353         *state, style, str, len, symbol, font);
14354     if (style->draw_end) style->draw_end(out, style->userdata);
14355     return ret;
14356 }
14357 
14358 NK_INTERN void
14359 nk_draw_button_text_image(struct nk_command_buffer *out,
14360     const struct nk_rect *bounds, const struct nk_rect *label,
14361     const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
14362     const char *str, int len, const struct nk_user_font *font,
14363     const struct nk_image *img)
14364 {
14365     struct nk_text text;
14366     const struct nk_style_item *background;
14367     background = nk_draw_button(out, bounds, state, style);
14368 
14369     /* select correct colors */
14370     if (background->type == NK_STYLE_ITEM_COLOR)
14371         text.background = background->data.color;
14372     else text.background = style->text_background;
14373     if (state & NK_WIDGET_STATE_HOVER)
14374         text.text = style->text_hover;
14375     else if (state & NK_WIDGET_STATE_ACTIVED)
14376         text.text = style->text_active;
14377     else text.text = style->text_normal;
14378 
14379     text.padding = nk_vec2(0,0);
14380     nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14381     nk_draw_image(out, *image, img, nk_white);
14382 }
14383 
14384 NK_INTERN int
14385 nk_do_button_text_image(nk_flags *state,
14386     struct nk_command_buffer *out, struct nk_rect bounds,
14387     struct nk_image img, const char* str, int len, nk_flags align,
14388     enum nk_button_behavior behavior, const struct nk_style_button *style,
14389     const struct nk_user_font *font, const struct nk_input *in)
14390 {
14391     int ret;
14392     struct nk_rect icon;
14393     struct nk_rect content;
14394 
14395     NK_ASSERT(style);
14396     NK_ASSERT(state);
14397     NK_ASSERT(font);
14398     NK_ASSERT(out);
14399     if (!out || !font || !style || !str)
14400         return nk_false;
14401 
14402     ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14403     icon.y = bounds.y + style->padding.y;
14404     icon.w = icon.h = bounds.h - 2 * style->padding.y;
14405     if (align & NK_TEXT_ALIGN_LEFT) {
14406         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14407         icon.x = NK_MAX(icon.x, 0);
14408     } else icon.x = bounds.x + 2 * style->padding.x;
14409 
14410     icon.x += style->image_padding.x;
14411     icon.y += style->image_padding.y;
14412     icon.w -= 2 * style->image_padding.x;
14413     icon.h -= 2 * style->image_padding.y;
14414 
14415     if (style->draw_begin) style->draw_begin(out, style->userdata);
14416     nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
14417     if (style->draw_end) style->draw_end(out, style->userdata);
14418     return ret;
14419 }
14420 
14421 /* ===============================================================
14422  *
14423  *                          TOGGLE
14424  *
14425  * ===============================================================*/
14426 enum nk_toggle_type {
14427     NK_TOGGLE_CHECK,
14428     NK_TOGGLE_OPTION
14429 };
14430 
14431 NK_INTERN int
14432 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
14433     nk_flags *state, int active)
14434 {
14435     nk_widget_state_reset(state);
14436     if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
14437         *state = NK_WIDGET_STATE_ACTIVE;
14438         active = !active;
14439     }
14440     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
14441         *state |= NK_WIDGET_STATE_ENTERED;
14442     else if (nk_input_is_mouse_prev_hovering_rect(in, select))
14443         *state |= NK_WIDGET_STATE_LEFT;
14444     return active;
14445 }
14446 
14447 NK_INTERN void
14448 nk_draw_checkbox(struct nk_command_buffer *out,
14449     nk_flags state, const struct nk_style_toggle *style, int active,
14450     const struct nk_rect *label, const struct nk_rect *selector,
14451     const struct nk_rect *cursors, const char *string, int len,
14452     const struct nk_user_font *font)
14453 {
14454     const struct nk_style_item *background;
14455     const struct nk_style_item *cursor;
14456     struct nk_text text;
14457 
14458     /* select correct colors/images */
14459     if (state & NK_WIDGET_STATE_HOVER) {
14460         background = &style->hover;
14461         cursor = &style->cursor_hover;
14462         text.text = style->text_hover;
14463     } else if (state & NK_WIDGET_STATE_ACTIVED) {
14464         background = &style->hover;
14465         cursor = &style->cursor_hover;
14466         text.text = style->text_active;
14467     } else {
14468         background = &style->normal;
14469         cursor = &style->cursor_normal;
14470         text.text = style->text_normal;
14471     }
14472 
14473     /* draw background and cursor */
14474     if (background->type == NK_STYLE_ITEM_COLOR) {
14475         nk_fill_rect(out, *selector, 0, style->border_color);
14476         nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
14477     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14478     if (active) {
14479         if (cursor->type == NK_STYLE_ITEM_IMAGE)
14480             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14481         else nk_fill_rect(out, *cursors, 0, cursor->data.color);
14482     }
14483 
14484     text.padding.x = 0;
14485     text.padding.y = 0;
14486     text.background = style->text_background;
14487     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14488 }
14489 
14490 NK_INTERN void
14491 nk_draw_option(struct nk_command_buffer *out,
14492     nk_flags state, const struct nk_style_toggle *style, int active,
14493     const struct nk_rect *label, const struct nk_rect *selector,
14494     const struct nk_rect *cursors, const char *string, int len,
14495     const struct nk_user_font *font)
14496 {
14497     const struct nk_style_item *background;
14498     const struct nk_style_item *cursor;
14499     struct nk_text text;
14500 
14501     /* select correct colors/images */
14502     if (state & NK_WIDGET_STATE_HOVER) {
14503         background = &style->hover;
14504         cursor = &style->cursor_hover;
14505         text.text = style->text_hover;
14506     } else if (state & NK_WIDGET_STATE_ACTIVED) {
14507         background = &style->hover;
14508         cursor = &style->cursor_hover;
14509         text.text = style->text_active;
14510     } else {
14511         background = &style->normal;
14512         cursor = &style->cursor_normal;
14513         text.text = style->text_normal;
14514     }
14515 
14516     /* draw background and cursor */
14517     if (background->type == NK_STYLE_ITEM_COLOR) {
14518         nk_fill_circle(out, *selector, style->border_color);
14519         nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
14520     } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14521     if (active) {
14522         if (cursor->type == NK_STYLE_ITEM_IMAGE)
14523             nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14524         else nk_fill_circle(out, *cursors, cursor->data.color);
14525     }
14526 
14527     text.padding.x = 0;
14528     text.padding.y = 0;
14529     text.background = style->text_background;
14530     nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14531 }
14532 
14533 NK_INTERN int
14534 nk_do_toggle(nk_flags *state,
14535     struct nk_command_buffer *out, struct nk_rect r,
14536     int *active, const char *str, int len, enum nk_toggle_type type,
14537     const struct nk_style_toggle *style, const struct nk_input *in,
14538     const struct nk_user_font *font)
14539 {
14540     int was_active;
14541     struct nk_rect bounds;
14542     struct nk_rect select;
14543     struct nk_rect cursor;
14544     struct nk_rect label;
14545 
14546     NK_ASSERT(style);
14547     NK_ASSERT(out);
14548     NK_ASSERT(font);
14549     if (!out || !style || !font || !active)
14550         return 0;
14551 
14552     r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
14553     r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
14554 
14555     /* add additional touch padding for touch screen devices */
14556     bounds.x = r.x - style->touch_padding.x;
14557     bounds.y = r.y - style->touch_padding.y;
14558     bounds.w = r.w + 2 * style->touch_padding.x;
14559     bounds.h = r.h + 2 * style->touch_padding.y;
14560 
14561     /* calculate the selector space */
14562     select.w = font->height;
14563     select.h = select.w;
14564     select.y = r.y + r.h/2.0f - select.h/2.0f;
14565     select.x = r.x;
14566 
14567     /* calculate the bounds of the cursor inside the selector */
14568     cursor.x = select.x + style->padding.x + style->border;
14569     cursor.y = select.y + style->padding.y + style->border;
14570     cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
14571     cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
14572 
14573     /* label behind the selector */
14574     label.x = select.x + select.w + style->spacing;
14575     label.y = select.y;
14576     label.w = NK_MAX(r.x + r.w, label.x) - label.x;
14577     label.h = select.w;
14578 
14579     /* update selector */
14580     was_active = *active;
14581     *active = nk_toggle_behavior(in, bounds, state, *active);
14582 
14583     /* draw selector */
14584     if (style->draw_begin)
14585         style->draw_begin(out, style->userdata);
14586     if (type == NK_TOGGLE_CHECK) {
14587         nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14588     } else {
14589         nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14590     }
14591     if (style->draw_end)
14592         style->draw_end(out, style->userdata);
14593     return (was_active != *active);
14594 }
14595 
14596 /* ===============================================================
14597  *
14598  *                          SELECTABLE
14599  *
14600  * ===============================================================*/
14601 NK_INTERN void
14602 nk_draw_selectable(struct nk_command_buffer *out,
14603     nk_flags state, const struct nk_style_selectable *style, int active,
14604     const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img,
14605     const char *string, int len, nk_flags align, const struct nk_user_font *font)
14606 {
14607     const struct nk_style_item *background;
14608     struct nk_text text;
14609     text.padding = style->padding;
14610 
14611     /* select correct colors/images */
14612     if (!active) {
14613         if (state & NK_WIDGET_STATE_ACTIVED) {
14614             background = &style->pressed;
14615             text.text = style->text_pressed;
14616         } else if (state & NK_WIDGET_STATE_HOVER) {
14617             background = &style->hover;
14618             text.text = style->text_hover;
14619         } else {
14620             background = &style->normal;
14621             text.text = style->text_normal;
14622         }
14623     } else {
14624         if (state & NK_WIDGET_STATE_ACTIVED) {
14625             background = &style->pressed_active;
14626             text.text = style->text_pressed_active;
14627         } else if (state & NK_WIDGET_STATE_HOVER) {
14628             background = &style->hover_active;
14629             text.text = style->text_hover_active;
14630         } else {
14631             background = &style->normal_active;
14632             text.text = style->text_normal_active;
14633         }
14634     }
14635 
14636 
14637     /* draw selectable background and text */
14638     if (background->type == NK_STYLE_ITEM_IMAGE) {
14639         nk_draw_image(out, *bounds, &background->data.image, nk_white);
14640         text.background = nk_rgba(0,0,0,0);
14641     } else {
14642         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14643         text.background = background->data.color;
14644     }
14645     if (img && icon) nk_draw_image(out, *icon, img, nk_white);
14646     nk_widget_text(out, *bounds, string, len, &text, align, font);
14647 }
14648 
14649 NK_INTERN int
14650 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
14651     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14652     const struct nk_style_selectable *style, const struct nk_input *in,
14653     const struct nk_user_font *font)
14654 {
14655     int old_value;
14656     struct nk_rect touch;
14657 
14658     NK_ASSERT(state);
14659     NK_ASSERT(out);
14660     NK_ASSERT(str);
14661     NK_ASSERT(len);
14662     NK_ASSERT(value);
14663     NK_ASSERT(style);
14664     NK_ASSERT(font);
14665 
14666     if (!state || !out || !str || !len || !value || !style || !font) return 0;
14667     old_value = *value;
14668 
14669     /* remove padding */
14670     touch.x = bounds.x - style->touch_padding.x;
14671     touch.y = bounds.y - style->touch_padding.y;
14672     touch.w = bounds.w + style->touch_padding.x * 2;
14673     touch.h = bounds.h + style->touch_padding.y * 2;
14674 
14675     /* update button */
14676     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
14677         *value = !(*value);
14678 
14679     /* draw selectable */
14680     if (style->draw_begin) style->draw_begin(out, style->userdata);
14681     nk_draw_selectable(out, *state, style, *value, &bounds, 0,0, str, len, align, font);
14682     if (style->draw_end) style->draw_end(out, style->userdata);
14683     return old_value != *value;
14684 }
14685 
14686 NK_INTERN int
14687 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
14688     struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14689     const struct nk_image *img, const struct nk_style_selectable *style,
14690     const struct nk_input *in, const struct nk_user_font *font)
14691 {
14692     int old_value;
14693     struct nk_rect touch;
14694     struct nk_rect icon;
14695 
14696     NK_ASSERT(state);
14697     NK_ASSERT(out);
14698     NK_ASSERT(str);
14699     NK_ASSERT(len);
14700     NK_ASSERT(value);
14701     NK_ASSERT(style);
14702     NK_ASSERT(font);
14703 
14704     if (!state || !out || !str || !len || !value || !style || !font) return 0;
14705     old_value = *value;
14706 
14707     /* toggle behavior */
14708     touch.x = bounds.x - style->touch_padding.x;
14709     touch.y = bounds.y - style->touch_padding.y;
14710     touch.w = bounds.w + style->touch_padding.x * 2;
14711     touch.h = bounds.h + style->touch_padding.y * 2;
14712     if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
14713         *value = !(*value);
14714 
14715     icon.y = bounds.y + style->padding.y;
14716     icon.w = icon.h = bounds.h - 2 * style->padding.y;
14717     if (align & NK_TEXT_ALIGN_LEFT) {
14718         icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14719         icon.x = NK_MAX(icon.x, 0);
14720     } else icon.x = bounds.x + 2 * style->padding.x;
14721 
14722     icon.x += style->image_padding.x;
14723     icon.y += style->image_padding.y;
14724     icon.w -= 2 * style->image_padding.x;
14725     icon.h -= 2 * style->image_padding.y;
14726 
14727     /* draw selectable */
14728     if (style->draw_begin) style->draw_begin(out, style->userdata);
14729     nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, str, len, align, font);
14730     if (style->draw_end) style->draw_end(out, style->userdata);
14731     return old_value != *value;
14732 }
14733 
14734 
14735 /* ===============================================================
14736  *
14737  *                          SLIDER
14738  *
14739  * ===============================================================*/
14740 NK_INTERN float
14741 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
14742     struct nk_rect *visual_cursor, struct nk_input *in,
14743     struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
14744     float slider_step, float slider_steps)
14745 {
14746     int left_mouse_down;
14747     int left_mouse_click_in_cursor;
14748 
14749     /* check if visual cursor is being dragged */
14750     nk_widget_state_reset(state);
14751     left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
14752     left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
14753             NK_BUTTON_LEFT, *visual_cursor, nk_true);
14754 
14755     if (left_mouse_down && left_mouse_click_in_cursor)
14756     {
14757         float ratio = 0;
14758         const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
14759         const float pxstep = bounds.w / slider_steps;
14760 
14761         /* only update value if the next slider step is reached */
14762         *state = NK_WIDGET_STATE_ACTIVE;
14763         if (NK_ABS(d) >= pxstep) {
14764             const float steps = (float)((int)(NK_ABS(d) / pxstep));
14765             slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
14766             slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
14767             ratio = (slider_value - slider_min)/slider_step;
14768             logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
14769             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
14770         }
14771     }
14772 
14773     /* slider widget state */
14774     if (nk_input_is_mouse_hovering_rect(in, bounds))
14775         *state = NK_WIDGET_STATE_HOVERED;
14776     if (*state & NK_WIDGET_STATE_HOVER &&
14777         !nk_input_is_mouse_prev_hovering_rect(in, bounds))
14778         *state |= NK_WIDGET_STATE_ENTERED;
14779     else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
14780         *state |= NK_WIDGET_STATE_LEFT;
14781     return slider_value;
14782 }
14783 
14784 NK_INTERN void
14785 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
14786     const struct nk_style_slider *style, const struct nk_rect *bounds,
14787     const struct nk_rect *visual_cursor, float min, float value, float max)
14788 {
14789     struct nk_rect fill;
14790     struct nk_rect bar;
14791     const struct nk_style_item *background;
14792 
14793     /* select correct slider images/colors */
14794     struct nk_color bar_color;
14795     const struct nk_style_item *cursor;
14796 
14797     NK_UNUSED(min);
14798     NK_UNUSED(max);
14799     NK_UNUSED(value);
14800 
14801     if (state & NK_WIDGET_STATE_ACTIVED) {
14802         background = &style->active;
14803         bar_color = style->bar_active;
14804         cursor = &style->cursor_active;
14805     } else if (state & NK_WIDGET_STATE_HOVER) {
14806         background = &style->hover;
14807         bar_color = style->bar_hover;
14808         cursor = &style->cursor_hover;
14809     } else {
14810         background = &style->normal;
14811         bar_color = style->bar_normal;
14812         cursor = &style->cursor_normal;
14813     }
14814 
14815     /* calculate slider background bar */
14816     bar.x = bounds->x;
14817     bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
14818     bar.w = bounds->w;
14819     bar.h = bounds->h/6;
14820 
14821     /* filled background bar style */
14822     fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
14823     fill.x = bar.x;
14824     fill.y = bar.y;
14825     fill.h = bar.h;
14826 
14827     /* draw background */
14828     if (background->type == NK_STYLE_ITEM_IMAGE) {
14829         nk_draw_image(out, *bounds, &background->data.image, nk_white);
14830     } else {
14831         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14832         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14833     }
14834 
14835     /* draw slider bar */
14836     nk_fill_rect(out, bar, style->rounding, bar_color);
14837     nk_fill_rect(out, fill, style->rounding, style->bar_filled);
14838 
14839     /* draw cursor */
14840     if (cursor->type == NK_STYLE_ITEM_IMAGE)
14841         nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
14842     else nk_fill_circle(out, *visual_cursor, cursor->data.color);
14843 }
14844 
14845 NK_INTERN float
14846 nk_do_slider(nk_flags *state,
14847     struct nk_command_buffer *out, struct nk_rect bounds,
14848     float min, float val, float max, float step,
14849     const struct nk_style_slider *style, struct nk_input *in,
14850     const struct nk_user_font *font)
14851 {
14852     float slider_range;
14853     float slider_min;
14854     float slider_max;
14855     float slider_value;
14856     float slider_steps;
14857     float cursor_offset;
14858 
14859     struct nk_rect visual_cursor;
14860     struct nk_rect logical_cursor;
14861 
14862     NK_ASSERT(style);
14863     NK_ASSERT(out);
14864     if (!out || !style)
14865         return 0;
14866 
14867     /* remove padding from slider bounds */
14868     bounds.x = bounds.x + style->padding.x;
14869     bounds.y = bounds.y + style->padding.y;
14870     bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
14871     bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
14872     bounds.w -= 2 * style->padding.x;
14873     bounds.h -= 2 * style->padding.y;
14874 
14875     /* optional buttons */
14876     if (style->show_buttons) {
14877         nk_flags ws;
14878         struct nk_rect button;
14879         button.y = bounds.y;
14880         button.w = bounds.h;
14881         button.h = bounds.h;
14882 
14883         /* decrement button */
14884         button.x = bounds.x;
14885         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
14886             &style->dec_button, in, font))
14887             val -= step;
14888 
14889         /* increment button */
14890         button.x = (bounds.x + bounds.w) - button.w;
14891         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
14892             &style->inc_button, in, font))
14893             val += step;
14894 
14895         bounds.x = bounds.x + button.w + style->spacing.x;
14896         bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
14897     }
14898 
14899     /* remove one cursor size to support visual cursor */
14900     bounds.x += style->cursor_size.x*0.5f;
14901     bounds.w -= style->cursor_size.x;
14902 
14903     /* make sure the provided values are correct */
14904     slider_max = NK_MAX(min, max);
14905     slider_min = NK_MIN(min, max);
14906     slider_value = NK_CLAMP(slider_min, val, slider_max);
14907     slider_range = slider_max - slider_min;
14908     slider_steps = slider_range / step;
14909     cursor_offset = (slider_value - slider_min) / step;
14910 
14911     /* calculate cursor
14912     Basically you have two cursors. One for visual representation and interaction
14913     and one for updating the actual cursor value. */
14914     logical_cursor.h = bounds.h;
14915     logical_cursor.w = bounds.w / slider_steps;
14916     logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
14917     logical_cursor.y = bounds.y;
14918 
14919     visual_cursor.h = style->cursor_size.y;
14920     visual_cursor.w = style->cursor_size.x;
14921     visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
14922     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14923 
14924     slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
14925         in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
14926     visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14927 
14928     /* draw slider */
14929     if (style->draw_begin) style->draw_begin(out, style->userdata);
14930     nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
14931     if (style->draw_end) style->draw_end(out, style->userdata);
14932     return slider_value;
14933 }
14934 
14935 /* ===============================================================
14936  *
14937  *                          PROGRESSBAR
14938  *
14939  * ===============================================================*/
14940 NK_INTERN nk_size
14941 nk_progress_behavior(nk_flags *state, const struct nk_input *in,
14942     struct nk_rect r, nk_size max, nk_size value, int modifiable)
14943 {
14944     nk_widget_state_reset(state);
14945     if (in && modifiable && nk_input_is_mouse_hovering_rect(in, r)) {
14946         int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
14947         int left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
14948             NK_BUTTON_LEFT, r, nk_true);
14949 
14950         if (left_mouse_down && left_mouse_click_in_cursor) {
14951             float ratio = NK_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w;
14952             value = (nk_size)NK_MAX(0,((float)max * ratio));
14953             *state = NK_WIDGET_STATE_ACTIVE;
14954         } else *state = NK_WIDGET_STATE_HOVERED;
14955     }
14956 
14957     /* set progressbar widget state */
14958     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
14959         *state |= NK_WIDGET_STATE_ENTERED;
14960     else if (nk_input_is_mouse_prev_hovering_rect(in, r))
14961         *state |= NK_WIDGET_STATE_LEFT;
14962 
14963     if (!max) return value;
14964     value = NK_MIN(value, max);
14965     return value;
14966 }
14967 
14968 NK_INTERN void
14969 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
14970     const struct nk_style_progress *style, const struct nk_rect *bounds,
14971     const struct nk_rect *scursor, nk_size value, nk_size max)
14972 {
14973     const struct nk_style_item *background;
14974     const struct nk_style_item *cursor;
14975 
14976     NK_UNUSED(max);
14977     NK_UNUSED(value);
14978 
14979     /* select correct colors/images to draw */
14980     if (state & NK_WIDGET_STATE_ACTIVED) {
14981         background = &style->active;
14982         cursor = &style->cursor_active;
14983     } else if (state & NK_WIDGET_STATE_HOVER){
14984         background = &style->hover;
14985         cursor = &style->cursor_hover;
14986     } else {
14987         background = &style->normal;
14988         cursor = &style->cursor_normal;
14989     }
14990 
14991     /* draw background */
14992     if (background->type == NK_STYLE_ITEM_COLOR) {
14993         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14994         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14995     } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
14996 
14997     /* draw cursor */
14998     if (cursor->type == NK_STYLE_ITEM_COLOR) {
14999         nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
15000         nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
15001     } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
15002 }
15003 
15004 NK_INTERN nk_size
15005 nk_do_progress(nk_flags *state,
15006     struct nk_command_buffer *out, struct nk_rect bounds,
15007     nk_size value, nk_size max, int modifiable,
15008     const struct nk_style_progress *style, const struct nk_input *in)
15009 {
15010     float prog_scale;
15011     nk_size prog_value;
15012     struct nk_rect cursor;
15013 
15014     NK_ASSERT(style);
15015     NK_ASSERT(out);
15016     if (!out || !style) return 0;
15017 
15018     /* calculate progressbar cursor */
15019     cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
15020     cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
15021     cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
15022     prog_scale = (float)value / (float)max;
15023     cursor.w = (bounds.w - 2) * prog_scale;
15024 
15025     /* update progressbar */
15026     prog_value = NK_MIN(value, max);
15027     prog_value = nk_progress_behavior(state, in, bounds, max, prog_value, modifiable);
15028 
15029     /* draw progressbar */
15030     if (style->draw_begin) style->draw_begin(out, style->userdata);
15031     nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
15032     if (style->draw_end) style->draw_end(out, style->userdata);
15033     return prog_value;
15034 }
15035 
15036 /* ===============================================================
15037  *
15038  *                          SCROLLBAR
15039  *
15040  * ===============================================================*/
15041 NK_INTERN float
15042 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
15043     int has_scrolling, const struct nk_rect *scroll,
15044     const struct nk_rect *cursor, const struct nk_rect *empty0,
15045     const struct nk_rect *empty1, float scroll_offset,
15046     float target, float scroll_step, enum nk_orientation o)
15047 {
15048     nk_flags ws = 0;
15049     int left_mouse_down;
15050     int left_mouse_click_in_cursor;
15051     float scroll_delta;
15052 
15053     nk_widget_state_reset(state);
15054     if (!in) return scroll_offset;
15055 
15056     left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
15057     left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
15058         NK_BUTTON_LEFT, *cursor, nk_true);
15059     if (nk_input_is_mouse_hovering_rect(in, *scroll))
15060         *state = NK_WIDGET_STATE_HOVERED;
15061 
15062     scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
15063     if (left_mouse_down && left_mouse_click_in_cursor) {
15064         /* update cursor by mouse dragging */
15065         float pixel, delta;
15066         *state = NK_WIDGET_STATE_ACTIVE;
15067         if (o == NK_VERTICAL) {
15068             float cursor_y;
15069             pixel = in->mouse.delta.y;
15070             delta = (pixel / scroll->h) * target;
15071             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
15072             cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
15073             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
15074         } else {
15075             float cursor_x;
15076             pixel = in->mouse.delta.x;
15077             delta = (pixel / scroll->w) * target;
15078             scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
15079             cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
15080             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
15081         }
15082     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
15083             nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
15084         /* scroll page up by click on empty space or shortcut */
15085         if (o == NK_VERTICAL)
15086             scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
15087         else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
15088     } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
15089         nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
15090         /* scroll page down by click on empty space or shortcut */
15091         if (o == NK_VERTICAL)
15092             scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
15093         else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
15094     } else if (has_scrolling) {
15095         if ((scroll_delta < 0 || (scroll_delta > 0))) {
15096             /* update cursor by mouse scrolling */
15097             scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
15098             if (o == NK_VERTICAL)
15099                 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
15100             else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
15101         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
15102             /* update cursor to the beginning  */
15103             if (o == NK_VERTICAL) scroll_offset = 0;
15104         } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
15105             /* update cursor to the end */
15106             if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
15107         }
15108     }
15109     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
15110         *state |= NK_WIDGET_STATE_ENTERED;
15111     else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
15112         *state |= NK_WIDGET_STATE_LEFT;
15113     return scroll_offset;
15114 }
15115 
15116 NK_INTERN void
15117 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
15118     const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
15119     const struct nk_rect *scroll)
15120 {
15121     const struct nk_style_item *background;
15122     const struct nk_style_item *cursor;
15123 
15124     /* select correct colors/images to draw */
15125     if (state & NK_WIDGET_STATE_ACTIVED) {
15126         background = &style->active;
15127         cursor = &style->cursor_active;
15128     } else if (state & NK_WIDGET_STATE_HOVER) {
15129         background = &style->hover;
15130         cursor = &style->cursor_hover;
15131     } else {
15132         background = &style->normal;
15133         cursor = &style->cursor_normal;
15134     }
15135 
15136     /* draw background */
15137     if (background->type == NK_STYLE_ITEM_COLOR) {
15138         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
15139         nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
15140     } else {
15141         nk_draw_image(out, *bounds, &background->data.image, nk_white);
15142     }
15143 
15144     /* draw cursor */
15145     if (background->type == NK_STYLE_ITEM_COLOR) {
15146         nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
15147         nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
15148     } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
15149 }
15150 
15151 NK_INTERN float
15152 nk_do_scrollbarv(nk_flags *state,
15153     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
15154     float offset, float target, float step, float button_pixel_inc,
15155     const struct nk_style_scrollbar *style, struct nk_input *in,
15156     const struct nk_user_font *font)
15157 {
15158     struct nk_rect empty_north;
15159     struct nk_rect empty_south;
15160     struct nk_rect cursor;
15161 
15162     float scroll_step;
15163     float scroll_offset;
15164     float scroll_off;
15165     float scroll_ratio;
15166 
15167     NK_ASSERT(out);
15168     NK_ASSERT(style);
15169     NK_ASSERT(state);
15170     if (!out || !style) return 0;
15171 
15172     scroll.w = NK_MAX(scroll.w, 1);
15173     scroll.h = NK_MAX(scroll.h, 0);
15174     if (target <= scroll.h) return 0;
15175 
15176     /* optional scrollbar buttons */
15177     if (style->show_buttons) {
15178         nk_flags ws;
15179         float scroll_h;
15180         struct nk_rect button;
15181 
15182         button.x = scroll.x;
15183         button.w = scroll.w;
15184         button.h = scroll.w;
15185 
15186         scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
15187         scroll_step = NK_MIN(step, button_pixel_inc);
15188 
15189         /* decrement button */
15190         button.y = scroll.y;
15191         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
15192             NK_BUTTON_REPEATER, &style->dec_button, in, font))
15193             offset = offset - scroll_step;
15194 
15195         /* increment button */
15196         button.y = scroll.y + scroll.h - button.h;
15197         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
15198             NK_BUTTON_REPEATER, &style->inc_button, in, font))
15199             offset = offset + scroll_step;
15200 
15201         scroll.y = scroll.y + button.h;
15202         scroll.h = scroll_h;
15203     }
15204 
15205     /* calculate scrollbar constants */
15206     scroll_step = NK_MIN(step, scroll.h);
15207     scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
15208     scroll_ratio = scroll.h / target;
15209     scroll_off = scroll_offset / target;
15210 
15211     /* calculate scrollbar cursor bounds */
15212     cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
15213     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
15214     cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
15215     cursor.x = scroll.x + style->border + style->padding.x;
15216 
15217     /* calculate empty space around cursor */
15218     empty_north.x = scroll.x;
15219     empty_north.y = scroll.y;
15220     empty_north.w = scroll.w;
15221     empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
15222 
15223     empty_south.x = scroll.x;
15224     empty_south.y = cursor.y + cursor.h;
15225     empty_south.w = scroll.w;
15226     empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
15227 
15228     /* update scrollbar */
15229     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
15230         &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
15231     scroll_off = scroll_offset / target;
15232     cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
15233 
15234     /* draw scrollbar */
15235     if (style->draw_begin) style->draw_begin(out, style->userdata);
15236     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15237     if (style->draw_end) style->draw_end(out, style->userdata);
15238     return scroll_offset;
15239 }
15240 
15241 NK_INTERN float
15242 nk_do_scrollbarh(nk_flags *state,
15243     struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
15244     float offset, float target, float step, float button_pixel_inc,
15245     const struct nk_style_scrollbar *style, struct nk_input *in,
15246     const struct nk_user_font *font)
15247 {
15248     struct nk_rect cursor;
15249     struct nk_rect empty_west;
15250     struct nk_rect empty_east;
15251 
15252     float scroll_step;
15253     float scroll_offset;
15254     float scroll_off;
15255     float scroll_ratio;
15256 
15257     NK_ASSERT(out);
15258     NK_ASSERT(style);
15259     if (!out || !style) return 0;
15260 
15261     /* scrollbar background */
15262     scroll.h = NK_MAX(scroll.h, 1);
15263     scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
15264     if (target <= scroll.w) return 0;
15265 
15266     /* optional scrollbar buttons */
15267     if (style->show_buttons) {
15268         nk_flags ws;
15269         float scroll_w;
15270         struct nk_rect button;
15271         button.y = scroll.y;
15272         button.w = scroll.h;
15273         button.h = scroll.h;
15274 
15275         scroll_w = scroll.w - 2 * button.w;
15276         scroll_step = NK_MIN(step, button_pixel_inc);
15277 
15278         /* decrement button */
15279         button.x = scroll.x;
15280         if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
15281             NK_BUTTON_REPEATER, &style->dec_button, in, font))
15282             offset = offset - scroll_step;
15283 
15284         /* increment button */
15285         button.x = scroll.x + scroll.w - button.w;
15286         if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
15287             NK_BUTTON_REPEATER, &style->inc_button, in, font))
15288             offset = offset + scroll_step;
15289 
15290         scroll.x = scroll.x + button.w;
15291         scroll.w = scroll_w;
15292     }
15293 
15294     /* calculate scrollbar constants */
15295     scroll_step = NK_MIN(step, scroll.w);
15296     scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
15297     scroll_ratio = scroll.w / target;
15298     scroll_off = scroll_offset / target;
15299 
15300     /* calculate cursor bounds */
15301     cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
15302     cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
15303     cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
15304     cursor.y = scroll.y + style->border + style->padding.y;
15305 
15306     /* calculate empty space around cursor */
15307     empty_west.x = scroll.x;
15308     empty_west.y = scroll.y;
15309     empty_west.w = cursor.x - scroll.x;
15310     empty_west.h = scroll.h;
15311 
15312     empty_east.x = cursor.x + cursor.w;
15313     empty_east.y = scroll.y;
15314     empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
15315     empty_east.h = scroll.h;
15316 
15317     /* update scrollbar */
15318     scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
15319         &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
15320     scroll_off = scroll_offset / target;
15321     cursor.x = scroll.x + (scroll_off * scroll.w);
15322 
15323     /* draw scrollbar */
15324     if (style->draw_begin) style->draw_begin(out, style->userdata);
15325     nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15326     if (style->draw_end) style->draw_end(out, style->userdata);
15327     return scroll_offset;
15328 }
15329 
15330 /* ===============================================================
15331  *
15332  *                          FILTER
15333  *
15334  * ===============================================================*/
15335 NK_API int nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
15336 {(void)unicode;NK_UNUSED(box);return nk_true;}
15337 
15338 NK_API int
15339 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
15340 {
15341     NK_UNUSED(box);
15342     if (unicode > 128) return nk_false;
15343     else return nk_true;
15344 }
15345 
15346 NK_API int
15347 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
15348 {
15349     NK_UNUSED(box);
15350     if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
15351         return nk_false;
15352     else return nk_true;
15353 }
15354 
15355 NK_API int
15356 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
15357 {
15358     NK_UNUSED(box);
15359     if ((unicode < '0' || unicode > '9') && unicode != '-')
15360         return nk_false;
15361     else return nk_true;
15362 }
15363 
15364 NK_API int
15365 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
15366 {
15367     NK_UNUSED(box);
15368     if ((unicode < '0' || unicode > '9') &&
15369         (unicode < 'a' || unicode > 'f') &&
15370         (unicode < 'A' || unicode > 'F'))
15371         return nk_false;
15372     else return nk_true;
15373 }
15374 
15375 NK_API int
15376 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
15377 {
15378     NK_UNUSED(box);
15379     if (unicode < '0' || unicode > '7')
15380         return nk_false;
15381     else return nk_true;
15382 }
15383 
15384 NK_API int
15385 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
15386 {
15387     NK_UNUSED(box);
15388     if (unicode != '0' && unicode != '1')
15389         return nk_false;
15390     else return nk_true;
15391 }
15392 
15393 /* ===============================================================
15394  *
15395  *                          EDIT
15396  *
15397  * ===============================================================*/
15398 NK_INTERN void
15399 nk_edit_draw_text(struct nk_command_buffer *out,
15400     const struct nk_style_edit *style, float pos_x, float pos_y,
15401     float x_offset, const char *text, int byte_len, float row_height,
15402     const struct nk_user_font *font, struct nk_color background,
15403     struct nk_color foreground, int is_selected)
15404 {
15405     NK_ASSERT(out);
15406     NK_ASSERT(font);
15407     NK_ASSERT(style);
15408     if (!text || !byte_len || !out || !style) return;
15409 
15410     {int glyph_len = 0;
15411     nk_rune unicode = 0;
15412     int text_len = 0;
15413     float line_width = 0;
15414     float glyph_width;
15415     const char *line = text;
15416     float line_offset = 0;
15417     int line_count = 0;
15418 
15419     struct nk_text txt;
15420     txt.padding = nk_vec2(0,0);
15421     txt.background = background;
15422     txt.text = foreground;
15423 
15424     glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
15425     if (!glyph_len) return;
15426     while ((text_len < byte_len) && glyph_len)
15427     {
15428         if (unicode == '\n') {
15429             /* new line separator so draw previous line */
15430             struct nk_rect label;
15431             label.y = pos_y + line_offset;
15432             label.h = row_height;
15433             label.w = line_width;
15434             label.x = pos_x;
15435             if (!line_count)
15436                 label.x += x_offset;
15437 
15438             if (is_selected) /* selection needs to draw different background color */
15439                 nk_fill_rect(out, label, 0, background);
15440             nk_widget_text(out, label, line, (int)((text + text_len) - line),
15441                 &txt, NK_TEXT_CENTERED, font);
15442 
15443             text_len++;
15444             line_count++;
15445             line_width = 0;
15446             line = text + text_len;
15447             line_offset += row_height;
15448             glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
15449             continue;
15450         }
15451         if (unicode == '\r') {
15452             text_len++;
15453             glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15454             continue;
15455         }
15456         glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15457         line_width += (float)glyph_width;
15458         text_len += glyph_len;
15459         glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15460         continue;
15461     }
15462     if (line_width > 0) {
15463         /* draw last line */
15464         struct nk_rect label;
15465         label.y = pos_y + line_offset;
15466         label.h = row_height;
15467         label.w = line_width;
15468         label.x = pos_x;
15469         if (!line_count)
15470             label.x += x_offset;
15471 
15472         if (is_selected)
15473             nk_fill_rect(out, label, 0, background);
15474         nk_widget_text(out, label, line, (int)((text + text_len) - line),
15475             &txt, NK_TEXT_LEFT, font);
15476     }}
15477 }
15478 
15479 NK_INTERN nk_flags
15480 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
15481     struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
15482     struct nk_text_edit *edit, const struct nk_style_edit *style,
15483     struct nk_input *in, const struct nk_user_font *font)
15484 {
15485     struct nk_rect area;
15486     nk_flags ret = 0;
15487     float row_height;
15488     char prev_state = 0;
15489     char is_hovered = 0;
15490     char select_all = 0;
15491     char cursor_follow = 0;
15492     struct nk_rect old_clip;
15493     struct nk_rect clip;
15494 
15495     NK_ASSERT(state);
15496     NK_ASSERT(out);
15497     NK_ASSERT(style);
15498     if (!state || !out || !style)
15499         return ret;
15500 
15501     /* visible text area calculation */
15502     area.x = bounds.x + style->padding.x + style->border;
15503     area.y = bounds.y + style->padding.y + style->border;
15504     area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
15505     area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
15506     if (flags & NK_EDIT_MULTILINE)
15507         area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
15508     row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
15509 
15510     /* calculate clipping rectangle */
15511     old_clip = out->clip;
15512     nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
15513 
15514     /* update edit state */
15515     prev_state = (char)edit->active;
15516     is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
15517     if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) {
15518         edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
15519                                 bounds.x, bounds.y, bounds.w, bounds.h);
15520     }
15521 
15522     /* (de)activate text editor */
15523     if (!prev_state && edit->active) {
15524         const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
15525             NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE;
15526         nk_textedit_clear_state(edit, type, filter);
15527         if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
15528             edit->mode = NK_TEXT_EDIT_MODE_INSERT;
15529         if (flags & NK_EDIT_AUTO_SELECT)
15530             select_all = nk_true;
15531         if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
15532             edit->cursor = edit->string.len;
15533             in = 0;
15534         }
15535     } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15536     if (flags & NK_EDIT_READ_ONLY)
15537         edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15538 
15539     ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
15540     if (prev_state != edit->active)
15541         ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
15542 
15543     /* handle user input */
15544     if (edit->active && in)
15545     {
15546         int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
15547         const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
15548         const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
15549 
15550         /* mouse click handler */
15551         is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
15552         if (select_all) {
15553             nk_textedit_select_all(edit);
15554         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15555             in->mouse.buttons[NK_BUTTON_LEFT].clicked) {
15556             nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
15557         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15558             (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
15559             nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
15560             cursor_follow = nk_true;
15561         } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
15562             in->mouse.buttons[NK_BUTTON_RIGHT].down) {
15563             nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
15564             nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
15565             cursor_follow = nk_true;
15566         }
15567 
15568         {int i; /* keyboard input */
15569         int old_mode = edit->mode;
15570         for (i = 0; i < NK_KEY_MAX; ++i) {
15571             if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
15572             if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
15573                 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
15574                 cursor_follow = nk_true;
15575             }
15576         }
15577         if (old_mode != edit->mode) {
15578             in->keyboard.text_len = 0;
15579         }}
15580 
15581         /* text input */
15582         edit->filter = filter;
15583         if (in->keyboard.text_len) {
15584             nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
15585             cursor_follow = nk_true;
15586             in->keyboard.text_len = 0;
15587         }
15588 
15589         /* enter key handler */
15590         if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) {
15591             cursor_follow = nk_true;
15592             if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
15593                 nk_textedit_text(edit, "\n", 1);
15594             else if (flags & NK_EDIT_SIG_ENTER)
15595                 ret |= NK_EDIT_COMMITED;
15596             else nk_textedit_text(edit, "\n", 1);
15597         }
15598 
15599         /* cut & copy handler */
15600         {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
15601         int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
15602         if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
15603         {
15604             int glyph_len;
15605             nk_rune unicode;
15606             const char *text;
15607             int b = edit->select_start;
15608             int e = edit->select_end;
15609 
15610             int begin = NK_MIN(b, e);
15611             int end = NK_MAX(b, e);
15612             text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
15613             if (edit->clip.copy)
15614                 edit->clip.copy(edit->clip.userdata, text, end - begin);
15615             if (cut && !(flags & NK_EDIT_READ_ONLY)){
15616                 nk_textedit_cut(edit);
15617                 cursor_follow = nk_true;
15618             }
15619         }}
15620 
15621         /* paste handler */
15622         {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
15623         if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
15624             edit->clip.paste(edit->clip.userdata, edit);
15625             cursor_follow = nk_true;
15626         }}
15627 
15628         /* tab handler */
15629         {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
15630         if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
15631             nk_textedit_text(edit, "    ", 4);
15632             cursor_follow = nk_true;
15633         }}
15634     }
15635 
15636     /* set widget state */
15637     if (edit->active)
15638         *state = NK_WIDGET_STATE_ACTIVE;
15639     else nk_widget_state_reset(state);
15640 
15641     if (is_hovered)
15642         *state |= NK_WIDGET_STATE_HOVERED;
15643 
15644     /* DRAW EDIT */
15645     {const char *text = nk_str_get_const(&edit->string);
15646     int len = nk_str_len_char(&edit->string);
15647 
15648     {/* select background colors/images  */
15649     const struct nk_style_item *background;
15650     if (*state & NK_WIDGET_STATE_ACTIVED)
15651         background = &style->active;
15652     else if (*state & NK_WIDGET_STATE_HOVER)
15653         background = &style->hover;
15654     else background = &style->normal;
15655 
15656     /* draw background frame */
15657     if (background->type == NK_STYLE_ITEM_COLOR) {
15658         nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
15659         nk_fill_rect(out, bounds, style->rounding, background->data.color);
15660     } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
15661 
15662     area.w = NK_MAX(0, area.w - style->cursor_size);
15663     if (edit->active)
15664     {
15665         int total_lines = 1;
15666         struct nk_vec2 text_size = nk_vec2(0,0);
15667 
15668         /* text pointer positions */
15669         const char *cursor_ptr = 0;
15670         const char *select_begin_ptr = 0;
15671         const char *select_end_ptr = 0;
15672 
15673         /* 2D pixel positions */
15674         struct nk_vec2 cursor_pos = nk_vec2(0,0);
15675         struct nk_vec2 selection_offset_start = nk_vec2(0,0);
15676         struct nk_vec2 selection_offset_end = nk_vec2(0,0);
15677 
15678         int selection_begin = NK_MIN(edit->select_start, edit->select_end);
15679         int selection_end = NK_MAX(edit->select_start, edit->select_end);
15680 
15681         /* calculate total line count + total space + cursor/selection position */
15682         float line_width = 0.0f;
15683         if (text && len)
15684         {
15685             /* utf8 encoding */
15686             float glyph_width;
15687             int glyph_len = 0;
15688             nk_rune unicode = 0;
15689             int text_len = 0;
15690             int glyphs = 0;
15691             int row_begin = 0;
15692 
15693             glyph_len = nk_utf_decode(text, &unicode, len);
15694             glyph_width = font->width(font->userdata, font->height, text, glyph_len);
15695             line_width = 0;
15696 
15697             /* iterate all lines */
15698             while ((text_len < len) && glyph_len)
15699             {
15700                 /* set cursor 2D position and line */
15701                 if (!cursor_ptr && glyphs == edit->cursor)
15702                 {
15703                     int glyph_offset;
15704                     struct nk_vec2 out_offset;
15705                     struct nk_vec2 row_size;
15706                     const char *remaining;
15707 
15708                     /* calculate 2d position */
15709                     cursor_pos.y = (float)(total_lines-1) * row_height;
15710                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15711                                 text_len-row_begin, row_height, &remaining,
15712                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15713                     cursor_pos.x = row_size.x;
15714                     cursor_ptr = text + text_len;
15715                 }
15716 
15717                 /* set start selection 2D position and line */
15718                 if (!select_begin_ptr && edit->select_start != edit->select_end &&
15719                     glyphs == selection_begin)
15720                 {
15721                     int glyph_offset;
15722                     struct nk_vec2 out_offset;
15723                     struct nk_vec2 row_size;
15724                     const char *remaining;
15725 
15726                     /* calculate 2d position */
15727                     selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
15728                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15729                                 text_len-row_begin, row_height, &remaining,
15730                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15731                     selection_offset_start.x = row_size.x;
15732                     select_begin_ptr = text + text_len;
15733                 }
15734 
15735                 /* set end selection 2D position and line */
15736                 if (!select_end_ptr && edit->select_start != edit->select_end &&
15737                     glyphs == selection_end)
15738                 {
15739                     int glyph_offset;
15740                     struct nk_vec2 out_offset;
15741                     struct nk_vec2 row_size;
15742                     const char *remaining;
15743 
15744                     /* calculate 2d position */
15745                     selection_offset_end.y = (float)(total_lines-1) * row_height;
15746                     row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15747                                 text_len-row_begin, row_height, &remaining,
15748                                 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15749                     selection_offset_end.x = row_size.x;
15750                     select_end_ptr = text + text_len;
15751                 }
15752                 if (unicode == '\n') {
15753                     text_size.x = NK_MAX(text_size.x, line_width);
15754                     total_lines++;
15755                     line_width = 0;
15756                     text_len++;
15757                     glyphs++;
15758                     row_begin = text_len;
15759                     glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15760                     glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15761                     continue;
15762                 }
15763 
15764                 glyphs++;
15765                 text_len += glyph_len;
15766                 line_width += (float)glyph_width;
15767 
15768                 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15769                 glyph_width = font->width(font->userdata, font->height,
15770                     text+text_len, glyph_len);
15771                 continue;
15772             }
15773             text_size.y = (float)total_lines * row_height;
15774 
15775             /* handle case when cursor is at end of text buffer */
15776             if (!cursor_ptr && edit->cursor == edit->string.len) {
15777                 cursor_pos.x = line_width;
15778                 cursor_pos.y = text_size.y - row_height;
15779             }
15780         }
15781         {
15782             /* scrollbar */
15783             if (cursor_follow)
15784             {
15785                 /* update scrollbar to follow cursor */
15786                 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
15787                     /* horizontal scroll */
15788                     const float scroll_increment = area.w * 0.25f;
15789                     if (cursor_pos.x < edit->scrollbar.x)
15790                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
15791                     if (cursor_pos.x >= edit->scrollbar.x + area.w)
15792                         edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x);
15793                 } else edit->scrollbar.x = 0;
15794 
15795                 if (flags & NK_EDIT_MULTILINE) {
15796                     /* vertical scroll */
15797                     if (cursor_pos.y < edit->scrollbar.y)
15798                         edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
15799                     if (cursor_pos.y >= edit->scrollbar.y + area.h)
15800                         edit->scrollbar.y = edit->scrollbar.y + row_height;
15801                 } else edit->scrollbar.y = 0;
15802             }
15803 
15804             /* scrollbar widget */
15805             if (flags & NK_EDIT_MULTILINE)
15806             {
15807                 nk_flags ws;
15808                 struct nk_rect scroll;
15809                 float scroll_target;
15810                 float scroll_offset;
15811                 float scroll_step;
15812                 float scroll_inc;
15813 
15814                 scroll = area;
15815                 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
15816                 scroll.w = style->scrollbar_size.x;
15817 
15818                 scroll_offset = edit->scrollbar.y;
15819                 scroll_step = scroll.h * 0.10f;
15820                 scroll_inc = scroll.h * 0.01f;
15821                 scroll_target = text_size.y;
15822                 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
15823                         scroll_offset, scroll_target, scroll_step, scroll_inc,
15824                         &style->scrollbar, in, font);
15825             }
15826         }
15827 
15828         /* draw text */
15829         {struct nk_color background_color;
15830         struct nk_color text_color;
15831         struct nk_color sel_background_color;
15832         struct nk_color sel_text_color;
15833         struct nk_color cursor_color;
15834         struct nk_color cursor_text_color;
15835         const struct nk_style_item *background;
15836         nk_push_scissor(out, clip);
15837 
15838         /* select correct colors to draw */
15839         if (*state & NK_WIDGET_STATE_ACTIVED) {
15840             background = &style->active;
15841             text_color = style->text_active;
15842             sel_text_color = style->selected_text_hover;
15843             sel_background_color = style->selected_hover;
15844             cursor_color = style->cursor_hover;
15845             cursor_text_color = style->cursor_text_hover;
15846         } else if (*state & NK_WIDGET_STATE_HOVER) {
15847             background = &style->hover;
15848             text_color = style->text_hover;
15849             sel_text_color = style->selected_text_hover;
15850             sel_background_color = style->selected_hover;
15851             cursor_text_color = style->cursor_text_hover;
15852             cursor_color = style->cursor_hover;
15853         } else {
15854             background = &style->normal;
15855             text_color = style->text_normal;
15856             sel_text_color = style->selected_text_normal;
15857             sel_background_color = style->selected_normal;
15858             cursor_color = style->cursor_normal;
15859             cursor_text_color = style->cursor_text_normal;
15860         }
15861         if (background->type == NK_STYLE_ITEM_IMAGE)
15862             background_color = nk_rgba(0,0,0,0);
15863         else background_color = background->data.color;
15864 
15865 
15866         if (edit->select_start == edit->select_end) {
15867             /* no selection so just draw the complete text */
15868             const char *begin = nk_str_get_const(&edit->string);
15869             int l = nk_str_len_char(&edit->string);
15870             nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15871                 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15872                 background_color, text_color, nk_false);
15873         } else {
15874             /* edit has selection so draw 1-3 text chunks */
15875             if (edit->select_start != edit->select_end && selection_begin > 0){
15876                 /* draw unselected text before selection */
15877                 const char *begin = nk_str_get_const(&edit->string);
15878                 NK_ASSERT(select_begin_ptr);
15879                 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15880                     area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
15881                     row_height, font, background_color, text_color, nk_false);
15882             }
15883             if (edit->select_start != edit->select_end) {
15884                 /* draw selected text */
15885                 NK_ASSERT(select_begin_ptr);
15886                 if (!select_end_ptr) {
15887                     const char *begin = nk_str_get_const(&edit->string);
15888                     select_end_ptr = begin + nk_str_len_char(&edit->string);
15889                 }
15890                 nk_edit_draw_text(out, style,
15891                     area.x - edit->scrollbar.x,
15892                     area.y + selection_offset_start.y - edit->scrollbar.y,
15893                     selection_offset_start.x,
15894                     select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
15895                     row_height, font, sel_background_color, sel_text_color, nk_true);
15896             }
15897             if ((edit->select_start != edit->select_end &&
15898                 selection_end < edit->string.len))
15899             {
15900                 /* draw unselected text after selected text */
15901                 const char *begin = select_end_ptr;
15902                 const char *end = nk_str_get_const(&edit->string) +
15903                                     nk_str_len_char(&edit->string);
15904                 NK_ASSERT(select_end_ptr);
15905                 nk_edit_draw_text(out, style,
15906                     area.x - edit->scrollbar.x,
15907                     area.y + selection_offset_end.y - edit->scrollbar.y,
15908                     selection_offset_end.x,
15909                     begin, (int)(end - begin), row_height, font,
15910                     background_color, text_color, nk_true);
15911             }
15912         }
15913 
15914         /* cursor */
15915         if (edit->select_start == edit->select_end)
15916         {
15917             if (edit->cursor >= nk_str_len(&edit->string) ||
15918                 (cursor_ptr && *cursor_ptr == '\n')) {
15919                 /* draw cursor at end of line */
15920                 struct nk_rect cursor;
15921                 cursor.w = style->cursor_size;
15922                 cursor.h = font->height;
15923                 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
15924                 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
15925                 cursor.y -= edit->scrollbar.y;
15926                 nk_fill_rect(out, cursor, 0, cursor_color);
15927             } else {
15928                 /* draw cursor inside text */
15929                 int glyph_len;
15930                 struct nk_rect label;
15931                 struct nk_text txt;
15932 
15933                 nk_rune unicode;
15934                 NK_ASSERT(cursor_ptr);
15935                 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
15936 
15937                 label.x = area.x + cursor_pos.x - edit->scrollbar.x;
15938                 label.y = area.y + cursor_pos.y - edit->scrollbar.y;
15939                 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
15940                 label.h = row_height;
15941 
15942                 txt.padding = nk_vec2(0,0);
15943                 txt.background = cursor_color;;
15944                 txt.text = cursor_text_color;
15945                 nk_fill_rect(out, label, 0, cursor_color);
15946                 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
15947             }
15948         }}
15949     } else {
15950         /* not active so just draw text */
15951         int l = nk_str_len_char(&edit->string);
15952         const char *begin = nk_str_get_const(&edit->string);
15953 
15954         const struct nk_style_item *background;
15955         struct nk_color background_color;
15956         struct nk_color text_color;
15957         nk_push_scissor(out, clip);
15958         if (*state & NK_WIDGET_STATE_ACTIVED) {
15959             background = &style->active;
15960             text_color = style->text_active;
15961         } else if (*state & NK_WIDGET_STATE_HOVER) {
15962             background = &style->hover;
15963             text_color = style->text_hover;
15964         } else {
15965             background = &style->normal;
15966             text_color = style->text_normal;
15967         }
15968         if (background->type == NK_STYLE_ITEM_IMAGE)
15969             background_color = nk_rgba(0,0,0,0);
15970         else background_color = background->data.color;
15971         nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15972             area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15973             background_color, text_color, nk_false);
15974     }
15975     nk_push_scissor(out, old_clip);}
15976     return ret;
15977 }
15978 
15979 /* ===============================================================
15980  *
15981  *                          PROPERTY
15982  *
15983  * ===============================================================*/
15984 enum nk_property_status {
15985     NK_PROPERTY_DEFAULT,
15986     NK_PROPERTY_EDIT,
15987     NK_PROPERTY_DRAG
15988 };
15989 enum nk_property_filter {
15990     NK_FILTER_INT,
15991     NK_FILTER_FLOAT
15992 };
15993 enum nk_property_kind {
15994     NK_PROPERTY_INT,
15995     NK_PROPERTY_FLOAT,
15996     NK_PROPERTY_DOUBLE
15997 };
15998 union nk_property {
15999     int i;
16000     float f;
16001     double d;
16002 };
16003 struct nk_property_variant {
16004     enum nk_property_kind kind;
16005     union nk_property value;
16006     union nk_property min_value;
16007     union nk_property max_value;
16008     union nk_property step;
16009 };
16010 
16011 NK_INTERN void
16012 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
16013     struct nk_rect drag, struct nk_property_variant *variant,
16014     float inc_per_pixel)
16015 {
16016     int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
16017     int left_mouse_click_in_cursor = in &&
16018         nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true);
16019 
16020     nk_widget_state_reset(state);
16021     if (nk_input_is_mouse_hovering_rect(in, drag))
16022         *state = NK_WIDGET_STATE_HOVERED;
16023 
16024     if (left_mouse_down && left_mouse_click_in_cursor) {
16025         float delta, pixels;
16026         pixels = in->mouse.delta.x;
16027         delta = pixels * inc_per_pixel;
16028         switch (variant->kind) {
16029         default: break;
16030         case NK_PROPERTY_INT:
16031             variant->value.i = variant->value.i + (int)delta;
16032             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
16033             break;
16034         case NK_PROPERTY_FLOAT:
16035             variant->value.f = variant->value.f + (float)delta;
16036             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
16037             break;
16038         case NK_PROPERTY_DOUBLE:
16039             variant->value.d = variant->value.d + (double)delta;
16040             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
16041             break;
16042         }
16043         *state = NK_WIDGET_STATE_ACTIVE;
16044     }
16045     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
16046         *state |= NK_WIDGET_STATE_ENTERED;
16047     else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
16048         *state |= NK_WIDGET_STATE_LEFT;
16049 }
16050 
16051 NK_INTERN void
16052 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
16053     struct nk_rect property,  struct nk_rect label, struct nk_rect edit,
16054     struct nk_rect empty, int *state, struct nk_property_variant *variant,
16055     float inc_per_pixel)
16056 {
16057     if (in && *state == NK_PROPERTY_DEFAULT) {
16058         if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
16059             *state = NK_PROPERTY_EDIT;
16060         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true))
16061             *state = NK_PROPERTY_DRAG;
16062         else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true))
16063             *state = NK_PROPERTY_DRAG;
16064     }
16065     if (*state == NK_PROPERTY_DRAG) {
16066         nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
16067         if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
16068     }
16069 }
16070 
16071 NK_INTERN void
16072 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
16073     const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
16074     const char *name, int len, const struct nk_user_font *font)
16075 {
16076     struct nk_text text;
16077     const struct nk_style_item *background;
16078 
16079     /* select correct background and text color */
16080     if (state & NK_WIDGET_STATE_ACTIVED) {
16081         background = &style->active;
16082         text.text = style->label_active;
16083     } else if (state & NK_WIDGET_STATE_HOVER) {
16084         background = &style->hover;
16085         text.text = style->label_hover;
16086     } else {
16087         background = &style->normal;
16088         text.text = style->label_normal;
16089     }
16090 
16091     /* draw background */
16092     if (background->type == NK_STYLE_ITEM_IMAGE) {
16093         nk_draw_image(out, *bounds, &background->data.image, nk_white);
16094         text.background = nk_rgba(0,0,0,0);
16095     } else {
16096         text.background = background->data.color;
16097         nk_fill_rect(out, *bounds, style->rounding, background->data.color);
16098         nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
16099     }
16100 
16101     /* draw label */
16102     text.padding = nk_vec2(0,0);
16103     nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
16104 }
16105 
16106 NK_INTERN void
16107 nk_do_property(nk_flags *ws,
16108     struct nk_command_buffer *out, struct nk_rect property,
16109     const char *name, struct nk_property_variant *variant,
16110     float inc_per_pixel, char *buffer, int *len,
16111     int *state, int *cursor, int *select_begin, int *select_end,
16112     const struct nk_style_property *style,
16113     enum nk_property_filter filter, struct nk_input *in,
16114     const struct nk_user_font *font, struct nk_text_edit *text_edit,
16115     enum nk_button_behavior behavior)
16116 {
16117     const nk_plugin_filter filters[] = {
16118         nk_filter_decimal,
16119         nk_filter_float
16120     };
16121     int active, old;
16122     int num_len, name_len;
16123     char string[NK_MAX_NUMBER_BUFFER];
16124     float size;
16125 
16126     char *dst = 0;
16127     int *length;
16128 
16129     struct nk_rect left;
16130     struct nk_rect right;
16131     struct nk_rect label;
16132     struct nk_rect edit;
16133     struct nk_rect empty;
16134 
16135     /* left decrement button */
16136     left.h = font->height/2;
16137     left.w = left.h;
16138     left.x = property.x + style->border + style->padding.x;
16139     left.y = property.y + style->border + property.h/2.0f - left.h/2;
16140 
16141     /* text label */
16142     name_len = nk_strlen(name);
16143     size = font->width(font->userdata, font->height, name, name_len);
16144     label.x = left.x + left.w + style->padding.x;
16145     label.w = (float)size + 2 * style->padding.x;
16146     label.y = property.y + style->border + style->padding.y;
16147     label.h = property.h - (2 * style->border + 2 * style->padding.y);
16148 
16149     /* right increment button */
16150     right.y = left.y;
16151     right.w = left.w;
16152     right.h = left.h;
16153     right.x = property.x + property.w - (right.w + style->padding.x);
16154 
16155     /* edit */
16156     if (*state == NK_PROPERTY_EDIT) {
16157         size = font->width(font->userdata, font->height, buffer, *len);
16158         size += style->edit.cursor_size;
16159         length = len;
16160         dst = buffer;
16161     } else {
16162         switch (variant->kind) {
16163         default: break;
16164         case NK_PROPERTY_INT:
16165             nk_itoa(string, variant->value.i);
16166             num_len = nk_strlen(string);
16167             break;
16168         case NK_PROPERTY_FLOAT:
16169             NK_DTOA(string, (double)variant->value.f);
16170             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
16171             break;
16172         case NK_PROPERTY_DOUBLE:
16173             NK_DTOA(string, variant->value.d);
16174             num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
16175             break;
16176         }
16177         size = font->width(font->userdata, font->height, string, num_len);
16178         dst = string;
16179         length = &num_len;
16180     }
16181 
16182     edit.w =  (float)size + 2 * style->padding.x;
16183     edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
16184     edit.x = right.x - (edit.w + style->padding.x);
16185     edit.y = property.y + style->border;
16186     edit.h = property.h - (2 * style->border);
16187 
16188     /* empty left space activator */
16189     empty.w = edit.x - (label.x + label.w);
16190     empty.x = label.x + label.w;
16191     empty.y = property.y;
16192     empty.h = property.h;
16193 
16194     /* update property */
16195     old = (*state == NK_PROPERTY_EDIT);
16196     nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
16197 
16198     /* draw property */
16199     if (style->draw_begin) style->draw_begin(out, style->userdata);
16200     nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
16201     if (style->draw_end) style->draw_end(out, style->userdata);
16202 
16203     /* execute right button  */
16204     if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
16205         switch (variant->kind) {
16206         default: break;
16207         case NK_PROPERTY_INT:
16208             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
16209         case NK_PROPERTY_FLOAT:
16210             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
16211         case NK_PROPERTY_DOUBLE:
16212             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
16213         }
16214     }
16215     /* execute left button  */
16216     if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
16217         switch (variant->kind) {
16218         default: break;
16219         case NK_PROPERTY_INT:
16220             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
16221         case NK_PROPERTY_FLOAT:
16222             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
16223         case NK_PROPERTY_DOUBLE:
16224             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
16225         }
16226     }
16227     if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
16228         /* property has been activated so setup buffer */
16229         NK_MEMCPY(buffer, dst, (nk_size)*length);
16230         *cursor = nk_utf_len(buffer, *length);
16231         *len = *length;
16232         length = len;
16233         dst = buffer;
16234         active = 0;
16235     } else active = (*state == NK_PROPERTY_EDIT);
16236 
16237     /* execute and run text edit field */
16238     nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
16239     text_edit->active = (unsigned char)active;
16240     text_edit->string.len = *length;
16241     text_edit->cursor = NK_CLAMP(0, *cursor, *length);
16242     text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
16243     text_edit->select_end = NK_CLAMP(0,*select_end, *length);
16244     text_edit->string.buffer.allocated = (nk_size)*length;
16245     text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER;
16246     text_edit->string.buffer.memory.ptr = dst;
16247     text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
16248     text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
16249     nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
16250         filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
16251 
16252     *length = text_edit->string.len;
16253     *cursor = text_edit->cursor;
16254     *select_begin = text_edit->select_start;
16255     *select_end = text_edit->select_end;
16256     if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
16257         text_edit->active = nk_false;
16258 
16259     if (active && !text_edit->active) {
16260         /* property is now not active so convert edit text to value*/
16261         *state = NK_PROPERTY_DEFAULT;
16262         buffer[*len] = '\0';
16263         switch (variant->kind) {
16264         default: break;
16265         case NK_PROPERTY_INT:
16266             variant->value.i = nk_strtoi(buffer, 0);
16267             variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
16268             break;
16269         case NK_PROPERTY_FLOAT:
16270             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16271             variant->value.f = nk_strtof(buffer, 0);
16272             variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
16273             break;
16274         case NK_PROPERTY_DOUBLE:
16275             nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16276             variant->value.d = nk_strtod(buffer, 0);
16277             variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
16278             break;
16279         }
16280     }
16281 }
16282 /* ===============================================================
16283  *
16284  *                          COLOR PICKER
16285  *
16286  * ===============================================================*/
16287 NK_INTERN int
16288 nk_color_picker_behavior(nk_flags *state,
16289     const struct nk_rect *bounds, const struct nk_rect *matrix,
16290     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16291     struct nk_color *color, const struct nk_input *in)
16292 {
16293     float hsva[4];
16294     int value_changed = 0;
16295     int hsv_changed = 0;
16296 
16297     NK_ASSERT(state);
16298     NK_ASSERT(matrix);
16299     NK_ASSERT(hue_bar);
16300     NK_ASSERT(color);
16301 
16302     /* color matrix */
16303     nk_color_hsva_fv(hsva, *color);
16304     if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
16305         hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
16306         hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
16307         value_changed = hsv_changed = 1;
16308     }
16309 
16310     /* hue bar */
16311     if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
16312         hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
16313         value_changed = hsv_changed = 1;
16314     }
16315 
16316     /* alpha bar */
16317     if (alpha_bar) {
16318         if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
16319             hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
16320             value_changed = 1;
16321         }
16322     }
16323     nk_widget_state_reset(state);
16324     if (hsv_changed) {
16325         *color = nk_hsva_fv(hsva);
16326         *state = NK_WIDGET_STATE_ACTIVE;
16327     }
16328     if (value_changed) {
16329         color->a = (nk_byte)(hsva[3] * 255.0f);
16330         *state = NK_WIDGET_STATE_ACTIVE;
16331     }
16332 
16333     /* set color picker widget state */
16334     if (nk_input_is_mouse_hovering_rect(in, *bounds))
16335         *state = NK_WIDGET_STATE_HOVERED;
16336     if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16337         *state |= NK_WIDGET_STATE_ENTERED;
16338     else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16339         *state |= NK_WIDGET_STATE_LEFT;
16340     return value_changed;
16341 }
16342 
16343 NK_INTERN void
16344 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
16345     const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16346     struct nk_color color)
16347 {
16348     NK_STORAGE const struct nk_color black = {0,0,0,255};
16349     NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
16350     NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
16351 
16352     const float crosshair_size = 7.0f;
16353     struct nk_color temp;
16354     float hsva[4];
16355     float line_y;
16356     int i;
16357 
16358     NK_ASSERT(o);
16359     NK_ASSERT(matrix);
16360     NK_ASSERT(hue_bar);
16361 
16362     /* draw hue bar */
16363     nk_color_hsv_fv(hsva, color);
16364     for (i = 0; i < 6; ++i) {
16365         NK_GLOBAL const struct nk_color hue_colors[] = {
16366             {255, 0, 0, 255},
16367             {255,255,0,255},
16368             {0,255,0,255},
16369             {0, 255,255,255},
16370             {0,0,255,255},
16371             {255, 0, 255, 255},
16372             {255, 0, 0, 255}
16373         };
16374         nk_fill_rect_multi_color(o,
16375             nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
16376                 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
16377                 hue_colors[i+1], hue_colors[i+1]);
16378     }
16379     line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
16380     nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
16381         line_y, 1, nk_rgb(255,255,255));
16382 
16383     /* draw alpha bar */
16384     if (alpha_bar) {
16385         float alpha = NK_SATURATE((float)color.a/255.0f);
16386         line_y = (float)(int)(alpha_bar->y +  (1.0f - alpha) * matrix->h + 0.5f);
16387 
16388         nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
16389         nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
16390             line_y, 1, nk_rgb(255,255,255));
16391     }
16392 
16393     /* draw color matrix */
16394     temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
16395     nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
16396     nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
16397 
16398     /* draw cross-hair */
16399     {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
16400     p.x = (float)(int)(matrix->x + S * matrix->w);
16401     p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
16402     nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
16403     nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
16404     nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
16405     nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
16406 }
16407 
16408 NK_INTERN int
16409 nk_do_color_picker(nk_flags *state,
16410     struct nk_command_buffer *out, struct nk_color *color,
16411     enum nk_color_format fmt, struct nk_rect bounds,
16412     struct nk_vec2 padding, const struct nk_input *in,
16413     const struct nk_user_font *font)
16414 {
16415     int ret = 0;
16416     struct nk_rect matrix;
16417     struct nk_rect hue_bar;
16418     struct nk_rect alpha_bar;
16419     float bar_w;
16420 
16421     NK_ASSERT(out);
16422     NK_ASSERT(color);
16423     NK_ASSERT(state);
16424     NK_ASSERT(font);
16425     if (!out || !color || !state || !font)
16426         return ret;
16427 
16428     bar_w = font->height;
16429     bounds.x += padding.x;
16430     bounds.y += padding.x;
16431     bounds.w -= 2 * padding.x;
16432     bounds.h -= 2 * padding.y;
16433 
16434     matrix.x = bounds.x;
16435     matrix.y = bounds.y;
16436     matrix.h = bounds.h;
16437     matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
16438 
16439     hue_bar.w = bar_w;
16440     hue_bar.y = bounds.y;
16441     hue_bar.h = matrix.h;
16442     hue_bar.x = matrix.x + matrix.w + padding.x;
16443 
16444     alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
16445     alpha_bar.y = bounds.y;
16446     alpha_bar.w = bar_w;
16447     alpha_bar.h = matrix.h;
16448 
16449     ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
16450         (fmt == NK_RGBA) ? &alpha_bar:0, color, in);
16451     nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *color);
16452     return ret;
16453 }
16454 
16455 /* ==============================================================
16456  *
16457  *                          STYLE
16458  *
16459  * ===============================================================*/
16460 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
16461 #define NK_COLOR_MAP(NK_COLOR)\
16462     NK_COLOR(NK_COLOR_TEXT,                 175,175,175,255) \
16463     NK_COLOR(NK_COLOR_WINDOW,               45, 45, 45, 255) \
16464     NK_COLOR(NK_COLOR_HEADER,               40, 40, 40, 255) \
16465     NK_COLOR(NK_COLOR_BORDER,               65, 65, 65, 255) \
16466     NK_COLOR(NK_COLOR_BUTTON,               50, 50, 50, 255) \
16467     NK_COLOR(NK_COLOR_BUTTON_HOVER,         40, 40, 40, 255) \
16468     NK_COLOR(NK_COLOR_BUTTON_ACTIVE,        35, 35, 35, 255) \
16469     NK_COLOR(NK_COLOR_TOGGLE,               100,100,100,255) \
16470     NK_COLOR(NK_COLOR_TOGGLE_HOVER,         120,120,120,255) \
16471     NK_COLOR(NK_COLOR_TOGGLE_CURSOR,        45, 45, 45, 255) \
16472     NK_COLOR(NK_COLOR_SELECT,               45, 45, 45, 255) \
16473     NK_COLOR(NK_COLOR_SELECT_ACTIVE,        35, 35, 35,255) \
16474     NK_COLOR(NK_COLOR_SLIDER,               38, 38, 38, 255) \
16475     NK_COLOR(NK_COLOR_SLIDER_CURSOR,        100,100,100,255) \
16476     NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER,  120,120,120,255) \
16477     NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
16478     NK_COLOR(NK_COLOR_PROPERTY,             38, 38, 38, 255) \
16479     NK_COLOR(NK_COLOR_EDIT,                 38, 38, 38, 255)  \
16480     NK_COLOR(NK_COLOR_EDIT_CURSOR,          175,175,175,255) \
16481     NK_COLOR(NK_COLOR_COMBO,                45, 45, 45, 255) \
16482     NK_COLOR(NK_COLOR_CHART,                120,120,120,255) \
16483     NK_COLOR(NK_COLOR_CHART_COLOR,          45, 45, 45, 255) \
16484     NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,255, 0,  0, 255) \
16485     NK_COLOR(NK_COLOR_SCROLLBAR,            40, 40, 40, 255) \
16486     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR,     100,100,100,255) \
16487     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,120,120,120,255) \
16488     NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,150,150,150,255) \
16489     NK_COLOR(NK_COLOR_TAB_HEADER,           40, 40, 40,255)
16490 
16491 NK_GLOBAL const struct nk_color
16492 nk_default_color_style[NK_COLOR_COUNT] = {
16493 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
16494     NK_COLOR_MAP(NK_COLOR)
16495 #undef NK_COLOR
16496 };
16497 
16498 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
16499 #define NK_COLOR(a,b,c,d,e) #a,
16500     NK_COLOR_MAP(NK_COLOR)
16501 #undef NK_COLOR
16502 };
16503 
16504 NK_API const char *nk_style_get_color_by_name(enum nk_style_colors c)
16505 {return nk_color_names[c];}
16506 
16507 NK_API struct nk_style_item nk_style_item_image(struct nk_image img)
16508 {struct nk_style_item i; i.type = NK_STYLE_ITEM_IMAGE; i.data.image = img; return i;}
16509 
16510 NK_API struct nk_style_item nk_style_item_color(struct nk_color col)
16511 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = col; return i;}
16512 
16513 NK_API struct nk_style_item nk_style_item_hide(void)
16514 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = nk_rgba(0,0,0,0); return i;}
16515 
16516 NK_API void
16517 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
16518 {
16519     struct nk_style *style;
16520     struct nk_style_text *text;
16521     struct nk_style_button *button;
16522     struct nk_style_toggle *toggle;
16523     struct nk_style_selectable *select;
16524     struct nk_style_slider *slider;
16525     struct nk_style_progress *prog;
16526     struct nk_style_scrollbar *scroll;
16527     struct nk_style_edit *edit;
16528     struct nk_style_property *property;
16529     struct nk_style_combo *combo;
16530     struct nk_style_chart *chart;
16531     struct nk_style_tab *tab;
16532     struct nk_style_window *win;
16533 
16534     NK_ASSERT(ctx);
16535     if (!ctx) return;
16536     style = &ctx->style;
16537     table = (!table) ? nk_default_color_style: table;
16538 
16539     /* default text */
16540     text = &style->text;
16541     text->color = table[NK_COLOR_TEXT];
16542     text->padding = nk_vec2(0,0);
16543 
16544     /* default button */
16545     button = &style->button;
16546     nk_zero_struct(*button);
16547     button->normal          = nk_style_item_color(table[NK_COLOR_BUTTON]);
16548     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
16549     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
16550     button->border_color    = table[NK_COLOR_BORDER];
16551     button->text_background = table[NK_COLOR_BUTTON];
16552     button->text_normal     = table[NK_COLOR_TEXT];
16553     button->text_hover      = table[NK_COLOR_TEXT];
16554     button->text_active     = table[NK_COLOR_TEXT];
16555     button->padding         = nk_vec2(2.0f,2.0f);
16556     button->image_padding   = nk_vec2(0.0f,0.0f);
16557     button->touch_padding   = nk_vec2(0.0f, 0.0f);
16558     button->userdata        = nk_handle_ptr(0);
16559     button->text_alignment  = NK_TEXT_CENTERED;
16560     button->border          = 1.0f;
16561     button->rounding        = 4.0f;
16562     button->draw_begin      = 0;
16563     button->draw_end        = 0;
16564 
16565     /* contextual button */
16566     button = &style->contextual_button;
16567     nk_zero_struct(*button);
16568     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
16569     button->hover           = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
16570     button->active          = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
16571     button->border_color    = table[NK_COLOR_WINDOW];
16572     button->text_background = table[NK_COLOR_WINDOW];
16573     button->text_normal     = table[NK_COLOR_TEXT];
16574     button->text_hover      = table[NK_COLOR_TEXT];
16575     button->text_active     = table[NK_COLOR_TEXT];
16576     button->padding         = nk_vec2(2.0f,2.0f);
16577     button->touch_padding   = nk_vec2(0.0f,0.0f);
16578     button->userdata        = nk_handle_ptr(0);
16579     button->text_alignment  = NK_TEXT_CENTERED;
16580     button->border          = 0.0f;
16581     button->rounding        = 0.0f;
16582     button->draw_begin      = 0;
16583     button->draw_end        = 0;
16584 
16585     /* menu button */
16586     button = &style->menu_button;
16587     nk_zero_struct(*button);
16588     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
16589     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
16590     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
16591     button->border_color    = table[NK_COLOR_WINDOW];
16592     button->text_background = table[NK_COLOR_WINDOW];
16593     button->text_normal     = table[NK_COLOR_TEXT];
16594     button->text_hover      = table[NK_COLOR_TEXT];
16595     button->text_active     = table[NK_COLOR_TEXT];
16596     button->padding         = nk_vec2(2.0f,2.0f);
16597     button->touch_padding   = nk_vec2(0.0f,0.0f);
16598     button->userdata        = nk_handle_ptr(0);
16599     button->text_alignment  = NK_TEXT_CENTERED;
16600     button->border          = 0.0f;
16601     button->rounding        = 1.0f;
16602     button->draw_begin      = 0;
16603     button->draw_end        = 0;
16604 
16605     /* checkbox toggle */
16606     toggle = &style->checkbox;
16607     nk_zero_struct(*toggle);
16608     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
16609     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
16610     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
16611     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
16612     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
16613     toggle->userdata        = nk_handle_ptr(0);
16614     toggle->text_background = table[NK_COLOR_WINDOW];
16615     toggle->text_normal     = table[NK_COLOR_TEXT];
16616     toggle->text_hover      = table[NK_COLOR_TEXT];
16617     toggle->text_active     = table[NK_COLOR_TEXT];
16618     toggle->padding         = nk_vec2(2.0f, 2.0f);
16619     toggle->touch_padding   = nk_vec2(0,0);
16620     toggle->border_color    = nk_rgba(0,0,0,0);
16621     toggle->border          = 0.0f;
16622     toggle->spacing         = 4;
16623 
16624     /* option toggle */
16625     toggle = &style->option;
16626     nk_zero_struct(*toggle);
16627     toggle->normal          = nk_style_item_color(table[NK_COLOR_TOGGLE]);
16628     toggle->hover           = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
16629     toggle->active          = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
16630     toggle->cursor_normal   = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
16631     toggle->cursor_hover    = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
16632     toggle->userdata        = nk_handle_ptr(0);
16633     toggle->text_background = table[NK_COLOR_WINDOW];
16634     toggle->text_normal     = table[NK_COLOR_TEXT];
16635     toggle->text_hover      = table[NK_COLOR_TEXT];
16636     toggle->text_active     = table[NK_COLOR_TEXT];
16637     toggle->padding         = nk_vec2(3.0f, 3.0f);
16638     toggle->touch_padding   = nk_vec2(0,0);
16639     toggle->border_color    = nk_rgba(0,0,0,0);
16640     toggle->border          = 0.0f;
16641     toggle->spacing         = 4;
16642 
16643     /* selectable */
16644     select = &style->selectable;
16645     nk_zero_struct(*select);
16646     select->normal          = nk_style_item_color(table[NK_COLOR_SELECT]);
16647     select->hover           = nk_style_item_color(table[NK_COLOR_SELECT]);
16648     select->pressed         = nk_style_item_color(table[NK_COLOR_SELECT]);
16649     select->normal_active   = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
16650     select->hover_active    = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
16651     select->pressed_active  = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
16652     select->text_normal     = table[NK_COLOR_TEXT];
16653     select->text_hover      = table[NK_COLOR_TEXT];
16654     select->text_pressed    = table[NK_COLOR_TEXT];
16655     select->text_normal_active  = table[NK_COLOR_TEXT];
16656     select->text_hover_active   = table[NK_COLOR_TEXT];
16657     select->text_pressed_active = table[NK_COLOR_TEXT];
16658     select->padding         = nk_vec2(2.0f,2.0f);
16659     select->touch_padding   = nk_vec2(0,0);
16660     select->userdata        = nk_handle_ptr(0);
16661     select->rounding        = 0.0f;
16662     select->draw_begin      = 0;
16663     select->draw_end        = 0;
16664 
16665     /* slider */
16666     slider = &style->slider;
16667     nk_zero_struct(*slider);
16668     slider->normal          = nk_style_item_hide();
16669     slider->hover           = nk_style_item_hide();
16670     slider->active          = nk_style_item_hide();
16671     slider->bar_normal      = table[NK_COLOR_SLIDER];
16672     slider->bar_hover       = table[NK_COLOR_SLIDER];
16673     slider->bar_active      = table[NK_COLOR_SLIDER];
16674     slider->bar_filled      = table[NK_COLOR_SLIDER_CURSOR];
16675     slider->cursor_normal   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
16676     slider->cursor_hover    = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
16677     slider->cursor_active   = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
16678     slider->inc_symbol      = NK_SYMBOL_TRIANGLE_RIGHT;
16679     slider->dec_symbol      = NK_SYMBOL_TRIANGLE_LEFT;
16680     slider->cursor_size     = nk_vec2(16,16);
16681     slider->padding         = nk_vec2(2,2);
16682     slider->spacing         = nk_vec2(2,2);
16683     slider->userdata        = nk_handle_ptr(0);
16684     slider->show_buttons    = nk_false;
16685     slider->bar_height      = 8;
16686     slider->rounding        = 0;
16687     slider->draw_begin      = 0;
16688     slider->draw_end        = 0;
16689 
16690     /* slider buttons */
16691     button = &style->slider.inc_button;
16692     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
16693     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
16694     button->active          = nk_style_item_color(nk_rgb(44,44,44));
16695     button->border_color    = nk_rgb(65,65,65);
16696     button->text_background = nk_rgb(40,40,40);
16697     button->text_normal     = nk_rgb(175,175,175);
16698     button->text_hover      = nk_rgb(175,175,175);
16699     button->text_active     = nk_rgb(175,175,175);
16700     button->padding         = nk_vec2(8.0f,8.0f);
16701     button->touch_padding   = nk_vec2(0.0f,0.0f);
16702     button->userdata        = nk_handle_ptr(0);
16703     button->text_alignment  = NK_TEXT_CENTERED;
16704     button->border          = 1.0f;
16705     button->rounding        = 0.0f;
16706     button->draw_begin      = 0;
16707     button->draw_end        = 0;
16708     style->slider.dec_button = style->slider.inc_button;
16709 
16710     /* progressbar */
16711     prog = &style->progress;
16712     nk_zero_struct(*prog);
16713     prog->normal            = nk_style_item_color(table[NK_COLOR_SLIDER]);
16714     prog->hover             = nk_style_item_color(table[NK_COLOR_SLIDER]);
16715     prog->active            = nk_style_item_color(table[NK_COLOR_SLIDER]);
16716     prog->cursor_normal     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
16717     prog->cursor_hover      = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
16718     prog->cursor_active     = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
16719     prog->border_color      = nk_rgba(0,0,0,0);
16720     prog->cursor_border_color = nk_rgba(0,0,0,0);
16721     prog->userdata          = nk_handle_ptr(0);
16722     prog->padding           = nk_vec2(4,4);
16723     prog->rounding          = 0;
16724     prog->border            = 0;
16725     prog->cursor_rounding   = 0;
16726     prog->cursor_border     = 0;
16727     prog->draw_begin        = 0;
16728     prog->draw_end          = 0;
16729 
16730     /* scrollbars */
16731     scroll = &style->scrollh;
16732     nk_zero_struct(*scroll);
16733     scroll->normal          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16734     scroll->hover           = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16735     scroll->active          = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16736     scroll->cursor_normal   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]);
16737     scroll->cursor_hover    = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]);
16738     scroll->cursor_active   = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]);
16739     scroll->dec_symbol      = NK_SYMBOL_CIRCLE_SOLID;
16740     scroll->inc_symbol      = NK_SYMBOL_CIRCLE_SOLID;
16741     scroll->userdata        = nk_handle_ptr(0);
16742     scroll->border_color    = table[NK_COLOR_SCROLLBAR];
16743     scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
16744     scroll->padding         = nk_vec2(0,0);
16745     scroll->show_buttons    = nk_false;
16746     scroll->border          = 0;
16747     scroll->rounding        = 0;
16748     scroll->border_cursor   = 0;
16749     scroll->rounding_cursor = 0;
16750     scroll->draw_begin      = 0;
16751     scroll->draw_end        = 0;
16752     style->scrollv = style->scrollh;
16753 
16754     /* scrollbars buttons */
16755     button = &style->scrollh.inc_button;
16756     button->normal          = nk_style_item_color(nk_rgb(40,40,40));
16757     button->hover           = nk_style_item_color(nk_rgb(42,42,42));
16758     button->active          = nk_style_item_color(nk_rgb(44,44,44));
16759     button->border_color    = nk_rgb(65,65,65);
16760     button->text_background = nk_rgb(40,40,40);
16761     button->text_normal     = nk_rgb(175,175,175);
16762     button->text_hover      = nk_rgb(175,175,175);
16763     button->text_active     = nk_rgb(175,175,175);
16764     button->padding         = nk_vec2(4.0f,4.0f);
16765     button->touch_padding   = nk_vec2(0.0f,0.0f);
16766     button->userdata        = nk_handle_ptr(0);
16767     button->text_alignment  = NK_TEXT_CENTERED;
16768     button->border          = 1.0f;
16769     button->rounding        = 0.0f;
16770     button->draw_begin      = 0;
16771     button->draw_end        = 0;
16772     style->scrollh.dec_button = style->scrollh.inc_button;
16773     style->scrollv.inc_button = style->scrollh.inc_button;
16774     style->scrollv.dec_button = style->scrollh.inc_button;
16775 
16776     /* edit */
16777     edit = &style->edit;
16778     nk_zero_struct(*edit);
16779     edit->normal            = nk_style_item_color(table[NK_COLOR_EDIT]);
16780     edit->hover             = nk_style_item_color(table[NK_COLOR_EDIT]);
16781     edit->active            = nk_style_item_color(table[NK_COLOR_EDIT]);
16782     edit->cursor_normal     = table[NK_COLOR_TEXT];
16783     edit->cursor_hover      = table[NK_COLOR_TEXT];
16784     edit->cursor_text_normal= table[NK_COLOR_EDIT];
16785     edit->cursor_text_hover = table[NK_COLOR_EDIT];
16786     edit->border_color      = table[NK_COLOR_BORDER];
16787     edit->text_normal       = table[NK_COLOR_TEXT];
16788     edit->text_hover        = table[NK_COLOR_TEXT];
16789     edit->text_active       = table[NK_COLOR_TEXT];
16790     edit->selected_normal   = table[NK_COLOR_TEXT];
16791     edit->selected_hover    = table[NK_COLOR_TEXT];
16792     edit->selected_text_normal  = table[NK_COLOR_EDIT];
16793     edit->selected_text_hover   = table[NK_COLOR_EDIT];
16794     edit->scrollbar_size    = nk_vec2(10,10);
16795     edit->scrollbar         = style->scrollv;
16796     edit->padding           = nk_vec2(4,4);
16797     edit->row_padding       = 2;
16798     edit->cursor_size       = 4;
16799     edit->border            = 1;
16800     edit->rounding          = 0;
16801 
16802     /* property */
16803     property = &style->property;
16804     nk_zero_struct(*property);
16805     property->normal        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16806     property->hover         = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16807     property->active        = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16808     property->border_color  = table[NK_COLOR_BORDER];
16809     property->label_normal  = table[NK_COLOR_TEXT];
16810     property->label_hover   = table[NK_COLOR_TEXT];
16811     property->label_active  = table[NK_COLOR_TEXT];
16812     property->sym_left      = NK_SYMBOL_TRIANGLE_LEFT;
16813     property->sym_right     = NK_SYMBOL_TRIANGLE_RIGHT;
16814     property->userdata      = nk_handle_ptr(0);
16815     property->padding       = nk_vec2(4,4);
16816     property->border        = 1;
16817     property->rounding      = 10;
16818     property->draw_begin    = 0;
16819     property->draw_end      = 0;
16820 
16821     /* property buttons */
16822     button = &style->property.dec_button;
16823     nk_zero_struct(*button);
16824     button->normal          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16825     button->hover           = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16826     button->active          = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16827     button->border_color    = nk_rgba(0,0,0,0);
16828     button->text_background = table[NK_COLOR_PROPERTY];
16829     button->text_normal     = table[NK_COLOR_TEXT];
16830     button->text_hover      = table[NK_COLOR_TEXT];
16831     button->text_active     = table[NK_COLOR_TEXT];
16832     button->padding         = nk_vec2(0.0f,0.0f);
16833     button->touch_padding   = nk_vec2(0.0f,0.0f);
16834     button->userdata        = nk_handle_ptr(0);
16835     button->text_alignment  = NK_TEXT_CENTERED;
16836     button->border          = 0.0f;
16837     button->rounding        = 0.0f;
16838     button->draw_begin      = 0;
16839     button->draw_end        = 0;
16840     style->property.inc_button = style->property.dec_button;
16841 
16842     /* property edit */
16843     edit = &style->property.edit;
16844     nk_zero_struct(*edit);
16845     edit->normal            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16846     edit->hover             = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16847     edit->active            = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16848     edit->border_color      = nk_rgba(0,0,0,0);
16849     edit->cursor_normal     = table[NK_COLOR_TEXT];
16850     edit->cursor_hover      = table[NK_COLOR_TEXT];
16851     edit->cursor_text_normal= table[NK_COLOR_EDIT];
16852     edit->cursor_text_hover = table[NK_COLOR_EDIT];
16853     edit->text_normal       = table[NK_COLOR_TEXT];
16854     edit->text_hover        = table[NK_COLOR_TEXT];
16855     edit->text_active       = table[NK_COLOR_TEXT];
16856     edit->selected_normal   = table[NK_COLOR_TEXT];
16857     edit->selected_hover    = table[NK_COLOR_TEXT];
16858     edit->selected_text_normal  = table[NK_COLOR_EDIT];
16859     edit->selected_text_hover   = table[NK_COLOR_EDIT];
16860     edit->padding           = nk_vec2(0,0);
16861     edit->cursor_size       = 8;
16862     edit->border            = 0;
16863     edit->rounding          = 0;
16864 
16865     /* chart */
16866     chart = &style->chart;
16867     nk_zero_struct(*chart);
16868     chart->background       = nk_style_item_color(table[NK_COLOR_CHART]);
16869     chart->border_color     = table[NK_COLOR_BORDER];
16870     chart->selected_color   = table[NK_COLOR_CHART_COLOR_HIGHLIGHT];
16871     chart->color            = table[NK_COLOR_CHART_COLOR];
16872     chart->padding          = nk_vec2(4,4);
16873     chart->border           = 0;
16874     chart->rounding         = 0;
16875 
16876     /* combo */
16877     combo = &style->combo;
16878     combo->normal           = nk_style_item_color(table[NK_COLOR_COMBO]);
16879     combo->hover            = nk_style_item_color(table[NK_COLOR_COMBO]);
16880     combo->active           = nk_style_item_color(table[NK_COLOR_COMBO]);
16881     combo->border_color     = table[NK_COLOR_BORDER];
16882     combo->label_normal     = table[NK_COLOR_TEXT];
16883     combo->label_hover      = table[NK_COLOR_TEXT];
16884     combo->label_active     = table[NK_COLOR_TEXT];
16885     combo->sym_normal       = NK_SYMBOL_TRIANGLE_DOWN;
16886     combo->sym_hover        = NK_SYMBOL_TRIANGLE_DOWN;
16887     combo->sym_active       = NK_SYMBOL_TRIANGLE_DOWN;
16888     combo->content_padding  = nk_vec2(4,4);
16889     combo->button_padding   = nk_vec2(0,4);
16890     combo->spacing          = nk_vec2(4,0);
16891     combo->border           = 1;
16892     combo->rounding         = 0;
16893 
16894     /* combo button */
16895     button = &style->combo.button;
16896     nk_zero_struct(*button);
16897     button->normal          = nk_style_item_color(table[NK_COLOR_COMBO]);
16898     button->hover           = nk_style_item_color(table[NK_COLOR_COMBO]);
16899     button->active          = nk_style_item_color(table[NK_COLOR_COMBO]);
16900     button->border_color    = nk_rgba(0,0,0,0);
16901     button->text_background = table[NK_COLOR_COMBO];
16902     button->text_normal     = table[NK_COLOR_TEXT];
16903     button->text_hover      = table[NK_COLOR_TEXT];
16904     button->text_active     = table[NK_COLOR_TEXT];
16905     button->padding         = nk_vec2(2.0f,2.0f);
16906     button->touch_padding   = nk_vec2(0.0f,0.0f);
16907     button->userdata        = nk_handle_ptr(0);
16908     button->text_alignment  = NK_TEXT_CENTERED;
16909     button->border          = 0.0f;
16910     button->rounding        = 0.0f;
16911     button->draw_begin      = 0;
16912     button->draw_end        = 0;
16913 
16914     /* tab */
16915     tab = &style->tab;
16916     tab->background         = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
16917     tab->border_color       = table[NK_COLOR_BORDER];
16918     tab->text               = table[NK_COLOR_TEXT];
16919     tab->sym_minimize       = NK_SYMBOL_TRIANGLE_RIGHT;
16920     tab->sym_maximize       = NK_SYMBOL_TRIANGLE_DOWN;
16921     tab->padding            = nk_vec2(4,4);
16922     tab->spacing            = nk_vec2(4,4);
16923     tab->indent             = 10.0f;
16924     tab->border             = 1;
16925     tab->rounding           = 0;
16926 
16927     /* tab button */
16928     button = &style->tab.tab_minimize_button;
16929     nk_zero_struct(*button);
16930     button->normal          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
16931     button->hover           = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
16932     button->active          = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
16933     button->border_color    = nk_rgba(0,0,0,0);
16934     button->text_background = table[NK_COLOR_TAB_HEADER];
16935     button->text_normal     = table[NK_COLOR_TEXT];
16936     button->text_hover      = table[NK_COLOR_TEXT];
16937     button->text_active     = table[NK_COLOR_TEXT];
16938     button->padding         = nk_vec2(2.0f,2.0f);
16939     button->touch_padding   = nk_vec2(0.0f,0.0f);
16940     button->userdata        = nk_handle_ptr(0);
16941     button->text_alignment  = NK_TEXT_CENTERED;
16942     button->border          = 0.0f;
16943     button->rounding        = 0.0f;
16944     button->draw_begin      = 0;
16945     button->draw_end        = 0;
16946     style->tab.tab_maximize_button =*button;
16947 
16948     /* node button */
16949     button = &style->tab.node_minimize_button;
16950     nk_zero_struct(*button);
16951     button->normal          = nk_style_item_color(table[NK_COLOR_WINDOW]);
16952     button->hover           = nk_style_item_color(table[NK_COLOR_WINDOW]);
16953     button->active          = nk_style_item_color(table[NK_COLOR_WINDOW]);
16954     button->border_color    = nk_rgba(0,0,0,0);
16955     button->text_background = table[NK_COLOR_TAB_HEADER];
16956     button->text_normal     = table[NK_COLOR_TEXT];
16957     button->text_hover      = table[NK_COLOR_TEXT];
16958     button->text_active     = table[NK_COLOR_TEXT];
16959     button->padding         = nk_vec2(2.0f,2.0f);
16960     button->touch_padding   = nk_vec2(0.0f,0.0f);
16961     button->userdata        = nk_handle_ptr(0);
16962     button->text_alignment  = NK_TEXT_CENTERED;
16963     button->border          = 0.0f;
16964     button->rounding        = 0.0f;
16965     button->draw_begin      = 0;
16966     button->draw_end        = 0;
16967     style->tab.node_maximize_button =*button;
16968 
16969     /* window header */
16970     win = &style->window;
16971     win->header.align = NK_HEADER_RIGHT;
16972     win->header.close_symbol = NK_SYMBOL_X;
16973     win->header.minimize_symbol = NK_SYMBOL_MINUS;
16974     win->header.maximize_symbol = NK_SYMBOL_PLUS;
16975     win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]);
16976     win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]);
16977     win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]);
16978     win->header.label_normal = table[NK_COLOR_TEXT];
16979     win->header.label_hover = table[NK_COLOR_TEXT];
16980     win->header.label_active = table[NK_COLOR_TEXT];
16981     win->header.label_padding = nk_vec2(4,4);
16982     win->header.padding = nk_vec2(4,4);
16983     win->header.spacing = nk_vec2(0,0);
16984 
16985     /* window header close button */
16986     button = &style->window.header.close_button;
16987     nk_zero_struct(*button);
16988     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
16989     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
16990     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
16991     button->border_color    = nk_rgba(0,0,0,0);
16992     button->text_background = table[NK_COLOR_HEADER];
16993     button->text_normal     = table[NK_COLOR_TEXT];
16994     button->text_hover      = table[NK_COLOR_TEXT];
16995     button->text_active     = table[NK_COLOR_TEXT];
16996     button->padding         = nk_vec2(0.0f,0.0f);
16997     button->touch_padding   = nk_vec2(0.0f,0.0f);
16998     button->userdata        = nk_handle_ptr(0);
16999     button->text_alignment  = NK_TEXT_CENTERED;
17000     button->border          = 0.0f;
17001     button->rounding        = 0.0f;
17002     button->draw_begin      = 0;
17003     button->draw_end        = 0;
17004 
17005     /* window header minimize button */
17006     button = &style->window.header.minimize_button;
17007     nk_zero_struct(*button);
17008     button->normal          = nk_style_item_color(table[NK_COLOR_HEADER]);
17009     button->hover           = nk_style_item_color(table[NK_COLOR_HEADER]);
17010     button->active          = nk_style_item_color(table[NK_COLOR_HEADER]);
17011     button->border_color    = nk_rgba(0,0,0,0);
17012     button->text_background = table[NK_COLOR_HEADER];
17013     button->text_normal     = table[NK_COLOR_TEXT];
17014     button->text_hover      = table[NK_COLOR_TEXT];
17015     button->text_active     = table[NK_COLOR_TEXT];
17016     button->padding         = nk_vec2(0.0f,0.0f);
17017     button->touch_padding   = nk_vec2(0.0f,0.0f);
17018     button->userdata        = nk_handle_ptr(0);
17019     button->text_alignment  = NK_TEXT_CENTERED;
17020     button->border          = 0.0f;
17021     button->rounding        = 0.0f;
17022     button->draw_begin      = 0;
17023     button->draw_end        = 0;
17024 
17025     /* window */
17026     win->background = table[NK_COLOR_WINDOW];
17027     win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]);
17028     win->border_color = table[NK_COLOR_BORDER];
17029     win->popup_border_color = table[NK_COLOR_BORDER];
17030     win->combo_border_color = table[NK_COLOR_BORDER];
17031     win->contextual_border_color = table[NK_COLOR_BORDER];
17032     win->menu_border_color = table[NK_COLOR_BORDER];
17033     win->group_border_color = table[NK_COLOR_BORDER];
17034     win->tooltip_border_color = table[NK_COLOR_BORDER];
17035     win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
17036 
17037     win->rounding = 0.0f;
17038     win->spacing = nk_vec2(4,4);
17039     win->scrollbar_size = nk_vec2(10,10);
17040     win->min_size = nk_vec2(64,64);
17041 
17042     win->combo_border = 1.0f;
17043     win->contextual_border = 1.0f;
17044     win->menu_border = 1.0f;
17045     win->group_border = 1.0f;
17046     win->tooltip_border = 1.0f;
17047     win->popup_border = 1.0f;
17048     win->border = 2.0f;
17049     win->min_row_height_padding = 8;
17050 
17051     win->padding = nk_vec2(4,4);
17052     win->group_padding = nk_vec2(4,4);
17053     win->popup_padding = nk_vec2(4,4);
17054     win->combo_padding = nk_vec2(4,4);
17055     win->contextual_padding = nk_vec2(4,4);
17056     win->menu_padding = nk_vec2(4,4);
17057     win->tooltip_padding = nk_vec2(4,4);
17058 }
17059 
17060 NK_API void
17061 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
17062 {
17063     struct nk_style *style;
17064     NK_ASSERT(ctx);
17065 
17066     if (!ctx) return;
17067     style = &ctx->style;
17068     style->font = font;
17069     ctx->stacks.fonts.head = 0;
17070     if (ctx->current)
17071         nk_layout_reset_min_row_height(ctx);
17072 }
17073 
17074 NK_API int
17075 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
17076 {
17077     struct nk_config_stack_user_font *font_stack;
17078     struct nk_config_stack_user_font_element *element;
17079 
17080     NK_ASSERT(ctx);
17081     if (!ctx) return 0;
17082 
17083     font_stack = &ctx->stacks.fonts;
17084     NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
17085     if (font_stack->head >= (int)NK_LEN(font_stack->elements))
17086         return 0;
17087 
17088     element = &font_stack->elements[font_stack->head++];
17089     element->address = &ctx->style.font;
17090     element->old_value = ctx->style.font;
17091     ctx->style.font = font;
17092     return 1;
17093 }
17094 
17095 NK_API int
17096 nk_style_pop_font(struct nk_context *ctx)
17097 {
17098     struct nk_config_stack_user_font *font_stack;
17099     struct nk_config_stack_user_font_element *element;
17100 
17101     NK_ASSERT(ctx);
17102     if (!ctx) return 0;
17103 
17104     font_stack = &ctx->stacks.fonts;
17105     NK_ASSERT(font_stack->head > 0);
17106     if (font_stack->head < 1)
17107         return 0;
17108 
17109     element = &font_stack->elements[--font_stack->head];
17110     *element->address = element->old_value;
17111     return 1;
17112 }
17113 
17114 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
17115 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
17116 {\
17117     struct nk_config_stack_##type * type_stack;\
17118     struct nk_config_stack_##type##_element *element;\
17119     NK_ASSERT(ctx);\
17120     if (!ctx) return 0;\
17121     type_stack = &ctx->stacks.stack;\
17122     NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
17123     if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
17124         return 0;\
17125     element = &type_stack->elements[type_stack->head++];\
17126     element->address = address;\
17127     element->old_value = *address;\
17128     *address = value;\
17129     return 1;\
17130 }
17131 
17132 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
17133 nk_style_pop_##type(struct nk_context *ctx)\
17134 {\
17135     struct nk_config_stack_##type *type_stack;\
17136     struct nk_config_stack_##type##_element *element;\
17137     NK_ASSERT(ctx);\
17138     if (!ctx) return 0;\
17139     type_stack = &ctx->stacks.stack;\
17140     NK_ASSERT(type_stack->head > 0);\
17141     if (type_stack->head < 1)\
17142         return 0;\
17143     element = &type_stack->elements[--type_stack->head];\
17144     *element->address = element->old_value;\
17145     return 1;\
17146 }
17147 
17148 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
17149 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
17150 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
17151 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
17152 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
17153 
17154 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
17155 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
17156 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
17157 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
17158 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
17159 
17160 NK_API int
17161 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
17162 {
17163     struct nk_style *style;
17164     NK_ASSERT(ctx);
17165     if (!ctx) return 0;
17166     style = &ctx->style;
17167     if (style->cursors[c]) {
17168         style->cursor_active = style->cursors[c];
17169         return 1;
17170     }
17171     return 0;
17172 }
17173 
17174 NK_API void
17175 nk_style_show_cursor(struct nk_context *ctx)
17176 {
17177     ctx->style.cursor_visible = nk_true;
17178 }
17179 
17180 NK_API void
17181 nk_style_hide_cursor(struct nk_context *ctx)
17182 {
17183     ctx->style.cursor_visible = nk_false;
17184 }
17185 
17186 NK_API void
17187 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
17188     const struct nk_cursor *c)
17189 {
17190     struct nk_style *style;
17191     NK_ASSERT(ctx);
17192     if (!ctx) return;
17193     style = &ctx->style;
17194     style->cursors[cursor] = c;
17195 }
17196 
17197 NK_API void
17198 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors)
17199 {
17200     int i = 0;
17201     struct nk_style *style;
17202     NK_ASSERT(ctx);
17203     if (!ctx) return;
17204     style = &ctx->style;
17205     for (i = 0; i < NK_CURSOR_COUNT; ++i)
17206         style->cursors[i] = &cursors[i];
17207     style->cursor_visible = nk_true;
17208 }
17209 
17210 /* ===============================================================
17211  *
17212  *                          POOL
17213  *
17214  * ===============================================================*/
17215 NK_INTERN void
17216 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
17217     unsigned int capacity)
17218 {
17219     nk_zero(pool, sizeof(*pool));
17220     pool->alloc = *alloc;
17221     pool->capacity = capacity;
17222     pool->type = NK_BUFFER_DYNAMIC;
17223     pool->pages = 0;
17224 }
17225 
17226 NK_INTERN void
17227 nk_pool_free(struct nk_pool *pool)
17228 {
17229     struct nk_page *iter = pool->pages;
17230     if (!pool) return;
17231     if (pool->type == NK_BUFFER_FIXED) return;
17232     while (iter) {
17233         struct nk_page *next = iter->next;
17234         pool->alloc.free(pool->alloc.userdata, iter);
17235         iter = next;
17236     }
17237 }
17238 
17239 NK_INTERN void
17240 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
17241 {
17242     nk_zero(pool, sizeof(*pool));
17243     NK_ASSERT(size >= sizeof(struct nk_page));
17244     if (size < sizeof(struct nk_page)) return;
17245     pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
17246     pool->pages = (struct nk_page*)memory;
17247     pool->type = NK_BUFFER_FIXED;
17248     pool->size = size;
17249 }
17250 
17251 NK_INTERN struct nk_page_element*
17252 nk_pool_alloc(struct nk_pool *pool)
17253 {
17254     if (!pool->pages || pool->pages->size >= pool->capacity) {
17255         /* allocate new page */
17256         struct nk_page *page;
17257         if (pool->type == NK_BUFFER_FIXED) {
17258             if (!pool->pages) {
17259                 NK_ASSERT(pool->pages);
17260                 return 0;
17261             }
17262             NK_ASSERT(pool->pages->size < pool->capacity);
17263             return 0;
17264         } else {
17265             nk_size size = sizeof(struct nk_page);
17266             size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
17267             page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
17268             page->next = pool->pages;
17269             pool->pages = page;
17270             page->size = 0;
17271         }
17272     }
17273     return &pool->pages->win[pool->pages->size++];
17274 }
17275 
17276 /* ===============================================================
17277  *
17278  *                          CONTEXT
17279  *
17280  * ===============================================================*/
17281 NK_INTERN void* nk_create_window(struct nk_context *ctx);
17282 NK_INTERN void nk_remove_window(struct nk_context*, struct nk_window*);
17283 NK_INTERN void nk_free_window(struct nk_context *ctx, struct nk_window *win);
17284 NK_INTERN void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
17285 NK_INTERN void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
17286 NK_INTERN void* nk_create_panel(struct nk_context *ctx);
17287 NK_INTERN void nk_free_panel(struct nk_context*, struct nk_panel *pan);
17288 
17289 NK_INTERN void
17290 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
17291 {
17292     NK_ASSERT(ctx);
17293     if (!ctx) return;
17294     nk_zero_struct(*ctx);
17295     nk_style_default(ctx);
17296     ctx->seq = 1;
17297     if (font) ctx->style.font = font;
17298 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17299     nk_draw_list_init(&ctx->draw_list);
17300 #endif
17301 }
17302 
17303 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
17304 NK_API int
17305 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
17306 {
17307     struct nk_allocator alloc;
17308     alloc.userdata.ptr = 0;
17309     alloc.alloc = nk_malloc;
17310     alloc.free = nk_mfree;
17311     return nk_init(ctx, &alloc, font);
17312 }
17313 #endif
17314 
17315 NK_API int
17316 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
17317     const struct nk_user_font *font)
17318 {
17319     NK_ASSERT(memory);
17320     if (!memory) return 0;
17321     nk_setup(ctx, font);
17322     nk_buffer_init_fixed(&ctx->memory, memory, size);
17323     ctx->use_pool = nk_false;
17324     return 1;
17325 }
17326 
17327 NK_API int
17328 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
17329     struct nk_buffer *pool, const struct nk_user_font *font)
17330 {
17331     NK_ASSERT(cmds);
17332     NK_ASSERT(pool);
17333     if (!cmds || !pool) return 0;
17334 
17335     nk_setup(ctx, font);
17336     ctx->memory = *cmds;
17337     if (pool->type == NK_BUFFER_FIXED) {
17338         /* take memory from buffer and alloc fixed pool */
17339         nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
17340     } else {
17341         /* create dynamic pool from buffer allocator */
17342         struct nk_allocator *alloc = &pool->pool;
17343         nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17344     }
17345     ctx->use_pool = nk_true;
17346     return 1;
17347 }
17348 
17349 NK_API int
17350 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
17351     const struct nk_user_font *font)
17352 {
17353     NK_ASSERT(alloc);
17354     if (!alloc) return 0;
17355     nk_setup(ctx, font);
17356     nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
17357     nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17358     ctx->use_pool = nk_true;
17359     return 1;
17360 }
17361 
17362 #ifdef NK_INCLUDE_COMMAND_USERDATA
17363 NK_API void
17364 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
17365 {
17366     if (!ctx) return;
17367     ctx->userdata = handle;
17368     if (ctx->current)
17369         ctx->current->buffer.userdata = handle;
17370 }
17371 #endif
17372 
17373 NK_API void
17374 nk_free(struct nk_context *ctx)
17375 {
17376     NK_ASSERT(ctx);
17377     if (!ctx) return;
17378     nk_buffer_free(&ctx->memory);
17379     if (ctx->use_pool)
17380         nk_pool_free(&ctx->pool);
17381 
17382     nk_zero(&ctx->input, sizeof(ctx->input));
17383     nk_zero(&ctx->style, sizeof(ctx->style));
17384     nk_zero(&ctx->memory, sizeof(ctx->memory));
17385 
17386     ctx->seq = 0;
17387     ctx->build = 0;
17388     ctx->begin = 0;
17389     ctx->end = 0;
17390     ctx->active = 0;
17391     ctx->current = 0;
17392     ctx->freelist = 0;
17393     ctx->count = 0;
17394 }
17395 
17396 NK_API void
17397 nk_clear(struct nk_context *ctx)
17398 {
17399     struct nk_window *iter;
17400     struct nk_window *next;
17401     NK_ASSERT(ctx);
17402 
17403     if (!ctx) return;
17404     if (ctx->use_pool)
17405         nk_buffer_clear(&ctx->memory);
17406     else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
17407 
17408     ctx->build = 0;
17409     ctx->memory.calls = 0;
17410     ctx->last_widget_state = 0;
17411     ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
17412     NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
17413 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17414     nk_draw_list_clear(&ctx->draw_list);
17415 #endif
17416 
17417     /* garbage collector */
17418     iter = ctx->begin;
17419     while (iter) {
17420         /* make sure valid minimized windows do not get removed */
17421         if ((iter->flags & NK_WINDOW_MINIMIZED) &&
17422             !(iter->flags & NK_WINDOW_CLOSED) &&
17423             iter->seq == ctx->seq) {
17424             iter = iter->next;
17425             continue;
17426         }
17427         /* remove hotness from hidden or closed windows*/
17428         if (((iter->flags & NK_WINDOW_HIDDEN) ||
17429             (iter->flags & NK_WINDOW_CLOSED)) &&
17430             iter == ctx->active) {
17431             ctx->active = iter->prev;
17432             ctx->end = iter->prev;
17433             if (ctx->active)
17434                 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
17435         }
17436         /* free unused popup windows */
17437         if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
17438             nk_free_window(ctx, iter->popup.win);
17439             iter->popup.win = 0;
17440         }
17441         /* remove unused window state tables */
17442         {struct nk_table *n, *it = iter->tables;
17443         while (it) {
17444             n = it->next;
17445             if (it->seq != ctx->seq) {
17446                 nk_remove_table(iter, it);
17447                 nk_zero(it, sizeof(union nk_page_data));
17448                 nk_free_table(ctx, it);
17449                 if (it == iter->tables)
17450                     iter->tables = n;
17451             } it = n;
17452         }}
17453         /* window itself is not used anymore so free */
17454         if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
17455             next = iter->next;
17456             nk_remove_window(ctx, iter);
17457             nk_free_window(ctx, iter);
17458             iter = next;
17459         } else iter = iter->next;
17460     }
17461     ctx->seq++;
17462 }
17463 
17464 /* ----------------------------------------------------------------
17465  *
17466  *                          BUFFERING
17467  *
17468  * ---------------------------------------------------------------*/
17469 NK_INTERN void
17470 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17471 {
17472     NK_ASSERT(ctx);
17473     NK_ASSERT(buffer);
17474     if (!ctx || !buffer) return;
17475     buffer->begin = ctx->memory.allocated;
17476     buffer->end = buffer->begin;
17477     buffer->last = buffer->begin;
17478     buffer->clip = nk_null_rect;
17479 }
17480 
17481 NK_INTERN void
17482 nk_start(struct nk_context *ctx, struct nk_window *win)
17483 {
17484     NK_ASSERT(ctx);
17485     NK_ASSERT(win);
17486     nk_start_buffer(ctx, &win->buffer);
17487 }
17488 
17489 NK_INTERN void
17490 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
17491 {
17492     struct nk_popup_buffer *buf;
17493     NK_ASSERT(ctx);
17494     NK_ASSERT(win);
17495     if (!ctx || !win) return;
17496 
17497     /* save buffer fill state for popup */
17498     buf = &win->popup.buf;
17499     buf->begin = win->buffer.end;
17500     buf->end = win->buffer.end;
17501     buf->parent = win->buffer.last;
17502     buf->last = buf->begin;
17503     buf->active = nk_true;
17504 }
17505 
17506 NK_INTERN void
17507 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
17508 {
17509     struct nk_popup_buffer *buf;
17510     NK_ASSERT(ctx);
17511     NK_ASSERT(win);
17512     if (!ctx || !win) return;
17513 
17514     buf = &win->popup.buf;
17515     buf->last = win->buffer.last;
17516     buf->end = win->buffer.end;
17517 }
17518 
17519 NK_INTERN void
17520 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17521 {
17522     NK_ASSERT(ctx);
17523     NK_ASSERT(buffer);
17524     if (!ctx || !buffer) return;
17525     buffer->end = ctx->memory.allocated;
17526 }
17527 
17528 NK_INTERN void
17529 nk_finish(struct nk_context *ctx, struct nk_window *win)
17530 {
17531     struct nk_popup_buffer *buf;
17532     struct nk_command *parent_last;
17533     void *memory;
17534 
17535     NK_ASSERT(ctx);
17536     NK_ASSERT(win);
17537     if (!ctx || !win) return;
17538     nk_finish_buffer(ctx, &win->buffer);
17539     if (!win->popup.buf.active) return;
17540 
17541     buf = &win->popup.buf;
17542     memory = ctx->memory.memory.ptr;
17543     parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
17544     parent_last->next = buf->end;
17545 }
17546 
17547 NK_INTERN void
17548 nk_build(struct nk_context *ctx)
17549 {
17550     struct nk_window *it = 0;
17551     struct nk_command *cmd = 0;
17552     nk_byte *buffer = 0;
17553 
17554     /* draw cursor overlay */
17555     if (!ctx->style.cursor_active)
17556         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
17557     if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
17558         struct nk_rect mouse_bounds;
17559         const struct nk_cursor *cursor = ctx->style.cursor_active;
17560         nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
17561         nk_start_buffer(ctx, &ctx->overlay);
17562 
17563         mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
17564         mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
17565         mouse_bounds.w = cursor->size.x;
17566         mouse_bounds.h = cursor->size.y;
17567 
17568         nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
17569         nk_finish_buffer(ctx, &ctx->overlay);
17570     }
17571     /* build one big draw command list out of all window buffers */
17572     it = ctx->begin;
17573     buffer = (nk_byte*)ctx->memory.memory.ptr;
17574     while (it != 0) {
17575         struct nk_window *next = it->next;
17576         if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
17577             it->seq != ctx->seq)
17578             goto cont;
17579 
17580         cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
17581         while (next && ((next->buffer.last == next->buffer.begin) ||
17582             (next->flags & NK_WINDOW_HIDDEN)))
17583             next = next->next; /* skip empty command buffers */
17584 
17585         if (next) cmd->next = next->buffer.begin;
17586         cont: it = next;
17587     }
17588     /* append all popup draw commands into lists */
17589     it = ctx->begin;
17590     while (it != 0) {
17591         struct nk_window *next = it->next;
17592         struct nk_popup_buffer *buf;
17593         if (!it->popup.buf.active)
17594             goto skip;
17595 
17596         buf = &it->popup.buf;
17597         cmd->next = buf->begin;
17598         cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
17599         buf->active = nk_false;
17600         skip: it = next;
17601     }
17602     if (cmd) {
17603         /* append overlay commands */
17604         if (ctx->overlay.end != ctx->overlay.begin)
17605             cmd->next = ctx->overlay.begin;
17606         else cmd->next = ctx->memory.allocated;
17607     }
17608 }
17609 
17610 NK_API const struct nk_command*
17611 nk__begin(struct nk_context *ctx)
17612 {
17613     struct nk_window *iter;
17614     nk_byte *buffer;
17615     NK_ASSERT(ctx);
17616     if (!ctx) return 0;
17617     if (!ctx->count) return 0;
17618 
17619     buffer = (nk_byte*)ctx->memory.memory.ptr;
17620     if (!ctx->build) {
17621         nk_build(ctx);
17622         ctx->build = nk_true;
17623     }
17624     iter = ctx->begin;
17625     while (iter && ((iter->buffer.begin == iter->buffer.end) ||
17626         (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
17627         iter = iter->next;
17628     if (!iter) return 0;
17629     return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
17630 }
17631 
17632 NK_API const struct nk_command*
17633 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
17634 {
17635     nk_byte *buffer;
17636     const struct nk_command *next;
17637     NK_ASSERT(ctx);
17638     if (!ctx || !cmd || !ctx->count) return 0;
17639     if (cmd->next >= ctx->memory.allocated) return 0;
17640     buffer = (nk_byte*)ctx->memory.memory.ptr;
17641     next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
17642     return next;
17643 }
17644 
17645 /* ----------------------------------------------------------------
17646  *
17647  *                          PANEL
17648  *
17649  * ---------------------------------------------------------------*/
17650 static int
17651 nk_panel_has_header(nk_flags flags, const char *title)
17652 {
17653     int active = 0;
17654     active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
17655     active = active || (flags & NK_WINDOW_TITLE);
17656     active = active && !(flags & NK_WINDOW_HIDDEN) && title;
17657     return active;
17658 }
17659 
17660 NK_INTERN struct nk_vec2
17661 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
17662 {
17663     switch (type) {
17664     default:
17665     case NK_PANEL_WINDOW: return style->window.padding;
17666     case NK_PANEL_GROUP: return style->window.group_padding;
17667     case NK_PANEL_POPUP: return style->window.popup_padding;
17668     case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
17669     case NK_PANEL_COMBO: return style->window.combo_padding;
17670     case NK_PANEL_MENU: return style->window.menu_padding;
17671     case NK_PANEL_TOOLTIP: return style->window.menu_padding;
17672     }
17673 }
17674 
17675 NK_INTERN float
17676 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
17677     enum nk_panel_type type)
17678 {
17679     if (flags & NK_WINDOW_BORDER) {
17680         switch (type) {
17681         default:
17682         case NK_PANEL_WINDOW: return style->window.border;
17683         case NK_PANEL_GROUP: return style->window.group_border;
17684         case NK_PANEL_POPUP: return style->window.popup_border;
17685         case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
17686         case NK_PANEL_COMBO: return style->window.combo_border;
17687         case NK_PANEL_MENU: return style->window.menu_border;
17688         case NK_PANEL_TOOLTIP: return style->window.menu_border;
17689     }} else return 0;
17690 }
17691 
17692 NK_INTERN struct nk_color
17693 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
17694 {
17695     switch (type) {
17696     default:
17697     case NK_PANEL_WINDOW: return style->window.border_color;
17698     case NK_PANEL_GROUP: return style->window.group_border_color;
17699     case NK_PANEL_POPUP: return style->window.popup_border_color;
17700     case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
17701     case NK_PANEL_COMBO: return style->window.combo_border_color;
17702     case NK_PANEL_MENU: return style->window.menu_border_color;
17703     case NK_PANEL_TOOLTIP: return style->window.menu_border_color;
17704     }
17705 }
17706 
17707 NK_INTERN int
17708 nk_panel_is_sub(enum nk_panel_type type)
17709 {
17710     return (type & NK_PANEL_SET_SUB)?1:0;
17711 }
17712 
17713 NK_INTERN int
17714 nk_panel_is_nonblock(enum nk_panel_type type)
17715 {
17716     return (type & NK_PANEL_SET_NONBLOCK)?1:0;
17717 }
17718 
17719 NK_INTERN int
17720 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
17721 {
17722     struct nk_input *in;
17723     struct nk_window *win;
17724     struct nk_panel *layout;
17725     struct nk_command_buffer *out;
17726     const struct nk_style *style;
17727     const struct nk_user_font *font;
17728 
17729     struct nk_vec2 scrollbar_size;
17730     struct nk_vec2 panel_padding;
17731 
17732     NK_ASSERT(ctx);
17733     NK_ASSERT(ctx->current);
17734     NK_ASSERT(ctx->current->layout);
17735     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
17736     nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
17737     if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
17738         nk_zero(ctx->current->layout, sizeof(struct nk_panel));
17739         ctx->current->layout->type = panel_type;
17740         return 0;
17741     }
17742     /* pull state into local stack */
17743     style = &ctx->style;
17744     font = style->font;
17745     win = ctx->current;
17746     layout = win->layout;
17747     out = &win->buffer;
17748     in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
17749 #ifdef NK_INCLUDE_COMMAND_USERDATA
17750     win->buffer.userdata = ctx->userdata;
17751 #endif
17752     /* pull style configuration into local stack */
17753     scrollbar_size = style->window.scrollbar_size;
17754     panel_padding = nk_panel_get_padding(style, panel_type);
17755 
17756     /* window movement */
17757     if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
17758         int left_mouse_down;
17759         int left_mouse_click_in_cursor;
17760 
17761         /* calculate draggable window space */
17762         struct nk_rect header;
17763         header.x = win->bounds.x;
17764         header.y = win->bounds.y;
17765         header.w = win->bounds.w;
17766         if (nk_panel_has_header(win->flags, title)) {
17767             header.h = font->height + 2.0f * style->window.header.padding.y;
17768             header.h += 2.0f * style->window.header.label_padding.y;
17769         } else header.h = panel_padding.y;
17770 
17771         /* window movement by dragging */
17772         left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
17773         left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
17774             NK_BUTTON_LEFT, header, nk_true);
17775         if (left_mouse_down && left_mouse_click_in_cursor) {
17776             win->bounds.x = win->bounds.x + in->mouse.delta.x;
17777             win->bounds.y = win->bounds.y + in->mouse.delta.y;
17778             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
17779             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
17780             ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
17781         }
17782     }
17783 
17784     /* setup panel */
17785     layout->type = panel_type;
17786     layout->flags = win->flags;
17787     layout->bounds = win->bounds;
17788     layout->bounds.x += panel_padding.x;
17789     layout->bounds.w -= 2*panel_padding.x;
17790     if (win->flags & NK_WINDOW_BORDER) {
17791         layout->border = nk_panel_get_border(style, win->flags, panel_type);
17792         layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
17793     } else layout->border = 0;
17794     layout->at_y = layout->bounds.y;
17795     layout->at_x = layout->bounds.x;
17796     layout->max_x = 0;
17797     layout->header_height = 0;
17798     layout->footer_height = 0;
17799     nk_layout_reset_min_row_height(ctx);
17800     layout->row.index = 0;
17801     layout->row.columns = 0;
17802     layout->row.ratio = 0;
17803     layout->row.item_width = 0;
17804     layout->row.tree_depth = 0;
17805     layout->row.height = panel_padding.y;
17806     layout->has_scrolling = nk_true;
17807     if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
17808         layout->bounds.w -= scrollbar_size.x;
17809     if (!nk_panel_is_nonblock(panel_type)) {
17810         layout->footer_height = 0;
17811         if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
17812             layout->footer_height = scrollbar_size.y;
17813         layout->bounds.h -= layout->footer_height;
17814     }
17815 
17816     /* panel header */
17817     if (nk_panel_has_header(win->flags, title))
17818     {
17819         struct nk_text text;
17820         struct nk_rect header;
17821         const struct nk_style_item *background = 0;
17822 
17823         /* calculate header bounds */
17824         header.x = win->bounds.x;
17825         header.y = win->bounds.y;
17826         header.w = win->bounds.w;
17827         header.h = font->height + 2.0f * style->window.header.padding.y;
17828         header.h += (2.0f * style->window.header.label_padding.y);
17829 
17830         /* shrink panel by header */
17831         layout->header_height = header.h;
17832         layout->bounds.y += header.h;
17833         layout->bounds.h -= header.h;
17834         layout->at_y += header.h;
17835 
17836         /* select correct header background and text color */
17837         if (ctx->active == win) {
17838             background = &style->window.header.active;
17839             text.text = style->window.header.label_active;
17840         } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
17841             background = &style->window.header.hover;
17842             text.text = style->window.header.label_hover;
17843         } else {
17844             background = &style->window.header.normal;
17845             text.text = style->window.header.label_normal;
17846         }
17847 
17848         /* draw header background */
17849         header.h += 1.0f;
17850         if (background->type == NK_STYLE_ITEM_IMAGE) {
17851             text.background = nk_rgba(0,0,0,0);
17852             nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
17853         } else {
17854             text.background = background->data.color;
17855             nk_fill_rect(out, header, 0, background->data.color);
17856         }
17857 
17858         /* window close button */
17859         {struct nk_rect button;
17860         button.y = header.y + style->window.header.padding.y;
17861         button.h = header.h - 2 * style->window.header.padding.y;
17862         button.w = button.h;
17863         if (win->flags & NK_WINDOW_CLOSABLE) {
17864             nk_flags ws = 0;
17865             if (style->window.header.align == NK_HEADER_RIGHT) {
17866                 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
17867                 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
17868             } else {
17869                 button.x = header.x + style->window.header.padding.x;
17870                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17871             }
17872 
17873             if (nk_do_button_symbol(&ws, &win->buffer, button,
17874                 style->window.header.close_symbol, NK_BUTTON_DEFAULT,
17875                 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17876             {
17877                 layout->flags |= NK_WINDOW_HIDDEN;
17878                 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
17879             }
17880         }
17881 
17882         /* window minimize button */
17883         if (win->flags & NK_WINDOW_MINIMIZABLE) {
17884             nk_flags ws = 0;
17885             if (style->window.header.align == NK_HEADER_RIGHT) {
17886                 button.x = (header.w + header.x) - button.w;
17887                 if (!(win->flags & NK_WINDOW_CLOSABLE)) {
17888                     button.x -= style->window.header.padding.x;
17889                     header.w -= style->window.header.padding.x;
17890                 }
17891                 header.w -= button.w + style->window.header.spacing.x;
17892             } else {
17893                 button.x = header.x;
17894                 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17895             }
17896             if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
17897                 style->window.header.maximize_symbol: style->window.header.minimize_symbol,
17898                 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17899                 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
17900                     layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
17901                     layout->flags | NK_WINDOW_MINIMIZED;
17902         }}
17903 
17904         {/* window header title */
17905         int text_len = nk_strlen(title);
17906         struct nk_rect label = {0,0,0,0};
17907         float t = font->width(font->userdata, font->height, title, text_len);
17908         text.padding = nk_vec2(0,0);
17909 
17910         label.x = header.x + style->window.header.padding.x;
17911         label.x += style->window.header.label_padding.x;
17912         label.y = header.y + style->window.header.label_padding.y;
17913         label.h = font->height + 2 * style->window.header.label_padding.y;
17914         label.w = t + 2 * style->window.header.spacing.x;
17915         label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
17916         nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
17917     }
17918 
17919     /* draw window background */
17920     if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
17921         struct nk_rect body;
17922         body.x = win->bounds.x;
17923         body.w = win->bounds.w;
17924         body.y = (win->bounds.y + layout->header_height);
17925         body.h = (win->bounds.h - layout->header_height);
17926         if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE)
17927             nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
17928         else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
17929     }
17930 
17931     /* set clipping rectangle */
17932     {struct nk_rect clip;
17933     layout->clip = layout->bounds;
17934     nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
17935         layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
17936     nk_push_scissor(out, clip);
17937     layout->clip = clip;}
17938     return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
17939 }
17940 
17941 NK_INTERN void
17942 nk_panel_end(struct nk_context *ctx)
17943 {
17944     struct nk_input *in;
17945     struct nk_window *window;
17946     struct nk_panel *layout;
17947     const struct nk_style *style;
17948     struct nk_command_buffer *out;
17949 
17950     struct nk_vec2 scrollbar_size;
17951     struct nk_vec2 panel_padding;
17952 
17953     NK_ASSERT(ctx);
17954     NK_ASSERT(ctx->current);
17955     NK_ASSERT(ctx->current->layout);
17956     if (!ctx || !ctx->current || !ctx->current->layout)
17957         return;
17958 
17959     window = ctx->current;
17960     layout = window->layout;
17961     style = &ctx->style;
17962     out = &window->buffer;
17963     in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
17964     if (!nk_panel_is_sub(layout->type))
17965         nk_push_scissor(out, nk_null_rect);
17966 
17967     /* cache configuration data */
17968     scrollbar_size = style->window.scrollbar_size;
17969     panel_padding = nk_panel_get_padding(style, layout->type);
17970 
17971     /* update the current cursor Y-position to point over the last added widget */
17972     layout->at_y += layout->row.height;
17973 
17974     /* dynamic panels */
17975     if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
17976     {
17977         /* update panel height to fit dynamic growth */
17978         struct nk_rect empty_space;
17979         if (layout->at_y < (layout->bounds.y + layout->bounds.h))
17980             layout->bounds.h = layout->at_y - layout->bounds.y;
17981 
17982         /* fill top empty space */
17983         empty_space.x = window->bounds.x;
17984         empty_space.y = layout->bounds.y;
17985         empty_space.h = panel_padding.y;
17986         empty_space.w = window->bounds.w;
17987         nk_fill_rect(out, empty_space, 0, style->window.background);
17988 
17989         /* fill left empty space */
17990         empty_space.x = window->bounds.x;
17991         empty_space.y = layout->bounds.y;
17992         empty_space.w = panel_padding.x + layout->border;
17993         empty_space.h = layout->bounds.h;
17994         nk_fill_rect(out, empty_space, 0, style->window.background);
17995 
17996         /* fill right empty space */
17997         empty_space.x = layout->bounds.x + layout->bounds.w - layout->border;
17998         empty_space.y = layout->bounds.y;
17999         empty_space.w = panel_padding.x + layout->border;
18000         empty_space.h = layout->bounds.h;
18001         if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
18002             empty_space.w += scrollbar_size.x;
18003         nk_fill_rect(out, empty_space, 0, style->window.background);
18004 
18005         /* fill bottom empty space */
18006         if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) {
18007             empty_space.x = window->bounds.x;
18008             empty_space.y = layout->bounds.y + layout->bounds.h;
18009             empty_space.w = window->bounds.w;
18010             empty_space.h = scrollbar_size.y;
18011             nk_fill_rect(out, empty_space, 0, style->window.background);
18012         }
18013     }
18014 
18015     /* scrollbars */
18016     if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
18017         !(layout->flags & NK_WINDOW_MINIMIZED) &&
18018         window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
18019     {
18020         struct nk_rect scroll;
18021         int scroll_has_scrolling;
18022         float scroll_target;
18023         float scroll_offset;
18024         float scroll_step;
18025         float scroll_inc;
18026 
18027         /* mouse wheel scrolling */
18028         if (nk_panel_is_sub(layout->type))
18029         {
18030             /* sub-window mouse wheel scrolling */
18031             struct nk_window *root_window = window;
18032             struct nk_panel *root_panel = window->layout;
18033             while (root_panel->parent)
18034                 root_panel = root_panel->parent;
18035             while (root_window->parent)
18036                 root_window = root_window->parent;
18037 
18038             /* only allow scrolling if parent window is active */
18039             scroll_has_scrolling = 0;
18040             if ((root_window == ctx->active) && layout->has_scrolling) {
18041                 /* and panel is being hovered and inside clip rect*/
18042                 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
18043                     NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
18044                         root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
18045                 {
18046                     /* deactivate all parent scrolling */
18047                     root_panel = window->layout;
18048                     while (root_panel->parent) {
18049                         root_panel->has_scrolling = nk_false;
18050                         root_panel = root_panel->parent;
18051                     }
18052                     root_panel->has_scrolling = nk_false;
18053                     scroll_has_scrolling = nk_true;
18054                 }
18055             }
18056         } else if (!nk_panel_is_sub(layout->type)) {
18057             /* window mouse wheel scrolling */
18058             scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
18059             if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
18060                 window->scrolled = nk_true;
18061             else window->scrolled = nk_false;
18062         } else scroll_has_scrolling = nk_false;
18063 
18064         {
18065             /* vertical scrollbar */
18066             nk_flags state = 0;
18067             scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
18068             scroll.y = layout->bounds.y;
18069             scroll.w = scrollbar_size.x;
18070             scroll.h = layout->bounds.h;
18071 
18072             scroll_offset = (float)*layout->offset_y;
18073             scroll_step = scroll.h * 0.10f;
18074             scroll_inc = scroll.h * 0.01f;
18075             scroll_target = (float)(int)(layout->at_y - scroll.y);
18076             scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
18077                 scroll_offset, scroll_target, scroll_step, scroll_inc,
18078                 &ctx->style.scrollv, in, style->font);
18079             *layout->offset_y = (nk_uint)scroll_offset;
18080             if (in && scroll_has_scrolling)
18081                 in->mouse.scroll_delta.y = 0;
18082         }
18083         {
18084             /* horizontal scrollbar */
18085             nk_flags state = 0;
18086             scroll.x = layout->bounds.x;
18087             scroll.y = layout->bounds.y + layout->bounds.h;
18088             scroll.w = layout->bounds.w;
18089             scroll.h = scrollbar_size.y;
18090 
18091             scroll_offset = (float)*layout->offset_x;
18092             scroll_target = (float)(int)(layout->max_x - scroll.x);
18093             scroll_step = layout->max_x * 0.05f;
18094             scroll_inc = layout->max_x * 0.005f;
18095             scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
18096                 scroll_offset, scroll_target, scroll_step, scroll_inc,
18097                 &ctx->style.scrollh, in, style->font);
18098             *layout->offset_x = (nk_uint)scroll_offset;
18099         }
18100     }
18101 
18102     /* hide scroll if no user input */
18103     if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
18104         int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
18105         int is_window_hovered = nk_window_is_hovered(ctx);
18106         int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
18107         if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
18108             window->scrollbar_hiding_timer += ctx->delta_time_seconds;
18109         else window->scrollbar_hiding_timer = 0;
18110     } else window->scrollbar_hiding_timer = 0;
18111 
18112     /* window border */
18113     if (layout->flags & NK_WINDOW_BORDER)
18114     {
18115         struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
18116         const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) ?
18117             style->window.border + window->bounds.y + layout->header_height:
18118             (layout->flags & NK_WINDOW_DYNAMIC)?
18119             layout->bounds.y + layout->bounds.h + layout->footer_height:
18120             window->bounds.y + window->bounds.h;
18121 
18122         /* draw border top */
18123         nk_stroke_line(out,window->bounds.x,window->bounds.y,
18124             window->bounds.x + window->bounds.w, window->bounds.y,
18125             layout->border, border_color);
18126 
18127         /* draw bottom border */
18128         nk_stroke_line(out, window->bounds.x, padding_y,
18129             window->bounds.x + window->bounds.w, padding_y, layout->border, border_color);
18130 
18131         /* draw left border */
18132         nk_stroke_line(out, window->bounds.x + layout->border*0.5f,
18133             window->bounds.y, window->bounds.x + layout->border*0.5f,
18134             padding_y, layout->border, border_color);
18135 
18136         /* draw right border */
18137         nk_stroke_line(out, window->bounds.x + window->bounds.w - layout->border*0.5f,
18138             window->bounds.y, window->bounds.x + window->bounds.w - layout->border*0.5f,
18139             padding_y, layout->border, border_color);
18140     }
18141 
18142     /* scaler */
18143     if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
18144     {
18145         /* calculate scaler bounds */
18146         struct nk_rect scaler;
18147         scaler.w = scrollbar_size.x;
18148         scaler.h = scrollbar_size.y;
18149         scaler.y = layout->bounds.y + layout->bounds.h;
18150         if (layout->flags & NK_WINDOW_SCALE_LEFT)
18151             scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
18152         else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
18153         if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
18154             scaler.x -= scaler.w;
18155 
18156         /* draw scaler */
18157         {const struct nk_style_item *item = &style->window.scaler;
18158         if (item->type == NK_STYLE_ITEM_IMAGE)
18159             nk_draw_image(out, scaler, &item->data.image, nk_white);
18160         else {
18161             if (layout->flags & NK_WINDOW_SCALE_LEFT) {
18162                 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
18163                     scaler.y + scaler.h, scaler.x + scaler.w,
18164                     scaler.y + scaler.h, item->data.color);
18165             } else {
18166                 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
18167                     scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
18168             }
18169         }}
18170 
18171         /* do window scaling */
18172         if (!(window->flags & NK_WINDOW_ROM)) {
18173             struct nk_vec2 window_size = style->window.min_size;
18174             int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
18175             int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
18176                     NK_BUTTON_LEFT, scaler, nk_true);
18177 
18178             if (left_mouse_down && left_mouse_click_in_scaler) {
18179                 float delta_x = in->mouse.delta.x;
18180                 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
18181                     delta_x = -delta_x;
18182                     window->bounds.x += in->mouse.delta.x;
18183                 }
18184                 /* dragging in x-direction  */
18185                 if (window->bounds.w + delta_x >= window_size.x) {
18186                     if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
18187                         window->bounds.w = window->bounds.w + delta_x;
18188                         scaler.x += in->mouse.delta.x;
18189                     }
18190                 }
18191                 /* dragging in y-direction (only possible if static window) */
18192                 if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
18193                     if (window_size.y < window->bounds.h + in->mouse.delta.y) {
18194                         if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
18195                             window->bounds.h = window->bounds.h + in->mouse.delta.y;
18196                             scaler.y += in->mouse.delta.y;
18197                         }
18198                     }
18199                 }
18200                 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
18201                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
18202                 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
18203             }
18204         }
18205     }
18206     if (!nk_panel_is_sub(layout->type)) {
18207         /* window is hidden so clear command buffer  */
18208         if (layout->flags & NK_WINDOW_HIDDEN)
18209             nk_command_buffer_reset(&window->buffer);
18210         /* window is visible and not tab */
18211         else nk_finish(ctx, window);
18212     }
18213 
18214     /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
18215     if (layout->flags & NK_WINDOW_REMOVE_ROM) {
18216         layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
18217         layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
18218     }
18219     window->flags = layout->flags;
18220 
18221     /* property garbage collector */
18222     if (window->property.active && window->property.old != window->property.seq &&
18223         window->property.active == window->property.prev) {
18224         nk_zero(&window->property, sizeof(window->property));
18225     } else {
18226         window->property.old = window->property.seq;
18227         window->property.prev = window->property.active;
18228         window->property.seq = 0;
18229     }
18230     /* edit garbage collector */
18231     if (window->edit.active && window->edit.old != window->edit.seq &&
18232        window->edit.active == window->edit.prev) {
18233         nk_zero(&window->edit, sizeof(window->edit));
18234     } else {
18235         window->edit.old = window->edit.seq;
18236         window->edit.prev = window->edit.active;
18237         window->edit.seq = 0;
18238     }
18239     /* contextual garbage collector */
18240     if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
18241         window->popup.con_count = 0;
18242         window->popup.con_old = 0;
18243         window->popup.active_con = 0;
18244     } else {
18245         window->popup.con_old = window->popup.con_count;
18246         window->popup.con_count = 0;
18247     }
18248     window->popup.combo_count = 0;
18249     /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
18250     NK_ASSERT(!layout->row.tree_depth);
18251 }
18252 
18253 /* ----------------------------------------------------------------
18254  *
18255  *                          PAGE ELEMENT
18256  *
18257  * ---------------------------------------------------------------*/
18258 NK_INTERN struct nk_page_element*
18259 nk_create_page_element(struct nk_context *ctx)
18260 {
18261     struct nk_page_element *elem;
18262     if (ctx->freelist) {
18263         /* unlink page element from free list */
18264         elem = ctx->freelist;
18265         ctx->freelist = elem->next;
18266     } else if (ctx->use_pool) {
18267         /* allocate page element from memory pool */
18268         elem = nk_pool_alloc(&ctx->pool);
18269         NK_ASSERT(elem);
18270         if (!elem) return 0;
18271     } else {
18272         /* allocate new page element from back of fixed size memory buffer */
18273         NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
18274         NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
18275         elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
18276         NK_ASSERT(elem);
18277         if (!elem) return 0;
18278     }
18279     nk_zero_struct(*elem);
18280     elem->next = 0;
18281     elem->prev = 0;
18282     return elem;
18283 }
18284 
18285 NK_INTERN void
18286 nk_link_page_element_into_freelist(struct nk_context *ctx,
18287     struct nk_page_element *elem)
18288 {
18289     /* link table into freelist */
18290     if (!ctx->freelist) {
18291         ctx->freelist = elem;
18292     } else {
18293         elem->next = ctx->freelist;
18294         ctx->freelist = elem;
18295     }
18296 }
18297 
18298 NK_INTERN void
18299 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
18300 {
18301     /* we have a pool so just add to free list */
18302     if (ctx->use_pool) {
18303         nk_link_page_element_into_freelist(ctx, elem);
18304         return;
18305     }
18306     /* if possible remove last element from back of fixed memory buffer */
18307     {void *elem_end = (void*)(elem + 1);
18308     void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
18309     if (elem_end == buffer_end)
18310         ctx->memory.size -= sizeof(struct nk_page_element);
18311     else nk_link_page_element_into_freelist(ctx, elem);}
18312 }
18313 
18314 /* ----------------------------------------------------------------
18315  *
18316  *                          PANEL
18317  *
18318  * ---------------------------------------------------------------*/
18319 NK_INTERN void*
18320 nk_create_panel(struct nk_context *ctx)
18321 {
18322     struct nk_page_element *elem;
18323     elem = nk_create_page_element(ctx);
18324     if (!elem) return 0;
18325     nk_zero_struct(*elem);
18326     return &elem->data.pan;
18327 }
18328 
18329 NK_INTERN void
18330 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
18331 {
18332     union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
18333     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18334     nk_free_page_element(ctx, pe);
18335 }
18336 
18337 /* ----------------------------------------------------------------
18338  *
18339  *                          TABLES
18340  *
18341  * ---------------------------------------------------------------*/
18342 NK_INTERN struct nk_table*
18343 nk_create_table(struct nk_context *ctx)
18344 {
18345     struct nk_page_element *elem;
18346     elem = nk_create_page_element(ctx);
18347     if (!elem) return 0;
18348     nk_zero_struct(*elem);
18349     return &elem->data.tbl;
18350 }
18351 
18352 NK_INTERN void
18353 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
18354 {
18355     union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
18356     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18357     nk_free_page_element(ctx, pe);
18358 }
18359 
18360 NK_INTERN void
18361 nk_push_table(struct nk_window *win, struct nk_table *tbl)
18362 {
18363     if (!win->tables) {
18364         win->tables = tbl;
18365         tbl->next = 0;
18366         tbl->prev = 0;
18367         tbl->size = 0;
18368         win->table_count = 1;
18369         return;
18370     }
18371     win->tables->prev = tbl;
18372     tbl->next = win->tables;
18373     tbl->prev = 0;
18374     tbl->size = 0;
18375     win->tables = tbl;
18376     win->table_count++;
18377 }
18378 
18379 NK_INTERN void
18380 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
18381 {
18382     if (win->tables == tbl)
18383         win->tables = tbl->next;
18384     if (tbl->next)
18385         tbl->next->prev = tbl->prev;
18386     if (tbl->prev)
18387         tbl->prev->next = tbl->next;
18388     tbl->next = 0;
18389     tbl->prev = 0;
18390 }
18391 
18392 NK_INTERN nk_uint*
18393 nk_add_value(struct nk_context *ctx, struct nk_window *win,
18394             nk_hash name, nk_uint value)
18395 {
18396     NK_ASSERT(ctx);
18397     NK_ASSERT(win);
18398     if (!win || !ctx) return 0;
18399     if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
18400         struct nk_table *tbl = nk_create_table(ctx);
18401         NK_ASSERT(tbl);
18402         if (!tbl) return 0;
18403         nk_push_table(win, tbl);
18404     }
18405     win->tables->seq = win->seq;
18406     win->tables->keys[win->tables->size] = name;
18407     win->tables->values[win->tables->size] = value;
18408     return &win->tables->values[win->tables->size++];
18409 }
18410 
18411 NK_INTERN nk_uint*
18412 nk_find_value(struct nk_window *win, nk_hash name)
18413 {
18414     struct nk_table *iter = win->tables;
18415     while (iter) {
18416         unsigned int i = 0;
18417         unsigned int size = iter->size;
18418         for (i = 0; i < size; ++i) {
18419             if (iter->keys[i] == name) {
18420                 iter->seq = win->seq;
18421                 return &iter->values[i];
18422             }
18423         } size = NK_VALUE_PAGE_CAPACITY;
18424         iter = iter->next;
18425     }
18426     return 0;
18427 }
18428 
18429 /* ----------------------------------------------------------------
18430  *
18431  *                          WINDOW
18432  *
18433  * ---------------------------------------------------------------*/
18434 NK_INTERN void*
18435 nk_create_window(struct nk_context *ctx)
18436 {
18437     struct nk_page_element *elem;
18438     elem = nk_create_page_element(ctx);
18439     if (!elem) return 0;
18440     elem->data.win.seq = ctx->seq;
18441     return &elem->data.win;
18442 }
18443 
18444 NK_INTERN void
18445 nk_free_window(struct nk_context *ctx, struct nk_window *win)
18446 {
18447     /* unlink windows from list */
18448     struct nk_table *it = win->tables;
18449     if (win->popup.win) {
18450         nk_free_window(ctx, win->popup.win);
18451         win->popup.win = 0;
18452     }
18453     win->next = 0;
18454     win->prev = 0;
18455 
18456     while (it) {
18457         /*free window state tables */
18458         struct nk_table *n = it->next;
18459         nk_remove_table(win, it);
18460         nk_free_table(ctx, it);
18461         if (it == win->tables)
18462             win->tables = n;
18463         it = n;
18464     }
18465 
18466     /* link windows into freelist */
18467     {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
18468     struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18469     nk_free_page_element(ctx, pe);}
18470 }
18471 
18472 NK_INTERN struct nk_window*
18473 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
18474 {
18475     struct nk_window *iter;
18476     iter = ctx->begin;
18477     while (iter) {
18478         NK_ASSERT(iter != iter->next);
18479         if (iter->name == hash) {
18480             int max_len = nk_strlen(iter->name_string);
18481             if (!nk_stricmpn(iter->name_string, name, max_len))
18482                 return iter;
18483         }
18484         iter = iter->next;
18485     }
18486     return 0;
18487 }
18488 
18489 enum nk_window_insert_location {
18490     NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
18491     NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
18492 };
18493 NK_INTERN void
18494 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
18495     enum nk_window_insert_location loc)
18496 {
18497     const struct nk_window *iter;
18498     NK_ASSERT(ctx);
18499     NK_ASSERT(win);
18500     if (!win || !ctx) return;
18501 
18502     iter = ctx->begin;
18503     while (iter) {
18504         NK_ASSERT(iter != iter->next);
18505         NK_ASSERT(iter != win);
18506         if (iter == win) return;
18507         iter = iter->next;
18508     }
18509 
18510     if (!ctx->begin) {
18511         win->next = 0;
18512         win->prev = 0;
18513         ctx->begin = win;
18514         ctx->end = win;
18515         ctx->count = 1;
18516         return;
18517     }
18518     if (loc == NK_INSERT_BACK) {
18519         struct nk_window *end;
18520         end = ctx->end;
18521         end->flags |= NK_WINDOW_ROM;
18522         end->next = win;
18523         win->prev = ctx->end;
18524         win->next = 0;
18525         ctx->end = win;
18526         ctx->active = ctx->end;
18527         ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18528     } else {
18529         /*ctx->end->flags |= NK_WINDOW_ROM;*/
18530         ctx->begin->prev = win;
18531         win->next = ctx->begin;
18532         win->prev = 0;
18533         ctx->begin = win;
18534         ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
18535     }
18536     ctx->count++;
18537 }
18538 
18539 NK_INTERN void
18540 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
18541 {
18542     if (win == ctx->begin || win == ctx->end) {
18543         if (win == ctx->begin) {
18544             ctx->begin = win->next;
18545             if (win->next)
18546                 win->next->prev = 0;
18547         }
18548         if (win == ctx->end) {
18549             ctx->end = win->prev;
18550             if (win->prev)
18551                 win->prev->next = 0;
18552         }
18553     } else {
18554         if (win->next)
18555             win->next->prev = win->prev;
18556         if (win->prev)
18557             win->prev->next = win->next;
18558     }
18559     if (win == ctx->active || !ctx->active) {
18560         ctx->active = ctx->end;
18561         if (ctx->end)
18562             ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18563     }
18564     win->next = 0;
18565     win->prev = 0;
18566     ctx->count--;
18567 }
18568 
18569 NK_API int
18570 nk_begin(struct nk_context *ctx, const char *title,
18571     struct nk_rect bounds, nk_flags flags)
18572 {
18573     return nk_begin_titled(ctx, title, title, bounds, flags);
18574 }
18575 
18576 NK_API int
18577 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
18578     struct nk_rect bounds, nk_flags flags)
18579 {
18580     struct nk_window *win;
18581     struct nk_style *style;
18582     nk_hash title_hash;
18583     int title_len;
18584     int ret = 0;
18585 
18586     NK_ASSERT(ctx);
18587     NK_ASSERT(name);
18588     NK_ASSERT(title);
18589     NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
18590     NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
18591     if (!ctx || ctx->current || !title || !name)
18592         return 0;
18593 
18594     /* find or create window */
18595     style = &ctx->style;
18596     title_len = (int)nk_strlen(name);
18597     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18598     win = nk_find_window(ctx, title_hash, name);
18599     if (!win) {
18600         /* create new window */
18601         nk_size name_length = (nk_size)nk_strlen(name);
18602         win = (struct nk_window*)nk_create_window(ctx);
18603         NK_ASSERT(win);
18604         if (!win) return 0;
18605 
18606         if (flags & NK_WINDOW_BACKGROUND)
18607             nk_insert_window(ctx, win, NK_INSERT_FRONT);
18608         else nk_insert_window(ctx, win, NK_INSERT_BACK);
18609         nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
18610 
18611         win->flags = flags;
18612         win->bounds = bounds;
18613         win->name = title_hash;
18614         name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
18615         NK_MEMCPY(win->name_string, name, name_length);
18616         win->name_string[name_length] = 0;
18617         win->popup.win = 0;
18618         if (!ctx->active)
18619             ctx->active = win;
18620     } else {
18621         /* update window */
18622         win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
18623         win->flags |= flags;
18624         if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
18625             win->bounds = bounds;
18626         /* If this assert triggers you either:
18627          *
18628          * I.) Have more than one window with the same name or
18629          * II.) You forgot to actually draw the window.
18630          *      More specific you did not call `nk_clear` (nk_clear will be
18631          *      automatically called for you if you are using one of the
18632          *      provided demo backends). */
18633         NK_ASSERT(win->seq != ctx->seq);
18634         win->seq = ctx->seq;
18635         if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
18636             ctx->active = win;
18637             ctx->end = win;
18638         }
18639     }
18640     if (win->flags & NK_WINDOW_HIDDEN) {
18641         ctx->current = win;
18642         win->layout = 0;
18643         return 0;
18644     } else nk_start(ctx, win);
18645 
18646     /* window overlapping */
18647     if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
18648     {
18649         int inpanel, ishovered;
18650         struct nk_window *iter = win;
18651         float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
18652             (2.0f * style->window.header.label_padding.y);
18653         struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
18654             win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
18655 
18656         /* activate window if hovered and no other window is overlapping this window */
18657         inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
18658         inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
18659         ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
18660         if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
18661             iter = win->next;
18662             while (iter) {
18663                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18664                     iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18665                 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18666                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18667                     (!(iter->flags & NK_WINDOW_HIDDEN)))
18668                     break;
18669 
18670                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18671                     NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18672                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18673                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18674                     break;
18675                 iter = iter->next;
18676             }
18677         }
18678 
18679         /* activate window if clicked */
18680         if (iter && inpanel && (win != ctx->end)) {
18681             iter = win->next;
18682             while (iter) {
18683                 /* try to find a panel with higher priority in the same position */
18684                 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18685                 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18686                 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
18687                     iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18688                     !(iter->flags & NK_WINDOW_HIDDEN))
18689                     break;
18690                 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18691                     NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18692                     iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18693                     iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18694                     break;
18695                 iter = iter->next;
18696             }
18697         }
18698         if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
18699             win->flags |= (nk_flags)NK_WINDOW_ROM;
18700             iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
18701             ctx->active = iter;
18702             if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
18703                 /* current window is active in that position so transfer to top
18704                  * at the highest priority in stack */
18705                 nk_remove_window(ctx, iter);
18706                 nk_insert_window(ctx, iter, NK_INSERT_BACK);
18707             }
18708         } else {
18709             if (!iter && ctx->end != win) {
18710                 if (!(win->flags & NK_WINDOW_BACKGROUND)) {
18711                     /* current window is active in that position so transfer to top
18712                      * at the highest priority in stack */
18713                     nk_remove_window(ctx, win);
18714                     nk_insert_window(ctx, win, NK_INSERT_BACK);
18715                 }
18716                 win->flags &= ~(nk_flags)NK_WINDOW_ROM;
18717                 ctx->active = win;
18718             }
18719             if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
18720                 win->flags |= NK_WINDOW_ROM;
18721         }
18722     }
18723     win->layout = (struct nk_panel*)nk_create_panel(ctx);
18724     ctx->current = win;
18725     ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
18726     win->layout->offset_x = &win->scrollbar.x;
18727     win->layout->offset_y = &win->scrollbar.y;
18728     return ret;
18729 }
18730 
18731 NK_API void
18732 nk_end(struct nk_context *ctx)
18733 {
18734     struct nk_panel *layout;
18735     NK_ASSERT(ctx);
18736     NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
18737     if (!ctx || !ctx->current)
18738         return;
18739 
18740     layout = ctx->current->layout;
18741     if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
18742         ctx->current = 0;
18743         return;
18744     }
18745     nk_panel_end(ctx);
18746     nk_free_panel(ctx, ctx->current->layout);
18747     ctx->current = 0;
18748 }
18749 
18750 NK_API struct nk_rect
18751 nk_window_get_bounds(const struct nk_context *ctx)
18752 {
18753     NK_ASSERT(ctx);
18754     NK_ASSERT(ctx->current);
18755     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18756     return ctx->current->bounds;
18757 }
18758 
18759 NK_API struct nk_vec2
18760 nk_window_get_position(const struct nk_context *ctx)
18761 {
18762     NK_ASSERT(ctx);
18763     NK_ASSERT(ctx->current);
18764     if (!ctx || !ctx->current) return nk_vec2(0,0);
18765     return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
18766 }
18767 
18768 NK_API struct nk_vec2
18769 nk_window_get_size(const struct nk_context *ctx)
18770 {
18771     NK_ASSERT(ctx);
18772     NK_ASSERT(ctx->current);
18773     if (!ctx || !ctx->current) return nk_vec2(0,0);
18774     return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
18775 }
18776 
18777 NK_API float
18778 nk_window_get_width(const struct nk_context *ctx)
18779 {
18780     NK_ASSERT(ctx);
18781     NK_ASSERT(ctx->current);
18782     if (!ctx || !ctx->current) return 0;
18783     return ctx->current->bounds.w;
18784 }
18785 
18786 NK_API float
18787 nk_window_get_height(const struct nk_context *ctx)
18788 {
18789     NK_ASSERT(ctx);
18790     NK_ASSERT(ctx->current);
18791     if (!ctx || !ctx->current) return 0;
18792     return ctx->current->bounds.h;
18793 }
18794 
18795 NK_API struct nk_rect
18796 nk_window_get_content_region(struct nk_context *ctx)
18797 {
18798     NK_ASSERT(ctx);
18799     NK_ASSERT(ctx->current);
18800     if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18801     return ctx->current->layout->clip;
18802 }
18803 
18804 NK_API struct nk_vec2
18805 nk_window_get_content_region_min(struct nk_context *ctx)
18806 {
18807     NK_ASSERT(ctx);
18808     NK_ASSERT(ctx->current);
18809     NK_ASSERT(ctx->current->layout);
18810     if (!ctx || !ctx->current) return nk_vec2(0,0);
18811     return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
18812 }
18813 
18814 NK_API struct nk_vec2
18815 nk_window_get_content_region_max(struct nk_context *ctx)
18816 {
18817     NK_ASSERT(ctx);
18818     NK_ASSERT(ctx->current);
18819     NK_ASSERT(ctx->current->layout);
18820     if (!ctx || !ctx->current) return nk_vec2(0,0);
18821     return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
18822         ctx->current->layout->clip.y + ctx->current->layout->clip.h);
18823 }
18824 
18825 NK_API struct nk_vec2
18826 nk_window_get_content_region_size(struct nk_context *ctx)
18827 {
18828     NK_ASSERT(ctx);
18829     NK_ASSERT(ctx->current);
18830     NK_ASSERT(ctx->current->layout);
18831     if (!ctx || !ctx->current) return nk_vec2(0,0);
18832     return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
18833 }
18834 
18835 NK_API struct nk_command_buffer*
18836 nk_window_get_canvas(struct nk_context *ctx)
18837 {
18838     NK_ASSERT(ctx);
18839     NK_ASSERT(ctx->current);
18840     NK_ASSERT(ctx->current->layout);
18841     if (!ctx || !ctx->current) return 0;
18842     return &ctx->current->buffer;
18843 }
18844 
18845 NK_API struct nk_panel*
18846 nk_window_get_panel(struct nk_context *ctx)
18847 {
18848     NK_ASSERT(ctx);
18849     NK_ASSERT(ctx->current);
18850     if (!ctx || !ctx->current) return 0;
18851     return ctx->current->layout;
18852 }
18853 
18854 NK_API int
18855 nk_window_has_focus(const struct nk_context *ctx)
18856 {
18857     NK_ASSERT(ctx);
18858     NK_ASSERT(ctx->current);
18859     NK_ASSERT(ctx->current->layout);
18860     if (!ctx || !ctx->current) return 0;
18861     return ctx->current == ctx->active;
18862 }
18863 
18864 NK_API int
18865 nk_window_is_hovered(struct nk_context *ctx)
18866 {
18867     NK_ASSERT(ctx);
18868     NK_ASSERT(ctx->current);
18869     if (!ctx || !ctx->current) return 0;
18870     if(ctx->current->flags & NK_WINDOW_HIDDEN)
18871         return 0;
18872     return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
18873 }
18874 
18875 NK_API int
18876 nk_window_is_any_hovered(struct nk_context *ctx)
18877 {
18878     struct nk_window *iter;
18879     NK_ASSERT(ctx);
18880     if (!ctx) return 0;
18881     iter = ctx->begin;
18882     while (iter) {
18883         /* check if window is being hovered */
18884         if(!(iter->flags & NK_WINDOW_HIDDEN)) {
18885             /* check if window popup is being hovered */
18886             if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
18887                 return 1;
18888 
18889             if (iter->flags & NK_WINDOW_MINIMIZED) {
18890                 struct nk_rect header = iter->bounds;
18891                 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
18892                 if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
18893                     return 1;
18894             } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
18895                 return 1;
18896             }
18897         }
18898         iter = iter->next;
18899     }
18900     return 0;
18901 }
18902 
18903 NK_API int
18904 nk_item_is_any_active(struct nk_context *ctx)
18905 {
18906     int any_hovered = nk_window_is_any_hovered(ctx);
18907     int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
18908     return any_hovered || any_active;
18909 }
18910 
18911 NK_API int
18912 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
18913 {
18914     int title_len;
18915     nk_hash title_hash;
18916     struct nk_window *win;
18917     NK_ASSERT(ctx);
18918     if (!ctx) return 0;
18919 
18920     title_len = (int)nk_strlen(name);
18921     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18922     win = nk_find_window(ctx, title_hash, name);
18923     if (!win) return 0;
18924     return win->flags & NK_WINDOW_MINIMIZED;
18925 }
18926 
18927 NK_API int
18928 nk_window_is_closed(struct nk_context *ctx, const char *name)
18929 {
18930     int title_len;
18931     nk_hash title_hash;
18932     struct nk_window *win;
18933     NK_ASSERT(ctx);
18934     if (!ctx) return 1;
18935 
18936     title_len = (int)nk_strlen(name);
18937     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18938     win = nk_find_window(ctx, title_hash, name);
18939     if (!win) return 1;
18940     return (win->flags & NK_WINDOW_CLOSED);
18941 }
18942 
18943 NK_API int
18944 nk_window_is_hidden(struct nk_context *ctx, const char *name)
18945 {
18946     int title_len;
18947     nk_hash title_hash;
18948     struct nk_window *win;
18949     NK_ASSERT(ctx);
18950     if (!ctx) return 1;
18951 
18952     title_len = (int)nk_strlen(name);
18953     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18954     win = nk_find_window(ctx, title_hash, name);
18955     if (!win) return 1;
18956     return (win->flags & NK_WINDOW_HIDDEN);
18957 }
18958 
18959 NK_API int
18960 nk_window_is_active(struct nk_context *ctx, const char *name)
18961 {
18962     int title_len;
18963     nk_hash title_hash;
18964     struct nk_window *win;
18965     NK_ASSERT(ctx);
18966     if (!ctx) return 0;
18967 
18968     title_len = (int)nk_strlen(name);
18969     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18970     win = nk_find_window(ctx, title_hash, name);
18971     if (!win) return 0;
18972     return win == ctx->active;
18973 }
18974 
18975 NK_API struct nk_window*
18976 nk_window_find(struct nk_context *ctx, const char *name)
18977 {
18978     int title_len;
18979     nk_hash title_hash;
18980     title_len = (int)nk_strlen(name);
18981     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18982     return nk_find_window(ctx, title_hash, name);
18983 }
18984 
18985 NK_API void
18986 nk_window_close(struct nk_context *ctx, const char *name)
18987 {
18988     struct nk_window *win;
18989     NK_ASSERT(ctx);
18990     if (!ctx) return;
18991     win = nk_window_find(ctx, name);
18992     if (!win) return;
18993     NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
18994     if (ctx->current == win) return;
18995     win->flags |= NK_WINDOW_HIDDEN;
18996     win->flags |= NK_WINDOW_CLOSED;
18997 }
18998 
18999 NK_API void
19000 nk_window_set_bounds(struct nk_context *ctx,
19001     const char *name, struct nk_rect bounds)
19002 {
19003     struct nk_window *win;
19004     NK_ASSERT(ctx);
19005     if (!ctx) return;
19006     win = nk_window_find(ctx, name);
19007     if (!win) return;
19008     NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
19009     win->bounds = bounds;
19010 }
19011 
19012 NK_API void
19013 nk_window_set_position(struct nk_context *ctx,
19014     const char *name, struct nk_vec2 pos)
19015 {
19016     struct nk_window *win = nk_window_find(ctx, name);
19017     if (!win) return;
19018     win->bounds.x = pos.x;
19019     win->bounds.y = pos.y;
19020 }
19021 
19022 NK_API void
19023 nk_window_set_size(struct nk_context *ctx,
19024     const char *name, struct nk_vec2 size)
19025 {
19026     struct nk_window *win = nk_window_find(ctx, name);
19027     if (!win) return;
19028     win->bounds.w = size.x;
19029     win->bounds.h = size.y;
19030 }
19031 
19032 NK_API void
19033 nk_window_collapse(struct nk_context *ctx, const char *name,
19034                     enum nk_collapse_states c)
19035 {
19036     int title_len;
19037     nk_hash title_hash;
19038     struct nk_window *win;
19039     NK_ASSERT(ctx);
19040     if (!ctx) return;
19041 
19042     title_len = (int)nk_strlen(name);
19043     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
19044     win = nk_find_window(ctx, title_hash, name);
19045     if (!win) return;
19046     if (c == NK_MINIMIZED)
19047         win->flags |= NK_WINDOW_MINIMIZED;
19048     else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
19049 }
19050 
19051 NK_API void
19052 nk_window_collapse_if(struct nk_context *ctx, const char *name,
19053     enum nk_collapse_states c, int cond)
19054 {
19055     NK_ASSERT(ctx);
19056     if (!ctx || !cond) return;
19057     nk_window_collapse(ctx, name, c);
19058 }
19059 
19060 NK_API void
19061 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
19062 {
19063     int title_len;
19064     nk_hash title_hash;
19065     struct nk_window *win;
19066     NK_ASSERT(ctx);
19067     if (!ctx) return;
19068 
19069     title_len = (int)nk_strlen(name);
19070     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
19071     win = nk_find_window(ctx, title_hash, name);
19072     if (!win) return;
19073     if (s == NK_HIDDEN) {
19074         win->flags |= NK_WINDOW_HIDDEN;
19075     } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
19076 }
19077 
19078 NK_API void
19079 nk_window_show_if(struct nk_context *ctx, const char *name,
19080     enum nk_show_states s, int cond)
19081 {
19082     NK_ASSERT(ctx);
19083     if (!ctx || !cond) return;
19084     nk_window_show(ctx, name, s);
19085 }
19086 
19087 NK_API void
19088 nk_window_set_focus(struct nk_context *ctx, const char *name)
19089 {
19090     int title_len;
19091     nk_hash title_hash;
19092     struct nk_window *win;
19093     NK_ASSERT(ctx);
19094     if (!ctx) return;
19095 
19096     title_len = (int)nk_strlen(name);
19097     title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
19098     win = nk_find_window(ctx, title_hash, name);
19099     if (win && ctx->end != win) {
19100         nk_remove_window(ctx, win);
19101         nk_insert_window(ctx, win, NK_INSERT_BACK);
19102     }
19103     ctx->active = win;
19104 }
19105 
19106 /*----------------------------------------------------------------
19107  *
19108  *                          MENUBAR
19109  *
19110  * --------------------------------------------------------------*/
19111 NK_API void
19112 nk_menubar_begin(struct nk_context *ctx)
19113 {
19114     struct nk_panel *layout;
19115     NK_ASSERT(ctx);
19116     NK_ASSERT(ctx->current);
19117     NK_ASSERT(ctx->current->layout);
19118     if (!ctx || !ctx->current || !ctx->current->layout)
19119         return;
19120 
19121     layout = ctx->current->layout;
19122     NK_ASSERT(layout->at_y == layout->bounds.y);
19123     /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
19124     If you want a menubar the first nuklear function after `nk_begin` has to be a
19125     `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
19126     widgets (also supports multiple rows).
19127     Example:
19128         if (nk_begin(...)) {
19129             nk_menubar_begin(...);
19130                 nk_layout_xxxx(...);
19131                 nk_button(...);
19132                 nk_layout_xxxx(...);
19133                 nk_button(...);
19134             nk_menubar_end(...);
19135         }
19136         nk_end(...);
19137     */
19138     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
19139         return;
19140 
19141     layout->menu.x = layout->at_x;
19142     layout->menu.y = layout->at_y + layout->row.height;
19143     layout->menu.w = layout->bounds.w;
19144     layout->menu.offset.x = *layout->offset_x;
19145     layout->menu.offset.y = *layout->offset_y;
19146     *layout->offset_y = 0;
19147 }
19148 
19149 NK_API void
19150 nk_menubar_end(struct nk_context *ctx)
19151 {
19152     struct nk_window *win;
19153     struct nk_panel *layout;
19154     struct nk_command_buffer *out;
19155 
19156     NK_ASSERT(ctx);
19157     NK_ASSERT(ctx->current);
19158     NK_ASSERT(ctx->current->layout);
19159     if (!ctx || !ctx->current || !ctx->current->layout)
19160         return;
19161 
19162     win = ctx->current;
19163     out = &win->buffer;
19164     layout = win->layout;
19165     if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
19166         return;
19167 
19168     layout->menu.h = layout->at_y - layout->menu.y;
19169     layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
19170     layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
19171 
19172     *layout->offset_x = layout->menu.offset.x;
19173     *layout->offset_y = layout->menu.offset.y;
19174     layout->at_y = layout->bounds.y - layout->row.height;
19175 
19176     layout->clip.y = layout->bounds.y;
19177     layout->clip.h = layout->bounds.h;
19178     nk_push_scissor(out, layout->clip);
19179 }
19180 /* -------------------------------------------------------------
19181  *
19182  *                          LAYOUT
19183  *
19184  * --------------------------------------------------------------*/
19185 NK_API void
19186 nk_layout_set_min_row_height(struct nk_context *ctx, float height)
19187 {
19188     struct nk_window *win;
19189     struct nk_panel *layout;
19190 
19191     NK_ASSERT(ctx);
19192     NK_ASSERT(ctx->current);
19193     NK_ASSERT(ctx->current->layout);
19194     if (!ctx || !ctx->current || !ctx->current->layout)
19195         return;
19196 
19197     win = ctx->current;
19198     layout = win->layout;
19199     layout->row.min_height = height;
19200 }
19201 
19202 NK_API void
19203 nk_layout_reset_min_row_height(struct nk_context *ctx)
19204 {
19205     struct nk_window *win;
19206     struct nk_panel *layout;
19207 
19208     NK_ASSERT(ctx);
19209     NK_ASSERT(ctx->current);
19210     NK_ASSERT(ctx->current->layout);
19211     if (!ctx || !ctx->current || !ctx->current->layout)
19212         return;
19213 
19214     win = ctx->current;
19215     layout = win->layout;
19216     layout->row.min_height = ctx->style.font->height;
19217     layout->row.min_height += ctx->style.text.padding.y*2;
19218     layout->row.min_height += ctx->style.window.min_row_height_padding*2;
19219 }
19220 
19221 NK_INTERN float
19222 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
19223     float total_space, int columns)
19224 {
19225     float panel_padding;
19226     float panel_spacing;
19227     float panel_space;
19228 
19229     struct nk_vec2 spacing;
19230     struct nk_vec2 padding;
19231 
19232     spacing = style->window.spacing;
19233     padding = nk_panel_get_padding(style, type);
19234 
19235     /* calculate the usable panel space */
19236     panel_padding = 2 * padding.x;
19237     panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
19238     panel_space  = total_space - panel_padding - panel_spacing;
19239     return panel_space;
19240 }
19241 
19242 NK_INTERN void
19243 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
19244     float height, int cols)
19245 {
19246     struct nk_panel *layout;
19247     const struct nk_style *style;
19248     struct nk_command_buffer *out;
19249 
19250     struct nk_vec2 item_spacing;
19251     struct nk_color color;
19252 
19253     NK_ASSERT(ctx);
19254     NK_ASSERT(ctx->current);
19255     NK_ASSERT(ctx->current->layout);
19256     if (!ctx || !ctx->current || !ctx->current->layout)
19257         return;
19258 
19259     /* prefetch some configuration data */
19260     layout = win->layout;
19261     style = &ctx->style;
19262     out = &win->buffer;
19263     color = style->window.background;
19264     item_spacing = style->window.spacing;
19265 
19266     /*  if one of these triggers you forgot to add an `if` condition around either
19267         a window, group, popup, combobox or contextual menu `begin` and `end` block.
19268         Example:
19269             if (nk_begin(...) {...} nk_end(...); or
19270             if (nk_group_begin(...) { nk_group_end(...);} */
19271     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
19272     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
19273     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
19274 
19275     /* update the current row and set the current row layout */
19276     layout->row.index = 0;
19277     layout->at_y += layout->row.height;
19278     layout->row.columns = cols;
19279     if (height == 0.0f)
19280         layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
19281     else layout->row.height = height + item_spacing.y;
19282 
19283     layout->row.item_offset = 0;
19284     if (layout->flags & NK_WINDOW_DYNAMIC) {
19285         /* draw background for dynamic panels */
19286         struct nk_rect background;
19287         background.x = win->bounds.x;
19288         background.w = win->bounds.w;
19289         background.y = layout->at_y - 1.0f;
19290         background.h = layout->row.height + 1.0f;
19291         nk_fill_rect(out, background, 0, color);
19292     }
19293 }
19294 
19295 NK_INTERN void
19296 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
19297     float height, int cols, int width)
19298 {
19299     /* update the current row and set the current row layout */
19300     struct nk_window *win;
19301     NK_ASSERT(ctx);
19302     NK_ASSERT(ctx->current);
19303     NK_ASSERT(ctx->current->layout);
19304     if (!ctx || !ctx->current || !ctx->current->layout)
19305         return;
19306 
19307     win = ctx->current;
19308     nk_panel_layout(ctx, win, height, cols);
19309     if (fmt == NK_DYNAMIC)
19310         win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED;
19311     else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
19312 
19313     win->layout->row.ratio = 0;
19314     win->layout->row.filled = 0;
19315     win->layout->row.item_offset = 0;
19316     win->layout->row.item_width = (float)width;
19317 }
19318 
19319 NK_API float
19320 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
19321 {
19322     struct nk_window *win;
19323     NK_ASSERT(ctx);
19324     NK_ASSERT(pixel_width);
19325     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
19326     win = ctx->current;
19327     return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
19328 }
19329 
19330 NK_API void
19331 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
19332 {
19333     nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
19334 }
19335 
19336 NK_API void
19337 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
19338 {
19339     nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
19340 }
19341 
19342 NK_API void
19343 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
19344     float row_height, int cols)
19345 {
19346     struct nk_window *win;
19347     struct nk_panel *layout;
19348 
19349     NK_ASSERT(ctx);
19350     NK_ASSERT(ctx->current);
19351     NK_ASSERT(ctx->current->layout);
19352     if (!ctx || !ctx->current || !ctx->current->layout)
19353         return;
19354 
19355     win = ctx->current;
19356     layout = win->layout;
19357     nk_panel_layout(ctx, win, row_height, cols);
19358     if (fmt == NK_DYNAMIC)
19359         layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
19360     else layout->row.type = NK_LAYOUT_STATIC_ROW;
19361 
19362     layout->row.ratio = 0;
19363     layout->row.filled = 0;
19364     layout->row.item_width = 0;
19365     layout->row.item_offset = 0;
19366     layout->row.columns = cols;
19367 }
19368 
19369 NK_API void
19370 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
19371 {
19372     struct nk_window *win;
19373     struct nk_panel *layout;
19374 
19375     NK_ASSERT(ctx);
19376     NK_ASSERT(ctx->current);
19377     NK_ASSERT(ctx->current->layout);
19378     if (!ctx || !ctx->current || !ctx->current->layout)
19379         return;
19380 
19381     win = ctx->current;
19382     layout = win->layout;
19383     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19384     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19385         return;
19386 
19387     if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
19388         float ratio = ratio_or_width;
19389         if ((ratio + layout->row.filled) > 1.0f) return;
19390         if (ratio > 0.0f)
19391             layout->row.item_width = NK_SATURATE(ratio);
19392         else layout->row.item_width = 1.0f - layout->row.filled;
19393     } else layout->row.item_width = ratio_or_width;
19394 }
19395 
19396 NK_API void
19397 nk_layout_row_end(struct nk_context *ctx)
19398 {
19399     struct nk_window *win;
19400     struct nk_panel *layout;
19401 
19402     NK_ASSERT(ctx);
19403     NK_ASSERT(ctx->current);
19404     NK_ASSERT(ctx->current->layout);
19405     if (!ctx || !ctx->current || !ctx->current->layout)
19406         return;
19407 
19408     win = ctx->current;
19409     layout = win->layout;
19410     NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19411     if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19412         return;
19413     layout->row.item_width = 0;
19414     layout->row.item_offset = 0;
19415 }
19416 
19417 NK_API void
19418 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
19419     float height, int cols, const float *ratio)
19420 {
19421     int i;
19422     int n_undef = 0;
19423     struct nk_window *win;
19424     struct nk_panel *layout;
19425 
19426     NK_ASSERT(ctx);
19427     NK_ASSERT(ctx->current);
19428     NK_ASSERT(ctx->current->layout);
19429     if (!ctx || !ctx->current || !ctx->current->layout)
19430         return;
19431 
19432     win = ctx->current;
19433     layout = win->layout;
19434     nk_panel_layout(ctx, win, height, cols);
19435     if (fmt == NK_DYNAMIC) {
19436         /* calculate width of undefined widget ratios */
19437         float r = 0;
19438         layout->row.ratio = ratio;
19439         for (i = 0; i < cols; ++i) {
19440             if (ratio[i] < 0.0f)
19441                 n_undef++;
19442             else r += ratio[i];
19443         }
19444         r = NK_SATURATE(1.0f - r);
19445         layout->row.type = NK_LAYOUT_DYNAMIC;
19446         layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
19447     } else {
19448         layout->row.ratio = ratio;
19449         layout->row.type = NK_LAYOUT_STATIC;
19450         layout->row.item_width = 0;
19451         layout->row.item_offset = 0;
19452     }
19453     layout->row.item_offset = 0;
19454     layout->row.filled = 0;
19455 }
19456 
19457 NK_API void
19458 nk_layout_row_template_begin(struct nk_context *ctx, float height)
19459 {
19460     struct nk_window *win;
19461     struct nk_panel *layout;
19462 
19463     NK_ASSERT(ctx);
19464     NK_ASSERT(ctx->current);
19465     NK_ASSERT(ctx->current->layout);
19466     if (!ctx || !ctx->current || !ctx->current->layout)
19467         return;
19468 
19469     win = ctx->current;
19470     layout = win->layout;
19471     nk_panel_layout(ctx, win, height, 1);
19472     layout->row.type = NK_LAYOUT_TEMPLATE;
19473     layout->row.columns = 0;
19474     layout->row.ratio = 0;
19475     layout->row.item_width = 0;
19476     layout->row.item_height = 0;
19477     layout->row.item_offset = 0;
19478     layout->row.filled = 0;
19479     layout->row.item.x = 0;
19480     layout->row.item.y = 0;
19481     layout->row.item.w = 0;
19482     layout->row.item.h = 0;
19483 }
19484 
19485 NK_API void
19486 nk_layout_row_template_push_dynamic(struct nk_context *ctx)
19487 {
19488     struct nk_window *win;
19489     struct nk_panel *layout;
19490 
19491     NK_ASSERT(ctx);
19492     NK_ASSERT(ctx->current);
19493     NK_ASSERT(ctx->current->layout);
19494     if (!ctx || !ctx->current || !ctx->current->layout)
19495         return;
19496 
19497     win = ctx->current;
19498     layout = win->layout;
19499     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19500     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19501     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19502     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19503     layout->row.templates[layout->row.columns++] = -1.0f;
19504 }
19505 
19506 NK_API void
19507 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
19508 {
19509     struct nk_window *win;
19510     struct nk_panel *layout;
19511 
19512     NK_ASSERT(ctx);
19513     NK_ASSERT(ctx->current);
19514     NK_ASSERT(ctx->current->layout);
19515     if (!ctx || !ctx->current || !ctx->current->layout)
19516         return;
19517 
19518     win = ctx->current;
19519     layout = win->layout;
19520     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19521     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19522     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19523     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19524     layout->row.templates[layout->row.columns++] = -min_width;
19525 }
19526 
19527 NK_API void
19528 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
19529 {
19530     struct nk_window *win;
19531     struct nk_panel *layout;
19532 
19533     NK_ASSERT(ctx);
19534     NK_ASSERT(ctx->current);
19535     NK_ASSERT(ctx->current->layout);
19536     if (!ctx || !ctx->current || !ctx->current->layout)
19537         return;
19538 
19539     win = ctx->current;
19540     layout = win->layout;
19541     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19542     NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19543     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19544     if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19545     layout->row.templates[layout->row.columns++] = width;
19546 }
19547 
19548 NK_API void
19549 nk_layout_row_template_end(struct nk_context *ctx)
19550 {
19551     struct nk_window *win;
19552     struct nk_panel *layout;
19553 
19554     int i = 0;
19555     int variable_count = 0;
19556     int min_variable_count = 0;
19557     float min_fixed_width = 0.0f;
19558     float total_fixed_width = 0.0f;
19559     float max_variable_width = 0.0f;
19560 
19561     NK_ASSERT(ctx);
19562     NK_ASSERT(ctx->current);
19563     NK_ASSERT(ctx->current->layout);
19564     if (!ctx || !ctx->current || !ctx->current->layout)
19565         return;
19566 
19567     win = ctx->current;
19568     layout = win->layout;
19569     NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19570     if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19571     for (i = 0; i < layout->row.columns; ++i) {
19572         float width = layout->row.templates[i];
19573         if (width >= 0.0f) {
19574             total_fixed_width += width;
19575             min_fixed_width += width;
19576         } else if (width < -1.0f) {
19577             width = -width;
19578             total_fixed_width += width;
19579             max_variable_width = NK_MAX(max_variable_width, width);
19580             variable_count++;
19581         } else {
19582             min_variable_count++;
19583             variable_count++;
19584         }
19585     }
19586     if (variable_count) {
19587         float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19588                             layout->bounds.w, layout->row.columns);
19589         float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
19590         int enough_space = var_width >= max_variable_width;
19591         if (!enough_space)
19592             var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
19593         for (i = 0; i < layout->row.columns; ++i) {
19594             float *width = &layout->row.templates[i];
19595             *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
19596         }
19597     }
19598 }
19599 
19600 NK_API void
19601 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
19602     float height, int widget_count)
19603 {
19604     struct nk_window *win;
19605     struct nk_panel *layout;
19606 
19607     NK_ASSERT(ctx);
19608     NK_ASSERT(ctx->current);
19609     NK_ASSERT(ctx->current->layout);
19610     if (!ctx || !ctx->current || !ctx->current->layout)
19611         return;
19612 
19613     win = ctx->current;
19614     layout = win->layout;
19615     nk_panel_layout(ctx, win, height, widget_count);
19616     if (fmt == NK_STATIC)
19617         layout->row.type = NK_LAYOUT_STATIC_FREE;
19618     else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
19619 
19620     layout->row.ratio = 0;
19621     layout->row.filled = 0;
19622     layout->row.item_width = 0;
19623     layout->row.item_offset = 0;
19624 }
19625 
19626 NK_API void
19627 nk_layout_space_end(struct nk_context *ctx)
19628 {
19629     struct nk_window *win;
19630     struct nk_panel *layout;
19631 
19632     NK_ASSERT(ctx);
19633     NK_ASSERT(ctx->current);
19634     NK_ASSERT(ctx->current->layout);
19635     if (!ctx || !ctx->current || !ctx->current->layout)
19636         return;
19637 
19638     win = ctx->current;
19639     layout = win->layout;
19640     layout->row.item_width = 0;
19641     layout->row.item_height = 0;
19642     layout->row.item_offset = 0;
19643     nk_zero(&layout->row.item, sizeof(layout->row.item));
19644 }
19645 
19646 NK_API void
19647 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
19648 {
19649     struct nk_window *win;
19650     struct nk_panel *layout;
19651 
19652     NK_ASSERT(ctx);
19653     NK_ASSERT(ctx->current);
19654     NK_ASSERT(ctx->current->layout);
19655     if (!ctx || !ctx->current || !ctx->current->layout)
19656         return;
19657 
19658     win = ctx->current;
19659     layout = win->layout;
19660     layout->row.item = rect;
19661 }
19662 
19663 NK_API struct nk_rect
19664 nk_layout_space_bounds(struct nk_context *ctx)
19665 {
19666     struct nk_rect ret;
19667     struct nk_window *win;
19668     struct nk_panel *layout;
19669 
19670     NK_ASSERT(ctx);
19671     NK_ASSERT(ctx->current);
19672     NK_ASSERT(ctx->current->layout);
19673     win = ctx->current;
19674     layout = win->layout;
19675 
19676     ret.x = layout->clip.x;
19677     ret.y = layout->clip.y;
19678     ret.w = layout->clip.w;
19679     ret.h = layout->row.height;
19680     return ret;
19681 }
19682 
19683 NK_API struct nk_rect
19684 nk_layout_widget_bounds(struct nk_context *ctx)
19685 {
19686     struct nk_rect ret;
19687     struct nk_window *win;
19688     struct nk_panel *layout;
19689 
19690     NK_ASSERT(ctx);
19691     NK_ASSERT(ctx->current);
19692     NK_ASSERT(ctx->current->layout);
19693     win = ctx->current;
19694     layout = win->layout;
19695 
19696     ret.x = layout->at_x;
19697     ret.y = layout->at_y;
19698     ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
19699     ret.h = layout->row.height;
19700     return ret;
19701 }
19702 
19703 NK_API struct nk_vec2
19704 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
19705 {
19706     struct nk_window *win;
19707     struct nk_panel *layout;
19708 
19709     NK_ASSERT(ctx);
19710     NK_ASSERT(ctx->current);
19711     NK_ASSERT(ctx->current->layout);
19712     win = ctx->current;
19713     layout = win->layout;
19714 
19715     ret.x += layout->at_x - (float)*layout->offset_x;
19716     ret.y += layout->at_y - (float)*layout->offset_y;
19717     return ret;
19718 }
19719 
19720 NK_API struct nk_vec2
19721 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
19722 {
19723     struct nk_window *win;
19724     struct nk_panel *layout;
19725 
19726     NK_ASSERT(ctx);
19727     NK_ASSERT(ctx->current);
19728     NK_ASSERT(ctx->current->layout);
19729     win = ctx->current;
19730     layout = win->layout;
19731 
19732     ret.x += -layout->at_x + (float)*layout->offset_x;
19733     ret.y += -layout->at_y + (float)*layout->offset_y;
19734     return ret;
19735 }
19736 
19737 NK_API struct nk_rect
19738 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret)
19739 {
19740     struct nk_window *win;
19741     struct nk_panel *layout;
19742 
19743     NK_ASSERT(ctx);
19744     NK_ASSERT(ctx->current);
19745     NK_ASSERT(ctx->current->layout);
19746     win = ctx->current;
19747     layout = win->layout;
19748 
19749     ret.x += layout->at_x - (float)*layout->offset_x;
19750     ret.y += layout->at_y - (float)*layout->offset_y;
19751     return ret;
19752 }
19753 
19754 NK_API struct nk_rect
19755 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret)
19756 {
19757     struct nk_window *win;
19758     struct nk_panel *layout;
19759 
19760     NK_ASSERT(ctx);
19761     NK_ASSERT(ctx->current);
19762     NK_ASSERT(ctx->current->layout);
19763     win = ctx->current;
19764     layout = win->layout;
19765 
19766     ret.x += -layout->at_x + (float)*layout->offset_x;
19767     ret.y += -layout->at_y + (float)*layout->offset_y;
19768     return ret;
19769 }
19770 
19771 NK_INTERN void
19772 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
19773 {
19774     struct nk_panel *layout = win->layout;
19775     struct nk_vec2 spacing = ctx->style.window.spacing;
19776     const float row_height = layout->row.height - spacing.y;
19777     nk_panel_layout(ctx, win, row_height, layout->row.columns);
19778 }
19779 
19780 NK_INTERN void
19781 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
19782     struct nk_window *win, int modify)
19783 {
19784     struct nk_panel *layout;
19785     const struct nk_style *style;
19786 
19787     struct nk_vec2 spacing;
19788     struct nk_vec2 padding;
19789 
19790     float item_offset = 0;
19791     float item_width = 0;
19792     float item_spacing = 0;
19793     float panel_space = 0;
19794 
19795     NK_ASSERT(ctx);
19796     NK_ASSERT(ctx->current);
19797     NK_ASSERT(ctx->current->layout);
19798     if (!ctx || !ctx->current || !ctx->current->layout)
19799         return;
19800 
19801     win = ctx->current;
19802     layout = win->layout;
19803     style = &ctx->style;
19804     NK_ASSERT(bounds);
19805 
19806     spacing = style->window.spacing;
19807     padding = nk_panel_get_padding(style, layout->type);
19808     panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19809                                             layout->bounds.w, layout->row.columns);
19810 
19811     /* calculate the width of one item inside the current layout space */
19812     switch (layout->row.type) {
19813     case NK_LAYOUT_DYNAMIC_FIXED: {
19814         /* scaling fixed size widgets item width */
19815         item_width = NK_MAX(1.0f,panel_space-1.0f) / (float)layout->row.columns;
19816         item_offset = (float)layout->row.index * item_width;
19817         item_spacing = (float)layout->row.index * spacing.x;
19818     } break;
19819     case NK_LAYOUT_DYNAMIC_ROW: {
19820         /* scaling single ratio widget width */
19821         item_width = layout->row.item_width * panel_space;
19822         item_offset = layout->row.item_offset;
19823         item_spacing = 0;
19824 
19825         if (modify) {
19826             layout->row.item_offset += item_width + spacing.x;
19827             layout->row.filled += layout->row.item_width;
19828             layout->row.index = 0;
19829         }
19830     } break;
19831     case NK_LAYOUT_DYNAMIC_FREE: {
19832         /* panel width depended free widget placing */
19833         bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
19834         bounds->x -= (float)*layout->offset_x;
19835         bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
19836         bounds->y -= (float)*layout->offset_y;
19837         bounds->w = layout->bounds.w  * layout->row.item.w;
19838         bounds->h = layout->row.height * layout->row.item.h;
19839         return;
19840     } break;
19841     case NK_LAYOUT_DYNAMIC: {
19842         /* scaling arrays of panel width ratios for every widget */
19843         float ratio;
19844         NK_ASSERT(layout->row.ratio);
19845         ratio = (layout->row.ratio[layout->row.index] < 0) ?
19846             layout->row.item_width : layout->row.ratio[layout->row.index];
19847 
19848         item_spacing = (float)layout->row.index * spacing.x;
19849         item_width = (ratio * panel_space);
19850         item_offset = layout->row.item_offset;
19851 
19852         if (modify) {
19853             layout->row.item_offset += item_width;
19854             layout->row.filled += ratio;
19855         }
19856     } break;
19857     case NK_LAYOUT_STATIC_FIXED: {
19858         /* non-scaling fixed widgets item width */
19859         item_width = layout->row.item_width;
19860         item_offset = (float)layout->row.index * item_width;
19861         item_spacing = (float)layout->row.index * spacing.x;
19862     } break;
19863     case NK_LAYOUT_STATIC_ROW: {
19864         /* scaling single ratio widget width */
19865         item_width = layout->row.item_width;
19866         item_offset = layout->row.item_offset;
19867         item_spacing = (float)layout->row.index * spacing.x;
19868         if (modify) layout->row.item_offset += item_width;
19869     } break;
19870     case NK_LAYOUT_STATIC_FREE: {
19871         /* free widget placing */
19872         bounds->x = layout->at_x + layout->row.item.x;
19873         bounds->w = layout->row.item.w;
19874         if (((bounds->x + bounds->w) > layout->max_x) && modify)
19875             layout->max_x = (bounds->x + bounds->w);
19876         bounds->x -= (float)*layout->offset_x;
19877         bounds->y = layout->at_y + layout->row.item.y;
19878         bounds->y -= (float)*layout->offset_y;
19879         bounds->h = layout->row.item.h;
19880         return;
19881     } break;
19882     case NK_LAYOUT_STATIC: {
19883         /* non-scaling array of panel pixel width for every widget */
19884         item_spacing = (float)layout->row.index * spacing.x;
19885         item_width = layout->row.ratio[layout->row.index];
19886         item_offset = layout->row.item_offset;
19887         if (modify) layout->row.item_offset += item_width;
19888     } break;
19889     case NK_LAYOUT_TEMPLATE: {
19890         /* stretchy row layout with combined dynamic/static widget width*/
19891         NK_ASSERT(layout->row.index < layout->row.columns);
19892         NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19893         item_width = layout->row.templates[layout->row.index];
19894         item_offset = layout->row.item_offset;
19895         item_spacing = (float)layout->row.index * spacing.x;
19896         if (modify) layout->row.item_offset += item_width;
19897     } break;
19898     default: NK_ASSERT(0); break;
19899     };
19900 
19901     /* set the bounds of the newly allocated widget */
19902     bounds->w = item_width;
19903     bounds->h = layout->row.height - spacing.y;
19904     bounds->y = layout->at_y - (float)*layout->offset_y;
19905     bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
19906     if (((bounds->x + bounds->w) > layout->max_x) && modify)
19907         layout->max_x = bounds->x + bounds->w;
19908     bounds->x -= (float)*layout->offset_x;
19909 }
19910 
19911 NK_INTERN void
19912 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
19913 {
19914     struct nk_window *win;
19915     struct nk_panel *layout;
19916 
19917     NK_ASSERT(ctx);
19918     NK_ASSERT(ctx->current);
19919     NK_ASSERT(ctx->current->layout);
19920     if (!ctx || !ctx->current || !ctx->current->layout)
19921         return;
19922 
19923     /* check if the end of the row has been hit and begin new row if so */
19924     win = ctx->current;
19925     layout = win->layout;
19926     if (layout->row.index >= layout->row.columns)
19927         nk_panel_alloc_row(ctx, win);
19928 
19929     /* calculate widget position and size */
19930     nk_layout_widget_space(bounds, ctx, win, nk_true);
19931     layout->row.index++;
19932 }
19933 
19934 NK_INTERN void
19935 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
19936 {
19937     float y;
19938     int index;
19939     struct nk_window *win;
19940     struct nk_panel *layout;
19941 
19942     NK_ASSERT(ctx);
19943     NK_ASSERT(ctx->current);
19944     NK_ASSERT(ctx->current->layout);
19945     if (!ctx || !ctx->current || !ctx->current->layout)
19946         return;
19947 
19948     win = ctx->current;
19949     layout = win->layout;
19950     y = layout->at_y;
19951     index = layout->row.index;
19952     if (layout->row.index >= layout->row.columns) {
19953         layout->at_y += layout->row.height;
19954         layout->row.index = 0;
19955     }
19956     nk_layout_widget_space(bounds, ctx, win, nk_false);
19957     if (!layout->row.index) {
19958         bounds->x -= layout->row.item_offset;
19959     }
19960     layout->at_y = y;
19961     layout->row.index = index;
19962 }
19963 
19964 NK_INTERN int
19965 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
19966     struct nk_image *img, const char *title, enum nk_collapse_states *state)
19967 {
19968     struct nk_window *win;
19969     struct nk_panel *layout;
19970     const struct nk_style *style;
19971     struct nk_command_buffer *out;
19972     const struct nk_input *in;
19973     const struct nk_style_button *button;
19974     enum nk_symbol_type symbol;
19975     float row_height;
19976 
19977     struct nk_vec2 item_spacing;
19978     struct nk_rect header = {0,0,0,0};
19979     struct nk_rect sym = {0,0,0,0};
19980     struct nk_text text;
19981 
19982     nk_flags ws = 0;
19983     enum nk_widget_layout_states widget_state;
19984 
19985     NK_ASSERT(ctx);
19986     NK_ASSERT(ctx->current);
19987     NK_ASSERT(ctx->current->layout);
19988     if (!ctx || !ctx->current || !ctx->current->layout)
19989         return 0;
19990 
19991     /* cache some data */
19992     win = ctx->current;
19993     layout = win->layout;
19994     out = &win->buffer;
19995     style = &ctx->style;
19996     item_spacing = style->window.spacing;
19997 
19998     /* calculate header bounds and draw background */
19999     row_height = style->font->height + 2 * style->tab.padding.y;
20000     nk_layout_set_min_row_height(ctx, row_height);
20001     nk_layout_row_dynamic(ctx, row_height, 1);
20002     nk_layout_reset_min_row_height(ctx);
20003 
20004     widget_state = nk_widget(&header, ctx);
20005     if (type == NK_TREE_TAB) {
20006         const struct nk_style_item *background = &style->tab.background;
20007         if (background->type == NK_STYLE_ITEM_IMAGE) {
20008             nk_draw_image(out, header, &background->data.image, nk_white);
20009             text.background = nk_rgba(0,0,0,0);
20010         } else {
20011             text.background = background->data.color;
20012             nk_fill_rect(out, header, 0, style->tab.border_color);
20013             nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
20014                 style->tab.rounding, background->data.color);
20015         }
20016     } else text.background = style->window.background;
20017 
20018     /* update node state */
20019     in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
20020     in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
20021     if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
20022         *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
20023 
20024     /* select correct button style */
20025     if (*state == NK_MAXIMIZED) {
20026         symbol = style->tab.sym_maximize;
20027         if (type == NK_TREE_TAB)
20028             button = &style->tab.tab_maximize_button;
20029         else button = &style->tab.node_maximize_button;
20030     } else {
20031         symbol = style->tab.sym_minimize;
20032         if (type == NK_TREE_TAB)
20033             button = &style->tab.tab_minimize_button;
20034         else button = &style->tab.node_minimize_button;
20035     }
20036 
20037     {/* draw triangle button */
20038     sym.w = sym.h = style->font->height;
20039     sym.y = header.y + style->tab.padding.y;
20040     sym.x = header.x + style->tab.padding.x;
20041     nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
20042         button, 0, style->font);
20043 
20044     if (img) {
20045         /* draw optional image icon */
20046         sym.x = sym.x + sym.w + 4 * item_spacing.x;
20047         nk_draw_image(&win->buffer, sym, img, nk_white);
20048         sym.w = style->font->height + style->tab.spacing.x;}
20049     }
20050 
20051     {/* draw label */
20052     struct nk_rect label;
20053     header.w = NK_MAX(header.w, sym.w + item_spacing.x);
20054     label.x = sym.x + sym.w + item_spacing.x;
20055     label.y = sym.y;
20056     label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
20057     label.h = style->font->height;
20058     text.text = style->tab.text;
20059     text.padding = nk_vec2(0,0);
20060     nk_widget_text(out, label, title, nk_strlen(title), &text,
20061         NK_TEXT_LEFT, style->font);}
20062 
20063     /* increase x-axis cursor widget position pointer */
20064     if (*state == NK_MAXIMIZED) {
20065         layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
20066         layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
20067         layout->bounds.w -= (style->tab.indent + style->window.padding.x);
20068         layout->row.tree_depth++;
20069         return nk_true;
20070     } else return nk_false;
20071 }
20072 
20073 NK_INTERN int
20074 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
20075     struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
20076     const char *hash, int len, int line)
20077 {
20078     struct nk_window *win = ctx->current;
20079     int title_len = 0;
20080     nk_hash tree_hash = 0;
20081     nk_uint *state = 0;
20082 
20083     /* retrieve tree state from internal widget state tables */
20084     if (!hash) {
20085         title_len = (int)nk_strlen(title);
20086         tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
20087     } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
20088     state = nk_find_value(win, tree_hash);
20089     if (!state) {
20090         state = nk_add_value(ctx, win, tree_hash, 0);
20091         *state = initial_state;
20092     }
20093     return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
20094 }
20095 
20096 NK_API int
20097 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
20098     const char *title, enum nk_collapse_states *state)
20099 {return nk_tree_state_base(ctx, type, 0, title, state);}
20100 
20101 NK_API int
20102 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
20103     struct nk_image img, const char *title, enum nk_collapse_states *state)
20104 {return nk_tree_state_base(ctx, type, &img, title, state);}
20105 
20106 NK_API void
20107 nk_tree_state_pop(struct nk_context *ctx)
20108 {
20109     struct nk_window *win = 0;
20110     struct nk_panel *layout = 0;
20111 
20112     NK_ASSERT(ctx);
20113     NK_ASSERT(ctx->current);
20114     NK_ASSERT(ctx->current->layout);
20115     if (!ctx || !ctx->current || !ctx->current->layout)
20116         return;
20117 
20118     win = ctx->current;
20119     layout = win->layout;
20120     layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
20121     layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
20122     NK_ASSERT(layout->row.tree_depth);
20123     layout->row.tree_depth--;
20124 }
20125 
20126 NK_API int
20127 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
20128     const char *title, enum nk_collapse_states initial_state,
20129     const char *hash, int len, int line)
20130 {return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);}
20131 
20132 NK_API int
20133 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
20134     struct nk_image img, const char *title, enum nk_collapse_states initial_state,
20135     const char *hash, int len,int seed)
20136 {return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);}
20137 
20138 NK_API void
20139 nk_tree_pop(struct nk_context *ctx)
20140 {nk_tree_state_pop(ctx);}
20141 
20142 /*----------------------------------------------------------------
20143  *
20144  *                          WIDGETS
20145  *
20146  * --------------------------------------------------------------*/
20147 NK_API struct nk_rect
20148 nk_widget_bounds(struct nk_context *ctx)
20149 {
20150     struct nk_rect bounds;
20151     NK_ASSERT(ctx);
20152     NK_ASSERT(ctx->current);
20153     if (!ctx || !ctx->current)
20154         return nk_rect(0,0,0,0);
20155     nk_layout_peek(&bounds, ctx);
20156     return bounds;
20157 }
20158 
20159 NK_API struct nk_vec2
20160 nk_widget_position(struct nk_context *ctx)
20161 {
20162     struct nk_rect bounds;
20163     NK_ASSERT(ctx);
20164     NK_ASSERT(ctx->current);
20165     if (!ctx || !ctx->current)
20166         return nk_vec2(0,0);
20167 
20168     nk_layout_peek(&bounds, ctx);
20169     return nk_vec2(bounds.x, bounds.y);
20170 }
20171 
20172 NK_API struct nk_vec2
20173 nk_widget_size(struct nk_context *ctx)
20174 {
20175     struct nk_rect bounds;
20176     NK_ASSERT(ctx);
20177     NK_ASSERT(ctx->current);
20178     if (!ctx || !ctx->current)
20179         return nk_vec2(0,0);
20180 
20181     nk_layout_peek(&bounds, ctx);
20182     return nk_vec2(bounds.w, bounds.h);
20183 }
20184 
20185 NK_API float
20186 nk_widget_width(struct nk_context *ctx)
20187 {
20188     struct nk_rect bounds;
20189     NK_ASSERT(ctx);
20190     NK_ASSERT(ctx->current);
20191     if (!ctx || !ctx->current)
20192         return 0;
20193 
20194     nk_layout_peek(&bounds, ctx);
20195     return bounds.w;
20196 }
20197 
20198 NK_API float
20199 nk_widget_height(struct nk_context *ctx)
20200 {
20201     struct nk_rect bounds;
20202     NK_ASSERT(ctx);
20203     NK_ASSERT(ctx->current);
20204     if (!ctx || !ctx->current)
20205         return 0;
20206 
20207     nk_layout_peek(&bounds, ctx);
20208     return bounds.h;
20209 }
20210 
20211 NK_API int
20212 nk_widget_is_hovered(struct nk_context *ctx)
20213 {
20214     struct nk_rect c, v;
20215     struct nk_rect bounds;
20216     NK_ASSERT(ctx);
20217     NK_ASSERT(ctx->current);
20218     if (!ctx || !ctx->current || ctx->active != ctx->current)
20219         return 0;
20220 
20221     c = ctx->current->layout->clip;
20222     c.x = (float)((int)c.x);
20223     c.y = (float)((int)c.y);
20224     c.w = (float)((int)c.w);
20225     c.h = (float)((int)c.h);
20226 
20227     nk_layout_peek(&bounds, ctx);
20228     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20229     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20230         return 0;
20231     return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
20232 }
20233 
20234 NK_API int
20235 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
20236 {
20237     struct nk_rect c, v;
20238     struct nk_rect bounds;
20239     NK_ASSERT(ctx);
20240     NK_ASSERT(ctx->current);
20241     if (!ctx || !ctx->current || ctx->active != ctx->current)
20242         return 0;
20243 
20244     c = ctx->current->layout->clip;
20245     c.x = (float)((int)c.x);
20246     c.y = (float)((int)c.y);
20247     c.w = (float)((int)c.w);
20248     c.h = (float)((int)c.h);
20249 
20250     nk_layout_peek(&bounds, ctx);
20251     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20252     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20253         return 0;
20254     return nk_input_mouse_clicked(&ctx->input, btn, bounds);
20255 }
20256 
20257 NK_API int
20258 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
20259 {
20260     struct nk_rect c, v;
20261     struct nk_rect bounds;
20262     NK_ASSERT(ctx);
20263     NK_ASSERT(ctx->current);
20264     if (!ctx || !ctx->current || ctx->active != ctx->current)
20265         return 0;
20266 
20267     c = ctx->current->layout->clip;
20268     c.x = (float)((int)c.x);
20269     c.y = (float)((int)c.y);
20270     c.w = (float)((int)c.w);
20271     c.h = (float)((int)c.h);
20272 
20273     nk_layout_peek(&bounds, ctx);
20274     nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20275     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20276         return 0;
20277     return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
20278 }
20279 
20280 NK_API enum nk_widget_layout_states
20281 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
20282 {
20283     struct nk_rect c, v;
20284     struct nk_window *win;
20285     struct nk_panel *layout;
20286     const struct nk_input *in;
20287 
20288     NK_ASSERT(ctx);
20289     NK_ASSERT(ctx->current);
20290     NK_ASSERT(ctx->current->layout);
20291     if (!ctx || !ctx->current || !ctx->current->layout)
20292         return NK_WIDGET_INVALID;
20293 
20294     /* allocate space and check if the widget needs to be updated and drawn */
20295     nk_panel_alloc_space(bounds, ctx);
20296     win = ctx->current;
20297     layout = win->layout;
20298     in = &ctx->input;
20299     c = layout->clip;
20300 
20301     /*  if one of these triggers you forgot to add an `if` condition around either
20302         a window, group, popup, combobox or contextual menu `begin` and `end` block.
20303         Example:
20304             if (nk_begin(...) {...} nk_end(...); or
20305             if (nk_group_begin(...) { nk_group_end(...);} */
20306     NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
20307     NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
20308     NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
20309 
20310     /* need to convert to int here to remove floating point errors */
20311     bounds->x = (float)((int)bounds->x);
20312     bounds->y = (float)((int)bounds->y);
20313     bounds->w = (float)((int)bounds->w);
20314     bounds->h = (float)((int)bounds->h);
20315 
20316     c.x = (float)((int)c.x);
20317     c.y = (float)((int)c.y);
20318     c.w = (float)((int)c.w);
20319     c.h = (float)((int)c.h);
20320 
20321     nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
20322     if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
20323         return NK_WIDGET_INVALID;
20324     if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
20325         return NK_WIDGET_ROM;
20326     return NK_WIDGET_VALID;
20327 }
20328 
20329 NK_API enum nk_widget_layout_states
20330 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
20331     struct nk_vec2 item_padding)
20332 {
20333     /* update the bounds to stand without padding  */
20334     struct nk_window *win;
20335     struct nk_style *style;
20336     struct nk_panel *layout;
20337     enum nk_widget_layout_states state;
20338     struct nk_vec2 panel_padding;
20339 
20340     NK_ASSERT(ctx);
20341     NK_ASSERT(ctx->current);
20342     NK_ASSERT(ctx->current->layout);
20343     if (!ctx || !ctx->current || !ctx->current->layout)
20344         return NK_WIDGET_INVALID;
20345 
20346     win = ctx->current;
20347     style = &ctx->style;
20348     layout = win->layout;
20349     state = nk_widget(bounds, ctx);
20350 
20351     panel_padding = nk_panel_get_padding(style, layout->type);
20352     if (layout->row.index == 1) {
20353         bounds->w += panel_padding.x;
20354         bounds->x -= panel_padding.x;
20355     } else bounds->x -= item_padding.x;
20356 
20357     if (layout->row.index == layout->row.columns)
20358         bounds->w += panel_padding.x;
20359     else bounds->w += item_padding.x;
20360     return state;
20361 }
20362 
20363 /*----------------------------------------------------------------
20364  *
20365  *                          MISC
20366  *
20367  * --------------------------------------------------------------*/
20368 NK_API void
20369 nk_spacing(struct nk_context *ctx, int cols)
20370 {
20371     struct nk_window *win;
20372     struct nk_panel *layout;
20373     struct nk_rect none;
20374     int i, index, rows;
20375 
20376     NK_ASSERT(ctx);
20377     NK_ASSERT(ctx->current);
20378     NK_ASSERT(ctx->current->layout);
20379     if (!ctx || !ctx->current || !ctx->current->layout)
20380         return;
20381 
20382     /* spacing over row boundaries */
20383     win = ctx->current;
20384     layout = win->layout;
20385     index = (layout->row.index + cols) % layout->row.columns;
20386     rows = (layout->row.index + cols) / layout->row.columns;
20387     if (rows) {
20388         for (i = 0; i < rows; ++i)
20389             nk_panel_alloc_row(ctx, win);
20390         cols = index;
20391     }
20392     /* non table layout need to allocate space */
20393     if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
20394         layout->row.type != NK_LAYOUT_STATIC_FIXED) {
20395         for (i = 0; i < cols; ++i)
20396             nk_panel_alloc_space(&none, ctx);
20397     }
20398     layout->row.index = index;
20399 }
20400 
20401 /*----------------------------------------------------------------
20402  *
20403  *                          TEXT
20404  *
20405  * --------------------------------------------------------------*/
20406 NK_API void
20407 nk_text_colored(struct nk_context *ctx, const char *str, int len,
20408     nk_flags alignment, struct nk_color color)
20409 {
20410     struct nk_window *win;
20411     const struct nk_style *style;
20412 
20413     struct nk_vec2 item_padding;
20414     struct nk_rect bounds;
20415     struct nk_text text;
20416 
20417     NK_ASSERT(ctx);
20418     NK_ASSERT(ctx->current);
20419     NK_ASSERT(ctx->current->layout);
20420     if (!ctx || !ctx->current || !ctx->current->layout) return;
20421 
20422     win = ctx->current;
20423     style = &ctx->style;
20424     nk_panel_alloc_space(&bounds, ctx);
20425     item_padding = style->text.padding;
20426 
20427     text.padding.x = item_padding.x;
20428     text.padding.y = item_padding.y;
20429     text.background = style->window.background;
20430     text.text = color;
20431     nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
20432 }
20433 
20434 NK_API void
20435 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
20436     int len, struct nk_color color)
20437 {
20438     struct nk_window *win;
20439     const struct nk_style *style;
20440 
20441     struct nk_vec2 item_padding;
20442     struct nk_rect bounds;
20443     struct nk_text text;
20444 
20445     NK_ASSERT(ctx);
20446     NK_ASSERT(ctx->current);
20447     NK_ASSERT(ctx->current->layout);
20448     if (!ctx || !ctx->current || !ctx->current->layout) return;
20449 
20450     win = ctx->current;
20451     style = &ctx->style;
20452     nk_panel_alloc_space(&bounds, ctx);
20453     item_padding = style->text.padding;
20454 
20455     text.padding.x = item_padding.x;
20456     text.padding.y = item_padding.y;
20457     text.background = style->window.background;
20458     text.text = color;
20459     nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
20460 }
20461 
20462 #ifdef NK_INCLUDE_STANDARD_VARARGS
20463 NK_API void
20464 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
20465     struct nk_color color, const char *fmt, ...)
20466 {
20467     char buf[256];
20468     va_list args;
20469     va_start(args, fmt);
20470     nk_strfmt(buf, NK_LEN(buf), fmt, args);
20471     nk_label_colored(ctx, buf, flags, color);
20472     va_end(args);
20473 }
20474 
20475 NK_API void
20476 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
20477     const char *fmt, ...)
20478 {
20479     char buf[256];
20480     va_list args;
20481     va_start(args, fmt);
20482     nk_strfmt(buf, NK_LEN(buf), fmt, args);
20483     nk_label_colored_wrap(ctx, buf, color);
20484     va_end(args);
20485 }
20486 
20487 NK_API void
20488 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
20489 {
20490     char buf[256];
20491     va_list args;
20492     va_start(args, fmt);
20493     nk_strfmt(buf, NK_LEN(buf), fmt, args);
20494     nk_label(ctx, buf, flags);
20495     va_end(args);
20496 }
20497 
20498 NK_API void
20499 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
20500 {
20501     char buf[256];
20502     va_list args;
20503     va_start(args, fmt);
20504     nk_strfmt(buf, NK_LEN(buf), fmt, args);
20505     nk_label_wrap(ctx, buf);
20506     va_end(args);
20507 }
20508 
20509 NK_API void
20510 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
20511 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));}
20512 
20513 NK_API void
20514 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
20515 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);}
20516 
20517 NK_API void
20518 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
20519 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);}
20520 
20521 NK_API void
20522 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
20523 {
20524     double double_value = (double)value;
20525     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
20526 }
20527 
20528 NK_API void
20529 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
20530 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);}
20531 
20532 NK_API void
20533 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
20534 {
20535     double c[4]; nk_color_dv(c, color);
20536     nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
20537         p, c[0], c[1], c[2], c[3]);
20538 }
20539 
20540 NK_API void
20541 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
20542 {
20543     char hex[16];
20544     nk_color_hex_rgba(hex, color);
20545     nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
20546 }
20547 #endif
20548 
20549 NK_API void
20550 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
20551 {
20552     NK_ASSERT(ctx);
20553     if (!ctx) return;
20554     nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
20555 }
20556 
20557 NK_API void
20558 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
20559 {
20560     NK_ASSERT(ctx);
20561     if (!ctx) return;
20562     nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
20563 }
20564 
20565 NK_API void
20566 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
20567 {nk_text(ctx, str, nk_strlen(str), alignment);}
20568 
20569 NK_API void
20570 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
20571     struct nk_color color)
20572 {nk_text_colored(ctx, str, nk_strlen(str), align, color);}
20573 
20574 NK_API void
20575 nk_label_wrap(struct nk_context *ctx, const char *str)
20576 {nk_text_wrap(ctx, str, nk_strlen(str));}
20577 
20578 NK_API void
20579 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
20580 {nk_text_wrap_colored(ctx, str, nk_strlen(str), color);}
20581 
20582 NK_API void
20583 nk_image(struct nk_context *ctx, struct nk_image img)
20584 {
20585     struct nk_window *win;
20586     struct nk_rect bounds;
20587 
20588     NK_ASSERT(ctx);
20589     NK_ASSERT(ctx->current);
20590     NK_ASSERT(ctx->current->layout);
20591     if (!ctx || !ctx->current || !ctx->current->layout) return;
20592 
20593     win = ctx->current;
20594     if (!nk_widget(&bounds, ctx)) return;
20595     nk_draw_image(&win->buffer, bounds, &img, nk_white);
20596 }
20597 
20598 /*----------------------------------------------------------------
20599  *
20600  *                          BUTTON
20601  *
20602  * --------------------------------------------------------------*/
20603 NK_API void
20604 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20605 {
20606     NK_ASSERT(ctx);
20607     if (!ctx) return;
20608     ctx->button_behavior = behavior;
20609 }
20610 
20611 NK_API int
20612 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20613 {
20614     struct nk_config_stack_button_behavior *button_stack;
20615     struct nk_config_stack_button_behavior_element *element;
20616 
20617     NK_ASSERT(ctx);
20618     if (!ctx) return 0;
20619 
20620     button_stack = &ctx->stacks.button_behaviors;
20621     NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
20622     if (button_stack->head >= (int)NK_LEN(button_stack->elements))
20623         return 0;
20624 
20625     element = &button_stack->elements[button_stack->head++];
20626     element->address = &ctx->button_behavior;
20627     element->old_value = ctx->button_behavior;
20628     ctx->button_behavior = behavior;
20629     return 1;
20630 }
20631 
20632 NK_API int
20633 nk_button_pop_behavior(struct nk_context *ctx)
20634 {
20635     struct nk_config_stack_button_behavior *button_stack;
20636     struct nk_config_stack_button_behavior_element *element;
20637 
20638     NK_ASSERT(ctx);
20639     if (!ctx) return 0;
20640 
20641     button_stack = &ctx->stacks.button_behaviors;
20642     NK_ASSERT(button_stack->head > 0);
20643     if (button_stack->head < 1)
20644         return 0;
20645 
20646     element = &button_stack->elements[--button_stack->head];
20647     *element->address = element->old_value;
20648     return 1;
20649 }
20650 
20651 NK_API int
20652 nk_button_text_styled(struct nk_context *ctx,
20653     const struct nk_style_button *style, const char *title, int len)
20654 {
20655     struct nk_window *win;
20656     struct nk_panel *layout;
20657     const struct nk_input *in;
20658 
20659     struct nk_rect bounds;
20660     enum nk_widget_layout_states state;
20661 
20662     NK_ASSERT(ctx);
20663     NK_ASSERT(style);
20664     NK_ASSERT(ctx->current);
20665     NK_ASSERT(ctx->current->layout);
20666     if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
20667 
20668     win = ctx->current;
20669     layout = win->layout;
20670     state = nk_widget(&bounds, ctx);
20671 
20672     if (!state) return 0;
20673     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20674     return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
20675                     title, len, style->text_alignment, ctx->button_behavior,
20676                     style, in, ctx->style.font);
20677 }
20678 
20679 NK_API int
20680 nk_button_text(struct nk_context *ctx, const char *title, int len)
20681 {
20682     NK_ASSERT(ctx);
20683     if (!ctx) return 0;
20684     return nk_button_text_styled(ctx, &ctx->style.button, title, len);
20685 }
20686 
20687 NK_API int nk_button_label_styled(struct nk_context *ctx,
20688     const struct nk_style_button *style, const char *title)
20689 {return nk_button_text_styled(ctx, style, title, nk_strlen(title));}
20690 
20691 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
20692 {return nk_button_text(ctx, title, nk_strlen(title));}
20693 
20694 NK_API int
20695 nk_button_color(struct nk_context *ctx, struct nk_color color)
20696 {
20697     struct nk_window *win;
20698     struct nk_panel *layout;
20699     const struct nk_input *in;
20700     struct nk_style_button button;
20701 
20702     int ret = 0;
20703     struct nk_rect bounds;
20704     struct nk_rect content;
20705     enum nk_widget_layout_states state;
20706 
20707     NK_ASSERT(ctx);
20708     NK_ASSERT(ctx->current);
20709     NK_ASSERT(ctx->current->layout);
20710     if (!ctx || !ctx->current || !ctx->current->layout)
20711         return 0;
20712 
20713     win = ctx->current;
20714     layout = win->layout;
20715 
20716     state = nk_widget(&bounds, ctx);
20717     if (!state) return 0;
20718     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20719 
20720     button = ctx->style.button;
20721     button.normal = nk_style_item_color(color);
20722     button.hover = nk_style_item_color(color);
20723     button.active = nk_style_item_color(color);
20724     ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
20725                 &button, in, ctx->button_behavior, &content);
20726     nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
20727     return ret;
20728 }
20729 
20730 NK_API int
20731 nk_button_symbol_styled(struct nk_context *ctx,
20732     const struct nk_style_button *style, enum nk_symbol_type symbol)
20733 {
20734     struct nk_window *win;
20735     struct nk_panel *layout;
20736     const struct nk_input *in;
20737 
20738     struct nk_rect bounds;
20739     enum nk_widget_layout_states state;
20740 
20741     NK_ASSERT(ctx);
20742     NK_ASSERT(ctx->current);
20743     NK_ASSERT(ctx->current->layout);
20744     if (!ctx || !ctx->current || !ctx->current->layout)
20745         return 0;
20746 
20747     win = ctx->current;
20748     layout = win->layout;
20749     state = nk_widget(&bounds, ctx);
20750     if (!state) return 0;
20751     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20752     return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20753             symbol, ctx->button_behavior, style, in, ctx->style.font);
20754 }
20755 
20756 NK_API int
20757 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
20758 {
20759     NK_ASSERT(ctx);
20760     if (!ctx) return 0;
20761     return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
20762 }
20763 
20764 NK_API int
20765 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
20766     struct nk_image img)
20767 {
20768     struct nk_window *win;
20769     struct nk_panel *layout;
20770     const struct nk_input *in;
20771 
20772     struct nk_rect bounds;
20773     enum nk_widget_layout_states state;
20774 
20775     NK_ASSERT(ctx);
20776     NK_ASSERT(ctx->current);
20777     NK_ASSERT(ctx->current->layout);
20778     if (!ctx || !ctx->current || !ctx->current->layout)
20779         return 0;
20780 
20781     win = ctx->current;
20782     layout = win->layout;
20783 
20784     state = nk_widget(&bounds, ctx);
20785     if (!state) return 0;
20786     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20787     return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
20788                 img, ctx->button_behavior, style, in);
20789 }
20790 
20791 NK_API int
20792 nk_button_image(struct nk_context *ctx, struct nk_image img)
20793 {
20794     NK_ASSERT(ctx);
20795     if (!ctx) return 0;
20796     return nk_button_image_styled(ctx, &ctx->style.button, img);
20797 }
20798 
20799 NK_API int
20800 nk_button_symbol_text_styled(struct nk_context *ctx,
20801     const struct nk_style_button *style, enum nk_symbol_type symbol,
20802     const char *text, int len, nk_flags align)
20803 {
20804     struct nk_window *win;
20805     struct nk_panel *layout;
20806     const struct nk_input *in;
20807 
20808     struct nk_rect bounds;
20809     enum nk_widget_layout_states state;
20810 
20811     NK_ASSERT(ctx);
20812     NK_ASSERT(ctx->current);
20813     NK_ASSERT(ctx->current->layout);
20814     if (!ctx || !ctx->current || !ctx->current->layout)
20815         return 0;
20816 
20817     win = ctx->current;
20818     layout = win->layout;
20819 
20820     state = nk_widget(&bounds, ctx);
20821     if (!state) return 0;
20822     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20823     return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20824                 symbol, text, len, align, ctx->button_behavior,
20825                 style, ctx->style.font, in);
20826 }
20827 
20828 NK_API int
20829 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
20830     const char* text, int len, nk_flags align)
20831 {
20832     NK_ASSERT(ctx);
20833     if (!ctx) return 0;
20834     return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
20835 }
20836 
20837 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
20838     const char *label, nk_flags align)
20839 {return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);}
20840 
20841 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx,
20842     const struct nk_style_button *style, enum nk_symbol_type symbol,
20843     const char *title, nk_flags align)
20844 {return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);}
20845 
20846 NK_API int
20847 nk_button_image_text_styled(struct nk_context *ctx,
20848     const struct nk_style_button *style, struct nk_image img, const char *text,
20849     int len, nk_flags align)
20850 {
20851     struct nk_window *win;
20852     struct nk_panel *layout;
20853     const struct nk_input *in;
20854 
20855     struct nk_rect bounds;
20856     enum nk_widget_layout_states state;
20857 
20858     NK_ASSERT(ctx);
20859     NK_ASSERT(ctx->current);
20860     NK_ASSERT(ctx->current->layout);
20861     if (!ctx || !ctx->current || !ctx->current->layout)
20862         return 0;
20863 
20864     win = ctx->current;
20865     layout = win->layout;
20866 
20867     state = nk_widget(&bounds, ctx);
20868     if (!state) return 0;
20869     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20870     return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
20871             bounds, img, text, len, align, ctx->button_behavior,
20872             style, ctx->style.font, in);
20873 }
20874 
20875 NK_API int
20876 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
20877     const char *text, int len, nk_flags align)
20878 {return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);}
20879 
20880 
20881 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
20882     const char *label, nk_flags align)
20883 {return nk_button_image_text(ctx, img, label, nk_strlen(label), align);}
20884 
20885 NK_API int nk_button_image_label_styled(struct nk_context *ctx,
20886     const struct nk_style_button *style, struct nk_image img,
20887     const char *label, nk_flags text_alignment)
20888 {return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);}
20889 
20890 /*----------------------------------------------------------------
20891  *
20892  *                          SELECTABLE
20893  *
20894  * --------------------------------------------------------------*/
20895 NK_API int
20896 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
20897     nk_flags align, int *value)
20898 {
20899     struct nk_window *win;
20900     struct nk_panel *layout;
20901     const struct nk_input *in;
20902     const struct nk_style *style;
20903 
20904     enum nk_widget_layout_states state;
20905     struct nk_rect bounds;
20906 
20907     NK_ASSERT(ctx);
20908     NK_ASSERT(value);
20909     NK_ASSERT(ctx->current);
20910     NK_ASSERT(ctx->current->layout);
20911     if (!ctx || !ctx->current || !ctx->current->layout || !value)
20912         return 0;
20913 
20914     win = ctx->current;
20915     layout = win->layout;
20916     style = &ctx->style;
20917 
20918     state = nk_widget(&bounds, ctx);
20919     if (!state) return 0;
20920     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20921     return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
20922                 str, len, align, value, &style->selectable, in, style->font);
20923 }
20924 
20925 NK_API int
20926 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
20927     const char *str, int len, nk_flags align, int *value)
20928 {
20929     struct nk_window *win;
20930     struct nk_panel *layout;
20931     const struct nk_input *in;
20932     const struct nk_style *style;
20933 
20934     enum nk_widget_layout_states state;
20935     struct nk_rect bounds;
20936 
20937     NK_ASSERT(ctx);
20938     NK_ASSERT(value);
20939     NK_ASSERT(ctx->current);
20940     NK_ASSERT(ctx->current->layout);
20941     if (!ctx || !ctx->current || !ctx->current->layout || !value)
20942         return 0;
20943 
20944     win = ctx->current;
20945     layout = win->layout;
20946     style = &ctx->style;
20947 
20948     state = nk_widget(&bounds, ctx);
20949     if (!state) return 0;
20950     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20951     return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
20952                 str, len, align, value, &img, &style->selectable, in, style->font);
20953 }
20954 
20955 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
20956     nk_flags align, int value)
20957 {nk_selectable_text(ctx, str, len, align, &value);return value;}
20958 
20959 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
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 {return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);}
20965 
20966 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
20967 {nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;}
20968 
20969 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
20970     const char *str, nk_flags align, int value)
20971 {nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;}
20972 
20973 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
20974     const char *str, int len, nk_flags align, int value)
20975 {nk_selectable_image_text(ctx, img, str, len, align, &value);return value;}
20976 
20977 /*----------------------------------------------------------------
20978  *
20979  *                          CHECKBOX
20980  *
20981  * --------------------------------------------------------------*/
20982 NK_API int
20983 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
20984 {
20985     struct nk_window *win;
20986     struct nk_panel *layout;
20987     const struct nk_input *in;
20988     const struct nk_style *style;
20989 
20990     struct nk_rect bounds;
20991     enum nk_widget_layout_states state;
20992 
20993     NK_ASSERT(ctx);
20994     NK_ASSERT(ctx->current);
20995     NK_ASSERT(ctx->current->layout);
20996     if (!ctx || !ctx->current || !ctx->current->layout)
20997         return active;
20998 
20999     win = ctx->current;
21000     style = &ctx->style;
21001     layout = win->layout;
21002 
21003     state = nk_widget(&bounds, ctx);
21004     if (!state) return active;
21005     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21006     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
21007         text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
21008     return active;
21009 }
21010 
21011 NK_API unsigned int
21012 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
21013     unsigned int flags, unsigned int value)
21014 {
21015     int old_active;
21016     NK_ASSERT(ctx);
21017     NK_ASSERT(text);
21018     if (!ctx || !text) return flags;
21019     old_active = (int)((flags & value) & value);
21020     if (nk_check_text(ctx, text, len, old_active))
21021         flags |= value;
21022     else flags &= ~value;
21023     return flags;
21024 }
21025 
21026 NK_API int
21027 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
21028 {
21029     int old_val;
21030     NK_ASSERT(ctx);
21031     NK_ASSERT(text);
21032     NK_ASSERT(active);
21033     if (!ctx || !text || !active) return 0;
21034     old_val = *active;
21035     *active = nk_check_text(ctx, text, len, *active);
21036     return old_val != *active;
21037 }
21038 
21039 NK_API int
21040 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
21041     unsigned int *flags, unsigned int value)
21042 {
21043     int active;
21044     NK_ASSERT(ctx);
21045     NK_ASSERT(text);
21046     NK_ASSERT(flags);
21047     if (!ctx || !text || !flags) return 0;
21048 
21049     active = (int)((*flags & value) & value);
21050     if (nk_checkbox_text(ctx, text, len, &active)) {
21051         if (active) *flags |= value;
21052         else *flags &= ~value;
21053         return 1;
21054     }
21055     return 0;
21056 }
21057 
21058 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
21059 {return nk_check_text(ctx, label, nk_strlen(label), active);}
21060 
21061 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
21062     unsigned int flags, unsigned int value)
21063 {return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);}
21064 
21065 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
21066 {return nk_checkbox_text(ctx, label, nk_strlen(label), active);}
21067 
21068 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
21069     unsigned int *flags, unsigned int value)
21070 {return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);}
21071 
21072 /*----------------------------------------------------------------
21073  *
21074  *                          OPTION
21075  *
21076  * --------------------------------------------------------------*/
21077 NK_API int
21078 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
21079 {
21080     struct nk_window *win;
21081     struct nk_panel *layout;
21082     const struct nk_input *in;
21083     const struct nk_style *style;
21084 
21085     struct nk_rect bounds;
21086     enum nk_widget_layout_states state;
21087 
21088     NK_ASSERT(ctx);
21089     NK_ASSERT(ctx->current);
21090     NK_ASSERT(ctx->current->layout);
21091     if (!ctx || !ctx->current || !ctx->current->layout)
21092         return is_active;
21093 
21094     win = ctx->current;
21095     style = &ctx->style;
21096     layout = win->layout;
21097 
21098     state = nk_widget(&bounds, ctx);
21099     if (!state) return state;
21100     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21101     nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
21102         text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
21103     return is_active;
21104 }
21105 
21106 NK_API int
21107 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
21108 {
21109     int old_value;
21110     NK_ASSERT(ctx);
21111     NK_ASSERT(text);
21112     NK_ASSERT(active);
21113     if (!ctx || !text || !active) return 0;
21114     old_value = *active;
21115     *active = nk_option_text(ctx, text, len, old_value);
21116     return old_value != *active;
21117 }
21118 
21119 NK_API int
21120 nk_option_label(struct nk_context *ctx, const char *label, int active)
21121 {return nk_option_text(ctx, label, nk_strlen(label), active);}
21122 
21123 NK_API int
21124 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
21125 {return nk_radio_text(ctx, label, nk_strlen(label), active);}
21126 
21127 /*----------------------------------------------------------------
21128  *
21129  *                          SLIDER
21130  *
21131  * --------------------------------------------------------------*/
21132 NK_API int
21133 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
21134     float value_step)
21135 {
21136     struct nk_window *win;
21137     struct nk_panel *layout;
21138     struct nk_input *in;
21139     const struct nk_style *style;
21140 
21141     int ret = 0;
21142     float old_value;
21143     struct nk_rect bounds;
21144     enum nk_widget_layout_states state;
21145 
21146     NK_ASSERT(ctx);
21147     NK_ASSERT(ctx->current);
21148     NK_ASSERT(ctx->current->layout);
21149     NK_ASSERT(value);
21150     if (!ctx || !ctx->current || !ctx->current->layout || !value)
21151         return ret;
21152 
21153     win = ctx->current;
21154     style = &ctx->style;
21155     layout = win->layout;
21156 
21157     state = nk_widget(&bounds, ctx);
21158     if (!state) return ret;
21159     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21160 
21161     old_value = *value;
21162     *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
21163                 old_value, max_value, value_step, &style->slider, in, style->font);
21164     return (old_value > *value || old_value < *value);
21165 }
21166 
21167 NK_API float
21168 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
21169 {
21170     nk_slider_float(ctx, min, &val, max, step); return val;
21171 }
21172 
21173 NK_API int
21174 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
21175 {
21176     float value = (float)val;
21177     nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21178     return (int)value;
21179 }
21180 
21181 NK_API int
21182 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
21183 {
21184     int ret;
21185     float value = (float)*val;
21186     ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21187     *val =  (int)value;
21188     return ret;
21189 }
21190 
21191 /*----------------------------------------------------------------
21192  *
21193  *                          PROGRESSBAR
21194  *
21195  * --------------------------------------------------------------*/
21196 NK_API int
21197 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
21198 {
21199     struct nk_window *win;
21200     struct nk_panel *layout;
21201     const struct nk_style *style;
21202     const struct nk_input *in;
21203 
21204     struct nk_rect bounds;
21205     enum nk_widget_layout_states state;
21206     nk_size old_value;
21207 
21208     NK_ASSERT(ctx);
21209     NK_ASSERT(cur);
21210     NK_ASSERT(ctx->current);
21211     NK_ASSERT(ctx->current->layout);
21212     if (!ctx || !ctx->current || !ctx->current->layout || !cur)
21213         return 0;
21214 
21215     win = ctx->current;
21216     style = &ctx->style;
21217     layout = win->layout;
21218     state = nk_widget(&bounds, ctx);
21219     if (!state) return 0;
21220 
21221     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21222     old_value = *cur;
21223     *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
21224             *cur, max, is_modifyable, &style->progress, in);
21225     return (*cur != old_value);
21226 }
21227 
21228 NK_API nk_size nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
21229 {nk_progress(ctx, &cur, max, modifyable);return cur;}
21230 
21231 /*----------------------------------------------------------------
21232  *
21233  *                          EDIT
21234  *
21235  * --------------------------------------------------------------*/
21236 NK_API void
21237 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
21238 {
21239     nk_hash hash;
21240     struct nk_window *win;
21241 
21242     NK_ASSERT(ctx);
21243     NK_ASSERT(ctx->current);
21244     if (!ctx || !ctx->current) return;
21245 
21246     win = ctx->current;
21247     hash = win->edit.seq;
21248     win->edit.active = nk_true;
21249     win->edit.name = hash;
21250     if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
21251         win->edit.mode = NK_TEXT_EDIT_MODE_INSERT;
21252 }
21253 
21254 NK_API void
21255 nk_edit_unfocus(struct nk_context *ctx)
21256 {
21257     struct nk_window *win;
21258     NK_ASSERT(ctx);
21259     NK_ASSERT(ctx->current);
21260     if (!ctx || !ctx->current) return;
21261 
21262     win = ctx->current;
21263     win->edit.active = nk_false;
21264     win->edit.name = 0;
21265 }
21266 
21267 NK_API nk_flags
21268 nk_edit_string(struct nk_context *ctx, nk_flags flags,
21269     char *memory, int *len, int max, nk_plugin_filter filter)
21270 {
21271     nk_hash hash;
21272     nk_flags state;
21273     struct nk_text_edit *edit;
21274     struct nk_window *win;
21275 
21276     NK_ASSERT(ctx);
21277     NK_ASSERT(memory);
21278     NK_ASSERT(len);
21279     if (!ctx || !memory || !len)
21280         return 0;
21281 
21282     filter = (!filter) ? nk_filter_default: filter;
21283     win = ctx->current;
21284     hash = win->edit.seq;
21285     edit = &ctx->text_edit;
21286     nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
21287         NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter);
21288 
21289     if (win->edit.active && hash == win->edit.name) {
21290         if (flags & NK_EDIT_NO_CURSOR)
21291             edit->cursor = nk_utf_len(memory, *len);
21292         else edit->cursor = win->edit.cursor;
21293         if (!(flags & NK_EDIT_SELECTABLE)) {
21294             edit->select_start = win->edit.cursor;
21295             edit->select_end = win->edit.cursor;
21296         } else {
21297             edit->select_start = win->edit.sel_start;
21298             edit->select_end = win->edit.sel_end;
21299         }
21300         edit->mode = win->edit.mode;
21301         edit->scrollbar.x = (float)win->edit.scrollbar.x;
21302         edit->scrollbar.y = (float)win->edit.scrollbar.y;
21303         edit->active = nk_true;
21304     } else edit->active = nk_false;
21305 
21306     max = NK_MAX(1, max);
21307     *len = NK_MIN(*len, max-1);
21308     nk_str_init_fixed(&edit->string, memory, (nk_size)max);
21309     edit->string.buffer.allocated = (nk_size)*len;
21310     edit->string.len = nk_utf_len(memory, *len);
21311     state = nk_edit_buffer(ctx, flags, edit, filter);
21312     *len = (int)edit->string.buffer.allocated;
21313 
21314     if (edit->active) {
21315         win->edit.cursor = edit->cursor;
21316         win->edit.sel_start = edit->select_start;
21317         win->edit.sel_end = edit->select_end;
21318         win->edit.mode = edit->mode;
21319         win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x;
21320         win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y;
21321     }
21322     return state;
21323 }
21324 
21325 NK_API nk_flags
21326 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
21327     struct nk_text_edit *edit, nk_plugin_filter filter)
21328 {
21329     struct nk_window *win;
21330     struct nk_style *style;
21331     struct nk_input *in;
21332 
21333     enum nk_widget_layout_states state;
21334     struct nk_rect bounds;
21335 
21336     nk_flags ret_flags = 0;
21337     unsigned char prev_state;
21338     nk_hash hash;
21339 
21340     /* make sure correct values */
21341     NK_ASSERT(ctx);
21342     NK_ASSERT(edit);
21343     NK_ASSERT(ctx->current);
21344     NK_ASSERT(ctx->current->layout);
21345     if (!ctx || !ctx->current || !ctx->current->layout)
21346         return 0;
21347 
21348     win = ctx->current;
21349     style = &ctx->style;
21350     state = nk_widget(&bounds, ctx);
21351     if (!state) return state;
21352     in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21353 
21354     /* check if edit is currently hot item */
21355     hash = win->edit.seq++;
21356     if (win->edit.active && hash == win->edit.name) {
21357         if (flags & NK_EDIT_NO_CURSOR)
21358             edit->cursor = edit->string.len;
21359         if (!(flags & NK_EDIT_SELECTABLE)) {
21360             edit->select_start = edit->cursor;
21361             edit->select_end = edit->cursor;
21362         }
21363         if (flags & NK_EDIT_CLIPBOARD)
21364             edit->clip = ctx->clip;
21365         edit->active = (unsigned char)win->edit.active;
21366     } else edit->active = nk_false;
21367     edit->mode = win->edit.mode;
21368 
21369     filter = (!filter) ? nk_filter_default: filter;
21370     prev_state = (unsigned char)edit->active;
21371     in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
21372     ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
21373                     filter, edit, &style->edit, in, style->font);
21374 
21375     if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
21376         ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT];
21377     if (edit->active && prev_state != edit->active) {
21378         /* current edit is now hot */
21379         win->edit.active = nk_true;
21380         win->edit.name = hash;
21381     } else if (prev_state && !edit->active) {
21382         /* current edit is now cold */
21383         win->edit.active = nk_false;
21384     }
21385     return ret_flags;
21386 }
21387 
21388 NK_API nk_flags
21389 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
21390     char *buffer, int max, nk_plugin_filter filter)
21391 {
21392     nk_flags result;
21393     int len = nk_strlen(buffer);
21394     result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
21395     buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
21396     return result;
21397 }
21398 
21399 /*----------------------------------------------------------------
21400  *
21401  *                          PROPERTY
21402  *
21403  * --------------------------------------------------------------*/
21404 NK_INTERN struct nk_property_variant
21405 nk_property_variant_int(int value, int min_value, int max_value, int step)
21406 {
21407     struct nk_property_variant result;
21408     result.kind = NK_PROPERTY_INT;
21409     result.value.i = value;
21410     result.min_value.i = min_value;
21411     result.max_value.i = max_value;
21412     result.step.i = step;
21413     return result;
21414 }
21415 
21416 NK_INTERN struct nk_property_variant
21417 nk_property_variant_float(float value, float min_value, float max_value, float step)
21418 {
21419     struct nk_property_variant result;
21420     result.kind = NK_PROPERTY_FLOAT;
21421     result.value.f = value;
21422     result.min_value.f = min_value;
21423     result.max_value.f = max_value;
21424     result.step.f = step;
21425     return result;
21426 }
21427 
21428 NK_INTERN struct nk_property_variant
21429 nk_property_variant_double(double value, double min_value, double max_value,
21430     double step)
21431 {
21432     struct nk_property_variant result;
21433     result.kind = NK_PROPERTY_DOUBLE;
21434     result.value.d = value;
21435     result.min_value.d = min_value;
21436     result.max_value.d = max_value;
21437     result.step.d = step;
21438     return result;
21439 }
21440 
21441 NK_INTERN void
21442 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
21443     float inc_per_pixel, const enum nk_property_filter filter)
21444 {
21445     struct nk_window *win;
21446     struct nk_panel *layout;
21447     struct nk_input *in;
21448     const struct nk_style *style;
21449 
21450     struct nk_rect bounds;
21451     enum nk_widget_layout_states s;
21452 
21453     int *state = 0;
21454     nk_hash hash = 0;
21455     char *buffer = 0;
21456     int *len = 0;
21457     int *cursor = 0;
21458     int *select_begin = 0;
21459     int *select_end = 0;
21460     int old_state;
21461 
21462     char dummy_buffer[NK_MAX_NUMBER_BUFFER];
21463     int dummy_state = NK_PROPERTY_DEFAULT;
21464     int dummy_length = 0;
21465     int dummy_cursor = 0;
21466     int dummy_select_begin = 0;
21467     int dummy_select_end = 0;
21468 
21469     NK_ASSERT(ctx);
21470     NK_ASSERT(ctx->current);
21471     NK_ASSERT(ctx->current->layout);
21472     if (!ctx || !ctx->current || !ctx->current->layout)
21473         return;
21474 
21475     win = ctx->current;
21476     layout = win->layout;
21477     style = &ctx->style;
21478     s = nk_widget(&bounds, ctx);
21479     if (!s) return;
21480 
21481     /* calculate hash from name */
21482     if (name[0] == '#') {
21483         hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
21484         name++; /* special number hash */
21485     } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
21486 
21487     /* check if property is currently hot item */
21488     if (win->property.active && hash == win->property.name) {
21489         buffer = win->property.buffer;
21490         len = &win->property.length;
21491         cursor = &win->property.cursor;
21492         state = &win->property.state;
21493         select_begin = &win->property.select_start;
21494         select_end = &win->property.select_end;
21495     } else {
21496         buffer = dummy_buffer;
21497         len = &dummy_length;
21498         cursor = &dummy_cursor;
21499         state = &dummy_state;
21500         select_begin =  &dummy_select_begin;
21501         select_end = &dummy_select_end;
21502     }
21503 
21504     /* execute property widget */
21505     old_state = *state;
21506     ctx->text_edit.clip = ctx->clip;
21507     in = ((s == NK_WIDGET_ROM && !win->property.active) ||
21508         layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21509     nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
21510         variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
21511         select_end, &style->property, filter, in, style->font, &ctx->text_edit,
21512         ctx->button_behavior);
21513 
21514     if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
21515         /* current property is now hot */
21516         win->property.active = 1;
21517         NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
21518         win->property.length = *len;
21519         win->property.cursor = *cursor;
21520         win->property.state = *state;
21521         win->property.name = hash;
21522         win->property.select_start = *select_begin;
21523         win->property.select_end = *select_end;
21524         if (*state == NK_PROPERTY_DRAG) {
21525             ctx->input.mouse.grab = nk_true;
21526             ctx->input.mouse.grabbed = nk_true;
21527         }
21528     }
21529     /* check if previously active property is now inactive */
21530     if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
21531         if (old_state == NK_PROPERTY_DRAG) {
21532             ctx->input.mouse.grab = nk_false;
21533             ctx->input.mouse.grabbed = nk_false;
21534             ctx->input.mouse.ungrab = nk_true;
21535         }
21536         win->property.select_start = 0;
21537         win->property.select_end = 0;
21538         win->property.active = 0;
21539     }
21540 }
21541 
21542 NK_API void
21543 nk_property_int(struct nk_context *ctx, const char *name,
21544     int min, int *val, int max, int step, float inc_per_pixel)
21545 {
21546     struct nk_property_variant variant;
21547     NK_ASSERT(ctx);
21548     NK_ASSERT(name);
21549     NK_ASSERT(val);
21550 
21551     if (!ctx || !ctx->current || !name || !val) return;
21552     variant = nk_property_variant_int(*val, min, max, step);
21553     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21554     *val = variant.value.i;
21555 }
21556 
21557 NK_API void
21558 nk_property_float(struct nk_context *ctx, const char *name,
21559     float min, float *val, float max, float step, float inc_per_pixel)
21560 {
21561     struct nk_property_variant variant;
21562     NK_ASSERT(ctx);
21563     NK_ASSERT(name);
21564     NK_ASSERT(val);
21565 
21566     if (!ctx || !ctx->current || !name || !val) return;
21567     variant = nk_property_variant_float(*val, min, max, step);
21568     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21569     *val = variant.value.f;
21570 }
21571 
21572 NK_API void
21573 nk_property_double(struct nk_context *ctx, const char *name,
21574     double min, double *val, double max, double step, float inc_per_pixel)
21575 {
21576     struct nk_property_variant variant;
21577     NK_ASSERT(ctx);
21578     NK_ASSERT(name);
21579     NK_ASSERT(val);
21580 
21581     if (!ctx || !ctx->current || !name || !val) return;
21582     variant = nk_property_variant_double(*val, min, max, step);
21583     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21584     *val = variant.value.d;
21585 }
21586 
21587 NK_API int
21588 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
21589     int max, int step, float inc_per_pixel)
21590 {
21591     struct nk_property_variant variant;
21592     NK_ASSERT(ctx);
21593     NK_ASSERT(name);
21594 
21595     if (!ctx || !ctx->current || !name) return val;
21596     variant = nk_property_variant_int(val, min, max, step);
21597     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21598     val = variant.value.i;
21599     return val;
21600 }
21601 
21602 NK_API float
21603 nk_propertyf(struct nk_context *ctx, const char *name, float min,
21604     float val, float max, float step, float inc_per_pixel)
21605 {
21606     struct nk_property_variant variant;
21607     NK_ASSERT(ctx);
21608     NK_ASSERT(name);
21609 
21610     if (!ctx || !ctx->current || !name) return val;
21611     variant = nk_property_variant_float(val, min, max, step);
21612     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21613     val = variant.value.f;
21614     return val;
21615 }
21616 
21617 NK_API double
21618 nk_propertyd(struct nk_context *ctx, const char *name, double min,
21619     double val, double max, double step, float inc_per_pixel)
21620 {
21621     struct nk_property_variant variant;
21622     NK_ASSERT(ctx);
21623     NK_ASSERT(name);
21624 
21625     if (!ctx || !ctx->current || !name) return val;
21626     variant = nk_property_variant_double(val, min, max, step);
21627     nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21628     val = variant.value.d;
21629     return val;
21630 }
21631 
21632 /*----------------------------------------------------------------
21633  *
21634  *                          COLOR PICKER
21635  *
21636  * --------------------------------------------------------------*/
21637 NK_API int
21638 nk_color_pick(struct nk_context * ctx, struct nk_color *color,
21639     enum nk_color_format fmt)
21640 {
21641     struct nk_window *win;
21642     struct nk_panel *layout;
21643     const struct nk_style *config;
21644     const struct nk_input *in;
21645 
21646     enum nk_widget_layout_states state;
21647     struct nk_rect bounds;
21648 
21649     NK_ASSERT(ctx);
21650     NK_ASSERT(color);
21651     NK_ASSERT(ctx->current);
21652     NK_ASSERT(ctx->current->layout);
21653     if (!ctx || !ctx->current || !ctx->current->layout || !color)
21654         return 0;
21655 
21656     win = ctx->current;
21657     config = &ctx->style;
21658     layout = win->layout;
21659     state = nk_widget(&bounds, ctx);
21660     if (!state) return 0;
21661     in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21662     return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
21663                 nk_vec2(0,0), in, config->font);
21664 }
21665 
21666 NK_API struct nk_color
21667 nk_color_picker(struct nk_context *ctx, struct nk_color color,
21668     enum nk_color_format fmt)
21669 {
21670     nk_color_pick(ctx, &color, fmt);
21671     return color;
21672 }
21673 
21674 /* -------------------------------------------------------------
21675  *
21676  *                          CHART
21677  *
21678  * --------------------------------------------------------------*/
21679 NK_API int
21680 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
21681     struct nk_color color, struct nk_color highlight,
21682     int count, float min_value, float max_value)
21683 {
21684     struct nk_window *win;
21685     struct nk_chart *chart;
21686     const struct nk_style *config;
21687     const struct nk_style_chart *style;
21688 
21689     const struct nk_style_item *background;
21690     struct nk_rect bounds = {0, 0, 0, 0};
21691 
21692     NK_ASSERT(ctx);
21693     NK_ASSERT(ctx->current);
21694     NK_ASSERT(ctx->current->layout);
21695 
21696     if (!ctx || !ctx->current || !ctx->current->layout) return 0;
21697     if (!nk_widget(&bounds, ctx)) {
21698         chart = &ctx->current->layout->chart;
21699         nk_zero(chart, sizeof(*chart));
21700         return 0;
21701     }
21702 
21703     win = ctx->current;
21704     config = &ctx->style;
21705     chart = &win->layout->chart;
21706     style = &config->chart;
21707 
21708     /* setup basic generic chart  */
21709     nk_zero(chart, sizeof(*chart));
21710     chart->x = bounds.x + style->padding.x;
21711     chart->y = bounds.y + style->padding.y;
21712     chart->w = bounds.w - 2 * style->padding.x;
21713     chart->h = bounds.h - 2 * style->padding.y;
21714     chart->w = NK_MAX(chart->w, 2 * style->padding.x);
21715     chart->h = NK_MAX(chart->h, 2 * style->padding.y);
21716 
21717     /* add first slot into chart */
21718     {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21719     slot->type = type;
21720     slot->count = count;
21721     slot->color = color;
21722     slot->highlight = highlight;
21723     slot->min = NK_MIN(min_value, max_value);
21724     slot->max = NK_MAX(min_value, max_value);
21725     slot->range = slot->max - slot->min;}
21726 
21727     /* draw chart background */
21728     background = &style->background;
21729     if (background->type == NK_STYLE_ITEM_IMAGE) {
21730         nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
21731     } else {
21732         nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
21733         nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
21734             style->rounding, style->background.data.color);
21735     }
21736     return 1;
21737 }
21738 
21739 NK_API int
21740 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
21741     int count, float min_value, float max_value)
21742 {return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21743 
21744 NK_API void
21745 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
21746     struct nk_color color, struct nk_color highlight,
21747     int count, float min_value, float max_value)
21748 {
21749     NK_ASSERT(ctx);
21750     NK_ASSERT(ctx->current);
21751     NK_ASSERT(ctx->current->layout);
21752     NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
21753     if (!ctx || !ctx->current || !ctx->current->layout) return;
21754     if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
21755 
21756     /* add another slot into the graph */
21757     {struct nk_chart *chart = &ctx->current->layout->chart;
21758     struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21759     slot->type = type;
21760     slot->count = count;
21761     slot->color = color;
21762     slot->highlight = highlight;
21763     slot->min = NK_MIN(min_value, max_value);
21764     slot->max = NK_MAX(min_value, max_value);
21765     slot->range = slot->max - slot->min;}
21766 }
21767 
21768 NK_API void
21769 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
21770     int count, float min_value, float max_value)
21771 {nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21772 
21773 NK_INTERN nk_flags
21774 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
21775     struct nk_chart *g, float value, int slot)
21776 {
21777     struct nk_panel *layout = win->layout;
21778     const struct nk_input *i = &ctx->input;
21779     struct nk_command_buffer *out = &win->buffer;
21780 
21781     nk_flags ret = 0;
21782     struct nk_vec2 cur;
21783     struct nk_rect bounds;
21784     struct nk_color color;
21785     float step;
21786     float range;
21787     float ratio;
21788 
21789     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21790     step = g->w / (float)g->slots[slot].count;
21791     range = g->slots[slot].max - g->slots[slot].min;
21792     ratio = (value - g->slots[slot].min) / range;
21793 
21794     if (g->slots[slot].index == 0) {
21795         /* first data point does not have a connection */
21796         g->slots[slot].last.x = g->x;
21797         g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
21798 
21799         bounds.x = g->slots[slot].last.x - 2;
21800         bounds.y = g->slots[slot].last.y - 2;
21801         bounds.w = bounds.h = 4;
21802 
21803         color = g->slots[slot].color;
21804         if (!(layout->flags & NK_WINDOW_ROM) &&
21805             NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
21806             ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
21807             ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
21808                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
21809             color = g->slots[slot].highlight;
21810         }
21811         nk_fill_rect(out, bounds, 0, color);
21812         g->slots[slot].index += 1;
21813         return ret;
21814     }
21815 
21816     /* draw a line between the last data point and the new one */
21817     color = g->slots[slot].color;
21818     cur.x = g->x + (float)(step * (float)g->slots[slot].index);
21819     cur.y = (g->y + g->h) - (ratio * (float)g->h);
21820     nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
21821 
21822     bounds.x = cur.x - 3;
21823     bounds.y = cur.y - 3;
21824     bounds.w = bounds.h = 6;
21825 
21826     /* user selection of current data point */
21827     if (!(layout->flags & NK_WINDOW_ROM)) {
21828         if (nk_input_is_mouse_hovering_rect(i, bounds)) {
21829             ret = NK_CHART_HOVERING;
21830             ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
21831                 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
21832             color = g->slots[slot].highlight;
21833         }
21834     }
21835     nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
21836 
21837     /* save current data point position */
21838     g->slots[slot].last.x = cur.x;
21839     g->slots[slot].last.y = cur.y;
21840     g->slots[slot].index  += 1;
21841     return ret;
21842 }
21843 
21844 NK_INTERN nk_flags
21845 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
21846     struct nk_chart *chart, float value, int slot)
21847 {
21848     struct nk_command_buffer *out = &win->buffer;
21849     const struct nk_input *in = &ctx->input;
21850     struct nk_panel *layout = win->layout;
21851 
21852     float ratio;
21853     nk_flags ret = 0;
21854     struct nk_color color;
21855     struct nk_rect item = {0,0,0,0};
21856 
21857     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21858     if (chart->slots[slot].index  >= chart->slots[slot].count)
21859         return nk_false;
21860     if (chart->slots[slot].count) {
21861         float padding = (float)(chart->slots[slot].count-1);
21862         item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
21863     }
21864 
21865     /* calculate bounds of current bar chart entry */
21866     color = chart->slots[slot].color;;
21867     item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
21868     if (value >= 0) {
21869         ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
21870         item.y = (chart->y + chart->h) - chart->h * ratio;
21871     } else {
21872         ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
21873         item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
21874     }
21875     item.x = chart->x + ((float)chart->slots[slot].index * item.w);
21876     item.x = item.x + ((float)chart->slots[slot].index);
21877 
21878     /* user chart bar selection */
21879     if (!(layout->flags & NK_WINDOW_ROM) &&
21880         NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
21881         ret = NK_CHART_HOVERING;
21882         ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
21883                 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
21884         color = chart->slots[slot].highlight;
21885     }
21886     nk_fill_rect(out, item, 0, color);
21887     chart->slots[slot].index += 1;
21888     return ret;
21889 }
21890 
21891 NK_API nk_flags
21892 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
21893 {
21894     nk_flags flags;
21895     struct nk_window *win;
21896 
21897     NK_ASSERT(ctx);
21898     NK_ASSERT(ctx->current);
21899     NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21900     NK_ASSERT(slot < ctx->current->layout->chart.slot);
21901     if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
21902     if (slot >= ctx->current->layout->chart.slot) return nk_false;
21903 
21904     win = ctx->current;
21905     if (win->layout->chart.slot < slot) return nk_false;
21906     switch (win->layout->chart.slots[slot].type) {
21907     case NK_CHART_LINES:
21908         flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
21909     case NK_CHART_COLUMN:
21910         flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
21911     default:
21912     case NK_CHART_MAX:
21913         flags = 0;
21914     }
21915     return flags;
21916 }
21917 
21918 NK_API nk_flags
21919 nk_chart_push(struct nk_context *ctx, float value)
21920 {return nk_chart_push_slot(ctx, value, 0);}
21921 
21922 NK_API void
21923 nk_chart_end(struct nk_context *ctx)
21924 {
21925     struct nk_window *win;
21926     struct nk_chart *chart;
21927 
21928     NK_ASSERT(ctx);
21929     NK_ASSERT(ctx->current);
21930     if (!ctx || !ctx->current)
21931         return;
21932 
21933     win = ctx->current;
21934     chart = &win->layout->chart;
21935     NK_MEMSET(chart, 0, sizeof(*chart));
21936     return;
21937 }
21938 
21939 NK_API void
21940 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
21941     int count, int offset)
21942 {
21943     int i = 0;
21944     float min_value;
21945     float max_value;
21946 
21947     NK_ASSERT(ctx);
21948     NK_ASSERT(values);
21949     if (!ctx || !values || !count) return;
21950 
21951     min_value = values[offset];
21952     max_value = values[offset];
21953     for (i = 0; i < count; ++i) {
21954         min_value = NK_MIN(values[i + offset], min_value);
21955         max_value = NK_MAX(values[i + offset], max_value);
21956     }
21957 
21958     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
21959         for (i = 0; i < count; ++i)
21960             nk_chart_push(ctx, values[i + offset]);
21961         nk_chart_end(ctx);
21962     }
21963 }
21964 
21965 NK_API void
21966 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
21967     float(*value_getter)(void* user, int index), int count, int offset)
21968 {
21969     int i = 0;
21970     float min_value;
21971     float max_value;
21972 
21973     NK_ASSERT(ctx);
21974     NK_ASSERT(value_getter);
21975     if (!ctx || !value_getter || !count) return;
21976 
21977     max_value = min_value = value_getter(userdata, offset);
21978     for (i = 0; i < count; ++i) {
21979         float value = value_getter(userdata, i + offset);
21980         min_value = NK_MIN(value, min_value);
21981         max_value = NK_MAX(value, max_value);
21982     }
21983 
21984     if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
21985         for (i = 0; i < count; ++i)
21986             nk_chart_push(ctx, value_getter(userdata, i + offset));
21987         nk_chart_end(ctx);
21988     }
21989 }
21990 
21991 /* -------------------------------------------------------------
21992  *
21993  *                          GROUP
21994  *
21995  * --------------------------------------------------------------*/
21996 NK_API int
21997 nk_group_scrolled_offset_begin(struct nk_context *ctx,
21998     nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
21999 {
22000     struct nk_rect bounds;
22001     struct nk_window panel;
22002     struct nk_window *win;
22003 
22004     win = ctx->current;
22005     nk_panel_alloc_space(&bounds, ctx);
22006     {const struct nk_rect *c = &win->layout->clip;
22007     if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
22008         !(flags & NK_WINDOW_MOVABLE)) {
22009         return 0;
22010     }}
22011     if (win->flags & NK_WINDOW_ROM)
22012         flags |= NK_WINDOW_ROM;
22013 
22014     /* initialize a fake window to create the panel from */
22015     nk_zero(&panel, sizeof(panel));
22016     panel.bounds = bounds;
22017     panel.flags = flags;
22018     panel.scrollbar.x = *x_offset;
22019     panel.scrollbar.y = *y_offset;
22020     panel.buffer = win->buffer;
22021     panel.layout = (struct nk_panel*)nk_create_panel(ctx);
22022     ctx->current = &panel;
22023     nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
22024 
22025     win->buffer = panel.buffer;
22026     win->buffer.clip = panel.layout->clip;
22027     panel.layout->offset_x = x_offset;
22028     panel.layout->offset_y = y_offset;
22029     panel.layout->parent = win->layout;
22030     win->layout = panel.layout;
22031 
22032     ctx->current = win;
22033     if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
22034         (panel.layout->flags & NK_WINDOW_MINIMIZED))
22035     {
22036         nk_flags f = panel.layout->flags;
22037         nk_group_scrolled_end(ctx);
22038         if (f & NK_WINDOW_CLOSED)
22039             return NK_WINDOW_CLOSED;
22040         if (f & NK_WINDOW_MINIMIZED)
22041             return NK_WINDOW_MINIMIZED;
22042     }
22043     return 1;
22044 }
22045 
22046 NK_API void
22047 nk_group_scrolled_end(struct nk_context *ctx)
22048 {
22049     struct nk_window *win;
22050     struct nk_panel *parent;
22051     struct nk_panel *g;
22052 
22053     struct nk_rect clip;
22054     struct nk_window pan;
22055     struct nk_vec2 panel_padding;
22056 
22057     NK_ASSERT(ctx);
22058     NK_ASSERT(ctx->current);
22059     if (!ctx || !ctx->current)
22060         return;
22061 
22062     /* make sure nk_group_begin was called correctly */
22063     NK_ASSERT(ctx->current);
22064     win = ctx->current;
22065     NK_ASSERT(win->layout);
22066     g = win->layout;
22067     NK_ASSERT(g->parent);
22068     parent = g->parent;
22069 
22070     /* dummy window */
22071     nk_zero_struct(pan);
22072     panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
22073     pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
22074     pan.bounds.x = g->bounds.x - panel_padding.x;
22075     pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
22076     pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
22077     if (g->flags & NK_WINDOW_BORDER) {
22078         pan.bounds.x -= g->border;
22079         pan.bounds.y -= g->border;
22080         pan.bounds.w += 2*g->border;
22081         pan.bounds.h += 2*g->border;
22082     }
22083     if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
22084         pan.bounds.w += ctx->style.window.scrollbar_size.x;
22085         pan.bounds.h += ctx->style.window.scrollbar_size.y;
22086     }
22087     pan.scrollbar.x = *g->offset_x;
22088     pan.scrollbar.y = *g->offset_y;
22089     pan.flags = g->flags;
22090     pan.buffer = win->buffer;
22091     pan.layout = g;
22092     pan.parent = win;
22093     ctx->current = &pan;
22094 
22095     /* make sure group has correct clipping rectangle */
22096     nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
22097         pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
22098     nk_push_scissor(&pan.buffer, clip);
22099     nk_end(ctx);
22100 
22101     win->buffer = pan.buffer;
22102     nk_push_scissor(&win->buffer, parent->clip);
22103     ctx->current = win;
22104     win->layout = parent;
22105     g->bounds = pan.bounds;
22106     return;
22107 }
22108 
22109 NK_API int
22110 nk_group_scrolled_begin(struct nk_context *ctx,
22111     struct nk_scroll *scroll, const char *title, nk_flags flags)
22112 {return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);}
22113 
22114 NK_API int
22115 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
22116 {
22117     int title_len;
22118     nk_hash title_hash;
22119     struct nk_window *win;
22120     nk_uint *x_offset;
22121     nk_uint *y_offset;
22122 
22123     NK_ASSERT(ctx);
22124     NK_ASSERT(title);
22125     NK_ASSERT(ctx->current);
22126     NK_ASSERT(ctx->current->layout);
22127     if (!ctx || !ctx->current || !ctx->current->layout || !title)
22128         return 0;
22129 
22130     /* find persistent group scrollbar value */
22131     win = ctx->current;
22132     title_len = (int)nk_strlen(title);
22133     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
22134     x_offset = nk_find_value(win, title_hash);
22135     if (!x_offset) {
22136         x_offset = nk_add_value(ctx, win, title_hash, 0);
22137         y_offset = nk_add_value(ctx, win, title_hash+1, 0);
22138 
22139         NK_ASSERT(x_offset);
22140         NK_ASSERT(y_offset);
22141         if (!x_offset || !y_offset) return 0;
22142         *x_offset = *y_offset = 0;
22143     } else y_offset = nk_find_value(win, title_hash+1);
22144     return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
22145 }
22146 
22147 NK_API void
22148 nk_group_end(struct nk_context *ctx)
22149 {nk_group_scrolled_end(ctx);}
22150 
22151 NK_API int
22152 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
22153     const char *title, nk_flags flags, int row_height, int row_count)
22154 {
22155     int title_len;
22156     nk_hash title_hash;
22157     nk_uint *x_offset;
22158     nk_uint *y_offset;
22159 
22160     int result;
22161     struct nk_window *win;
22162     struct nk_panel *layout;
22163     const struct nk_style *style;
22164     struct nk_vec2 item_spacing;
22165 
22166     NK_ASSERT(ctx);
22167     NK_ASSERT(view);
22168     NK_ASSERT(title);
22169     if (!ctx || !view || !title) return 0;
22170 
22171     win = ctx->current;
22172     style = &ctx->style;
22173     item_spacing = style->window.spacing;
22174     row_height += NK_MAX(0, (int)item_spacing.y);
22175 
22176     /* find persistent list view scrollbar offset */
22177     title_len = (int)nk_strlen(title);
22178     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
22179     x_offset = nk_find_value(win, title_hash);
22180     if (!x_offset) {
22181         x_offset = nk_add_value(ctx, win, title_hash, 0);
22182         y_offset = nk_add_value(ctx, win, title_hash+1, 0);
22183 
22184         NK_ASSERT(x_offset);
22185         NK_ASSERT(y_offset);
22186         if (!x_offset || !y_offset) return 0;
22187         *x_offset = *y_offset = 0;
22188     } else y_offset = nk_find_value(win, title_hash+1);
22189     view->scroll_value = *y_offset;
22190     view->scroll_pointer = y_offset;
22191 
22192     *y_offset = 0;
22193     result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
22194     win = ctx->current;
22195     layout = win->layout;
22196 
22197     view->total_height = row_height * NK_MAX(row_count,1);
22198     view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
22199     view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0);
22200     view->end = view->begin + view->count;
22201     view->ctx = ctx;
22202     return result;
22203 }
22204 
22205 NK_API void
22206 nk_list_view_end(struct nk_list_view *view)
22207 {
22208     struct nk_context *ctx;
22209     struct nk_window *win;
22210     struct nk_panel *layout;
22211 
22212     NK_ASSERT(view);
22213     NK_ASSERT(view->ctx);
22214     NK_ASSERT(view->scroll_pointer);
22215     if (!view || !view->ctx) return;
22216 
22217     ctx = view->ctx;
22218     win = ctx->current;
22219     layout = win->layout;
22220     layout->at_y = layout->bounds.y + (float)view->total_height;
22221     *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
22222     nk_group_end(view->ctx);
22223 }
22224 
22225 /* --------------------------------------------------------------
22226  *
22227  *                          POPUP
22228  *
22229  * --------------------------------------------------------------*/
22230 NK_API int
22231 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
22232     const char *title, nk_flags flags, struct nk_rect rect)
22233 {
22234     struct nk_window *popup;
22235     struct nk_window *win;
22236     struct nk_panel *panel;
22237 
22238     int title_len;
22239     nk_hash title_hash;
22240     nk_size allocated;
22241 
22242     NK_ASSERT(ctx);
22243     NK_ASSERT(title);
22244     NK_ASSERT(ctx->current);
22245     NK_ASSERT(ctx->current->layout);
22246     if (!ctx || !ctx->current || !ctx->current->layout)
22247         return 0;
22248 
22249     win = ctx->current;
22250     panel = win->layout;
22251     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
22252     (void)panel;
22253     title_len = (int)nk_strlen(title);
22254     title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
22255 
22256     popup = win->popup.win;
22257     if (!popup) {
22258         popup = (struct nk_window*)nk_create_window(ctx);
22259         popup->parent = win;
22260         win->popup.win = popup;
22261         win->popup.active = 0;
22262         win->popup.type = NK_PANEL_POPUP;
22263     }
22264 
22265     /* make sure we have correct popup */
22266     if (win->popup.name != title_hash) {
22267         if (!win->popup.active) {
22268             nk_zero(popup, sizeof(*popup));
22269             win->popup.name = title_hash;
22270             win->popup.active = 1;
22271             win->popup.type = NK_PANEL_POPUP;
22272         } else return 0;
22273     }
22274 
22275     /* popup position is local to window */
22276     ctx->current = popup;
22277     rect.x += win->layout->clip.x;
22278     rect.y += win->layout->clip.y;
22279 
22280     /* setup popup data */
22281     popup->parent = win;
22282     popup->bounds = rect;
22283     popup->seq = ctx->seq;
22284     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
22285     popup->flags = flags;
22286     popup->flags |= NK_WINDOW_BORDER;
22287     if (type == NK_POPUP_DYNAMIC)
22288         popup->flags |= NK_WINDOW_DYNAMIC;
22289 
22290     popup->buffer = win->buffer;
22291     nk_start_popup(ctx, win);
22292     allocated = ctx->memory.allocated;
22293     nk_push_scissor(&popup->buffer, nk_null_rect);
22294 
22295     if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
22296         /* popup is running therefore invalidate parent panels */
22297         struct nk_panel *root;
22298         root = win->layout;
22299         while (root) {
22300             root->flags |= NK_WINDOW_ROM;
22301             root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
22302             root = root->parent;
22303         }
22304         win->popup.active = 1;
22305         popup->layout->offset_x = &popup->scrollbar.x;
22306         popup->layout->offset_y = &popup->scrollbar.y;
22307         popup->layout->parent = win->layout;
22308         return 1;
22309     } else {
22310         /* popup was closed/is invalid so cleanup */
22311         struct nk_panel *root;
22312         root = win->layout;
22313         while (root) {
22314             root->flags |= NK_WINDOW_REMOVE_ROM;
22315             root = root->parent;
22316         }
22317         win->popup.buf.active = 0;
22318         win->popup.active = 0;
22319         ctx->memory.allocated = allocated;
22320         ctx->current = win;
22321         nk_free_panel(ctx, popup->layout);
22322         popup->layout = 0;
22323         return 0;
22324     }
22325 }
22326 
22327 NK_INTERN int
22328 nk_nonblock_begin(struct nk_context *ctx,
22329     nk_flags flags, struct nk_rect body, struct nk_rect header,
22330     enum nk_panel_type panel_type)
22331 {
22332     struct nk_window *popup;
22333     struct nk_window *win;
22334     struct nk_panel *panel;
22335     int is_active = nk_true;
22336 
22337     NK_ASSERT(ctx);
22338     NK_ASSERT(ctx->current);
22339     NK_ASSERT(ctx->current->layout);
22340     if (!ctx || !ctx->current || !ctx->current->layout)
22341         return 0;
22342 
22343     /* popups cannot have popups */
22344     win = ctx->current;
22345     panel = win->layout;
22346     NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
22347     (void)panel;
22348     popup = win->popup.win;
22349     if (!popup) {
22350         /* create window for nonblocking popup */
22351         popup = (struct nk_window*)nk_create_window(ctx);
22352         popup->parent = win;
22353         win->popup.win = popup;
22354         win->popup.type = panel_type;
22355         nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
22356     } else {
22357         /* close the popup if user pressed outside or in the header */
22358         int pressed, in_body, in_header;
22359         pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
22360         in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22361         in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
22362         if (pressed && (!in_body || in_header))
22363             is_active = nk_false;
22364     }
22365     win->popup.header = header;
22366 
22367     if (!is_active) {
22368         /* remove read only mode from all parent panels */
22369         struct nk_panel *root = win->layout;
22370         while (root) {
22371             root->flags |= NK_WINDOW_REMOVE_ROM;
22372             root = root->parent;
22373         }
22374         return is_active;
22375     }
22376 
22377     popup->bounds = body;
22378     popup->parent = win;
22379     popup->layout = (struct nk_panel*)nk_create_panel(ctx);
22380     popup->flags = flags;
22381     popup->flags |= NK_WINDOW_BORDER;
22382     popup->flags |= NK_WINDOW_DYNAMIC;
22383     popup->seq = ctx->seq;
22384     win->popup.active = 1;
22385     NK_ASSERT(popup->layout);
22386 
22387     nk_start_popup(ctx, win);
22388     popup->buffer = win->buffer;
22389     nk_push_scissor(&popup->buffer, nk_null_rect);
22390     ctx->current = popup;
22391 
22392     nk_panel_begin(ctx, 0, panel_type);
22393     win->buffer = popup->buffer;
22394     popup->layout->parent = win->layout;
22395     popup->layout->offset_x = &popup->scrollbar.x;
22396     popup->layout->offset_y = &popup->scrollbar.y;
22397 
22398     /* set read only mode to all parent panels */
22399     {struct nk_panel *root;
22400     root = win->layout;
22401     while (root) {
22402         root->flags |= NK_WINDOW_ROM;
22403         root = root->parent;
22404     }}
22405     return is_active;
22406 }
22407 
22408 NK_API void
22409 nk_popup_close(struct nk_context *ctx)
22410 {
22411     struct nk_window *popup;
22412     NK_ASSERT(ctx);
22413     if (!ctx || !ctx->current) return;
22414 
22415     popup = ctx->current;
22416     NK_ASSERT(popup->parent);
22417     NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
22418     popup->flags |= NK_WINDOW_HIDDEN;
22419 }
22420 
22421 NK_API void
22422 nk_popup_end(struct nk_context *ctx)
22423 {
22424     struct nk_window *win;
22425     struct nk_window *popup;
22426 
22427     NK_ASSERT(ctx);
22428     NK_ASSERT(ctx->current);
22429     NK_ASSERT(ctx->current->layout);
22430     if (!ctx || !ctx->current || !ctx->current->layout)
22431         return;
22432 
22433     popup = ctx->current;
22434     if (!popup->parent) return;
22435     win = popup->parent;
22436     if (popup->flags & NK_WINDOW_HIDDEN) {
22437         struct nk_panel *root;
22438         root = win->layout;
22439         while (root) {
22440             root->flags |= NK_WINDOW_REMOVE_ROM;
22441             root = root->parent;
22442         }
22443         win->popup.active = 0;
22444     }
22445     nk_push_scissor(&popup->buffer, nk_null_rect);
22446     nk_end(ctx);
22447 
22448     win->buffer = popup->buffer;
22449     nk_finish_popup(ctx, win);
22450     ctx->current = win;
22451     nk_push_scissor(&win->buffer, win->layout->clip);
22452 }
22453 /* -------------------------------------------------------------
22454  *
22455  *                          TOOLTIP
22456  *
22457  * -------------------------------------------------------------- */
22458 NK_API int
22459 nk_tooltip_begin(struct nk_context *ctx, float width)
22460 {
22461     struct nk_window *win;
22462     const struct nk_input *in;
22463     struct nk_rect bounds;
22464     int ret;
22465 
22466     NK_ASSERT(ctx);
22467     NK_ASSERT(ctx->current);
22468     NK_ASSERT(ctx->current->layout);
22469     if (!ctx || !ctx->current || !ctx->current->layout)
22470         return 0;
22471 
22472     /* make sure that no nonblocking popup is currently active */
22473     win = ctx->current;
22474     in = &ctx->input;
22475     if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
22476         return 0;
22477 
22478     bounds.w = (float) nk_iceilf(width);
22479     bounds.h = (float) nk_iceilf(nk_null_rect.h);
22480     bounds.x = nk_ifloorf(in->mouse.pos.x + 1) - win->layout->clip.x;
22481     bounds.y = nk_ifloorf(in->mouse.pos.y + 1) - win->layout->clip.y;
22482 
22483     ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
22484         "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
22485     if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
22486     win->popup.type = NK_PANEL_TOOLTIP;
22487     ctx->current->layout->type = NK_PANEL_TOOLTIP;
22488     return ret;
22489 }
22490 
22491 NK_API void
22492 nk_tooltip_end(struct nk_context *ctx)
22493 {
22494     NK_ASSERT(ctx);
22495     NK_ASSERT(ctx->current);
22496     if (!ctx || !ctx->current) return;
22497     ctx->current->seq--;
22498     nk_popup_close(ctx);
22499     nk_popup_end(ctx);
22500 }
22501 
22502 NK_API void
22503 nk_tooltip(struct nk_context *ctx, const char *text)
22504 {
22505     const struct nk_style *style;
22506     struct nk_vec2 padding;
22507 
22508     int text_len;
22509     float text_width;
22510     float text_height;
22511 
22512     NK_ASSERT(ctx);
22513     NK_ASSERT(ctx->current);
22514     NK_ASSERT(ctx->current->layout);
22515     NK_ASSERT(text);
22516     if (!ctx || !ctx->current || !ctx->current->layout || !text)
22517         return;
22518 
22519     /* fetch configuration data */
22520     style = &ctx->style;
22521     padding = style->window.padding;
22522 
22523     /* calculate size of the text and tooltip */
22524     text_len = nk_strlen(text);
22525     text_width = style->font->width(style->font->userdata,
22526                     style->font->height, text, text_len);
22527     text_width += (4 * padding.x);
22528     text_height = (style->font->height + 2 * padding.y);
22529 
22530     /* execute tooltip and fill with text */
22531     if (nk_tooltip_begin(ctx, (float)text_width)) {
22532         nk_layout_row_dynamic(ctx, (float)text_height, 1);
22533         nk_text(ctx, text, text_len, NK_TEXT_LEFT);
22534         nk_tooltip_end(ctx);
22535     }
22536 }
22537 #ifdef NK_INCLUDE_STANDARD_VARARGS
22538 NK_API void
22539 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...)
22540 {
22541     char buf[256];
22542     va_list args;
22543     va_start(args, fmt);
22544     nk_strfmt(buf, NK_LEN(buf), fmt, args);
22545     va_end(args);
22546     nk_tooltip(ctx, buf);
22547 }
22548 #endif
22549 
22550 /* -------------------------------------------------------------
22551  *
22552  *                          CONTEXTUAL
22553  *
22554  * -------------------------------------------------------------- */
22555 NK_API int
22556 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
22557     struct nk_rect trigger_bounds)
22558 {
22559     struct nk_window *win;
22560     struct nk_window *popup;
22561     struct nk_rect body;
22562 
22563     NK_STORAGE const struct nk_rect null_rect = {0,0,0,0};
22564     int is_clicked = 0;
22565     int is_active = 0;
22566     int is_open = 0;
22567     int ret = 0;
22568 
22569     NK_ASSERT(ctx);
22570     NK_ASSERT(ctx->current);
22571     NK_ASSERT(ctx->current->layout);
22572     if (!ctx || !ctx->current || !ctx->current->layout)
22573         return 0;
22574 
22575     win = ctx->current;
22576     ++win->popup.con_count;
22577 
22578     /* check if currently active contextual is active */
22579     popup = win->popup.win;
22580     is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
22581     is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
22582     if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
22583         return 0;
22584     if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked))
22585         return 0;
22586 
22587     /* calculate contextual position on click */
22588     win->popup.active_con = win->popup.con_count;
22589     if (is_clicked) {
22590         body.x = ctx->input.mouse.pos.x;
22591         body.y = ctx->input.mouse.pos.y;
22592     } else {
22593         body.x = popup->bounds.x;
22594         body.y = popup->bounds.y;
22595     }
22596     body.w = size.x;
22597     body.h = size.y;
22598 
22599     /* start nonblocking contextual popup */
22600     ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
22601             null_rect, NK_PANEL_CONTEXTUAL);
22602     if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
22603     else {
22604         win->popup.active_con = 0;
22605         if (win->popup.win)
22606             win->popup.win->flags = 0;
22607     }
22608     return ret;
22609 }
22610 
22611 NK_API int
22612 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
22613     nk_flags alignment)
22614 {
22615     struct nk_window *win;
22616     const struct nk_input *in;
22617     const struct nk_style *style;
22618 
22619     struct nk_rect bounds;
22620     enum nk_widget_layout_states state;
22621 
22622     NK_ASSERT(ctx);
22623     NK_ASSERT(ctx->current);
22624     NK_ASSERT(ctx->current->layout);
22625     if (!ctx || !ctx->current || !ctx->current->layout)
22626         return 0;
22627 
22628     win = ctx->current;
22629     style = &ctx->style;
22630     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22631     if (!state) return nk_false;
22632 
22633     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22634     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
22635         text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
22636         nk_contextual_close(ctx);
22637         return nk_true;
22638     }
22639     return nk_false;
22640 }
22641 
22642 NK_API int nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
22643 {return nk_contextual_item_text(ctx, label, nk_strlen(label), align);}
22644 
22645 NK_API int
22646 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
22647     const char *text, int len, nk_flags align)
22648 {
22649     struct nk_window *win;
22650     const struct nk_input *in;
22651     const struct nk_style *style;
22652 
22653     struct nk_rect bounds;
22654     enum nk_widget_layout_states state;
22655 
22656     NK_ASSERT(ctx);
22657     NK_ASSERT(ctx->current);
22658     NK_ASSERT(ctx->current->layout);
22659     if (!ctx || !ctx->current || !ctx->current->layout)
22660         return 0;
22661 
22662     win = ctx->current;
22663     style = &ctx->style;
22664     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22665     if (!state) return nk_false;
22666 
22667     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22668     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
22669         img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
22670         nk_contextual_close(ctx);
22671         return nk_true;
22672     }
22673     return nk_false;
22674 }
22675 
22676 NK_API int nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
22677     const char *label, nk_flags align)
22678 {return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);}
22679 
22680 NK_API int
22681 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
22682     const char *text, int len, nk_flags align)
22683 {
22684     struct nk_window *win;
22685     const struct nk_input *in;
22686     const struct nk_style *style;
22687 
22688     struct nk_rect bounds;
22689     enum nk_widget_layout_states state;
22690 
22691     NK_ASSERT(ctx);
22692     NK_ASSERT(ctx->current);
22693     NK_ASSERT(ctx->current->layout);
22694     if (!ctx || !ctx->current || !ctx->current->layout)
22695         return 0;
22696 
22697     win = ctx->current;
22698     style = &ctx->style;
22699     state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22700     if (!state) return nk_false;
22701 
22702     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22703     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
22704         symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
22705         nk_contextual_close(ctx);
22706         return nk_true;
22707     }
22708     return nk_false;
22709 }
22710 
22711 NK_API int nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
22712     const char *text, nk_flags align)
22713 {return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);}
22714 
22715 NK_API void
22716 nk_contextual_close(struct nk_context *ctx)
22717 {
22718     NK_ASSERT(ctx);
22719     NK_ASSERT(ctx->current);
22720     NK_ASSERT(ctx->current->layout);
22721     if (!ctx || !ctx->current || !ctx->current->layout) return;
22722     nk_popup_close(ctx);
22723 }
22724 
22725 NK_API void
22726 nk_contextual_end(struct nk_context *ctx)
22727 {
22728     struct nk_window *popup;
22729     struct nk_panel *panel;
22730     NK_ASSERT(ctx);
22731     NK_ASSERT(ctx->current);
22732     if (!ctx || !ctx->current) return;
22733 
22734     popup = ctx->current;
22735     panel = popup->layout;
22736     NK_ASSERT(popup->parent);
22737     NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
22738     if (panel->flags & NK_WINDOW_DYNAMIC) {
22739         /* Close behavior
22740         This is a bit of a hack solution since we do not know before we end our popup
22741         how big it will be. We therefore do not directly know when a
22742         click outside the non-blocking popup must close it at that direct frame.
22743         Instead it will be closed in the next frame.*/
22744         struct nk_rect body = {0,0,0,0};
22745         if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
22746             struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
22747             body = panel->bounds;
22748             body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
22749             body.h = (panel->bounds.y + panel->bounds.h) - body.y;
22750         }
22751         {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
22752         int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22753         if (pressed && in_body)
22754             popup->flags |= NK_WINDOW_HIDDEN;
22755         }
22756     }
22757     if (popup->flags & NK_WINDOW_HIDDEN)
22758         popup->seq = 0;
22759     nk_popup_end(ctx);
22760     return;
22761 }
22762 /* -------------------------------------------------------------
22763  *
22764  *                          COMBO
22765  *
22766  * --------------------------------------------------------------*/
22767 NK_INTERN int
22768 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
22769     struct nk_vec2 size, int is_clicked, struct nk_rect header)
22770 {
22771     struct nk_window *popup;
22772     int is_open = 0;
22773     int is_active = 0;
22774     struct nk_rect body;
22775     nk_hash hash;
22776 
22777     NK_ASSERT(ctx);
22778     NK_ASSERT(ctx->current);
22779     NK_ASSERT(ctx->current->layout);
22780     if (!ctx || !ctx->current || !ctx->current->layout)
22781         return 0;
22782 
22783     popup = win->popup.win;
22784     body.x = header.x;
22785     body.w = size.x;
22786     body.y = header.y + header.h-ctx->style.window.combo_border;
22787     body.h = size.y;
22788 
22789     hash = win->popup.combo_count++;
22790     is_open = (popup) ? nk_true:nk_false;
22791     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
22792     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
22793         (!is_open && !is_active && !is_clicked)) return 0;
22794     if (!nk_nonblock_begin(ctx, 0, body,
22795         (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
22796 
22797     win->popup.type = NK_PANEL_COMBO;
22798     win->popup.name = hash;
22799     return 1;
22800 }
22801 
22802 NK_API int
22803 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
22804     struct nk_vec2 size)
22805 {
22806     const struct nk_input *in;
22807     struct nk_window *win;
22808     struct nk_style *style;
22809 
22810     enum nk_widget_layout_states s;
22811     int is_clicked = nk_false;
22812     struct nk_rect header;
22813     const struct nk_style_item *background;
22814     struct nk_text text;
22815 
22816     NK_ASSERT(ctx);
22817     NK_ASSERT(selected);
22818     NK_ASSERT(ctx->current);
22819     NK_ASSERT(ctx->current->layout);
22820     if (!ctx || !ctx->current || !ctx->current->layout || !selected)
22821         return 0;
22822 
22823     win = ctx->current;
22824     style = &ctx->style;
22825     s = nk_widget(&header, ctx);
22826     if (s == NK_WIDGET_INVALID)
22827         return 0;
22828 
22829     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22830     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22831         is_clicked = nk_true;
22832 
22833     /* draw combo box header background and border */
22834     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22835         background = &style->combo.active;
22836         text.text = style->combo.label_active;
22837     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22838         background = &style->combo.hover;
22839         text.text = style->combo.label_hover;
22840     } else {
22841         background = &style->combo.normal;
22842         text.text = style->combo.label_normal;
22843     }
22844     if (background->type == NK_STYLE_ITEM_IMAGE) {
22845         text.background = nk_rgba(0,0,0,0);
22846         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22847     } else {
22848         text.background = background->data.color;
22849         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22850         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22851     }
22852     {
22853         /* print currently selected text item */
22854         struct nk_rect label;
22855         struct nk_rect button;
22856         struct nk_rect content;
22857 
22858         enum nk_symbol_type sym;
22859         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22860             sym = style->combo.sym_hover;
22861         else if (is_clicked)
22862             sym = style->combo.sym_active;
22863         else sym = style->combo.sym_normal;
22864 
22865         /* calculate button */
22866         button.w = header.h - 2 * style->combo.button_padding.y;
22867         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22868         button.y = header.y + style->combo.button_padding.y;
22869         button.h = button.w;
22870 
22871         content.x = button.x + style->combo.button.padding.x;
22872         content.y = button.y + style->combo.button.padding.y;
22873         content.w = button.w - 2 * style->combo.button.padding.x;
22874         content.h = button.h - 2 * style->combo.button.padding.y;
22875 
22876         /* draw selected label */
22877         text.padding = nk_vec2(0,0);
22878         label.x = header.x + style->combo.content_padding.x;
22879         label.y = header.y + style->combo.content_padding.y;
22880         label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
22881         label.h = header.h - 2 * style->combo.content_padding.y;
22882         nk_widget_text(&win->buffer, label, selected, len, &text,
22883             NK_TEXT_LEFT, ctx->style.font);
22884 
22885         /* draw open/close button */
22886         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22887             &ctx->style.combo.button, sym, style->font);
22888     }
22889     return nk_combo_begin(ctx, win, size, is_clicked, header);
22890 }
22891 
22892 NK_API int nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
22893 {return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);}
22894 
22895 NK_API int
22896 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
22897 {
22898     struct nk_window *win;
22899     struct nk_style *style;
22900     const struct nk_input *in;
22901 
22902     struct nk_rect header;
22903     int is_clicked = nk_false;
22904     enum nk_widget_layout_states s;
22905     const struct nk_style_item *background;
22906 
22907     NK_ASSERT(ctx);
22908     NK_ASSERT(ctx->current);
22909     NK_ASSERT(ctx->current->layout);
22910     if (!ctx || !ctx->current || !ctx->current->layout)
22911         return 0;
22912 
22913     win = ctx->current;
22914     style = &ctx->style;
22915     s = nk_widget(&header, ctx);
22916     if (s == NK_WIDGET_INVALID)
22917         return 0;
22918 
22919     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22920     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22921         is_clicked = nk_true;
22922 
22923     /* draw combo box header background and border */
22924     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
22925         background = &style->combo.active;
22926     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22927         background = &style->combo.hover;
22928     else background = &style->combo.normal;
22929 
22930     if (background->type == NK_STYLE_ITEM_IMAGE) {
22931         nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
22932     } else {
22933         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22934         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22935     }
22936     {
22937         struct nk_rect content;
22938         struct nk_rect button;
22939         struct nk_rect bounds;
22940 
22941         enum nk_symbol_type sym;
22942         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22943             sym = style->combo.sym_hover;
22944         else if (is_clicked)
22945             sym = style->combo.sym_active;
22946         else sym = style->combo.sym_normal;
22947 
22948         /* calculate button */
22949         button.w = header.h - 2 * style->combo.button_padding.y;
22950         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22951         button.y = header.y + style->combo.button_padding.y;
22952         button.h = button.w;
22953 
22954         content.x = button.x + style->combo.button.padding.x;
22955         content.y = button.y + style->combo.button.padding.y;
22956         content.w = button.w - 2 * style->combo.button.padding.x;
22957         content.h = button.h - 2 * style->combo.button.padding.y;
22958 
22959         /* draw color */
22960         bounds.h = header.h - 4 * style->combo.content_padding.y;
22961         bounds.y = header.y + 2 * style->combo.content_padding.y;
22962         bounds.x = header.x + 2 * style->combo.content_padding.x;
22963         bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
22964         nk_fill_rect(&win->buffer, bounds, 0, color);
22965 
22966         /* draw open/close button */
22967         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22968             &ctx->style.combo.button, sym, style->font);
22969     }
22970     return nk_combo_begin(ctx, win, size, is_clicked, header);
22971 }
22972 
22973 NK_API int
22974 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
22975 {
22976     struct nk_window *win;
22977     struct nk_style *style;
22978     const struct nk_input *in;
22979 
22980     struct nk_rect header;
22981     int is_clicked = nk_false;
22982     enum nk_widget_layout_states s;
22983     const struct nk_style_item *background;
22984     struct nk_color sym_background;
22985     struct nk_color symbol_color;
22986 
22987     NK_ASSERT(ctx);
22988     NK_ASSERT(ctx->current);
22989     NK_ASSERT(ctx->current->layout);
22990     if (!ctx || !ctx->current || !ctx->current->layout)
22991         return 0;
22992 
22993     win = ctx->current;
22994     style = &ctx->style;
22995     s = nk_widget(&header, ctx);
22996     if (s == NK_WIDGET_INVALID)
22997         return 0;
22998 
22999     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23000     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23001         is_clicked = nk_true;
23002 
23003     /* draw combo box header background and border */
23004     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
23005         background = &style->combo.active;
23006         symbol_color = style->combo.symbol_active;
23007     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
23008         background = &style->combo.hover;
23009         symbol_color = style->combo.symbol_hover;
23010     } else {
23011         background = &style->combo.normal;
23012         symbol_color = style->combo.symbol_hover;
23013     }
23014 
23015     if (background->type == NK_STYLE_ITEM_IMAGE) {
23016         sym_background = nk_rgba(0,0,0,0);
23017         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23018     } else {
23019         sym_background = background->data.color;
23020         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23021         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23022     }
23023     {
23024         struct nk_rect bounds = {0,0,0,0};
23025         struct nk_rect content;
23026         struct nk_rect button;
23027 
23028         enum nk_symbol_type sym;
23029         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23030             sym = style->combo.sym_hover;
23031         else if (is_clicked)
23032             sym = style->combo.sym_active;
23033         else sym = style->combo.sym_normal;
23034 
23035         /* calculate button */
23036         button.w = header.h - 2 * style->combo.button_padding.y;
23037         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
23038         button.y = header.y + style->combo.button_padding.y;
23039         button.h = button.w;
23040 
23041         content.x = button.x + style->combo.button.padding.x;
23042         content.y = button.y + style->combo.button.padding.y;
23043         content.w = button.w - 2 * style->combo.button.padding.x;
23044         content.h = button.h - 2 * style->combo.button.padding.y;
23045 
23046         /* draw symbol */
23047         bounds.h = header.h - 2 * style->combo.content_padding.y;
23048         bounds.y = header.y + style->combo.content_padding.y;
23049         bounds.x = header.x + style->combo.content_padding.x;
23050         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
23051         nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
23052             1.0f, style->font);
23053 
23054         /* draw open/close button */
23055         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
23056             &ctx->style.combo.button, sym, style->font);
23057     }
23058     return nk_combo_begin(ctx, win, size, is_clicked, header);
23059 }
23060 
23061 NK_API int
23062 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
23063     enum nk_symbol_type symbol, struct nk_vec2 size)
23064 {
23065     struct nk_window *win;
23066     struct nk_style *style;
23067     struct nk_input *in;
23068 
23069     struct nk_rect header;
23070     int is_clicked = nk_false;
23071     enum nk_widget_layout_states s;
23072     const struct nk_style_item *background;
23073     struct nk_color symbol_color;
23074     struct nk_text text;
23075 
23076     NK_ASSERT(ctx);
23077     NK_ASSERT(ctx->current);
23078     NK_ASSERT(ctx->current->layout);
23079     if (!ctx || !ctx->current || !ctx->current->layout)
23080         return 0;
23081 
23082     win = ctx->current;
23083     style = &ctx->style;
23084     s = nk_widget(&header, ctx);
23085     if (!s) return 0;
23086 
23087     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23088     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23089         is_clicked = nk_true;
23090 
23091     /* draw combo box header background and border */
23092     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
23093         background = &style->combo.active;
23094         symbol_color = style->combo.symbol_active;
23095         text.text = style->combo.label_active;
23096     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
23097         background = &style->combo.hover;
23098         symbol_color = style->combo.symbol_hover;
23099         text.text = style->combo.label_hover;
23100     } else {
23101         background = &style->combo.normal;
23102         symbol_color = style->combo.symbol_normal;
23103         text.text = style->combo.label_normal;
23104     }
23105     if (background->type == NK_STYLE_ITEM_IMAGE) {
23106         text.background = nk_rgba(0,0,0,0);
23107         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23108     } else {
23109         text.background = background->data.color;
23110         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23111         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23112     }
23113     {
23114         struct nk_rect content;
23115         struct nk_rect button;
23116         struct nk_rect label;
23117         struct nk_rect image;
23118 
23119         enum nk_symbol_type sym;
23120         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23121             sym = style->combo.sym_hover;
23122         else if (is_clicked)
23123             sym = style->combo.sym_active;
23124         else sym = style->combo.sym_normal;
23125 
23126         /* calculate button */
23127         button.w = header.h - 2 * style->combo.button_padding.y;
23128         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
23129         button.y = header.y + style->combo.button_padding.y;
23130         button.h = button.w;
23131 
23132         content.x = button.x + style->combo.button.padding.x;
23133         content.y = button.y + style->combo.button.padding.y;
23134         content.w = button.w - 2 * style->combo.button.padding.x;
23135         content.h = button.h - 2 * style->combo.button.padding.y;
23136         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
23137             &ctx->style.combo.button, sym, style->font);
23138 
23139         /* draw symbol */
23140         image.x = header.x + style->combo.content_padding.x;
23141         image.y = header.y + style->combo.content_padding.y;
23142         image.h = header.h - 2 * style->combo.content_padding.y;
23143         image.w = image.h;
23144         nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
23145             1.0f, style->font);
23146 
23147         /* draw label */
23148         text.padding = nk_vec2(0,0);
23149         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
23150         label.y = header.y + style->combo.content_padding.y;
23151         label.w = (button.x - style->combo.content_padding.x) - label.x;
23152         label.h = header.h - 2 * style->combo.content_padding.y;
23153         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
23154     }
23155     return nk_combo_begin(ctx, win, size, is_clicked, header);
23156 }
23157 
23158 NK_API int
23159 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
23160 {
23161     struct nk_window *win;
23162     struct nk_style *style;
23163     const struct nk_input *in;
23164 
23165     struct nk_rect header;
23166     int is_clicked = nk_false;
23167     enum nk_widget_layout_states s;
23168     const struct nk_style_item *background;
23169 
23170     NK_ASSERT(ctx);
23171     NK_ASSERT(ctx->current);
23172     NK_ASSERT(ctx->current->layout);
23173     if (!ctx || !ctx->current || !ctx->current->layout)
23174         return 0;
23175 
23176     win = ctx->current;
23177     style = &ctx->style;
23178     s = nk_widget(&header, ctx);
23179     if (s == NK_WIDGET_INVALID)
23180         return 0;
23181 
23182     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23183     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23184         is_clicked = nk_true;
23185 
23186     /* draw combo box header background and border */
23187     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
23188         background = &style->combo.active;
23189     else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23190         background = &style->combo.hover;
23191     else background = &style->combo.normal;
23192 
23193     if (background->type == NK_STYLE_ITEM_IMAGE) {
23194         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23195     } else {
23196         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23197         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23198     }
23199     {
23200         struct nk_rect bounds = {0,0,0,0};
23201         struct nk_rect content;
23202         struct nk_rect button;
23203 
23204         enum nk_symbol_type sym;
23205         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23206             sym = style->combo.sym_hover;
23207         else if (is_clicked)
23208             sym = style->combo.sym_active;
23209         else sym = style->combo.sym_normal;
23210 
23211         /* calculate button */
23212         button.w = header.h - 2 * style->combo.button_padding.y;
23213         button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
23214         button.y = header.y + style->combo.button_padding.y;
23215         button.h = button.w;
23216 
23217         content.x = button.x + style->combo.button.padding.x;
23218         content.y = button.y + style->combo.button.padding.y;
23219         content.w = button.w - 2 * style->combo.button.padding.x;
23220         content.h = button.h - 2 * style->combo.button.padding.y;
23221 
23222         /* draw image */
23223         bounds.h = header.h - 2 * style->combo.content_padding.y;
23224         bounds.y = header.y + style->combo.content_padding.y;
23225         bounds.x = header.x + style->combo.content_padding.x;
23226         bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
23227         nk_draw_image(&win->buffer, bounds, &img, nk_white);
23228 
23229         /* draw open/close button */
23230         nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
23231             &ctx->style.combo.button, sym, style->font);
23232     }
23233     return nk_combo_begin(ctx, win, size, is_clicked, header);
23234 }
23235 
23236 NK_API int
23237 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
23238     struct nk_image img, struct nk_vec2 size)
23239 {
23240     struct nk_window *win;
23241     struct nk_style *style;
23242     struct nk_input *in;
23243 
23244     struct nk_rect header;
23245     int is_clicked = nk_false;
23246     enum nk_widget_layout_states s;
23247     const struct nk_style_item *background;
23248     struct nk_text text;
23249 
23250     NK_ASSERT(ctx);
23251     NK_ASSERT(ctx->current);
23252     NK_ASSERT(ctx->current->layout);
23253     if (!ctx || !ctx->current || !ctx->current->layout)
23254         return 0;
23255 
23256     win = ctx->current;
23257     style = &ctx->style;
23258     s = nk_widget(&header, ctx);
23259     if (!s) return 0;
23260 
23261     in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23262     if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23263         is_clicked = nk_true;
23264 
23265     /* draw combo box header background and border */
23266     if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
23267         background = &style->combo.active;
23268         text.text = style->combo.label_active;
23269     } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
23270         background = &style->combo.hover;
23271         text.text = style->combo.label_hover;
23272     } else {
23273         background = &style->combo.normal;
23274         text.text = style->combo.label_normal;
23275     }
23276     if (background->type == NK_STYLE_ITEM_IMAGE) {
23277         text.background = nk_rgba(0,0,0,0);
23278         nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23279     } else {
23280         text.background = background->data.color;
23281         nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23282         nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23283     }
23284     {
23285         struct nk_rect content;
23286         struct nk_rect button;
23287         struct nk_rect label;
23288         struct nk_rect image;
23289 
23290         enum nk_symbol_type sym;
23291         if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23292             sym = style->combo.sym_hover;
23293         else if (is_clicked)
23294             sym = style->combo.sym_active;
23295         else sym = style->combo.sym_normal;
23296 
23297         /* calculate button */
23298         button.w = header.h - 2 * style->combo.button_padding.y;
23299         button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
23300         button.y = header.y + style->combo.button_padding.y;
23301         button.h = button.w;
23302 
23303         content.x = button.x + style->combo.button.padding.x;
23304         content.y = button.y + style->combo.button.padding.y;
23305         content.w = button.w - 2 * style->combo.button.padding.x;
23306         content.h = button.h - 2 * style->combo.button.padding.y;
23307         nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
23308             &ctx->style.combo.button, sym, style->font);
23309 
23310         /* draw image */
23311         image.x = header.x + style->combo.content_padding.x;
23312         image.y = header.y + style->combo.content_padding.y;
23313         image.h = header.h - 2 * style->combo.content_padding.y;
23314         image.w = image.h;
23315         nk_draw_image(&win->buffer, image, &img, nk_white);
23316 
23317         /* draw label */
23318         text.padding = nk_vec2(0,0);
23319         label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
23320         label.y = header.y + style->combo.content_padding.y;
23321         label.w = (button.x - style->combo.content_padding.x) - label.x;
23322         label.h = header.h - 2 * style->combo.content_padding.y;
23323         nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
23324     }
23325     return nk_combo_begin(ctx, win, size, is_clicked, header);
23326 }
23327 
23328 NK_API int nk_combo_begin_symbol_label(struct nk_context *ctx,
23329     const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
23330 {return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);}
23331 
23332 NK_API int nk_combo_begin_image_label(struct nk_context *ctx,
23333     const char *selected, struct nk_image img, struct nk_vec2 size)
23334 {return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);}
23335 
23336 NK_API int nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
23337 {return nk_contextual_item_text(ctx, text, len, align);}
23338 
23339 NK_API int nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
23340 {return nk_contextual_item_label(ctx, label, align);}
23341 
23342 NK_API int nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
23343     int len, nk_flags alignment)
23344 {return nk_contextual_item_image_text(ctx, img, text, len, alignment);}
23345 
23346 NK_API int nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
23347     const char *text, nk_flags alignment)
23348 {return nk_contextual_item_image_label(ctx, img, text, alignment);}
23349 
23350 NK_API int nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
23351     const char *text, int len, nk_flags alignment)
23352 {return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);}
23353 
23354 NK_API int nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
23355     const char *label, nk_flags alignment)
23356 {return nk_contextual_item_symbol_label(ctx, sym, label, alignment);}
23357 
23358 NK_API void nk_combo_end(struct nk_context *ctx)
23359 {nk_contextual_end(ctx);}
23360 
23361 NK_API void nk_combo_close(struct nk_context *ctx)
23362 {nk_contextual_close(ctx);}
23363 
23364 NK_API int
23365 nk_combo(struct nk_context *ctx, const char **items, int count,
23366     int selected, int item_height, struct nk_vec2 size)
23367 {
23368     int i = 0;
23369     int max_height;
23370     struct nk_vec2 item_spacing;
23371     struct nk_vec2 window_padding;
23372 
23373     NK_ASSERT(ctx);
23374     NK_ASSERT(items);
23375     NK_ASSERT(ctx->current);
23376     if (!ctx || !items ||!count)
23377         return selected;
23378 
23379     item_spacing = ctx->style.window.spacing;
23380     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23381     max_height = count * item_height + count * (int)item_spacing.y;
23382     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23383     size.y = NK_MIN(size.y, (float)max_height);
23384     if (nk_combo_begin_label(ctx, items[selected], size)) {
23385         nk_layout_row_dynamic(ctx, (float)item_height, 1);
23386         for (i = 0; i < count; ++i) {
23387             if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
23388                 selected = i;
23389         }
23390         nk_combo_end(ctx);
23391     }
23392     return selected;
23393 }
23394 
23395 NK_API int
23396 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23397     int separator, int selected, int count, int item_height, struct nk_vec2 size)
23398 {
23399     int i;
23400     int max_height;
23401     struct nk_vec2 item_spacing;
23402     struct nk_vec2 window_padding;
23403     const char *current_item;
23404     const char *iter;
23405     int length = 0;
23406 
23407     NK_ASSERT(ctx);
23408     NK_ASSERT(items_separated_by_separator);
23409     if (!ctx || !items_separated_by_separator)
23410         return selected;
23411 
23412     /* calculate popup window */
23413     item_spacing = ctx->style.window.spacing;
23414     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23415     max_height = count * item_height + count * (int)item_spacing.y;
23416     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23417     size.y = NK_MIN(size.y, (float)max_height);
23418 
23419     /* find selected item */
23420     current_item = items_separated_by_separator;
23421     for (i = 0; i < count; ++i) {
23422         iter = current_item;
23423         while (*iter && *iter != separator) iter++;
23424         length = (int)(iter - current_item);
23425         if (i == selected) break;
23426         current_item = iter + 1;
23427     }
23428 
23429     if (nk_combo_begin_text(ctx, current_item, length, size)) {
23430         current_item = items_separated_by_separator;
23431         nk_layout_row_dynamic(ctx, (float)item_height, 1);
23432         for (i = 0; i < count; ++i) {
23433             iter = current_item;
23434             while (*iter && *iter != separator) iter++;
23435             length = (int)(iter - current_item);
23436             if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
23437                 selected = i;
23438             current_item = current_item + length + 1;
23439         }
23440         nk_combo_end(ctx);
23441     }
23442     return selected;
23443 }
23444 
23445 NK_API int
23446 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23447     int selected, int count, int item_height, struct nk_vec2 size)
23448 {return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);}
23449 
23450 NK_API int
23451 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
23452     void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
23453 {
23454     int i;
23455     int max_height;
23456     struct nk_vec2 item_spacing;
23457     struct nk_vec2 window_padding;
23458     const char *item;
23459 
23460     NK_ASSERT(ctx);
23461     NK_ASSERT(item_getter);
23462     if (!ctx || !item_getter)
23463         return selected;
23464 
23465     /* calculate popup window */
23466     item_spacing = ctx->style.window.spacing;
23467     window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23468     max_height = count * item_height + count * (int)item_spacing.y;
23469     max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23470     size.y = NK_MIN(size.y, (float)max_height);
23471 
23472     item_getter(userdata, selected, &item);
23473     if (nk_combo_begin_label(ctx, item, size)) {
23474         nk_layout_row_dynamic(ctx, (float)item_height, 1);
23475         for (i = 0; i < count; ++i) {
23476             item_getter(userdata, i, &item);
23477             if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
23478                 selected = i;
23479         }
23480         nk_combo_end(ctx);
23481     }
23482     return selected;
23483 }
23484 
23485 NK_API void nk_combobox(struct nk_context *ctx, const char **items, int count,
23486     int *selected, int item_height, struct nk_vec2 size)
23487 {*selected = nk_combo(ctx, items, count, *selected, item_height, size);}
23488 
23489 NK_API void nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23490     int *selected, int count, int item_height, struct nk_vec2 size)
23491 {*selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);}
23492 
23493 NK_API void nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23494     int separator,int *selected, int count, int item_height, struct nk_vec2 size)
23495 {*selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
23496     *selected, count, item_height, size);}
23497 
23498 NK_API void nk_combobox_callback(struct nk_context *ctx,
23499     void(*item_getter)(void* data, int id, const char **out_text),
23500     void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
23501 {*selected = nk_combo_callback(ctx, item_getter, userdata,  *selected, count, item_height, size);}
23502 
23503 /*
23504  * -------------------------------------------------------------
23505  *
23506  *                          MENU
23507  *
23508  * --------------------------------------------------------------
23509  */
23510 NK_INTERN int
23511 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
23512     const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
23513 {
23514     int is_open = 0;
23515     int is_active = 0;
23516     struct nk_rect body;
23517     struct nk_window *popup;
23518     nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
23519 
23520     NK_ASSERT(ctx);
23521     NK_ASSERT(ctx->current);
23522     NK_ASSERT(ctx->current->layout);
23523     if (!ctx || !ctx->current || !ctx->current->layout)
23524         return 0;
23525 
23526     body.x = header.x;
23527     body.w = size.x;
23528     body.y = header.y + header.h;
23529     body.h = size.y;
23530 
23531     popup = win->popup.win;
23532     is_open = popup ? nk_true : nk_false;
23533     is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
23534     if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
23535         (!is_open && !is_active && !is_clicked)) return 0;
23536     if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
23537         return 0;
23538 
23539     win->popup.type = NK_PANEL_MENU;
23540     win->popup.name = hash;
23541     return 1;
23542 }
23543 
23544 NK_API int
23545 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
23546     nk_flags align, struct nk_vec2 size)
23547 {
23548     struct nk_window *win;
23549     const struct nk_input *in;
23550     struct nk_rect header;
23551     int is_clicked = nk_false;
23552     nk_flags state;
23553 
23554     NK_ASSERT(ctx);
23555     NK_ASSERT(ctx->current);
23556     NK_ASSERT(ctx->current->layout);
23557     if (!ctx || !ctx->current || !ctx->current->layout)
23558         return 0;
23559 
23560     win = ctx->current;
23561     state = nk_widget(&header, ctx);
23562     if (!state) return 0;
23563     in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23564     if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
23565         title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23566         is_clicked = nk_true;
23567     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23568 }
23569 
23570 NK_API int nk_menu_begin_label(struct nk_context *ctx,
23571     const char *text, nk_flags align, struct nk_vec2 size)
23572 {return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);}
23573 
23574 NK_API int
23575 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
23576     struct nk_vec2 size)
23577 {
23578     struct nk_window *win;
23579     struct nk_rect header;
23580     const struct nk_input *in;
23581     int is_clicked = nk_false;
23582     nk_flags state;
23583 
23584     NK_ASSERT(ctx);
23585     NK_ASSERT(ctx->current);
23586     NK_ASSERT(ctx->current->layout);
23587     if (!ctx || !ctx->current || !ctx->current->layout)
23588         return 0;
23589 
23590     win = ctx->current;
23591     state = nk_widget(&header, ctx);
23592     if (!state) return 0;
23593     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23594     if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
23595         img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
23596         is_clicked = nk_true;
23597     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23598 }
23599 
23600 NK_API int
23601 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
23602     enum nk_symbol_type sym, struct nk_vec2 size)
23603 {
23604     struct nk_window *win;
23605     const struct nk_input *in;
23606     struct nk_rect header;
23607     int is_clicked = nk_false;
23608     nk_flags state;
23609 
23610     NK_ASSERT(ctx);
23611     NK_ASSERT(ctx->current);
23612     NK_ASSERT(ctx->current->layout);
23613     if (!ctx || !ctx->current || !ctx->current->layout)
23614         return 0;
23615 
23616     win = ctx->current;
23617     state = nk_widget(&header, ctx);
23618     if (!state) return 0;
23619     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23620     if (nk_do_button_symbol(&ctx->last_widget_state,  &win->buffer, header,
23621         sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23622         is_clicked = nk_true;
23623     return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23624 }
23625 
23626 NK_API int
23627 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
23628     nk_flags align, struct nk_image img, struct nk_vec2 size)
23629 {
23630     struct nk_window *win;
23631     struct nk_rect header;
23632     const struct nk_input *in;
23633     int is_clicked = nk_false;
23634     nk_flags state;
23635 
23636     NK_ASSERT(ctx);
23637     NK_ASSERT(ctx->current);
23638     NK_ASSERT(ctx->current->layout);
23639     if (!ctx || !ctx->current || !ctx->current->layout)
23640         return 0;
23641 
23642     win = ctx->current;
23643     state = nk_widget(&header, ctx);
23644     if (!state) return 0;
23645     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23646     if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
23647         header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23648         ctx->style.font, in))
23649         is_clicked = nk_true;
23650     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23651 }
23652 
23653 NK_API int nk_menu_begin_image_label(struct nk_context *ctx,
23654     const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
23655 {return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);}
23656 
23657 NK_API int
23658 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
23659     nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
23660 {
23661     struct nk_window *win;
23662     struct nk_rect header;
23663     const struct nk_input *in;
23664     int is_clicked = nk_false;
23665     nk_flags state;
23666 
23667     NK_ASSERT(ctx);
23668     NK_ASSERT(ctx->current);
23669     NK_ASSERT(ctx->current->layout);
23670     if (!ctx || !ctx->current || !ctx->current->layout)
23671         return 0;
23672 
23673     win = ctx->current;
23674     state = nk_widget(&header, ctx);
23675     if (!state) return 0;
23676 
23677     in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23678     if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
23679         header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23680         ctx->style.font, in)) is_clicked = nk_true;
23681     return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23682 }
23683 
23684 NK_API int nk_menu_begin_symbol_label(struct nk_context *ctx,
23685     const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
23686 {return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);}
23687 
23688 NK_API int nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
23689 {return nk_contextual_item_text(ctx, title, len, align);}
23690 
23691 NK_API int nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
23692 {return nk_contextual_item_label(ctx, label, align);}
23693 
23694 NK_API int nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
23695     const char *label, nk_flags align)
23696 {return nk_contextual_item_image_label(ctx, img, label, align);}
23697 
23698 NK_API int nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
23699     const char *text, int len, nk_flags align)
23700 {return nk_contextual_item_image_text(ctx, img, text, len, align);}
23701 
23702 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
23703     const char *text, int len, nk_flags align)
23704 {return nk_contextual_item_symbol_text(ctx, sym, text, len, align);}
23705 
23706 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
23707     const char *label, nk_flags align)
23708 {return nk_contextual_item_symbol_label(ctx, sym, label, align);}
23709 
23710 NK_API void nk_menu_close(struct nk_context *ctx)
23711 {nk_contextual_close(ctx);}
23712 
23713 NK_API void
23714 nk_menu_end(struct nk_context *ctx)
23715 {nk_contextual_end(ctx);}
23716 
23717 #endif /* NK_IMPLEMENTATION */
23718