Nuklear
This is a minimal-state, immediate-mode graphical user interface toolkit written in ANSI C and licensed under public domain. It was designed as a simple embeddable user interface for application and does not have any dependencies, a default render backend or OS window/input handling but instead provides a highly modular, library-based approach, with simple input state for input and draw commands describing primitive shapes as output. So instead of providing a layered library that tries to abstract over a number of platform and render backends, it focuses only on the actual UI.
nuklear.h
Go to the documentation of this file.
1 /*
2 # Nuklear
3 ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif)
4 
5 ## Contents
6 1. About section
7 2. Highlights section
8 3. Features section
9 4. Usage section
10  1. Flags section
11  2. Constants section
12  3. Dependencies section
13 5. Example section
14 6. API section
15  1. Context section
16  2. Input section
17  3. Drawing section
18  4. Window section
19  5. Layouting section
20  6. Groups section
21  7. Tree section
22  8. Properties section
23 7. License section
24 8. Changelog section
25 9. Gallery section
26 10. Credits section
27 
28 ## About
29 This is a minimal state immediate mode graphical user interface toolkit
30 written in ANSI C and licensed under public domain. It was designed as a simple
31 embeddable user interface for application and does not have any dependencies,
32 a default renderbackend or OS window and input handling but instead provides a very modular
33 library approach by using simple input state for input and draw
34 commands describing primitive shapes as output. So instead of providing a
35 layered library that tries to abstract over a number of platform and
36 render backends it only focuses on the actual UI.
37 
38 ## Highlights
39 - Graphical user interface toolkit
40 - Single header library
41 - Written in C89 (a.k.a. ANSI C or ISO C90)
42 - Small codebase (~18kLOC)
43 - Focus on portability, efficiency and simplicity
44 - No dependencies (not even the standard library if not wanted)
45 - Fully skinnable and customizable
46 - Low memory footprint with total memory control if needed or wanted
47 - UTF-8 support
48 - No global or hidden state
49 - Customizable library modules (you can compile and use only what you need)
50 - Optional font baker and vertex buffer output
51 - [Code available on github](https://github.com/Immediate-Mode-UI/Nuklear/)
52 
53 ## Features
54 - Absolutely no platform dependent code
55 - Memory management control ranging from/to
56  - Ease of use by allocating everything from standard library
57  - Control every byte of memory inside the library
58 - Font handling control ranging from/to
59  - Use your own font implementation for everything
60  - Use this libraries internal font baking and handling API
61 - Drawing output control ranging from/to
62  - Simple shapes for more high level APIs which already have drawing capabilities
63  - Hardware accessible anti-aliased vertex buffer output
64 - Customizable colors and properties ranging from/to
65  - Simple changes to color by filling a simple color table
66  - Complete control with ability to use skinning to decorate widgets
67 - Bendable UI library with widget ranging from/to
68  - Basic widgets like buttons, checkboxes, slider, ...
69  - Advanced widget like abstract comboboxes, contextual menus,...
70 - Compile time configuration to only compile what you need
71  - Subset which can be used if you do not want to link or use the standard library
72 - Can be easily modified to only update on user input instead of frame updates
73 
74 ## Usage
75 This library is self contained in one single header file and can be used either
76 in header only mode or in implementation mode. The header only mode is used
77 by default when included and allows including this header in other headers
78 and does not contain the actual implementation. <br /><br />
79 
80 The implementation mode requires to define the preprocessor macro
81 NK_IMPLEMENTATION in *one* .c/.cpp file before #including this file, e.g.:
82 
83 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C
84  #define NK_IMPLEMENTATION
85  #include "nuklear.h"
86 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
87 
88 Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
89 below in header and implementation mode if you want to use additional functionality
90 or need more control over the library.
91 
92 !!! WARNING
93  Every time nuklear is included define the same compiler flags. This very important not doing so could lead to compiler errors or even worse stack corruptions.
94 
95 ### Flags
96 Flag | Description
97 --------------------------------|------------------------------------------
98 NK_PRIVATE | If defined declares all functions as static, so they can only be accessed inside the file that contains the implementation
99 NK_INCLUDE_FIXED_TYPES | If defined it will include header `<stdint.h>` for fixed sized types otherwise nuklear tries to select the correct type. If that fails it will throw a compiler error and you have to select the correct types yourself.
100 NK_INCLUDE_DEFAULT_ALLOCATOR | If defined it will include header `<stdlib.h>` and provide additional functions to use this library without caring for memory allocation control and therefore ease memory management.
101 NK_INCLUDE_STANDARD_IO | If defined it will include header `<stdio.h>` and provide additional functions depending on file loading.
102 NK_INCLUDE_STANDARD_VARARGS | If defined it will include header <stdarg.h> and provide additional functions depending on file loading.
103 NK_INCLUDE_STANDARD_BOOL | If defined it will include header `<stdbool.h>` for nk_bool otherwise nuklear defines nk_bool as int.
104 NK_INCLUDE_VERTEX_BUFFER_OUTPUT | Defining this adds a vertex draw command list backend to this library, which allows you to convert queue commands into vertex draw commands. This is mainly if you need a hardware accessible format for OpenGL, DirectX, Vulkan, Metal,...
105 NK_INCLUDE_FONT_BAKING | Defining this adds `stb_truetype` and `stb_rect_pack` implementation to this library and provides font baking and rendering. If you already have font handling or do not want to use this font handler you don't have to define it.
106 NK_INCLUDE_DEFAULT_FONT | Defining this adds the default font: ProggyClean.ttf into this library which can be loaded into a font atlas and allows using this library without having a truetype font
107 NK_INCLUDE_COMMAND_USERDATA | Defining this adds a userdata pointer into each command. Can be useful for example if you want to provide custom shaders depending on the used widget. Can be combined with the style structures.
108 NK_BUTTON_TRIGGER_ON_RELEASE | Different platforms require button clicks occurring either on buttons being pressed (up to down) or released (down to up). By default this library will react on buttons being pressed, but if you define this it will only trigger if a button is released.
109 NK_ZERO_COMMAND_MEMORY | Defining this will zero out memory for each drawing command added to a drawing queue (inside nk_command_buffer_push). Zeroing command memory is very useful for fast checking (using memcmp) if command buffers are equal and avoid drawing frames when nothing on screen has changed since previous frame.
110 NK_UINT_DRAW_INDEX | Defining this will set the size of vertex index elements when using NK_VERTEX_BUFFER_OUTPUT to 32bit instead of the default of 16bit
111 NK_KEYSTATE_BASED_INPUT | Define this if your backend uses key state for each frame rather than key press/release events
112 
113 !!! WARNING
114  The following flags will pull in the standard C library:
115  - NK_INCLUDE_DEFAULT_ALLOCATOR
116  - NK_INCLUDE_STANDARD_IO
117  - NK_INCLUDE_STANDARD_VARARGS
118 
119 !!! WARNING
120  The following flags if defined need to be defined for both header and implementation:
121  - NK_INCLUDE_FIXED_TYPES
122  - NK_INCLUDE_DEFAULT_ALLOCATOR
123  - NK_INCLUDE_STANDARD_VARARGS
124  - NK_INCLUDE_STANDARD_BOOL
125  - NK_INCLUDE_VERTEX_BUFFER_OUTPUT
126  - NK_INCLUDE_FONT_BAKING
127  - NK_INCLUDE_DEFAULT_FONT
128  - NK_INCLUDE_STANDARD_VARARGS
129  - NK_INCLUDE_COMMAND_USERDATA
130  - NK_UINT_DRAW_INDEX
131 
132 ### Constants
133 Define | Description
134 --------------------------------|---------------------------------------
135 NK_BUFFER_DEFAULT_INITIAL_SIZE | Initial buffer size allocated by all buffers while using the default allocator functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't want to allocate the default 4k memory then redefine it.
136 NK_MAX_NUMBER_BUFFER | Maximum buffer size for the conversion buffer between float and string Under normal circumstances this should be more than sufficient.
137 NK_INPUT_MAX | Defines the max number of bytes which can be added as text input in one frame. Under normal circumstances this should be more than sufficient.
138 
139 !!! WARNING
140  The following constants if defined need to be defined for both header and implementation:
141  - NK_MAX_NUMBER_BUFFER
142  - NK_BUFFER_DEFAULT_INITIAL_SIZE
143  - NK_INPUT_MAX
144 
145 ### Dependencies
146 Function | Description
147 ------------|---------------------------------------------------------------
148 NK_ASSERT | If you don't define this, nuklear will use <assert.h> with assert().
149 NK_MEMSET | You can define this to 'memset' or your own memset implementation replacement. If not nuklear will use its own version.
150 NK_MEMCPY | You can define this to 'memcpy' or your own memcpy implementation replacement. If not nuklear will use its own version.
151 NK_INV_SQRT | You can define this to your own inverse sqrt implementation replacement. If not nuklear will use its own slow and not highly accurate version.
152 NK_SIN | You can define this to 'sinf' or your own sine implementation replacement. If not nuklear will use its own approximation implementation.
153 NK_COS | You can define this to 'cosf' or your own cosine implementation replacement. If not nuklear will use its own approximation implementation.
154 NK_STRTOD | You can define this to `strtod` or your own string to double conversion implementation replacement. If not defined nuklear will use its own imprecise and possibly unsafe version (does not handle nan or infinity!).
155 NK_DTOA | You can define this to `dtoa` or your own double to string conversion implementation replacement. If not defined nuklear will use its own imprecise and possibly unsafe version (does not handle nan or infinity!).
156 NK_VSNPRINTF| If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO` and want to be safe define this to `vsnprintf` on compilers supporting later versions of C or C++. By default nuklear will check for your stdlib version in C as well as compiler version in C++. if `vsnprintf` is available it will define it to `vsnprintf` directly. If not defined and if you have older versions of C or C++ it will be defined to `vsprintf` which is unsafe.
157 
158 !!! WARNING
159  The following dependencies will pull in the standard C library if not redefined:
160  - NK_ASSERT
161 
162 !!! WARNING
163  The following dependencies if defined need to be defined for both header and implementation:
164  - NK_ASSERT
165 
166 !!! WARNING
167  The following dependencies if defined need to be defined only for the implementation part:
168  - NK_MEMSET
169  - NK_MEMCPY
170  - NK_SQRT
171  - NK_SIN
172  - NK_COS
173  - NK_STRTOD
174  - NK_DTOA
175  - NK_VSNPRINTF
176 
177 ## Example
178 
179 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
180 // init gui state
181 enum {EASY, HARD};
182 static int op = EASY;
183 static float value = 0.6f;
184 static int i = 20;
185 struct nk_context ctx;
186 
187 nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);
188 if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220),
189  NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
190  // fixed widget pixel width
191  nk_layout_row_static(&ctx, 30, 80, 1);
192  if (nk_button_label(&ctx, "button")) {
193  // event handling
194  }
195 
196  // fixed widget window ratio width
197  nk_layout_row_dynamic(&ctx, 30, 2);
198  if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY;
199  if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD;
200 
201  // custom widget pixel width
202  nk_layout_row_begin(&ctx, NK_STATIC, 30, 2);
203  {
204  nk_layout_row_push(&ctx, 50);
205  nk_label(&ctx, "Volume:", NK_TEXT_LEFT);
206  nk_layout_row_push(&ctx, 110);
207  nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f);
208  }
209  nk_layout_row_end(&ctx);
210 }
211 nk_end(&ctx);
212 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213 
214 ![](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png)
215 
216 ## API
217 
218 */
219 #ifndef NK_SINGLE_FILE
220  #define NK_SINGLE_FILE
221 #endif
222 
228 #ifndef NK_NUKLEAR_H_
229 #define NK_NUKLEAR_H_
230 
231 #ifdef __cplusplus
232 extern "C" {
233 #endif
234 /*
235  * ==============================================================
236  *
237  * CONSTANTS
238  *
239  * ===============================================================
240  */
241 
242 #define NK_UNDEFINED (-1.0f)
243 #define NK_UTF_INVALID 0xFFFD
244 #define NK_UTF_SIZE 4
245 #ifndef NK_INPUT_MAX
246  #define NK_INPUT_MAX 16
247 #endif
248 #ifndef NK_MAX_NUMBER_BUFFER
249  #define NK_MAX_NUMBER_BUFFER 64
250 #endif
251 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
252  #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
253 #endif
254 /*
255  * ==============================================================
256  *
257  * HELPER
258  *
259  * ===============================================================
260  */
261 
262 #ifndef NK_API
263  #ifdef NK_PRIVATE
264  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
265  #define NK_API static inline
266  #elif defined(__cplusplus)
267  #define NK_API static inline
268  #else
269  #define NK_API static
270  #endif
271  #else
272  #define NK_API extern
273  #endif
274 #endif
275 #ifndef NK_LIB
276  #ifdef NK_SINGLE_FILE
277  #define NK_LIB static
278  #else
279  #define NK_LIB extern
280  #endif
281 #endif
282 
283 #define NK_INTERN static
284 #define NK_STORAGE static
285 #define NK_GLOBAL static
286 
287 #define NK_FLAG(x) (1 << (x))
288 #define NK_STRINGIFY(x) #x
289 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
290 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
291 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
292 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
293 
294 #ifdef _MSC_VER
295  #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
296 #else
297  #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
298 #endif
299 
300 #ifndef NK_STATIC_ASSERT
301  #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
302 #endif
303 
304 #ifndef NK_FILE_LINE
305 #ifdef _MSC_VER
306  #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
307 #else
308  #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
309 #endif
310 #endif
311 
312 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
313 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
314 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
315 
316 #ifdef NK_INCLUDE_STANDARD_VARARGS
317  #include <stdarg.h>
318  #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
319  #include <sal.h>
320  #define NK_PRINTF_FORMAT_STRING _Printf_format_string_
321  #else
322  #define NK_PRINTF_FORMAT_STRING
323  #endif
324  #if defined(__GNUC__)
325  #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1)))
326  #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0)))
327  #else
328  #define NK_PRINTF_VARARG_FUNC(fmtargnumber)
329  #define NK_PRINTF_VALIST_FUNC(fmtargnumber)
330  #endif
331 #endif
332 
333 /*
334  * ===============================================================
335  *
336  * BASIC
337  *
338  * ===============================================================
339  */
340  #ifdef NK_INCLUDE_FIXED_TYPES
341  #include <stdint.h>
342  #define NK_INT8 int8_t
343  #define NK_UINT8 uint8_t
344  #define NK_INT16 int16_t
345  #define NK_UINT16 uint16_t
346  #define NK_INT32 int32_t
347  #define NK_UINT32 uint32_t
348  #define NK_SIZE_TYPE uintptr_t
349  #define NK_POINTER_TYPE uintptr_t
350 #else
351  #ifndef NK_INT8
352  #define NK_INT8 signed char
353  #endif
354  #ifndef NK_UINT8
355  #define NK_UINT8 unsigned char
356  #endif
357  #ifndef NK_INT16
358  #define NK_INT16 signed short
359  #endif
360  #ifndef NK_UINT16
361  #define NK_UINT16 unsigned short
362  #endif
363  #ifndef NK_INT32
364  #if defined(_MSC_VER)
365  #define NK_INT32 __int32
366  #else
367  #define NK_INT32 signed int
368  #endif
369  #endif
370  #ifndef NK_UINT32
371  #if defined(_MSC_VER)
372  #define NK_UINT32 unsigned __int32
373  #else
374  #define NK_UINT32 unsigned int
375  #endif
376  #endif
377  #ifndef NK_SIZE_TYPE
378  #if defined(_WIN64) && defined(_MSC_VER)
379  #define NK_SIZE_TYPE unsigned __int64
380  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
381  #define NK_SIZE_TYPE unsigned __int32
382  #elif defined(__GNUC__) || defined(__clang__)
383  #if defined(__x86_64__) || defined(__ppc64__) || defined(__PPC64__) || defined(__aarch64__)
384  #define NK_SIZE_TYPE unsigned long
385  #else
386  #define NK_SIZE_TYPE unsigned int
387  #endif
388  #else
389  #define NK_SIZE_TYPE unsigned long
390  #endif
391  #endif
392  #ifndef NK_POINTER_TYPE
393  #if defined(_WIN64) && defined(_MSC_VER)
394  #define NK_POINTER_TYPE unsigned __int64
395  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
396  #define NK_POINTER_TYPE unsigned __int32
397  #elif defined(__GNUC__) || defined(__clang__)
398  #if defined(__x86_64__) || defined(__ppc64__) || defined(__PPC64__) || defined(__aarch64__)
399  #define NK_POINTER_TYPE unsigned long
400  #else
401  #define NK_POINTER_TYPE unsigned int
402  #endif
403  #else
404  #define NK_POINTER_TYPE unsigned long
405  #endif
406  #endif
407 #endif
408 
409 #ifndef NK_BOOL
410  #ifdef NK_INCLUDE_STANDARD_BOOL
411  #include <stdbool.h>
412  #define NK_BOOL bool
413  #else
414  #define NK_BOOL int
415  #endif
416 #endif
417 
418 typedef NK_INT8 nk_char;
419 typedef NK_UINT8 nk_uchar;
420 typedef NK_UINT8 nk_byte;
421 typedef NK_INT16 nk_short;
422 typedef NK_UINT16 nk_ushort;
423 typedef NK_INT32 nk_int;
424 typedef NK_UINT32 nk_uint;
425 typedef NK_SIZE_TYPE nk_size;
426 typedef NK_POINTER_TYPE nk_ptr;
427 typedef NK_BOOL nk_bool;
428 
429 typedef nk_uint nk_hash;
430 typedef nk_uint nk_flags;
431 typedef nk_uint nk_rune;
432 
433 /* Make sure correct type size:
434  * This will fire with a negative subscript error if the type sizes
435  * are set incorrectly by the compiler, and compile out if not */
436 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
437 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
438 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
439 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
440 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
441 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
442 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
443 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
444 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
445 #ifdef NK_INCLUDE_STANDARD_BOOL
446 NK_STATIC_ASSERT(sizeof(nk_bool) == sizeof(bool));
447 #else
448 NK_STATIC_ASSERT(sizeof(nk_bool) >= 2);
449 #endif
450 
451 /* ============================================================================
452  *
453  * API
454  *
455  * =========================================================================== */
456 struct nk_buffer;
457 struct nk_allocator;
458 struct nk_command_buffer;
459 struct nk_draw_command;
460 struct nk_convert_config;
461 struct nk_style_item;
462 struct nk_text_edit;
463 struct nk_draw_list;
464 struct nk_user_font;
465 struct nk_panel;
466 struct nk_context;
467 struct nk_draw_vertex_layout_element;
468 struct nk_style_button;
469 struct nk_style_toggle;
470 struct nk_style_selectable;
471 struct nk_style_slide;
472 struct nk_style_progress;
473 struct nk_style_scrollbar;
474 struct nk_style_edit;
475 struct nk_style_property;
476 struct nk_style_chart;
477 struct nk_style_combo;
478 struct nk_style_tab;
480 struct nk_style_window;
481 
482 enum {nk_false, nk_true};
483 struct nk_color {nk_byte r,g,b,a;};
484 struct nk_colorf {float r,g,b,a;};
485 struct nk_vec2 {float x,y;};
486 struct nk_vec2i {short x, y;};
487 struct nk_rect {float x,y,w,h;};
488 struct nk_recti {short x,y,w,h;};
489 typedef char nk_glyph[NK_UTF_SIZE];
490 typedef union {void *ptr; int id;} nk_handle;
491 struct nk_image {nk_handle handle; nk_ushort w, h; nk_ushort region[4];};
492 struct nk_nine_slice {struct nk_image img; nk_ushort l, t, r, b;};
493 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
494 struct nk_scroll {nk_uint x, y;};
495 
496 enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
497 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
498 enum nk_modify {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
499 enum nk_orientation {NK_VERTICAL, NK_HORIZONTAL};
500 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true};
501 enum nk_show_states {NK_HIDDEN = nk_false, NK_SHOWN = nk_true};
502 enum nk_chart_type {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX};
503 enum nk_chart_event {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02};
504 enum nk_color_format {NK_RGB, NK_RGBA};
505 enum nk_popup_type {NK_POPUP_STATIC, NK_POPUP_DYNAMIC};
506 enum nk_layout_format {NK_DYNAMIC, NK_STATIC};
507 enum nk_tree_type {NK_TREE_NODE, NK_TREE_TAB};
508 
509 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
510 typedef void (*nk_plugin_free)(nk_handle, void *old);
511 typedef nk_bool(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
512 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
513 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
514 
515 struct nk_allocator {
516  nk_handle userdata;
517  nk_plugin_alloc alloc;
518  nk_plugin_free free;
519 };
520 enum nk_symbol_type {
521  NK_SYMBOL_NONE,
522  NK_SYMBOL_X,
523  NK_SYMBOL_UNDERSCORE,
524  NK_SYMBOL_CIRCLE_SOLID,
525  NK_SYMBOL_CIRCLE_OUTLINE,
526  NK_SYMBOL_RECT_SOLID,
527  NK_SYMBOL_RECT_OUTLINE,
528  NK_SYMBOL_TRIANGLE_UP,
529  NK_SYMBOL_TRIANGLE_DOWN,
530  NK_SYMBOL_TRIANGLE_LEFT,
531  NK_SYMBOL_TRIANGLE_RIGHT,
532  NK_SYMBOL_PLUS,
533  NK_SYMBOL_MINUS,
534  NK_SYMBOL_TRIANGLE_UP_OUTLINE,
535  NK_SYMBOL_TRIANGLE_DOWN_OUTLINE,
536  NK_SYMBOL_TRIANGLE_LEFT_OUTLINE,
537  NK_SYMBOL_TRIANGLE_RIGHT_OUTLINE,
538  NK_SYMBOL_MAX
539 };
540 /* =============================================================================
541  *
542  * CONTEXT
543  *
544  * =============================================================================*/
580 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
581 
592 NK_API nk_bool nk_init_default(struct nk_context*, const struct nk_user_font*);
593 #endif
612 NK_API nk_bool nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
613 
626 NK_API nk_bool nk_init(struct nk_context*, const struct nk_allocator*, const struct nk_user_font*);
627 
643 NK_API nk_bool nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
644 
655 NK_API void nk_clear(struct nk_context*);
656 
664 NK_API void nk_free(struct nk_context*);
665 
666 #ifdef NK_INCLUDE_COMMAND_USERDATA
675 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
676 #endif
677 /* =============================================================================
678  *
679  * INPUT
680  *
681  * =============================================================================*/
746 enum nk_keys {
747  NK_KEY_NONE,
748  NK_KEY_SHIFT,
749  NK_KEY_CTRL,
750  NK_KEY_DEL,
751  NK_KEY_ENTER,
752  NK_KEY_TAB,
753  NK_KEY_BACKSPACE,
754  NK_KEY_COPY,
755  NK_KEY_CUT,
756  NK_KEY_PASTE,
757  NK_KEY_UP,
758  NK_KEY_DOWN,
759  NK_KEY_LEFT,
760  NK_KEY_RIGHT,
761  /* Shortcuts: text field */
762  NK_KEY_TEXT_INSERT_MODE,
763  NK_KEY_TEXT_REPLACE_MODE,
764  NK_KEY_TEXT_RESET_MODE,
765  NK_KEY_TEXT_LINE_START,
766  NK_KEY_TEXT_LINE_END,
767  NK_KEY_TEXT_START,
768  NK_KEY_TEXT_END,
769  NK_KEY_TEXT_UNDO,
770  NK_KEY_TEXT_REDO,
771  NK_KEY_TEXT_SELECT_ALL,
772  NK_KEY_TEXT_WORD_LEFT,
773  NK_KEY_TEXT_WORD_RIGHT,
774  /* Shortcuts: scrollbar */
775  NK_KEY_SCROLL_START,
776  NK_KEY_SCROLL_END,
777  NK_KEY_SCROLL_DOWN,
778  NK_KEY_SCROLL_UP,
779  NK_KEY_MAX
780 };
781 enum nk_buttons {
782  NK_BUTTON_LEFT,
783  NK_BUTTON_MIDDLE,
784  NK_BUTTON_RIGHT,
785  NK_BUTTON_DOUBLE,
786  NK_BUTTON_MAX
787 };
788 
797 NK_API void nk_input_begin(struct nk_context*);
798 
808 NK_API void nk_input_motion(struct nk_context*, int x, int y);
809 
819 NK_API void nk_input_key(struct nk_context*, enum nk_keys, nk_bool down);
820 
832 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, nk_bool down);
833 
845 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
846 
861 NK_API void nk_input_char(struct nk_context*, char);
862 
874 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
875 
888 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
889 
898 NK_API void nk_input_end(struct nk_context*);
899 
1131 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON};
1132 enum nk_convert_result {
1133  NK_CONVERT_SUCCESS = 0,
1134  NK_CONVERT_INVALID_PARAM = 1,
1135  NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1),
1136  NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2),
1137  NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3)
1138 };
1140  nk_handle texture;
1141  struct nk_vec2 uv;
1142 };
1144  float global_alpha;
1145  enum nk_anti_aliasing line_AA;
1146  enum nk_anti_aliasing shape_AA;
1151  const struct nk_draw_vertex_layout_element *vertex_layout;
1152  nk_size vertex_size;
1154 };
1155 
1166 NK_API const struct nk_command* nk__begin(struct nk_context*);
1167 
1178 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1179 
1187 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1188 
1189 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1190 
1215 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*);
1216 
1227 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1228 
1238 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1239 
1251 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1252 
1262 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1263 #endif
1264 
1409 enum nk_panel_flags {
1410  NK_WINDOW_BORDER = NK_FLAG(0),
1411  NK_WINDOW_MOVABLE = NK_FLAG(1),
1412  NK_WINDOW_SCALABLE = NK_FLAG(2),
1413  NK_WINDOW_CLOSABLE = NK_FLAG(3),
1414  NK_WINDOW_MINIMIZABLE = NK_FLAG(4),
1415  NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5),
1416  NK_WINDOW_TITLE = NK_FLAG(6),
1417  NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7),
1418  NK_WINDOW_BACKGROUND = NK_FLAG(8),
1419  NK_WINDOW_SCALE_LEFT = NK_FLAG(9),
1420  NK_WINDOW_NO_INPUT = NK_FLAG(10)
1421 };
1422 
1439 NK_API nk_bool nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1440 
1458 NK_API nk_bool nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1459 
1470 NK_API void nk_end(struct nk_context *ctx);
1471 
1484 NK_API struct nk_window *nk_window_find(const struct nk_context *ctx, const char *name);
1485 
1499 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
1500 
1514 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
1515 
1529 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context *ctx);
1530 
1543 NK_API float nk_window_get_width(const struct nk_context *ctx);
1544 
1558 NK_API float nk_window_get_height(const struct nk_context* ctx);
1559 
1575 NK_API struct nk_panel* nk_window_get_panel(const struct nk_context* ctx);
1576 
1593 NK_API struct nk_rect nk_window_get_content_region(const struct nk_context* ctx);
1594 
1611 NK_API struct nk_vec2 nk_window_get_content_region_min(const struct nk_context *ctx);
1612 
1629 NK_API struct nk_vec2 nk_window_get_content_region_max(const struct nk_context *ctx);
1630 
1645 NK_API struct nk_vec2 nk_window_get_content_region_size(const struct nk_context *ctx);
1646 
1662 NK_API struct nk_command_buffer* nk_window_get_canvas(const struct nk_context* ctx);
1663 
1677 NK_API void nk_window_get_scroll(const struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y);
1678 
1691 NK_API nk_bool nk_window_has_focus(const struct nk_context *ctx);
1692 
1705 NK_API nk_bool nk_window_is_hovered(const struct nk_context *ctx);
1706 
1719 NK_API nk_bool nk_window_is_collapsed(const struct nk_context *ctx, const char *name);
1720 
1732 NK_API nk_bool nk_window_is_closed(const struct nk_context *ctx, const char* name);
1733 
1745 NK_API nk_bool nk_window_is_hidden(const struct nk_context *ctx, const char* name);
1746 
1757 NK_API nk_bool nk_window_is_active(const struct nk_context *ctx, const char* name);
1758 
1768 NK_API nk_bool nk_window_is_any_hovered(const struct nk_context *ctx);
1769 
1782 NK_API nk_bool nk_item_is_any_active(const struct nk_context *ctx);
1783 
1794 NK_API void nk_window_set_bounds(struct nk_context *ctx, const char *name, struct nk_rect bounds);
1795 
1804 NK_API void nk_window_set_position(struct nk_context *ctx, const char *name, struct nk_vec2 pos);
1805 
1814 NK_API void nk_window_set_size(struct nk_context *ctx, const char *name, struct nk_vec2 size);
1815 
1823 NK_API void nk_window_set_focus(struct nk_context *ctx, const char *name);
1824 
1838 NK_API void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y);
1839 
1849 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1850 
1861 NK_API void nk_window_collapse(struct nk_context *ctx, const char *name, enum nk_collapse_states state);
1862 
1874 NK_API void nk_window_collapse_if(struct nk_context *ctx, const char *name, enum nk_collapse_states state, int cond);
1875 
1885 NK_API void nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states state);
1886 
1898 NK_API void nk_window_show_if(struct nk_context *ctx, const char *name, enum nk_show_states state, int cond);
1899 
1909 NK_API void nk_rule_horizontal(struct nk_context *ctx, struct nk_color color, nk_bool rounding);
1910 
1911 /* =============================================================================
1912  *
1913  * LAYOUT
1914  *
1915  * =============================================================================*/
2184 enum nk_widget_align {
2185  NK_WIDGET_ALIGN_LEFT = 0x01,
2186  NK_WIDGET_ALIGN_CENTERED = 0x02,
2187  NK_WIDGET_ALIGN_RIGHT = 0x04,
2188  NK_WIDGET_ALIGN_TOP = 0x08,
2189  NK_WIDGET_ALIGN_MIDDLE = 0x10,
2190  NK_WIDGET_ALIGN_BOTTOM = 0x20
2191 };
2192 enum nk_widget_alignment {
2193  NK_WIDGET_LEFT = NK_WIDGET_ALIGN_MIDDLE|NK_WIDGET_ALIGN_LEFT,
2194  NK_WIDGET_CENTERED = NK_WIDGET_ALIGN_MIDDLE|NK_WIDGET_ALIGN_CENTERED,
2195  NK_WIDGET_RIGHT = NK_WIDGET_ALIGN_MIDDLE|NK_WIDGET_ALIGN_RIGHT
2196 };
2197 
2210 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height);
2211 
2220 
2230 NK_API struct nk_rect nk_layout_widget_bounds(const struct nk_context *ctx);
2231 
2242 NK_API float nk_layout_ratio_from_pixel(const struct nk_context *ctx, float pixel_width);
2243 
2255 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
2256 
2269 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
2270 
2281 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
2282 
2291 NK_API void nk_layout_row_push(struct nk_context*, float value);
2292 
2300 NK_API void nk_layout_row_end(struct nk_context*);
2301 
2312 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
2313 
2322 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
2323 
2333 
2342 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
2343 
2352 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
2353 
2362 
2373 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
2374 
2383 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds);
2384 
2392 NK_API void nk_layout_space_end(struct nk_context*);
2393 
2403 NK_API struct nk_rect nk_layout_space_bounds(const struct nk_context *ctx);
2404 
2415 NK_API struct nk_vec2 nk_layout_space_to_screen(const struct nk_context* ctx, struct nk_vec2 vec);
2416 
2427 NK_API struct nk_vec2 nk_layout_space_to_local(const struct nk_context *ctx, struct nk_vec2 vec);
2428 
2439 NK_API struct nk_rect nk_layout_space_rect_to_screen(const struct nk_context *ctx, struct nk_rect bounds);
2440 
2451 NK_API struct nk_rect nk_layout_space_rect_to_local(const struct nk_context *ctx, struct nk_rect bounds);
2452 
2461 NK_API void nk_spacer(struct nk_context *ctx);
2462 
2463 
2563 NK_API nk_bool nk_group_begin(struct nk_context*, const char *title, nk_flags);
2564 
2575 NK_API nk_bool nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
2576 
2584 NK_API void nk_group_end(struct nk_context*);
2585 
2600 NK_API nk_bool nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
2601 
2614 NK_API nk_bool nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
2615 
2623 NK_API void nk_group_scrolled_end(struct nk_context*);
2624 
2635 NK_API void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset);
2636 
2647 NK_API void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset);
2648 
2738 #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__)
2739 
2753 #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)
2754 
2770 NK_API nk_bool nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
2771 
2790 #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__)
2791 
2807 #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)
2808 
2825 NK_API nk_bool nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
2826 
2834 NK_API void nk_tree_pop(struct nk_context*);
2835 
2848 NK_API nk_bool nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
2849 
2863 NK_API nk_bool nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
2864 
2872 NK_API void nk_tree_state_pop(struct nk_context*);
2873 
2874 #define nk_tree_element_push(ctx, type, title, state, sel) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
2875 #define nk_tree_element_push_id(ctx, type, title, state, sel, id) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
2876 NK_API nk_bool nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, const char *hash, int len, int seed);
2877 NK_API nk_bool nk_tree_element_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, const char *hash, int len,int seed);
2878 NK_API void nk_tree_element_pop(struct nk_context*);
2879 
2880 /* =============================================================================
2881  *
2882  * LIST VIEW
2883  *
2884  * ============================================================================= */
2886 /* public: */
2887  int begin, end, count;
2888 /* private: */
2889  int total_height;
2890  struct nk_context *ctx;
2891  nk_uint *scroll_pointer;
2892  nk_uint scroll_value;
2893 };
2894 NK_API nk_bool nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
2895 NK_API void nk_list_view_end(struct nk_list_view*);
2896 /* =============================================================================
2897  *
2898  * WIDGET
2899  *
2900  * ============================================================================= */
2906 };
2908  NK_WIDGET_STATE_MODIFIED = NK_FLAG(1),
2909  NK_WIDGET_STATE_INACTIVE = NK_FLAG(2),
2911  NK_WIDGET_STATE_HOVER = NK_FLAG(4),
2913  NK_WIDGET_STATE_LEFT = NK_FLAG(6),
2914  NK_WIDGET_STATE_HOVERED = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED,
2915  NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED
2916 };
2917 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
2918 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, const struct nk_context*, struct nk_vec2);
2919 NK_API struct nk_rect nk_widget_bounds(const struct nk_context*);
2920 NK_API struct nk_vec2 nk_widget_position(const struct nk_context*);
2921 NK_API struct nk_vec2 nk_widget_size(const struct nk_context*);
2922 NK_API float nk_widget_width(const struct nk_context*);
2923 NK_API float nk_widget_height(const struct nk_context*);
2924 NK_API nk_bool nk_widget_is_hovered(const struct nk_context*);
2925 NK_API nk_bool nk_widget_is_mouse_clicked(const struct nk_context*, enum nk_buttons);
2926 NK_API nk_bool nk_widget_has_mouse_click_down(const struct nk_context*, enum nk_buttons, nk_bool down);
2927 NK_API void nk_spacing(struct nk_context*, int cols);
2928 NK_API void nk_widget_disable_begin(struct nk_context* ctx);
2929 NK_API void nk_widget_disable_end(struct nk_context* ctx);
2930 /* =============================================================================
2931  *
2932  * TEXT
2933  *
2934  * ============================================================================= */
2935 enum nk_text_align {
2936  NK_TEXT_ALIGN_LEFT = 0x01,
2937  NK_TEXT_ALIGN_CENTERED = 0x02,
2938  NK_TEXT_ALIGN_RIGHT = 0x04,
2939  NK_TEXT_ALIGN_TOP = 0x08,
2940  NK_TEXT_ALIGN_MIDDLE = 0x10,
2941  NK_TEXT_ALIGN_BOTTOM = 0x20
2942 };
2943 enum nk_text_alignment {
2944  NK_TEXT_LEFT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT,
2945  NK_TEXT_CENTERED = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED,
2946  NK_TEXT_RIGHT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT
2947 };
2948 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
2949 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
2950 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
2951 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
2952 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
2953 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
2954 NK_API void nk_label_wrap(struct nk_context*, const char*);
2955 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
2956 NK_API void nk_image(struct nk_context*, struct nk_image);
2957 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color);
2958 #ifdef NK_INCLUDE_STANDARD_VARARGS
2959 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3);
2960 NK_API void nk_labelf_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(4);
2961 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2);
2962 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3);
2963 NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
2964 NK_API void nk_labelfv_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(4);
2965 NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
2966 NK_API void nk_labelfv_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3);
2967 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
2968 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
2969 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
2970 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
2971 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
2972 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
2973 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
2974 #endif
2975 /* =============================================================================
2976  *
2977  * BUTTON
2978  *
2979  * ============================================================================= */
2980 NK_API nk_bool nk_button_text(struct nk_context*, const char *title, int len);
2981 NK_API nk_bool nk_button_label(struct nk_context*, const char *title);
2982 NK_API nk_bool nk_button_color(struct nk_context*, struct nk_color);
2983 NK_API nk_bool nk_button_symbol(struct nk_context*, enum nk_symbol_type);
2984 NK_API nk_bool nk_button_image(struct nk_context*, struct nk_image img);
2985 NK_API nk_bool nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
2986 NK_API nk_bool nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2987 NK_API nk_bool nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
2988 NK_API nk_bool nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
2989 NK_API nk_bool nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
2990 NK_API nk_bool nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
2991 NK_API nk_bool nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
2992 NK_API nk_bool nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
2993 NK_API nk_bool nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2994 NK_API nk_bool nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
2995 NK_API nk_bool nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
2996 NK_API nk_bool nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
2997 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior);
2998 NK_API nk_bool nk_button_push_behavior(struct nk_context*, enum nk_button_behavior);
2999 NK_API nk_bool nk_button_pop_behavior(struct nk_context*);
3000 /* =============================================================================
3001  *
3002  * CHECKBOX
3003  *
3004  * ============================================================================= */
3005 NK_API nk_bool nk_check_label(struct nk_context*, const char*, nk_bool active);
3006 NK_API nk_bool nk_check_text(struct nk_context*, const char*, int, nk_bool active);
3007 NK_API nk_bool nk_check_text_align(struct nk_context*, const char*, int, nk_bool active, nk_flags widget_alignment, nk_flags text_alignment);
3008 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
3009 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
3010 NK_API nk_bool nk_checkbox_label(struct nk_context*, const char*, nk_bool *active);
3011 NK_API nk_bool nk_checkbox_label_align(struct nk_context *ctx, const char *label, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment);
3012 NK_API nk_bool nk_checkbox_text(struct nk_context*, const char*, int, nk_bool *active);
3013 NK_API nk_bool nk_checkbox_text_align(struct nk_context *ctx, const char *text, int len, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment);
3014 NK_API nk_bool nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
3015 NK_API nk_bool nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
3016 /* =============================================================================
3017  *
3018  * RADIO BUTTON
3019  *
3020  * ============================================================================= */
3021 NK_API nk_bool nk_radio_label(struct nk_context*, const char*, nk_bool *active);
3022 NK_API nk_bool nk_radio_label_align(struct nk_context *ctx, const char *label, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment);
3023 NK_API nk_bool nk_radio_text(struct nk_context*, const char*, int, nk_bool *active);
3024 NK_API nk_bool nk_radio_text_align(struct nk_context *ctx, const char *text, int len, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment);
3025 NK_API nk_bool nk_option_label(struct nk_context*, const char*, nk_bool active);
3026 NK_API nk_bool nk_option_label_align(struct nk_context *ctx, const char *label, nk_bool active, nk_flags widget_alignment, nk_flags text_alignment);
3027 NK_API nk_bool nk_option_text(struct nk_context*, const char*, int, nk_bool active);
3028 NK_API nk_bool nk_option_text_align(struct nk_context *ctx, const char *text, int len, nk_bool is_active, nk_flags widget_alignment, nk_flags text_alignment);
3029 /* =============================================================================
3030  *
3031  * SELECTABLE
3032  *
3033  * ============================================================================= */
3034 NK_API nk_bool nk_selectable_label(struct nk_context*, const char*, nk_flags align, nk_bool *value);
3035 NK_API nk_bool nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, nk_bool *value);
3036 NK_API nk_bool nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, nk_bool *value);
3037 NK_API nk_bool nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, nk_bool *value);
3038 NK_API nk_bool nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, nk_bool *value);
3039 NK_API nk_bool nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, nk_bool *value);
3040 
3041 NK_API nk_bool nk_select_label(struct nk_context*, const char*, nk_flags align, nk_bool value);
3042 NK_API nk_bool nk_select_text(struct nk_context*, const char*, int, nk_flags align, nk_bool value);
3043 NK_API nk_bool nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, nk_bool value);
3044 NK_API nk_bool nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, nk_bool value);
3045 NK_API nk_bool nk_select_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, nk_bool value);
3046 NK_API nk_bool nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, nk_bool value);
3047 
3048 /* =============================================================================
3049  *
3050  * SLIDER
3051  *
3052  * ============================================================================= */
3053 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
3054 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
3055 NK_API nk_bool nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
3056 NK_API nk_bool nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
3057 
3058 /* =============================================================================
3059  *
3060  * KNOB
3061  *
3062  * ============================================================================= */
3063 NK_API nk_bool nk_knob_float(struct nk_context*, float min, float *val, float max, float step, enum nk_heading zero_direction, float dead_zone_degrees);
3064 NK_API nk_bool nk_knob_int(struct nk_context*, int min, int *val, int max, int step, enum nk_heading zero_direction, float dead_zone_degrees);
3065 
3066 /* =============================================================================
3067  *
3068  * PROGRESSBAR
3069  *
3070  * ============================================================================= */
3071 NK_API nk_bool nk_progress(struct nk_context*, nk_size *cur, nk_size max, nk_bool modifyable);
3072 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, nk_bool modifyable);
3073 
3074 /* =============================================================================
3075  *
3076  * COLOR PICKER
3077  *
3078  * ============================================================================= */
3079 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format);
3080 NK_API nk_bool nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format);
3081 /* =============================================================================
3082  *
3083  * PROPERTIES
3084  *
3085  * =============================================================================*/
3172 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
3173 
3189 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
3190 
3208 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
3209 
3229 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
3230 
3250 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
3251 
3271 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
3272 
3273 /* =============================================================================
3274  *
3275  * TEXT EDIT
3276  *
3277  * ============================================================================= */
3278 enum nk_edit_flags {
3279  NK_EDIT_DEFAULT = 0,
3280  NK_EDIT_READ_ONLY = NK_FLAG(0),
3281  NK_EDIT_AUTO_SELECT = NK_FLAG(1),
3282  NK_EDIT_SIG_ENTER = NK_FLAG(2),
3283  NK_EDIT_ALLOW_TAB = NK_FLAG(3),
3284  NK_EDIT_NO_CURSOR = NK_FLAG(4),
3285  NK_EDIT_SELECTABLE = NK_FLAG(5),
3286  NK_EDIT_CLIPBOARD = NK_FLAG(6),
3287  NK_EDIT_CTRL_ENTER_NEWLINE = NK_FLAG(7),
3288  NK_EDIT_NO_HORIZONTAL_SCROLL = NK_FLAG(8),
3289  NK_EDIT_ALWAYS_INSERT_MODE = NK_FLAG(9),
3290  NK_EDIT_MULTILINE = NK_FLAG(10),
3291  NK_EDIT_GOTO_END_ON_ACTIVATE = NK_FLAG(11)
3292 };
3293 enum nk_edit_types {
3294  NK_EDIT_SIMPLE = NK_EDIT_ALWAYS_INSERT_MODE,
3295  NK_EDIT_FIELD = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD,
3296  NK_EDIT_BOX = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD,
3297  NK_EDIT_EDITOR = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD
3298 };
3300  NK_EDIT_ACTIVE = NK_FLAG(0),
3301  NK_EDIT_INACTIVE = NK_FLAG(1),
3302  NK_EDIT_ACTIVATED = NK_FLAG(2),
3303  NK_EDIT_DEACTIVATED = NK_FLAG(3),
3304  NK_EDIT_COMMITED = NK_FLAG(4)
3305 };
3306 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
3307 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
3308 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
3309 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
3310 NK_API void nk_edit_unfocus(struct nk_context*);
3311 /* =============================================================================
3312  *
3313  * CHART
3314  *
3315  * ============================================================================= */
3316 NK_API nk_bool nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
3317 NK_API nk_bool nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
3318 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
3319 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);
3320 NK_API nk_flags nk_chart_push(struct nk_context*, float);
3321 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
3322 NK_API void nk_chart_end(struct nk_context*);
3323 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
3324 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);
3325 /* =============================================================================
3326  *
3327  * POPUP
3328  *
3329  * ============================================================================= */
3330 NK_API nk_bool nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
3331 NK_API void nk_popup_close(struct nk_context*);
3332 NK_API void nk_popup_end(struct nk_context*);
3333 NK_API void nk_popup_get_scroll(const struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
3334 NK_API void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
3335 /* =============================================================================
3336  *
3337  * COMBOBOX
3338  *
3339  * ============================================================================= */
3340 NK_API int nk_combo(struct nk_context*, const char *const *items, int count, int selected, int item_height, struct nk_vec2 size);
3341 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);
3342 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);
3343 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);
3344 NK_API void nk_combobox(struct nk_context*, const char *const *items, int count, int *selected, int item_height, struct nk_vec2 size);
3345 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);
3346 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);
3347 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);
3348 /* =============================================================================
3349  *
3350  * ABSTRACT COMBOBOX
3351  *
3352  * ============================================================================= */
3353 NK_API nk_bool nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
3354 NK_API nk_bool nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
3355 NK_API nk_bool nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
3356 NK_API nk_bool nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size);
3357 NK_API nk_bool nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
3358 NK_API nk_bool nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
3359 NK_API nk_bool nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size);
3360 NK_API nk_bool nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
3361 NK_API nk_bool nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size);
3362 NK_API nk_bool nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
3363 NK_API nk_bool nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
3364 NK_API nk_bool nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3365 NK_API nk_bool nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
3366 NK_API nk_bool nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3367 NK_API nk_bool nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3368 NK_API void nk_combo_close(struct nk_context*);
3369 NK_API void nk_combo_end(struct nk_context*);
3370 /* =============================================================================
3371  *
3372  * CONTEXTUAL
3373  *
3374  * ============================================================================= */
3375 NK_API nk_bool nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
3376 NK_API nk_bool nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
3377 NK_API nk_bool nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
3378 NK_API nk_bool nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3379 NK_API nk_bool nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3380 NK_API nk_bool nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3381 NK_API nk_bool nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3382 NK_API void nk_contextual_close(struct nk_context*);
3383 NK_API void nk_contextual_end(struct nk_context*);
3384 /* =============================================================================
3385  *
3386  * TOOLTIP
3387  *
3388  * ============================================================================= */
3389 NK_API void nk_tooltip(struct nk_context*, const char*);
3390 #ifdef NK_INCLUDE_STANDARD_VARARGS
3391 NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2);
3392 NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
3393 #endif
3394 NK_API nk_bool nk_tooltip_begin(struct nk_context*, float width);
3395 NK_API void nk_tooltip_end(struct nk_context*);
3396 /* =============================================================================
3397  *
3398  * MENU
3399  *
3400  * ============================================================================= */
3401 NK_API void nk_menubar_begin(struct nk_context*);
3402 NK_API void nk_menubar_end(struct nk_context*);
3403 NK_API nk_bool nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
3404 NK_API nk_bool nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
3405 NK_API nk_bool nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
3406 NK_API nk_bool nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
3407 NK_API nk_bool nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
3408 NK_API nk_bool nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
3409 NK_API nk_bool nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
3410 NK_API nk_bool nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
3411 NK_API nk_bool nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
3412 NK_API nk_bool nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
3413 NK_API nk_bool nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
3414 NK_API nk_bool nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
3415 NK_API nk_bool nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
3416 NK_API nk_bool nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
3417 NK_API void nk_menu_close(struct nk_context*);
3418 NK_API void nk_menu_end(struct nk_context*);
3419 /* =============================================================================
3420  *
3421  * STYLE
3422  *
3423  * ============================================================================= */
3424 
3425 #define NK_WIDGET_DISABLED_FACTOR 0.5f
3426 
3427 enum nk_style_colors {
3428  NK_COLOR_TEXT,
3429  NK_COLOR_WINDOW,
3430  NK_COLOR_HEADER,
3431  NK_COLOR_BORDER,
3432  NK_COLOR_BUTTON,
3433  NK_COLOR_BUTTON_HOVER,
3434  NK_COLOR_BUTTON_ACTIVE,
3435  NK_COLOR_TOGGLE,
3436  NK_COLOR_TOGGLE_HOVER,
3437  NK_COLOR_TOGGLE_CURSOR,
3438  NK_COLOR_SELECT,
3439  NK_COLOR_SELECT_ACTIVE,
3440  NK_COLOR_SLIDER,
3441  NK_COLOR_SLIDER_CURSOR,
3442  NK_COLOR_SLIDER_CURSOR_HOVER,
3443  NK_COLOR_SLIDER_CURSOR_ACTIVE,
3444  NK_COLOR_PROPERTY,
3445  NK_COLOR_EDIT,
3446  NK_COLOR_EDIT_CURSOR,
3447  NK_COLOR_COMBO,
3448  NK_COLOR_CHART,
3449  NK_COLOR_CHART_COLOR,
3450  NK_COLOR_CHART_COLOR_HIGHLIGHT,
3451  NK_COLOR_SCROLLBAR,
3452  NK_COLOR_SCROLLBAR_CURSOR,
3453  NK_COLOR_SCROLLBAR_CURSOR_HOVER,
3454  NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,
3455  NK_COLOR_TAB_HEADER,
3456  NK_COLOR_KNOB,
3457  NK_COLOR_KNOB_CURSOR,
3458  NK_COLOR_KNOB_CURSOR_HOVER,
3459  NK_COLOR_KNOB_CURSOR_ACTIVE,
3460  NK_COLOR_COUNT
3461 };
3462 enum nk_style_cursor {
3463  NK_CURSOR_ARROW,
3464  NK_CURSOR_TEXT,
3465  NK_CURSOR_MOVE,
3466  NK_CURSOR_RESIZE_VERTICAL,
3467  NK_CURSOR_RESIZE_HORIZONTAL,
3468  NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT,
3469  NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT,
3470  NK_CURSOR_COUNT
3471 };
3472 NK_API void nk_style_default(struct nk_context*);
3473 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
3474 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
3475 NK_API void nk_style_load_all_cursors(struct nk_context*, const struct nk_cursor*);
3476 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors);
3477 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
3478 NK_API nk_bool nk_style_set_cursor(struct nk_context*, enum nk_style_cursor);
3479 NK_API void nk_style_show_cursor(struct nk_context*);
3480 NK_API void nk_style_hide_cursor(struct nk_context*);
3481 
3482 NK_API nk_bool nk_style_push_font(struct nk_context*, const struct nk_user_font*);
3483 NK_API nk_bool nk_style_push_float(struct nk_context*, float*, float);
3484 NK_API nk_bool nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
3485 NK_API nk_bool nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item);
3486 NK_API nk_bool nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
3487 NK_API nk_bool nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
3488 
3489 NK_API nk_bool nk_style_pop_font(struct nk_context*);
3490 NK_API nk_bool nk_style_pop_float(struct nk_context*);
3491 NK_API nk_bool nk_style_pop_vec2(struct nk_context*);
3492 NK_API nk_bool nk_style_pop_style_item(struct nk_context*);
3493 NK_API nk_bool nk_style_pop_flags(struct nk_context*);
3494 NK_API nk_bool nk_style_pop_color(struct nk_context*);
3495 /* =============================================================================
3496  *
3497  * COLOR
3498  *
3499  * ============================================================================= */
3500 NK_API struct nk_color nk_rgb(int r, int g, int b);
3501 NK_API struct nk_color nk_rgb_iv(const int *rgb);
3502 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
3503 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
3504 NK_API struct nk_color nk_rgb_fv(const float *rgb);
3505 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c);
3506 NK_API struct nk_color nk_rgb_hex(const char *rgb);
3507 NK_API struct nk_color nk_rgb_factor(struct nk_color col, float factor);
3508 
3509 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
3510 NK_API struct nk_color nk_rgba_u32(nk_uint);
3511 NK_API struct nk_color nk_rgba_iv(const int *rgba);
3512 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
3513 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
3514 NK_API struct nk_color nk_rgba_fv(const float *rgba);
3515 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c);
3516 NK_API struct nk_color nk_rgba_hex(const char *rgb);
3517 
3518 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a);
3519 NK_API struct nk_colorf nk_hsva_colorfv(const float *c);
3520 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in);
3521 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in);
3522 
3523 NK_API struct nk_color nk_hsv(int h, int s, int v);
3524 NK_API struct nk_color nk_hsv_iv(const int *hsv);
3525 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
3526 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
3527 NK_API struct nk_color nk_hsv_fv(const float *hsv);
3528 
3529 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
3530 NK_API struct nk_color nk_hsva_iv(const int *hsva);
3531 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
3532 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
3533 NK_API struct nk_color nk_hsva_fv(const float *hsva);
3534 
3535 /* color (conversion nuklear --> user) */
3536 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
3537 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
3538 NK_API struct nk_colorf nk_color_cf(struct nk_color);
3539 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
3540 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
3541 
3542 NK_API nk_uint nk_color_u32(struct nk_color);
3543 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
3544 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
3545 
3546 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
3547 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
3548 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
3549 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
3550 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
3551 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
3552 
3553 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
3554 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
3555 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
3556 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
3557 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
3558 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
3559 /* =============================================================================
3560  *
3561  * IMAGE
3562  *
3563  * ============================================================================= */
3564 NK_API nk_handle nk_handle_ptr(void*);
3565 NK_API nk_handle nk_handle_id(int);
3566 NK_API struct nk_image nk_image_handle(nk_handle);
3567 NK_API struct nk_image nk_image_ptr(void*);
3568 NK_API struct nk_image nk_image_id(int);
3569 NK_API nk_bool nk_image_is_subimage(const struct nk_image* img);
3570 NK_API struct nk_image nk_subimage_ptr(void*, nk_ushort w, nk_ushort h, struct nk_rect sub_region);
3571 NK_API struct nk_image nk_subimage_id(int, nk_ushort w, nk_ushort h, struct nk_rect sub_region);
3572 NK_API struct nk_image nk_subimage_handle(nk_handle, nk_ushort w, nk_ushort h, struct nk_rect sub_region);
3573 /* =============================================================================
3574  *
3575  * 9-SLICE
3576  *
3577  * ============================================================================= */
3578 NK_API struct nk_nine_slice nk_nine_slice_handle(nk_handle, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
3579 NK_API struct nk_nine_slice nk_nine_slice_ptr(void*, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
3580 NK_API struct nk_nine_slice nk_nine_slice_id(int, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
3581 NK_API int nk_nine_slice_is_sub9slice(const struct nk_nine_slice* img);
3582 NK_API struct nk_nine_slice nk_sub9slice_ptr(void*, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
3583 NK_API struct nk_nine_slice nk_sub9slice_id(int, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
3584 NK_API struct nk_nine_slice nk_sub9slice_handle(nk_handle, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b);
3585 /* =============================================================================
3586  *
3587  * MATH
3588  *
3589  * ============================================================================= */
3590 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
3591 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
3592 
3593 NK_API struct nk_vec2 nk_vec2(float x, float y);
3594 NK_API struct nk_vec2 nk_vec2i(int x, int y);
3595 NK_API struct nk_vec2 nk_vec2v(const float *xy);
3596 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
3597 
3598 NK_API struct nk_rect nk_get_null_rect(void);
3599 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
3600 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
3601 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
3602 NK_API struct nk_rect nk_rectv(const float *xywh);
3603 NK_API struct nk_rect nk_rectiv(const int *xywh);
3604 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
3605 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
3606 /* =============================================================================
3607  *
3608  * STRING
3609  *
3610  * ============================================================================= */
3611 NK_API int nk_strlen(const char *str);
3612 NK_API int nk_stricmp(const char *s1, const char *s2);
3613 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
3614 NK_API int nk_strtoi(const char *str, char **endptr);
3615 NK_API float nk_strtof(const char *str, char **endptr);
3616 #ifndef NK_STRTOD
3617 #define NK_STRTOD nk_strtod
3618 NK_API double nk_strtod(const char *str, char **endptr);
3619 #endif
3620 NK_API int nk_strfilter(const char *text, const char *regexp);
3621 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
3622 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
3623 /* =============================================================================
3624  *
3625  * UTF-8
3626  *
3627  * ============================================================================= */
3628 NK_API int nk_utf_decode(const char*, nk_rune*, int);
3629 NK_API int nk_utf_encode(nk_rune, char*, int);
3630 NK_API int nk_utf_len(const char*, int byte_len);
3631 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
3632 /* ===============================================================
3633  *
3634  * FONT
3635  *
3636  * ===============================================================*/
3789 struct nk_user_font_glyph;
3790 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
3791 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
3792  struct nk_user_font_glyph *glyph,
3793  nk_rune codepoint, nk_rune next_codepoint);
3794 
3795 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT)
3796 struct nk_user_font_glyph {
3797  struct nk_vec2 uv[2];
3798  struct nk_vec2 offset;
3799  float width, height;
3800  float xadvance;
3801 };
3802 #endif
3803 
3805  nk_handle userdata;
3806  float height;
3807  nk_text_width_f width;
3808 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3809  nk_query_font_glyph_f query;
3810  nk_handle texture;
3811 #endif
3812 };
3813 
3814 #ifdef NK_INCLUDE_FONT_BAKING
3815 enum nk_font_coord_type {
3816  NK_COORD_UV,
3817  NK_COORD_PIXEL
3818 };
3819 
3820 struct nk_font;
3821 struct nk_baked_font {
3822  float height;
3823  float ascent;
3824  float descent;
3825  nk_rune glyph_offset;
3826  nk_rune glyph_count;
3827  const nk_rune *ranges;
3828 };
3829 
3830 struct nk_font_config {
3831  struct nk_font_config *next;
3832  void *ttf_blob;
3833  nk_size ttf_size;
3835  unsigned char ttf_data_owned_by_atlas;
3836  unsigned char merge_mode;
3837  unsigned char pixel_snap;
3838  unsigned char oversample_v, oversample_h;
3839  unsigned char padding[3];
3840 
3841  float size;
3842  enum nk_font_coord_type coord_type;
3843  struct nk_vec2 spacing;
3844  const nk_rune *range;
3845  struct nk_baked_font *font;
3846  nk_rune fallback_glyph;
3847  struct nk_font_config *n;
3848  struct nk_font_config *p;
3849 };
3850 
3851 struct nk_font_glyph {
3852  nk_rune codepoint;
3853  float xadvance;
3854  float x0, y0, x1, y1, w, h;
3855  float u0, v0, u1, v1;
3856 };
3857 
3858 struct nk_font {
3859  struct nk_font *next;
3860  struct nk_user_font handle;
3861  struct nk_baked_font info;
3862  float scale;
3863  struct nk_font_glyph *glyphs;
3864  const struct nk_font_glyph *fallback;
3865  nk_rune fallback_codepoint;
3866  nk_handle texture;
3867  struct nk_font_config *config;
3868 };
3869 
3870 enum nk_font_atlas_format {
3871  NK_FONT_ATLAS_ALPHA8,
3872  NK_FONT_ATLAS_RGBA32
3873 };
3874 
3875 struct nk_font_atlas {
3876  void *pixel;
3877  int tex_width;
3878  int tex_height;
3879 
3880  struct nk_allocator permanent;
3881  struct nk_allocator temporary;
3882 
3883  struct nk_recti custom;
3884  struct nk_cursor cursors[NK_CURSOR_COUNT];
3885 
3886  int glyph_count;
3887  struct nk_font_glyph *glyphs;
3888  struct nk_font *default_font;
3889  struct nk_font *fonts;
3890  struct nk_font_config *config;
3891  int font_num;
3892 };
3893 
3895 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
3896 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
3897 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
3898 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
3899 
3900 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
3901 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
3902 #endif
3903 NK_API void nk_font_atlas_init(struct nk_font_atlas*, const struct nk_allocator*);
3904 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, const struct nk_allocator *persistent, const struct nk_allocator *transient);
3905 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
3906 NK_API struct nk_font_config nk_font_config(float pixel_height);
3907 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
3908 #ifdef NK_INCLUDE_DEFAULT_FONT
3909 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
3910 #endif
3911 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);
3912 #ifdef NK_INCLUDE_STANDARD_IO
3913 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*);
3914 #endif
3915 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*);
3916 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);
3917 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
3918 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
3919 NK_API const struct nk_font_glyph* nk_font_find_glyph(const struct nk_font*, nk_rune unicode);
3920 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
3921 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
3922 
3923 #endif
3924 
3962  void *memory;
3963  unsigned int type;
3964  nk_size size;
3965  nk_size allocated;
3966  nk_size needed;
3967  nk_size calls;
3968 };
3969 
3970 enum nk_allocation_type {
3971  NK_BUFFER_FIXED,
3972  NK_BUFFER_DYNAMIC
3973 };
3974 
3975 enum nk_buffer_allocation_type {
3976  NK_BUFFER_FRONT,
3977  NK_BUFFER_BACK,
3978  NK_BUFFER_MAX
3979 };
3980 
3982  nk_bool active;
3983  nk_size offset;
3984 };
3985 
3986 struct nk_memory {void *ptr;nk_size size;};
3987 struct nk_buffer {
3988  struct nk_buffer_marker marker[NK_BUFFER_MAX];
3989  struct nk_allocator pool;
3990  enum nk_allocation_type type;
3991  struct nk_memory memory;
3992  float grow_factor;
3993  nk_size allocated;
3994  nk_size needed;
3995  nk_size calls;
3996  nk_size size;
3997 };
3998 
3999 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4000 NK_API void nk_buffer_init_default(struct nk_buffer*);
4001 #endif
4002 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
4003 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
4004 NK_API void nk_buffer_info(struct nk_memory_status*, const struct nk_buffer*);
4005 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
4006 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
4007 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type);
4008 NK_API void nk_buffer_clear(struct nk_buffer*);
4009 NK_API void nk_buffer_free(struct nk_buffer*);
4010 NK_API void *nk_buffer_memory(struct nk_buffer*);
4011 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
4012 NK_API nk_size nk_buffer_total(const struct nk_buffer*);
4013 
4024 struct nk_str {
4025  struct nk_buffer buffer;
4026  int len;
4027 };
4028 
4029 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4030 NK_API void nk_str_init_default(struct nk_str*);
4031 #endif
4032 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
4033 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
4034 NK_API void nk_str_clear(struct nk_str*);
4035 NK_API void nk_str_free(struct nk_str*);
4036 
4037 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
4038 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
4039 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
4040 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
4041 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
4042 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
4043 
4044 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
4045 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
4046 
4047 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
4048 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
4049 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
4050 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
4051 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
4052 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
4053 
4054 NK_API void nk_str_remove_chars(struct nk_str*, int len);
4055 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
4056 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
4057 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
4058 
4059 NK_API char *nk_str_at_char(struct nk_str*, int pos);
4060 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
4061 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
4062 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
4063 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
4064 
4065 NK_API char *nk_str_get(struct nk_str*);
4066 NK_API const char *nk_str_get_const(const struct nk_str*);
4067 NK_API int nk_str_len(const struct nk_str*);
4068 NK_API int nk_str_len_char(const struct nk_str*);
4069 
4101 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
4102 #define NK_TEXTEDIT_UNDOSTATECOUNT 99
4103 #endif
4104 
4105 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
4106 #define NK_TEXTEDIT_UNDOCHARCOUNT 999
4107 #endif
4108 
4109 struct nk_text_edit;
4111  nk_handle userdata;
4112  nk_plugin_paste paste;
4113  nk_plugin_copy copy;
4114 };
4115 
4117  int where;
4118  short insert_length;
4119  short delete_length;
4120  short char_storage;
4121 };
4122 
4124  struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT];
4125  nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT];
4126  short undo_point;
4127  short redo_point;
4128  short undo_char_point;
4129  short redo_char_point;
4130 };
4131 
4132 enum nk_text_edit_type {
4133  NK_TEXT_EDIT_SINGLE_LINE,
4134  NK_TEXT_EDIT_MULTI_LINE
4135 };
4136 
4137 enum nk_text_edit_mode {
4138  NK_TEXT_EDIT_MODE_VIEW,
4139  NK_TEXT_EDIT_MODE_INSERT,
4140  NK_TEXT_EDIT_MODE_REPLACE
4141 };
4142 
4144  struct nk_clipboard clip;
4145  struct nk_str string;
4146  nk_plugin_filter filter;
4147  struct nk_vec2 scrollbar;
4148 
4149  int cursor;
4150  int select_start;
4151  int select_end;
4152  unsigned char mode;
4153  unsigned char cursor_at_end_of_line;
4154  unsigned char initialized;
4155  unsigned char has_preferred_x;
4156  unsigned char single_line;
4157  unsigned char active;
4158  unsigned char padding1;
4159  float preferred_x;
4160  struct nk_text_undo_state undo;
4161 };
4162 
4164 NK_API nk_bool nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
4165 NK_API nk_bool nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
4166 NK_API nk_bool nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
4167 NK_API nk_bool nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
4168 NK_API nk_bool nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
4169 NK_API nk_bool nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
4170 NK_API nk_bool nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
4171 
4173 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4174 NK_API void nk_textedit_init_default(struct nk_text_edit*);
4175 #endif
4176 NK_API void nk_textedit_init(struct nk_text_edit*, const struct nk_allocator*, nk_size size);
4177 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
4178 NK_API void nk_textedit_free(struct nk_text_edit*);
4179 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
4180 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
4181 NK_API void nk_textedit_delete_selection(struct nk_text_edit*);
4182 NK_API void nk_textedit_select_all(struct nk_text_edit*);
4183 NK_API nk_bool nk_textedit_cut(struct nk_text_edit*);
4184 NK_API nk_bool nk_textedit_paste(struct nk_text_edit*, char const*, int len);
4185 NK_API void nk_textedit_undo(struct nk_text_edit*);
4186 NK_API void nk_textedit_redo(struct nk_text_edit*);
4187 
4188 /* ===============================================================
4189  *
4190  * DRAWING
4191  *
4192  * ===============================================================*/
4242 enum nk_command_type {
4243  NK_COMMAND_NOP,
4244  NK_COMMAND_SCISSOR,
4245  NK_COMMAND_LINE,
4246  NK_COMMAND_CURVE,
4247  NK_COMMAND_RECT,
4248  NK_COMMAND_RECT_FILLED,
4249  NK_COMMAND_RECT_MULTI_COLOR,
4250  NK_COMMAND_CIRCLE,
4251  NK_COMMAND_CIRCLE_FILLED,
4252  NK_COMMAND_ARC,
4253  NK_COMMAND_ARC_FILLED,
4254  NK_COMMAND_TRIANGLE,
4255  NK_COMMAND_TRIANGLE_FILLED,
4256  NK_COMMAND_POLYGON,
4257  NK_COMMAND_POLYGON_FILLED,
4258  NK_COMMAND_POLYLINE,
4259  NK_COMMAND_TEXT,
4260  NK_COMMAND_IMAGE,
4261  NK_COMMAND_CUSTOM
4262 };
4263 
4265 struct nk_command {
4266  enum nk_command_type type;
4267  nk_size next;
4268 #ifdef NK_INCLUDE_COMMAND_USERDATA
4269  nk_handle userdata;
4270 #endif
4271 };
4272 
4274  struct nk_command header;
4275  short x, y;
4276  unsigned short w, h;
4277 };
4278 
4280  struct nk_command header;
4281  unsigned short line_thickness;
4282  struct nk_vec2i begin;
4283  struct nk_vec2i end;
4284  struct nk_color color;
4285 };
4286 
4288  struct nk_command header;
4289  unsigned short line_thickness;
4290  struct nk_vec2i begin;
4291  struct nk_vec2i end;
4292  struct nk_vec2i ctrl[2];
4293  struct nk_color color;
4294 };
4295 
4297  struct nk_command header;
4298  unsigned short rounding;
4299  unsigned short line_thickness;
4300  short x, y;
4301  unsigned short w, h;
4302  struct nk_color color;
4303 };
4304 
4306  struct nk_command header;
4307  unsigned short rounding;
4308  short x, y;
4309  unsigned short w, h;
4310  struct nk_color color;
4311 };
4312 
4314  struct nk_command header;
4315  short x, y;
4316  unsigned short w, h;
4317  struct nk_color left;
4318  struct nk_color top;
4319  struct nk_color bottom;
4320  struct nk_color right;
4321 };
4322 
4324  struct nk_command header;
4325  unsigned short line_thickness;
4326  struct nk_vec2i a;
4327  struct nk_vec2i b;
4328  struct nk_vec2i c;
4329  struct nk_color color;
4330 };
4331 
4333  struct nk_command header;
4334  struct nk_vec2i a;
4335  struct nk_vec2i b;
4336  struct nk_vec2i c;
4337  struct nk_color color;
4338 };
4339 
4341  struct nk_command header;
4342  short x, y;
4343  unsigned short line_thickness;
4344  unsigned short w, h;
4345  struct nk_color color;
4346 };
4347 
4349  struct nk_command header;
4350  short x, y;
4351  unsigned short w, h;
4352  struct nk_color color;
4353 };
4354 
4356  struct nk_command header;
4357  short cx, cy;
4358  unsigned short r;
4359  unsigned short line_thickness;
4360  float a[2];
4361  struct nk_color color;
4362 };
4363 
4365  struct nk_command header;
4366  short cx, cy;
4367  unsigned short r;
4368  float a[2];
4369  struct nk_color color;
4370 };
4371 
4373  struct nk_command header;
4374  struct nk_color color;
4375  unsigned short line_thickness;
4376  unsigned short point_count;
4377  struct nk_vec2i points[1];
4378 };
4379 
4381  struct nk_command header;
4382  struct nk_color color;
4383  unsigned short point_count;
4384  struct nk_vec2i points[1];
4385 };
4386 
4388  struct nk_command header;
4389  struct nk_color color;
4390  unsigned short line_thickness;
4391  unsigned short point_count;
4392  struct nk_vec2i points[1];
4393 };
4394 
4396  struct nk_command header;
4397  short x, y;
4398  unsigned short w, h;
4399  struct nk_image img;
4400  struct nk_color col;
4401 };
4402 
4403 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
4404  unsigned short w, unsigned short h, nk_handle callback_data);
4406  struct nk_command header;
4407  short x, y;
4408  unsigned short w, h;
4409  nk_handle callback_data;
4410  nk_command_custom_callback callback;
4411 };
4412 
4414  struct nk_command header;
4415  const struct nk_user_font *font;
4416  struct nk_color background;
4417  struct nk_color foreground;
4418  short x, y;
4419  unsigned short w, h;
4420  float height;
4421  int length;
4422  char string[1];
4423 };
4424 
4425 enum nk_command_clipping {
4426  NK_CLIPPING_OFF = nk_false,
4427  NK_CLIPPING_ON = nk_true
4428 };
4429 
4431  struct nk_buffer *base;
4432  struct nk_rect clip;
4433  int use_clipping;
4434  nk_handle userdata;
4435  nk_size begin, end, last;
4436 };
4437 
4439 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);
4440 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
4441 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
4442 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
4443 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);
4444 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
4445 NK_API void nk_stroke_polyline(struct nk_command_buffer*, const float *points, int point_count, float line_thickness, struct nk_color col);
4446 NK_API void nk_stroke_polygon(struct nk_command_buffer*, const float *points, int point_count, float line_thickness, struct nk_color);
4447 
4449 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
4450 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);
4451 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
4452 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);
4453 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);
4454 NK_API void nk_fill_polygon(struct nk_command_buffer*, const float *points, int point_count, struct nk_color);
4455 
4457 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
4458 NK_API void nk_draw_nine_slice(struct nk_command_buffer*, struct nk_rect, const struct nk_nine_slice*, struct nk_color);
4459 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);
4460 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
4461 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
4462 
4463 /* ===============================================================
4464  *
4465  * INPUT
4466  *
4467  * ===============================================================*/
4469  nk_bool down;
4470  unsigned int clicked;
4471  struct nk_vec2 clicked_pos;
4472 };
4473 struct nk_mouse {
4474  struct nk_mouse_button buttons[NK_BUTTON_MAX];
4475  struct nk_vec2 pos;
4476 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
4477  struct nk_vec2 down_pos;
4478 #endif
4479  struct nk_vec2 prev;
4480  struct nk_vec2 delta;
4481  struct nk_vec2 scroll_delta;
4482  unsigned char grab;
4483  unsigned char grabbed;
4484  unsigned char ungrab;
4485 };
4486 
4487 struct nk_key {
4488  nk_bool down;
4489  unsigned int clicked;
4490 };
4491 struct nk_keyboard {
4492  struct nk_key keys[NK_KEY_MAX];
4493  char text[NK_INPUT_MAX];
4494  int text_len;
4495 };
4496 
4497 struct nk_input {
4498  struct nk_keyboard keyboard;
4499  struct nk_mouse mouse;
4500 };
4501 
4502 NK_API nk_bool nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
4503 NK_API nk_bool nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4504 NK_API nk_bool nk_input_has_mouse_click_in_button_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4505 NK_API nk_bool nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, nk_bool down);
4506 NK_API nk_bool nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
4507 NK_API nk_bool nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, nk_bool down);
4508 NK_API nk_bool nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
4509 NK_API nk_bool nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
4510 NK_API nk_bool nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
4511 NK_API nk_bool nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
4512 NK_API nk_bool nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
4513 NK_API nk_bool nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
4514 NK_API nk_bool nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
4515 NK_API nk_bool nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
4516 NK_API nk_bool nk_input_is_key_released(const struct nk_input*, enum nk_keys);
4517 NK_API nk_bool nk_input_is_key_down(const struct nk_input*, enum nk_keys);
4518 
4519 /* ===============================================================
4520  *
4521  * DRAW LIST
4522  *
4523  * ===============================================================*/
4524 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4541 #ifdef NK_UINT_DRAW_INDEX
4542 typedef nk_uint nk_draw_index;
4543 #else
4544 typedef nk_ushort nk_draw_index;
4545 #endif
4546 enum nk_draw_list_stroke {
4547  NK_STROKE_OPEN = nk_false, /***< build up path has no connection back to the beginning */
4548  NK_STROKE_CLOSED = nk_true /***< build up path has a connection back to the beginning */
4549 };
4550 
4551 enum nk_draw_vertex_layout_attribute {
4552  NK_VERTEX_POSITION,
4553  NK_VERTEX_COLOR,
4554  NK_VERTEX_TEXCOORD,
4555  NK_VERTEX_ATTRIBUTE_COUNT
4556 };
4557 
4558 enum nk_draw_vertex_layout_format {
4559  NK_FORMAT_SCHAR,
4560  NK_FORMAT_SSHORT,
4561  NK_FORMAT_SINT,
4562  NK_FORMAT_UCHAR,
4563  NK_FORMAT_USHORT,
4564  NK_FORMAT_UINT,
4565  NK_FORMAT_FLOAT,
4566  NK_FORMAT_DOUBLE,
4567 
4568 NK_FORMAT_COLOR_BEGIN,
4569  NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
4570  NK_FORMAT_R16G15B16,
4571  NK_FORMAT_R32G32B32,
4572 
4573  NK_FORMAT_R8G8B8A8,
4574  NK_FORMAT_B8G8R8A8,
4575  NK_FORMAT_R16G15B16A16,
4576  NK_FORMAT_R32G32B32A32,
4577  NK_FORMAT_R32G32B32A32_FLOAT,
4578  NK_FORMAT_R32G32B32A32_DOUBLE,
4579 
4580  NK_FORMAT_RGB32,
4581  NK_FORMAT_RGBA32,
4582 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
4583  NK_FORMAT_COUNT
4584 };
4585 
4586 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
4587 struct nk_draw_vertex_layout_element {
4588  enum nk_draw_vertex_layout_attribute attribute;
4589  enum nk_draw_vertex_layout_format format;
4590  nk_size offset;
4591 };
4592 
4593 struct nk_draw_command {
4594  unsigned int elem_count;
4595  struct nk_rect clip_rect;
4596  nk_handle texture;
4597 #ifdef NK_INCLUDE_COMMAND_USERDATA
4598  nk_handle userdata;
4599 #endif
4600 };
4601 
4602 struct nk_draw_list {
4603  struct nk_rect clip_rect;
4604  struct nk_vec2 circle_vtx[12];
4605  struct nk_convert_config config;
4606 
4607  struct nk_buffer *buffer;
4608  struct nk_buffer *vertices;
4609  struct nk_buffer *elements;
4610 
4611  unsigned int element_count;
4612  unsigned int vertex_count;
4613  unsigned int cmd_count;
4614  nk_size cmd_offset;
4615 
4616  unsigned int path_count;
4617  unsigned int path_offset;
4618 
4619  enum nk_anti_aliasing line_AA;
4620  enum nk_anti_aliasing shape_AA;
4621 
4622 #ifdef NK_INCLUDE_COMMAND_USERDATA
4623  nk_handle userdata;
4624 #endif
4625 };
4626 
4627 /* draw list */
4628 NK_API void nk_draw_list_init(struct nk_draw_list*);
4629 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);
4630 
4631 /* drawing */
4632 #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))
4633 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
4634 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*);
4635 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
4636 
4637 /* path */
4638 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
4639 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
4640 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);
4641 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);
4642 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
4643 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);
4644 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
4645 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
4646 
4647 /* stroke */
4648 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);
4649 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
4650 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);
4651 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);
4652 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);
4653 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);
4654 
4655 /* fill */
4656 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
4657 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);
4658 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);
4659 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);
4660 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);
4661 
4662 /* misc */
4663 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
4664 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);
4665 #ifdef NK_INCLUDE_COMMAND_USERDATA
4666 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
4667 #endif
4668 
4669 #endif
4670 
4671 /* ===============================================================
4672  *
4673  * GUI
4674  *
4675  * ===============================================================*/
4676 enum nk_style_item_type {
4677  NK_STYLE_ITEM_COLOR,
4678  NK_STYLE_ITEM_IMAGE,
4679  NK_STYLE_ITEM_NINE_SLICE
4680 };
4681 
4683  struct nk_color color;
4684  struct nk_image image;
4685  struct nk_nine_slice slice;
4686 };
4687 
4689  enum nk_style_item_type type;
4690  union nk_style_item_data data;
4691 };
4692 
4694  struct nk_color color;
4695  struct nk_vec2 padding;
4696  float color_factor;
4697  float disabled_factor;
4698 };
4699 
4701  /* background */
4702  struct nk_style_item normal;
4703  struct nk_style_item hover;
4704  struct nk_style_item active;
4705  struct nk_color border_color;
4706  float color_factor_background;
4707 
4708  /* text */
4709  struct nk_color text_background;
4710  struct nk_color text_normal;
4711  struct nk_color text_hover;
4712  struct nk_color text_active;
4713  nk_flags text_alignment;
4714  float color_factor_text;
4715 
4716  /* properties */
4717  float border;
4718  float rounding;
4719  struct nk_vec2 padding;
4720  struct nk_vec2 image_padding;
4721  struct nk_vec2 touch_padding;
4722  float disabled_factor;
4723 
4724  /* optional user callbacks */
4725  nk_handle userdata;
4726  void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata);
4727  void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
4728 };
4729 
4731  /* background */
4732  struct nk_style_item normal;
4733  struct nk_style_item hover;
4734  struct nk_style_item active;
4735  struct nk_color border_color;
4736 
4737  /* cursor */
4738  struct nk_style_item cursor_normal;
4739  struct nk_style_item cursor_hover;
4740 
4741  /* text */
4742  struct nk_color text_normal;
4743  struct nk_color text_hover;
4744  struct nk_color text_active;
4745  struct nk_color text_background;
4746  nk_flags text_alignment;
4747 
4748  /* properties */
4749  struct nk_vec2 padding;
4750  struct nk_vec2 touch_padding;
4751  float spacing;
4752  float border;
4753  float color_factor;
4754  float disabled_factor;
4755 
4756  /* optional user callbacks */
4757  nk_handle userdata;
4758  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4759  void(*draw_end)(struct nk_command_buffer*, nk_handle);
4760 };
4761 
4763  /* background (inactive) */
4764  struct nk_style_item normal;
4765  struct nk_style_item hover;
4766  struct nk_style_item pressed;
4767 
4768  /* background (active) */
4769  struct nk_style_item normal_active;
4770  struct nk_style_item hover_active;
4771  struct nk_style_item pressed_active;
4772 
4773  /* text color (inactive) */
4774  struct nk_color text_normal;
4775  struct nk_color text_hover;
4776  struct nk_color text_pressed;
4777 
4778  /* text color (active) */
4779  struct nk_color text_normal_active;
4780  struct nk_color text_hover_active;
4781  struct nk_color text_pressed_active;
4782  struct nk_color text_background;
4783  nk_flags text_alignment;
4784 
4785  /* properties */
4786  float rounding;
4787  struct nk_vec2 padding;
4788  struct nk_vec2 touch_padding;
4789  struct nk_vec2 image_padding;
4790  float color_factor;
4791  float disabled_factor;
4792 
4793  /* optional user callbacks */
4794  nk_handle userdata;
4795  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4796  void(*draw_end)(struct nk_command_buffer*, nk_handle);
4797 };
4798 
4800  /* background */
4801  struct nk_style_item normal;
4802  struct nk_style_item hover;
4803  struct nk_style_item active;
4804  struct nk_color border_color;
4805 
4806  /* background bar */
4807  struct nk_color bar_normal;
4808  struct nk_color bar_hover;
4809  struct nk_color bar_active;
4810  struct nk_color bar_filled;
4811 
4812  /* cursor */
4813  struct nk_style_item cursor_normal;
4814  struct nk_style_item cursor_hover;
4815  struct nk_style_item cursor_active;
4816 
4817  /* properties */
4818  float border;
4819  float rounding;
4820  float bar_height;
4821  struct nk_vec2 padding;
4822  struct nk_vec2 spacing;
4823  struct nk_vec2 cursor_size;
4824  float color_factor;
4825  float disabled_factor;
4826 
4827  /* optional buttons */
4828  int show_buttons;
4829  struct nk_style_button inc_button;
4830  struct nk_style_button dec_button;
4831  enum nk_symbol_type inc_symbol;
4832  enum nk_symbol_type dec_symbol;
4833 
4834  /* optional user callbacks */
4835  nk_handle userdata;
4836  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4837  void(*draw_end)(struct nk_command_buffer*, nk_handle);
4838 };
4839 
4841  /* background */
4842  struct nk_style_item normal;
4843  struct nk_style_item hover;
4844  struct nk_style_item active;
4845  struct nk_color border_color;
4846 
4847  /* knob */
4848  struct nk_color knob_normal;
4849  struct nk_color knob_hover;
4850  struct nk_color knob_active;
4851  struct nk_color knob_border_color;
4852 
4853  /* cursor */
4854  struct nk_color cursor_normal;
4855  struct nk_color cursor_hover;
4856  struct nk_color cursor_active;
4857 
4858  /* properties */
4859  float border;
4860  float knob_border;
4861  struct nk_vec2 padding;
4862  struct nk_vec2 spacing;
4863  float cursor_width;
4864  float color_factor;
4865  float disabled_factor;
4866 
4867  /* optional user callbacks */
4868  nk_handle userdata;
4869  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4870  void(*draw_end)(struct nk_command_buffer*, nk_handle);
4871 };
4872 
4874  /* background */
4875  struct nk_style_item normal;
4876  struct nk_style_item hover;
4877  struct nk_style_item active;
4878  struct nk_color border_color;
4879 
4880  /* cursor */
4881  struct nk_style_item cursor_normal;
4882  struct nk_style_item cursor_hover;
4883  struct nk_style_item cursor_active;
4884  struct nk_color cursor_border_color;
4885 
4886  /* properties */
4887  float rounding;
4888  float border;
4889  float cursor_border;
4890  float cursor_rounding;
4891  struct nk_vec2 padding;
4892  float color_factor;
4893  float disabled_factor;
4894 
4895  /* optional user callbacks */
4896  nk_handle userdata;
4897  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4898  void(*draw_end)(struct nk_command_buffer*, nk_handle);
4899 };
4900 
4902  /* background */
4903  struct nk_style_item normal;
4904  struct nk_style_item hover;
4905  struct nk_style_item active;
4906  struct nk_color border_color;
4907 
4908  /* cursor */
4909  struct nk_style_item cursor_normal;
4910  struct nk_style_item cursor_hover;
4911  struct nk_style_item cursor_active;
4912  struct nk_color cursor_border_color;
4913 
4914  /* properties */
4915  float border;
4916  float rounding;
4917  float border_cursor;
4918  float rounding_cursor;
4919  struct nk_vec2 padding;
4920  float color_factor;
4921  float disabled_factor;
4922 
4923  /* optional buttons */
4924  int show_buttons;
4925  struct nk_style_button inc_button;
4926  struct nk_style_button dec_button;
4927  enum nk_symbol_type inc_symbol;
4928  enum nk_symbol_type dec_symbol;
4929 
4930  /* optional user callbacks */
4931  nk_handle userdata;
4932  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
4933  void(*draw_end)(struct nk_command_buffer*, nk_handle);
4934 };
4935 
4937  /* background */
4938  struct nk_style_item normal;
4939  struct nk_style_item hover;
4940  struct nk_style_item active;
4941  struct nk_color border_color;
4942  struct nk_style_scrollbar scrollbar;
4943 
4944  /* cursor */
4945  struct nk_color cursor_normal;
4946  struct nk_color cursor_hover;
4947  struct nk_color cursor_text_normal;
4948  struct nk_color cursor_text_hover;
4949 
4950  /* text (unselected) */
4951  struct nk_color text_normal;
4952  struct nk_color text_hover;
4953  struct nk_color text_active;
4954 
4955  /* text (selected) */
4956  struct nk_color selected_normal;
4957  struct nk_color selected_hover;
4958  struct nk_color selected_text_normal;
4959  struct nk_color selected_text_hover;
4960 
4961  /* properties */
4962  float border;
4963  float rounding;
4964  float cursor_size;
4965  struct nk_vec2 scrollbar_size;
4966  struct nk_vec2 padding;
4967  float row_padding;
4968  float color_factor;
4969  float disabled_factor;
4970 };
4971 
4973  /* background */
4974  struct nk_style_item normal;
4975  struct nk_style_item hover;
4976  struct nk_style_item active;
4977  struct nk_color border_color;
4978 
4979  /* text */
4980  struct nk_color label_normal;
4981  struct nk_color label_hover;
4982  struct nk_color label_active;
4983 
4984  /* symbols */
4985  enum nk_symbol_type sym_left;
4986  enum nk_symbol_type sym_right;
4987 
4988  /* properties */
4989  float border;
4990  float rounding;
4991  struct nk_vec2 padding;
4992  float color_factor;
4993  float disabled_factor;
4994 
4995  struct nk_style_edit edit;
4996  struct nk_style_button inc_button;
4997  struct nk_style_button dec_button;
4998 
4999  /* optional user callbacks */
5000  nk_handle userdata;
5001  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
5002  void(*draw_end)(struct nk_command_buffer*, nk_handle);
5003 };
5004 
5006  /* colors */
5007  struct nk_style_item background;
5008  struct nk_color border_color;
5009  struct nk_color selected_color;
5010  struct nk_color color;
5011 
5012  /* properties */
5013  float border;
5014  float rounding;
5015  struct nk_vec2 padding;
5016  float color_factor;
5017  float disabled_factor;
5018  nk_bool show_markers;
5019 };
5020 
5022  /* background */
5023  struct nk_style_item normal;
5024  struct nk_style_item hover;
5025  struct nk_style_item active;
5026  struct nk_color border_color;
5027 
5028  /* label */
5029  struct nk_color label_normal;
5030  struct nk_color label_hover;
5031  struct nk_color label_active;
5032 
5033  /* symbol */
5034  struct nk_color symbol_normal;
5035  struct nk_color symbol_hover;
5036  struct nk_color symbol_active;
5037 
5038  /* button */
5039  struct nk_style_button button;
5040  enum nk_symbol_type sym_normal;
5041  enum nk_symbol_type sym_hover;
5042  enum nk_symbol_type sym_active;
5043 
5044  /* properties */
5045  float border;
5046  float rounding;
5047  struct nk_vec2 content_padding;
5048  struct nk_vec2 button_padding;
5049  struct nk_vec2 spacing;
5050  float color_factor;
5051  float disabled_factor;
5052 };
5053 
5055  /* background */
5056  struct nk_style_item background;
5057  struct nk_color border_color;
5058  struct nk_color text;
5059 
5060  /* button */
5061  struct nk_style_button tab_maximize_button;
5062  struct nk_style_button tab_minimize_button;
5063  struct nk_style_button node_maximize_button;
5064  struct nk_style_button node_minimize_button;
5065  enum nk_symbol_type sym_minimize;
5066  enum nk_symbol_type sym_maximize;
5067 
5068  /* properties */
5069  float border;
5070  float rounding;
5071  float indent;
5072  struct nk_vec2 padding;
5073  struct nk_vec2 spacing;
5074  float color_factor;
5075  float disabled_factor;
5076 };
5077 
5078 enum nk_style_header_align {
5079  NK_HEADER_LEFT,
5080  NK_HEADER_RIGHT
5081 };
5083  /* background */
5084  struct nk_style_item normal;
5085  struct nk_style_item hover;
5086  struct nk_style_item active;
5087 
5088  /* button */
5089  struct nk_style_button close_button;
5090  struct nk_style_button minimize_button;
5091  enum nk_symbol_type close_symbol;
5092  enum nk_symbol_type minimize_symbol;
5093  enum nk_symbol_type maximize_symbol;
5094 
5095  /* title */
5096  struct nk_color label_normal;
5097  struct nk_color label_hover;
5098  struct nk_color label_active;
5099 
5100  /* properties */
5101  enum nk_style_header_align align;
5102  struct nk_vec2 padding;
5103  struct nk_vec2 label_padding;
5104  struct nk_vec2 spacing;
5105 };
5106 
5108  struct nk_style_window_header header;
5109  struct nk_style_item fixed_background;
5110  struct nk_color background;
5111 
5112  struct nk_color border_color;
5113  struct nk_color popup_border_color;
5114  struct nk_color combo_border_color;
5115  struct nk_color contextual_border_color;
5116  struct nk_color menu_border_color;
5117  struct nk_color group_border_color;
5118  struct nk_color tooltip_border_color;
5119  struct nk_style_item scaler;
5120 
5121  float border;
5122  float combo_border;
5123  float contextual_border;
5124  float menu_border;
5125  float group_border;
5126  float tooltip_border;
5127  float popup_border;
5128  float min_row_height_padding;
5129 
5130  float rounding;
5131  struct nk_vec2 spacing;
5132  struct nk_vec2 scrollbar_size;
5133  struct nk_vec2 min_size;
5134 
5135  struct nk_vec2 padding;
5136  struct nk_vec2 group_padding;
5137  struct nk_vec2 popup_padding;
5138  struct nk_vec2 combo_padding;
5139  struct nk_vec2 contextual_padding;
5140  struct nk_vec2 menu_padding;
5141  struct nk_vec2 tooltip_padding;
5142 };
5143 
5144 struct nk_style {
5145  const struct nk_user_font *font;
5146  const struct nk_cursor *cursors[NK_CURSOR_COUNT];
5147  const struct nk_cursor *cursor_active;
5148  struct nk_cursor *cursor_last;
5149  int cursor_visible;
5150 
5151  struct nk_style_text text;
5152  struct nk_style_button button;
5153  struct nk_style_button contextual_button;
5154  struct nk_style_button menu_button;
5155  struct nk_style_toggle option;
5156  struct nk_style_toggle checkbox;
5157  struct nk_style_selectable selectable;
5158  struct nk_style_slider slider;
5159  struct nk_style_knob knob;
5160  struct nk_style_progress progress;
5161  struct nk_style_property property;
5162  struct nk_style_edit edit;
5163  struct nk_style_chart chart;
5164  struct nk_style_scrollbar scrollh;
5165  struct nk_style_scrollbar scrollv;
5166  struct nk_style_tab tab;
5167  struct nk_style_combo combo;
5168  struct nk_style_window window;
5169 };
5170 
5171 NK_API struct nk_style_item nk_style_item_color(struct nk_color);
5172 NK_API struct nk_style_item nk_style_item_image(struct nk_image img);
5173 NK_API struct nk_style_item nk_style_item_nine_slice(struct nk_nine_slice slice);
5174 NK_API struct nk_style_item nk_style_item_hide(void);
5175 
5176 /*==============================================================
5177  * PANEL
5178  * =============================================================*/
5179 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
5180 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
5181 #endif
5182 #ifndef NK_CHART_MAX_SLOT
5183 #define NK_CHART_MAX_SLOT 4
5184 #endif
5185 
5186 enum nk_panel_type {
5187  NK_PANEL_NONE = 0,
5188  NK_PANEL_WINDOW = NK_FLAG(0),
5189  NK_PANEL_GROUP = NK_FLAG(1),
5190  NK_PANEL_POPUP = NK_FLAG(2),
5191  NK_PANEL_CONTEXTUAL = NK_FLAG(4),
5192  NK_PANEL_COMBO = NK_FLAG(5),
5193  NK_PANEL_MENU = NK_FLAG(6),
5194  NK_PANEL_TOOLTIP = NK_FLAG(7)
5195 };
5196 enum nk_panel_set {
5197  NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP,
5198  NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP,
5199  NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP
5200 };
5201 
5203  enum nk_chart_type type;
5204  struct nk_color color;
5205  struct nk_color highlight;
5206  float min, max, range;
5207  int count;
5208  struct nk_vec2 last;
5209  int index;
5210  nk_bool show_markers;
5211 };
5212 
5213 struct nk_chart {
5214  int slot;
5215  float x, y, w, h;
5216  struct nk_chart_slot slots[NK_CHART_MAX_SLOT];
5217 };
5218 
5219 enum nk_panel_row_layout_type {
5220  NK_LAYOUT_DYNAMIC_FIXED = 0,
5221  NK_LAYOUT_DYNAMIC_ROW,
5222  NK_LAYOUT_DYNAMIC_FREE,
5223  NK_LAYOUT_DYNAMIC,
5224  NK_LAYOUT_STATIC_FIXED,
5225  NK_LAYOUT_STATIC_ROW,
5226  NK_LAYOUT_STATIC_FREE,
5227  NK_LAYOUT_STATIC,
5228  NK_LAYOUT_TEMPLATE,
5229  NK_LAYOUT_COUNT
5230 };
5232  enum nk_panel_row_layout_type type;
5233  int index;
5234  float height;
5235  float min_height;
5236  int columns;
5237  const float *ratio;
5238  float item_width;
5239  float item_height;
5240  float item_offset;
5241  float filled;
5242  struct nk_rect item;
5243  int tree_depth;
5244  float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS];
5245 };
5246 
5248  nk_size begin;
5249  nk_size parent;
5250  nk_size last;
5251  nk_size end;
5252  nk_bool active;
5253 };
5254 
5256  float x, y, w, h;
5257  struct nk_scroll offset;
5258 };
5259 
5260 struct nk_panel {
5261  enum nk_panel_type type;
5262  nk_flags flags;
5263  struct nk_rect bounds;
5264  nk_uint *offset_x;
5265  nk_uint *offset_y;
5266  float at_x, at_y, max_x;
5267  float footer_height;
5268  float header_height;
5269  float border;
5270  unsigned int has_scrolling;
5271  struct nk_rect clip;
5272  struct nk_menu_state menu;
5273  struct nk_row_layout row;
5274  struct nk_chart chart;
5275  struct nk_command_buffer *buffer;
5276  struct nk_panel *parent;
5277 };
5278 
5279 /*==============================================================
5280  * WINDOW
5281  * =============================================================*/
5282 #ifndef NK_WINDOW_MAX_NAME
5283 #define NK_WINDOW_MAX_NAME 64
5284 #endif
5285 
5286 struct nk_table;
5288  NK_WINDOW_PRIVATE = NK_FLAG(11),
5289  NK_WINDOW_DYNAMIC = NK_WINDOW_PRIVATE,
5290  NK_WINDOW_ROM = NK_FLAG(12),
5292  NK_WINDOW_HIDDEN = NK_FLAG(13),
5293  NK_WINDOW_CLOSED = NK_FLAG(14),
5294  NK_WINDOW_MINIMIZED = NK_FLAG(15),
5295  NK_WINDOW_REMOVE_ROM = NK_FLAG(16)
5296 };
5297 
5299  struct nk_window *win;
5300  enum nk_panel_type type;
5301  struct nk_popup_buffer buf;
5302  nk_hash name;
5303  nk_bool active;
5304  unsigned combo_count;
5305  unsigned con_count, con_old;
5306  unsigned active_con;
5307  struct nk_rect header;
5308 };
5309 
5311  nk_hash name;
5312  unsigned int seq;
5313  unsigned int old;
5314  int active, prev;
5315  int cursor;
5316  int sel_start;
5317  int sel_end;
5318  struct nk_scroll scrollbar;
5319  unsigned char mode;
5320  unsigned char single_line;
5321 };
5322 
5324  int active, prev;
5325  char buffer[NK_MAX_NUMBER_BUFFER];
5326  int length;
5327  int cursor;
5328  int select_start;
5329  int select_end;
5330  nk_hash name;
5331  unsigned int seq;
5332  unsigned int old;
5333  int state;
5334 };
5335 
5336 struct nk_window {
5337  unsigned int seq;
5338  nk_hash name;
5339  char name_string[NK_WINDOW_MAX_NAME];
5340  nk_flags flags;
5341 
5342  struct nk_rect bounds;
5343  struct nk_scroll scrollbar;
5344  struct nk_command_buffer buffer;
5345  struct nk_panel *layout;
5346  float scrollbar_hiding_timer;
5347 
5348  /* persistent widget state */
5349  struct nk_property_state property;
5350  struct nk_popup_state popup;
5351  struct nk_edit_state edit;
5352  unsigned int scrolled;
5353  nk_bool widgets_disabled;
5354 
5355  struct nk_table *tables;
5356  unsigned int table_count;
5357 
5358  /* window list hooks */
5359  struct nk_window *next;
5360  struct nk_window *prev;
5361  struct nk_window *parent;
5362 };
5363 
5364 /*==============================================================
5365  * STACK
5366  * =============================================================*/
5393 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
5394 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
5395 #endif
5396 
5397 #ifndef NK_FONT_STACK_SIZE
5398 #define NK_FONT_STACK_SIZE 8
5399 #endif
5400 
5401 #ifndef NK_STYLE_ITEM_STACK_SIZE
5402 #define NK_STYLE_ITEM_STACK_SIZE 16
5403 #endif
5404 
5405 #ifndef NK_FLOAT_STACK_SIZE
5406 #define NK_FLOAT_STACK_SIZE 32
5407 #endif
5408 
5409 #ifndef NK_VECTOR_STACK_SIZE
5410 #define NK_VECTOR_STACK_SIZE 16
5411 #endif
5412 
5413 #ifndef NK_FLAGS_STACK_SIZE
5414 #define NK_FLAGS_STACK_SIZE 32
5415 #endif
5416 
5417 #ifndef NK_COLOR_STACK_SIZE
5418 #define NK_COLOR_STACK_SIZE 32
5419 #endif
5420 
5421 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
5422  struct nk_config_stack_##name##_element {\
5423  prefix##_##type *address;\
5424  prefix##_##type old_value;\
5425  }
5426 #define NK_CONFIG_STACK(type,size)\
5427  struct nk_config_stack_##type {\
5428  int head;\
5429  struct nk_config_stack_##type##_element elements[size];\
5430  }
5431 
5432 #define nk_float float
5433 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
5434 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
5435 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
5436 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags);
5437 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
5438 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
5439 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
5440 
5441 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE);
5442 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE);
5443 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE);
5444 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE);
5445 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE);
5446 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE);
5447 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE);
5448 
5450  struct nk_config_stack_style_item style_items;
5451  struct nk_config_stack_float floats;
5452  struct nk_config_stack_vec2 vectors;
5453  struct nk_config_stack_flags flags;
5454  struct nk_config_stack_color colors;
5455  struct nk_config_stack_user_font fonts;
5456  struct nk_config_stack_button_behavior button_behaviors;
5457 };
5458 
5459 /*==============================================================
5460  * CONTEXT
5461  * =============================================================*/
5462 #define NK_VALUE_PAGE_CAPACITY \
5463  (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
5464 
5465 struct nk_table {
5466  unsigned int seq;
5467  unsigned int size;
5468  nk_hash keys[NK_VALUE_PAGE_CAPACITY];
5469  nk_uint values[NK_VALUE_PAGE_CAPACITY];
5470  struct nk_table *next, *prev;
5471 };
5472 
5474  struct nk_table tbl;
5475  struct nk_panel pan;
5476  struct nk_window win;
5477 };
5478 
5480  union nk_page_data data;
5481  struct nk_page_element *next;
5482  struct nk_page_element *prev;
5483 };
5484 
5485 struct nk_page {
5486  unsigned int size;
5487  struct nk_page *next;
5488  struct nk_page_element win[1];
5489 };
5490 
5491 struct nk_pool {
5492  struct nk_allocator alloc;
5493  enum nk_allocation_type type;
5494  unsigned int page_count;
5495  struct nk_page *pages;
5496  struct nk_page_element *freelist;
5497  unsigned capacity;
5498  nk_size size;
5499  nk_size cap;
5500 };
5501 
5502 struct nk_context {
5503 /* public: can be accessed freely */
5504  struct nk_input input;
5505  struct nk_style style;
5506  struct nk_buffer memory;
5507  struct nk_clipboard clip;
5508  nk_flags last_widget_state;
5509  enum nk_button_behavior button_behavior;
5510  struct nk_configuration_stacks stacks;
5511  float delta_time_seconds;
5512 
5513 /* private:
5514  should only be accessed if you
5515  know what you are doing */
5516 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
5517  struct nk_draw_list draw_list;
5518 #endif
5519 #ifdef NK_INCLUDE_COMMAND_USERDATA
5520  nk_handle userdata;
5521 #endif
5526  struct nk_text_edit text_edit;
5528  struct nk_command_buffer overlay;
5529 
5531  int build;
5532  int use_pool;
5533  struct nk_pool pool;
5534  struct nk_window *begin;
5535  struct nk_window *end;
5536  struct nk_window *active;
5537  struct nk_window *current;
5538  struct nk_page_element *freelist;
5539  unsigned int count;
5540  unsigned int seq;
5541 };
5542 
5543 /* ==============================================================
5544  * MATH
5545  * =============================================================== */
5546 #define NK_PI 3.141592654f
5547 #define NK_PI_HALF 1.570796326f
5548 #define NK_UTF_INVALID 0xFFFD
5549 #define NK_MAX_FLOAT_PRECISION 2
5550 
5551 #define NK_UNUSED(x) ((void)(x))
5552 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
5553 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
5554 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
5555 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
5556 #define NK_INBOX(px, py, x, y, w, h)\
5557  (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
5558 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
5559  ((x1 < (x0 + w0)) && (x0 < (x1 + w1)) && \
5560  (y1 < (y0 + h0)) && (y0 < (y1 + h1)))
5561 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
5562  (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
5563 
5564 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
5565 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
5566 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
5567 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
5568 
5569 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
5570 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
5571 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
5572 
5573 /* ==============================================================
5574  * ALIGNMENT
5575  * =============================================================== */
5576 /* Pointer to Integer type conversion for pointer alignment */
5577 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
5578 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
5579 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
5580 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
5581 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
5582 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
5583 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
5584 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
5585 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
5586 #else /* generates warning but works */
5587 # define NK_UINT_TO_PTR(x) ((void*)(x))
5588 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
5589 #endif
5590 
5591 #define NK_ALIGN_PTR(x, mask)\
5592  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
5593 #define NK_ALIGN_PTR_BACK(x, mask)\
5594  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
5595 
5596 #if ((defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)) && !defined(EMSCRIPTEN)
5597 #define NK_OFFSETOF(st,m) (__builtin_offsetof(st,m))
5598 #else
5599 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
5600 #endif
5601 
5602 #ifdef __cplusplus
5603 }
5604 #endif
5605 
5606 #ifdef __cplusplus
5607 template<typename T> struct nk_alignof;
5608 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
5609 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
5610 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
5611  diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
5612 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
5613 #else
5614 #define NK_ALIGNOF(t) NK_OFFSETOF(struct {char c; t _h;}, _h)
5615 #endif
5616 
5617 #define NK_CONTAINER_OF(ptr,type,member)\
5618  (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
5619 
5620 
5621 
5622 #endif /* NK_NUKLEAR_H_ */
5623 
5624 #ifdef NK_IMPLEMENTATION
5625 
5626 #ifndef NK_INTERNAL_H
5627 #define NK_INTERNAL_H
5628 
5629 #ifndef NK_POOL_DEFAULT_CAPACITY
5630 #define NK_POOL_DEFAULT_CAPACITY 16
5631 #endif
5632 
5633 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
5634 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
5635 #endif
5636 
5637 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
5638 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
5639 #endif
5640 
5641 /* standard library headers */
5642 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5643 #include <stdlib.h> /* malloc, free */
5644 #endif
5645 #ifdef NK_INCLUDE_STANDARD_IO
5646 #include <stdio.h> /* fopen, fclose,... */
5647 #endif
5648 #ifdef NK_INCLUDE_STANDARD_VARARGS
5649 #include <stdarg.h> /* valist, va_start, va_end, ... */
5650 #endif
5651 #ifndef NK_ASSERT
5652 #include <assert.h>
5653 #define NK_ASSERT(expr) assert(expr)
5654 #endif
5655 
5656 #define NK_DEFAULT (-1)
5657 
5658 #ifndef NK_VSNPRINTF
5659 /* If your compiler does support `vsnprintf` I would highly recommend
5660  * defining this to vsnprintf instead since `vsprintf` is basically
5661  * unbelievable unsafe and should *NEVER* be used. But I have to support
5662  * it since C89 only provides this unsafe version. */
5663  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
5664  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
5665  (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
5666  (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
5667  defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
5668  #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
5669  #else
5670  #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
5671  #endif
5672 #endif
5673 
5674 #define NK_SCHAR_MIN (-127)
5675 #define NK_SCHAR_MAX 127
5676 #define NK_UCHAR_MIN 0
5677 #define NK_UCHAR_MAX 256
5678 #define NK_SSHORT_MIN (-32767)
5679 #define NK_SSHORT_MAX 32767
5680 #define NK_USHORT_MIN 0
5681 #define NK_USHORT_MAX 65535
5682 #define NK_SINT_MIN (-2147483647)
5683 #define NK_SINT_MAX 2147483647
5684 #define NK_UINT_MIN 0
5685 #define NK_UINT_MAX 4294967295u
5686 
5687 /* Make sure correct type size:
5688  * This will fire with a negative subscript error if the type sizes
5689  * are set incorrectly by the compiler, and compile out if not */
5690 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
5691 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
5692 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
5693 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
5694 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
5695 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
5696 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
5697 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
5698 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
5699 #ifdef NK_INCLUDE_STANDARD_BOOL
5700 NK_STATIC_ASSERT(sizeof(nk_bool) == sizeof(bool));
5701 #else
5702 NK_STATIC_ASSERT(sizeof(nk_bool) == 4);
5703 #endif
5704 
5705 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
5706 #define NK_FLOAT_PRECISION 0.00000000000001
5707 
5708 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
5709 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
5710 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
5711 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
5712 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
5713 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
5714 
5715 /* widget */
5716 #define nk_widget_state_reset(s)\
5717  if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
5718  (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
5719  else (*(s)) = NK_WIDGET_STATE_INACTIVE;
5720 
5721 /* math */
5722 #ifndef NK_INV_SQRT
5723 NK_LIB float nk_inv_sqrt(float n);
5724 #endif
5725 #ifndef NK_SIN
5726 NK_LIB float nk_sin(float x);
5727 #endif
5728 #ifndef NK_COS
5729 NK_LIB float nk_cos(float x);
5730 #endif
5731 #ifndef NK_ATAN
5732 NK_LIB float nk_atan(float x);
5733 #endif
5734 #ifndef NK_ATAN2
5735 NK_LIB float nk_atan2(float y, float x);
5736 #endif
5737 NK_LIB nk_uint nk_round_up_pow2(nk_uint v);
5738 NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount);
5739 NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad);
5740 NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1);
5741 NK_LIB double nk_pow(double x, int n);
5742 NK_LIB int nk_ifloord(double x);
5743 NK_LIB int nk_ifloorf(float x);
5744 NK_LIB int nk_iceilf(float x);
5745 NK_LIB int nk_log10(double n);
5746 NK_LIB float nk_roundf(float x);
5747 
5748 /* util */
5749 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
5750 NK_LIB nk_bool nk_is_lower(int c);
5751 NK_LIB nk_bool nk_is_upper(int c);
5752 NK_LIB int nk_to_upper(int c);
5753 NK_LIB int nk_to_lower(int c);
5754 
5755 #ifndef NK_MEMCPY
5756 NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n);
5757 #endif
5758 #ifndef NK_MEMSET
5759 NK_LIB void nk_memset(void *ptr, int c0, nk_size size);
5760 #endif
5761 NK_LIB void nk_zero(void *ptr, nk_size size);
5762 NK_LIB char *nk_itoa(char *s, long n);
5763 NK_LIB int nk_string_float_limit(char *string, int prec);
5764 #ifndef NK_DTOA
5765 NK_LIB char *nk_dtoa(char *s, double n);
5766 #endif
5767 NK_LIB int nk_text_clamp(const struct nk_user_font *font, const char *text, int text_len, float space, int *glyphs, float *text_width, nk_rune *sep_list, int sep_count);
5768 NK_LIB struct nk_vec2 nk_text_calculate_text_bounds(const struct nk_user_font *font, const char *begin, int byte_len, float row_height, const char **remaining, struct nk_vec2 *out_offset, int *glyphs, int op);
5769 #ifdef NK_INCLUDE_STANDARD_VARARGS
5770 NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args);
5771 #endif
5772 #ifdef NK_INCLUDE_STANDARD_IO
5773 NK_LIB char *nk_file_load(const char* path, nk_size* siz, const struct nk_allocator *alloc);
5774 #endif
5775 
5776 /* buffer */
5777 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
5778 NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size);
5779 NK_LIB void nk_mfree(nk_handle unused, void *ptr);
5780 #endif
5781 NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type);
5782 NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align);
5783 NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size);
5784 
5785 /* draw */
5786 NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip);
5787 NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b);
5788 NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size);
5789 NK_LIB void nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, struct nk_rect content, struct nk_color background, struct nk_color foreground, float border_width, const struct nk_user_font *font);
5790 
5791 /* buffering */
5792 NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
5793 NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win);
5794 NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win);
5795 NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*);
5796 NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
5797 NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w);
5798 NK_LIB void nk_build(struct nk_context *ctx);
5799 
5800 /* text editor */
5801 NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter);
5802 NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
5803 NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
5804 NK_LIB void nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, const struct nk_user_font *font, float row_height);
5805 
5806 /* window */
5807 enum nk_window_insert_location {
5808  NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
5809  NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
5810 };
5811 NK_LIB void *nk_create_window(struct nk_context *ctx);
5812 NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*);
5813 NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win);
5814 NK_LIB struct nk_window *nk_find_window(const struct nk_context *ctx, nk_hash hash, const char *name);
5815 NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc);
5816 
5817 /* pool */
5818 NK_LIB void nk_pool_init(struct nk_pool *pool, const struct nk_allocator *alloc, unsigned int capacity);
5819 NK_LIB void nk_pool_free(struct nk_pool *pool);
5820 NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size);
5821 NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool);
5822 
5823 /* page-element */
5824 NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx);
5825 NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem);
5826 NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem);
5827 
5828 /* table */
5829 NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx);
5830 NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
5831 NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
5832 NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl);
5833 NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value);
5834 NK_LIB nk_uint *nk_find_value(const struct nk_window *win, nk_hash name);
5835 
5836 /* panel */
5837 NK_LIB void *nk_create_panel(struct nk_context *ctx);
5838 NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan);
5839 NK_LIB nk_bool nk_panel_has_header(nk_flags flags, const char *title);
5840 NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type);
5841 NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type);
5842 NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type);
5843 NK_LIB nk_bool nk_panel_is_sub(enum nk_panel_type type);
5844 NK_LIB nk_bool nk_panel_is_nonblock(enum nk_panel_type type);
5845 NK_LIB nk_bool nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type);
5846 NK_LIB void nk_panel_end(struct nk_context *ctx);
5847 
5848 /* layout */
5849 NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns);
5850 NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols);
5851 NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width);
5852 NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win);
5853 NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify);
5854 NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx);
5855 NK_LIB void nk_layout_peek(struct nk_rect *bounds, const struct nk_context *ctx);
5856 
5857 /* popup */
5858 NK_LIB nk_bool nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type);
5859 
5860 /* text */
5861 struct nk_text {
5862  struct nk_vec2 padding;
5863  struct nk_color background;
5864  struct nk_color text;
5865 };
5866 NK_LIB void nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, nk_flags a, const struct nk_user_font *f);
5867 NK_LIB void nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, const struct nk_user_font *f);
5868 
5869 /* button */
5870 NK_LIB nk_bool nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior);
5871 NK_LIB const struct nk_style_item* nk_draw_button(struct nk_command_buffer *out, const struct nk_rect *bounds, nk_flags state, const struct nk_style_button *style);
5872 NK_LIB nk_bool nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, const struct nk_style_button *style, const struct nk_input *in, enum nk_button_behavior behavior, struct nk_rect *content);
5873 NK_LIB void nk_draw_button_text(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const char *txt, int len, nk_flags text_alignment, const struct nk_user_font *font);
5874 NK_LIB nk_bool nk_do_button_text(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *string, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
5875 NK_LIB void nk_draw_button_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, enum nk_symbol_type type, const struct nk_user_font *font);
5876 NK_LIB nk_bool nk_do_button_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
5877 NK_LIB void nk_draw_button_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const struct nk_image *img);
5878 NK_LIB nk_bool nk_do_button_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, enum nk_button_behavior b, const struct nk_style_button *style, const struct nk_input *in);
5879 NK_LIB void nk_draw_button_text_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, const char *str, int len, enum nk_symbol_type type, const struct nk_user_font *font);
5880 NK_LIB nk_bool nk_do_button_text_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, const char *str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
5881 NK_LIB void nk_draw_button_text_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, const char *str, int len, const struct nk_user_font *font, const struct nk_image *img);
5882 NK_LIB nk_bool nk_do_button_text_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, const char* str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
5883 
5884 /* toggle */
5885 enum nk_toggle_type {
5886  NK_TOGGLE_CHECK,
5887  NK_TOGGLE_OPTION
5888 };
5889 NK_LIB nk_bool nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, nk_bool active);
5890 NK_LIB void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, nk_bool active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font, nk_flags text_alignment);
5891 NK_LIB void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, nk_bool active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font, nk_flags text_alignment);
5892 NK_LIB nk_bool nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, nk_bool *active, const char *str, int len, enum nk_toggle_type type, const struct nk_style_toggle *style, const struct nk_input *in, const struct nk_user_font *font, nk_flags widget_alignment, nk_flags text_alignment);
5893 
5894 /* progress */
5895 NK_LIB nk_size nk_progress_behavior(nk_flags *state, struct nk_input *in, struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, nk_bool modifiable);
5896 NK_LIB void nk_draw_progress(struct nk_command_buffer *out, nk_flags state, const struct nk_style_progress *style, const struct nk_rect *bounds, const struct nk_rect *scursor, nk_size value, nk_size max);
5897 NK_LIB nk_size nk_do_progress(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_size value, nk_size max, nk_bool modifiable, const struct nk_style_progress *style, struct nk_input *in);
5898 
5899 /* slider */
5900 NK_LIB float nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, struct nk_rect *visual_cursor, struct nk_input *in, struct nk_rect bounds, float slider_min, float slider_max, float slider_value, float slider_step, float slider_steps);
5901 NK_LIB void nk_draw_slider(struct nk_command_buffer *out, nk_flags state, const struct nk_style_slider *style, const struct nk_rect *bounds, const struct nk_rect *visual_cursor, float min, float value, float max);
5902 NK_LIB float nk_do_slider(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, float min, float val, float max, float step, const struct nk_style_slider *style, struct nk_input *in, const struct nk_user_font *font);
5903 
5904 /* scrollbar */
5905 NK_LIB float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o);
5906 NK_LIB void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll);
5907 NK_LIB float nk_do_scrollbarv(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
5908 NK_LIB float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
5909 
5910 /* selectable */
5911 NK_LIB void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, nk_bool active, const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, const char *string, int len, nk_flags align, const struct nk_user_font *font);
5912 NK_LIB nk_bool nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
5913 NK_LIB nk_bool nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
5914 
5915 /* edit */
5916 NK_LIB void nk_edit_draw_text(struct nk_command_buffer *out, const struct nk_style_edit *style, float pos_x, float pos_y, float x_offset, const char *text, int byte_len, float row_height, const struct nk_user_font *font, struct nk_color background, struct nk_color foreground, nk_bool is_selected);
5917 NK_LIB nk_flags nk_do_edit(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, struct nk_text_edit *edit, const struct nk_style_edit *style, struct nk_input *in, const struct nk_user_font *font);
5918 
5919 /* color-picker */
5920 NK_LIB nk_bool nk_color_picker_behavior(nk_flags *state, const struct nk_rect *bounds, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf *color, const struct nk_input *in);
5921 NK_LIB void nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf col);
5922 NK_LIB nk_bool nk_do_color_picker(nk_flags *state, struct nk_command_buffer *out, struct nk_colorf *col, enum nk_color_format fmt, struct nk_rect bounds, struct nk_vec2 padding, const struct nk_input *in, const struct nk_user_font *font);
5923 
5924 /* property */
5925 enum nk_property_status {
5926  NK_PROPERTY_DEFAULT,
5927  NK_PROPERTY_EDIT,
5928  NK_PROPERTY_DRAG
5929 };
5930 enum nk_property_filter {
5931  NK_FILTER_INT,
5932  NK_FILTER_FLOAT
5933 };
5934 enum nk_property_kind {
5935  NK_PROPERTY_INT,
5936  NK_PROPERTY_FLOAT,
5937  NK_PROPERTY_DOUBLE
5938 };
5939 union nk_property {
5940  int i;
5941  float f;
5942  double d;
5943 };
5944 struct nk_property_variant {
5945  enum nk_property_kind kind;
5946  union nk_property value;
5947  union nk_property min_value;
5948  union nk_property max_value;
5949  union nk_property step;
5950 };
5951 NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step);
5952 NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step);
5953 NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step);
5954 
5955 NK_LIB void nk_drag_behavior(nk_flags *state, const struct nk_input *in, struct nk_rect drag, struct nk_property_variant *variant, float inc_per_pixel);
5956 NK_LIB void nk_property_behavior(nk_flags *ws, const struct nk_input *in, struct nk_rect property, struct nk_rect label, struct nk_rect edit, struct nk_rect empty, int *state, struct nk_property_variant *variant, float inc_per_pixel);
5957 NK_LIB void nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, const char *name, int len, const struct nk_user_font *font);
5958 NK_LIB void nk_do_property(nk_flags *ws, struct nk_command_buffer *out, struct nk_rect property, const char *name, struct nk_property_variant *variant, float inc_per_pixel, char *buffer, int *len, int *state, int *cursor, int *select_begin, int *select_end, const struct nk_style_property *style, enum nk_property_filter filter, struct nk_input *in, const struct nk_user_font *font, struct nk_text_edit *text_edit, enum nk_button_behavior behavior);
5959 NK_LIB void nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, float inc_per_pixel, const enum nk_property_filter filter);
5960 
5961 #ifdef NK_INCLUDE_FONT_BAKING
5962 
5968 #ifndef NK_NO_STB_RECT_PACK_IMPLEMENTATION
5969 #define STB_RECT_PACK_IMPLEMENTATION
5970 #endif /* NK_NO_STB_RECT_PACK_IMPLEMENTATION */
5971 
5977 #ifndef NK_NO_STB_TRUETYPE_IMPLEMENTATION
5978 #define STB_TRUETYPE_IMPLEMENTATION
5979 #endif /* NK_NO_STB_TRUETYPE_IMPLEMENTATION */
5980 
5981 /* Allow consumer to define own STBTT_malloc/STBTT_free, and use the font atlas' allocator otherwise */
5982 #ifndef STBTT_malloc
5983 static void*
5984 nk_stbtt_malloc(nk_size size, void *user_data) {
5985  struct nk_allocator *alloc = (struct nk_allocator *) user_data;
5986  return alloc->alloc(alloc->userdata, 0, size);
5987 }
5988 
5989 static void
5990 nk_stbtt_free(void *ptr, void *user_data) {
5991  struct nk_allocator *alloc = (struct nk_allocator *) user_data;
5992  alloc->free(alloc->userdata, ptr);
5993 }
5994 
5995 #define STBTT_malloc(x,u) nk_stbtt_malloc(x,u)
5996 #define STBTT_free(x,u) nk_stbtt_free(x,u)
5997 
5998 #endif /* STBTT_malloc */
5999 
6000 #endif /* NK_INCLUDE_FONT_BAKING */
6001 
6002 #endif
6003 
6004 
6005 
6006 
6007 /* ===============================================================
6008  *
6009  * MATH
6010  *
6011  * ===============================================================*/
6012 /* ### Math
6013  Since nuklear is supposed to work on all systems providing floating point
6014  math without any dependencies I also had to implement my own math functions
6015  for sqrt, sin and cos. Since the actual highly accurate implementations for
6016  the standard library functions are quite complex and I do not need high
6017  precision for my use cases I use approximations.
6018 
6019  Sqrt
6020  ----
6021  For square root nuklear uses the famous fast inverse square root:
6022  https://en.wikipedia.org/wiki/Fast_inverse_square_root with
6023  slightly tweaked magic constant. While on today's hardware it is
6024  probably not faster it is still fast and accurate enough for
6025  nuklear's use cases. IMPORTANT: this requires float format IEEE 754
6026 
6027  Sine/Cosine
6028  -----------
6029  All constants inside both function are generated Remez's minimax
6030  approximations for value range 0...2*PI. The reason why I decided to
6031  approximate exactly that range is that nuklear only needs sine and
6032  cosine to generate circles which only requires that exact range.
6033  In addition I used Remez instead of Taylor for additional precision:
6034  www.lolengine.net/blog/2011/12/21/better-function-approximations.
6035 
6036  The tool I used to generate constants for both sine and cosine
6037  (it can actually approximate a lot more functions) can be
6038  found here: www.lolengine.net/wiki/oss/lolremez
6039 */
6040 #ifndef NK_INV_SQRT
6041 #define NK_INV_SQRT nk_inv_sqrt
6052 NK_LIB float
6053 nk_inv_sqrt(float n)
6054 {
6055  float x2;
6056  const float threehalfs = 1.5f;
6057  union {nk_uint i; float f;} conv = {0};
6058  conv.f = n;
6059  x2 = n * 0.5f;
6060  conv.i = 0x5f375A84 - (conv.i >> 1);
6061  conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
6062  return conv.f;
6063 }
6064 #endif
6065 #ifndef NK_SIN
6066 #define NK_SIN nk_sin
6077 NK_LIB float
6078 nk_sin(float x)
6079 {
6080  NK_STORAGE const float a0 = +1.91059300966915117e-31f;
6081  NK_STORAGE const float a1 = +1.00086760103908896f;
6082  NK_STORAGE const float a2 = -1.21276126894734565e-2f;
6083  NK_STORAGE const float a3 = -1.38078780785773762e-1f;
6084  NK_STORAGE const float a4 = -2.67353392911981221e-2f;
6085  NK_STORAGE const float a5 = +2.08026600266304389e-2f;
6086  NK_STORAGE const float a6 = -3.03996055049204407e-3f;
6087  NK_STORAGE const float a7 = +1.38235642404333740e-4f;
6088  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
6089 }
6090 #endif
6091 #ifndef NK_COS
6092 #define NK_COS nk_cos
6103 NK_LIB float
6104 nk_cos(float x)
6105 {
6106  /* New implementation. Also generated using lolremez. */
6107  /* Old version significantly deviated from expected results. */
6108  NK_STORAGE const float a0 = 9.9995999154986614e-1f;
6109  NK_STORAGE const float a1 = 1.2548995793001028e-3f;
6110  NK_STORAGE const float a2 = -5.0648546280678015e-1f;
6111  NK_STORAGE const float a3 = 1.2942246466519995e-2f;
6112  NK_STORAGE const float a4 = 2.8668384702547972e-2f;
6113  NK_STORAGE const float a5 = 7.3726485210586547e-3f;
6114  NK_STORAGE const float a6 = -3.8510875386947414e-3f;
6115  NK_STORAGE const float a7 = 4.7196604604366623e-4f;
6116  NK_STORAGE const float a8 = -1.8776444013090451e-5f;
6117  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8)))))));
6118 }
6119 #endif
6120 #ifndef NK_ATAN
6121 #define NK_ATAN nk_atan
6132 NK_LIB float
6133 nk_atan(float x)
6134 {
6135  /* ./lolremez --progress --float -d 9 -r "0:pi*2" "atan(x)" */
6136  float u = -1.0989005e-05f;
6137  NK_ASSERT(x >= 0.0f && "TODO support negative floats");
6138  u = u * x + 0.00034117949f;
6139  u = u * x + -0.0044932296f;
6140  u = u * x + 0.032596264f;
6141  u = u * x + -0.14088021f;
6142  u = u * x + 0.36040401f;
6143  u = u * x + -0.47017866f;
6144  u = u * x + 0.00050198776f;
6145  u = u * x + 1.0077682f;
6146  u = u * x + -0.0004765437f;
6147  return u;
6148 }
6149 #endif
6150 #ifndef NK_ATAN2
6151 #define NK_ATAN2 nk_atan2
6163 NK_LIB float
6164 nk_atan2(float y, float x)
6165 {
6166  float ax = NK_ABS(x),
6167  ay = NK_ABS(y);
6168  /* 0 = +y +x 1 = -y +x
6169  2 = +y -x 3 = -y -x */
6170  nk_uint signs = (y < 0) | ((x < 0) << 1);
6171 
6172  float a;
6173  if(y == 0.0 && x == 0.0) return 0.0f;
6174  a = (ay > ax)
6175  ? NK_PI_HALF - NK_ATAN(ax / ay)
6176  : NK_ATAN(ay / ax);
6177 
6178  switch(signs){
6179  case 0: return a;
6180  case 1: return -a;
6181  case 2: return -a + NK_PI;
6182  case 3: return a - NK_PI;
6183  }
6184  return 0.0f; /* prevents warning */
6185 }
6186 #endif
6197 NK_LIB nk_uint
6198 nk_round_up_pow2(nk_uint v)
6199 {
6200  v--;
6201  v |= v >> 1;
6202  v |= v >> 2;
6203  v |= v >> 4;
6204  v |= v >> 8;
6205  v |= v >> 16;
6206  v++;
6207  return v;
6208 }
6220 NK_LIB double
6221 nk_pow(double x, int n)
6222 {
6223  /* check the sign of n */
6224  double r = 1;
6225  int plus = n >= 0;
6226  n = (plus) ? n : -n;
6227  while (n > 0) {
6228  if ((n & 1) == 1)
6229  r *= x;
6230  n /= 2;
6231  x *= x;
6232  }
6233  return plus ? r : 1.0 / r;
6234 }
6245 NK_LIB int
6246 nk_ifloord(double x)
6247 {
6248  x = (double)((int)x - ((x < 0.0) ? 1 : 0));
6249  return (int)x;
6250 }
6261 NK_LIB int
6262 nk_ifloorf(float x)
6263 {
6264  x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
6265  return (int)x;
6266 }
6277 NK_LIB int
6278 nk_iceilf(float x)
6279 {
6280  if (x >= 0) {
6281  int i = (int)x;
6282  return (x > i) ? i+1: i;
6283  } else {
6284  int t = (int)x;
6285  float r = x - (float)t;
6286  return (r > 0.0f) ? t+1: t;
6287  }
6288 }
6299 NK_LIB int
6300 nk_log10(double n)
6301 {
6302  int neg;
6303  int ret;
6304  int exp = 0;
6305 
6306  neg = (n < 0) ? 1 : 0;
6307  ret = (neg) ? (int)-n : (int)n;
6308  while ((ret / 10) > 0) {
6309  ret /= 10;
6310  exp++;
6311  }
6312  if (neg) exp = -exp;
6313  return exp;
6314 }
6325 NK_LIB float
6326 nk_roundf(float x)
6327 {
6328  return (x >= 0.0) ? nk_ifloorf(x + 0.5) : nk_iceilf(x - 0.5);
6329 }
6340 NK_API struct nk_rect
6341 nk_get_null_rect(void)
6342 {
6343  return nk_null_rect;
6344 }
6358 NK_API struct nk_rect
6359 nk_rect(float x, float y, float w, float h)
6360 {
6361  struct nk_rect r;
6362  r.x = x; r.y = y;
6363  r.w = w; r.h = h;
6364  return r;
6365 }
6379 NK_API struct nk_rect
6380 nk_recti(int x, int y, int w, int h)
6381 {
6382  struct nk_rect r;
6383  r.x = (float)x;
6384  r.y = (float)y;
6385  r.w = (float)w;
6386  r.h = (float)h;
6387  return r;
6388 }
6400 NK_API struct nk_rect
6401 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
6402 {
6403  return nk_rect(pos.x, pos.y, size.x, size.y);
6404 }
6415 NK_API struct nk_rect
6416 nk_rectv(const float *r)
6417 {
6418  return nk_rect(r[0], r[1], r[2], r[3]);
6419 }
6430 NK_API struct nk_rect
6431 nk_rectiv(const int *r)
6432 {
6433  return nk_recti(r[0], r[1], r[2], r[3]);
6434 }
6445 NK_API struct nk_vec2
6446 nk_rect_pos(struct nk_rect r)
6447 {
6448  struct nk_vec2 ret;
6449  ret.x = r.x; ret.y = r.y;
6450  return ret;
6451 }
6462 NK_API struct nk_vec2
6463 nk_rect_size(struct nk_rect r)
6464 {
6465  struct nk_vec2 ret;
6466  ret.x = r.w; ret.y = r.h;
6467  return ret;
6468 }
6480 NK_LIB struct nk_rect
6481 nk_shrink_rect(struct nk_rect r, float amount)
6482 {
6483  struct nk_rect res;
6484  r.w = NK_MAX(r.w, 2 * amount);
6485  r.h = NK_MAX(r.h, 2 * amount);
6486  res.x = r.x + amount;
6487  res.y = r.y + amount;
6488  res.w = r.w - 2 * amount;
6489  res.h = r.h - 2 * amount;
6490  return res;
6491 }
6503 NK_LIB struct nk_rect
6504 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
6505 {
6506  r.w = NK_MAX(r.w, 2 * pad.x);
6507  r.h = NK_MAX(r.h, 2 * pad.y);
6508  r.x += pad.x; r.y += pad.y;
6509  r.w -= 2 * pad.x;
6510  r.h -= 2 * pad.y;
6511  return r;
6512 }
6524 NK_API struct nk_vec2
6525 nk_vec2(float x, float y)
6526 {
6527  struct nk_vec2 ret;
6528  ret.x = x; ret.y = y;
6529  return ret;
6530 }
6542 NK_API struct nk_vec2
6543 nk_vec2i(int x, int y)
6544 {
6545  struct nk_vec2 ret;
6546  ret.x = (float)x;
6547  ret.y = (float)y;
6548  return ret;
6549 }
6560 NK_API struct nk_vec2
6561 nk_vec2v(const float *v)
6562 {
6563  return nk_vec2(v[0], v[1]);
6564 }
6575 NK_API struct nk_vec2
6576 nk_vec2iv(const int *v)
6577 {
6578  return nk_vec2i(v[0], v[1]);
6579 }
6593 NK_LIB void
6594 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6595  float x1, float y1)
6596 {
6597  NK_ASSERT(a);
6598  NK_ASSERT(clip);
6599  clip->x = NK_MAX(a->x, x0);
6600  clip->y = NK_MAX(a->y, y0);
6601  clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6602  clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6603  clip->w = NK_MAX(0, clip->w);
6604  clip->h = NK_MAX(0, clip->h);
6605 }
6606 
6618 NK_API void
6619 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
6620  float pad_x, float pad_y, enum nk_heading direction)
6621 {
6622  float w_half, h_half;
6623  NK_ASSERT(result);
6624 
6625  r.w = NK_MAX(2 * pad_x, r.w);
6626  r.h = NK_MAX(2 * pad_y, r.h);
6627  r.w = r.w - 2 * pad_x;
6628  r.h = r.h - 2 * pad_y;
6629 
6630  r.x = r.x + pad_x;
6631  r.y = r.y + pad_y;
6632 
6633  w_half = r.w / 2.0f;
6634  h_half = r.h / 2.0f;
6635 
6636  if (direction == NK_UP) {
6637  result[0] = nk_vec2(r.x + w_half, r.y);
6638  result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6639  result[2] = nk_vec2(r.x, r.y + r.h);
6640  } else if (direction == NK_RIGHT) {
6641  result[0] = nk_vec2(r.x, r.y);
6642  result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6643  result[2] = nk_vec2(r.x, r.y + r.h);
6644  } else if (direction == NK_DOWN) {
6645  result[0] = nk_vec2(r.x, r.y);
6646  result[1] = nk_vec2(r.x + r.w, r.y);
6647  result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6648  } else {
6649  result[0] = nk_vec2(r.x, r.y + h_half);
6650  result[1] = nk_vec2(r.x + r.w, r.y);
6651  result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6652  }
6653 }
6654 
6655 
6656 
6657 
6658 
6659 /* ===============================================================
6660  *
6661  * UTIL
6662  *
6663  * ===============================================================*/
6664 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
6665 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
6666 NK_LIB nk_bool nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
6667 NK_LIB nk_bool nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
6668 NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
6669 NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
6670 
6671 #ifndef NK_MEMCPY
6672 #define NK_MEMCPY nk_memcopy
6685 NK_LIB void*
6686 nk_memcopy(void *dst0, const void *src0, nk_size length)
6687 {
6688  nk_ptr t;
6689  char *dst = (char*)dst0;
6690  const char *src = (const char*)src0;
6691  if (length == 0 || dst == src)
6692  goto done;
6693 
6694  #define nk_word int
6695  #define nk_wsize sizeof(nk_word)
6696  #define nk_wmask (nk_wsize-1)
6697  #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
6698  #define NK_TLOOP1(s) do { s; } while (--t)
6699 
6700  if (dst < src) {
6701  t = (nk_ptr)src; /* only need low bits */
6702  if ((t | (nk_ptr)dst) & nk_wmask) {
6703  if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
6704  t = length;
6705  else
6706  t = nk_wsize - (t & nk_wmask);
6707  length -= t;
6708  NK_TLOOP1(*dst++ = *src++);
6709  }
6710  t = length / nk_wsize;
6711  NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
6712  src += nk_wsize; dst += nk_wsize);
6713  t = length & nk_wmask;
6714  NK_TLOOP(*dst++ = *src++);
6715  } else {
6716  src += length;
6717  dst += length;
6718  t = (nk_ptr)src;
6719  if ((t | (nk_ptr)dst) & nk_wmask) {
6720  if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
6721  t = length;
6722  else
6723  t &= nk_wmask;
6724  length -= t;
6725  NK_TLOOP1(*--dst = *--src);
6726  }
6727  t = length / nk_wsize;
6728  NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
6729  *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
6730  t = length & nk_wmask;
6731  NK_TLOOP(*--dst = *--src);
6732  }
6733  #undef nk_word
6734  #undef nk_wsize
6735  #undef nk_wmask
6736  #undef NK_TLOOP
6737  #undef NK_TLOOP1
6738 done:
6739  return (dst0);
6740 }
6741 #endif
6742 #ifndef NK_MEMSET
6743 #define NK_MEMSET nk_memset
6756 NK_LIB void
6757 nk_memset(void *ptr, int c0, nk_size size)
6758 {
6759  #define nk_word unsigned
6760  #define nk_wsize sizeof(nk_word)
6761  #define nk_wmask (nk_wsize - 1)
6762  nk_byte *dst = (nk_byte*)ptr;
6763  unsigned c = 0;
6764  nk_size t = 0;
6765 
6766  if ((c = (nk_byte)c0) != 0) {
6767  c = (c << 8) | c; /* at least 16-bits */
6768  if (sizeof(unsigned int) > 2)
6769  c = (c << 16) | c; /* at least 32-bits*/
6770  }
6771 
6772  /* too small of a word count */
6773  dst = (nk_byte*)ptr;
6774  if (size < 3 * nk_wsize) {
6775  while (size--) *dst++ = (nk_byte)c0;
6776  return;
6777  }
6778 
6779  /* align destination */
6780  if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
6781  t = nk_wsize -t;
6782  size -= t;
6783  do {
6784  *dst++ = (nk_byte)c0;
6785  } while (--t != 0);
6786  }
6787 
6788  /* fill word */
6789  t = size / nk_wsize;
6790  do {
6791  *(nk_word*)((void*)dst) = c;
6792  dst += nk_wsize;
6793  } while (--t != 0);
6794 
6795  /* fill trailing bytes */
6796  t = (size & nk_wmask);
6797  if (t != 0) {
6798  do {
6799  *dst++ = (nk_byte)c0;
6800  } while (--t != 0);
6801  }
6802 
6803  #undef nk_word
6804  #undef nk_wsize
6805  #undef nk_wmask
6806 }
6807 #endif
6819 NK_LIB void
6820 nk_zero(void *ptr, nk_size size)
6821 {
6822  NK_ASSERT(ptr);
6823  NK_MEMSET(ptr, 0, size);
6824 }
6835 NK_API int
6836 nk_strlen(const char *str)
6837 {
6838  int siz = 0;
6839  NK_ASSERT(str);
6840  while (str && *str++ != '\0') siz++;
6841  return siz;
6842 }
6854 NK_API int
6855 nk_strtoi(const char *str, char **endptr)
6856 {
6857  int neg = 1;
6858  const char *p = str;
6859  int value = 0;
6860 
6861  NK_ASSERT(str);
6862  if (!str) return 0;
6863 
6864  /* skip whitespace */
6865  while (*p == ' ') p++;
6866  if (*p == '-') {
6867  neg = -1;
6868  p++;
6869  }
6870  while (*p && *p >= '0' && *p <= '9') {
6871  value = value * 10 + (int) (*p - '0');
6872  p++;
6873  }
6874  if (endptr)
6875  *endptr = (char *)p;
6876  return neg*value;
6877 }
6889 NK_API double
6890 nk_strtod(const char *str, char **endptr)
6891 {
6892  double m;
6893  double neg = 1.0;
6894  char *p = (char *)str;
6895  double value = 0;
6896  double number = 0;
6897 
6898  NK_ASSERT(str);
6899  if (!str) return 0;
6900 
6901  /* skip whitespace */
6902  while (*p == ' ') p++;
6903  if (*p == '-') {
6904  neg = -1.0;
6905  p++;
6906  }
6907 
6908  while (*p && *p != '.' && *p != 'e') {
6909  value = value * 10.0 + (double) (*p - '0');
6910  p++;
6911  }
6912 
6913  if (*p == '.') {
6914  p++;
6915  for(m = 0.1; *p && *p != 'e'; p++ ) {
6916  value = value + (double) (*p - '0') * m;
6917  m *= 0.1;
6918  }
6919  }
6920  if (*p == 'e') {
6921  int i, pow, div;
6922  p++;
6923  if (*p == '-') {
6924  div = nk_true;
6925  p++;
6926  } else if (*p == '+') {
6927  div = nk_false;
6928  p++;
6929  } else div = nk_false;
6930 
6931  for (pow = 0; *p; p++)
6932  pow = pow * 10 + (int) (*p - '0');
6933 
6934  for (m = 1.0, i = 0; i < pow; i++)
6935  m *= 10.0;
6936 
6937  if (div)
6938  value /= m;
6939  else value *= m;
6940  }
6941  number = value * neg;
6942  if (endptr)
6943  *endptr = p;
6944  return number;
6945 }
6957 NK_API float
6958 nk_strtof(const char *str, char **endptr)
6959 {
6960  float float_value;
6961  double double_value;
6962  double_value = NK_STRTOD(str, endptr);
6963  float_value = (float)double_value;
6964  return float_value;
6965 }
6977 NK_API int
6978 nk_stricmp(const char *s1, const char *s2)
6979 {
6980  nk_int c1,c2,d;
6981  do {
6982  c1 = *s1++;
6983  c2 = *s2++;
6984  d = c1 - c2;
6985  while (d) {
6986  if (c1 <= 'Z' && c1 >= 'A') {
6987  d += ('a' - 'A');
6988  if (!d) break;
6989  }
6990  if (c2 <= 'Z' && c2 >= 'A') {
6991  d -= ('a' - 'A');
6992  if (!d) break;
6993  }
6994  return ((d >= 0) << 1) - 1;
6995  }
6996  } while (c1);
6997  return 0;
6998 }
7011 NK_API int
7012 nk_stricmpn(const char *s1, const char *s2, int n)
7013 {
7014  int c1,c2,d;
7015  NK_ASSERT(n >= 0);
7016  do {
7017  c1 = *s1++;
7018  c2 = *s2++;
7019  if (!n--) return 0;
7020 
7021  d = c1 - c2;
7022  while (d) {
7023  if (c1 <= 'Z' && c1 >= 'A') {
7024  d += ('a' - 'A');
7025  if (!d) break;
7026  }
7027  if (c2 <= 'Z' && c2 >= 'A') {
7028  d -= ('a' - 'A');
7029  if (!d) break;
7030  }
7031  return ((d >= 0) << 1) - 1;
7032  }
7033  } while (c1);
7034  return 0;
7035 }
7047 NK_INTERN int
7048 nk_str_match_here(const char *regexp, const char *text)
7049 {
7050  if (regexp[0] == '\0')
7051  return 1;
7052  if (regexp[1] == '*')
7053  return nk_str_match_star(regexp[0], regexp+2, text);
7054  if (regexp[0] == '$' && regexp[1] == '\0')
7055  return *text == '\0';
7056  if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
7057  return nk_str_match_here(regexp+1, text+1);
7058  return 0;
7059 }
7072 NK_INTERN int
7073 nk_str_match_star(int c, const char *regexp, const char *text)
7074 {
7075  do {/* a '* matches zero or more instances */
7076  if (nk_str_match_here(regexp, text))
7077  return 1;
7078  } while (*text != '\0' && (*text++ == c || c == '.'));
7079  return 0;
7080 }
7092 NK_API int
7093 nk_strfilter(const char *text, const char *regexp)
7094 {
7095  /*
7096  c matches any literal character c
7097  . matches any single character
7098  ^ matches the beginning of the input string
7099  $ matches the end of the input string
7100  * matches zero or more occurrences of the previous character*/
7101  if (regexp[0] == '^')
7102  return nk_str_match_here(regexp+1, text);
7103  do { /* must look even if string is empty */
7104  if (nk_str_match_here(regexp, text))
7105  return 1;
7106  } while (*text++ != '\0');
7107  return 0;
7108 }
7120 NK_API int
7121 nk_strmatch_fuzzy_text(const char *str, int str_len,
7122  const char *pattern, int *out_score)
7123 {
7124  /* Returns true if each character in pattern is found sequentially within str
7125  * if found then out_score is also set. Score value has no intrinsic meaning.
7126  * Range varies with pattern. Can only compare scores with same search pattern. */
7127 
7128  /* bonus for adjacent matches */
7129  #define NK_ADJACENCY_BONUS 5
7130  /* bonus if match occurs after a separator */
7131  #define NK_SEPARATOR_BONUS 10
7132  /* bonus if match is uppercase and prev is lower */
7133  #define NK_CAMEL_BONUS 10
7134  /* penalty applied for every letter in str before the first match */
7135  #define NK_LEADING_LETTER_PENALTY (-3)
7136  /* maximum penalty for leading letters */
7137  #define NK_MAX_LEADING_LETTER_PENALTY (-9)
7138  /* penalty for every letter that doesn't matter */
7139  #define NK_UNMATCHED_LETTER_PENALTY (-1)
7140 
7141  /* loop variables */
7142  int score = 0;
7143  char const * pattern_iter = pattern;
7144  int str_iter = 0;
7145  int prev_matched = nk_false;
7146  int prev_lower = nk_false;
7147  /* true so if first letter match gets separator bonus*/
7148  int prev_separator = nk_true;
7149 
7150  /* use "best" matched letter if multiple string letters match the pattern */
7151  char const * best_letter = 0;
7152  int best_letter_score = 0;
7153 
7154  /* loop over strings */
7155  NK_ASSERT(str);
7156  NK_ASSERT(pattern);
7157  if (!str || !str_len || !pattern) return 0;
7158  while (str_iter < str_len)
7159  {
7160  const char pattern_letter = *pattern_iter;
7161  const char str_letter = str[str_iter];
7162 
7163  int next_match = *pattern_iter != '\0' &&
7164  nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
7165  int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
7166 
7167  int advanced = next_match && best_letter;
7168  int pattern_repeat = best_letter && *pattern_iter != '\0';
7169  pattern_repeat = pattern_repeat &&
7170  nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
7171 
7172  if (advanced || pattern_repeat) {
7173  score += best_letter_score;
7174  best_letter = 0;
7175  best_letter_score = 0;
7176  }
7177 
7178  if (next_match || rematch)
7179  {
7180  int new_score = 0;
7181  /* Apply penalty for each letter before the first pattern match */
7182  if (pattern_iter == pattern) {
7183  int count = (int)(&str[str_iter] - str);
7184  int penalty = NK_LEADING_LETTER_PENALTY * count;
7185  if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
7186  penalty = NK_MAX_LEADING_LETTER_PENALTY;
7187 
7188  score += penalty;
7189  }
7190 
7191  /* apply bonus for consecutive bonuses */
7192  if (prev_matched)
7193  new_score += NK_ADJACENCY_BONUS;
7194 
7195  /* apply bonus for matches after a separator */
7196  if (prev_separator)
7197  new_score += NK_SEPARATOR_BONUS;
7198 
7199  /* apply bonus across camel case boundaries */
7200  if (prev_lower && nk_is_upper(str_letter))
7201  new_score += NK_CAMEL_BONUS;
7202 
7203  /* update pattern iter IFF the next pattern letter was matched */
7204  if (next_match)
7205  ++pattern_iter;
7206 
7207  /* update best letter in str which may be for a "next" letter or a rematch */
7208  if (new_score >= best_letter_score) {
7209  /* apply penalty for now skipped letter */
7210  if (best_letter != 0)
7211  score += NK_UNMATCHED_LETTER_PENALTY;
7212 
7213  best_letter = &str[str_iter];
7214  best_letter_score = new_score;
7215  }
7216  prev_matched = nk_true;
7217  } else {
7218  score += NK_UNMATCHED_LETTER_PENALTY;
7219  prev_matched = nk_false;
7220  }
7221 
7222  /* separators should be more easily defined */
7223  prev_lower = nk_is_lower(str_letter) != 0;
7224  prev_separator = str_letter == '_' || str_letter == ' ';
7225 
7226  ++str_iter;
7227  }
7228 
7229  /* apply score for last match */
7230  if (best_letter)
7231  score += best_letter_score;
7232 
7233  /* did not match full pattern */
7234  if (*pattern_iter != '\0')
7235  return nk_false;
7236 
7237  if (out_score)
7238  *out_score = score;
7239  return nk_true;
7240 }
7253 NK_API int
7254 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
7255 {
7256  return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);
7257 }
7269 NK_LIB int
7270 nk_string_float_limit(char *string, int prec)
7271 {
7272  int dot = 0;
7273  char *c = string;
7274  while (*c) {
7275  if (*c == '.') {
7276  dot = 1;
7277  c++;
7278  continue;
7279  }
7280  if (dot == (prec+1)) {
7281  *c = 0;
7282  break;
7283  }
7284  if (dot > 0) dot++;
7285  c++;
7286  }
7287  return (int)(c - string);
7288 }
7299 NK_INTERN void
7300 nk_strrev_ascii(char *s)
7301 {
7302  int len = nk_strlen(s);
7303  int end = len / 2;
7304  int i = 0;
7305  char t;
7306  for (; i < end; ++i) {
7307  t = s[i];
7308  s[i] = s[len - 1 - i];
7309  s[len -1 - i] = t;
7310  }
7311 }
7323 NK_LIB char*
7324 nk_itoa(char *s, long n)
7325 {
7326  long i = 0;
7327  if (n == 0) {
7328  s[i++] = '0';
7329  s[i] = 0;
7330  return s;
7331  }
7332  if (n < 0) {
7333  s[i++] = '-';
7334  n = -n;
7335  }
7336  while (n > 0) {
7337  s[i++] = (char)('0' + (n % 10));
7338  n /= 10;
7339  }
7340  s[i] = 0;
7341  if (s[0] == '-')
7342  ++s;
7343 
7344  nk_strrev_ascii(s);
7345  return s;
7346 }
7347 #ifndef NK_DTOA
7348 #define NK_DTOA nk_dtoa
7360 NK_LIB char*
7361 nk_dtoa(char *s, double n)
7362 {
7363  int useExp = 0;
7364  int digit = 0, m = 0, m1 = 0;
7365  char *c = s;
7366  int neg = 0;
7367 
7368  NK_ASSERT(s);
7369  if (!s) return 0;
7370 
7371  if (n == 0.0) {
7372  s[0] = '0'; s[1] = '\0';
7373  return s;
7374  }
7375 
7376  neg = (n < 0);
7377  if (neg) n = -n;
7378 
7379  /* calculate magnitude */
7380  m = nk_log10(n);
7381  useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
7382  if (neg) *(c++) = '-';
7383 
7384  /* set up for scientific notation */
7385  if (useExp) {
7386  if (m < 0)
7387  m -= 1;
7388  n = n / (double)nk_pow(10.0, m);
7389  m1 = m;
7390  m = 0;
7391  }
7392  if (m < 1.0) {
7393  m = 0;
7394  }
7395 
7396  /* convert the number */
7397  while (n > NK_FLOAT_PRECISION || m >= 0) {
7398  double weight = nk_pow(10.0, m);
7399  if (weight > 0) {
7400  double t = (double)n / weight;
7401  digit = nk_ifloord(t);
7402  n -= ((double)digit * weight);
7403  *(c++) = (char)('0' + (char)digit);
7404  }
7405  if (m == 0 && n > 0)
7406  *(c++) = '.';
7407  m--;
7408  }
7409 
7410  if (useExp) {
7411  /* convert the exponent */
7412  int i, j;
7413  *(c++) = 'e';
7414  if (m1 > 0) {
7415  *(c++) = '+';
7416  } else {
7417  *(c++) = '-';
7418  m1 = -m1;
7419  }
7420  m = 0;
7421  while (m1 > 0) {
7422  *(c++) = (char)('0' + (char)(m1 % 10));
7423  m1 /= 10;
7424  m++;
7425  }
7426  c -= m;
7427  for (i = 0, j = m-1; i<j; i++, j--) {
7428  /* swap without temporary */
7429  c[i] ^= c[j];
7430  c[j] ^= c[i];
7431  c[i] ^= c[j];
7432  }
7433  c += m;
7434  }
7435  *(c) = '\0';
7436  return s;
7437 }
7438 #endif
7439 #ifdef NK_INCLUDE_STANDARD_VARARGS
7440 #ifndef NK_INCLUDE_STANDARD_IO
7454 NK_INTERN int
7455 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
7456 {
7457  enum nk_arg_type {
7458  NK_ARG_TYPE_CHAR,
7459  NK_ARG_TYPE_SHORT,
7460  NK_ARG_TYPE_DEFAULT,
7461  NK_ARG_TYPE_LONG
7462  };
7463  enum nk_arg_flags {
7464  NK_ARG_FLAG_LEFT = 0x01,
7465  NK_ARG_FLAG_PLUS = 0x02,
7466  NK_ARG_FLAG_SPACE = 0x04,
7467  NK_ARG_FLAG_NUM = 0x10,
7468  NK_ARG_FLAG_ZERO = 0x20
7469  };
7470 
7471  char number_buffer[NK_MAX_NUMBER_BUFFER];
7472  enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
7473  int precision = NK_DEFAULT;
7474  int width = NK_DEFAULT;
7475  nk_flags flag = 0;
7476 
7477  int len = 0;
7478  int result = -1;
7479  const char *iter = fmt;
7480 
7481  NK_ASSERT(buf);
7482  NK_ASSERT(buf_size);
7483  if (!buf || !buf_size || !fmt) return 0;
7484  for (iter = fmt; *iter && len < buf_size; iter++) {
7485  /* copy all non-format characters */
7486  while (*iter && (*iter != '%') && (len < buf_size))
7487  buf[len++] = *iter++;
7488  if (!(*iter) || len >= buf_size) break;
7489  iter++;
7490 
7491  /* flag arguments */
7492  while (*iter) {
7493  if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
7494  else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
7495  else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
7496  else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
7497  else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
7498  else break;
7499  iter++;
7500  }
7501 
7502  /* width argument */
7503  width = NK_DEFAULT;
7504  if (*iter >= '1' && *iter <= '9') {
7505  const char *end;
7506  width = nk_strtoi(iter, &end);
7507  if (end == iter)
7508  width = -1;
7509  else iter = end;
7510  } else if (*iter == '*') {
7511  width = va_arg(args, int);
7512  iter++;
7513  }
7514 
7515  /* precision argument */
7516  precision = NK_DEFAULT;
7517  if (*iter == '.') {
7518  iter++;
7519  if (*iter == '*') {
7520  precision = va_arg(args, int);
7521  iter++;
7522  } else {
7523  const char *end;
7524  precision = nk_strtoi(iter, &end);
7525  if (end == iter)
7526  precision = -1;
7527  else iter = end;
7528  }
7529  }
7530 
7531  /* length modifier */
7532  if (*iter == 'h') {
7533  if (*(iter+1) == 'h') {
7534  arg_type = NK_ARG_TYPE_CHAR;
7535  iter++;
7536  } else arg_type = NK_ARG_TYPE_SHORT;
7537  iter++;
7538  } else if (*iter == 'l') {
7539  arg_type = NK_ARG_TYPE_LONG;
7540  iter++;
7541  } else arg_type = NK_ARG_TYPE_DEFAULT;
7542 
7543  /* specifier */
7544  if (*iter == '%') {
7545  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
7546  NK_ASSERT(precision == NK_DEFAULT);
7547  NK_ASSERT(width == NK_DEFAULT);
7548  if (len < buf_size)
7549  buf[len++] = '%';
7550  } else if (*iter == 's') {
7551  /* string */
7552  const char *str = va_arg(args, const char*);
7553  NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
7554  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
7555  NK_ASSERT(precision == NK_DEFAULT);
7556  NK_ASSERT(width == NK_DEFAULT);
7557  if (str == buf) return -1;
7558  while (str && *str && len < buf_size)
7559  buf[len++] = *str++;
7560  } else if (*iter == 'n') {
7561  /* current length callback */
7562  signed int *n = va_arg(args, int*);
7563  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
7564  NK_ASSERT(precision == NK_DEFAULT);
7565  NK_ASSERT(width == NK_DEFAULT);
7566  if (n) *n = len;
7567  } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
7568  /* signed integer */
7569  long value = 0;
7570  const char *num_iter;
7571  int num_len, num_print, padding;
7572  int cur_precision = NK_MAX(precision, 1);
7573  int cur_width = NK_MAX(width, 0);
7574 
7575  /* retrieve correct value type */
7576  if (arg_type == NK_ARG_TYPE_CHAR)
7577  value = (signed char)va_arg(args, int);
7578  else if (arg_type == NK_ARG_TYPE_SHORT)
7579  value = (signed short)va_arg(args, int);
7580  else if (arg_type == NK_ARG_TYPE_LONG)
7581  value = va_arg(args, signed long);
7582  else if (*iter == 'c')
7583  value = (unsigned char)va_arg(args, int);
7584  else value = va_arg(args, signed int);
7585 
7586  /* convert number to string */
7587  nk_itoa(number_buffer, value);
7588  num_len = nk_strlen(number_buffer);
7589  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
7590  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
7591  padding = NK_MAX(padding-1, 0);
7592 
7593  /* fill left padding up to a total of `width` characters */
7594  if (!(flag & NK_ARG_FLAG_LEFT)) {
7595  while (padding-- > 0 && (len < buf_size)) {
7596  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
7597  buf[len++] = '0';
7598  else buf[len++] = ' ';
7599  }
7600  }
7601 
7602  /* copy string value representation into buffer */
7603  if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
7604  buf[len++] = '+';
7605  else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
7606  buf[len++] = ' ';
7607 
7608  /* fill up to precision number of digits with '0' */
7609  num_print = NK_MAX(cur_precision, num_len);
7610  while (precision && (num_print > num_len) && (len < buf_size)) {
7611  buf[len++] = '0';
7612  num_print--;
7613  }
7614 
7615  /* copy string value representation into buffer */
7616  num_iter = number_buffer;
7617  while (precision && *num_iter && len < buf_size)
7618  buf[len++] = *num_iter++;
7619 
7620  /* fill right padding up to width characters */
7621  if (flag & NK_ARG_FLAG_LEFT) {
7622  while ((padding-- > 0) && (len < buf_size))
7623  buf[len++] = ' ';
7624  }
7625  } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
7626  /* unsigned integer */
7627  unsigned long value = 0;
7628  int num_len = 0, num_print, padding = 0;
7629  int cur_precision = NK_MAX(precision, 1);
7630  int cur_width = NK_MAX(width, 0);
7631  unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
7632 
7633  /* print oct/hex/dec value */
7634  const char *upper_output_format = "0123456789ABCDEF";
7635  const char *lower_output_format = "0123456789abcdef";
7636  const char *output_format = (*iter == 'x') ?
7637  lower_output_format: upper_output_format;
7638 
7639  /* retrieve correct value type */
7640  if (arg_type == NK_ARG_TYPE_CHAR)
7641  value = (unsigned char)va_arg(args, int);
7642  else if (arg_type == NK_ARG_TYPE_SHORT)
7643  value = (unsigned short)va_arg(args, int);
7644  else if (arg_type == NK_ARG_TYPE_LONG)
7645  value = va_arg(args, unsigned long);
7646  else value = va_arg(args, unsigned int);
7647 
7648  do {
7649  /* convert decimal number into hex/oct number */
7650  int digit = output_format[value % base];
7651  if (num_len < NK_MAX_NUMBER_BUFFER)
7652  number_buffer[num_len++] = (char)digit;
7653  value /= base;
7654  } while (value > 0);
7655 
7656  num_print = NK_MAX(cur_precision, num_len);
7657  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
7658  if (flag & NK_ARG_FLAG_NUM)
7659  padding = NK_MAX(padding-1, 0);
7660 
7661  /* fill left padding up to a total of `width` characters */
7662  if (!(flag & NK_ARG_FLAG_LEFT)) {
7663  while ((padding-- > 0) && (len < buf_size)) {
7664  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
7665  buf[len++] = '0';
7666  else buf[len++] = ' ';
7667  }
7668  }
7669 
7670  /* fill up to precision number of digits */
7671  if (num_print && (flag & NK_ARG_FLAG_NUM)) {
7672  if ((*iter == 'o') && (len < buf_size)) {
7673  buf[len++] = '0';
7674  } else if ((*iter == 'x') && ((len+1) < buf_size)) {
7675  buf[len++] = '0';
7676  buf[len++] = 'x';
7677  } else if ((*iter == 'X') && ((len+1) < buf_size)) {
7678  buf[len++] = '0';
7679  buf[len++] = 'X';
7680  }
7681  }
7682  while (precision && (num_print > num_len) && (len < buf_size)) {
7683  buf[len++] = '0';
7684  num_print--;
7685  }
7686 
7687  /* reverse number direction */
7688  while (num_len > 0) {
7689  if (precision && (len < buf_size))
7690  buf[len++] = number_buffer[num_len-1];
7691  num_len--;
7692  }
7693 
7694  /* fill right padding up to width characters */
7695  if (flag & NK_ARG_FLAG_LEFT) {
7696  while ((padding-- > 0) && (len < buf_size))
7697  buf[len++] = ' ';
7698  }
7699  } else if (*iter == 'f') {
7700  /* floating point */
7701  const char *num_iter;
7702  int cur_precision = (precision < 0) ? 6: precision;
7703  int prefix, cur_width = NK_MAX(width, 0);
7704  double value = va_arg(args, double);
7705  int num_len = 0, frac_len = 0, dot = 0;
7706  int padding = 0;
7707 
7708  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
7709  NK_DTOA(number_buffer, value);
7710  num_len = nk_strlen(number_buffer);
7711 
7712  /* calculate padding */
7713  num_iter = number_buffer;
7714  while (*num_iter && *num_iter != '.')
7715  num_iter++;
7716 
7717  prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
7718  padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
7719  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
7720  padding = NK_MAX(padding-1, 0);
7721 
7722  /* fill left padding up to a total of `width` characters */
7723  if (!(flag & NK_ARG_FLAG_LEFT)) {
7724  while (padding-- > 0 && (len < buf_size)) {
7725  if (flag & NK_ARG_FLAG_ZERO)
7726  buf[len++] = '0';
7727  else buf[len++] = ' ';
7728  }
7729  }
7730 
7731  /* copy string value representation into buffer */
7732  num_iter = number_buffer;
7733  if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
7734  buf[len++] = '+';
7735  else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
7736  buf[len++] = ' ';
7737  while (*num_iter) {
7738  if (dot) frac_len++;
7739  if (len < buf_size)
7740  buf[len++] = *num_iter;
7741  if (*num_iter == '.') dot = 1;
7742  if (frac_len >= cur_precision) break;
7743  num_iter++;
7744  }
7745 
7746  /* fill number up to precision */
7747  while (frac_len < cur_precision) {
7748  if (!dot && len < buf_size) {
7749  buf[len++] = '.';
7750  dot = 1;
7751  }
7752  if (len < buf_size)
7753  buf[len++] = '0';
7754  frac_len++;
7755  }
7756 
7757  /* fill right padding up to width characters */
7758  if (flag & NK_ARG_FLAG_LEFT) {
7759  while ((padding-- > 0) && (len < buf_size))
7760  buf[len++] = ' ';
7761  }
7762  } else {
7763  /* Specifier not supported: g,G,e,E,p,z */
7764  NK_ASSERT(0 && "specifier is not supported!");
7765  return result;
7766  }
7767  }
7768  buf[(len >= buf_size)?(buf_size-1):len] = 0;
7769  result = (len >= buf_size)?-1:len;
7770  return result;
7771 }
7772 #endif
7786 NK_LIB int
7787 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
7788 {
7789  int result = -1;
7790  NK_ASSERT(buf);
7791  NK_ASSERT(buf_size);
7792  if (!buf || !buf_size || !fmt) return 0;
7793 #ifdef NK_INCLUDE_STANDARD_IO
7794  result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
7795  result = (result >= buf_size) ? -1: result;
7796  buf[buf_size-1] = 0;
7797 #else
7798  result = nk_vsnprintf(buf, buf_size, fmt, args);
7799 #endif
7800  return result;
7801 }
7802 #endif
7815 NK_API nk_hash
7816 nk_murmur_hash(const void * key, int len, nk_hash seed)
7817 {
7818  /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
7819  #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
7820 
7821  nk_uint h1 = seed;
7822  nk_uint k1;
7823  const nk_byte *data = (const nk_byte*)key;
7824  const nk_byte *keyptr = data;
7825  nk_byte *k1ptr;
7826  const int bsize = sizeof(k1);
7827  const int nblocks = len/4;
7828 
7829  const nk_uint c1 = 0xcc9e2d51;
7830  const nk_uint c2 = 0x1b873593;
7831  const nk_byte *tail;
7832  int i;
7833 
7834  /* body */
7835  if (!key) return 0;
7836  for (i = 0; i < nblocks; ++i, keyptr += bsize) {
7837  k1ptr = (nk_byte*)&k1;
7838  k1ptr[0] = keyptr[0];
7839  k1ptr[1] = keyptr[1];
7840  k1ptr[2] = keyptr[2];
7841  k1ptr[3] = keyptr[3];
7842 
7843  k1 *= c1;
7844  k1 = NK_ROTL(k1,15);
7845  k1 *= c2;
7846 
7847  h1 ^= k1;
7848  h1 = NK_ROTL(h1,13);
7849  h1 = h1*5+0xe6546b64;
7850  }
7851 
7852  /* tail */
7853  tail = (const nk_byte*)(data + nblocks*4);
7854  k1 = 0;
7855  switch (len & 3) {
7856  case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */
7857  case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */
7858  case 1: k1 ^= tail[0];
7859  k1 *= c1;
7860  k1 = NK_ROTL(k1,15);
7861  k1 *= c2;
7862  h1 ^= k1;
7863  break;
7864  default: break;
7865  }
7866 
7867  /* finalization */
7868  h1 ^= (nk_uint)len;
7869  /* fmix32 */
7870  h1 ^= h1 >> 16;
7871  h1 *= 0x85ebca6b;
7872  h1 ^= h1 >> 13;
7873  h1 *= 0xc2b2ae35;
7874  h1 ^= h1 >> 16;
7875 
7876  #undef NK_ROTL
7877  return h1;
7878 }
7879 #ifdef NK_INCLUDE_STANDARD_IO
7892 NK_LIB char*
7893 nk_file_load(const char* path, nk_size* siz, const struct nk_allocator *alloc)
7894 {
7895  char *buf;
7896  FILE *fd;
7897  long ret;
7898 
7899  NK_ASSERT(path);
7900  NK_ASSERT(siz);
7901  NK_ASSERT(alloc);
7902  if (!path || !siz || !alloc)
7903  return 0;
7904 
7905  fd = fopen(path, "rb");
7906  if (!fd) return 0;
7907  fseek(fd, 0, SEEK_END);
7908  ret = ftell(fd);
7909  if (ret < 0) {
7910  fclose(fd);
7911  return 0;
7912  }
7913  *siz = (nk_size)ret;
7914  fseek(fd, 0, SEEK_SET);
7915  buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
7916  NK_ASSERT(buf);
7917  if (!buf) {
7918  fclose(fd);
7919  return 0;
7920  }
7921  *siz = (nk_size)fread(buf, 1,*siz, fd);
7922  fclose(fd);
7923  return buf;
7924 }
7925 #endif
7937 NK_LIB int
7938 nk_text_clamp(const struct nk_user_font *font, const char *text,
7939  int text_len, float space, int *glyphs, float *text_width,
7940  nk_rune *sep_list, int sep_count)
7941 {
7942  int i = 0;
7943  int glyph_len = 0;
7944  float last_width = 0;
7945  nk_rune unicode = 0;
7946  float width = 0;
7947  int len = 0;
7948  int g = 0;
7949  float s;
7950 
7951  int sep_len = 0;
7952  int sep_g = 0;
7953  float sep_width = 0;
7954  sep_count = NK_MAX(sep_count,0);
7955 
7956  glyph_len = nk_utf_decode(text, &unicode, text_len);
7957  while (glyph_len && (width < space) && (len < text_len)) {
7958  len += glyph_len;
7959  s = font->width(font->userdata, font->height, text, len);
7960  for (i = 0; i < sep_count; ++i) {
7961  if (unicode != sep_list[i]) continue;
7962  sep_width = last_width = width;
7963  sep_g = g+1;
7964  sep_len = len;
7965  break;
7966  }
7967  if (i == sep_count){
7968  last_width = sep_width = width;
7969  sep_g = g+1;
7970  }
7971  width = s;
7972  glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
7973  g++;
7974  }
7975  if (len >= text_len) {
7976  *glyphs = g;
7977  *text_width = last_width;
7978  return len;
7979  } else {
7980  *glyphs = sep_g;
7981  *text_width = sep_width;
7982  return (!sep_len) ? len: sep_len;
7983  }
7984 }
7995 NK_LIB struct nk_vec2
7996 nk_text_calculate_text_bounds(const struct nk_user_font *font,
7997  const char *begin, int byte_len, float row_height, const char **remaining,
7998  struct nk_vec2 *out_offset, int *glyphs, int op)
7999 {
8000  float line_height = row_height;
8001  struct nk_vec2 text_size = nk_vec2(0,0);
8002  float line_width = 0.0f;
8003 
8004  float glyph_width;
8005  int glyph_len = 0;
8006  nk_rune unicode = 0;
8007  int text_len = 0;
8008  if (!begin || byte_len <= 0 || !font)
8009  return nk_vec2(0,row_height);
8010 
8011  glyph_len = nk_utf_decode(begin, &unicode, byte_len);
8012  if (!glyph_len) return text_size;
8013  glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
8014 
8015  *glyphs = 0;
8016  while ((text_len < byte_len) && glyph_len) {
8017  if (unicode == '\n') {
8018  text_size.x = NK_MAX(text_size.x, line_width);
8019  text_size.y += line_height;
8020  line_width = 0;
8021  *glyphs+=1;
8022  if (op == NK_STOP_ON_NEW_LINE)
8023  break;
8024 
8025  text_len++;
8026  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
8027  continue;
8028  }
8029 
8030  if (unicode == '\r') {
8031  text_len++;
8032  *glyphs+=1;
8033  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
8034  continue;
8035  }
8036 
8037  *glyphs = *glyphs + 1;
8038  text_len += glyph_len;
8039  line_width += (float)glyph_width;
8040  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
8041  glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
8042  continue;
8043  }
8044 
8045  if (text_size.x < line_width)
8046  text_size.x = line_width;
8047  if (out_offset)
8048  *out_offset = nk_vec2(line_width, text_size.y + line_height);
8049  if (line_width > 0 || text_size.y == 0.0f)
8050  text_size.y += line_height;
8051  if (remaining)
8052  *remaining = begin+text_len;
8053  return text_size;
8054 }
8055 
8056 
8057 
8058 
8059 
8060 /* ==============================================================
8061  *
8062  * COLOR
8063  *
8064  * ===============================================================*/
8076 NK_INTERN int
8077 nk_parse_hex(const char *p, int length)
8078 {
8079  int i = 0;
8080  int len = 0;
8081  while (len < length) {
8082  i <<= 4;
8083  if (p[len] >= 'a' && p[len] <= 'f')
8084  i += ((p[len] - 'a') + 10);
8085  else if (p[len] >= 'A' && p[len] <= 'F')
8086  i += ((p[len] - 'A') + 10);
8087  else i += (p[len] - '0');
8088  len++;
8089  }
8090  return i;
8091 }
8103 NK_API struct nk_color
8104 nk_rgb_factor(struct nk_color col, float factor)
8105 {
8106  if (factor == 1.0f)
8107  return col;
8108  col.r = (nk_byte)(col.r * factor);
8109  col.g = (nk_byte)(col.g * factor);
8110  col.b = (nk_byte)(col.b * factor);
8111  return col;
8112 }
8126 NK_API struct nk_color
8127 nk_rgba(int r, int g, int b, int a)
8128 {
8129  struct nk_color ret;
8130  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
8131  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
8132  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
8133  ret.a = (nk_byte)NK_CLAMP(0, a, 255);
8134  return ret;
8135 }
8146 NK_API struct nk_color
8147 nk_rgb_hex(const char *rgb)
8148 {
8149  struct nk_color col;
8150  const char *c = rgb;
8151  if (*c == '#') c++;
8152  col.r = (nk_byte)nk_parse_hex(c, 2);
8153  col.g = (nk_byte)nk_parse_hex(c+2, 2);
8154  col.b = (nk_byte)nk_parse_hex(c+4, 2);
8155  col.a = 255;
8156  return col;
8157 }
8168 NK_API struct nk_color
8169 nk_rgba_hex(const char *rgb)
8170 {
8171  struct nk_color col;
8172  const char *c = rgb;
8173  if (*c == '#') c++;
8174  col.r = (nk_byte)nk_parse_hex(c, 2);
8175  col.g = (nk_byte)nk_parse_hex(c+2, 2);
8176  col.b = (nk_byte)nk_parse_hex(c+4, 2);
8177  col.a = (nk_byte)nk_parse_hex(c+6, 2);
8178  return col;
8179 }
8191 NK_API void
8192 nk_color_hex_rgba(char *output, struct nk_color col)
8193 {
8194  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
8195  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
8196  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
8197  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
8198  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
8199  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
8200  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
8201  output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
8202  output[7] = (char)NK_TO_HEX((col.a & 0x0F));
8203  output[8] = '\0';
8204  #undef NK_TO_HEX
8205 }
8217 NK_API void
8218 nk_color_hex_rgb(char *output, struct nk_color col)
8219 {
8220  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
8221  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
8222  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
8223  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
8224  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
8225  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
8226  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
8227  output[6] = '\0';
8228  #undef NK_TO_HEX
8229 }
8240 NK_API struct nk_color
8241 nk_rgba_iv(const int *c)
8242 {
8243  return nk_rgba(c[0], c[1], c[2], c[3]);
8244 }
8255 NK_API struct nk_color
8256 nk_rgba_bv(const nk_byte *c)
8257 {
8258  return nk_rgba(c[0], c[1], c[2], c[3]);
8259 }
8272 NK_API struct nk_color
8273 nk_rgb(int r, int g, int b)
8274 {
8275  struct nk_color ret;
8276  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
8277  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
8278  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
8279  ret.a = (nk_byte)255;
8280  return ret;
8281 }
8292 NK_API struct nk_color
8293 nk_rgb_iv(const int *c)
8294 {
8295  return nk_rgb(c[0], c[1], c[2]);
8296 }
8307 NK_API struct nk_color
8308 nk_rgb_bv(const nk_byte* c)
8309 {
8310  return nk_rgb(c[0], c[1], c[2]);
8311 }
8322 NK_API struct nk_color
8323 nk_rgba_u32(nk_uint in)
8324 {
8325  struct nk_color ret;
8326  ret.r = (in & 0xFF);
8327  ret.g = ((in >> 8) & 0xFF);
8328  ret.b = ((in >> 16) & 0xFF);
8329  ret.a = (nk_byte)((in >> 24) & 0xFF);
8330  return ret;
8331 }
8345 NK_API struct nk_color
8346 nk_rgba_f(float r, float g, float b, float a)
8347 {
8348  struct nk_color ret;
8349  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
8350  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
8351  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
8352  ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
8353  return ret;
8354 }
8365 NK_API struct nk_color
8366 nk_rgba_fv(const float *c)
8367 {
8368  return nk_rgba_f(c[0], c[1], c[2], c[3]);
8369 }
8380 NK_API struct nk_color
8381 nk_rgba_cf(struct nk_colorf c)
8382 {
8383  return nk_rgba_f(c.r, c.g, c.b, c.a);
8384 }
8397 NK_API struct nk_color
8398 nk_rgb_f(float r, float g, float b)
8399 {
8400  struct nk_color ret;
8401  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
8402  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
8403  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
8404  ret.a = 255;
8405  return ret;
8406 }
8417 NK_API struct nk_color
8418 nk_rgb_fv(const float *c)
8419 {
8420  return nk_rgb_f(c[0], c[1], c[2]);
8421 }
8432 NK_API struct nk_color
8433 nk_rgb_cf(struct nk_colorf c)
8434 {
8435  return nk_rgb_f(c.r, c.g, c.b);
8436 }
8449 NK_API struct nk_color
8450 nk_hsv(int h, int s, int v)
8451 {
8452  return nk_hsva(h, s, v, 255);
8453 }
8464 NK_API struct nk_color
8465 nk_hsv_iv(const int *c)
8466 {
8467  return nk_hsv(c[0], c[1], c[2]);
8468 }
8479 NK_API struct nk_color
8480 nk_hsv_bv(const nk_byte *c)
8481 {
8482  return nk_hsv(c[0], c[1], c[2]);
8483 }
8496 NK_API struct nk_color
8497 nk_hsv_f(float h, float s, float v)
8498 {
8499  return nk_hsva_f(h, s, v, 1.0f);
8500 }
8511 NK_API struct nk_color
8512 nk_hsv_fv(const float *c)
8513 {
8514  return nk_hsv_f(c[0], c[1], c[2]);
8515 }
8529 NK_API struct nk_color
8530 nk_hsva(int h, int s, int v, int a)
8531 {
8532  float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
8533  float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
8534  float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
8535  float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
8536  return nk_hsva_f(hf, sf, vf, af);
8537 }
8548 NK_API struct nk_color
8549 nk_hsva_iv(const int *c)
8550 {
8551  return nk_hsva(c[0], c[1], c[2], c[3]);
8552 }
8563 NK_API struct nk_color
8564 nk_hsva_bv(const nk_byte *c)
8565 {
8566  return nk_hsva(c[0], c[1], c[2], c[3]);
8567 }
8581 NK_API struct nk_colorf
8582 nk_hsva_colorf(float h, float s, float v, float a)
8583 {
8584  int i;
8585  float p, q, t, f;
8586  struct nk_colorf out = {0,0,0,0};
8587  if (s <= 0.0f) {
8588  out.r = v; out.g = v; out.b = v; out.a = a;
8589  return out;
8590  }
8591  h = h / (60.0f/360.0f);
8592  i = (int)h;
8593  f = h - (float)i;
8594  p = v * (1.0f - s);
8595  q = v * (1.0f - (s * f));
8596  t = v * (1.0f - s * (1.0f - f));
8597 
8598  switch (i) {
8599  case 0: default: out.r = v; out.g = t; out.b = p; break;
8600  case 1: out.r = q; out.g = v; out.b = p; break;
8601  case 2: out.r = p; out.g = v; out.b = t; break;
8602  case 3: out.r = p; out.g = q; out.b = v; break;
8603  case 4: out.r = t; out.g = p; out.b = v; break;
8604  case 5: out.r = v; out.g = p; out.b = q; break;}
8605  out.a = a;
8606  return out;
8607 }
8618 NK_API struct nk_colorf
8619 nk_hsva_colorfv(const float *c)
8620 {
8621  return nk_hsva_colorf(c[0], c[1], c[2], c[3]);
8622 }
8636 NK_API struct nk_color
8637 nk_hsva_f(float h, float s, float v, float a)
8638 {
8639  struct nk_colorf c = nk_hsva_colorf(h, s, v, a);
8640  return nk_rgba_f(c.r, c.g, c.b, c.a);
8641 }
8652 NK_API struct nk_color
8653 nk_hsva_fv(const float *c)
8654 {
8655  return nk_hsva_f(c[0], c[1], c[2], c[3]);
8656 }
8667 NK_API nk_uint
8668 nk_color_u32(struct nk_color in)
8669 {
8670  nk_uint out = (nk_uint)in.r;
8671  out |= ((nk_uint)in.g << 8);
8672  out |= ((nk_uint)in.b << 16);
8673  out |= ((nk_uint)in.a << 24);
8674  return out;
8675 }
8690 NK_API void
8691 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
8692 {
8693  NK_STORAGE const float s = 1.0f/255.0f;
8694  *r = (float)in.r * s;
8695  *g = (float)in.g * s;
8696  *b = (float)in.b * s;
8697  *a = (float)in.a * s;
8698 }
8710 NK_API void
8711 nk_color_fv(float *c, struct nk_color in)
8712 {
8713  nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
8714 }
8725 NK_API struct nk_colorf
8726 nk_color_cf(struct nk_color in)
8727 {
8728  struct nk_colorf o;
8729  nk_color_f(&o.r, &o.g, &o.b, &o.a, in);
8730  return o;
8731 }
8746 NK_API void
8747 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
8748 {
8749  NK_STORAGE const double s = 1.0/255.0;
8750  *r = (double)in.r * s;
8751  *g = (double)in.g * s;
8752  *b = (double)in.b * s;
8753  *a = (double)in.a * s;
8754 }
8766 NK_API void
8767 nk_color_dv(double *c, struct nk_color in)
8768 {
8769  nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
8770 }
8784 NK_API void
8785 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
8786 {
8787  float a;
8788  nk_color_hsva_f(out_h, out_s, out_v, &a, in);
8789 }
8801 NK_API void
8802 nk_color_hsv_fv(float *out, struct nk_color in)
8803 {
8804  float a;
8805  nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
8806 }
8818 NK_API void
8819 nk_colorf_hsva_f(float *out_h, float *out_s,
8820  float *out_v, float *out_a, struct nk_colorf in)
8821 {
8822  float chroma;
8823  float K = 0.0f;
8824  if (in.g < in.b) {
8825  const float t = in.g; in.g = in.b; in.b = t;
8826  K = -1.f;
8827  }
8828  if (in.r < in.g) {
8829  const float t = in.r; in.r = in.g; in.g = t;
8830  K = -2.f/6.0f - K;
8831  }
8832  chroma = in.r - ((in.g < in.b) ? in.g: in.b);
8833  *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f));
8834  *out_s = chroma / (in.r + 1e-20f);
8835  *out_v = in.r;
8836  *out_a = in.a;
8837 
8838 }
8850 NK_API void
8851 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in)
8852 {
8853  nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in);
8854 }
8866 NK_API void
8867 nk_color_hsva_f(float *out_h, float *out_s,
8868  float *out_v, float *out_a, struct nk_color in)
8869 {
8870  struct nk_colorf col;
8871  nk_color_f(&col.r,&col.g,&col.b,&col.a, in);
8872  nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col);
8873 }
8885 NK_API void
8886 nk_color_hsva_fv(float *out, struct nk_color in)
8887 {
8888  nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
8889 }
8902 NK_API void
8903 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
8904  int *out_a, struct nk_color in)
8905 {
8906  float h,s,v,a;
8907  nk_color_hsva_f(&h, &s, &v, &a, in);
8908  *out_h = (nk_byte)(h * 255.0f);
8909  *out_s = (nk_byte)(s * 255.0f);
8910  *out_v = (nk_byte)(v * 255.0f);
8911  *out_a = (nk_byte)(a * 255.0f);
8912 }
8924 NK_API void
8925 nk_color_hsva_iv(int *out, struct nk_color in)
8926 {
8927  nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
8928 }
8940 NK_API void
8941 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
8942 {
8943  int tmp[4];
8944  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
8945  out[0] = (nk_byte)tmp[0];
8946  out[1] = (nk_byte)tmp[1];
8947  out[2] = (nk_byte)tmp[2];
8948  out[3] = (nk_byte)tmp[3];
8949 }
8964 NK_API void
8965 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
8966 {
8967  int tmp[4];
8968  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
8969  *h = (nk_byte)tmp[0];
8970  *s = (nk_byte)tmp[1];
8971  *v = (nk_byte)tmp[2];
8972  *a = (nk_byte)tmp[3];
8973 }
8987 NK_API void
8988 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
8989 {
8990  int a;
8991  nk_color_hsva_i(out_h, out_s, out_v, &a, in);
8992 }
9006 NK_API void
9007 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
9008 {
9009  int tmp[4];
9010  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
9011  *out_h = (nk_byte)tmp[0];
9012  *out_s = (nk_byte)tmp[1];
9013  *out_v = (nk_byte)tmp[2];
9014 }
9026 NK_API void
9027 nk_color_hsv_iv(int *out, struct nk_color in)
9028 {
9029  nk_color_hsv_i(&out[0], &out[1], &out[2], in);
9030 }
9042 NK_API void
9043 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
9044 {
9045  int tmp[4];
9046  nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
9047  out[0] = (nk_byte)tmp[0];
9048  out[1] = (nk_byte)tmp[1];
9049  out[2] = (nk_byte)tmp[2];
9050 }
9051 
9052 
9053 
9054 
9055 /* ===============================================================
9056  *
9057  * UTF-8
9058  *
9059  * ===============================================================*/
9060 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
9061 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
9062 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
9063 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
9064 
9076 NK_INTERN int
9077 nk_utf_validate(nk_rune *u, int i)
9078 {
9079  NK_ASSERT(u);
9080  if (!u) return 0;
9081  if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
9082  NK_BETWEEN(*u, 0xD800, 0xDFFF))
9083  *u = NK_UTF_INVALID;
9084  for (i = 1; *u > nk_utfmax[i]; ++i);
9085  return i;
9086 }
9098 NK_INTERN nk_rune
9099 nk_utf_decode_byte(char c, int *i)
9100 {
9101  NK_ASSERT(i);
9102  if (!i) return 0;
9103  for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
9104  if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
9105  return (nk_byte)(c & ~nk_utfmask[*i]);
9106  }
9107  return 0;
9108 }
9121 NK_API int
9122 nk_utf_decode(const char *c, nk_rune *u, int clen)
9123 {
9124  int i, j, len, type=0;
9125  nk_rune udecoded;
9126 
9127  NK_ASSERT(c);
9128  NK_ASSERT(u);
9129 
9130  if (!c || !u) return 0;
9131  if (!clen) return 0;
9132  *u = NK_UTF_INVALID;
9133 
9134  udecoded = nk_utf_decode_byte(c[0], &len);
9135  if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
9136  return 1;
9137 
9138  for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
9139  udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
9140  if (type != 0)
9141  return j;
9142  }
9143  if (j < len)
9144  return 0;
9145  *u = udecoded;
9146  nk_utf_validate(u, len);
9147  return len;
9148 }
9160 NK_INTERN char
9161 nk_utf_encode_byte(nk_rune u, int i)
9162 {
9163  return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
9164 }
9177 NK_API int
9178 nk_utf_encode(nk_rune u, char *c, int clen)
9179 {
9180  int len, i;
9181  len = nk_utf_validate(&u, 0);
9182  if (clen < len || !len || len > NK_UTF_SIZE)
9183  return 0;
9184 
9185  for (i = len - 1; i != 0; --i) {
9186  c[i] = nk_utf_encode_byte(u, 0);
9187  u >>= 6;
9188  }
9189  c[0] = nk_utf_encode_byte(u, len);
9190  return len;
9191 }
9203 NK_API int
9204 nk_utf_len(const char *str, int len)
9205 {
9206  const char *text;
9207  int glyphs = 0;
9208  int text_len;
9209  int glyph_len;
9210  int src_len = 0;
9211  nk_rune unicode;
9212 
9213  NK_ASSERT(str);
9214  if (!str || !len) return 0;
9215 
9216  text = str;
9217  text_len = len;
9218  glyph_len = nk_utf_decode(text, &unicode, text_len);
9219  while (glyph_len && src_len < len) {
9220  glyphs++;
9221  src_len = src_len + glyph_len;
9222  glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
9223  }
9224  return glyphs;
9225 }
9238 NK_API const char*
9239 nk_utf_at(const char *buffer, int length, int index,
9240  nk_rune *unicode, int *len)
9241 {
9242  int i = 0;
9243  int src_len = 0;
9244  int glyph_len = 0;
9245  const char *text;
9246  int text_len;
9247 
9248  NK_ASSERT(buffer);
9249  NK_ASSERT(unicode);
9250  NK_ASSERT(len);
9251 
9252  if (!buffer || !unicode || !len) return 0;
9253  if (index < 0) {
9254  *unicode = NK_UTF_INVALID;
9255  *len = 0;
9256  return 0;
9257  }
9258 
9259  text = buffer;
9260  text_len = length;
9261  glyph_len = nk_utf_decode(text, unicode, text_len);
9262  while (glyph_len) {
9263  if (i == index) {
9264  *len = glyph_len;
9265  break;
9266  }
9267 
9268  i++;
9269  src_len = src_len + glyph_len;
9270  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
9271  }
9272  if (i != index) return 0;
9273  return buffer + src_len;
9274 }
9275 
9276 
9277 
9278 
9279 
9280 /* ==============================================================
9281  *
9282  * BUFFER
9283  *
9284  * ===============================================================*/
9285 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
9298 NK_LIB void*
9299 nk_malloc(nk_handle unused, void *old,nk_size size)
9300 {
9301  NK_UNUSED(unused);
9302  NK_UNUSED(old);
9303  return malloc(size);
9304 }
9316 NK_LIB void
9317 nk_mfree(nk_handle unused, void *ptr)
9318 {
9319  NK_UNUSED(unused);
9320  free(ptr);
9321 }
9332 NK_API void
9333 nk_buffer_init_default(struct nk_buffer *buffer)
9334 {
9335  struct nk_allocator alloc;
9336  alloc.userdata.ptr = 0;
9337  alloc.alloc = nk_malloc;
9338  alloc.free = nk_mfree;
9339  nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
9340 }
9341 #endif
9342 
9354 NK_API void
9355 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
9356  nk_size initial_size)
9357 {
9358  NK_ASSERT(b);
9359  NK_ASSERT(a);
9360  NK_ASSERT(initial_size);
9361  if (!b || !a || !initial_size) return;
9362 
9363  nk_zero(b, sizeof(*b));
9364  b->type = NK_BUFFER_DYNAMIC;
9365  b->memory.ptr = a->alloc(a->userdata,0, initial_size);
9366  b->memory.size = initial_size;
9367  b->size = initial_size;
9368  b->grow_factor = 2.0f;
9369  b->pool = *a;
9370 }
9383 NK_API void
9384 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
9385 {
9386  NK_ASSERT(b);
9387  NK_ASSERT(m);
9388  NK_ASSERT(size);
9389  if (!b || !m || !size) return;
9390 
9391  nk_zero(b, sizeof(*b));
9392  b->type = NK_BUFFER_FIXED;
9393  b->memory.ptr = m;
9394  b->memory.size = size;
9395  b->size = size;
9396 }
9407 NK_LIB void*
9408 nk_buffer_align(void *unaligned,
9409  nk_size align, nk_size *alignment,
9410  enum nk_buffer_allocation_type type)
9411 {
9412  void *memory = 0;
9413  switch (type) {
9414  default:
9415  case NK_BUFFER_MAX:
9416  case NK_BUFFER_FRONT:
9417  if (align) {
9418  memory = NK_ALIGN_PTR(unaligned, align);
9419  *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
9420  } else {
9421  memory = unaligned;
9422  *alignment = 0;
9423  }
9424  break;
9425  case NK_BUFFER_BACK:
9426  if (align) {
9427  memory = NK_ALIGN_PTR_BACK(unaligned, align);
9428  *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
9429  } else {
9430  memory = unaligned;
9431  *alignment = 0;
9432  }
9433  break;
9434  }
9435  return memory;
9436 }
9449 NK_LIB void*
9450 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
9451 {
9452  void *temp;
9453  nk_size buffer_size;
9454 
9455  NK_ASSERT(b);
9456  NK_ASSERT(size);
9457  if (!b || !size || !b->pool.alloc || !b->pool.free)
9458  return 0;
9459 
9460  buffer_size = b->memory.size;
9461  temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
9462  NK_ASSERT(temp);
9463  if (!temp) return 0;
9464 
9465  *size = capacity;
9466  if (temp != b->memory.ptr) {
9467  NK_MEMCPY(temp, b->memory.ptr, buffer_size);
9468  b->pool.free(b->pool.userdata, b->memory.ptr);
9469  }
9470 
9471  if (b->size == buffer_size) {
9472  /* no back buffer so just set correct size */
9473  b->size = capacity;
9474  return temp;
9475  } else {
9476  /* copy back buffer to the end of the new buffer */
9477  void *dst, *src;
9478  nk_size back_size;
9479  back_size = buffer_size - b->size;
9480  dst = nk_ptr_add(void, temp, capacity - back_size);
9481  src = nk_ptr_add(void, temp, b->size);
9482  NK_MEMCPY(dst, src, back_size);
9483  b->size = capacity - back_size;
9484  }
9485  return temp;
9486 }
9498 NK_LIB void*
9499 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
9500  nk_size size, nk_size align)
9501 {
9502  int full;
9503  nk_size alignment;
9504  void *unaligned;
9505  void *memory;
9506 
9507  NK_ASSERT(b);
9508  NK_ASSERT(size);
9509  if (!b || !size) return 0;
9510  b->needed += size;
9511 
9512  /* calculate total size with needed alignment + size */
9513  if (type == NK_BUFFER_FRONT)
9514  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
9515  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
9516  memory = nk_buffer_align(unaligned, align, &alignment, type);
9517 
9518  /* check if buffer has enough memory*/
9519  if (type == NK_BUFFER_FRONT)
9520  full = ((b->allocated + size + alignment) > b->size);
9521  else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
9522 
9523  if (full) {
9524  nk_size capacity;
9525  if (b->type != NK_BUFFER_DYNAMIC)
9526  return 0;
9527  NK_ASSERT(b->pool.alloc && b->pool.free);
9528  if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
9529  return 0;
9530 
9531  /* buffer is full so allocate bigger buffer if dynamic */
9532  capacity = (nk_size)((float)b->memory.size * b->grow_factor);
9533  capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
9534  b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
9535  if (!b->memory.ptr) return 0;
9536 
9537  /* align newly allocated pointer */
9538  if (type == NK_BUFFER_FRONT)
9539  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
9540  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
9541  memory = nk_buffer_align(unaligned, align, &alignment, type);
9542  }
9543  if (type == NK_BUFFER_FRONT)
9544  b->allocated += size + alignment;
9545  else b->size -= (size + alignment);
9546  b->needed += alignment;
9547  b->calls++;
9548  return memory;
9549 }
9561 NK_API void
9562 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type,
9563  const void *memory, nk_size size, nk_size align)
9564 {
9565  void *mem = nk_buffer_alloc(b, type, size, align);
9566  if (!mem) return;
9567  NK_MEMCPY(mem, memory, size);
9568 }
9580 NK_API void
9581 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
9582 {
9583  NK_ASSERT(buffer);
9584  if (!buffer) return;
9585  buffer->marker[type].active = nk_true;
9586  if (type == NK_BUFFER_BACK)
9587  buffer->marker[type].offset = buffer->size;
9588  else buffer->marker[type].offset = buffer->allocated;
9589 }
9601 NK_API void
9602 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
9603 {
9604  NK_ASSERT(buffer);
9605  if (!buffer) return;
9606  if (type == NK_BUFFER_BACK) {
9607  /* reset back buffer either back to marker or empty */
9608  buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
9609  if (buffer->marker[type].active)
9610  buffer->size = buffer->marker[type].offset;
9611  else buffer->size = buffer->memory.size;
9612  buffer->marker[type].active = nk_false;
9613  } else {
9614  /* reset front buffer either back to back marker or empty */
9615  buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
9616  if (buffer->marker[type].active)
9617  buffer->allocated = buffer->marker[type].offset;
9618  else buffer->allocated = 0;
9619  buffer->marker[type].active = nk_false;
9620  }
9621 }
9632 NK_API void
9633 nk_buffer_clear(struct nk_buffer *b)
9634 {
9635  NK_ASSERT(b);
9636  if (!b) return;
9637  b->allocated = 0;
9638  b->size = b->memory.size;
9639  b->calls = 0;
9640  b->needed = 0;
9641 }
9652 NK_API void
9653 nk_buffer_free(struct nk_buffer *b)
9654 {
9655  NK_ASSERT(b);
9656  if (!b || !b->memory.ptr) return;
9657  if (b->type == NK_BUFFER_FIXED) return;
9658  if (!b->pool.free) return;
9659  NK_ASSERT(b->pool.free);
9660  b->pool.free(b->pool.userdata, b->memory.ptr);
9661 }
9673 NK_API void
9674 nk_buffer_info(struct nk_memory_status *s, const struct nk_buffer *b)
9675 {
9676  NK_ASSERT(b);
9677  NK_ASSERT(s);
9678  if (!s || !b) return;
9679  s->allocated = b->allocated;
9680  s->size = b->memory.size;
9681  s->needed = b->needed;
9682  s->memory = b->memory.ptr;
9683  s->calls = b->calls;
9684 }
9695 NK_API void*
9696 nk_buffer_memory(struct nk_buffer *buffer)
9697 {
9698  NK_ASSERT(buffer);
9699  if (!buffer) return 0;
9700  return buffer->memory.ptr;
9701 }
9712 NK_API const void*
9713 nk_buffer_memory_const(const struct nk_buffer *buffer)
9714 {
9715  NK_ASSERT(buffer);
9716  if (!buffer) return 0;
9717  return buffer->memory.ptr;
9718 }
9729 NK_API nk_size
9730 nk_buffer_total(const struct nk_buffer *buffer)
9731 {
9732  NK_ASSERT(buffer);
9733  if (!buffer) return 0;
9734  return buffer->memory.size;
9735 }
9736 
9737 
9738 
9739 
9740 /* ===============================================================
9741  *
9742  * STRING
9743  *
9744  * ===============================================================*/
9745 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
9756 NK_API void
9757 nk_str_init_default(struct nk_str *str)
9758 {
9759  struct nk_allocator alloc;
9760  alloc.userdata.ptr = 0;
9761  alloc.alloc = nk_malloc;
9762  alloc.free = nk_mfree;
9763  nk_buffer_init(&str->buffer, &alloc, 32);
9764  str->len = 0;
9765 }
9766 #endif
9767 
9780 NK_API void
9781 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
9782 {
9783  nk_buffer_init(&str->buffer, alloc, size);
9784  str->len = 0;
9785 }
9798 NK_API void
9799 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
9800 {
9801  nk_buffer_init_fixed(&str->buffer, memory, size);
9802  str->len = 0;
9803 }
9816 NK_API int
9817 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
9818 {
9819  char *mem;
9820  NK_ASSERT(s);
9821  NK_ASSERT(str);
9822  if (!s || !str || !len) return 0;
9823  mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
9824  if (!mem) return 0;
9825  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
9826  s->len += nk_utf_len(str, len);
9827  return len;
9828 }
9840 NK_API int
9841 nk_str_append_str_char(struct nk_str *s, const char *str)
9842 {
9843  return nk_str_append_text_char(s, str, nk_strlen(str));
9844 }
9857 NK_API int
9858 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
9859 {
9860  int i = 0;
9861  int byte_len = 0;
9862  nk_rune unicode;
9863  if (!str || !text || !len) return 0;
9864  for (i = 0; i < len; ++i)
9865  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
9866  nk_str_append_text_char(str, text, byte_len);
9867  return len;
9868 }
9880 NK_API int
9881 nk_str_append_str_utf8(struct nk_str *str, const char *text)
9882 {
9883  int byte_len = 0;
9884  int num_runes = 0;
9885  int glyph_len = 0;
9886  nk_rune unicode;
9887  if (!str || !text) return 0;
9888 
9889  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
9890  while (unicode != '\0' && glyph_len) {
9891  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
9892  byte_len += glyph_len;
9893  num_runes++;
9894  }
9895  nk_str_append_text_char(str, text, byte_len);
9896  return num_runes;
9897 }
9910 NK_API int
9911 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
9912 {
9913  int i = 0;
9914  int byte_len = 0;
9915  nk_glyph glyph;
9916 
9917  NK_ASSERT(str);
9918  if (!str || !text || !len) return 0;
9919  for (i = 0; i < len; ++i) {
9920  byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
9921  if (!byte_len) break;
9922  nk_str_append_text_char(str, glyph, byte_len);
9923  }
9924  return len;
9925 }
9937 NK_API int
9938 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
9939 {
9940  int i = 0;
9941  nk_glyph glyph;
9942  int byte_len;
9943  NK_ASSERT(str);
9944  if (!str || !runes) return 0;
9945  while (runes[i] != '\0') {
9946  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
9947  nk_str_append_text_char(str, glyph, byte_len);
9948  i++;
9949  }
9950  return i;
9951 }
9965 NK_API int
9966 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
9967 {
9968  int i;
9969  void *mem;
9970  char *src;
9971  char *dst;
9972 
9973  int copylen;
9974  NK_ASSERT(s);
9975  NK_ASSERT(str);
9976  NK_ASSERT(len >= 0);
9977  if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
9978  if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
9979  (s->buffer.type == NK_BUFFER_FIXED)) return 0;
9980 
9981  copylen = (int)s->buffer.allocated - pos;
9982  if (!copylen) {
9983  nk_str_append_text_char(s, str, len);
9984  return 1;
9985  }
9986  mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
9987  if (!mem) return 0;
9988 
9989  /* memmove */
9990  NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
9991  NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
9992  dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
9993  src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
9994  for (i = 0; i < copylen; ++i) *dst-- = *src--;
9995  mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
9996  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
9997  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
9998  return 1;
9999 }
10013 NK_API int
10014 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
10015 {
10016  int glyph_len;
10017  nk_rune unicode;
10018  const char *begin;
10019  const char *buffer;
10020 
10021  NK_ASSERT(str);
10022  NK_ASSERT(cstr);
10023  NK_ASSERT(len);
10024  if (!str || !cstr || !len) return 0;
10025  begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
10026  if (!str->len)
10027  return nk_str_append_text_char(str, cstr, len);
10028  buffer = nk_str_get_const(str);
10029  if (!begin) return 0;
10030  return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
10031 }
10045 NK_API int
10046 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
10047 {
10048  return nk_str_insert_text_utf8(str, pos, text, len);
10049 }
10062 NK_API int
10063 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
10064 {
10065  return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
10066 }
10080 NK_API int
10081 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
10082 {
10083  int i = 0;
10084  int byte_len = 0;
10085  nk_rune unicode;
10086 
10087  NK_ASSERT(str);
10088  NK_ASSERT(text);
10089  if (!str || !text || !len) return 0;
10090  for (i = 0; i < len; ++i)
10091  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
10092  nk_str_insert_at_rune(str, pos, text, byte_len);
10093  return len;
10094 }
10107 NK_API int
10108 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
10109 {
10110  int byte_len = 0;
10111  int num_runes = 0;
10112  int glyph_len = 0;
10113  nk_rune unicode;
10114  if (!str || !text) return 0;
10115 
10116  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
10117  while (unicode != '\0' && glyph_len) {
10118  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
10119  byte_len += glyph_len;
10120  num_runes++;
10121  }
10122  nk_str_insert_at_rune(str, pos, text, byte_len);
10123  return num_runes;
10124 }
10138 NK_API int
10139 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
10140 {
10141  int i = 0;
10142  int byte_len = 0;
10143  nk_glyph glyph;
10144 
10145  NK_ASSERT(str);
10146  if (!str || !runes || !len) return 0;
10147  for (i = 0; i < len; ++i) {
10148  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
10149  if (!byte_len) break;
10150  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
10151  }
10152  return len;
10153 }
10166 NK_API int
10167 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
10168 {
10169  int i = 0;
10170  nk_glyph glyph;
10171  int byte_len;
10172  NK_ASSERT(str);
10173  if (!str || !runes) return 0;
10174  while (runes[i] != '\0') {
10175  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
10176  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
10177  i++;
10178  }
10179  return i;
10180 }
10192 NK_API void
10193 nk_str_remove_chars(struct nk_str *s, int len)
10194 {
10195  NK_ASSERT(s);
10196  NK_ASSERT(len >= 0);
10197  if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
10198  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
10199  s->buffer.allocated -= (nk_size)len;
10200  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
10201 }
10213 NK_API void
10214 nk_str_remove_runes(struct nk_str *str, int len)
10215 {
10216  int index;
10217  const char *begin;
10218  const char *end;
10219  nk_rune unicode;
10220 
10221  NK_ASSERT(str);
10222  NK_ASSERT(len >= 0);
10223  if (!str || len < 0) return;
10224  if (len >= str->len) {
10225  str->len = 0;
10226  return;
10227  }
10228 
10229  index = str->len - len;
10230  begin = nk_str_at_rune(str, index, &unicode, &len);
10231  end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
10232  nk_str_remove_chars(str, (int)(end-begin)+1);
10233 }
10246 NK_API void
10247 nk_str_delete_chars(struct nk_str *s, int pos, int len)
10248 {
10249  NK_ASSERT(s);
10250  if (!s || !len || (nk_size)pos > s->buffer.allocated ||
10251  (nk_size)(pos + len) > s->buffer.allocated) return;
10252 
10253  if ((nk_size)(pos + len) < s->buffer.allocated) {
10254  /* memmove */
10255  char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
10256  char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
10257  NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
10258  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
10259  s->buffer.allocated -= (nk_size)len;
10260  } else nk_str_remove_chars(s, len);
10261  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
10262 }
10275 NK_API void
10276 nk_str_delete_runes(struct nk_str *s, int pos, int len)
10277 {
10278  char *temp;
10279  nk_rune unicode;
10280  char *begin;
10281  char *end;
10282  int unused;
10283 
10284  NK_ASSERT(s);
10285  NK_ASSERT(s->len >= pos + len);
10286  if (s->len < pos + len)
10287  len = NK_CLAMP(0, (s->len - pos), s->len);
10288  if (!len) return;
10289 
10290  temp = (char *)s->buffer.memory.ptr;
10291  begin = nk_str_at_rune(s, pos, &unicode, &unused);
10292  if (!begin) return;
10293  s->buffer.memory.ptr = begin;
10294  end = nk_str_at_rune(s, len, &unicode, &unused);
10295  s->buffer.memory.ptr = temp;
10296  if (!end) return;
10297  nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
10298 }
10310 NK_API char*
10311 nk_str_at_char(struct nk_str *s, int pos)
10312 {
10313  NK_ASSERT(s);
10314  if (!s || pos > (int)s->buffer.allocated) return 0;
10315  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
10316 }
10330 NK_API char*
10331 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
10332 {
10333  int i = 0;
10334  int src_len = 0;
10335  int glyph_len = 0;
10336  char *text;
10337  int text_len;
10338 
10339  NK_ASSERT(str);
10340  NK_ASSERT(unicode);
10341  NK_ASSERT(len);
10342 
10343  if (!str || !unicode || !len) return 0;
10344  if (pos < 0) {
10345  *unicode = 0;
10346  *len = 0;
10347  return 0;
10348  }
10349 
10350  text = (char*)str->buffer.memory.ptr;
10351  text_len = (int)str->buffer.allocated;
10352  glyph_len = nk_utf_decode(text, unicode, text_len);
10353  while (glyph_len) {
10354  if (i == pos) {
10355  *len = glyph_len;
10356  break;
10357  }
10358 
10359  i++;
10360  src_len = src_len + glyph_len;
10361  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
10362  }
10363  if (i != pos) return 0;
10364  return text + src_len;
10365 }
10377 NK_API const char*
10378 nk_str_at_char_const(const struct nk_str *s, int pos)
10379 {
10380  NK_ASSERT(s);
10381  if (!s || pos > (int)s->buffer.allocated) return 0;
10382  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
10383 }
10397 NK_API const char*
10398 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
10399 {
10400  int i = 0;
10401  int src_len = 0;
10402  int glyph_len = 0;
10403  char *text;
10404  int text_len;
10405 
10406  NK_ASSERT(str);
10407  NK_ASSERT(unicode);
10408  NK_ASSERT(len);
10409 
10410  if (!str || !unicode || !len) return 0;
10411  if (pos < 0) {
10412  *unicode = 0;
10413  *len = 0;
10414  return 0;
10415  }
10416 
10417  text = (char*)str->buffer.memory.ptr;
10418  text_len = (int)str->buffer.allocated;
10419  glyph_len = nk_utf_decode(text, unicode, text_len);
10420  while (glyph_len) {
10421  if (i == pos) {
10422  *len = glyph_len;
10423  break;
10424  }
10425 
10426  i++;
10427  src_len = src_len + glyph_len;
10428  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
10429  }
10430  if (i != pos) return 0;
10431  return text + src_len;
10432 }
10444 NK_API nk_rune
10445 nk_str_rune_at(const struct nk_str *str, int pos)
10446 {
10447  int len;
10448  nk_rune unicode = 0;
10449  nk_str_at_const(str, pos, &unicode, &len);
10450  return unicode;
10451 }
10462 NK_API char*
10463 nk_str_get(struct nk_str *s)
10464 {
10465  NK_ASSERT(s);
10466  if (!s || !s->len || !s->buffer.allocated) return 0;
10467  return (char*)s->buffer.memory.ptr;
10468 }
10479 NK_API const char*
10480 nk_str_get_const(const struct nk_str *s)
10481 {
10482  NK_ASSERT(s);
10483  if (!s || !s->len || !s->buffer.allocated) return 0;
10484  return (const char*)s->buffer.memory.ptr;
10485 }
10496 NK_API int
10497 nk_str_len(const struct nk_str *s)
10498 {
10499  NK_ASSERT(s);
10500  if (!s || !s->len || !s->buffer.allocated) return 0;
10501  return s->len;
10502 }
10513 NK_API int
10514 nk_str_len_char(const struct nk_str *s)
10515 {
10516  NK_ASSERT(s);
10517  if (!s || !s->len || !s->buffer.allocated) return 0;
10518  return (int)s->buffer.allocated;
10519 }
10530 NK_API void
10531 nk_str_clear(struct nk_str *str)
10532 {
10533  NK_ASSERT(str);
10534  nk_buffer_clear(&str->buffer);
10535  str->len = 0;
10536 }
10547 NK_API void
10548 nk_str_free(struct nk_str *str)
10549 {
10550  NK_ASSERT(str);
10551  nk_buffer_free(&str->buffer);
10552  str->len = 0;
10553 }
10554 
10555 
10556 
10557 
10558 /* ==============================================================
10559  *
10560  * DRAW
10561  *
10562  * ===============================================================*/
10573 NK_LIB void
10574 nk_command_buffer_init(struct nk_command_buffer *cb,
10575  struct nk_buffer *b, enum nk_command_clipping clip)
10576 {
10577  NK_ASSERT(cb);
10578  NK_ASSERT(b);
10579  if (!cb || !b) return;
10580  cb->base = b;
10581  cb->use_clipping = (int)clip;
10582  cb->begin = b->allocated;
10583  cb->end = b->allocated;
10584  cb->last = b->allocated;
10585 }
10596 NK_LIB void
10597 nk_command_buffer_reset(struct nk_command_buffer *b)
10598 {
10599  NK_ASSERT(b);
10600  if (!b) return;
10601  b->begin = 0;
10602  b->end = 0;
10603  b->last = 0;
10604  b->clip = nk_null_rect;
10605 #ifdef NK_INCLUDE_COMMAND_USERDATA
10606  b->userdata.ptr = 0;
10607 #endif
10608 }
10619 NK_LIB void*
10620 nk_command_buffer_push(struct nk_command_buffer* b,
10621  enum nk_command_type t, nk_size size)
10622 {
10623  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
10624  struct nk_command *cmd;
10625  nk_size alignment;
10626  void *unaligned;
10627  void *memory;
10628 
10629  NK_ASSERT(b);
10630  NK_ASSERT(b->base);
10631  if (!b) return 0;
10632  cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
10633  if (!cmd) return 0;
10634 
10635  /* make sure the offset to the next command is aligned */
10636  b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
10637  unaligned = (nk_byte*)cmd + size;
10638  memory = NK_ALIGN_PTR(unaligned, align);
10639  alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
10640 #ifdef NK_ZERO_COMMAND_MEMORY
10641  NK_MEMSET(cmd, 0, size + alignment);
10642 #endif
10643 
10644  cmd->type = t;
10645  cmd->next = b->base->allocated + alignment;
10646 #ifdef NK_INCLUDE_COMMAND_USERDATA
10647  cmd->userdata = b->userdata;
10648 #endif
10649  b->end = cmd->next;
10650  return cmd;
10651 }
10663 NK_API void
10664 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
10665 {
10666  struct nk_command_scissor *cmd;
10667  NK_ASSERT(b);
10668  if (!b) return;
10669 
10670  b->clip.x = r.x;
10671  b->clip.y = r.y;
10672  b->clip.w = r.w;
10673  b->clip.h = r.h;
10674  cmd = (struct nk_command_scissor*)
10675  nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
10676 
10677  if (!cmd) return;
10678  cmd->x = (short)r.x;
10679  cmd->y = (short)r.y;
10680  cmd->w = (unsigned short)NK_MAX(0, r.w);
10681  cmd->h = (unsigned short)NK_MAX(0, r.h);
10682 }
10695 NK_API void
10696 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
10697  float x1, float y1, float line_thickness, struct nk_color c)
10698 {
10699  struct nk_command_line *cmd;
10700  NK_ASSERT(b);
10701  if (!b || line_thickness <= 0) return;
10702  cmd = (struct nk_command_line*)
10703  nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
10704  if (!cmd) return;
10705  cmd->line_thickness = (unsigned short)line_thickness;
10706  cmd->begin.x = (short)x0;
10707  cmd->begin.y = (short)y0;
10708  cmd->end.x = (short)x1;
10709  cmd->end.y = (short)y1;
10710  cmd->color = c;
10711 }
10724 NK_API void
10725 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
10726  float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
10727  float bx, float by, float line_thickness, struct nk_color col)
10728 {
10729  struct nk_command_curve *cmd;
10730  NK_ASSERT(b);
10731  if (!b || col.a == 0 || line_thickness <= 0) return;
10732 
10733  cmd = (struct nk_command_curve*)
10734  nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
10735  if (!cmd) return;
10736  cmd->line_thickness = (unsigned short)line_thickness;
10737  cmd->begin.x = (short)ax;
10738  cmd->begin.y = (short)ay;
10739  cmd->ctrl[0].x = (short)ctrl0x;
10740  cmd->ctrl[0].y = (short)ctrl0y;
10741  cmd->ctrl[1].x = (short)ctrl1x;
10742  cmd->ctrl[1].y = (short)ctrl1y;
10743  cmd->end.x = (short)bx;
10744  cmd->end.y = (short)by;
10745  cmd->color = col;
10746 }
10758 NK_API void
10759 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
10760  float rounding, float line_thickness, struct nk_color c)
10761 {
10762  struct nk_command_rect *cmd;
10763  NK_ASSERT(b);
10764  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
10765  if (b->use_clipping) {
10766  const struct nk_rect *clip = &b->clip;
10767  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
10768  clip->x, clip->y, clip->w, clip->h)) return;
10769  }
10770  cmd = (struct nk_command_rect*)
10771  nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
10772  if (!cmd) return;
10773  cmd->rounding = (unsigned short)rounding;
10774  cmd->line_thickness = (unsigned short)line_thickness;
10775  cmd->x = (short)rect.x;
10776  cmd->y = (short)rect.y;
10777  cmd->w = (unsigned short)NK_MAX(0, rect.w);
10778  cmd->h = (unsigned short)NK_MAX(0, rect.h);
10779  cmd->color = c;
10780 }
10792 NK_API void
10793 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
10794  float rounding, struct nk_color c)
10795 {
10796  struct nk_command_rect_filled *cmd;
10797  NK_ASSERT(b);
10798  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
10799  if (b->use_clipping) {
10800  const struct nk_rect *clip = &b->clip;
10801  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
10802  clip->x, clip->y, clip->w, clip->h)) return;
10803  }
10804 
10805  cmd = (struct nk_command_rect_filled*)
10806  nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
10807  if (!cmd) return;
10808  cmd->rounding = (unsigned short)rounding;
10809  cmd->x = (short)rect.x;
10810  cmd->y = (short)rect.y;
10811  cmd->w = (unsigned short)NK_MAX(0, rect.w);
10812  cmd->h = (unsigned short)NK_MAX(0, rect.h);
10813  cmd->color = c;
10814 }
10826 NK_API void
10827 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
10828  struct nk_color left, struct nk_color top, struct nk_color right,
10829  struct nk_color bottom)
10830 {
10831  struct nk_command_rect_multi_color *cmd;
10832  NK_ASSERT(b);
10833  if (!b || rect.w == 0 || rect.h == 0) return;
10834  if (b->use_clipping) {
10835  const struct nk_rect *clip = &b->clip;
10836  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
10837  clip->x, clip->y, clip->w, clip->h)) return;
10838  }
10839 
10840  cmd = (struct nk_command_rect_multi_color*)
10841  nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
10842  if (!cmd) return;
10843  cmd->x = (short)rect.x;
10844  cmd->y = (short)rect.y;
10845  cmd->w = (unsigned short)NK_MAX(0, rect.w);
10846  cmd->h = (unsigned short)NK_MAX(0, rect.h);
10847  cmd->left = left;
10848  cmd->top = top;
10849  cmd->right = right;
10850  cmd->bottom = bottom;
10851 }
10863 NK_API void
10864 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
10865  float line_thickness, struct nk_color c)
10866 {
10867  struct nk_command_circle *cmd;
10868  if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
10869  if (b->use_clipping) {
10870  const struct nk_rect *clip = &b->clip;
10871  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
10872  return;
10873  }
10874 
10875  cmd = (struct nk_command_circle*)
10876  nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
10877  if (!cmd) return;
10878  cmd->line_thickness = (unsigned short)line_thickness;
10879  cmd->x = (short)r.x;
10880  cmd->y = (short)r.y;
10881  cmd->w = (unsigned short)NK_MAX(r.w, 0);
10882  cmd->h = (unsigned short)NK_MAX(r.h, 0);
10883  cmd->color = c;
10884 }
10897 NK_API void
10898 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
10899 {
10900  struct nk_command_circle_filled *cmd;
10901  NK_ASSERT(b);
10902  if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
10903  if (b->use_clipping) {
10904  const struct nk_rect *clip = &b->clip;
10905  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
10906  return;
10907  }
10908 
10909  cmd = (struct nk_command_circle_filled*)
10910  nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
10911  if (!cmd) return;
10912  cmd->x = (short)r.x;
10913  cmd->y = (short)r.y;
10914  cmd->w = (unsigned short)NK_MAX(r.w, 0);
10915  cmd->h = (unsigned short)NK_MAX(r.h, 0);
10916  cmd->color = c;
10917 }
10931 NK_API void
10932 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
10933  float a_min, float a_max, float line_thickness, struct nk_color c)
10934 {
10935  struct nk_command_arc *cmd;
10936  if (!b || c.a == 0 || line_thickness <= 0) return;
10937  cmd = (struct nk_command_arc*)
10938  nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
10939  if (!cmd) return;
10940  cmd->line_thickness = (unsigned short)line_thickness;
10941  cmd->cx = (short)cx;
10942  cmd->cy = (short)cy;
10943  cmd->r = (unsigned short)radius;
10944  cmd->a[0] = a_min;
10945  cmd->a[1] = a_max;
10946  cmd->color = c;
10947 }
10961 NK_API void
10962 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
10963  float a_min, float a_max, struct nk_color c)
10964 {
10965  struct nk_command_arc_filled *cmd;
10966  NK_ASSERT(b);
10967  if (!b || c.a == 0) return;
10968  cmd = (struct nk_command_arc_filled*)
10969  nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
10970  if (!cmd) return;
10971  cmd->cx = (short)cx;
10972  cmd->cy = (short)cy;
10973  cmd->r = (unsigned short)radius;
10974  cmd->a[0] = a_min;
10975  cmd->a[1] = a_max;
10976  cmd->color = c;
10977 }
10991 NK_API void
10992 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
10993  float y1, float x2, float y2, float line_thickness, struct nk_color c)
10994 {
10995  struct nk_command_triangle *cmd;
10996  NK_ASSERT(b);
10997  if (!b || c.a == 0 || line_thickness <= 0) return;
10998  if (b->use_clipping) {
10999  const struct nk_rect *clip = &b->clip;
11000  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
11001  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
11002  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
11003  return;
11004  }
11005 
11006  cmd = (struct nk_command_triangle*)
11007  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
11008  if (!cmd) return;
11009  cmd->line_thickness = (unsigned short)line_thickness;
11010  cmd->a.x = (short)x0;
11011  cmd->a.y = (short)y0;
11012  cmd->b.x = (short)x1;
11013  cmd->b.y = (short)y1;
11014  cmd->c.x = (short)x2;
11015  cmd->c.y = (short)y2;
11016  cmd->color = c;
11017 }
11031 NK_API void
11032 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
11033  float y1, float x2, float y2, struct nk_color c)
11034 {
11035  struct nk_command_triangle_filled *cmd;
11036  NK_ASSERT(b);
11037  if (!b || c.a == 0) return;
11038  if (!b) return;
11039  if (b->use_clipping) {
11040  const struct nk_rect *clip = &b->clip;
11041  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
11042  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
11043  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
11044  return;
11045  }
11046 
11047  cmd = (struct nk_command_triangle_filled*)
11048  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
11049  if (!cmd) return;
11050  cmd->a.x = (short)x0;
11051  cmd->a.y = (short)y0;
11052  cmd->b.x = (short)x1;
11053  cmd->b.y = (short)y1;
11054  cmd->c.x = (short)x2;
11055  cmd->c.y = (short)y2;
11056  cmd->color = c;
11057 }
11070 NK_API void
11071 nk_stroke_polygon(struct nk_command_buffer *b, const float *points, int point_count,
11072  float line_thickness, struct nk_color col)
11073 {
11074  int i;
11075  nk_size size = 0;
11076  struct nk_command_polygon *cmd;
11077 
11078  NK_ASSERT(b);
11079  if (!b || col.a == 0 || line_thickness <= 0) return;
11080  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
11081  cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
11082  if (!cmd) return;
11083  cmd->color = col;
11084  cmd->line_thickness = (unsigned short)line_thickness;
11085  cmd->point_count = (unsigned short)point_count;
11086  for (i = 0; i < point_count; ++i) {
11087  cmd->points[i].x = (short)points[i*2];
11088  cmd->points[i].y = (short)points[i*2+1];
11089  }
11090 }
11103 NK_API void
11104 nk_fill_polygon(struct nk_command_buffer *b, const float *points, int point_count,
11105  struct nk_color col)
11106 {
11107  int i;
11108  nk_size size = 0;
11109  struct nk_command_polygon_filled *cmd;
11110 
11111  NK_ASSERT(b);
11112  if (!b || col.a == 0) return;
11113  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
11114  cmd = (struct nk_command_polygon_filled*)
11115  nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
11116  if (!cmd) return;
11117  cmd->color = col;
11118  cmd->point_count = (unsigned short)point_count;
11119  for (i = 0; i < point_count; ++i) {
11120  cmd->points[i].x = (short)points[i*2+0];
11121  cmd->points[i].y = (short)points[i*2+1];
11122  }
11123 }
11136 NK_API void
11137 nk_stroke_polyline(struct nk_command_buffer *b, const float *points, int point_count,
11138  float line_thickness, struct nk_color col)
11139 {
11140  int i;
11141  nk_size size = 0;
11142  struct nk_command_polyline *cmd;
11143 
11144  NK_ASSERT(b);
11145  if (!b || col.a == 0 || line_thickness <= 0) return;
11146  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
11147  cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
11148  if (!cmd) return;
11149  cmd->color = col;
11150  cmd->point_count = (unsigned short)point_count;
11151  cmd->line_thickness = (unsigned short)line_thickness;
11152  for (i = 0; i < point_count; ++i) {
11153  cmd->points[i].x = (short)points[i*2];
11154  cmd->points[i].y = (short)points[i*2+1];
11155  }
11156 }
11168 NK_API void
11169 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
11170  const struct nk_image *img, struct nk_color col)
11171 {
11172  struct nk_command_image *cmd;
11173  NK_ASSERT(b);
11174  if (!b) return;
11175  if (b->use_clipping) {
11176  const struct nk_rect *c = &b->clip;
11177  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))
11178  return;
11179  }
11180 
11181  cmd = (struct nk_command_image*)
11182  nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
11183  if (!cmd) return;
11184  cmd->x = (short)r.x;
11185  cmd->y = (short)r.y;
11186  cmd->w = (unsigned short)NK_MAX(0, r.w);
11187  cmd->h = (unsigned short)NK_MAX(0, r.h);
11188  cmd->img = *img;
11189  cmd->col = col;
11190 }
11202 NK_API void
11203 nk_draw_nine_slice(struct nk_command_buffer *b, struct nk_rect r,
11204  const struct nk_nine_slice *slc, struct nk_color col)
11205 {
11206  struct nk_image img;
11207  const struct nk_image *slcimg = (const struct nk_image*)slc;
11208  nk_ushort rgnX, rgnY, rgnW, rgnH;
11209  rgnX = slcimg->region[0];
11210  rgnY = slcimg->region[1];
11211  rgnW = slcimg->region[2];
11212  rgnH = slcimg->region[3];
11213 
11214  /* top-left */
11215  img.handle = slcimg->handle;
11216  img.w = slcimg->w;
11217  img.h = slcimg->h;
11218  img.region[0] = rgnX;
11219  img.region[1] = rgnY;
11220  img.region[2] = slc->l;
11221  img.region[3] = slc->t;
11222 
11223  nk_draw_image(b,
11224  nk_rect(r.x, r.y, (float)slc->l, (float)slc->t),
11225  &img, col);
11226 
11227 #define IMG_RGN(x, y, w, h) img.region[0] = (nk_ushort)(x); img.region[1] = (nk_ushort)(y); img.region[2] = (nk_ushort)(w); img.region[3] = (nk_ushort)(h);
11228 
11229  /* top-center */
11230  IMG_RGN(rgnX + slc->l, rgnY, rgnW - slc->l - slc->r, slc->t);
11231  nk_draw_image(b,
11232  nk_rect(r.x + (float)slc->l, r.y, (float)(r.w - slc->l - slc->r), (float)slc->t),
11233  &img, col);
11234 
11235  /* top-right */
11236  IMG_RGN(rgnX + rgnW - slc->r, rgnY, slc->r, slc->t);
11237  nk_draw_image(b,
11238  nk_rect(r.x + r.w - (float)slc->r, r.y, (float)slc->r, (float)slc->t),
11239  &img, col);
11240 
11241  /* center-left */
11242  IMG_RGN(rgnX, rgnY + slc->t, slc->l, rgnH - slc->t - slc->b);
11243  nk_draw_image(b,
11244  nk_rect(r.x, r.y + (float)slc->t, (float)slc->l, (float)(r.h - slc->t - slc->b)),
11245  &img, col);
11246 
11247  /* center */
11248  IMG_RGN(rgnX + slc->l, rgnY + slc->t, rgnW - slc->l - slc->r, rgnH - slc->t - slc->b);
11249  nk_draw_image(b,
11250  nk_rect(r.x + (float)slc->l, r.y + (float)slc->t, (float)(r.w - slc->l - slc->r), (float)(r.h - slc->t - slc->b)),
11251  &img, col);
11252 
11253  /* center-right */
11254  IMG_RGN(rgnX + rgnW - slc->r, rgnY + slc->t, slc->r, rgnH - slc->t - slc->b);
11255  nk_draw_image(b,
11256  nk_rect(r.x + r.w - (float)slc->r, r.y + (float)slc->t, (float)slc->r, (float)(r.h - slc->t - slc->b)),
11257  &img, col);
11258 
11259  /* bottom-left */
11260  IMG_RGN(rgnX, rgnY + rgnH - slc->b, slc->l, slc->b);
11261  nk_draw_image(b,
11262  nk_rect(r.x, r.y + r.h - (float)slc->b, (float)slc->l, (float)slc->b),
11263  &img, col);
11264 
11265  /* bottom-center */
11266  IMG_RGN(rgnX + slc->l, rgnY + rgnH - slc->b, rgnW - slc->l - slc->r, slc->b);
11267  nk_draw_image(b,
11268  nk_rect(r.x + (float)slc->l, r.y + r.h - (float)slc->b, (float)(r.w - slc->l - slc->r), (float)slc->b),
11269  &img, col);
11270 
11271  /* bottom-right */
11272  IMG_RGN(rgnX + rgnW - slc->r, rgnY + rgnH - slc->b, slc->r, slc->b);
11273  nk_draw_image(b,
11274  nk_rect(r.x + r.w - (float)slc->r, r.y + r.h - (float)slc->b, (float)slc->r, (float)slc->b),
11275  &img, col);
11276 
11277 #undef IMG_RGN
11278 }
11290 NK_API void
11291 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
11292  nk_command_custom_callback cb, nk_handle usr)
11293 {
11294  struct nk_command_custom *cmd;
11295  NK_ASSERT(b);
11296  if (!b) return;
11297  if (b->use_clipping) {
11298  const struct nk_rect *c = &b->clip;
11299  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))
11300  return;
11301  }
11302 
11303  cmd = (struct nk_command_custom*)
11304  nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
11305  if (!cmd) return;
11306  cmd->x = (short)r.x;
11307  cmd->y = (short)r.y;
11308  cmd->w = (unsigned short)NK_MAX(0, r.w);
11309  cmd->h = (unsigned short)NK_MAX(0, r.h);
11310  cmd->callback_data = usr;
11311  cmd->callback = cb;
11312 }
11324 NK_API void
11325 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
11326  const char *string, int length, const struct nk_user_font *font,
11327  struct nk_color bg, struct nk_color fg)
11328 {
11329  float text_width = 0;
11330  struct nk_command_text *cmd;
11331 
11332  NK_ASSERT(b);
11333  NK_ASSERT(font);
11334  if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
11335  if (b->use_clipping) {
11336  const struct nk_rect *c = &b->clip;
11337  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))
11338  return;
11339  }
11340 
11341  /* make sure text fits inside bounds */
11342  text_width = font->width(font->userdata, font->height, string, length);
11343  if (text_width > r.w){
11344  int glyphs = 0;
11345  float txt_width = (float)text_width;
11346  length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
11347  }
11348 
11349  if (!length) return;
11350  cmd = (struct nk_command_text*)
11351  nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
11352  if (!cmd) return;
11353  cmd->x = (short)r.x;
11354  cmd->y = (short)r.y;
11355  cmd->w = (unsigned short)r.w;
11356  cmd->h = (unsigned short)r.h;
11357  cmd->background = bg;
11358  cmd->foreground = fg;
11359  cmd->font = font;
11360  cmd->length = length;
11361  cmd->height = font->height;
11362  NK_MEMCPY(cmd->string, string, (nk_size)length);
11363  cmd->string[length] = '\0';
11364 }
11365 
11366 
11367 
11368 
11369 /* ===============================================================
11370  *
11371  * VERTEX
11372  *
11373  * ===============================================================*/
11374 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11385 NK_API void
11386 nk_draw_list_init(struct nk_draw_list *list)
11387 {
11388  nk_size i = 0;
11389  NK_ASSERT(list);
11390  if (!list) return;
11391  nk_zero(list, sizeof(*list));
11392  for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
11393  const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
11394  list->circle_vtx[i].x = (float)NK_COS(a);
11395  list->circle_vtx[i].y = (float)NK_SIN(a);
11396  }
11397 }
11409 NK_API void
11410 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
11411  struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
11412  enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
11413 {
11414  NK_ASSERT(canvas);
11415  NK_ASSERT(config);
11416  NK_ASSERT(cmds);
11417  NK_ASSERT(vertices);
11418  NK_ASSERT(elements);
11419  if (!canvas || !config || !cmds || !vertices || !elements)
11420  return;
11421 
11422  canvas->buffer = cmds;
11423  canvas->config = *config;
11424  canvas->elements = elements;
11425  canvas->vertices = vertices;
11426  canvas->line_AA = line_aa;
11427  canvas->shape_AA = shape_aa;
11428  canvas->clip_rect = nk_null_rect;
11429 
11430  canvas->cmd_offset = 0;
11431  canvas->element_count = 0;
11432  canvas->vertex_count = 0;
11433  canvas->cmd_offset = 0;
11434  canvas->cmd_count = 0;
11435  canvas->path_count = 0;
11436 }
11448 NK_API const struct nk_draw_command*
11449 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
11450 {
11451  nk_byte *memory;
11452  nk_size offset;
11453  const struct nk_draw_command *cmd;
11454 
11455  NK_ASSERT(buffer);
11456  if (!buffer || !buffer->size || !canvas->cmd_count)
11457  return 0;
11458 
11459  memory = (nk_byte*)buffer->memory.ptr;
11460  offset = buffer->memory.size - canvas->cmd_offset;
11461  cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
11462  return cmd;
11463 }
11475 NK_API const struct nk_draw_command*
11476 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
11477 {
11478  nk_size size;
11479  nk_size offset;
11480  nk_byte *memory;
11481  const struct nk_draw_command *end;
11482 
11483  NK_ASSERT(buffer);
11484  NK_ASSERT(canvas);
11485  if (!buffer || !canvas)
11486  return 0;
11487 
11488  memory = (nk_byte*)buffer->memory.ptr;
11489  size = buffer->memory.size;
11490  offset = size - canvas->cmd_offset;
11491  end = nk_ptr_add(const struct nk_draw_command, memory, offset);
11492  end -= (canvas->cmd_count-1);
11493  return end;
11494 }
11505 NK_API const struct nk_draw_command*
11506 nk__draw_list_next(const struct nk_draw_command *cmd,
11507  const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
11508 {
11509  const struct nk_draw_command *end;
11510  NK_ASSERT(buffer);
11511  NK_ASSERT(canvas);
11512  if (!cmd || !buffer || !canvas)
11513  return 0;
11514 
11515  end = nk__draw_list_end(canvas, buffer);
11516  if (cmd <= end) return 0;
11517  return (cmd-1);
11518 }
11530 NK_INTERN struct nk_vec2*
11531 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
11532 {
11533  struct nk_vec2 *points;
11534  NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
11535  NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
11536  points = (struct nk_vec2*)
11537  nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
11538  point_size * (nk_size)count, point_align);
11539 
11540  if (!points) return 0;
11541  if (!list->path_offset) {
11542  void *memory = nk_buffer_memory(list->buffer);
11543  list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
11544  }
11545  list->path_count += (unsigned int)count;
11546  return points;
11547 }
11558 NK_INTERN struct nk_vec2
11559 nk_draw_list_path_last(struct nk_draw_list *list)
11560 {
11561  void *memory;
11562  struct nk_vec2 *point;
11563  NK_ASSERT(list->path_count);
11564  memory = nk_buffer_memory(list->buffer);
11565  point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
11566  point += (list->path_count-1);
11567  return *point;
11568 }
11580 NK_INTERN struct nk_draw_command*
11581 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
11582  nk_handle texture)
11583 {
11584  NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
11585  NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
11586  struct nk_draw_command *cmd;
11587 
11588  NK_ASSERT(list);
11589  cmd = (struct nk_draw_command*)
11590  nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
11591 
11592  if (!cmd) return 0;
11593  if (!list->cmd_count) {
11594  nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
11595  nk_size total = nk_buffer_total(list->buffer);
11596  memory = nk_ptr_add(nk_byte, memory, total);
11597  list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
11598  }
11599 
11600  cmd->elem_count = 0;
11601  cmd->clip_rect = clip;
11602  cmd->texture = texture;
11603 #ifdef NK_INCLUDE_COMMAND_USERDATA
11604  cmd->userdata = list->userdata;
11605 #endif
11606 
11607  list->cmd_count++;
11608  list->clip_rect = clip;
11609  return cmd;
11610 }
11621 NK_INTERN struct nk_draw_command*
11622 nk_draw_list_command_last(struct nk_draw_list *list)
11623 {
11624  void *memory;
11625  nk_size size;
11626  struct nk_draw_command *cmd;
11627  NK_ASSERT(list->cmd_count);
11628 
11629  memory = nk_buffer_memory(list->buffer);
11630  size = nk_buffer_total(list->buffer);
11631  cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
11632  return (cmd - (list->cmd_count-1));
11633 }
11645 NK_INTERN void
11646 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
11647 {
11648  NK_ASSERT(list);
11649  if (!list) return;
11650  if (!list->cmd_count) {
11651  nk_draw_list_push_command(list, rect, list->config.tex_null.texture);
11652  } else {
11653  struct nk_draw_command *prev = nk_draw_list_command_last(list);
11654  if (prev->elem_count == 0)
11655  prev->clip_rect = rect;
11656  nk_draw_list_push_command(list, rect, prev->texture);
11657  }
11658 }
11670 NK_INTERN void
11671 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
11672 {
11673  NK_ASSERT(list);
11674  if (!list) return;
11675  if (!list->cmd_count) {
11676  nk_draw_list_push_command(list, nk_null_rect, texture);
11677  } else {
11678  struct nk_draw_command *prev = nk_draw_list_command_last(list);
11679  if (prev->elem_count == 0) {
11680  prev->texture = texture;
11681  #ifdef NK_INCLUDE_COMMAND_USERDATA
11682  prev->userdata = list->userdata;
11683  #endif
11684  } else if (prev->texture.id != texture.id
11685  #ifdef NK_INCLUDE_COMMAND_USERDATA
11686  || prev->userdata.id != list->userdata.id
11687  #endif
11688  ) {
11689  nk_draw_list_push_command(list, prev->clip_rect, texture);
11690  }
11691  }
11692 }
11693 #ifdef NK_INCLUDE_COMMAND_USERDATA
11705 NK_API void
11706 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
11707 {
11708  list->userdata = userdata;
11709 }
11710 #endif
11722 NK_INTERN void*
11723 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
11724 {
11725  void *vtx;
11726  NK_ASSERT(list);
11727  if (!list) return 0;
11728  vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
11729  list->config.vertex_size*count, list->config.vertex_alignment);
11730  if (!vtx) return 0;
11731  list->vertex_count += (unsigned int)count;
11732 
11733  /* This assert triggers because your are drawing a lot of stuff and nuklear
11734  * defined `nk_draw_index` as `nk_ushort` to safe space be default.
11735  *
11736  * So you reached the maximum number of indices or rather vertexes.
11737  * To solve this issue please change typedef `nk_draw_index` to `nk_uint`
11738  * and don't forget to specify the new element size in your drawing
11739  * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements`
11740  * instead of specifying `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`.
11741  * Sorry for the inconvenience. */
11742  if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX &&
11743  "To many vertices for 16-bit vertex indices. Please read comment above on how to solve this problem"));
11744  return vtx;
11745 }
11757 NK_INTERN nk_draw_index*
11758 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
11759 {
11760  nk_draw_index *ids;
11761  struct nk_draw_command *cmd;
11762  NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
11763  NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
11764  NK_ASSERT(list);
11765  if (!list) return 0;
11766 
11767  ids = (nk_draw_index*)
11768  nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
11769  if (!ids) return 0;
11770  cmd = nk_draw_list_command_last(list);
11771  list->element_count += (unsigned int)count;
11772  cmd->elem_count += (unsigned int)count;
11773  return ids;
11774 }
11784 NK_INTERN int
11785 nk_draw_vertex_layout_element_is_end_of_layout(
11786  const struct nk_draw_vertex_layout_element *element)
11787 {
11788  return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
11789  element->format == NK_FORMAT_COUNT);
11790 }
11802 NK_INTERN void
11803 nk_draw_vertex_color(void *attr, const float *vals,
11804  enum nk_draw_vertex_layout_format format)
11805 {
11806  /* if this triggers you tried to provide a value format for a color */
11807  float val[4];
11808  NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
11809  NK_ASSERT(format <= NK_FORMAT_COLOR_END);
11810  if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
11811 
11812  val[0] = NK_SATURATE(vals[0]);
11813  val[1] = NK_SATURATE(vals[1]);
11814  val[2] = NK_SATURATE(vals[2]);
11815  val[3] = NK_SATURATE(vals[3]);
11816 
11817  switch (format) {
11818  default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
11819  case NK_FORMAT_R8G8B8A8:
11820  case NK_FORMAT_R8G8B8: {
11821  struct nk_color col = nk_rgba_fv(val);
11822  NK_MEMCPY(attr, &col.r, sizeof(col));
11823  } break;
11824  case NK_FORMAT_B8G8R8A8: {
11825  struct nk_color col = nk_rgba_fv(val);
11826  struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
11827  NK_MEMCPY(attr, &bgra, sizeof(bgra));
11828  } break;
11829  case NK_FORMAT_R16G15B16: {
11830  nk_ushort col[3];
11831  col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
11832  col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
11833  col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
11834  NK_MEMCPY(attr, col, sizeof(col));
11835  } break;
11836  case NK_FORMAT_R16G15B16A16: {
11837  nk_ushort col[4];
11838  col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX);
11839  col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX);
11840  col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX);
11841  col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX);
11842  NK_MEMCPY(attr, col, sizeof(col));
11843  } break;
11844  case NK_FORMAT_R32G32B32: {
11845  nk_uint col[3];
11846  col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
11847  col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
11848  col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
11849  NK_MEMCPY(attr, col, sizeof(col));
11850  } break;
11851  case NK_FORMAT_R32G32B32A32: {
11852  nk_uint col[4];
11853  col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX);
11854  col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX);
11855  col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX);
11856  col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX);
11857  NK_MEMCPY(attr, col, sizeof(col));
11858  } break;
11859  case NK_FORMAT_R32G32B32A32_FLOAT:
11860  NK_MEMCPY(attr, val, sizeof(float)*4);
11861  break;
11862  case NK_FORMAT_R32G32B32A32_DOUBLE: {
11863  double col[4];
11864  col[0] = (double)val[0];
11865  col[1] = (double)val[1];
11866  col[2] = (double)val[2];
11867  col[3] = (double)val[3];
11868  NK_MEMCPY(attr, col, sizeof(col));
11869  } break;
11870  case NK_FORMAT_RGB32:
11871  case NK_FORMAT_RGBA32: {
11872  struct nk_color col = nk_rgba_fv(val);
11873  nk_uint color = nk_color_u32(col);
11874  NK_MEMCPY(attr, &color, sizeof(color));
11875  } break; }
11876 }
11889 NK_INTERN void
11890 nk_draw_vertex_element(void *dst, const float *values, int value_count,
11891  enum nk_draw_vertex_layout_format format)
11892 {
11893  int value_index;
11894  void *attribute = dst;
11895  /* if this triggers you tried to provide a color format for a value */
11896  NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
11897  if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
11898  for (value_index = 0; value_index < value_count; ++value_index) {
11899  switch (format) {
11900  default: NK_ASSERT(0 && "invalid vertex layout format"); break;
11901  case NK_FORMAT_SCHAR: {
11902  char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX);
11903  NK_MEMCPY(attribute, &value, sizeof(value));
11904  attribute = (void*)((char*)attribute + sizeof(char));
11905  } break;
11906  case NK_FORMAT_SSHORT: {
11907  nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX);
11908  NK_MEMCPY(attribute, &value, sizeof(value));
11909  attribute = (void*)((char*)attribute + sizeof(value));
11910  } break;
11911  case NK_FORMAT_SINT: {
11912  nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX);
11913  NK_MEMCPY(attribute, &value, sizeof(value));
11914  attribute = (void*)((char*)attribute + sizeof(nk_int));
11915  } break;
11916  case NK_FORMAT_UCHAR: {
11917  unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX);
11918  NK_MEMCPY(attribute, &value, sizeof(value));
11919  attribute = (void*)((char*)attribute + sizeof(unsigned char));
11920  } break;
11921  case NK_FORMAT_USHORT: {
11922  nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX);
11923  NK_MEMCPY(attribute, &value, sizeof(value));
11924  attribute = (void*)((char*)attribute + sizeof(value));
11925  } break;
11926  case NK_FORMAT_UINT: {
11927  nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX);
11928  NK_MEMCPY(attribute, &value, sizeof(value));
11929  attribute = (void*)((char*)attribute + sizeof(nk_uint));
11930  } break;
11931  case NK_FORMAT_FLOAT:
11932  NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
11933  attribute = (void*)((char*)attribute + sizeof(float));
11934  break;
11935  case NK_FORMAT_DOUBLE: {
11936  double value = (double)values[value_index];
11937  NK_MEMCPY(attribute, &value, sizeof(value));
11938  attribute = (void*)((char*)attribute + sizeof(double));
11939  } break;
11940  }
11941  }
11942 }
11954 NK_INTERN void*
11955 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
11956  struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
11957 {
11958  void *result = (void*)((char*)dst + config->vertex_size);
11959  const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
11960  while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
11961  void *address = (void*)((char*)dst + elem_iter->offset);
11962  switch (elem_iter->attribute) {
11963  case NK_VERTEX_ATTRIBUTE_COUNT:
11964  default: NK_ASSERT(0 && "wrong element attribute"); break;
11965  case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
11966  case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
11967  case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
11968  }
11969  elem_iter++;
11970  }
11971  return result;
11972 }
11984 NK_API void
11985 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
11986  const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
11987  float thickness, enum nk_anti_aliasing aliasing)
11988 {
11989  nk_size count;
11990  int thick_line;
11991  struct nk_colorf col;
11992  struct nk_colorf col_trans;
11993  NK_ASSERT(list);
11994  if (!list || points_count < 2) return;
11995 
11996  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
11997  count = points_count;
11998  if (!closed) count = points_count-1;
11999  thick_line = thickness > 1.0f;
12000 
12001 #ifdef NK_INCLUDE_COMMAND_USERDATA
12002  nk_draw_list_push_userdata(list, list->userdata);
12003 #endif
12004 
12005  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
12006  nk_color_fv(&col.r, color);
12007  col_trans = col;
12008  col_trans.a = 0;
12009 
12010  if (aliasing == NK_ANTI_ALIASING_ON) {
12011  /* ANTI-ALIASED STROKE */
12012  const float AA_SIZE = 1.0f;
12013  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
12014  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
12015 
12016  /* allocate vertices and elements */
12017  nk_size i1 = 0;
12018  nk_size vertex_offset;
12019  nk_size index = list->vertex_count;
12020 
12021  const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12);
12022  const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
12023 
12024  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
12025  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
12026 
12027  nk_size size;
12028  struct nk_vec2 *normals, *temp;
12029  if (!vtx || !ids) return;
12030 
12031  /* temporary allocate normals + points */
12032  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
12033  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
12034  size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
12035  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
12036  if (!normals) return;
12037  temp = normals + points_count;
12038 
12039  /* make sure vertex pointer is still correct */
12040  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
12041 
12042  /* calculate normals */
12043  for (i1 = 0; i1 < count; ++i1) {
12044  const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
12045  struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
12046  float len;
12047 
12048  /* vec2 inverted length */
12049  len = nk_vec2_len_sqr(diff);
12050  if (len != 0.0f)
12051  len = NK_INV_SQRT(len);
12052  else len = 1.0f;
12053 
12054  diff = nk_vec2_muls(diff, len);
12055  normals[i1].x = diff.y;
12056  normals[i1].y = -diff.x;
12057  }
12058 
12059  if (!closed)
12060  normals[points_count-1] = normals[points_count-2];
12061 
12062  if (!thick_line) {
12063  nk_size idx1, i;
12064  if (!closed) {
12065  struct nk_vec2 d;
12066  temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
12067  temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
12068  d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
12069  temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
12070  temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
12071  }
12072 
12073  /* fill elements */
12074  idx1 = index;
12075  for (i1 = 0; i1 < count; i1++) {
12076  struct nk_vec2 dm;
12077  float dmr2;
12078  nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
12079  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
12080 
12081  /* average normals */
12082  dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
12083  dmr2 = dm.x * dm.x + dm.y* dm.y;
12084  if (dmr2 > 0.000001f) {
12085  float scale = 1.0f/dmr2;
12086  scale = NK_MIN(100.0f, scale);
12087  dm = nk_vec2_muls(dm, scale);
12088  }
12089 
12090  dm = nk_vec2_muls(dm, AA_SIZE);
12091  temp[i2*2+0] = nk_vec2_add(points[i2], dm);
12092  temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
12093 
12094  ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
12095  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
12096  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
12097  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
12098  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
12099  ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
12100  ids += 12;
12101  idx1 = idx2;
12102  }
12103 
12104  /* fill vertices */
12105  for (i = 0; i < points_count; ++i) {
12106  const struct nk_vec2 uv = list->config.tex_null.uv;
12107  vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
12108  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
12109  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
12110  }
12111  } else {
12112  nk_size idx1, i;
12113  const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
12114  if (!closed) {
12115  struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
12116  struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
12117 
12118  temp[0] = nk_vec2_add(points[0], d1);
12119  temp[1] = nk_vec2_add(points[0], d2);
12120  temp[2] = nk_vec2_sub(points[0], d2);
12121  temp[3] = nk_vec2_sub(points[0], d1);
12122 
12123  d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
12124  d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
12125 
12126  temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
12127  temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
12128  temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
12129  temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
12130  }
12131 
12132  /* add all elements */
12133  idx1 = index;
12134  for (i1 = 0; i1 < count; ++i1) {
12135  struct nk_vec2 dm_out, dm_in;
12136  const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
12137  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
12138 
12139  /* average normals */
12140  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
12141  float dmr2 = dm.x * dm.x + dm.y* dm.y;
12142  if (dmr2 > 0.000001f) {
12143  float scale = 1.0f/dmr2;
12144  scale = NK_MIN(100.0f, scale);
12145  dm = nk_vec2_muls(dm, scale);
12146  }
12147 
12148  dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
12149  dm_in = nk_vec2_muls(dm, half_inner_thickness);
12150  temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
12151  temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
12152  temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
12153  temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
12154 
12155  /* add indexes */
12156  ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
12157  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
12158  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
12159  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
12160  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
12161  ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
12162  ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
12163  ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
12164  ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
12165  ids += 18;
12166  idx1 = idx2;
12167  }
12168 
12169  /* add vertices */
12170  for (i = 0; i < points_count; ++i) {
12171  const struct nk_vec2 uv = list->config.tex_null.uv;
12172  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
12173  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
12174  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
12175  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
12176  }
12177  }
12178  /* free temporary normals + points */
12179  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
12180  } else {
12181  /* NON ANTI-ALIASED STROKE */
12182  nk_size i1 = 0;
12183  nk_size idx = list->vertex_count;
12184  const nk_size idx_count = count * 6;
12185  const nk_size vtx_count = count * 4;
12186  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
12187  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
12188  if (!vtx || !ids) return;
12189 
12190  for (i1 = 0; i1 < count; ++i1) {
12191  float dx, dy;
12192  const struct nk_vec2 uv = list->config.tex_null.uv;
12193  const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
12194  const struct nk_vec2 p1 = points[i1];
12195  const struct nk_vec2 p2 = points[i2];
12196  struct nk_vec2 diff = nk_vec2_sub(p2, p1);
12197  float len;
12198 
12199  /* vec2 inverted length */
12200  len = nk_vec2_len_sqr(diff);
12201  if (len != 0.0f)
12202  len = NK_INV_SQRT(len);
12203  else len = 1.0f;
12204  diff = nk_vec2_muls(diff, len);
12205 
12206  /* add vertices */
12207  dx = diff.x * (thickness * 0.5f);
12208  dy = diff.y * (thickness * 0.5f);
12209 
12210  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
12211  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
12212  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
12213  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
12214 
12215  ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
12216  ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
12217  ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
12218 
12219  ids += 6;
12220  idx += 4;
12221  }
12222  }
12223 }
12234 NK_API void
12235 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
12236  const struct nk_vec2 *points, const unsigned int points_count,
12237  struct nk_color color, enum nk_anti_aliasing aliasing)
12238 {
12239  struct nk_colorf col;
12240  struct nk_colorf col_trans;
12241 
12242  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
12243  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
12244  NK_ASSERT(list);
12245  if (!list || points_count < 3) return;
12246 
12247 #ifdef NK_INCLUDE_COMMAND_USERDATA
12248  nk_draw_list_push_userdata(list, list->userdata);
12249 #endif
12250 
12251  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
12252  nk_color_fv(&col.r, color);
12253  col_trans = col;
12254  col_trans.a = 0;
12255 
12256  if (aliasing == NK_ANTI_ALIASING_ON) {
12257  nk_size i = 0;
12258  nk_size i0 = 0;
12259  nk_size i1 = 0;
12260 
12261  const float AA_SIZE = 1.0f;
12262  nk_size vertex_offset = 0;
12263  nk_size index = list->vertex_count;
12264 
12265  const nk_size idx_count = (points_count-2)*3 + points_count*6;
12266  const nk_size vtx_count = (points_count*2);
12267 
12268  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
12269  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
12270 
12271  nk_size size = 0;
12272  struct nk_vec2 *normals = 0;
12273  unsigned int vtx_inner_idx = (unsigned int)(index + 0);
12274  unsigned int vtx_outer_idx = (unsigned int)(index + 1);
12275  if (!vtx || !ids) return;
12276 
12277  /* temporary allocate normals */
12278  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
12279  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
12280  size = pnt_size * points_count;
12281  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
12282  if (!normals) return;
12283  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
12284 
12285  /* add elements */
12286  for (i = 2; i < points_count; i++) {
12287  ids[0] = (nk_draw_index)(vtx_inner_idx);
12288  ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
12289  ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
12290  ids += 3;
12291  }
12292 
12293  /* compute normals */
12294  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
12295  struct nk_vec2 p0 = points[i0];
12296  struct nk_vec2 p1 = points[i1];
12297  struct nk_vec2 diff = nk_vec2_sub(p1, p0);
12298 
12299  /* vec2 inverted length */
12300  float len = nk_vec2_len_sqr(diff);
12301  if (len != 0.0f)
12302  len = NK_INV_SQRT(len);
12303  else len = 1.0f;
12304  diff = nk_vec2_muls(diff, len);
12305 
12306  normals[i0].x = diff.y;
12307  normals[i0].y = -diff.x;
12308  }
12309 
12310  /* add vertices + indexes */
12311  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
12312  const struct nk_vec2 uv = list->config.tex_null.uv;
12313  struct nk_vec2 n0 = normals[i0];
12314  struct nk_vec2 n1 = normals[i1];
12315  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
12316  float dmr2 = dm.x*dm.x + dm.y*dm.y;
12317  if (dmr2 > 0.000001f) {
12318  float scale = 1.0f / dmr2;
12319  scale = NK_MIN(scale, 100.0f);
12320  dm = nk_vec2_muls(dm, scale);
12321  }
12322  dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
12323 
12324  /* add vertices */
12325  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
12326  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
12327 
12328  /* add indexes */
12329  ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
12330  ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
12331  ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
12332  ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
12333  ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
12334  ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
12335  ids += 6;
12336  }
12337  /* free temporary normals + points */
12338  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
12339  } else {
12340  nk_size i = 0;
12341  nk_size index = list->vertex_count;
12342  const nk_size idx_count = (points_count-2)*3;
12343  const nk_size vtx_count = points_count;
12344  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
12345  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
12346 
12347  if (!vtx || !ids) return;
12348  for (i = 0; i < vtx_count; ++i)
12349  vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.tex_null.uv, col);
12350  for (i = 2; i < points_count; ++i) {
12351  ids[0] = (nk_draw_index)index;
12352  ids[1] = (nk_draw_index)(index+ i - 1);
12353  ids[2] = (nk_draw_index)(index+i);
12354  ids += 3;
12355  }
12356  }
12357 }
12368 NK_API void
12369 nk_draw_list_path_clear(struct nk_draw_list *list)
12370 {
12371  NK_ASSERT(list);
12372  if (!list) return;
12373  nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
12374  list->path_count = 0;
12375  list->path_offset = 0;
12376 }
12388 NK_API void
12389 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
12390 {
12391  struct nk_vec2 *points = 0;
12392  struct nk_draw_command *cmd = 0;
12393  NK_ASSERT(list);
12394  if (!list) return;
12395  if (!list->cmd_count)
12396  nk_draw_list_add_clip(list, nk_null_rect);
12397 
12398  cmd = nk_draw_list_command_last(list);
12399  if (cmd && cmd->texture.ptr != list->config.tex_null.texture.ptr)
12400  nk_draw_list_push_image(list, list->config.tex_null.texture);
12401 
12402  points = nk_draw_list_alloc_path(list, 1);
12403  if (!points) return;
12404  points[0] = pos;
12405 }
12417 NK_API void
12418 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
12419  float radius, int a_min, int a_max)
12420 {
12421  int a = 0;
12422  NK_ASSERT(list);
12423  if (!list) return;
12424  if (a_min <= a_max) {
12425  for (a = a_min; a <= a_max; a++) {
12426  const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
12427  const float x = center.x + c.x * radius;
12428  const float y = center.y + c.y * radius;
12429  nk_draw_list_path_line_to(list, nk_vec2(x, y));
12430  }
12431  }
12432 }
12444 NK_API void
12445 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
12446  float radius, float a_min, float a_max, unsigned int segments)
12447 {
12448  unsigned int i = 0;
12449  NK_ASSERT(list);
12450  if (!list) return;
12451  if (radius == 0.0f) return;
12452 
12453  /* This algorithm for arc drawing relies on these two trigonometric identities[1]:
12454  sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
12455  cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
12456 
12457  Two coordinates (x, y) of a point on a circle centered on
12458  the origin can be written in polar form as:
12459  x = r * cos(a)
12460  y = r * sin(a)
12461  where r is the radius of the circle,
12462  a is the angle between (x, y) and the origin.
12463 
12464  This allows us to rotate the coordinates around the
12465  origin by an angle b using the following transformation:
12466  x' = r * cos(a + b) = x * cos(b) - y * sin(b)
12467  y' = r * sin(a + b) = y * cos(b) + x * sin(b)
12468 
12469  [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
12470  */
12471  {const float d_angle = (a_max - a_min) / (float)segments;
12472  const float sin_d = (float)NK_SIN(d_angle);
12473  const float cos_d = (float)NK_COS(d_angle);
12474 
12475  float cx = (float)NK_COS(a_min) * radius;
12476  float cy = (float)NK_SIN(a_min) * radius;
12477  for(i = 0; i <= segments; ++i) {
12478  float new_cx, new_cy;
12479  const float x = center.x + cx;
12480  const float y = center.y + cy;
12481  nk_draw_list_path_line_to(list, nk_vec2(x, y));
12482 
12483  new_cx = cx * cos_d - cy * sin_d;
12484  new_cy = cy * cos_d + cx * sin_d;
12485  cx = new_cx;
12486  cy = new_cy;
12487  }}
12488 }
12500 NK_API void
12501 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
12502  struct nk_vec2 b, float rounding)
12503 {
12504  float r;
12505  NK_ASSERT(list);
12506  if (!list) return;
12507  r = rounding;
12508  r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
12509  r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
12510 
12511  if (r == 0.0f) {
12512  nk_draw_list_path_line_to(list, a);
12513  nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
12514  nk_draw_list_path_line_to(list, b);
12515  nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
12516  } else {
12517  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
12518  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
12519  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
12520  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
12521  }
12522 }
12534 NK_API void
12535 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
12536  struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
12537 {
12538  float t_step;
12539  unsigned int i_step;
12540  struct nk_vec2 p1;
12541 
12542  NK_ASSERT(list);
12543  NK_ASSERT(list->path_count);
12544  if (!list || !list->path_count) return;
12545  num_segments = NK_MAX(num_segments, 1);
12546 
12547  p1 = nk_draw_list_path_last(list);
12548  t_step = 1.0f/(float)num_segments;
12549  for (i_step = 1; i_step <= num_segments; ++i_step) {
12550  float t = t_step * (float)i_step;
12551  float u = 1.0f - t;
12552  float w1 = u*u*u;
12553  float w2 = 3*u*u*t;
12554  float w3 = 3*u*t*t;
12555  float w4 = t * t *t;
12556  float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
12557  float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
12558  nk_draw_list_path_line_to(list, nk_vec2(x,y));
12559  }
12560 }
12572 NK_API void
12573 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
12574 {
12575  struct nk_vec2 *points;
12576  NK_ASSERT(list);
12577  if (!list) return;
12578  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
12579  nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
12580  nk_draw_list_path_clear(list);
12581 }
12593 NK_API void
12594 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
12595  enum nk_draw_list_stroke closed, float thickness)
12596 {
12597  struct nk_vec2 *points;
12598  NK_ASSERT(list);
12599  if (!list) return;
12600  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
12601  nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
12602  closed, thickness, list->config.line_AA);
12603  nk_draw_list_path_clear(list);
12604 }
12616 NK_API void
12617 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
12618  struct nk_vec2 b, struct nk_color col, float thickness)
12619 {
12620  NK_ASSERT(list);
12621  if (!list || !col.a) return;
12622  if (list->line_AA == NK_ANTI_ALIASING_ON) {
12623  nk_draw_list_path_line_to(list, a);
12624  nk_draw_list_path_line_to(list, b);
12625  } else {
12626  nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
12627  nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
12628  }
12629  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
12630 }
12642 NK_API void
12643 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
12644  struct nk_color col, float rounding)
12645 {
12646  NK_ASSERT(list);
12647  if (!list || !col.a) return;
12648 
12649  if (list->line_AA == NK_ANTI_ALIASING_ON) {
12650  nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
12651  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
12652  } else {
12653  nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
12654  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
12655  } nk_draw_list_path_fill(list, col);
12656 }
12668 NK_API void
12669 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
12670  struct nk_color col, float rounding, float thickness)
12671 {
12672  NK_ASSERT(list);
12673  if (!list || !col.a) return;
12674  if (list->line_AA == NK_ANTI_ALIASING_ON) {
12675  nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
12676  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
12677  } else {
12678  nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
12679  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
12680  } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
12681 }
12693 NK_API void
12694 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
12695  struct nk_color left, struct nk_color top, struct nk_color right,
12696  struct nk_color bottom)
12697 {
12698  void *vtx;
12699  struct nk_colorf col_left, col_top;
12700  struct nk_colorf col_right, col_bottom;
12701  nk_draw_index *idx;
12702  nk_draw_index index;
12703 
12704  nk_color_fv(&col_left.r, left);
12705  nk_color_fv(&col_right.r, right);
12706  nk_color_fv(&col_top.r, top);
12707  nk_color_fv(&col_bottom.r, bottom);
12708 
12709  NK_ASSERT(list);
12710  if (!list) return;
12711 
12712  nk_draw_list_push_image(list, list->config.tex_null.texture);
12713  index = (nk_draw_index)list->vertex_count;
12714  vtx = nk_draw_list_alloc_vertices(list, 4);
12715  idx = nk_draw_list_alloc_elements(list, 6);
12716  if (!vtx || !idx) return;
12717 
12718  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
12719  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
12720  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
12721 
12722  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.tex_null.uv, col_left);
12723  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.tex_null.uv, col_top);
12724  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.tex_null.uv, col_right);
12725  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.tex_null.uv, col_bottom);
12726 }
12738 NK_API void
12739 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
12740  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
12741 {
12742  NK_ASSERT(list);
12743  if (!list || !col.a) return;
12744  nk_draw_list_path_line_to(list, a);
12745  nk_draw_list_path_line_to(list, b);
12746  nk_draw_list_path_line_to(list, c);
12747  nk_draw_list_path_fill(list, col);
12748 }
12760 NK_API void
12761 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
12762  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
12763 {
12764  NK_ASSERT(list);
12765  if (!list || !col.a) return;
12766  nk_draw_list_path_line_to(list, a);
12767  nk_draw_list_path_line_to(list, b);
12768  nk_draw_list_path_line_to(list, c);
12769  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
12770 }
12782 NK_API void
12783 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
12784  float radius, struct nk_color col, unsigned int segs)
12785 {
12786  float a_max;
12787  NK_ASSERT(list);
12788  if (!list || !col.a) return;
12789  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
12790  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
12791  nk_draw_list_path_fill(list, col);
12792 }
12804 NK_API void
12805 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
12806  float radius, struct nk_color col, unsigned int segs, float thickness)
12807 {
12808  float a_max;
12809  NK_ASSERT(list);
12810  if (!list || !col.a) return;
12811  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
12812  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
12813  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
12814 }
12826 NK_API void
12827 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
12828  struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
12829  struct nk_color col, unsigned int segments, float thickness)
12830 {
12831  NK_ASSERT(list);
12832  if (!list || !col.a) return;
12833  nk_draw_list_path_line_to(list, p0);
12834  nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
12835  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
12836 }
12848 NK_INTERN void
12849 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
12850  struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
12851  struct nk_color color)
12852 {
12853  void *vtx;
12854  struct nk_vec2 uvb;
12855  struct nk_vec2 uvd;
12856  struct nk_vec2 b;
12857  struct nk_vec2 d;
12858 
12859  struct nk_colorf col;
12860  nk_draw_index *idx;
12861  nk_draw_index index;
12862  NK_ASSERT(list);
12863  if (!list) return;
12864 
12865  nk_color_fv(&col.r, color);
12866  uvb = nk_vec2(uvc.x, uva.y);
12867  uvd = nk_vec2(uva.x, uvc.y);
12868  b = nk_vec2(c.x, a.y);
12869  d = nk_vec2(a.x, c.y);
12870 
12871  index = (nk_draw_index)list->vertex_count;
12872  vtx = nk_draw_list_alloc_vertices(list, 4);
12873  idx = nk_draw_list_alloc_elements(list, 6);
12874  if (!vtx || !idx) return;
12875 
12876  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
12877  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
12878  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
12879 
12880  vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
12881  vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
12882  vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
12883  vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
12884 }
12896 NK_API void
12897 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
12898  struct nk_rect rect, struct nk_color color)
12899 {
12900  NK_ASSERT(list);
12901  if (!list) return;
12902  /* push new command with given texture */
12903  nk_draw_list_push_image(list, texture.handle);
12904  if (nk_image_is_subimage(&texture)) {
12905  /* add region inside of the texture */
12906  struct nk_vec2 uv[2];
12907  uv[0].x = (float)texture.region[0]/(float)texture.w;
12908  uv[0].y = (float)texture.region[1]/(float)texture.h;
12909  uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
12910  uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
12911  nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
12912  nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color);
12913  } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
12914  nk_vec2(rect.x + rect.w, rect.y + rect.h),
12915  nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
12916 }
12928 NK_API void
12929 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
12930  struct nk_rect rect, const char *text, int len, float font_height,
12931  struct nk_color fg)
12932 {
12933  float x = 0;
12934  int text_len = 0;
12935  nk_rune unicode = 0;
12936  nk_rune next = 0;
12937  int glyph_len = 0;
12938  int next_glyph_len = 0;
12939  struct nk_user_font_glyph g;
12940 
12941  NK_ASSERT(list);
12942  if (!list || !len || !text) return;
12943  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
12944  list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
12945 
12946  nk_draw_list_push_image(list, font->texture);
12947  x = rect.x;
12948  glyph_len = nk_utf_decode(text, &unicode, len);
12949  if (!glyph_len) return;
12950 
12951  /* draw every glyph image */
12952  fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
12953  while (text_len < len && glyph_len) {
12954  float gx, gy, gh, gw;
12955  float char_width = 0;
12956  if (unicode == NK_UTF_INVALID) break;
12957 
12958  /* query currently drawn glyph information */
12959  next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
12960  font->query(font->userdata, font_height, &g, unicode,
12961  (next == NK_UTF_INVALID) ? '\0' : next);
12962 
12963  /* calculate and draw glyph drawing rectangle and image */
12964  gx = x + g.offset.x;
12965  gy = rect.y + g.offset.y;
12966  gw = g.width; gh = g.height;
12967  char_width = g.xadvance;
12968  nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
12969  g.uv[0], g.uv[1], fg);
12970 
12971  /* offset next glyph */
12972  text_len += glyph_len;
12973  x += char_width;
12974  glyph_len = next_glyph_len;
12975  unicode = next;
12976  }
12977 }
12989 NK_API nk_flags
12990 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
12991  struct nk_buffer *vertices, struct nk_buffer *elements,
12992  const struct nk_convert_config *config)
12993 {
12994  nk_flags res = NK_CONVERT_SUCCESS;
12995  const struct nk_command *cmd;
12996  NK_ASSERT(ctx);
12997  NK_ASSERT(cmds);
12998  NK_ASSERT(vertices);
12999  NK_ASSERT(elements);
13000  NK_ASSERT(config);
13001  NK_ASSERT(config->vertex_layout);
13002  NK_ASSERT(config->vertex_size);
13003  if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
13004  return NK_CONVERT_INVALID_PARAM;
13005 
13006  nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
13007  config->line_AA, config->shape_AA);
13008  nk_foreach(cmd, ctx)
13009  {
13010 #ifdef NK_INCLUDE_COMMAND_USERDATA
13011  ctx->draw_list.userdata = cmd->userdata;
13012 #endif
13013  switch (cmd->type) {
13014  case NK_COMMAND_NOP: break;
13015  case NK_COMMAND_SCISSOR: {
13016  const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
13017  nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
13018  } break;
13019  case NK_COMMAND_LINE: {
13020  const struct nk_command_line *l = (const struct nk_command_line*)cmd;
13021  nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
13022  nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
13023  } break;
13024  case NK_COMMAND_CURVE: {
13025  const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
13026  nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
13027  nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
13028  q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
13029  config->curve_segment_count, q->line_thickness);
13030  } break;
13031  case NK_COMMAND_RECT: {
13032  const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
13033  nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
13034  r->color, (float)r->rounding, r->line_thickness);
13035  } break;
13036  case NK_COMMAND_RECT_FILLED: {
13037  const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
13038  nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
13039  r->color, (float)r->rounding);
13040  } break;
13041  case NK_COMMAND_RECT_MULTI_COLOR: {
13042  const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
13043  nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
13044  r->left, r->top, r->right, r->bottom);
13045  } break;
13046  case NK_COMMAND_CIRCLE: {
13047  const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
13048  nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
13049  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
13050  config->circle_segment_count, c->line_thickness);
13051  } break;
13052  case NK_COMMAND_CIRCLE_FILLED: {
13053  const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
13054  nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
13055  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
13056  config->circle_segment_count);
13057  } break;
13058  case NK_COMMAND_ARC: {
13059  const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
13060  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
13061  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
13062  c->a[0], c->a[1], config->arc_segment_count);
13063  nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
13064  } break;
13065  case NK_COMMAND_ARC_FILLED: {
13066  const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
13067  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
13068  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
13069  c->a[0], c->a[1], config->arc_segment_count);
13070  nk_draw_list_path_fill(&ctx->draw_list, c->color);
13071  } break;
13072  case NK_COMMAND_TRIANGLE: {
13073  const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
13074  nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
13075  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
13076  t->line_thickness);
13077  } break;
13078  case NK_COMMAND_TRIANGLE_FILLED: {
13079  const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
13080  nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
13081  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
13082  } break;
13083  case NK_COMMAND_POLYGON: {
13084  int i;
13085  const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
13086  for (i = 0; i < p->point_count; ++i) {
13087  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
13088  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
13089  }
13090  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
13091  } break;
13092  case NK_COMMAND_POLYGON_FILLED: {
13093  int i;
13094  const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
13095  for (i = 0; i < p->point_count; ++i) {
13096  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
13097  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
13098  }
13099  nk_draw_list_path_fill(&ctx->draw_list, p->color);
13100  } break;
13101  case NK_COMMAND_POLYLINE: {
13102  int i;
13103  const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
13104  for (i = 0; i < p->point_count; ++i) {
13105  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
13106  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
13107  }
13108  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
13109  } break;
13110  case NK_COMMAND_TEXT: {
13111  const struct nk_command_text *t = (const struct nk_command_text*)cmd;
13112  nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
13113  t->string, t->length, t->height, t->foreground);
13114  } break;
13115  case NK_COMMAND_IMAGE: {
13116  const struct nk_command_image *i = (const struct nk_command_image*)cmd;
13117  nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
13118  } break;
13119  case NK_COMMAND_CUSTOM: {
13120  const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
13121  c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
13122  } break;
13123  default: break;
13124  }
13125  }
13126  res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
13127  res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
13128  res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
13129  return res;
13130 }
13141 NK_API const struct nk_draw_command*
13142 nk__draw_begin(const struct nk_context *ctx,
13143  const struct nk_buffer *buffer)
13144 {
13145  return nk__draw_list_begin(&ctx->draw_list, buffer);
13146 }
13158 NK_API const struct nk_draw_command*
13159 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
13160 {
13161  return nk__draw_list_end(&ctx->draw_list, buffer);
13162 }
13173 NK_API const struct nk_draw_command*
13174 nk__draw_next(const struct nk_draw_command *cmd,
13175  const struct nk_buffer *buffer, const struct nk_context *ctx)
13176 {
13177  return nk__draw_list_next(cmd, buffer, &ctx->draw_list);
13178 }
13179 #endif
13180 
13181 
13182 /* stb_rect_pack.h - v1.01 - public domain - rectangle packing */
13183 /* Sean Barrett 2014 */
13184 /* */
13185 /* Useful for e.g. packing rectangular textures into an atlas. */
13186 /* Does not do rotation. */
13187 /* */
13188 /* Before #including, */
13189 /* */
13190 /* #define STB_RECT_PACK_IMPLEMENTATION */
13191 /* */
13192 /* in the file that you want to have the implementation. */
13193 /* */
13194 /* Not necessarily the awesomest packing method, but better than */
13195 /* the totally naive one in stb_truetype (which is primarily what */
13196 /* this is meant to replace). */
13197 /* */
13198 /* Has only had a few tests run, may have issues. */
13199 /* */
13200 /* More docs to come. */
13201 /* */
13202 /* No memory allocations; uses qsort() and assert() from stdlib. */
13203 /* Can override those by defining STBRP_SORT and STBRP_ASSERT. */
13204 /* */
13205 /* This library currently uses the Skyline Bottom-Left algorithm. */
13206 /* */
13207 /* Please note: better rectangle packers are welcome! Please */
13208 /* implement them to the same API, but with a different init */
13209 /* function. */
13210 /* */
13211 /* Credits */
13212 /* */
13213 /* Library */
13214 /* Sean Barrett */
13215 /* Minor features */
13216 /* Martins Mozeiko */
13217 /* github:IntellectualKitty */
13218 /* */
13219 /* Bugfixes / warning fixes */
13220 /* Jeremy Jaussaud */
13221 /* Fabian Giesen */
13222 /* */
13223 /* Version history: */
13224 /* */
13225 /* 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section */
13226 /* 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles */
13227 /* 0.99 (2019-02-07) warning fixes */
13228 /* 0.11 (2017-03-03) return packing success/fail result */
13229 /* 0.10 (2016-10-25) remove cast-away-const to avoid warnings */
13230 /* 0.09 (2016-08-27) fix compiler warnings */
13231 /* 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) */
13232 /* 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) */
13233 /* 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort */
13234 /* 0.05: added STBRP_ASSERT to allow replacing assert */
13235 /* 0.04: fixed minor bug in STBRP_LARGE_RECTS support */
13236 /* 0.01: initial release */
13237 /* */
13238 /* LICENSE */
13239 /* */
13240 /* See end of file for license information. */
13241 
13242 /* //////////////////////////////////////////////////////////////////////////// */
13243 /* */
13244 /* INCLUDE SECTION */
13245 /* */
13246 
13247 #ifndef STB_INCLUDE_STB_RECT_PACK_H
13248 #define STB_INCLUDE_STB_RECT_PACK_H
13249 
13250 #define STB_RECT_PACK_VERSION 1
13251 
13252 #ifdef STBRP_STATIC
13253 #define STBRP_DEF static
13254 #else
13255 #define STBRP_DEF extern
13256 #endif
13257 
13258 #ifdef __cplusplus
13259 extern "C" {
13260 #endif
13261 
13262 typedef struct stbrp_context stbrp_context;
13263 typedef struct stbrp_node stbrp_node;
13264 typedef struct stbrp_rect stbrp_rect;
13265 
13266 typedef int stbrp_coord;
13267 
13268 #define STBRP__MAXVAL 0x7fffffff
13269 /* Mostly for internal use, but this is the maximum supported coordinate value. */
13270 
13271 STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
13272 /* Assign packed locations to rectangles. The rectangles are of type */
13273 /* 'stbrp_rect' defined below, stored in the array 'rects', and there */
13274 /* are 'num_rects' many of them. */
13275 /* */
13276 /* Rectangles which are successfully packed have the 'was_packed' flag */
13277 /* set to a non-zero value and 'x' and 'y' store the minimum location */
13278 /* on each axis (i.e. bottom-left in cartesian coordinates, top-left */
13279 /* if you imagine y increasing downwards). Rectangles which do not fit */
13280 /* have the 'was_packed' flag set to 0. */
13281 /* */
13282 /* You should not try to access the 'rects' array from another thread */
13283 /* while this function is running, as the function temporarily reorders */
13284 /* the array while it executes. */
13285 /* */
13286 /* To pack into another rectangle, you need to call stbrp_init_target */
13287 /* again. To continue packing into the same rectangle, you can call */
13288 /* this function again. Calling this multiple times with multiple rect */
13289 /* arrays will probably produce worse packing results than calling it */
13290 /* a single time with the full rectangle array, but the option is */
13291 /* available. */
13292 /* */
13293 /* The function returns 1 if all of the rectangles were successfully */
13294 /* packed and 0 otherwise. */
13295 
13296 struct stbrp_rect
13297 {
13298  /* reserved for your use: */
13299  int id;
13300 
13301  /* input: */
13302  stbrp_coord w, h;
13303 
13304  /* output: */
13305  stbrp_coord x, y;
13306  int was_packed; /* non-zero if valid packing */
13307 
13308 }; /* 16 bytes, nominally */
13309 
13310 
13311 STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
13312 /* Initialize a rectangle packer to: */
13313 /* pack a rectangle that is 'width' by 'height' in dimensions */
13314 /* using temporary storage provided by the array 'nodes', which is 'num_nodes' long */
13315 /* */
13316 /* You must call this function every time you start packing into a new target. */
13317 /* */
13318 /* There is no "shutdown" function. The 'nodes' memory must stay valid for */
13319 /* the following stbrp_pack_rects() call (or calls), but can be freed after */
13320 /* the call (or calls) finish. */
13321 /* */
13322 /* Note: to guarantee best results, either: */
13323 /* 1. make sure 'num_nodes' >= 'width' */
13324 /* or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' */
13325 /* */
13326 /* If you don't do either of the above things, widths will be quantized to multiples */
13327 /* of small integers to guarantee the algorithm doesn't run out of temporary storage. */
13328 /* */
13329 /* If you do #2, then the non-quantized algorithm will be used, but the algorithm */
13330 /* may run out of temporary storage and be unable to pack some rectangles. */
13331 
13332 STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
13333 /* Optionally call this function after init but before doing any packing to */
13334 /* change the handling of the out-of-temp-memory scenario, described above. */
13335 /* If you call init again, this will be reset to the default (false). */
13336 
13337 
13338 STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
13339 /* Optionally select which packing heuristic the library should use. Different */
13340 /* heuristics will produce better/worse results for different data sets. */
13341 /* If you call init again, this will be reset to the default. */
13342 
13343 enum
13344 {
13345  STBRP_HEURISTIC_Skyline_default=0,
13346  STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
13347  STBRP_HEURISTIC_Skyline_BF_sortHeight
13348 };
13349 
13350 
13351 /* //////////////////////////////////////////////////////////////////////////// */
13352 /* */
13353 /* the details of the following structures don't matter to you, but they must */
13354 /* be visible so you can handle the memory allocations for them */
13355 
13356 struct stbrp_node
13357 {
13358  stbrp_coord x,y;
13359  stbrp_node *next;
13360 };
13361 
13362 struct stbrp_context
13363 {
13364  int width;
13365  int height;
13366  int align;
13367  int init_mode;
13368  int heuristic;
13369  int num_nodes;
13370  stbrp_node *active_head;
13371  stbrp_node *free_head;
13372  stbrp_node extra[2]; /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
13373 };
13374 
13375 #ifdef __cplusplus
13376 }
13377 #endif
13378 
13379 #endif
13380 
13381 /* //////////////////////////////////////////////////////////////////////////// */
13382 /* */
13383 /* IMPLEMENTATION SECTION */
13384 /* */
13385 
13386 #ifdef STB_RECT_PACK_IMPLEMENTATION
13387 #ifndef STBRP_SORT
13388 #include <stdlib.h>
13389 #define STBRP_SORT qsort
13390 #endif
13391 
13392 #ifndef STBRP_ASSERT
13393 #include <assert.h>
13394 #define STBRP_ASSERT assert
13395 #endif
13396 
13397 #ifdef _MSC_VER
13398 #define STBRP__NOTUSED(v) (void)(v)
13399 #define STBRP__CDECL __cdecl
13400 #else
13401 #define STBRP__NOTUSED(v) (void)sizeof(v)
13402 #define STBRP__CDECL
13403 #endif
13404 
13405 enum
13406 {
13407  STBRP__INIT_skyline = 1
13408 };
13409 
13410 STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
13411 {
13412  switch (context->init_mode) {
13413  case STBRP__INIT_skyline:
13414  STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
13415  context->heuristic = heuristic;
13416  break;
13417  default:
13418  STBRP_ASSERT(0);
13419  }
13420 }
13421 
13422 STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
13423 {
13424  if (allow_out_of_mem)
13425  /* if it's ok to run out of memory, then don't bother aligning them; */
13426  /* this gives better packing, but may fail due to OOM (even though */
13427  /* the rectangles easily fit). @TODO a smarter approach would be to only */
13428  /* quantize once we've hit OOM, then we could get rid of this parameter. */
13429  context->align = 1;
13430  else {
13431  /* if it's not ok to run out of memory, then quantize the widths */
13432  /* so that num_nodes is always enough nodes. */
13433  /* */
13434  /* I.e. num_nodes * align >= width */
13435  /* align >= width / num_nodes */
13436  /* align = ceil(width/num_nodes) */
13437 
13438  context->align = (context->width + context->num_nodes-1) / context->num_nodes;
13439  }
13440 }
13441 
13442 STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
13443 {
13444  int i;
13445 
13446  for (i=0; i < num_nodes-1; ++i)
13447  nodes[i].next = &nodes[i+1];
13448  nodes[i].next = NULL;
13449  context->init_mode = STBRP__INIT_skyline;
13450  context->heuristic = STBRP_HEURISTIC_Skyline_default;
13451  context->free_head = &nodes[0];
13452  context->active_head = &context->extra[0];
13453  context->width = width;
13454  context->height = height;
13455  context->num_nodes = num_nodes;
13456  stbrp_setup_allow_out_of_mem(context, 0);
13457 
13458  /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
13459  context->extra[0].x = 0;
13460  context->extra[0].y = 0;
13461  context->extra[0].next = &context->extra[1];
13462  context->extra[1].x = (stbrp_coord) width;
13463  context->extra[1].y = (1<<30);
13464  context->extra[1].next = NULL;
13465 }
13466 
13467 /* find minimum y position if it starts at x1 */
13468 static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
13469 {
13470  stbrp_node *node = first;
13471  int x1 = x0 + width;
13472  int min_y, visited_width, waste_area;
13473 
13474  STBRP__NOTUSED(c);
13475 
13476  STBRP_ASSERT(first->x <= x0);
13477 
13478  #if 0
13479  /* skip in case we're past the node */
13480  while (node->next->x <= x0)
13481  ++node;
13482  #else
13483  STBRP_ASSERT(node->next->x > x0); /* we ended up handling this in the caller for efficiency */
13484  #endif
13485 
13486  STBRP_ASSERT(node->x <= x0);
13487 
13488  min_y = 0;
13489  waste_area = 0;
13490  visited_width = 0;
13491  while (node->x < x1) {
13492  if (node->y > min_y) {
13493  /* raise min_y higher. */
13494  /* we've accounted for all waste up to min_y, */
13495  /* but we'll now add more waste for everything we've visited */
13496  waste_area += visited_width * (node->y - min_y);
13497  min_y = node->y;
13498  /* the first time through, visited_width might be reduced */
13499  if (node->x < x0)
13500  visited_width += node->next->x - x0;
13501  else
13502  visited_width += node->next->x - node->x;
13503  } else {
13504  /* add waste area */
13505  int under_width = node->next->x - node->x;
13506  if (under_width + visited_width > width)
13507  under_width = width - visited_width;
13508  waste_area += under_width * (min_y - node->y);
13509  visited_width += under_width;
13510  }
13511  node = node->next;
13512  }
13513 
13514  *pwaste = waste_area;
13515  return min_y;
13516 }
13517 
13518 typedef struct
13519 {
13520  int x,y;
13521  stbrp_node **prev_link;
13522 } stbrp__findresult;
13523 
13524 static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
13525 {
13526  int best_waste = (1<<30), best_x, best_y = (1 << 30);
13527  stbrp__findresult fr;
13528  stbrp_node **prev, *node, *tail, **best = NULL;
13529 
13530  /* align to multiple of c->align */
13531  width = (width + c->align - 1);
13532  width -= width % c->align;
13533  STBRP_ASSERT(width % c->align == 0);
13534 
13535  /* if it can't possibly fit, bail immediately */
13536  if (width > c->width || height > c->height) {
13537  fr.prev_link = NULL;
13538  fr.x = fr.y = 0;
13539  return fr;
13540  }
13541 
13542  node = c->active_head;
13543  prev = &c->active_head;
13544  while (node->x + width <= c->width) {
13545  int y,waste;
13546  y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
13547  if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { /* actually just want to test BL */
13548  /* bottom left */
13549  if (y < best_y) {
13550  best_y = y;
13551  best = prev;
13552  }
13553  } else {
13554  /* best-fit */
13555  if (y + height <= c->height) {
13556  /* can only use it if it first vertically */
13557  if (y < best_y || (y == best_y && waste < best_waste)) {
13558  best_y = y;
13559  best_waste = waste;
13560  best = prev;
13561  }
13562  }
13563  }
13564  prev = &node->next;
13565  node = node->next;
13566  }
13567 
13568  best_x = (best == NULL) ? 0 : (*best)->x;
13569 
13570  /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
13571  /* */
13572  /* e.g, if fitting */
13573  /* */
13574  /* ____________________ */
13575  /* |____________________| */
13576  /* */
13577  /* into */
13578  /* */
13579  /* | | */
13580  /* | ____________| */
13581  /* |____________| */
13582  /* */
13583  /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
13584  /* */
13585  /* This makes BF take about 2x the time */
13586 
13587  if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
13588  tail = c->active_head;
13589  node = c->active_head;
13590  prev = &c->active_head;
13591  /* find first node that's admissible */
13592  while (tail->x < width)
13593  tail = tail->next;
13594  while (tail) {
13595  int xpos = tail->x - width;
13596  int y,waste;
13597  STBRP_ASSERT(xpos >= 0);
13598  /* find the left position that matches this */
13599  while (node->next->x <= xpos) {
13600  prev = &node->next;
13601  node = node->next;
13602  }
13603  STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
13604  y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
13605  if (y + height <= c->height) {
13606  if (y <= best_y) {
13607  if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
13608  best_x = xpos;
13609  STBRP_ASSERT(y <= best_y);
13610  best_y = y;
13611  best_waste = waste;
13612  best = prev;
13613  }
13614  }
13615  }
13616  tail = tail->next;
13617  }
13618  }
13619 
13620  fr.prev_link = best;
13621  fr.x = best_x;
13622  fr.y = best_y;
13623  return fr;
13624 }
13625 
13626 static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
13627 {
13628  /* find best position according to heuristic */
13629  stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
13630  stbrp_node *node, *cur;
13631 
13632  /* bail if: */
13633  /* 1. it failed */
13634  /* 2. the best node doesn't fit (we don't always check this) */
13635  /* 3. we're out of memory */
13636  if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
13637  res.prev_link = NULL;
13638  return res;
13639  }
13640 
13641  /* on success, create new node */
13642  node = context->free_head;
13643  node->x = (stbrp_coord) res.x;
13644  node->y = (stbrp_coord) (res.y + height);
13645 
13646  context->free_head = node->next;
13647 
13648  /* insert the new node into the right starting point, and */
13649  /* let 'cur' point to the remaining nodes needing to be */
13650  /* stitched back in */
13651 
13652  cur = *res.prev_link;
13653  if (cur->x < res.x) {
13654  /* preserve the existing one, so start testing with the next one */
13655  stbrp_node *next = cur->next;
13656  cur->next = node;
13657  cur = next;
13658  } else {
13659  *res.prev_link = node;
13660  }
13661 
13662  /* from here, traverse cur and free the nodes, until we get to one */
13663  /* that shouldn't be freed */
13664  while (cur->next && cur->next->x <= res.x + width) {
13665  stbrp_node *next = cur->next;
13666  /* move the current node to the free list */
13667  cur->next = context->free_head;
13668  context->free_head = cur;
13669  cur = next;
13670  }
13671 
13672  /* stitch the list back in */
13673  node->next = cur;
13674 
13675  if (cur->x < res.x + width)
13676  cur->x = (stbrp_coord) (res.x + width);
13677 
13678 #ifdef _DEBUG
13679  cur = context->active_head;
13680  while (cur->x < context->width) {
13681  STBRP_ASSERT(cur->x < cur->next->x);
13682  cur = cur->next;
13683  }
13684  STBRP_ASSERT(cur->next == NULL);
13685 
13686  {
13687  int count=0;
13688  cur = context->active_head;
13689  while (cur) {
13690  cur = cur->next;
13691  ++count;
13692  }
13693  cur = context->free_head;
13694  while (cur) {
13695  cur = cur->next;
13696  ++count;
13697  }
13698  STBRP_ASSERT(count == context->num_nodes+2);
13699  }
13700 #endif
13701 
13702  return res;
13703 }
13704 
13705 static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
13706 {
13707  const stbrp_rect *p = (const stbrp_rect *) a;
13708  const stbrp_rect *q = (const stbrp_rect *) b;
13709  if (p->h > q->h)
13710  return -1;
13711  if (p->h < q->h)
13712  return 1;
13713  return (p->w > q->w) ? -1 : (p->w < q->w);
13714 }
13715 
13716 static int STBRP__CDECL rect_original_order(const void *a, const void *b)
13717 {
13718  const stbrp_rect *p = (const stbrp_rect *) a;
13719  const stbrp_rect *q = (const stbrp_rect *) b;
13720  return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
13721 }
13722 
13723 STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
13724 {
13725  int i, all_rects_packed = 1;
13726 
13727  /* we use the 'was_packed' field internally to allow sorting/unsorting */
13728  for (i=0; i < num_rects; ++i) {
13729  rects[i].was_packed = i;
13730  }
13731 
13732  /* sort according to heuristic */
13733  STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
13734 
13735  for (i=0; i < num_rects; ++i) {
13736  if (rects[i].w == 0 || rects[i].h == 0) {
13737  rects[i].x = rects[i].y = 0; /* empty rect needs no space */
13738  } else {
13739  stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
13740  if (fr.prev_link) {
13741  rects[i].x = (stbrp_coord) fr.x;
13742  rects[i].y = (stbrp_coord) fr.y;
13743  } else {
13744  rects[i].x = rects[i].y = STBRP__MAXVAL;
13745  }
13746  }
13747  }
13748 
13749  /* unsort */
13750  STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
13751 
13752  /* set was_packed flags and all_rects_packed status */
13753  for (i=0; i < num_rects; ++i) {
13754  rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
13755  if (!rects[i].was_packed)
13756  all_rects_packed = 0;
13757  }
13758 
13759  /* return the all_rects_packed status */
13760  return all_rects_packed;
13761 }
13762 #endif
13763 
13764 /*
13765 ------------------------------------------------------------------------------
13766 This software is available under 2 licenses -- choose whichever you prefer.
13767 ------------------------------------------------------------------------------
13768 ALTERNATIVE A - MIT License
13769 Copyright (c) 2017 Sean Barrett
13770 Permission is hereby granted, free of charge, to any person obtaining a copy of
13771 this software and associated documentation files (the "Software"), to deal in
13772 the Software without restriction, including without limitation the rights to
13773 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
13774 of the Software, and to permit persons to whom the Software is furnished to do
13775 so, subject to the following conditions:
13776 The above copyright notice and this permission notice shall be included in all
13777 copies or substantial portions of the Software.
13778 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13779 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13780 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13781 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
13782 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
13783 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
13784 SOFTWARE.
13785 ------------------------------------------------------------------------------
13786 ALTERNATIVE B - Public Domain (www.unlicense.org)
13787 This is free and unencumbered software released into the public domain.
13788 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
13789 software, either in source code form or as a compiled binary, for any purpose,
13790 commercial or non-commercial, and by any means.
13791 In jurisdictions that recognize copyright laws, the author or authors of this
13792 software dedicate any and all copyright interest in the software to the public
13793 domain. We make this dedication for the benefit of the public at large and to
13794 the detriment of our heirs and successors. We intend this dedication to be an
13795 overt act of relinquishment in perpetuity of all present and future rights to
13796 this software under copyright law.
13797 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13798 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13799 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13800 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
13801 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
13802 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13803 ------------------------------------------------------------------------------
13804 */
13805 
13806 /* stb_truetype.h - v1.26 - public domain */
13807 /* authored from 2009-2021 by Sean Barrett / RAD Game Tools */
13808 /* */
13809 /* ======================================================================= */
13810 /* */
13811 /* NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES */
13812 /* */
13813 /* This library does no range checking of the offsets found in the file, */
13814 /* meaning an attacker can use it to read arbitrary memory. */
13815 /* */
13816 /* ======================================================================= */
13817 /* */
13818 /* This library processes TrueType files: */
13819 /* parse files */
13820 /* extract glyph metrics */
13821 /* extract glyph shapes */
13822 /* render glyphs to one-channel bitmaps with antialiasing (box filter) */
13823 /* render glyphs to one-channel SDF bitmaps (signed-distance field/function) */
13824 /* */
13825 /* Todo: */
13826 /* non-MS cmaps */
13827 /* crashproof on bad data */
13828 /* hinting? (no longer patented) */
13829 /* cleartype-style AA? */
13830 /* optimize: use simple memory allocator for intermediates */
13831 /* optimize: build edge-list directly from curves */
13832 /* optimize: rasterize directly from curves? */
13833 /* */
13834 /* ADDITIONAL CONTRIBUTORS */
13835 /* */
13836 /* Mikko Mononen: compound shape support, more cmap formats */
13837 /* Tor Andersson: kerning, subpixel rendering */
13838 /* Dougall Johnson: OpenType / Type 2 font handling */
13839 /* Daniel Ribeiro Maciel: basic GPOS-based kerning */
13840 /* */
13841 /* Misc other: */
13842 /* Ryan Gordon */
13843 /* Simon Glass */
13844 /* github:IntellectualKitty */
13845 /* Imanol Celaya */
13846 /* Daniel Ribeiro Maciel */
13847 /* */
13848 /* Bug/warning reports/fixes: */
13849 /* "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe */
13850 /* Cass Everitt Martins Mozeiko github:aloucks */
13851 /* stoiko (Haemimont Games) Cap Petschulat github:oyvindjam */
13852 /* Brian Hook Omar Cornut github:vassvik */
13853 /* Walter van Niftrik Ryan Griege */
13854 /* David Gow Peter LaValle */
13855 /* David Given Sergey Popov */
13856 /* Ivan-Assen Ivanov Giumo X. Clanjor */
13857 /* Anthony Pesch Higor Euripedes */
13858 /* Johan Duparc Thomas Fields */
13859 /* Hou Qiming Derek Vinyard */
13860 /* Rob Loach Cort Stratton */
13861 /* Kenney Phillis Jr. Brian Costabile */
13862 /* Ken Voskuil (kaesve) */
13863 /* */
13864 /* VERSION HISTORY */
13865 /* */
13866 /* 1.26 (2021-08-28) fix broken rasterizer */
13867 /* 1.25 (2021-07-11) many fixes */
13868 /* 1.24 (2020-02-05) fix warning */
13869 /* 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) */
13870 /* 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined */
13871 /* 1.21 (2019-02-25) fix warning */
13872 /* 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() */
13873 /* 1.19 (2018-02-11) GPOS kerning, STBTT_fmod */
13874 /* 1.18 (2018-01-29) add missing function */
13875 /* 1.17 (2017-07-23) make more arguments const; doc fix */
13876 /* 1.16 (2017-07-12) SDF support */
13877 /* 1.15 (2017-03-03) make more arguments const */
13878 /* 1.14 (2017-01-16) num-fonts-in-TTC function */
13879 /* 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts */
13880 /* 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual */
13881 /* 1.11 (2016-04-02) fix unused-variable warning */
13882 /* 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef */
13883 /* 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly */
13884 /* 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges */
13885 /* 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; */
13886 /* variant PackFontRanges to pack and render in separate phases; */
13887 /* fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); */
13888 /* fixed an assert() bug in the new rasterizer */
13889 /* replace assert() with STBTT_assert() in new rasterizer */
13890 /* */
13891 /* Full history can be found at the end of this file. */
13892 /* */
13893 /* LICENSE */
13894 /* */
13895 /* See end of file for license information. */
13896 /* */
13897 /* USAGE */
13898 /* */
13899 /* Include this file in whatever places need to refer to it. In ONE C/C++ */
13900 /* file, write: */
13901 /* #define STB_TRUETYPE_IMPLEMENTATION */
13902 /* before the #include of this file. This expands out the actual */
13903 /* implementation into that C/C++ file. */
13904 /* */
13905 /* To make the implementation private to the file that generates the implementation, */
13906 /* #define STBTT_STATIC */
13907 /* */
13908 /* Simple 3D API (don't ship this, but it's fine for tools and quick start) */
13909 /* stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture */
13910 /* stbtt_GetBakedQuad() -- compute quad to draw for a given char */
13911 /* */
13912 /* Improved 3D API (more shippable): */
13913 /* #include "stb_rect_pack.h" -- optional, but you really want it */
13914 /* stbtt_PackBegin() */
13915 /* stbtt_PackSetOversampling() -- for improved quality on small fonts */
13916 /* stbtt_PackFontRanges() -- pack and renders */
13917 /* stbtt_PackEnd() */
13918 /* stbtt_GetPackedQuad() */
13919 /* */
13920 /* "Load" a font file from a memory buffer (you have to keep the buffer loaded) */
13921 /* stbtt_InitFont() */
13922 /* stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections */
13923 /* stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections */
13924 /* */
13925 /* Render a unicode codepoint to a bitmap */
13926 /* stbtt_GetCodepointBitmap() -- allocates and returns a bitmap */
13927 /* stbtt_MakeCodepointBitmap() -- renders into bitmap you provide */
13928 /* stbtt_GetCodepointBitmapBox() -- how big the bitmap must be */
13929 /* */
13930 /* Character advance/positioning */
13931 /* stbtt_GetCodepointHMetrics() */
13932 /* stbtt_GetFontVMetrics() */
13933 /* stbtt_GetFontVMetricsOS2() */
13934 /* stbtt_GetCodepointKernAdvance() */
13935 /* */
13936 /* Starting with version 1.06, the rasterizer was replaced with a new, */
13937 /* faster and generally-more-precise rasterizer. The new rasterizer more */
13938 /* accurately measures pixel coverage for anti-aliasing, except in the case */
13939 /* where multiple shapes overlap, in which case it overestimates the AA pixel */
13940 /* coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If */
13941 /* this turns out to be a problem, you can re-enable the old rasterizer with */
13942 /* #define STBTT_RASTERIZER_VERSION 1 */
13943 /* which will incur about a 15% speed hit. */
13944 /* */
13945 /* ADDITIONAL DOCUMENTATION */
13946 /* */
13947 /* Immediately after this block comment are a series of sample programs. */
13948 /* */
13949 /* After the sample programs is the "header file" section. This section */
13950 /* includes documentation for each API function. */
13951 /* */
13952 /* Some important concepts to understand to use this library: */
13953 /* */
13954 /* Codepoint */
13955 /* Characters are defined by unicode codepoints, e.g. 65 is */
13956 /* uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is */
13957 /* the hiragana for "ma". */
13958 /* */
13959 /* Glyph */
13960 /* A visual character shape (every codepoint is rendered as */
13961 /* some glyph) */
13962 /* */
13963 /* Glyph index */
13964 /* A font-specific integer ID representing a glyph */
13965 /* */
13966 /* Baseline */
13967 /* Glyph shapes are defined relative to a baseline, which is the */
13968 /* bottom of uppercase characters. Characters extend both above */
13969 /* and below the baseline. */
13970 /* */
13971 /* Current Point */
13972 /* As you draw text to the screen, you keep track of a "current point" */
13973 /* which is the origin of each character. The current point's vertical */
13974 /* position is the baseline. Even "baked fonts" use this model. */
13975 /* */
13976 /* Vertical Font Metrics */
13977 /* The vertical qualities of the font, used to vertically position */
13978 /* and space the characters. See docs for stbtt_GetFontVMetrics. */
13979 /* */
13980 /* Font Size in Pixels or Points */
13981 /* The preferred interface for specifying font sizes in stb_truetype */
13982 /* is to specify how tall the font's vertical extent should be in pixels. */
13983 /* If that sounds good enough, skip the next paragraph. */
13984 /* */
13985 /* Most font APIs instead use "points", which are a common typographic */
13986 /* measurement for describing font size, defined as 72 points per inch. */
13987 /* stb_truetype provides a point API for compatibility. However, true */
13988 /* "per inch" conventions don't make much sense on computer displays */
13989 /* since different monitors have different number of pixels per */
13990 /* inch. For example, Windows traditionally uses a convention that */
13991 /* there are 96 pixels per inch, thus making 'inch' measurements have */
13992 /* nothing to do with inches, and thus effectively defining a point to */
13993 /* be 1.333 pixels. Additionally, the TrueType font data provides */
13994 /* an explicit scale factor to scale a given font's glyphs to points, */
13995 /* but the author has observed that this scale factor is often wrong */
13996 /* for non-commercial fonts, thus making fonts scaled in points */
13997 /* according to the TrueType spec incoherently sized in practice. */
13998 /* */
13999 /* DETAILED USAGE: */
14000 /* */
14001 /* Scale: */
14002 /* Select how high you want the font to be, in points or pixels. */
14003 /* Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute */
14004 /* a scale factor SF that will be used by all other functions. */
14005 /* */
14006 /* Baseline: */
14007 /* You need to select a y-coordinate that is the baseline of where */
14008 /* your text will appear. Call GetFontBoundingBox to get the baseline-relative */
14009 /* bounding box for all characters. SF*-y0 will be the distance in pixels */
14010 /* that the worst-case character could extend above the baseline, so if */
14011 /* you want the top edge of characters to appear at the top of the */
14012 /* screen where y=0, then you would set the baseline to SF*-y0. */
14013 /* */
14014 /* Current point: */
14015 /* Set the current point where the first character will appear. The */
14016 /* first character could extend left of the current point; this is font */
14017 /* dependent. You can either choose a current point that is the leftmost */
14018 /* point and hope, or add some padding, or check the bounding box or */
14019 /* left-side-bearing of the first character to be displayed and set */
14020 /* the current point based on that. */
14021 /* */
14022 /* Displaying a character: */
14023 /* Compute the bounding box of the character. It will contain signed values */
14024 /* relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1, */
14025 /* then the character should be displayed in the rectangle from */
14026 /* <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1). */
14027 /* */
14028 /* Advancing for the next character: */
14029 /* Call GlyphHMetrics, and compute 'current_point += SF * advance'. */
14030 /* */
14031 /* */
14032 /* ADVANCED USAGE */
14033 /* */
14034 /* Quality: */
14035 /* */
14036 /* - Use the functions with Subpixel at the end to allow your characters */
14037 /* to have subpixel positioning. Since the font is anti-aliased, not */
14038 /* hinted, this is very import for quality. (This is not possible with */
14039 /* baked fonts.) */
14040 /* */
14041 /* - Kerning is now supported, and if you're supporting subpixel rendering */
14042 /* then kerning is worth using to give your text a polished look. */
14043 /* */
14044 /* Performance: */
14045 /* */
14046 /* - Convert Unicode codepoints to glyph indexes and operate on the glyphs; */
14047 /* if you don't do this, stb_truetype is forced to do the conversion on */
14048 /* every call. */
14049 /* */
14050 /* - There are a lot of memory allocations. We should modify it to take */
14051 /* a temp buffer and allocate from the temp buffer (without freeing), */
14052 /* should help performance a lot. */
14053 /* */
14054 /* NOTES */
14055 /* */
14056 /* The system uses the raw data found in the .ttf file without changing it */
14057 /* and without building auxiliary data structures. This is a bit inefficient */
14058 /* on little-endian systems (the data is big-endian), but assuming you're */
14059 /* caching the bitmaps or glyph shapes this shouldn't be a big deal. */
14060 /* */
14061 /* It appears to be very hard to programmatically determine what font a */
14062 /* given file is in a general way. I provide an API for this, but I don't */
14063 /* recommend it. */
14064 /* */
14065 /* */
14066 /* PERFORMANCE MEASUREMENTS FOR 1.06: */
14067 /* */
14068 /* 32-bit 64-bit */
14069 /* Previous release: 8.83 s 7.68 s */
14070 /* Pool allocations: 7.72 s 6.34 s */
14071 /* Inline sort : 6.54 s 5.65 s */
14072 /* New rasterizer : 5.63 s 5.00 s */
14073 
14074 /* //////////////////////////////////////////////////////////////////////////// */
14075 /* //////////////////////////////////////////////////////////////////////////// */
14076 /* // */
14077 /* // SAMPLE PROGRAMS */
14078 /* // */
14079 /* */
14080 /* Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless. */
14081 /* See "tests/truetype_demo_win32.c" for a complete version. */
14082 #if 0
14083 #define STB_TRUETYPE_IMPLEMENTATION /* force following include to generate implementation */
14084 #include "stb_truetype.h"
14085 
14086 unsigned char ttf_buffer[1<<20];
14087 unsigned char temp_bitmap[512*512];
14088 
14089 stbtt_bakedchar cdata[96]; /* ASCII 32..126 is 95 glyphs */
14090 GLuint ftex;
14091 
14092 void my_stbtt_initfont(void)
14093 {
14094  fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
14095  stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); /* no guarantee this fits! */
14096  /* can free ttf_buffer at this point */
14097  glGenTextures(1, &ftex);
14098  glBindTexture(GL_TEXTURE_2D, ftex);
14099  glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
14100  /* can free temp_bitmap at this point */
14101  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
14102 }
14103 
14104 void my_stbtt_print(float x, float y, char *text)
14105 {
14106  /* assume orthographic projection with units = screen pixels, origin at top left */
14107  glEnable(GL_BLEND);
14108  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14109  glEnable(GL_TEXTURE_2D);
14110  glBindTexture(GL_TEXTURE_2D, ftex);
14111  glBegin(GL_QUADS);
14112  while (*text) {
14113  if (*text >= 32 && *text < 128) {
14114  stbtt_aligned_quad q;
14115  stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);/* 1=opengl & d3d10+,0=d3d9 */
14116  glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
14117  glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
14118  glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
14119  glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
14120  }
14121  ++text;
14122  }
14123  glEnd();
14124 }
14125 #endif
14126 /* */
14127 /* */
14128 /* //////////////////////////////////////////////////////////////////////////// */
14129 /* */
14130 /* Complete program (this compiles): get a single bitmap, print as ASCII art */
14131 /* */
14132 #if 0
14133 #include <stdio.h>
14134 #define STB_TRUETYPE_IMPLEMENTATION /* force following include to generate implementation */
14135 #include "stb_truetype.h"
14136 
14137 char ttf_buffer[1<<25];
14138 
14139 int main(int argc, char **argv)
14140 {
14141  stbtt_fontinfo font;
14142  unsigned char *bitmap;
14143  int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
14144 
14145  fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
14146 
14147  stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
14148  bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
14149 
14150  for (j=0; j < h; ++j) {
14151  for (i=0; i < w; ++i)
14152  putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
14153  putchar('\n');
14154  }
14155  return 0;
14156 }
14157 #endif
14158 /* */
14159 /* Output: */
14160 /* */
14161 /* .ii. */
14162 /* @@@@@@. */
14163 /* V@Mio@@o */
14164 /* :i. V@V */
14165 /* :oM@@M */
14166 /* :@@@MM@M */
14167 /* @@o o@M */
14168 /* :@@. M@M */
14169 /* @@@o@@@@ */
14170 /* :M@@V:@@. */
14171 /* */
14172 /* //////////////////////////////////////////////////////////////////////////// */
14173 /* */
14174 /* Complete program: print "Hello World!" banner, with bugs */
14175 /* */
14176 #if 0
14177 char buffer[24<<20];
14178 unsigned char screen[20][79];
14179 
14180 int main(int arg, char **argv)
14181 {
14182  stbtt_fontinfo font;
14183  int i,j,ascent,baseline,ch=0;
14184  float scale, xpos=2; /* leave a little padding in case the character extends left */
14185  char *text = "Heljo World!"; /* intentionally misspelled to show 'lj' brokenness */
14186 
14187  fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
14188  stbtt_InitFont(&font, buffer, 0);
14189 
14190  scale = stbtt_ScaleForPixelHeight(&font, 15);
14191  stbtt_GetFontVMetrics(&font, &ascent,0,0);
14192  baseline = (int) (ascent*scale);
14193 
14194  while (text[ch]) {
14195  int advance,lsb,x0,y0,x1,y1;
14196  float x_shift = xpos - (float) floor(xpos);
14197  stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
14198  stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
14199  stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
14200  /* note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong */
14201  /* because this API is really for baking character bitmaps into textures. if you want to render */
14202  /* a sequence of characters, you really need to render each bitmap to a temp buffer, then */
14203  /* "alpha blend" that into the working buffer */
14204  xpos += (advance * scale);
14205  if (text[ch+1])
14206  xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
14207  ++ch;
14208  }
14209 
14210  for (j=0; j < 20; ++j) {
14211  for (i=0; i < 78; ++i)
14212  putchar(" .:ioVM@"[screen[j][i]>>5]);
14213  putchar('\n');
14214  }
14215 
14216  return 0;
14217 }
14218 #endif
14219 
14220 
14221 /* //////////////////////////////////////////////////////////////////////////// */
14222 /* //////////////////////////////////////////////////////////////////////////// */
14223 /* // */
14224 /* // INTEGRATION WITH YOUR CODEBASE */
14225 /* // */
14226 /* // The following sections allow you to supply alternate definitions */
14227 /* // of C library functions used by stb_truetype, e.g. if you don't */
14228 /* // link with the C runtime library. */
14229 
14230 #ifdef STB_TRUETYPE_IMPLEMENTATION
14231  /* #define your own (u)stbtt_int8/16/32 before including to override this */
14232  #ifndef stbtt_uint8
14233  typedef unsigned char stbtt_uint8;
14234  typedef signed char stbtt_int8;
14235  typedef unsigned short stbtt_uint16;
14236  typedef signed short stbtt_int16;
14237  typedef unsigned int stbtt_uint32;
14238  typedef signed int stbtt_int32;
14239  #endif
14240 
14241  typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
14242  typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
14243 
14244  /* e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h */
14245  #ifndef STBTT_ifloor
14246  #include <math.h>
14247  #define STBTT_ifloor(x) ((int) floor(x))
14248  #define STBTT_iceil(x) ((int) ceil(x))
14249  #endif
14250 
14251  #ifndef STBTT_sqrt
14252  #include <math.h>
14253  #define STBTT_sqrt(x) sqrt(x)
14254  #define STBTT_pow(x,y) pow(x,y)
14255  #endif
14256 
14257  #ifndef STBTT_fmod
14258  #include <math.h>
14259  #define STBTT_fmod(x,y) fmod(x,y)
14260  #endif
14261 
14262  #ifndef STBTT_cos
14263  #include <math.h>
14264  #define STBTT_cos(x) cos(x)
14265  #define STBTT_acos(x) acos(x)
14266  #endif
14267 
14268  #ifndef STBTT_fabs
14269  #include <math.h>
14270  #define STBTT_fabs(x) fabs(x)
14271  #endif
14272 
14273  /* #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h */
14274  #ifndef STBTT_malloc
14275  #include <stdlib.h>
14276  #define STBTT_malloc(x,u) ((void)(u),malloc(x))
14277  #define STBTT_free(x,u) ((void)(u),free(x))
14278  #endif
14279 
14280  #ifndef STBTT_assert
14281  #include <assert.h>
14282  #define STBTT_assert(x) assert(x)
14283  #endif
14284 
14285  #ifndef STBTT_strlen
14286  #include <string.h>
14287  #define STBTT_strlen(x) strlen(x)
14288  #endif
14289 
14290  #ifndef STBTT_memcpy
14291  #include <string.h>
14292  #define STBTT_memcpy memcpy
14293  #define STBTT_memset memset
14294  #endif
14295 #endif
14296 
14297 /* ///////////////////////////////////////////////////////////////////////////// */
14298 /* ///////////////////////////////////////////////////////////////////////////// */
14299 /* // */
14300 /* // INTERFACE */
14301 /* // */
14302 /* // */
14303 
14304 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
14305 #define __STB_INCLUDE_STB_TRUETYPE_H__
14306 
14307 #ifdef STBTT_STATIC
14308 #define STBTT_DEF static
14309 #else
14310 #define STBTT_DEF extern
14311 #endif
14312 
14313 #ifdef __cplusplus
14314 extern "C" {
14315 #endif
14316 
14317 /* private structure */
14318 typedef struct
14319 {
14320  unsigned char *data;
14321  int cursor;
14322  int size;
14323 } stbtt__buf;
14324 
14325 /* //////////////////////////////////////////////////////////////////////////// */
14326 /* */
14327 /* TEXTURE BAKING API */
14328 /* */
14329 /* If you use this API, you only have to call two functions ever. */
14330 /* */
14331 
14332 typedef struct
14333 {
14334  unsigned short x0,y0,x1,y1; /* coordinates of bbox in bitmap */
14335  float xoff,yoff,xadvance;
14336 } stbtt_bakedchar;
14337 
14338 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, /* font location (use offset=0 for plain .ttf) */
14339  float pixel_height, /* height of font in pixels */
14340  unsigned char *pixels, int pw, int ph, /* bitmap to be filled in */
14341  int first_char, int num_chars, /* characters to bake */
14342  stbtt_bakedchar *chardata); /* you allocate this, it's num_chars long */
14343 /* if return is positive, the first unused row of the bitmap */
14344 /* if return is negative, returns the negative of the number of characters that fit */
14345 /* if return is 0, no characters fit and no rows were used */
14346 /* This uses a very crappy packing. */
14347 
14348 typedef struct
14349 {
14350  float x0,y0,s0,t0; /* top-left */
14351  float x1,y1,s1,t1; /* bottom-right */
14352 } stbtt_aligned_quad;
14353 
14354 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, /* same data as above */
14355  int char_index, /* character to display */
14356  float *xpos, float *ypos, /* pointers to current position in screen pixel space */
14357  stbtt_aligned_quad *q, /* output: quad to draw */
14358  int opengl_fillrule); /* true if opengl fill rule; false if DX9 or earlier */
14359 /* Call GetBakedQuad with char_index = 'character - first_char', and it */
14360 /* creates the quad you need to draw and advances the current position. */
14361 /* */
14362 /* The coordinate system used assumes y increases downwards. */
14363 /* */
14364 /* Characters will extend both above and below the current position; */
14365 /* see discussion of "BASELINE" above. */
14366 /* */
14367 /* It's inefficient; you might want to c&p it and optimize it. */
14368 
14369 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
14370 /* Query the font vertical metrics without having to create a font first. */
14371 
14372 
14373 /* //////////////////////////////////////////////////////////////////////////// */
14374 /* */
14375 /* NEW TEXTURE BAKING API */
14376 /* */
14377 /* This provides options for packing multiple fonts into one atlas, not */
14378 /* perfectly but better than nothing. */
14379 
14380 typedef struct
14381 {
14382  unsigned short x0,y0,x1,y1; /* coordinates of bbox in bitmap */
14383  float xoff,yoff,xadvance;
14384  float xoff2,yoff2;
14385 } stbtt_packedchar;
14386 
14387 typedef struct stbtt_pack_context stbtt_pack_context;
14388 typedef struct stbtt_fontinfo stbtt_fontinfo;
14389 #ifndef STB_RECT_PACK_VERSION
14390 typedef struct stbrp_rect stbrp_rect;
14391 #endif
14392 
14393 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
14394 /* Initializes a packing context stored in the passed-in stbtt_pack_context. */
14395 /* Future calls using this context will pack characters into the bitmap passed */
14396 /* in here: a 1-channel bitmap that is width * height. stride_in_bytes is */
14397 /* the distance from one row to the next (or 0 to mean they are packed tightly */
14398 /* together). "padding" is the amount of padding to leave between each */
14399 /* character (normally you want '1' for bitmaps you'll use as textures with */
14400 /* bilinear filtering). */
14401 /* */
14402 /* Returns 0 on failure, 1 on success. */
14403 
14404 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
14405 /* Cleans up the packing context and frees all memory. */
14406 
14407 #define STBTT_POINT_SIZE(x) (-(x))
14408 
14409 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
14410  int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
14411 /* Creates character bitmaps from the font_index'th font found in fontdata (use */
14412 /* font_index=0 if you don't know what that is). It creates num_chars_in_range */
14413 /* bitmaps for characters with unicode values starting at first_unicode_char_in_range */
14414 /* and increasing. Data for how to render them is stored in chardata_for_range; */
14415 /* pass these to stbtt_GetPackedQuad to get back renderable quads. */
14416 /* */
14417 /* font_size is the full height of the character from ascender to descender, */
14418 /* as computed by stbtt_ScaleForPixelHeight. To use a point size as computed */
14419 /* by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() */
14420 /* and pass that result as 'font_size': */
14421 /* ..., 20 , ... // font max minus min y is 20 pixels tall */
14422 /* ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall */
14423 
14424 typedef struct
14425 {
14426  float font_size;
14427  int first_unicode_codepoint_in_range; /* if non-zero, then the chars are continuous, and this is the first codepoint */
14428  int *array_of_unicode_codepoints; /* if non-zero, then this is an array of unicode codepoints */
14429  int num_chars;
14430  stbtt_packedchar *chardata_for_range; /* output */
14431  unsigned char h_oversample, v_oversample; /* don't set these, they're used internally */
14432 } stbtt_pack_range;
14433 
14434 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
14435 /* Creates character bitmaps from multiple ranges of characters stored in */
14436 /* ranges. This will usually create a better-packed bitmap than multiple */
14437 /* calls to stbtt_PackFontRange. Note that you can call this multiple */
14438 /* times within a single PackBegin/PackEnd. */
14439 
14440 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
14441 /* Oversampling a font increases the quality by allowing higher-quality subpixel */
14442 /* positioning, and is especially valuable at smaller text sizes. */
14443 /* */
14444 /* This function sets the amount of oversampling for all following calls to */
14445 /* stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given */
14446 /* pack context. The default (no oversampling) is achieved by h_oversample=1 */
14447 /* and v_oversample=1. The total number of pixels required is */
14448 /* h_oversample*v_oversample larger than the default; for example, 2x2 */
14449 /* oversampling requires 4x the storage of 1x1. For best results, render */
14450 /* oversampled textures with bilinear filtering. Look at the readme in */
14451 /* stb/tests/oversample for information about oversampled fonts */
14452 /* */
14453 /* To use with PackFontRangesGather etc., you must set it before calls */
14454 /* call to PackFontRangesGatherRects. */
14455 
14456 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
14457 /* If skip != 0, this tells stb_truetype to skip any codepoints for which */
14458 /* there is no corresponding glyph. If skip=0, which is the default, then */
14459 /* codepoints without a glyph recived the font's "missing character" glyph, */
14460 /* typically an empty box by convention. */
14461 
14462 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, /* same data as above */
14463  int char_index, /* character to display */
14464  float *xpos, float *ypos, /* pointers to current position in screen pixel space */
14465  stbtt_aligned_quad *q, /* output: quad to draw */
14466  int align_to_integer);
14467 
14468 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
14469 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
14470 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
14471 /* Calling these functions in sequence is roughly equivalent to calling */
14472 /* stbtt_PackFontRanges(). If you more control over the packing of multiple */
14473 /* fonts, or if you want to pack custom data into a font texture, take a look */
14474 /* at the source to of stbtt_PackFontRanges() and create a custom version */
14475 /* using these functions, e.g. call GatherRects multiple times, */
14476 /* building up a single array of rects, then call PackRects once, */
14477 /* then call RenderIntoRects repeatedly. This may result in a */
14478 /* better packing than calling PackFontRanges multiple times */
14479 /* (or it may not). */
14480 
14481 /* this is an opaque structure that you shouldn't mess with which holds */
14482 /* all the context needed from PackBegin to PackEnd. */
14483 struct stbtt_pack_context {
14484  void *user_allocator_context;
14485  void *pack_info;
14486  int width;
14487  int height;
14488  int stride_in_bytes;
14489  int padding;
14490  int skip_missing;
14491  unsigned int h_oversample, v_oversample;
14492  unsigned char *pixels;
14493  void *nodes;
14494 };
14495 
14496 /* //////////////////////////////////////////////////////////////////////////// */
14497 /* */
14498 /* FONT LOADING */
14499 /* */
14500 /* */
14501 
14502 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
14503 /* This function will determine the number of fonts in a font file. TrueType */
14504 /* collection (.ttc) files may contain multiple fonts, while TrueType font */
14505 /* (.ttf) files only contain one font. The number of fonts can be used for */
14506 /* indexing with the previous function where the index is between zero and one */
14507 /* less than the total fonts. If an error occurs, -1 is returned. */
14508 
14509 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
14510 /* Each .ttf/.ttc file may have more than one font. Each font has a sequential */
14511 /* index number starting from 0. Call this function to get the font offset for */
14512 /* a given index; it returns -1 if the index is out of range. A regular .ttf */
14513 /* file will only define one font and it always be at offset 0, so it will */
14514 /* return '0' for index 0, and -1 for all other indices. */
14515 
14516 /* The following structure is defined publicly so you can declare one on */
14517 /* the stack or as a global or etc, but you should treat it as opaque. */
14518 struct stbtt_fontinfo
14519 {
14520  void * userdata;
14521  unsigned char * data; /* pointer to .ttf file */
14522  int fontstart; /* offset of start of font */
14523 
14524  int numGlyphs; /* number of glyphs, needed for range checking */
14525 
14526  int loca,head,glyf,hhea,hmtx,kern,gpos,svg; /* table locations as offset from start of .ttf */
14527  int index_map; /* a cmap mapping for our chosen character encoding */
14528  int indexToLocFormat; /* format needed to map from glyph index to glyph */
14529 
14530  stbtt__buf cff; /* cff font data */
14531  stbtt__buf charstrings; /* the charstring index */
14532  stbtt__buf gsubrs; /* global charstring subroutines index */
14533  stbtt__buf subrs; /* private charstring subroutines index */
14534  stbtt__buf fontdicts; /* array of font dicts */
14535  stbtt__buf fdselect; /* map from glyph to fontdict */
14536 };
14537 
14538 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
14539 /* Given an offset into the file that defines a font, this function builds */
14540 /* the necessary cached info for the rest of the system. You must allocate */
14541 /* the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't */
14542 /* need to do anything special to free it, because the contents are pure */
14543 /* value data with no additional data structures. Returns 0 on failure. */
14544 
14545 
14546 /* //////////////////////////////////////////////////////////////////////////// */
14547 /* */
14548 /* CHARACTER TO GLYPH-INDEX CONVERSIOn */
14549 
14550 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
14551 /* If you're going to perform multiple operations on the same character */
14552 /* and you want a speed-up, call this function with the character you're */
14553 /* going to process, then use glyph-based functions instead of the */
14554 /* codepoint-based functions. */
14555 /* Returns 0 if the character codepoint is not defined in the font. */
14556 
14557 
14558 /* //////////////////////////////////////////////////////////////////////////// */
14559 /* */
14560 /* CHARACTER PROPERTIES */
14561 /* */
14562 
14563 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
14564 /* computes a scale factor to produce a font whose "height" is 'pixels' tall. */
14565 /* Height is measured as the distance from the highest ascender to the lowest */
14566 /* descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics */
14567 /* and computing: */
14568 /* scale = pixels / (ascent - descent) */
14569 /* so if you prefer to measure height by the ascent only, use a similar calculation. */
14570 
14571 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
14572 /* computes a scale factor to produce a font whose EM size is mapped to */
14573 /* 'pixels' tall. This is probably what traditional APIs compute, but */
14574 /* I'm not positive. */
14575 
14576 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
14577 /* ascent is the coordinate above the baseline the font extends; descent */
14578 /* is the coordinate below the baseline the font extends (i.e. it is typically negative) */
14579 /* lineGap is the spacing between one row's descent and the next row's ascent... */
14580 /* so you should advance the vertical position by "*ascent - *descent + *lineGap" */
14581 /* these are expressed in unscaled coordinates, so you must multiply by */
14582 /* the scale factor for a given size */
14583 
14584 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
14585 /* analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 */
14586 /* table (specific to MS/Windows TTF files). */
14587 /* */
14588 /* Returns 1 on success (table present), 0 on failure. */
14589 
14590 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
14591 /* the bounding box around all possible characters */
14592 
14593 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
14594 /* leftSideBearing is the offset from the current horizontal position to the left edge of the character */
14595 /* advanceWidth is the offset from the current horizontal position to the next horizontal position */
14596 /* these are expressed in unscaled coordinates */
14597 
14598 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
14599 /* an additional amount to add to the 'advance' value between ch1 and ch2 */
14600 
14601 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
14602 /* Gets the bounding box of the visible part of the glyph, in unscaled coordinates */
14603 
14604 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
14605 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
14606 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
14607 /* as above, but takes one or more glyph indices for greater efficiency */
14608 
14609 typedef struct stbtt_kerningentry
14610 {
14611  int glyph1; /* use stbtt_FindGlyphIndex */
14612  int glyph2;
14613  int advance;
14614 } stbtt_kerningentry;
14615 
14616 STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
14617 STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
14618 /* Retrieves a complete list of all of the kerning pairs provided by the font */
14619 /* stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. */
14620 /* The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) */
14621 
14622 /* //////////////////////////////////////////////////////////////////////////// */
14623 /* */
14624 /* GLYPH SHAPES (you probably don't need these, but they have to go before */
14625 /* the bitmaps for C declaration-order reasons) */
14626 /* */
14627 
14628 #ifndef STBTT_vmove /* you can predefine these to use different values (but why?) */
14629  enum {
14630  STBTT_vmove=1,
14631  STBTT_vline,
14632  STBTT_vcurve,
14633  STBTT_vcubic
14634  };
14635 #endif
14636 
14637 #ifndef stbtt_vertex /* you can predefine this to use different values */
14638  /* (we share this with other code at RAD) */
14639  #define stbtt_vertex_type short /* can't use stbtt_int16 because that's not visible in the header file */
14640  typedef struct
14641  {
14642  stbtt_vertex_type x,y,cx,cy,cx1,cy1;
14643  unsigned char type,padding;
14644  } stbtt_vertex;
14645 #endif
14646 
14647 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
14648 /* returns non-zero if nothing is drawn for this glyph */
14649 
14650 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
14651 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
14652 /* returns # of vertices and fills *vertices with the pointer to them */
14653 /* these are expressed in "unscaled" coordinates */
14654 /* */
14655 /* The shape is a series of contours. Each one starts with */
14656 /* a STBTT_moveto, then consists of a series of mixed */
14657 /* STBTT_lineto and STBTT_curveto segments. A lineto */
14658 /* draws a line from previous endpoint to its x,y; a curveto */
14659 /* draws a quadratic bezier from previous endpoint to */
14660 /* its x,y, using cx,cy as the bezier control point. */
14661 
14662 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
14663 /* frees the data allocated above */
14664 
14665 STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
14666 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
14667 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
14668 /* fills svg with the character's SVG data. */
14669 /* returns data size or 0 if SVG not found. */
14670 
14671 /* //////////////////////////////////////////////////////////////////////////// */
14672 /* */
14673 /* BITMAP RENDERING */
14674 /* */
14675 
14676 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
14677 /* frees the bitmap allocated below */
14678 
14679 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
14680 /* allocates a large-enough single-channel 8bpp bitmap and renders the */
14681 /* specified character/glyph at the specified scale into it, with */
14682 /* antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). */
14683 /* *width & *height are filled out with the width & height of the bitmap, */
14684 /* which is stored left-to-right, top-to-bottom. */
14685 /* */
14686 /* xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap */
14687 
14688 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
14689 /* the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel */
14690 /* shift for the character */
14691 
14692 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
14693 /* the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap */
14694 /* in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap */
14695 /* is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the */
14696 /* width and height and positioning info for it first. */
14697 
14698 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
14699 /* same as stbtt_MakeCodepointBitmap, but you can specify a subpixel */
14700 /* shift for the character */
14701 
14702 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
14703 /* same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering */
14704 /* is performed (see stbtt_PackSetOversampling) */
14705 
14706 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
14707 /* get the bbox of the bitmap centered around the glyph origin; so the */
14708 /* bitmap width is ix1-ix0, height is iy1-iy0, and location to place */
14709 /* the bitmap top left is (leftSideBearing*scale,iy0). */
14710 /* (Note that the bitmap uses y-increases-down, but the shape uses */
14711 /* y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) */
14712 
14713 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
14714 /* same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel */
14715 /* shift for the character */
14716 
14717 /* the following functions are equivalent to the above functions, but operate */
14718 /* on glyph indices instead of Unicode codepoints (for efficiency) */
14719 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
14720 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
14721 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
14722 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
14723 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
14724 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
14725 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
14726 
14727 
14728 /* @TODO: don't expose this structure */
14729 typedef struct
14730 {
14731  int w,h,stride;
14732  unsigned char *pixels;
14733 } stbtt__bitmap;
14734 
14735 /* rasterize a shape with quadratic beziers into a bitmap */
14736 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, /* 1-channel bitmap to draw into */
14737  float flatness_in_pixels, /* allowable error of curve in pixels */
14738  stbtt_vertex *vertices, /* array of vertices defining shape */
14739  int num_verts, /* number of vertices in above array */
14740  float scale_x, float scale_y, /* scale applied to input vertices */
14741  float shift_x, float shift_y, /* translation applied to input vertices */
14742  int x_off, int y_off, /* another translation applied to input */
14743  int invert, /* if non-zero, vertically flip shape */
14744  void *userdata); /* context for to STBTT_MALLOC */
14745 
14746 /* //////////////////////////////////////////////////////////////////////////// */
14747 /* */
14748 /* Signed Distance Function (or Field) rendering */
14749 
14750 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
14751 /* frees the SDF bitmap allocated below */
14752 
14753 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
14754 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
14755 /* These functions compute a discretized SDF field for a single character, suitable for storing */
14756 /* in a single-channel texture, sampling with bilinear filtering, and testing against */
14757 /* larger than some threshold to produce scalable fonts. */
14758 /* info -- the font */
14759 /* scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap */
14760 /* glyph/codepoint -- the character to generate the SDF for */
14761 /* padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), */
14762 /* which allows effects like bit outlines */
14763 /* onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) */
14764 /* pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) */
14765 /* if positive, > onedge_value is inside; if negative, < onedge_value is inside */
14766 /* width,height -- output height & width of the SDF bitmap (including padding) */
14767 /* xoff,yoff -- output origin of the character */
14768 /* return value -- a 2D array of bytes 0..255, width*height in size */
14769 /* */
14770 /* pixel_dist_scale & onedge_value are a scale & bias that allows you to make */
14771 /* optimal use of the limited 0..255 for your application, trading off precision */
14772 /* and special effects. SDF values outside the range 0..255 are clamped to 0..255. */
14773 /* */
14774 /* Example: */
14775 /* scale = stbtt_ScaleForPixelHeight(22) */
14776 /* padding = 5 */
14777 /* onedge_value = 180 */
14778 /* pixel_dist_scale = 180/5.0 = 36.0 */
14779 /* */
14780 /* This will create an SDF bitmap in which the character is about 22 pixels */
14781 /* high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled */
14782 /* shape, sample the SDF at each pixel and fill the pixel if the SDF value */
14783 /* is greater than or equal to 180/255. (You'll actually want to antialias, */
14784 /* which is beyond the scope of this example.) Additionally, you can compute */
14785 /* offset outlines (e.g. to stroke the character border inside & outside, */
14786 /* or only outside). For example, to fill outside the character up to 3 SDF */
14787 /* pixels, you would compare against (180-36.0*3)/255 = 72/255. The above */
14788 /* choice of variables maps a range from 5 pixels outside the shape to */
14789 /* 2 pixels inside the shape to 0..255; this is intended primarily for apply */
14790 /* outside effects only (the interior range is needed to allow proper */
14791 /* antialiasing of the font at *smaller* sizes) */
14792 /* */
14793 /* The function computes the SDF analytically at each SDF pixel, not by e.g. */
14794 /* building a higher-res bitmap and approximating it. In theory the quality */
14795 /* should be as high as possible for an SDF of this size & representation, but */
14796 /* unclear if this is true in practice (perhaps building a higher-res bitmap */
14797 /* and computing from that can allow drop-out prevention). */
14798 /* */
14799 /* The algorithm has not been optimized at all, so expect it to be slow */
14800 /* if computing lots of characters or very large sizes. */
14801 
14802 
14803 
14804 /* //////////////////////////////////////////////////////////////////////////// */
14805 /* */
14806 /* Finding the right font... */
14807 /* */
14808 /* You should really just solve this offline, keep your own tables */
14809 /* of what font is what, and don't try to get it out of the .ttf file. */
14810 /* That's because getting it out of the .ttf file is really hard, because */
14811 /* the names in the file can appear in many possible encodings, in many */
14812 /* possible languages, and e.g. if you need a case-insensitive comparison, */
14813 /* the details of that depend on the encoding & language in a complex way */
14814 /* (actually underspecified in truetype, but also gigantic). */
14815 /* */
14816 /* But you can use the provided functions in two possible ways: */
14817 /* stbtt_FindMatchingFont() will use *case-sensitive* comparisons on */
14818 /* unicode-encoded names to try to find the font you want; */
14819 /* you can run this before calling stbtt_InitFont() */
14820 /* */
14821 /* stbtt_GetFontNameString() lets you get any of the various strings */
14822 /* from the file yourself and do your own comparisons on them. */
14823 /* You have to have called stbtt_InitFont() first. */
14824 
14825 
14826 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
14827 /* returns the offset (not index) of the font that matches, or -1 if none */
14828 /* if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". */
14829 /* if you use any other flag, use a font name like "Arial"; this checks */
14830 /* the 'macStyle' header field; i don't know if fonts set this consistently */
14831 #define STBTT_MACSTYLE_DONTCARE 0
14832 #define STBTT_MACSTYLE_BOLD 1
14833 #define STBTT_MACSTYLE_ITALIC 2
14834 #define STBTT_MACSTYLE_UNDERSCORE 4
14835 #define STBTT_MACSTYLE_NONE 8 /* <= not same as 0, this makes us check the bitfield is 0 */
14836 
14837 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
14838 /* returns 1/0 whether the first string interpreted as utf8 is identical to */
14839 /* the second string interpreted as big-endian utf16... useful for strings from next func */
14840 
14841 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
14842 /* returns the string (which may be big-endian double byte, e.g. for unicode) */
14843 /* and puts the length in bytes in *length. */
14844 /* */
14845 /* some of the values for the IDs are below; for more see the truetype spec: */
14846 /* http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html */
14847 /* http://www.microsoft.com/typography/otspec/name.htm */
14848 
14849 enum { /* platformID */
14850  STBTT_PLATFORM_ID_UNICODE =0,
14851  STBTT_PLATFORM_ID_MAC =1,
14852  STBTT_PLATFORM_ID_ISO =2,
14853  STBTT_PLATFORM_ID_MICROSOFT =3
14854 };
14855 
14856 enum { /* encodingID for STBTT_PLATFORM_ID_UNICODE */
14857  STBTT_UNICODE_EID_UNICODE_1_0 =0,
14858  STBTT_UNICODE_EID_UNICODE_1_1 =1,
14859  STBTT_UNICODE_EID_ISO_10646 =2,
14860  STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
14861  STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
14862 };
14863 
14864 enum { /* encodingID for STBTT_PLATFORM_ID_MICROSOFT */
14865  STBTT_MS_EID_SYMBOL =0,
14866  STBTT_MS_EID_UNICODE_BMP =1,
14867  STBTT_MS_EID_SHIFTJIS =2,
14868  STBTT_MS_EID_UNICODE_FULL =10
14869 };
14870 
14871 enum { /* encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes */
14872  STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
14873  STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
14874  STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
14875  STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
14876 };
14877 
14878 enum { /* languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... */
14879  /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
14880  STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
14881  STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
14882  STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
14883  STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
14884  STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
14885  STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
14886 };
14887 
14888 enum { /* languageID for STBTT_PLATFORM_ID_MAC */
14889  STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
14890  STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
14891  STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
14892  STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
14893  STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
14894  STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
14895  STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
14896 };
14897 
14898 #ifdef __cplusplus
14899 }
14900 #endif
14901 
14902 #endif /* __STB_INCLUDE_STB_TRUETYPE_H__ */
14903 
14904 /* ///////////////////////////////////////////////////////////////////////////// */
14905 /* ///////////////////////////////////////////////////////////////////////////// */
14906 /* // */
14907 /* // IMPLEMENTATION */
14908 /* // */
14909 /* // */
14910 
14911 #ifdef STB_TRUETYPE_IMPLEMENTATION
14912 
14913 #ifndef STBTT_MAX_OVERSAMPLE
14914 #define STBTT_MAX_OVERSAMPLE 8
14915 #endif
14916 
14917 #if STBTT_MAX_OVERSAMPLE > 255
14918 #error "STBTT_MAX_OVERSAMPLE cannot be > 255"
14919 #endif
14920 
14921 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
14922 
14923 #ifndef STBTT_RASTERIZER_VERSION
14924 #define STBTT_RASTERIZER_VERSION 2
14925 #endif
14926 
14927 #ifdef _MSC_VER
14928 #define STBTT__NOTUSED(v) (void)(v)
14929 #else
14930 #define STBTT__NOTUSED(v) (void)sizeof(v)
14931 #endif
14932 
14933 /* //////////////////////////////////////////////////////////////////////// */
14934 /* */
14935 /* stbtt__buf helpers to parse data from file */
14936 /* */
14937 
14938 static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
14939 {
14940  if (b->cursor >= b->size)
14941  return 0;
14942  return b->data[b->cursor++];
14943 }
14944 
14945 static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
14946 {
14947  if (b->cursor >= b->size)
14948  return 0;
14949  return b->data[b->cursor];
14950 }
14951 
14952 static void stbtt__buf_seek(stbtt__buf *b, int o)
14953 {
14954  STBTT_assert(!(o > b->size || o < 0));
14955  b->cursor = (o > b->size || o < 0) ? b->size : o;
14956 }
14957 
14958 static void stbtt__buf_skip(stbtt__buf *b, int o)
14959 {
14960  stbtt__buf_seek(b, b->cursor + o);
14961 }
14962 
14963 static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
14964 {
14965  stbtt_uint32 v = 0;
14966  int i;
14967  STBTT_assert(n >= 1 && n <= 4);
14968  for (i = 0; i < n; i++)
14969  v = (v << 8) | stbtt__buf_get8(b);
14970  return v;
14971 }
14972 
14973 static stbtt__buf stbtt__new_buf(const void *p, size_t size)
14974 {
14975  stbtt__buf r;
14976  STBTT_assert(size < 0x40000000);
14977  r.data = (stbtt_uint8*) p;
14978  r.size = (int) size;
14979  r.cursor = 0;
14980  return r;
14981 }
14982 
14983 #define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
14984 #define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
14985 
14986 static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
14987 {
14988  stbtt__buf r = stbtt__new_buf(NULL, 0);
14989  if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
14990  r.data = b->data + o;
14991  r.size = s;
14992  return r;
14993 }
14994 
14995 static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
14996 {
14997  int count, start, offsize;
14998  start = b->cursor;
14999  count = stbtt__buf_get16(b);
15000  if (count) {
15001  offsize = stbtt__buf_get8(b);
15002  STBTT_assert(offsize >= 1 && offsize <= 4);
15003  stbtt__buf_skip(b, offsize * count);
15004  stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
15005  }
15006  return stbtt__buf_range(b, start, b->cursor - start);
15007 }
15008 
15009 static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
15010 {
15011  int b0 = stbtt__buf_get8(b);
15012  if (b0 >= 32 && b0 <= 246) return b0 - 139;
15013  else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
15014  else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
15015  else if (b0 == 28) return stbtt__buf_get16(b);
15016  else if (b0 == 29) return stbtt__buf_get32(b);
15017  STBTT_assert(0);
15018  return 0;
15019 }
15020 
15021 static void stbtt__cff_skip_operand(stbtt__buf *b) {
15022  int v, b0 = stbtt__buf_peek8(b);
15023  STBTT_assert(b0 >= 28);
15024  if (b0 == 30) {
15025  stbtt__buf_skip(b, 1);
15026  while (b->cursor < b->size) {
15027  v = stbtt__buf_get8(b);
15028  if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
15029  break;
15030  }
15031  } else {
15032  stbtt__cff_int(b);
15033  }
15034 }
15035 
15036 static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
15037 {
15038  stbtt__buf_seek(b, 0);
15039  while (b->cursor < b->size) {
15040  int start = b->cursor, end, op;
15041  while (stbtt__buf_peek8(b) >= 28)
15042  stbtt__cff_skip_operand(b);
15043  end = b->cursor;
15044  op = stbtt__buf_get8(b);
15045  if (op == 12) op = stbtt__buf_get8(b) | 0x100;
15046  if (op == key) return stbtt__buf_range(b, start, end-start);
15047  }
15048  return stbtt__buf_range(b, 0, 0);
15049 }
15050 
15051 static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
15052 {
15053  int i;
15054  stbtt__buf operands = stbtt__dict_get(b, key);
15055  for (i = 0; i < outcount && operands.cursor < operands.size; i++)
15056  out[i] = stbtt__cff_int(&operands);
15057 }
15058 
15059 static int stbtt__cff_index_count(stbtt__buf *b)
15060 {
15061  stbtt__buf_seek(b, 0);
15062  return stbtt__buf_get16(b);
15063 }
15064 
15065 static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
15066 {
15067  int count, offsize, start, end;
15068  stbtt__buf_seek(&b, 0);
15069  count = stbtt__buf_get16(&b);
15070  offsize = stbtt__buf_get8(&b);
15071  STBTT_assert(i >= 0 && i < count);
15072  STBTT_assert(offsize >= 1 && offsize <= 4);
15073  stbtt__buf_skip(&b, i*offsize);
15074  start = stbtt__buf_get(&b, offsize);
15075  end = stbtt__buf_get(&b, offsize);
15076  return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
15077 }
15078 
15079 /* //////////////////////////////////////////////////////////////////////// */
15080 /* */
15081 /* accessors to parse data from file */
15082 /* */
15083 
15084 /* on platforms that don't allow misaligned reads, if we want to allow */
15085 /* truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE */
15086 
15087 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
15088 #define ttCHAR(p) (* (stbtt_int8 *) (p))
15089 #define ttFixed(p) ttLONG(p)
15090 
15091 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
15092 static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
15093 static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
15094 static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
15095 
15096 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
15097 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
15098 
15099 static int stbtt__isfont(stbtt_uint8 *font)
15100 {
15101  /* check the version number */
15102  if (stbtt_tag4(font, '1',0,0,0)) return 1; /* TrueType 1 */
15103  if (stbtt_tag(font, "typ1")) return 1; /* TrueType with type 1 font -- we don't support this! */
15104  if (stbtt_tag(font, "OTTO")) return 1; /* OpenType with CFF */
15105  if (stbtt_tag4(font, 0,1,0,0)) return 1; /* OpenType 1.0 */
15106  if (stbtt_tag(font, "true")) return 1; /* Apple specification for TrueType fonts */
15107  return 0;
15108 }
15109 
15110 /* @OPTIMIZE: binary search */
15111 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
15112 {
15113  stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
15114  stbtt_uint32 tabledir = fontstart + 12;
15115  stbtt_int32 i;
15116  for (i=0; i < num_tables; ++i) {
15117  stbtt_uint32 loc = tabledir + 16*i;
15118  if (stbtt_tag(data+loc+0, tag))
15119  return ttULONG(data+loc+8);
15120  }
15121  return 0;
15122 }
15123 
15124 static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
15125 {
15126  /* if it's just a font, there's only one valid index */
15127  if (stbtt__isfont(font_collection))
15128  return index == 0 ? 0 : -1;
15129 
15130  /* check if it's a TTC */
15131  if (stbtt_tag(font_collection, "ttcf")) {
15132  /* version 1? */
15133  if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
15134  stbtt_int32 n = ttLONG(font_collection+8);
15135  if (index >= n)
15136  return -1;
15137  return ttULONG(font_collection+12+index*4);
15138  }
15139  }
15140  return -1;
15141 }
15142 
15143 static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
15144 {
15145  /* if it's just a font, there's only one valid font */
15146  if (stbtt__isfont(font_collection))
15147  return 1;
15148 
15149  /* check if it's a TTC */
15150  if (stbtt_tag(font_collection, "ttcf")) {
15151  /* version 1? */
15152  if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
15153  return ttLONG(font_collection+8);
15154  }
15155  }
15156  return 0;
15157 }
15158 
15159 static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
15160 {
15161  stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
15162  stbtt__buf pdict;
15163  stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
15164  if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
15165  pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
15166  stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
15167  if (!subrsoff) return stbtt__new_buf(NULL, 0);
15168  stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
15169  return stbtt__cff_get_index(&cff);
15170 }
15171 
15172 /* since most people won't use this, find this table the first time it's needed */
15173 static int stbtt__get_svg(stbtt_fontinfo *info)
15174 {
15175  stbtt_uint32 t;
15176  if (info->svg < 0) {
15177  t = stbtt__find_table(info->data, info->fontstart, "SVG ");
15178  if (t) {
15179  stbtt_uint32 offset = ttULONG(info->data + t + 2);
15180  info->svg = t + offset;
15181  } else {
15182  info->svg = 0;
15183  }
15184  }
15185  return info->svg;
15186 }
15187 
15188 static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
15189 {
15190  stbtt_uint32 cmap, t;
15191  stbtt_int32 i,numTables;
15192 
15193  info->data = data;
15194  info->fontstart = fontstart;
15195  info->cff = stbtt__new_buf(NULL, 0);
15196 
15197  cmap = stbtt__find_table(data, fontstart, "cmap"); /* required */
15198  info->loca = stbtt__find_table(data, fontstart, "loca"); /* required */
15199  info->head = stbtt__find_table(data, fontstart, "head"); /* required */
15200  info->glyf = stbtt__find_table(data, fontstart, "glyf"); /* required */
15201  info->hhea = stbtt__find_table(data, fontstart, "hhea"); /* required */
15202  info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); /* required */
15203  info->kern = stbtt__find_table(data, fontstart, "kern"); /* not required */
15204  info->gpos = stbtt__find_table(data, fontstart, "GPOS"); /* not required */
15205 
15206  if (!cmap || !info->head || !info->hhea || !info->hmtx)
15207  return 0;
15208  if (info->glyf) {
15209  /* required for truetype */
15210  if (!info->loca) return 0;
15211  } else {
15212  /* initialization for CFF / Type2 fonts (OTF) */
15213  stbtt__buf b, topdict, topdictidx;
15214  stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
15215  stbtt_uint32 cff;
15216 
15217  cff = stbtt__find_table(data, fontstart, "CFF ");
15218  if (!cff) return 0;
15219 
15220  info->fontdicts = stbtt__new_buf(NULL, 0);
15221  info->fdselect = stbtt__new_buf(NULL, 0);
15222 
15223  /* @TODO this should use size from table (not 512MB) */
15224  info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
15225  b = info->cff;
15226 
15227  /* read the header */
15228  stbtt__buf_skip(&b, 2);
15229  stbtt__buf_seek(&b, stbtt__buf_get8(&b)); /* hdrsize */
15230 
15231  /* @TODO the name INDEX could list multiple fonts, */
15232  /* but we just use the first one. */
15233  stbtt__cff_get_index(&b); /* name INDEX */
15234  topdictidx = stbtt__cff_get_index(&b);
15235  topdict = stbtt__cff_index_get(topdictidx, 0);
15236  stbtt__cff_get_index(&b); /* string INDEX */
15237  info->gsubrs = stbtt__cff_get_index(&b);
15238 
15239  stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
15240  stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
15241  stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
15242  stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
15243  info->subrs = stbtt__get_subrs(b, topdict);
15244 
15245  /* we only support Type 2 charstrings */
15246  if (cstype != 2) return 0;
15247  if (charstrings == 0) return 0;
15248 
15249  if (fdarrayoff) {
15250  /* looks like a CID font */
15251  if (!fdselectoff) return 0;
15252  stbtt__buf_seek(&b, fdarrayoff);
15253  info->fontdicts = stbtt__cff_get_index(&b);
15254  info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
15255  }
15256 
15257  stbtt__buf_seek(&b, charstrings);
15258  info->charstrings = stbtt__cff_get_index(&b);
15259  }
15260 
15261  t = stbtt__find_table(data, fontstart, "maxp");
15262  if (t)
15263  info->numGlyphs = ttUSHORT(data+t+4);
15264  else
15265  info->numGlyphs = 0xffff;
15266 
15267  info->svg = -1;
15268 
15269  /* find a cmap encoding table we understand *now* to avoid searching */
15270  /* later. (todo: could make this installable) */
15271  /* the same regardless of glyph. */
15272  numTables = ttUSHORT(data + cmap + 2);
15273  info->index_map = 0;
15274  for (i=0; i < numTables; ++i) {
15275  stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
15276  /* find an encoding we understand: */
15277  switch(ttUSHORT(data+encoding_record)) {
15278  case STBTT_PLATFORM_ID_MICROSOFT:
15279  switch (ttUSHORT(data+encoding_record+2)) {
15280  case STBTT_MS_EID_UNICODE_BMP:
15281  case STBTT_MS_EID_UNICODE_FULL:
15282  /* MS/Unicode */
15283  info->index_map = cmap + ttULONG(data+encoding_record+4);
15284  break;
15285  }
15286  break;
15287  case STBTT_PLATFORM_ID_UNICODE:
15288  /* Mac/iOS has these */
15289  /* all the encodingIDs are unicode, so we don't bother to check it */
15290  info->index_map = cmap + ttULONG(data+encoding_record+4);
15291  break;
15292  }
15293  }
15294  if (info->index_map == 0)
15295  return 0;
15296 
15297  info->indexToLocFormat = ttUSHORT(data+info->head + 50);
15298  return 1;
15299 }
15300 
15301 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
15302 {
15303  stbtt_uint8 *data = info->data;
15304  stbtt_uint32 index_map = info->index_map;
15305 
15306  stbtt_uint16 format = ttUSHORT(data + index_map + 0);
15307  if (format == 0) { /* apple byte encoding */
15308  stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
15309  if (unicode_codepoint < bytes-6)
15310  return ttBYTE(data + index_map + 6 + unicode_codepoint);
15311  return 0;
15312  } else if (format == 6) {
15313  stbtt_uint32 first = ttUSHORT(data + index_map + 6);
15314  stbtt_uint32 count = ttUSHORT(data + index_map + 8);
15315  if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
15316  return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
15317  return 0;
15318  } else if (format == 2) {
15319  STBTT_assert(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
15320  return 0;
15321  } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
15322  stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
15323  stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
15324  stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
15325  stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
15326 
15327  /* do a binary search of the segments */
15328  stbtt_uint32 endCount = index_map + 14;
15329  stbtt_uint32 search = endCount;
15330 
15331  if (unicode_codepoint > 0xffff)
15332  return 0;
15333 
15334  /* they lie from endCount .. endCount + segCount */
15335  /* but searchRange is the nearest power of two, so... */
15336  if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
15337  search += rangeShift*2;
15338 
15339  /* now decrement to bias correctly to find smallest */
15340  search -= 2;
15341  while (entrySelector) {
15342  stbtt_uint16 end;
15343  searchRange >>= 1;
15344  end = ttUSHORT(data + search + searchRange*2);
15345  if (unicode_codepoint > end)
15346  search += searchRange*2;
15347  --entrySelector;
15348  }
15349  search += 2;
15350 
15351  {
15352  stbtt_uint16 offset, start, last;
15353  stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
15354 
15355  start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
15356  last = ttUSHORT(data + endCount + 2*item);
15357  if (unicode_codepoint < start || unicode_codepoint > last)
15358  return 0;
15359 
15360  offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
15361  if (offset == 0)
15362  return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
15363 
15364  return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
15365  }
15366  } else if (format == 12 || format == 13) {
15367  stbtt_uint32 ngroups = ttULONG(data+index_map+12);
15368  stbtt_int32 low,high;
15369  low = 0; high = (stbtt_int32)ngroups;
15370  /* Binary search the right group. */
15371  while (low < high) {
15372  stbtt_int32 mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
15373  stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
15374  stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
15375  if ((stbtt_uint32) unicode_codepoint < start_char)
15376  high = mid;
15377  else if ((stbtt_uint32) unicode_codepoint > end_char)
15378  low = mid+1;
15379  else {
15380  stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
15381  if (format == 12)
15382  return start_glyph + unicode_codepoint-start_char;
15383  else /* format == 13 */
15384  return start_glyph;
15385  }
15386  }
15387  return 0; /* not found */
15388  }
15389  /* @TODO */
15390  STBTT_assert(0);
15391  return 0;
15392 }
15393 
15394 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
15395 {
15396  return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
15397 }
15398 
15399 static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
15400 {
15401  v->type = type;
15402  v->x = (stbtt_int16) x;
15403  v->y = (stbtt_int16) y;
15404  v->cx = (stbtt_int16) cx;
15405  v->cy = (stbtt_int16) cy;
15406 }
15407 
15408 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
15409 {
15410  int g1,g2;
15411 
15412  STBTT_assert(!info->cff.size);
15413 
15414  if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
15415  if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */
15416 
15417  if (info->indexToLocFormat == 0) {
15418  g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
15419  g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
15420  } else {
15421  g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
15422  g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
15423  }
15424 
15425  return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
15426 }
15427 
15428 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
15429 
15430 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
15431 {
15432  if (info->cff.size) {
15433  stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
15434  } else {
15435  int g = stbtt__GetGlyfOffset(info, glyph_index);
15436  if (g < 0) return 0;
15437 
15438  if (x0) *x0 = ttSHORT(info->data + g + 2);
15439  if (y0) *y0 = ttSHORT(info->data + g + 4);
15440  if (x1) *x1 = ttSHORT(info->data + g + 6);
15441  if (y1) *y1 = ttSHORT(info->data + g + 8);
15442  }
15443  return 1;
15444 }
15445 
15446 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
15447 {
15448  return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
15449 }
15450 
15451 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
15452 {
15453  stbtt_int16 numberOfContours;
15454  int g;
15455  if (info->cff.size)
15456  return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
15457  g = stbtt__GetGlyfOffset(info, glyph_index);
15458  if (g < 0) return 1;
15459  numberOfContours = ttSHORT(info->data + g);
15460  return numberOfContours == 0;
15461 }
15462 
15463 static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
15464  stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
15465 {
15466  if (start_off) {
15467  if (was_off)
15468  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
15469  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
15470  } else {
15471  if (was_off)
15472  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
15473  else
15474  stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
15475  }
15476  return num_vertices;
15477 }
15478 
15479 static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
15480 {
15481  stbtt_int16 numberOfContours;
15482  stbtt_uint8 *endPtsOfContours;
15483  stbtt_uint8 *data = info->data;
15484  stbtt_vertex *vertices=0;
15485  int num_vertices=0;
15486  int g = stbtt__GetGlyfOffset(info, glyph_index);
15487 
15488  *pvertices = NULL;
15489 
15490  if (g < 0) return 0;
15491 
15492  numberOfContours = ttSHORT(data + g);
15493 
15494  if (numberOfContours > 0) {
15495  stbtt_uint8 flags=0,flagcount;
15496  stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
15497  stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
15498  stbtt_uint8 *points;
15499  endPtsOfContours = (data + g + 10);
15500  ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
15501  points = data + g + 10 + numberOfContours * 2 + 2 + ins;
15502 
15503  n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
15504 
15505  m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */
15506  vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
15507  if (vertices == 0)
15508  return 0;
15509 
15510  next_move = 0;
15511  flagcount=0;
15512 
15513  /* in first pass, we load uninterpreted data into the allocated array */
15514  /* above, shifted to the end of the array so we won't overwrite it when */
15515  /* we create our final data starting from the front */
15516 
15517  off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
15518 
15519  /* first load flags */
15520 
15521  for (i=0; i < n; ++i) {
15522  if (flagcount == 0) {
15523  flags = *points++;
15524  if (flags & 8)
15525  flagcount = *points++;
15526  } else
15527  --flagcount;
15528  vertices[off+i].type = flags;
15529  }
15530 
15531  /* now load x coordinates */
15532  x=0;
15533  for (i=0; i < n; ++i) {
15534  flags = vertices[off+i].type;
15535  if (flags & 2) {
15536  stbtt_int16 dx = *points++;
15537  x += (flags & 16) ? dx : -dx; /* ??? */
15538  } else {
15539  if (!(flags & 16)) {
15540  x = x + (stbtt_int16) (points[0]*256 + points[1]);
15541  points += 2;
15542  }
15543  }
15544  vertices[off+i].x = (stbtt_int16) x;
15545  }
15546 
15547  /* now load y coordinates */
15548  y=0;
15549  for (i=0; i < n; ++i) {
15550  flags = vertices[off+i].type;
15551  if (flags & 4) {
15552  stbtt_int16 dy = *points++;
15553  y += (flags & 32) ? dy : -dy; /* ??? */
15554  } else {
15555  if (!(flags & 32)) {
15556  y = y + (stbtt_int16) (points[0]*256 + points[1]);
15557  points += 2;
15558  }
15559  }
15560  vertices[off+i].y = (stbtt_int16) y;
15561  }
15562 
15563  /* now convert them to our format */
15564  num_vertices=0;
15565  sx = sy = cx = cy = scx = scy = 0;
15566  for (i=0; i < n; ++i) {
15567  flags = vertices[off+i].type;
15568  x = (stbtt_int16) vertices[off+i].x;
15569  y = (stbtt_int16) vertices[off+i].y;
15570 
15571  if (next_move == i) {
15572  if (i != 0)
15573  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
15574 
15575  /* now start the new one */
15576  start_off = !(flags & 1);
15577  if (start_off) {
15578  /* if we start off with an off-curve point, then when we need to find a point on the curve */
15579  /* where we can start, and we need to save some state for when we wraparound. */
15580  scx = x;
15581  scy = y;
15582  if (!(vertices[off+i+1].type & 1)) {
15583  /* next point is also a curve point, so interpolate an on-point curve */
15584  sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
15585  sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
15586  } else {
15587  /* otherwise just use the next point as our start point */
15588  sx = (stbtt_int32) vertices[off+i+1].x;
15589  sy = (stbtt_int32) vertices[off+i+1].y;
15590  ++i; /* we're using point i+1 as the starting point, so skip it */
15591  }
15592  } else {
15593  sx = x;
15594  sy = y;
15595  }
15596  stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
15597  was_off = 0;
15598  next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
15599  ++j;
15600  } else {
15601  if (!(flags & 1)) { /* if it's a curve */
15602  if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
15603  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
15604  cx = x;
15605  cy = y;
15606  was_off = 1;
15607  } else {
15608  if (was_off)
15609  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
15610  else
15611  stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
15612  was_off = 0;
15613  }
15614  }
15615  }
15616  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
15617  } else if (numberOfContours < 0) {
15618  /* Compound shapes. */
15619  int more = 1;
15620  stbtt_uint8 *comp = data + g + 10;
15621  num_vertices = 0;
15622  vertices = 0;
15623  while (more) {
15624  stbtt_uint16 flags, gidx;
15625  int comp_num_verts = 0, i;
15626  stbtt_vertex *comp_verts = 0, *tmp = 0;
15627  float mtx[6] = {1,0,0,1,0,0}, m, n;
15628 
15629  flags = ttSHORT(comp); comp+=2;
15630  gidx = ttSHORT(comp); comp+=2;
15631 
15632  if (flags & 2) { /* XY values */
15633  if (flags & 1) { /* shorts */
15634  mtx[4] = ttSHORT(comp); comp+=2;
15635  mtx[5] = ttSHORT(comp); comp+=2;
15636  } else {
15637  mtx[4] = ttCHAR(comp); comp+=1;
15638  mtx[5] = ttCHAR(comp); comp+=1;
15639  }
15640  }
15641  else {
15642  /* @TODO handle matching point */
15643  STBTT_assert(0);
15644  }
15645  if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
15646  mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
15647  mtx[1] = mtx[2] = 0;
15648  } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
15649  mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
15650  mtx[1] = mtx[2] = 0;
15651  mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
15652  } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
15653  mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
15654  mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
15655  mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
15656  mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
15657  }
15658 
15659  /* Find transformation scales. */
15660  m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
15661  n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
15662 
15663  /* Get indexed glyph. */
15664  comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
15665  if (comp_num_verts > 0) {
15666  /* Transform vertices. */
15667  for (i = 0; i < comp_num_verts; ++i) {
15668  stbtt_vertex* v = &comp_verts[i];
15669  stbtt_vertex_type x,y;
15670  x=v->x; y=v->y;
15671  v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
15672  v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
15673  x=v->cx; y=v->cy;
15674  v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
15675  v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
15676  }
15677  /* Append vertices. */
15678  tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
15679  if (!tmp) {
15680  if (vertices) STBTT_free(vertices, info->userdata);
15681  if (comp_verts) STBTT_free(comp_verts, info->userdata);
15682  return 0;
15683  }
15684  if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
15685  STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
15686  if (vertices) STBTT_free(vertices, info->userdata);
15687  vertices = tmp;
15688  STBTT_free(comp_verts, info->userdata);
15689  num_vertices += comp_num_verts;
15690  }
15691  /* More components ? */
15692  more = flags & (1<<5);
15693  }
15694  } else {
15695  /* numberOfCounters == 0, do nothing */
15696  }
15697 
15698  *pvertices = vertices;
15699  return num_vertices;
15700 }
15701 
15702 typedef struct
15703 {
15704  int bounds;
15705  int started;
15706  float first_x, first_y;
15707  float x, y;
15708  stbtt_int32 min_x, max_x, min_y, max_y;
15709 
15710  stbtt_vertex *pvertices;
15711  int num_vertices;
15712 } stbtt__csctx;
15713 
15714 #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
15715 
15716 static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
15717 {
15718  if (x > c->max_x || !c->started) c->max_x = x;
15719  if (y > c->max_y || !c->started) c->max_y = y;
15720  if (x < c->min_x || !c->started) c->min_x = x;
15721  if (y < c->min_y || !c->started) c->min_y = y;
15722  c->started = 1;
15723 }
15724 
15725 static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
15726 {
15727  if (c->bounds) {
15728  stbtt__track_vertex(c, x, y);
15729  if (type == STBTT_vcubic) {
15730  stbtt__track_vertex(c, cx, cy);
15731  stbtt__track_vertex(c, cx1, cy1);
15732  }
15733  } else {
15734  stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
15735  c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
15736  c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
15737  }
15738  c->num_vertices++;
15739 }
15740 
15741 static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
15742 {
15743  if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
15744  stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
15745 }
15746 
15747 static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
15748 {
15749  stbtt__csctx_close_shape(ctx);
15750  ctx->first_x = ctx->x = ctx->x + dx;
15751  ctx->first_y = ctx->y = ctx->y + dy;
15752  stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
15753 }
15754 
15755 static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
15756 {
15757  ctx->x += dx;
15758  ctx->y += dy;
15759  stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
15760 }
15761 
15762 static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
15763 {
15764  float cx1 = ctx->x + dx1;
15765  float cy1 = ctx->y + dy1;
15766  float cx2 = cx1 + dx2;
15767  float cy2 = cy1 + dy2;
15768  ctx->x = cx2 + dx3;
15769  ctx->y = cy2 + dy3;
15770  stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
15771 }
15772 
15773 static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
15774 {
15775  int count = stbtt__cff_index_count(&idx);
15776  int bias = 107;
15777  if (count >= 33900)
15778  bias = 32768;
15779  else if (count >= 1240)
15780  bias = 1131;
15781  n += bias;
15782  if (n < 0 || n >= count)
15783  return stbtt__new_buf(NULL, 0);
15784  return stbtt__cff_index_get(idx, n);
15785 }
15786 
15787 static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
15788 {
15789  stbtt__buf fdselect = info->fdselect;
15790  int nranges, start, end, v, fmt, fdselector = -1, i;
15791 
15792  stbtt__buf_seek(&fdselect, 0);
15793  fmt = stbtt__buf_get8(&fdselect);
15794  if (fmt == 0) {
15795  /* untested */
15796  stbtt__buf_skip(&fdselect, glyph_index);
15797  fdselector = stbtt__buf_get8(&fdselect);
15798  } else if (fmt == 3) {
15799  nranges = stbtt__buf_get16(&fdselect);
15800  start = stbtt__buf_get16(&fdselect);
15801  for (i = 0; i < nranges; i++) {
15802  v = stbtt__buf_get8(&fdselect);
15803  end = stbtt__buf_get16(&fdselect);
15804  if (glyph_index >= start && glyph_index < end) {
15805  fdselector = v;
15806  break;
15807  }
15808  start = end;
15809  }
15810  }
15811  if (fdselector == -1) stbtt__new_buf(NULL, 0);
15812  return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
15813 }
15814 
15815 static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
15816 {
15817  int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
15818  int has_subrs = 0, clear_stack;
15819  float s[48];
15820  stbtt__buf subr_stack[10], subrs = info->subrs, b;
15821  float f;
15822 
15823 #define STBTT__CSERR(s) (0)
15824 
15825  /* this currently ignores the initial width value, which isn't needed if we have hmtx */
15826  b = stbtt__cff_index_get(info->charstrings, glyph_index);
15827  while (b.cursor < b.size) {
15828  i = 0;
15829  clear_stack = 1;
15830  b0 = stbtt__buf_get8(&b);
15831  switch (b0) {
15832  /* @TODO implement hinting */
15833  case 0x13: /* hintmask */
15834  case 0x14: /* cntrmask */
15835  if (in_header)
15836  maskbits += (sp / 2); /* implicit "vstem" */
15837  in_header = 0;
15838  stbtt__buf_skip(&b, (maskbits + 7) / 8);
15839  break;
15840 
15841  case 0x01: /* hstem */
15842  case 0x03: /* vstem */
15843  case 0x12: /* hstemhm */
15844  case 0x17: /* vstemhm */
15845  maskbits += (sp / 2);
15846  break;
15847 
15848  case 0x15: /* rmoveto */
15849  in_header = 0;
15850  if (sp < 2) return STBTT__CSERR("rmoveto stack");
15851  stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
15852  break;
15853  case 0x04: /* vmoveto */
15854  in_header = 0;
15855  if (sp < 1) return STBTT__CSERR("vmoveto stack");
15856  stbtt__csctx_rmove_to(c, 0, s[sp-1]);
15857  break;
15858  case 0x16: /* hmoveto */
15859  in_header = 0;
15860  if (sp < 1) return STBTT__CSERR("hmoveto stack");
15861  stbtt__csctx_rmove_to(c, s[sp-1], 0);
15862  break;
15863 
15864  case 0x05: /* rlineto */
15865  if (sp < 2) return STBTT__CSERR("rlineto stack");
15866  for (; i + 1 < sp; i += 2)
15867  stbtt__csctx_rline_to(c, s[i], s[i+1]);
15868  break;
15869 
15870  /* hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical */
15871  /* starting from a different place. */
15872 
15873  case 0x07: /* vlineto */
15874  if (sp < 1) return STBTT__CSERR("vlineto stack");
15875  goto vlineto;
15876  case 0x06: /* hlineto */
15877  if (sp < 1) return STBTT__CSERR("hlineto stack");
15878  for (;;) {
15879  if (i >= sp) break;
15880  stbtt__csctx_rline_to(c, s[i], 0);
15881  i++;
15882  vlineto:
15883  if (i >= sp) break;
15884  stbtt__csctx_rline_to(c, 0, s[i]);
15885  i++;
15886  }
15887  break;
15888 
15889  case 0x1F: /* hvcurveto */
15890  if (sp < 4) return STBTT__CSERR("hvcurveto stack");
15891  goto hvcurveto;
15892  case 0x1E: /* vhcurveto */
15893  if (sp < 4) return STBTT__CSERR("vhcurveto stack");
15894  for (;;) {
15895  if (i + 3 >= sp) break;
15896  stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
15897  i += 4;
15898  hvcurveto:
15899  if (i + 3 >= sp) break;
15900  stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
15901  i += 4;
15902  }
15903  break;
15904 
15905  case 0x08: /* rrcurveto */
15906  if (sp < 6) return STBTT__CSERR("rcurveline stack");
15907  for (; i + 5 < sp; i += 6)
15908  stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
15909  break;
15910 
15911  case 0x18: /* rcurveline */
15912  if (sp < 8) return STBTT__CSERR("rcurveline stack");
15913  for (; i + 5 < sp - 2; i += 6)
15914  stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
15915  if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
15916  stbtt__csctx_rline_to(c, s[i], s[i+1]);
15917  break;
15918 
15919  case 0x19: /* rlinecurve */
15920  if (sp < 8) return STBTT__CSERR("rlinecurve stack");
15921  for (; i + 1 < sp - 6; i += 2)
15922  stbtt__csctx_rline_to(c, s[i], s[i+1]);
15923  if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
15924  stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
15925  break;
15926 
15927  case 0x1A: /* vvcurveto */
15928  case 0x1B: /* hhcurveto */
15929  if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
15930  f = 0.0;
15931  if (sp & 1) { f = s[i]; i++; }
15932  for (; i + 3 < sp; i += 4) {
15933  if (b0 == 0x1B)
15934  stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
15935  else
15936  stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
15937  f = 0.0;
15938  }
15939  break;
15940 
15941  case 0x0A: /* callsubr */
15942  if (!has_subrs) {
15943  if (info->fdselect.size)
15944  subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
15945  has_subrs = 1;
15946  }
15947  /* FALLTHROUGH */
15948  case 0x1D: /* callgsubr */
15949  if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
15950  v = (int) s[--sp];
15951  if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
15952  subr_stack[subr_stack_height++] = b;
15953  b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
15954  if (b.size == 0) return STBTT__CSERR("subr not found");
15955  b.cursor = 0;
15956  clear_stack = 0;
15957  break;
15958 
15959  case 0x0B: /* return */
15960  if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
15961  b = subr_stack[--subr_stack_height];
15962  clear_stack = 0;
15963  break;
15964 
15965  case 0x0E: /* endchar */
15966  stbtt__csctx_close_shape(c);
15967  return 1;
15968 
15969  case 0x0C: { /* two-byte escape */
15970  float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
15971  float dx, dy;
15972  int b1 = stbtt__buf_get8(&b);
15973  switch (b1) {
15974  /* @TODO These "flex" implementations ignore the flex-depth and resolution, */
15975  /* and always draw beziers. */
15976  case 0x22: /* hflex */
15977  if (sp < 7) return STBTT__CSERR("hflex stack");
15978  dx1 = s[0];
15979  dx2 = s[1];
15980  dy2 = s[2];
15981  dx3 = s[3];
15982  dx4 = s[4];
15983  dx5 = s[5];
15984  dx6 = s[6];
15985  stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
15986  stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
15987  break;
15988 
15989  case 0x23: /* flex */
15990  if (sp < 13) return STBTT__CSERR("flex stack");
15991  dx1 = s[0];
15992  dy1 = s[1];
15993  dx2 = s[2];
15994  dy2 = s[3];
15995  dx3 = s[4];
15996  dy3 = s[5];
15997  dx4 = s[6];
15998  dy4 = s[7];
15999  dx5 = s[8];
16000  dy5 = s[9];
16001  dx6 = s[10];
16002  dy6 = s[11];
16003  /* fd is s[12] */
16004  stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
16005  stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
16006  break;
16007 
16008  case 0x24: /* hflex1 */
16009  if (sp < 9) return STBTT__CSERR("hflex1 stack");
16010  dx1 = s[0];
16011  dy1 = s[1];
16012  dx2 = s[2];
16013  dy2 = s[3];
16014  dx3 = s[4];
16015  dx4 = s[5];
16016  dx5 = s[6];
16017  dy5 = s[7];
16018  dx6 = s[8];
16019  stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
16020  stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
16021  break;
16022 
16023  case 0x25: /* flex1 */
16024  if (sp < 11) return STBTT__CSERR("flex1 stack");
16025  dx1 = s[0];
16026  dy1 = s[1];
16027  dx2 = s[2];
16028  dy2 = s[3];
16029  dx3 = s[4];
16030  dy3 = s[5];
16031  dx4 = s[6];
16032  dy4 = s[7];
16033  dx5 = s[8];
16034  dy5 = s[9];
16035  dx6 = dy6 = s[10];
16036  dx = dx1+dx2+dx3+dx4+dx5;
16037  dy = dy1+dy2+dy3+dy4+dy5;
16038  if (STBTT_fabs(dx) > STBTT_fabs(dy))
16039  dy6 = -dy;
16040  else
16041  dx6 = -dx;
16042  stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
16043  stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
16044  break;
16045 
16046  default:
16047  return STBTT__CSERR("unimplemented");
16048  }
16049  } break;
16050 
16051  default:
16052  if (b0 != 255 && b0 != 28 && b0 < 32)
16053  return STBTT__CSERR("reserved operator");
16054 
16055  /* push immediate */
16056  if (b0 == 255) {
16057  f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
16058  } else {
16059  stbtt__buf_skip(&b, -1);
16060  f = (float)(stbtt_int16)stbtt__cff_int(&b);
16061  }
16062  if (sp >= 48) return STBTT__CSERR("push stack overflow");
16063  s[sp++] = f;
16064  clear_stack = 0;
16065  break;
16066  }
16067  if (clear_stack) sp = 0;
16068  }
16069  return STBTT__CSERR("no endchar");
16070 
16071 #undef STBTT__CSERR
16072 }
16073 
16074 static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
16075 {
16076  /* runs the charstring twice, once to count and once to output (to avoid realloc) */
16077  stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
16078  stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
16079  if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
16080  *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
16081  output_ctx.pvertices = *pvertices;
16082  if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
16083  STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
16084  return output_ctx.num_vertices;
16085  }
16086  }
16087  *pvertices = NULL;
16088  return 0;
16089 }
16090 
16091 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
16092 {
16093  stbtt__csctx c = STBTT__CSCTX_INIT(1);
16094  int r = stbtt__run_charstring(info, glyph_index, &c);
16095  if (x0) *x0 = r ? c.min_x : 0;
16096  if (y0) *y0 = r ? c.min_y : 0;
16097  if (x1) *x1 = r ? c.max_x : 0;
16098  if (y1) *y1 = r ? c.max_y : 0;
16099  return r ? c.num_vertices : 0;
16100 }
16101 
16102 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
16103 {
16104  if (!info->cff.size)
16105  return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
16106  else
16107  return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
16108 }
16109 
16110 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
16111 {
16112  stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
16113  if (glyph_index < numOfLongHorMetrics) {
16114  if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
16115  if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
16116  } else {
16117  if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
16118  if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
16119  }
16120 }
16121 
16122 STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
16123 {
16124  stbtt_uint8 *data = info->data + info->kern;
16125 
16126  /* we only look at the first table. it must be 'horizontal' and format 0. */
16127  if (!info->kern)
16128  return 0;
16129  if (ttUSHORT(data+2) < 1) /* number of tables, need at least 1 */
16130  return 0;
16131  if (ttUSHORT(data+8) != 1) /* horizontal flag must be set in format */
16132  return 0;
16133 
16134  return ttUSHORT(data+10);
16135 }
16136 
16137 STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
16138 {
16139  stbtt_uint8 *data = info->data + info->kern;
16140  int k, length;
16141 
16142  /* we only look at the first table. it must be 'horizontal' and format 0. */
16143  if (!info->kern)
16144  return 0;
16145  if (ttUSHORT(data+2) < 1) /* number of tables, need at least 1 */
16146  return 0;
16147  if (ttUSHORT(data+8) != 1) /* horizontal flag must be set in format */
16148  return 0;
16149 
16150  length = ttUSHORT(data+10);
16151  if (table_length < length)
16152  length = table_length;
16153 
16154  for (k = 0; k < length; k++)
16155  {
16156  table[k].glyph1 = ttUSHORT(data+18+(k*6));
16157  table[k].glyph2 = ttUSHORT(data+20+(k*6));
16158  table[k].advance = ttSHORT(data+22+(k*6));
16159  }
16160 
16161  return length;
16162 }
16163 
16164 static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
16165 {
16166  stbtt_uint8 *data = info->data + info->kern;
16167  stbtt_uint32 needle, straw;
16168  int l, r, m;
16169 
16170  /* we only look at the first table. it must be 'horizontal' and format 0. */
16171  if (!info->kern)
16172  return 0;
16173  if (ttUSHORT(data+2) < 1) /* number of tables, need at least 1 */
16174  return 0;
16175  if (ttUSHORT(data+8) != 1) /* horizontal flag must be set in format */
16176  return 0;
16177 
16178  l = 0;
16179  r = ttUSHORT(data+10) - 1;
16180  needle = glyph1 << 16 | glyph2;
16181  while (l <= r) {
16182  m = (l + r) >> 1;
16183  straw = ttULONG(data+18+(m*6)); /* note: unaligned read */
16184  if (needle < straw)
16185  r = m - 1;
16186  else if (needle > straw)
16187  l = m + 1;
16188  else
16189  return ttSHORT(data+22+(m*6));
16190  }
16191  return 0;
16192 }
16193 
16194 static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
16195 {
16196  stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
16197  switch (coverageFormat) {
16198  case 1: {
16199  stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
16200 
16201  /* Binary search. */
16202  stbtt_int32 l=0, r=glyphCount-1, m;
16203  int straw, needle=glyph;
16204  while (l <= r) {
16205  stbtt_uint8 *glyphArray = coverageTable + 4;
16206  stbtt_uint16 glyphID;
16207  m = (l + r) >> 1;
16208  glyphID = ttUSHORT(glyphArray + 2 * m);
16209  straw = glyphID;
16210  if (needle < straw)
16211  r = m - 1;
16212  else if (needle > straw)
16213  l = m + 1;
16214  else {
16215  return m;
16216  }
16217  }
16218  break;
16219  }
16220 
16221  case 2: {
16222  stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
16223  stbtt_uint8 *rangeArray = coverageTable + 4;
16224 
16225  /* Binary search. */
16226  stbtt_int32 l=0, r=rangeCount-1, m;
16227  int strawStart, strawEnd, needle=glyph;
16228  while (l <= r) {
16229  stbtt_uint8 *rangeRecord;
16230  m = (l + r) >> 1;
16231  rangeRecord = rangeArray + 6 * m;
16232  strawStart = ttUSHORT(rangeRecord);
16233  strawEnd = ttUSHORT(rangeRecord + 2);
16234  if (needle < strawStart)
16235  r = m - 1;
16236  else if (needle > strawEnd)
16237  l = m + 1;
16238  else {
16239  stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
16240  return startCoverageIndex + glyph - strawStart;
16241  }
16242  }
16243  break;
16244  }
16245 
16246  default: return -1; /* unsupported */
16247  }
16248 
16249  return -1;
16250 }
16251 
16252 static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
16253 {
16254  stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
16255  switch (classDefFormat)
16256  {
16257  case 1: {
16258  stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
16259  stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
16260  stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
16261 
16262  if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
16263  return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
16264  break;
16265  }
16266 
16267  case 2: {
16268  stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
16269  stbtt_uint8 *classRangeRecords = classDefTable + 4;
16270 
16271  /* Binary search. */
16272  stbtt_int32 l=0, r=classRangeCount-1, m;
16273  int strawStart, strawEnd, needle=glyph;
16274  while (l <= r) {
16275  stbtt_uint8 *classRangeRecord;
16276  m = (l + r) >> 1;
16277  classRangeRecord = classRangeRecords + 6 * m;
16278  strawStart = ttUSHORT(classRangeRecord);
16279  strawEnd = ttUSHORT(classRangeRecord + 2);
16280  if (needle < strawStart)
16281  r = m - 1;
16282  else if (needle > strawEnd)
16283  l = m + 1;
16284  else
16285  return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
16286  }
16287  break;
16288  }
16289 
16290  default:
16291  return -1; /* Unsupported definition type, return an error. */
16292  }
16293 
16294  /* "All glyphs not assigned to a class fall into class 0". (OpenType spec) */
16295  return 0;
16296 }
16297 
16298 /* Define to STBTT_assert(x) if you want to break on unimplemented formats. */
16299 #define STBTT_GPOS_TODO_assert(x)
16300 
16301 static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
16302 {
16303  stbtt_uint16 lookupListOffset;
16304  stbtt_uint8 *lookupList;
16305  stbtt_uint16 lookupCount;
16306  stbtt_uint8 *data;
16307  stbtt_int32 i, sti;
16308 
16309  if (!info->gpos) return 0;
16310 
16311  data = info->data + info->gpos;
16312 
16313  if (ttUSHORT(data+0) != 1) return 0; /* Major version 1 */
16314  if (ttUSHORT(data+2) != 0) return 0; /* Minor version 0 */
16315 
16316  lookupListOffset = ttUSHORT(data+8);
16317  lookupList = data + lookupListOffset;
16318  lookupCount = ttUSHORT(lookupList);
16319 
16320  for (i=0; i<lookupCount; ++i) {
16321  stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
16322  stbtt_uint8 *lookupTable = lookupList + lookupOffset;
16323 
16324  stbtt_uint16 lookupType = ttUSHORT(lookupTable);
16325  stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
16326  stbtt_uint8 *subTableOffsets = lookupTable + 6;
16327  if (lookupType != 2) /* Pair Adjustment Positioning Subtable */
16328  continue;
16329 
16330  for (sti=0; sti<subTableCount; sti++) {
16331  stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
16332  stbtt_uint8 *table = lookupTable + subtableOffset;
16333  stbtt_uint16 posFormat = ttUSHORT(table);
16334  stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
16335  stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
16336  if (coverageIndex == -1) continue;
16337 
16338  switch (posFormat) {
16339  case 1: {
16340  stbtt_int32 l, r, m;
16341  int straw, needle;
16342  stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
16343  stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
16344  if (valueFormat1 == 4 && valueFormat2 == 0) { /* Support more formats? */
16345  stbtt_int32 valueRecordPairSizeInBytes = 2;
16346  stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
16347  stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
16348  stbtt_uint8 *pairValueTable = table + pairPosOffset;
16349  stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
16350  stbtt_uint8 *pairValueArray = pairValueTable + 2;
16351 
16352  if (coverageIndex >= pairSetCount) return 0;
16353 
16354  needle=glyph2;
16355  r=pairValueCount-1;
16356  l=0;
16357 
16358  /* Binary search. */
16359  while (l <= r) {
16360  stbtt_uint16 secondGlyph;
16361  stbtt_uint8 *pairValue;
16362  m = (l + r) >> 1;
16363  pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
16364  secondGlyph = ttUSHORT(pairValue);
16365  straw = secondGlyph;
16366  if (needle < straw)
16367  r = m - 1;
16368  else if (needle > straw)
16369  l = m + 1;
16370  else {
16371  stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
16372  return xAdvance;
16373  }
16374  }
16375  } else
16376  return 0;
16377  break;
16378  }
16379 
16380  case 2: {
16381  stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
16382  stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
16383  if (valueFormat1 == 4 && valueFormat2 == 0) { /* Support more formats? */
16384  stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
16385  stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
16386  int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
16387  int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
16388 
16389  stbtt_uint16 class1Count = ttUSHORT(table + 12);
16390  stbtt_uint16 class2Count = ttUSHORT(table + 14);
16391  stbtt_uint8 *class1Records, *class2Records;
16392  stbtt_int16 xAdvance;
16393 
16394  if (glyph1class < 0 || glyph1class >= class1Count) return 0; /* malformed */
16395  if (glyph2class < 0 || glyph2class >= class2Count) return 0; /* malformed */
16396 
16397  class1Records = table + 16;
16398  class2Records = class1Records + 2 * (glyph1class * class2Count);
16399  xAdvance = ttSHORT(class2Records + 2 * glyph2class);
16400  return xAdvance;
16401  } else
16402  return 0;
16403  break;
16404  }
16405 
16406  default:
16407  return 0; /* Unsupported position format */
16408  }
16409  }
16410  }
16411 
16412  return 0;
16413 }
16414 
16415 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
16416 {
16417  int xAdvance = 0;
16418 
16419  if (info->gpos)
16420  xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
16421  else if (info->kern)
16422  xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
16423 
16424  return xAdvance;
16425 }
16426 
16427 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
16428 {
16429  if (!info->kern && !info->gpos) /* if no kerning table, don't waste time looking up both codepoint->glyphs */
16430  return 0;
16431  return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
16432 }
16433 
16434 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
16435 {
16436  stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
16437 }
16438 
16439 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
16440 {
16441  if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
16442  if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
16443  if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
16444 }
16445 
16446 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
16447 {
16448  int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
16449  if (!tab)
16450  return 0;
16451  if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
16452  if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
16453  if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
16454  return 1;
16455 }
16456 
16457 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
16458 {
16459  *x0 = ttSHORT(info->data + info->head + 36);
16460  *y0 = ttSHORT(info->data + info->head + 38);
16461  *x1 = ttSHORT(info->data + info->head + 40);
16462  *y1 = ttSHORT(info->data + info->head + 42);
16463 }
16464 
16465 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
16466 {
16467  int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
16468  return (float) height / fheight;
16469 }
16470 
16471 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
16472 {
16473  int unitsPerEm = ttUSHORT(info->data + info->head + 18);
16474  return pixels / unitsPerEm;
16475 }
16476 
16477 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
16478 {
16479  STBTT_free(v, info->userdata);
16480 }
16481 
16482 STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
16483 {
16484  int i;
16485  stbtt_uint8 *data = info->data;
16486  stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
16487 
16488  int numEntries = ttUSHORT(svg_doc_list);
16489  stbtt_uint8 *svg_docs = svg_doc_list + 2;
16490 
16491  for(i=0; i<numEntries; i++) {
16492  stbtt_uint8 *svg_doc = svg_docs + (12 * i);
16493  if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
16494  return svg_doc;
16495  }
16496  return 0;
16497 }
16498 
16499 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
16500 {
16501  stbtt_uint8 *data = info->data;
16502  stbtt_uint8 *svg_doc;
16503 
16504  if (info->svg == 0)
16505  return 0;
16506 
16507  svg_doc = stbtt_FindSVGDoc(info, gl);
16508  if (svg_doc != NULL) {
16509  *svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
16510  return ttULONG(svg_doc + 8);
16511  } else {
16512  return 0;
16513  }
16514 }
16515 
16516 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
16517 {
16518  return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
16519 }
16520 
16521 /* //////////////////////////////////////////////////////////////////////////// */
16522 /* */
16523 /* antialiasing software rasterizer */
16524 /* */
16525 
16526 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
16527 {
16528  int x0=0,y0=0,x1,y1; /* =0 suppresses compiler warning */
16529  if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
16530  /* e.g. space character */
16531  if (ix0) *ix0 = 0;
16532  if (iy0) *iy0 = 0;
16533  if (ix1) *ix1 = 0;
16534  if (iy1) *iy1 = 0;
16535  } else {
16536  /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
16537  if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
16538  if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
16539  if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
16540  if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
16541  }
16542 }
16543 
16544 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
16545 {
16546  stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
16547 }
16548 
16549 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
16550 {
16551  stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
16552 }
16553 
16554 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
16555 {
16556  stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
16557 }
16558 
16559 /* //////////////////////////////////////////////////////////////////////////// */
16560 /* */
16561 /* Rasterizer */
16562 
16563 typedef struct stbtt__hheap_chunk
16564 {
16565  struct stbtt__hheap_chunk *next;
16566 } stbtt__hheap_chunk;
16567 
16568 typedef struct stbtt__hheap
16569 {
16570  struct stbtt__hheap_chunk *head;
16571  void *first_free;
16572  int num_remaining_in_head_chunk;
16573 } stbtt__hheap;
16574 
16575 static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
16576 {
16577  if (hh->first_free) {
16578  void *p = hh->first_free;
16579  hh->first_free = * (void **) p;
16580  return p;
16581  } else {
16582  if (hh->num_remaining_in_head_chunk == 0) {
16583  int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
16584  stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
16585  if (c == NULL)
16586  return NULL;
16587  c->next = hh->head;
16588  hh->head = c;
16589  hh->num_remaining_in_head_chunk = count;
16590  }
16591  --hh->num_remaining_in_head_chunk;
16592  return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
16593  }
16594 }
16595 
16596 static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
16597 {
16598  *(void **) p = hh->first_free;
16599  hh->first_free = p;
16600 }
16601 
16602 static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
16603 {
16604  stbtt__hheap_chunk *c = hh->head;
16605  while (c) {
16606  stbtt__hheap_chunk *n = c->next;
16607  STBTT_free(c, userdata);
16608  c = n;
16609  }
16610 }
16611 
16612 typedef struct stbtt__edge {
16613  float x0,y0, x1,y1;
16614  int invert;
16615 } stbtt__edge;
16616 
16617 
16618 typedef struct stbtt__active_edge
16619 {
16620  struct stbtt__active_edge *next;
16621  #if STBTT_RASTERIZER_VERSION==1
16622  int x,dx;
16623  float ey;
16624  int direction;
16625  #elif STBTT_RASTERIZER_VERSION==2
16626  float fx,fdx,fdy;
16627  float direction;
16628  float sy;
16629  float ey;
16630  #else
16631  #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
16632  #endif
16633 } stbtt__active_edge;
16634 
16635 #if STBTT_RASTERIZER_VERSION == 1
16636 #define STBTT_FIXSHIFT 10
16637 #define STBTT_FIX (1 << STBTT_FIXSHIFT)
16638 #define STBTT_FIXMASK (STBTT_FIX-1)
16639 
16640 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
16641 {
16642  stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
16643  float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
16644  STBTT_assert(z != NULL);
16645  if (!z) return z;
16646 
16647  /* round dx down to avoid overshooting */
16648  if (dxdy < 0)
16649  z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
16650  else
16651  z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
16652 
16653  z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); /* use z->dx so when we offset later it's by the same amount */
16654  z->x -= off_x * STBTT_FIX;
16655 
16656  z->ey = e->y1;
16657  z->next = 0;
16658  z->direction = e->invert ? 1 : -1;
16659  return z;
16660 }
16661 #elif STBTT_RASTERIZER_VERSION == 2
16662 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
16663 {
16664  stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
16665  float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
16666  STBTT_assert(z != NULL);
16667  /* STBTT_assert(e->y0 <= start_point); */
16668  if (!z) return z;
16669  z->fdx = dxdy;
16670  z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
16671  z->fx = e->x0 + dxdy * (start_point - e->y0);
16672  z->fx -= off_x;
16673  z->direction = e->invert ? 1.0f : -1.0f;
16674  z->sy = e->y0;
16675  z->ey = e->y1;
16676  z->next = 0;
16677  return z;
16678 }
16679 #else
16680 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
16681 #endif
16682 
16683 #if STBTT_RASTERIZER_VERSION == 1
16684 /* note: this routine clips fills that extend off the edges... ideally this */
16685 /* wouldn't happen, but it could happen if the truetype glyph bounding boxes */
16686 /* are wrong, or if the user supplies a too-small bitmap */
16687 static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
16688 {
16689  /* non-zero winding fill */
16690  int x0=0, w=0;
16691 
16692  while (e) {
16693  if (w == 0) {
16694  /* if we're currently at zero, we need to record the edge start point */
16695  x0 = e->x; w += e->direction;
16696  } else {
16697  int x1 = e->x; w += e->direction;
16698  /* if we went to zero, we need to draw */
16699  if (w == 0) {
16700  int i = x0 >> STBTT_FIXSHIFT;
16701  int j = x1 >> STBTT_FIXSHIFT;
16702 
16703  if (i < len && j >= 0) {
16704  if (i == j) {
16705  /* x0,x1 are the same pixel, so compute combined coverage */
16706  scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
16707  } else {
16708  if (i >= 0) /* add antialiasing for x0 */
16709  scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
16710  else
16711  i = -1; /* clip */
16712 
16713  if (j < len) /* add antialiasing for x1 */
16714  scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
16715  else
16716  j = len; /* clip */
16717 
16718  for (++i; i < j; ++i) /* fill pixels between x0 and x1 */
16719  scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
16720  }
16721  }
16722  }
16723  }
16724 
16725  e = e->next;
16726  }
16727 }
16728 
16729 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
16730 {
16731  stbtt__hheap hh = { 0, 0, 0 };
16732  stbtt__active_edge *active = NULL;
16733  int y,j=0;
16734  int max_weight = (255 / vsubsample); /* weight per vertical scanline */
16735  int s; /* vertical subsample index */
16736  unsigned char scanline_data[512], *scanline;
16737 
16738  if (result->w > 512)
16739  scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
16740  else
16741  scanline = scanline_data;
16742 
16743  y = off_y * vsubsample;
16744  e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
16745 
16746  while (j < result->h) {
16747  STBTT_memset(scanline, 0, result->w);
16748  for (s=0; s < vsubsample; ++s) {
16749  /* find center of pixel for this scanline */
16750  float scan_y = y + 0.5f;
16751  stbtt__active_edge **step = &active;
16752 
16753  /* update all active edges; */
16754  /* remove all active edges that terminate before the center of this scanline */
16755  while (*step) {
16756  stbtt__active_edge * z = *step;
16757  if (z->ey <= scan_y) {
16758  *step = z->next; /* delete from list */
16759  STBTT_assert(z->direction);
16760  z->direction = 0;
16761  stbtt__hheap_free(&hh, z);
16762  } else {
16763  z->x += z->dx; /* advance to position for current scanline */
16764  step = &((*step)->next); /* advance through list */
16765  }
16766  }
16767 
16768  /* resort the list if needed */
16769  for(;;) {
16770  int changed=0;
16771  step = &active;
16772  while (*step && (*step)->next) {
16773  if ((*step)->x > (*step)->next->x) {
16774  stbtt__active_edge *t = *step;
16775  stbtt__active_edge *q = t->next;
16776 
16777  t->next = q->next;
16778  q->next = t;
16779  *step = q;
16780  changed = 1;
16781  }
16782  step = &(*step)->next;
16783  }
16784  if (!changed) break;
16785  }
16786 
16787  /* insert all edges that start before the center of this scanline -- omit ones that also end on this scanline */
16788  while (e->y0 <= scan_y) {
16789  if (e->y1 > scan_y) {
16790  stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
16791  if (z != NULL) {
16792  /* find insertion point */
16793  if (active == NULL)
16794  active = z;
16795  else if (z->x < active->x) {
16796  /* insert at front */
16797  z->next = active;
16798  active = z;
16799  } else {
16800  /* find thing to insert AFTER */
16801  stbtt__active_edge *p = active;
16802  while (p->next && p->next->x < z->x)
16803  p = p->next;
16804  /* at this point, p->next->x is NOT < z->x */
16805  z->next = p->next;
16806  p->next = z;
16807  }
16808  }
16809  }
16810  ++e;
16811  }
16812 
16813  /* now process all active edges in XOR fashion */
16814  if (active)
16815  stbtt__fill_active_edges(scanline, result->w, active, max_weight);
16816 
16817  ++y;
16818  }
16819  STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
16820  ++j;
16821  }
16822 
16823  stbtt__hheap_cleanup(&hh, userdata);
16824 
16825  if (scanline != scanline_data)
16826  STBTT_free(scanline, userdata);
16827 }
16828 
16829 #elif STBTT_RASTERIZER_VERSION == 2
16830 
16831 /* the edge passed in here does not cross the vertical line at x or the vertical line at x+1 */
16832 /* (i.e. it has already been clipped to those) */
16833 static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
16834 {
16835  if (y0 == y1) return;
16836  STBTT_assert(y0 < y1);
16837  STBTT_assert(e->sy <= e->ey);
16838  if (y0 > e->ey) return;
16839  if (y1 < e->sy) return;
16840  if (y0 < e->sy) {
16841  x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
16842  y0 = e->sy;
16843  }
16844  if (y1 > e->ey) {
16845  x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
16846  y1 = e->ey;
16847  }
16848 
16849  if (x0 == x)
16850  STBTT_assert(x1 <= x+1);
16851  else if (x0 == x+1)
16852  STBTT_assert(x1 >= x);
16853  else if (x0 <= x)
16854  STBTT_assert(x1 <= x);
16855  else if (x0 >= x+1)
16856  STBTT_assert(x1 >= x+1);
16857  else
16858  STBTT_assert(x1 >= x && x1 <= x+1);
16859 
16860  if (x0 <= x && x1 <= x)
16861  scanline[x] += e->direction * (y1-y0);
16862  else if (x0 >= x+1 && x1 >= x+1)
16863  ;
16864  else {
16865  STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
16866  scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); /* coverage = 1 - average x position */
16867  }
16868 }
16869 
16870 static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
16871 {
16872  STBTT_assert(top_width >= 0);
16873  STBTT_assert(bottom_width >= 0);
16874  return (top_width + bottom_width) / 2.0f * height;
16875 }
16876 
16877 static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
16878 {
16879  return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
16880 }
16881 
16882 static float stbtt__sized_triangle_area(float height, float width)
16883 {
16884  return height * width / 2;
16885 }
16886 
16887 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
16888 {
16889  float y_bottom = y_top+1;
16890 
16891  while (e) {
16892  /* brute force every pixel */
16893 
16894  /* compute intersection points with top & bottom */
16895  STBTT_assert(e->ey >= y_top);
16896 
16897  if (e->fdx == 0) {
16898  float x0 = e->fx;
16899  if (x0 < len) {
16900  if (x0 >= 0) {
16901  stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
16902  stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
16903  } else {
16904  stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
16905  }
16906  }
16907  } else {
16908  float x0 = e->fx;
16909  float dx = e->fdx;
16910  float xb = x0 + dx;
16911  float x_top, x_bottom;
16912  float sy0,sy1;
16913  float dy = e->fdy;
16914  STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
16915 
16916  /* compute endpoints of line segment clipped to this scanline (if the */
16917  /* line segment starts on this scanline. x0 is the intersection of the */
16918  /* line with y_top, but that may be off the line segment. */
16919  if (e->sy > y_top) {
16920  x_top = x0 + dx * (e->sy - y_top);
16921  sy0 = e->sy;
16922  } else {
16923  x_top = x0;
16924  sy0 = y_top;
16925  }
16926  if (e->ey < y_bottom) {
16927  x_bottom = x0 + dx * (e->ey - y_top);
16928  sy1 = e->ey;
16929  } else {
16930  x_bottom = xb;
16931  sy1 = y_bottom;
16932  }
16933 
16934  if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
16935  /* from here on, we don't have to range check x values */
16936 
16937  if ((int) x_top == (int) x_bottom) {
16938  float height;
16939  /* simple case, only spans one pixel */
16940  int x = (int) x_top;
16941  height = (sy1 - sy0) * e->direction;
16942  STBTT_assert(x >= 0 && x < len);
16943  scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
16944  scanline_fill[x] += height; /* everything right of this pixel is filled */
16945  } else {
16946  int x,x1,x2;
16947  float y_crossing, y_final, step, sign, area;
16948  /* covers 2+ pixels */
16949  if (x_top > x_bottom) {
16950  /* flip scanline vertically; signed area is the same */
16951  float t;
16952  sy0 = y_bottom - (sy0 - y_top);
16953  sy1 = y_bottom - (sy1 - y_top);
16954  t = sy0, sy0 = sy1, sy1 = t;
16955  t = x_bottom, x_bottom = x_top, x_top = t;
16956  dx = -dx;
16957  dy = -dy;
16958  t = x0, x0 = xb, xb = t;
16959  }
16960  STBTT_assert(dy >= 0);
16961  STBTT_assert(dx >= 0);
16962 
16963  x1 = (int) x_top;
16964  x2 = (int) x_bottom;
16965  /* compute intersection with y axis at x1+1 */
16966  y_crossing = y_top + dy * (x1+1 - x0);
16967 
16968  /* compute intersection with y axis at x2 */
16969  y_final = y_top + dy * (x2 - x0);
16970 
16971  /* x1 x_top x2 x_bottom */
16972  /* y_top +------|-----+------------+------------+--------|---+------------+ */
16973  /* | | | | | | */
16974  /* | | | | | | */
16975  /* sy0 | Txxxxx|............|............|............|............| */
16976  /* y_crossing | *xxxxx.......|............|............|............| */
16977  /* | | xxxxx..|............|............|............| */
16978  /* | | /- xx*xxxx........|............|............| */
16979  /* | | dy < | xxxxxx..|............|............| */
16980  /* y_final | | \- | xx*xxx.........|............| */
16981  /* sy1 | | | | xxxxxB...|............| */
16982  /* | | | | | | */
16983  /* | | | | | | */
16984  /* y_bottom +------------+------------+------------+------------+------------+ */
16985  /* */
16986  /* goal is to measure the area covered by '.' in each pixel */
16987 
16988  /* if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 */
16989  /* @TODO: maybe test against sy1 rather than y_bottom? */
16990  if (y_crossing > y_bottom)
16991  y_crossing = y_bottom;
16992 
16993  sign = e->direction;
16994 
16995  /* area of the rectangle covered from sy0..y_crossing */
16996  area = sign * (y_crossing-sy0);
16997 
16998  /* area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) */
16999  scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
17000 
17001  /* check if final y_crossing is blown up; no test case for this */
17002  if (y_final > y_bottom) {
17003  y_final = y_bottom;
17004  dy = (y_final - y_crossing ) / (x2 - (x1+1)); /* if denom=0, y_final = y_crossing, so y_final <= y_bottom */
17005  }
17006 
17007  /* in second pixel, area covered by line segment found in first pixel */
17008  /* is always a rectangle 1 wide * the height of that line segment; this */
17009  /* is exactly what the variable 'area' stores. it also gets a contribution */
17010  /* from the line segment within it. the THIRD pixel will get the first */
17011  /* pixel's rectangle contribution, the second pixel's rectangle contribution, */
17012  /* and its own contribution. the 'own contribution' is the same in every pixel except */
17013  /* the leftmost and rightmost, a trapezoid that slides down in each pixel. */
17014  /* the second pixel's contribution to the third pixel will be the */
17015  /* rectangle 1 wide times the height change in the second pixel, which is dy. */
17016 
17017  step = sign * dy * 1; /* dy is dy/dx, change in y for every 1 change in x, */
17018  /* which multiplied by 1-pixel-width is how much pixel area changes for each step in x */
17019  /* so the area advances by 'step' every time */
17020 
17021  for (x = x1+1; x < x2; ++x) {
17022  scanline[x] += area + step/2; /* area of trapezoid is 1*step/2 */
17023  area += step;
17024  }
17025  STBTT_assert(STBTT_fabs(area) <= 1.01f); /* accumulated error from area += step unless we round step down */
17026  STBTT_assert(sy1 > y_final-0.01f);
17027 
17028  /* area covered in the last pixel is the rectangle from all the pixels to the left, */
17029  /* plus the trapezoid filled by the line segment in this pixel all the way to the right edge */
17030  scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
17031 
17032  /* the rest of the line is filled based on the total height of the line segment in this pixel */
17033  scanline_fill[x2] += sign * (sy1-sy0);
17034  }
17035  } else {
17036  /* if edge goes outside of box we're drawing, we require */
17037  /* clipping logic. since this does not match the intended use */
17038  /* of this library, we use a different, very slow brute */
17039  /* force implementation */
17040  /* note though that this does happen some of the time because */
17041  /* x_top and x_bottom can be extrapolated at the top & bottom of */
17042  /* the shape and actually lie outside the bounding box */
17043  int x;
17044  for (x=0; x < len; ++x) {
17045  /* cases: */
17046  /* */
17047  /* there can be up to two intersections with the pixel. any intersection */
17048  /* with left or right edges can be handled by splitting into two (or three) */
17049  /* regions. intersections with top & bottom do not necessitate case-wise logic. */
17050  /* */
17051  /* the old way of doing this found the intersections with the left & right edges, */
17052  /* then used some simple logic to produce up to three segments in sorted order */
17053  /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
17054  /* across the x border, then the corresponding y position might not be distinct */
17055  /* from the other y segment, and it might ignored as an empty segment. to avoid */
17056  /* that, we need to explicitly produce segments based on x positions. */
17057 
17058  /* rename variables to clearly-defined pairs */
17059  float y0 = y_top;
17060  float x1 = (float) (x);
17061  float x2 = (float) (x+1);
17062  float x3 = xb;
17063  float y3 = y_bottom;
17064 
17065  /* x = e->x + e->dx * (y-y_top) */
17066  /* (y-y_top) = (x - e->x) / e->dx */
17067  /* y = (x - e->x) / e->dx + y_top */
17068  float y1 = (x - x0) / dx + y_top;
17069  float y2 = (x+1 - x0) / dx + y_top;
17070 
17071  if (x0 < x1 && x3 > x2) { /* three segments descending down-right */
17072  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
17073  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
17074  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
17075  } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */
17076  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
17077  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
17078  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
17079  } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */
17080  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
17081  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
17082  } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */
17083  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
17084  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
17085  } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */
17086  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
17087  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
17088  } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */
17089  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
17090  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
17091  } else { /* one segment */
17092  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
17093  }
17094  }
17095  }
17096  }
17097  e = e->next;
17098  }
17099 }
17100 
17101 /* directly AA rasterize edges w/o supersampling */
17102 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
17103 {
17104  stbtt__hheap hh = { 0, 0, 0 };
17105  stbtt__active_edge *active = NULL;
17106  int y,j=0, i;
17107  float scanline_data[129], *scanline, *scanline2;
17108 
17109  STBTT__NOTUSED(vsubsample);
17110 
17111  if (result->w > 64)
17112  scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
17113  else
17114  scanline = scanline_data;
17115 
17116  scanline2 = scanline + result->w;
17117 
17118  y = off_y;
17119  e[n].y0 = (float) (off_y + result->h) + 1;
17120 
17121  while (j < result->h) {
17122  /* find center of pixel for this scanline */
17123  float scan_y_top = y + 0.0f;
17124  float scan_y_bottom = y + 1.0f;
17125  stbtt__active_edge **step = &active;
17126 
17127  STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
17128  STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
17129 
17130  /* update all active edges; */
17131  /* remove all active edges that terminate before the top of this scanline */
17132  while (*step) {
17133  stbtt__active_edge * z = *step;
17134  if (z->ey <= scan_y_top) {
17135  *step = z->next; /* delete from list */
17136  STBTT_assert(z->direction);
17137  z->direction = 0;
17138  stbtt__hheap_free(&hh, z);
17139  } else {
17140  step = &((*step)->next); /* advance through list */
17141  }
17142  }
17143 
17144  /* insert all edges that start before the bottom of this scanline */
17145  while (e->y0 <= scan_y_bottom) {
17146  if (e->y0 != e->y1) {
17147  stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
17148  if (z != NULL) {
17149  if (j == 0 && off_y != 0) {
17150  if (z->ey < scan_y_top) {
17151  /* this can happen due to subpixel positioning and some kind of fp rounding error i think */
17152  z->ey = scan_y_top;
17153  }
17154  }
17155  STBTT_assert(z->ey >= scan_y_top); /* if we get really unlucky a tiny bit of an edge can be out of bounds */
17156  /* insert at front */
17157  z->next = active;
17158  active = z;
17159  }
17160  }
17161  ++e;
17162  }
17163 
17164  /* now process all active edges */
17165  if (active)
17166  stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
17167 
17168  {
17169  float sum = 0;
17170  for (i=0; i < result->w; ++i) {
17171  float k;
17172  int m;
17173  sum += scanline2[i];
17174  k = scanline[i] + sum;
17175  k = (float) STBTT_fabs(k)*255 + 0.5f;
17176  m = (int) k;
17177  if (m > 255) m = 255;
17178  result->pixels[j*result->stride + i] = (unsigned char) m;
17179  }
17180  }
17181  /* advance all the edges */
17182  step = &active;
17183  while (*step) {
17184  stbtt__active_edge *z = *step;
17185  z->fx += z->fdx; /* advance to position for current scanline */
17186  step = &((*step)->next); /* advance through list */
17187  }
17188 
17189  ++y;
17190  ++j;
17191  }
17192 
17193  stbtt__hheap_cleanup(&hh, userdata);
17194 
17195  if (scanline != scanline_data)
17196  STBTT_free(scanline, userdata);
17197 }
17198 #else
17199 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
17200 #endif
17201 
17202 #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
17203 
17204 static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
17205 {
17206  int i,j;
17207  for (i=1; i < n; ++i) {
17208  stbtt__edge t = p[i], *a = &t;
17209  j = i;
17210  while (j > 0) {
17211  stbtt__edge *b = &p[j-1];
17212  int c = STBTT__COMPARE(a,b);
17213  if (!c) break;
17214  p[j] = p[j-1];
17215  --j;
17216  }
17217  if (i != j)
17218  p[j] = t;
17219  }
17220 }
17221 
17222 static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
17223 {
17224  /* threshold for transitioning to insertion sort */
17225  while (n > 12) {
17226  stbtt__edge t;
17227  int c01,c12,c,m,i,j;
17228 
17229  /* compute median of three */
17230  m = n >> 1;
17231  c01 = STBTT__COMPARE(&p[0],&p[m]);
17232  c12 = STBTT__COMPARE(&p[m],&p[n-1]);
17233  /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
17234  if (c01 != c12) {
17235  /* otherwise, we'll need to swap something else to middle */
17236  int z;
17237  c = STBTT__COMPARE(&p[0],&p[n-1]);
17238  /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
17239  /* 0<mid && mid>n: 0>n => 0; 0<n => n */
17240  z = (c == c12) ? 0 : n-1;
17241  t = p[z];
17242  p[z] = p[m];
17243  p[m] = t;
17244  }
17245  /* now p[m] is the median-of-three */
17246  /* swap it to the beginning so it won't move around */
17247  t = p[0];
17248  p[0] = p[m];
17249  p[m] = t;
17250 
17251  /* partition loop */
17252  i=1;
17253  j=n-1;
17254  for(;;) {
17255  /* handling of equality is crucial here */
17256  /* for sentinels & efficiency with duplicates */
17257  for (;;++i) {
17258  if (!STBTT__COMPARE(&p[i], &p[0])) break;
17259  }
17260  for (;;--j) {
17261  if (!STBTT__COMPARE(&p[0], &p[j])) break;
17262  }
17263  /* make sure we haven't crossed */
17264  if (i >= j) break;
17265  t = p[i];
17266  p[i] = p[j];
17267  p[j] = t;
17268 
17269  ++i;
17270  --j;
17271  }
17272  /* recurse on smaller side, iterate on larger */
17273  if (j < (n-i)) {
17274  stbtt__sort_edges_quicksort(p,j);
17275  p = p+i;
17276  n = n-i;
17277  } else {
17278  stbtt__sort_edges_quicksort(p+i, n-i);
17279  n = j;
17280  }
17281  }
17282 }
17283 
17284 static void stbtt__sort_edges(stbtt__edge *p, int n)
17285 {
17286  stbtt__sort_edges_quicksort(p, n);
17287  stbtt__sort_edges_ins_sort(p, n);
17288 }
17289 
17290 typedef struct
17291 {
17292  float x,y;
17293 } stbtt__point;
17294 
17295 static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
17296 {
17297  float y_scale_inv = invert ? -scale_y : scale_y;
17298  stbtt__edge *e;
17299  int n,i,j,k,m;
17300 #if STBTT_RASTERIZER_VERSION == 1
17301  int vsubsample = result->h < 8 ? 15 : 5;
17302 #elif STBTT_RASTERIZER_VERSION == 2
17303  int vsubsample = 1;
17304 #else
17305  #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
17306 #endif
17307  /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
17308 
17309  /* now we have to blow out the windings into explicit edge lists */
17310  n = 0;
17311  for (i=0; i < windings; ++i)
17312  n += wcount[i];
17313 
17314  e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); /* add an extra one as a sentinel */
17315  if (e == 0) return;
17316  n = 0;
17317 
17318  m=0;
17319  for (i=0; i < windings; ++i) {
17320  stbtt__point *p = pts + m;
17321  m += wcount[i];
17322  j = wcount[i]-1;
17323  for (k=0; k < wcount[i]; j=k++) {
17324  int a=k,b=j;
17325  /* skip the edge if horizontal */
17326  if (p[j].y == p[k].y)
17327  continue;
17328  /* add edge from j to k to the list */
17329  e[n].invert = 0;
17330  if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
17331  e[n].invert = 1;
17332  a=j,b=k;
17333  }
17334  e[n].x0 = p[a].x * scale_x + shift_x;
17335  e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
17336  e[n].x1 = p[b].x * scale_x + shift_x;
17337  e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
17338  ++n;
17339  }
17340  }
17341 
17342  /* now sort the edges by their highest point (should snap to integer, and then by x) */
17343  /* STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */
17344  stbtt__sort_edges(e, n);
17345 
17346  /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
17347  stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
17348 
17349  STBTT_free(e, userdata);
17350 }
17351 
17352 static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
17353 {
17354  if (!points) return; /* during first pass, it's unallocated */
17355  points[n].x = x;
17356  points[n].y = y;
17357 }
17358 
17359 /* tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching */
17360 static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
17361 {
17362  /* midpoint */
17363  float mx = (x0 + 2*x1 + x2)/4;
17364  float my = (y0 + 2*y1 + y2)/4;
17365  /* versus directly drawn line */
17366  float dx = (x0+x2)/2 - mx;
17367  float dy = (y0+y2)/2 - my;
17368  if (n > 16) /* 65536 segments on one curve better be enough! */
17369  return 1;
17370  if (dx*dx+dy*dy > objspace_flatness_squared) { /* half-pixel error allowed... need to be smaller if AA */
17371  stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
17372  stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
17373  } else {
17374  stbtt__add_point(points, *num_points,x2,y2);
17375  *num_points = *num_points+1;
17376  }
17377  return 1;
17378 }
17379 
17380 static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
17381 {
17382  /* @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough */
17383  float dx0 = x1-x0;
17384  float dy0 = y1-y0;
17385  float dx1 = x2-x1;
17386  float dy1 = y2-y1;
17387  float dx2 = x3-x2;
17388  float dy2 = y3-y2;
17389  float dx = x3-x0;
17390  float dy = y3-y0;
17391  float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
17392  float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
17393  float flatness_squared = longlen*longlen-shortlen*shortlen;
17394 
17395  if (n > 16) /* 65536 segments on one curve better be enough! */
17396  return;
17397 
17398  if (flatness_squared > objspace_flatness_squared) {
17399  float x01 = (x0+x1)/2;
17400  float y01 = (y0+y1)/2;
17401  float x12 = (x1+x2)/2;
17402  float y12 = (y1+y2)/2;
17403  float x23 = (x2+x3)/2;
17404  float y23 = (y2+y3)/2;
17405 
17406  float xa = (x01+x12)/2;
17407  float ya = (y01+y12)/2;
17408  float xb = (x12+x23)/2;
17409  float yb = (y12+y23)/2;
17410 
17411  float mx = (xa+xb)/2;
17412  float my = (ya+yb)/2;
17413 
17414  stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
17415  stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
17416  } else {
17417  stbtt__add_point(points, *num_points,x3,y3);
17418  *num_points = *num_points+1;
17419  }
17420 }
17421 
17422 /* returns number of contours */
17423 static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
17424 {
17425  stbtt__point *points=0;
17426  int num_points=0;
17427 
17428  float objspace_flatness_squared = objspace_flatness * objspace_flatness;
17429  int i,n=0,start=0, pass;
17430 
17431  /* count how many "moves" there are to get the contour count */
17432  for (i=0; i < num_verts; ++i)
17433  if (vertices[i].type == STBTT_vmove)
17434  ++n;
17435 
17436  *num_contours = n;
17437  if (n == 0) return 0;
17438 
17439  *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
17440 
17441  if (*contour_lengths == 0) {
17442  *num_contours = 0;
17443  return 0;
17444  }
17445 
17446  /* make two passes through the points so we don't need to realloc */
17447  for (pass=0; pass < 2; ++pass) {
17448  float x=0,y=0;
17449  if (pass == 1) {
17450  points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
17451  if (points == NULL) goto error;
17452  }
17453  num_points = 0;
17454  n= -1;
17455  for (i=0; i < num_verts; ++i) {
17456  switch (vertices[i].type) {
17457  case STBTT_vmove:
17458  /* start the next contour */
17459  if (n >= 0)
17460  (*contour_lengths)[n] = num_points - start;
17461  ++n;
17462  start = num_points;
17463 
17464  x = vertices[i].x, y = vertices[i].y;
17465  stbtt__add_point(points, num_points++, x,y);
17466  break;
17467  case STBTT_vline:
17468  x = vertices[i].x, y = vertices[i].y;
17469  stbtt__add_point(points, num_points++, x, y);
17470  break;
17471  case STBTT_vcurve:
17472  stbtt__tesselate_curve(points, &num_points, x,y,
17473  vertices[i].cx, vertices[i].cy,
17474  vertices[i].x, vertices[i].y,
17475  objspace_flatness_squared, 0);
17476  x = vertices[i].x, y = vertices[i].y;
17477  break;
17478  case STBTT_vcubic:
17479  stbtt__tesselate_cubic(points, &num_points, x,y,
17480  vertices[i].cx, vertices[i].cy,
17481  vertices[i].cx1, vertices[i].cy1,
17482  vertices[i].x, vertices[i].y,
17483  objspace_flatness_squared, 0);
17484  x = vertices[i].x, y = vertices[i].y;
17485  break;
17486  }
17487  }
17488  (*contour_lengths)[n] = num_points - start;
17489  }
17490 
17491  return points;
17492 error:
17493  STBTT_free(points, userdata);
17494  STBTT_free(*contour_lengths, userdata);
17495  *contour_lengths = 0;
17496  *num_contours = 0;
17497  return NULL;
17498 }
17499 
17500 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
17501 {
17502  float scale = scale_x > scale_y ? scale_y : scale_x;
17503  int winding_count = 0;
17504  int *winding_lengths = NULL;
17505  stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
17506  if (windings) {
17507  stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
17508  STBTT_free(winding_lengths, userdata);
17509  STBTT_free(windings, userdata);
17510  }
17511 }
17512 
17513 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
17514 {
17515  STBTT_free(bitmap, userdata);
17516 }
17517 
17518 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
17519 {
17520  int ix0,iy0,ix1,iy1;
17521  stbtt__bitmap gbm;
17522  stbtt_vertex *vertices;
17523  int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
17524 
17525  if (scale_x == 0) scale_x = scale_y;
17526  if (scale_y == 0) {
17527  if (scale_x == 0) {
17528  STBTT_free(vertices, info->userdata);
17529  return NULL;
17530  }
17531  scale_y = scale_x;
17532  }
17533 
17534  stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
17535 
17536  /* now we get the size */
17537  gbm.w = (ix1 - ix0);
17538  gbm.h = (iy1 - iy0);
17539  gbm.pixels = NULL; /* in case we error */
17540 
17541  if (width ) *width = gbm.w;
17542  if (height) *height = gbm.h;
17543  if (xoff ) *xoff = ix0;
17544  if (yoff ) *yoff = iy0;
17545 
17546  if (gbm.w && gbm.h) {
17547  gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
17548  if (gbm.pixels) {
17549  gbm.stride = gbm.w;
17550 
17551  stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
17552  }
17553  }
17554  STBTT_free(vertices, info->userdata);
17555  return gbm.pixels;
17556 }
17557 
17558 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
17559 {
17560  return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
17561 }
17562 
17563 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
17564 {
17565  int ix0,iy0;
17566  stbtt_vertex *vertices;
17567  int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
17568  stbtt__bitmap gbm;
17569 
17570  stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
17571  gbm.pixels = output;
17572  gbm.w = out_w;
17573  gbm.h = out_h;
17574  gbm.stride = out_stride;
17575 
17576  if (gbm.w && gbm.h)
17577  stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
17578 
17579  STBTT_free(vertices, info->userdata);
17580 }
17581 
17582 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
17583 {
17584  stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
17585 }
17586 
17587 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
17588 {
17589  return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
17590 }
17591 
17592 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
17593 {
17594  stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
17595 }
17596 
17597 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
17598 {
17599  stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
17600 }
17601 
17602 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
17603 {
17604  return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
17605 }
17606 
17607 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
17608 {
17609  stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
17610 }
17611 
17612 /* //////////////////////////////////////////////////////////////////////////// */
17613 /* */
17614 /* bitmap baking */
17615 /* */
17616 /* This is SUPER-CRAPPY packing to keep source code small */
17617 
17618 static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, /* font location (use offset=0 for plain .ttf) */
17619  float pixel_height, /* height of font in pixels */
17620  unsigned char *pixels, int pw, int ph, /* bitmap to be filled in */
17621  int first_char, int num_chars, /* characters to bake */
17622  stbtt_bakedchar *chardata)
17623 {
17624  float scale;
17625  int x,y,bottom_y, i;
17626  stbtt_fontinfo f;
17627  f.userdata = NULL;
17628  if (!stbtt_InitFont(&f, data, offset))
17629  return -1;
17630  STBTT_memset(pixels, 0, pw*ph); /* background of 0 around pixels */
17631  x=y=1;
17632  bottom_y = 1;
17633 
17634  scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
17635 
17636  for (i=0; i < num_chars; ++i) {
17637  int advance, lsb, x0,y0,x1,y1,gw,gh;
17638  int g = stbtt_FindGlyphIndex(&f, first_char + i);
17639  stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
17640  stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
17641  gw = x1-x0;
17642  gh = y1-y0;
17643  if (x + gw + 1 >= pw)
17644  y = bottom_y, x = 1; /* advance to next row */
17645  if (y + gh + 1 >= ph) /* check if it fits vertically AFTER potentially moving to next row */
17646  return -i;
17647  STBTT_assert(x+gw < pw);
17648  STBTT_assert(y+gh < ph);
17649  stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
17650  chardata[i].x0 = (stbtt_int16) x;
17651  chardata[i].y0 = (stbtt_int16) y;
17652  chardata[i].x1 = (stbtt_int16) (x + gw);
17653  chardata[i].y1 = (stbtt_int16) (y + gh);
17654  chardata[i].xadvance = scale * advance;
17655  chardata[i].xoff = (float) x0;
17656  chardata[i].yoff = (float) y0;
17657  x = x + gw + 1;
17658  if (y+gh+1 > bottom_y)
17659  bottom_y = y+gh+1;
17660  }
17661  return bottom_y;
17662 }
17663 
17664 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
17665 {
17666  float d3d_bias = opengl_fillrule ? 0 : -0.5f;
17667  float ipw = 1.0f / pw, iph = 1.0f / ph;
17668  const stbtt_bakedchar *b = chardata + char_index;
17669  int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
17670  int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
17671 
17672  q->x0 = round_x + d3d_bias;
17673  q->y0 = round_y + d3d_bias;
17674  q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
17675  q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
17676 
17677  q->s0 = b->x0 * ipw;
17678  q->t0 = b->y0 * iph;
17679  q->s1 = b->x1 * ipw;
17680  q->t1 = b->y1 * iph;
17681 
17682  *xpos += b->xadvance;
17683 }
17684 
17685 /* //////////////////////////////////////////////////////////////////////////// */
17686 /* */
17687 /* rectangle packing replacement routines if you don't have stb_rect_pack.h */
17688 /* */
17689 
17690 #ifndef STB_RECT_PACK_VERSION
17691 
17692 typedef int stbrp_coord;
17693 
17694 /* ////////////////////////////////////////////////////////////////////////////////// */
17695 /* // */
17696 /* // */
17697 /* COMPILER WARNING ?!?!? // */
17698 /* // */
17699 /* // */
17700 /* if you get a compile warning due to these symbols being defined more than // */
17701 /* once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // */
17702 /* // */
17703 /* ////////////////////////////////////////////////////////////////////////////////// */
17704 
17705 typedef struct
17706 {
17707  int width,height;
17708  int x,y,bottom_y;
17709 } stbrp_context;
17710 
17711 typedef struct
17712 {
17713  unsigned char x;
17714 } stbrp_node;
17715 
17716 struct stbrp_rect
17717 {
17718  stbrp_coord x,y;
17719  int id,w,h,was_packed;
17720 };
17721 
17722 static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
17723 {
17724  con->width = pw;
17725  con->height = ph;
17726  con->x = 0;
17727  con->y = 0;
17728  con->bottom_y = 0;
17729  STBTT__NOTUSED(nodes);
17730  STBTT__NOTUSED(num_nodes);
17731 }
17732 
17733 static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
17734 {
17735  int i;
17736  for (i=0; i < num_rects; ++i) {
17737  if (con->x + rects[i].w > con->width) {
17738  con->x = 0;
17739  con->y = con->bottom_y;
17740  }
17741  if (con->y + rects[i].h > con->height)
17742  break;
17743  rects[i].x = con->x;
17744  rects[i].y = con->y;
17745  rects[i].was_packed = 1;
17746  con->x += rects[i].w;
17747  if (con->y + rects[i].h > con->bottom_y)
17748  con->bottom_y = con->y + rects[i].h;
17749  }
17750  for ( ; i < num_rects; ++i)
17751  rects[i].was_packed = 0;
17752 }
17753 #endif
17754 
17755 /* //////////////////////////////////////////////////////////////////////////// */
17756 /* */
17757 /* bitmap baking */
17758 /* */
17759 /* This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If */
17760 /* stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. */
17761 
17762 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
17763 {
17764  stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
17765  int num_nodes = pw - padding;
17766  stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
17767 
17768  if (context == NULL || nodes == NULL) {
17769  if (context != NULL) STBTT_free(context, alloc_context);
17770  if (nodes != NULL) STBTT_free(nodes , alloc_context);
17771  return 0;
17772  }
17773 
17774  spc->user_allocator_context = alloc_context;
17775  spc->width = pw;
17776  spc->height = ph;
17777  spc->pixels = pixels;
17778  spc->pack_info = context;
17779  spc->nodes = nodes;
17780  spc->padding = padding;
17781  spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
17782  spc->h_oversample = 1;
17783  spc->v_oversample = 1;
17784  spc->skip_missing = 0;
17785 
17786  stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
17787 
17788  if (pixels)
17789  STBTT_memset(pixels, 0, pw*ph); /* background of 0 around pixels */
17790 
17791  return 1;
17792 }
17793 
17794 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
17795 {
17796  STBTT_free(spc->nodes , spc->user_allocator_context);
17797  STBTT_free(spc->pack_info, spc->user_allocator_context);
17798 }
17799 
17800 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
17801 {
17802  STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
17803  STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
17804  if (h_oversample <= STBTT_MAX_OVERSAMPLE)
17805  spc->h_oversample = h_oversample;
17806  if (v_oversample <= STBTT_MAX_OVERSAMPLE)
17807  spc->v_oversample = v_oversample;
17808 }
17809 
17810 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
17811 {
17812  spc->skip_missing = skip;
17813 }
17814 
17815 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
17816 
17817 static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
17818 {
17819  unsigned char buffer[STBTT_MAX_OVERSAMPLE];
17820  int safe_w = w - kernel_width;
17821  int j;
17822  STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); /* suppress bogus warning from VS2013 -analyze */
17823  for (j=0; j < h; ++j) {
17824  int i;
17825  unsigned int total;
17826  STBTT_memset(buffer, 0, kernel_width);
17827 
17828  total = 0;
17829 
17830  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
17831  switch (kernel_width) {
17832  case 2:
17833  for (i=0; i <= safe_w; ++i) {
17834  total += pixels[i] - buffer[i & STBTT__OVER_MASK];
17835  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
17836  pixels[i] = (unsigned char) (total / 2);
17837  }
17838  break;
17839  case 3:
17840  for (i=0; i <= safe_w; ++i) {
17841  total += pixels[i] - buffer[i & STBTT__OVER_MASK];
17842  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
17843  pixels[i] = (unsigned char) (total / 3);
17844  }
17845  break;
17846  case 4:
17847  for (i=0; i <= safe_w; ++i) {
17848  total += pixels[i] - buffer[i & STBTT__OVER_MASK];
17849  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
17850  pixels[i] = (unsigned char) (total / 4);
17851  }
17852  break;
17853  case 5:
17854  for (i=0; i <= safe_w; ++i) {
17855  total += pixels[i] - buffer[i & STBTT__OVER_MASK];
17856  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
17857  pixels[i] = (unsigned char) (total / 5);
17858  }
17859  break;
17860  default:
17861  for (i=0; i <= safe_w; ++i) {
17862  total += pixels[i] - buffer[i & STBTT__OVER_MASK];
17863  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
17864  pixels[i] = (unsigned char) (total / kernel_width);
17865  }
17866  break;
17867  }
17868 
17869  for (; i < w; ++i) {
17870  STBTT_assert(pixels[i] == 0);
17871  total -= buffer[i & STBTT__OVER_MASK];
17872  pixels[i] = (unsigned char) (total / kernel_width);
17873  }
17874 
17875  pixels += stride_in_bytes;
17876  }
17877 }
17878 
17879 static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
17880 {
17881  unsigned char buffer[STBTT_MAX_OVERSAMPLE];
17882  int safe_h = h - kernel_width;
17883  int j;
17884  STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); /* suppress bogus warning from VS2013 -analyze */
17885  for (j=0; j < w; ++j) {
17886  int i;
17887  unsigned int total;
17888  STBTT_memset(buffer, 0, kernel_width);
17889 
17890  total = 0;
17891 
17892  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
17893  switch (kernel_width) {
17894  case 2:
17895  for (i=0; i <= safe_h; ++i) {
17896  total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
17897  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
17898  pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
17899  }
17900  break;
17901  case 3:
17902  for (i=0; i <= safe_h; ++i) {
17903  total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
17904  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
17905  pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
17906  }
17907  break;
17908  case 4:
17909  for (i=0; i <= safe_h; ++i) {
17910  total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
17911  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
17912  pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
17913  }
17914  break;
17915  case 5:
17916  for (i=0; i <= safe_h; ++i) {
17917  total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
17918  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
17919  pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
17920  }
17921  break;
17922  default:
17923  for (i=0; i <= safe_h; ++i) {
17924  total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
17925  buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
17926  pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
17927  }
17928  break;
17929  }
17930 
17931  for (; i < h; ++i) {
17932  STBTT_assert(pixels[i*stride_in_bytes] == 0);
17933  total -= buffer[i & STBTT__OVER_MASK];
17934  pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
17935  }
17936 
17937  pixels += 1;
17938  }
17939 }
17940 
17941 static float stbtt__oversample_shift(int oversample)
17942 {
17943  if (!oversample)
17944  return 0.0f;
17945 
17946  /* The prefilter is a box filter of width "oversample", */
17947  /* which shifts phase by (oversample - 1)/2 pixels in */
17948  /* oversampled space. We want to shift in the opposite */
17949  /* direction to counter this. */
17950  return (float)-(oversample - 1) / (2.0f * (float)oversample);
17951 }
17952 
17953 /* rects array must be big enough to accommodate all characters in the given ranges */
17954 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
17955 {
17956  int i,j,k;
17957  int missing_glyph_added = 0;
17958 
17959  k=0;
17960  for (i=0; i < num_ranges; ++i) {
17961  float fh = ranges[i].font_size;
17962  float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
17963  ranges[i].h_oversample = (unsigned char) spc->h_oversample;
17964  ranges[i].v_oversample = (unsigned char) spc->v_oversample;
17965  for (j=0; j < ranges[i].num_chars; ++j) {
17966  int x0,y0,x1,y1;
17967  int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
17968  int glyph = stbtt_FindGlyphIndex(info, codepoint);
17969  if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
17970  rects[k].w = rects[k].h = 0;
17971  } else {
17972  stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
17973  scale * spc->h_oversample,
17974  scale * spc->v_oversample,
17975  0,0,
17976  &x0,&y0,&x1,&y1);
17977  rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
17978  rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
17979  if (glyph == 0)
17980  missing_glyph_added = 1;
17981  }
17982  ++k;
17983  }
17984  }
17985 
17986  return k;
17987 }
17988 
17989 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
17990 {
17991  stbtt_MakeGlyphBitmapSubpixel(info,
17992  output,
17993  out_w - (prefilter_x - 1),
17994  out_h - (prefilter_y - 1),
17995  out_stride,
17996  scale_x,
17997  scale_y,
17998  shift_x,
17999  shift_y,
18000  glyph);
18001 
18002  if (prefilter_x > 1)
18003  stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
18004 
18005  if (prefilter_y > 1)
18006  stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
18007 
18008  *sub_x = stbtt__oversample_shift(prefilter_x);
18009  *sub_y = stbtt__oversample_shift(prefilter_y);
18010 }
18011 
18012 /* rects array must be big enough to accommodate all characters in the given ranges */
18013 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
18014 {
18015  int i,j,k, missing_glyph = -1, return_value = 1;
18016 
18017  /* save current values */
18018  int old_h_over = spc->h_oversample;
18019  int old_v_over = spc->v_oversample;
18020 
18021  k = 0;
18022  for (i=0; i < num_ranges; ++i) {
18023  float fh = ranges[i].font_size;
18024  float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
18025  float recip_h,recip_v,sub_x,sub_y;
18026  spc->h_oversample = ranges[i].h_oversample;
18027  spc->v_oversample = ranges[i].v_oversample;
18028  recip_h = 1.0f / spc->h_oversample;
18029  recip_v = 1.0f / spc->v_oversample;
18030  sub_x = stbtt__oversample_shift(spc->h_oversample);
18031  sub_y = stbtt__oversample_shift(spc->v_oversample);
18032  for (j=0; j < ranges[i].num_chars; ++j) {
18033  stbrp_rect *r = &rects[k];
18034  if (r->was_packed && r->w != 0 && r->h != 0) {
18035  stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
18036  int advance, lsb, x0,y0,x1,y1;
18037  int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
18038  int glyph = stbtt_FindGlyphIndex(info, codepoint);
18039  stbrp_coord pad = (stbrp_coord) spc->padding;
18040 
18041  /* pad on left and top */
18042  r->x += pad;
18043  r->y += pad;
18044  r->w -= pad;
18045  r->h -= pad;
18046  stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
18047  stbtt_GetGlyphBitmapBox(info, glyph,
18048  scale * spc->h_oversample,
18049  scale * spc->v_oversample,
18050  &x0,&y0,&x1,&y1);
18051  stbtt_MakeGlyphBitmapSubpixel(info,
18052  spc->pixels + r->x + r->y*spc->stride_in_bytes,
18053  r->w - spc->h_oversample+1,
18054  r->h - spc->v_oversample+1,
18055  spc->stride_in_bytes,
18056  scale * spc->h_oversample,
18057  scale * spc->v_oversample,
18058  0,0,
18059  glyph);
18060 
18061  if (spc->h_oversample > 1)
18062  stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
18063  r->w, r->h, spc->stride_in_bytes,
18064  spc->h_oversample);
18065 
18066  if (spc->v_oversample > 1)
18067  stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
18068  r->w, r->h, spc->stride_in_bytes,
18069  spc->v_oversample);
18070 
18071  bc->x0 = (stbtt_int16) r->x;
18072  bc->y0 = (stbtt_int16) r->y;
18073  bc->x1 = (stbtt_int16) (r->x + r->w);
18074  bc->y1 = (stbtt_int16) (r->y + r->h);
18075  bc->xadvance = scale * advance;
18076  bc->xoff = (float) x0 * recip_h + sub_x;
18077  bc->yoff = (float) y0 * recip_v + sub_y;
18078  bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
18079  bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
18080 
18081  if (glyph == 0)
18082  missing_glyph = j;
18083  } else if (spc->skip_missing) {
18084  return_value = 0;
18085  } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
18086  ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
18087  } else {
18088  return_value = 0; /* if any fail, report failure */
18089  }
18090 
18091  ++k;
18092  }
18093  }
18094 
18095  /* restore original values */
18096  spc->h_oversample = old_h_over;
18097  spc->v_oversample = old_v_over;
18098 
18099  return return_value;
18100 }
18101 
18102 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
18103 {
18104  stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
18105 }
18106 
18107 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
18108 {
18109  stbtt_fontinfo info;
18110  int i,j,n, return_value = 1;
18111  /* stbrp_context *context = (stbrp_context *) spc->pack_info; */
18112  stbrp_rect *rects;
18113 
18114  /* flag all characters as NOT packed */
18115  for (i=0; i < num_ranges; ++i)
18116  for (j=0; j < ranges[i].num_chars; ++j)
18117  ranges[i].chardata_for_range[j].x0 =
18118  ranges[i].chardata_for_range[j].y0 =
18119  ranges[i].chardata_for_range[j].x1 =
18120  ranges[i].chardata_for_range[j].y1 = 0;
18121 
18122  n = 0;
18123  for (i=0; i < num_ranges; ++i)
18124  n += ranges[i].num_chars;
18125 
18126  rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
18127  if (rects == NULL)
18128  return 0;
18129 
18130  info.userdata = spc->user_allocator_context;
18131  stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
18132 
18133  n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
18134 
18135  stbtt_PackFontRangesPackRects(spc, rects, n);
18136 
18137  return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
18138 
18139  STBTT_free(rects, spc->user_allocator_context);
18140  return return_value;
18141 }
18142 
18143 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
18144  int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
18145 {
18146  stbtt_pack_range range;
18147  range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
18148  range.array_of_unicode_codepoints = NULL;
18149  range.num_chars = num_chars_in_range;
18150  range.chardata_for_range = chardata_for_range;
18151  range.font_size = font_size;
18152  return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
18153 }
18154 
18155 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
18156 {
18157  int i_ascent, i_descent, i_lineGap;
18158  float scale;
18159  stbtt_fontinfo info;
18160  stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
18161  scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
18162  stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
18163  *ascent = (float) i_ascent * scale;
18164  *descent = (float) i_descent * scale;
18165  *lineGap = (float) i_lineGap * scale;
18166 }
18167 
18168 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
18169 {
18170  float ipw = 1.0f / pw, iph = 1.0f / ph;
18171  const stbtt_packedchar *b = chardata + char_index;
18172 
18173  if (align_to_integer) {
18174  float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
18175  float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
18176  q->x0 = x;
18177  q->y0 = y;
18178  q->x1 = x + b->xoff2 - b->xoff;
18179  q->y1 = y + b->yoff2 - b->yoff;
18180  } else {
18181  q->x0 = *xpos + b->xoff;
18182  q->y0 = *ypos + b->yoff;
18183  q->x1 = *xpos + b->xoff2;
18184  q->y1 = *ypos + b->yoff2;
18185  }
18186 
18187  q->s0 = b->x0 * ipw;
18188  q->t0 = b->y0 * iph;
18189  q->s1 = b->x1 * ipw;
18190  q->t1 = b->y1 * iph;
18191 
18192  *xpos += b->xadvance;
18193 }
18194 
18195 /* //////////////////////////////////////////////////////////////////////////// */
18196 /* */
18197 /* sdf computation */
18198 /* */
18199 
18200 #define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
18201 #define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
18202 
18203 static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
18204 {
18205  float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
18206  float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
18207  float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
18208  float roperp = orig[1]*ray[0] - orig[0]*ray[1];
18209 
18210  float a = q0perp - 2*q1perp + q2perp;
18211  float b = q1perp - q0perp;
18212  float c = q0perp - roperp;
18213 
18214  float s0 = 0., s1 = 0.;
18215  int num_s = 0;
18216 
18217  if (a != 0.0) {
18218  float discr = b*b - a*c;
18219  if (discr > 0.0) {
18220  float rcpna = -1 / a;
18221  float d = (float) STBTT_sqrt(discr);
18222  s0 = (b+d) * rcpna;
18223  s1 = (b-d) * rcpna;
18224  if (s0 >= 0.0 && s0 <= 1.0)
18225  num_s = 1;
18226  if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
18227  if (num_s == 0) s0 = s1;
18228  ++num_s;
18229  }
18230  }
18231  } else {
18232  /* 2*b*s + c = 0 */
18233  /* s = -c / (2*b) */
18234  s0 = c / (-2 * b);
18235  if (s0 >= 0.0 && s0 <= 1.0)
18236  num_s = 1;
18237  }
18238 
18239  if (num_s == 0)
18240  return 0;
18241  else {
18242  float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
18243  float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
18244 
18245  float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
18246  float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
18247  float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
18248  float rod = orig[0]*rayn_x + orig[1]*rayn_y;
18249 
18250  float q10d = q1d - q0d;
18251  float q20d = q2d - q0d;
18252  float q0rd = q0d - rod;
18253 
18254  hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
18255  hits[0][1] = a*s0+b;
18256 
18257  if (num_s > 1) {
18258  hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
18259  hits[1][1] = a*s1+b;
18260  return 2;
18261  } else {
18262  return 1;
18263  }
18264  }
18265 }
18266 
18267 static int equal(float *a, float *b)
18268 {
18269  return (a[0] == b[0] && a[1] == b[1]);
18270 }
18271 
18272 static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
18273 {
18274  int i;
18275  float orig[2], ray[2] = { 1, 0 };
18276  float y_frac;
18277  int winding = 0;
18278 
18279  /* make sure y never passes through a vertex of the shape */
18280  y_frac = (float) STBTT_fmod(y, 1.0f);
18281  if (y_frac < 0.01f)
18282  y += 0.01f;
18283  else if (y_frac > 0.99f)
18284  y -= 0.01f;
18285 
18286  orig[0] = x;
18287  orig[1] = y;
18288 
18289  /* test a ray from (-infinity,y) to (x,y) */
18290  for (i=0; i < nverts; ++i) {
18291  if (verts[i].type == STBTT_vline) {
18292  int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
18293  int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
18294  if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
18295  float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
18296  if (x_inter < x)
18297  winding += (y0 < y1) ? 1 : -1;
18298  }
18299  }
18300  if (verts[i].type == STBTT_vcurve) {
18301  int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
18302  int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
18303  int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
18304  int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
18305  int by = STBTT_max(y0,STBTT_max(y1,y2));
18306  if (y > ay && y < by && x > ax) {
18307  float q0[2],q1[2],q2[2];
18308  float hits[2][2];
18309  q0[0] = (float)x0;
18310  q0[1] = (float)y0;
18311  q1[0] = (float)x1;
18312  q1[1] = (float)y1;
18313  q2[0] = (float)x2;
18314  q2[1] = (float)y2;
18315  if (equal(q0,q1) || equal(q1,q2)) {
18316  x0 = (int)verts[i-1].x;
18317  y0 = (int)verts[i-1].y;
18318  x1 = (int)verts[i ].x;
18319  y1 = (int)verts[i ].y;
18320  if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
18321  float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
18322  if (x_inter < x)
18323  winding += (y0 < y1) ? 1 : -1;
18324  }
18325  } else {
18326  int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
18327  if (num_hits >= 1)
18328  if (hits[0][0] < 0)
18329  winding += (hits[0][1] < 0 ? -1 : 1);
18330  if (num_hits >= 2)
18331  if (hits[1][0] < 0)
18332  winding += (hits[1][1] < 0 ? -1 : 1);
18333  }
18334  }
18335  }
18336  }
18337  return winding;
18338 }
18339 
18340 static float stbtt__cuberoot( float x )
18341 {
18342  if (x<0)
18343  return -(float) STBTT_pow(-x,1.0f/3.0f);
18344  else
18345  return (float) STBTT_pow( x,1.0f/3.0f);
18346 }
18347 
18348 /* x^3 + a*x^2 + b*x + c = 0 */
18349 static int stbtt__solve_cubic(float a, float b, float c, float* r)
18350 {
18351  float s = -a / 3;
18352  float p = b - a*a / 3;
18353  float q = a * (2*a*a - 9*b) / 27 + c;
18354  float p3 = p*p*p;
18355  float d = q*q + 4*p3 / 27;
18356  if (d >= 0) {
18357  float z = (float) STBTT_sqrt(d);
18358  float u = (-q + z) / 2;
18359  float v = (-q - z) / 2;
18360  u = stbtt__cuberoot(u);
18361  v = stbtt__cuberoot(v);
18362  r[0] = s + u + v;
18363  return 1;
18364  } else {
18365  float u = (float) STBTT_sqrt(-p/3);
18366  float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; /* p3 must be negative, since d is negative */
18367  float m = (float) STBTT_cos(v);
18368  float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
18369  r[0] = s + u * 2 * m;
18370  r[1] = s - u * (m + n);
18371  r[2] = s - u * (m - n);
18372 
18373  /* STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? */
18374  /* STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); */
18375  /* STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); */
18376  return 3;
18377  }
18378 }
18379 
18380 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
18381 {
18382  float scale_x = scale, scale_y = scale;
18383  int ix0,iy0,ix1,iy1;
18384  int w,h;
18385  unsigned char *data;
18386 
18387  if (scale == 0) return NULL;
18388 
18389  stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
18390 
18391  /* if empty, return NULL */
18392  if (ix0 == ix1 || iy0 == iy1)
18393  return NULL;
18394 
18395  ix0 -= padding;
18396  iy0 -= padding;
18397  ix1 += padding;
18398  iy1 += padding;
18399 
18400  w = (ix1 - ix0);
18401  h = (iy1 - iy0);
18402 
18403  if (width ) *width = w;
18404  if (height) *height = h;
18405  if (xoff ) *xoff = ix0;
18406  if (yoff ) *yoff = iy0;
18407 
18408  /* invert for y-downwards bitmaps */
18409  scale_y = -scale_y;
18410 
18411  {
18412  int x,y,i,j;
18413  float *precompute;
18414  stbtt_vertex *verts;
18415  int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
18416  data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
18417  precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
18418 
18419  for (i=0,j=num_verts-1; i < num_verts; j=i++) {
18420  if (verts[i].type == STBTT_vline) {
18421  float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
18422  float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
18423  float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
18424  precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
18425  } else if (verts[i].type == STBTT_vcurve) {
18426  float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
18427  float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
18428  float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
18429  float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
18430  float len2 = bx*bx + by*by;
18431  if (len2 != 0.0f)
18432  precompute[i] = 1.0f / (bx*bx + by*by);
18433  else
18434  precompute[i] = 0.0f;
18435  } else
18436  precompute[i] = 0.0f;
18437  }
18438 
18439  for (y=iy0; y < iy1; ++y) {
18440  for (x=ix0; x < ix1; ++x) {
18441  float val;
18442  float min_dist = 999999.0f;
18443  float sx = (float) x + 0.5f;
18444  float sy = (float) y + 0.5f;
18445  float x_gspace = (sx / scale_x);
18446  float y_gspace = (sy / scale_y);
18447 
18448  int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); /* @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path */
18449 
18450  for (i=0; i < num_verts; ++i) {
18451  float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
18452 
18453  if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
18454  float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
18455 
18456  float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
18457  if (dist2 < min_dist*min_dist)
18458  min_dist = (float) STBTT_sqrt(dist2);
18459 
18460  /* coarse culling against bbox */
18461  /* if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && */
18462  /* sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) */
18463  dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
18464  STBTT_assert(i != 0);
18465  if (dist < min_dist) {
18466  /* check position along line */
18467  /* x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) */
18468  /* minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) */
18469  float dx = x1-x0, dy = y1-y0;
18470  float px = x0-sx, py = y0-sy;
18471  /* minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy */
18472  /* derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve */
18473  float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
18474  if (t >= 0.0f && t <= 1.0f)
18475  min_dist = dist;
18476  }
18477  } else if (verts[i].type == STBTT_vcurve) {
18478  float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
18479  float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
18480  float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
18481  float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
18482  float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
18483  float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
18484  /* coarse culling against bbox to avoid computing cubic unnecessarily */
18485  if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
18486  int num=0;
18487  float ax = x1-x0, ay = y1-y0;
18488  float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
18489  float mx = x0 - sx, my = y0 - sy;
18490  float res[3] = {0.f,0.f,0.f};
18491  float px,py,t,it,dist2;
18492  float a_inv = precompute[i];
18493  if (a_inv == 0.0) { /* if a_inv is 0, it's 2nd degree so use quadratic formula */
18494  float a = 3*(ax*bx + ay*by);
18495  float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
18496  float c = mx*ax+my*ay;
18497  if (a == 0.0) { /* if a is 0, it's linear */
18498  if (b != 0.0) {
18499  res[num++] = -c/b;
18500  }
18501  } else {
18502  float discriminant = b*b - 4*a*c;
18503  if (discriminant < 0)
18504  num = 0;
18505  else {
18506  float root = (float) STBTT_sqrt(discriminant);
18507  res[0] = (-b - root)/(2*a);
18508  res[1] = (-b + root)/(2*a);
18509  num = 2; /* don't bother distinguishing 1-solution case, as code below will still work */
18510  }
18511  }
18512  } else {
18513  float b = 3*(ax*bx + ay*by) * a_inv; /* could precompute this as it doesn't depend on sample point */
18514  float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
18515  float d = (mx*ax+my*ay) * a_inv;
18516  num = stbtt__solve_cubic(b, c, d, res);
18517  }
18518  dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
18519  if (dist2 < min_dist*min_dist)
18520  min_dist = (float) STBTT_sqrt(dist2);
18521 
18522  if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
18523  t = res[0], it = 1.0f - t;
18524  px = it*it*x0 + 2*t*it*x1 + t*t*x2;
18525  py = it*it*y0 + 2*t*it*y1 + t*t*y2;
18526  dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
18527  if (dist2 < min_dist * min_dist)
18528  min_dist = (float) STBTT_sqrt(dist2);
18529  }
18530  if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
18531  t = res[1], it = 1.0f - t;
18532  px = it*it*x0 + 2*t*it*x1 + t*t*x2;
18533  py = it*it*y0 + 2*t*it*y1 + t*t*y2;
18534  dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
18535  if (dist2 < min_dist * min_dist)
18536  min_dist = (float) STBTT_sqrt(dist2);
18537  }
18538  if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
18539  t = res[2], it = 1.0f - t;
18540  px = it*it*x0 + 2*t*it*x1 + t*t*x2;
18541  py = it*it*y0 + 2*t*it*y1 + t*t*y2;
18542  dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
18543  if (dist2 < min_dist * min_dist)
18544  min_dist = (float) STBTT_sqrt(dist2);
18545  }
18546  }
18547  }
18548  }
18549  if (winding == 0)
18550  min_dist = -min_dist; /* if outside the shape, value is negative */
18551  val = onedge_value + pixel_dist_scale * min_dist;
18552  if (val < 0)
18553  val = 0;
18554  else if (val > 255)
18555  val = 255;
18556  data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
18557  }
18558  }
18559  STBTT_free(precompute, info->userdata);
18560  STBTT_free(verts, info->userdata);
18561  }
18562  return data;
18563 }
18564 
18565 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
18566 {
18567  return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
18568 }
18569 
18570 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
18571 {
18572  STBTT_free(bitmap, userdata);
18573 }
18574 
18575 /* //////////////////////////////////////////////////////////////////////////// */
18576 /* */
18577 /* font name matching -- recommended not to use this */
18578 /* */
18579 
18580 /* check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string */
18581 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
18582 {
18583  stbtt_int32 i=0;
18584 
18585  /* convert utf16 to utf8 and compare the results while converting */
18586  while (len2) {
18587  stbtt_uint16 ch = s2[0]*256 + s2[1];
18588  if (ch < 0x80) {
18589  if (i >= len1) return -1;
18590  if (s1[i++] != ch) return -1;
18591  } else if (ch < 0x800) {
18592  if (i+1 >= len1) return -1;
18593  if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
18594  if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
18595  } else if (ch >= 0xd800 && ch < 0xdc00) {
18596  stbtt_uint32 c;
18597  stbtt_uint16 ch2 = s2[2]*256 + s2[3];
18598  if (i+3 >= len1) return -1;
18599  c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
18600  if (s1[i++] != 0xf0 + (c >> 18)) return -1;
18601  if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
18602  if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
18603  if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
18604  s2 += 2; /* plus another 2 below */
18605  len2 -= 2;
18606  } else if (ch >= 0xdc00 && ch < 0xe000) {
18607  return -1;
18608  } else {
18609  if (i+2 >= len1) return -1;
18610  if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
18611  if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
18612  if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
18613  }
18614  s2 += 2;
18615  len2 -= 2;
18616  }
18617  return i;
18618 }
18619 
18620 static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
18621 {
18622  return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
18623 }
18624 
18625 /* returns results in whatever encoding you request... but note that 2-byte encodings */
18626 /* will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare */
18627 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
18628 {
18629  stbtt_int32 i,count,stringOffset;
18630  stbtt_uint8 *fc = font->data;
18631  stbtt_uint32 offset = font->fontstart;
18632  stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
18633  if (!nm) return NULL;
18634 
18635  count = ttUSHORT(fc+nm+2);
18636  stringOffset = nm + ttUSHORT(fc+nm+4);
18637  for (i=0; i < count; ++i) {
18638  stbtt_uint32 loc = nm + 6 + 12 * i;
18639  if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
18640  && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
18641  *length = ttUSHORT(fc+loc+8);
18642  return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
18643  }
18644  }
18645  return NULL;
18646 }
18647 
18648 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
18649 {
18650  stbtt_int32 i;
18651  stbtt_int32 count = ttUSHORT(fc+nm+2);
18652  stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
18653 
18654  for (i=0; i < count; ++i) {
18655  stbtt_uint32 loc = nm + 6 + 12 * i;
18656  stbtt_int32 id = ttUSHORT(fc+loc+6);
18657  if (id == target_id) {
18658  /* find the encoding */
18659  stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
18660 
18661  /* is this a Unicode encoding? */
18662  if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
18663  stbtt_int32 slen = ttUSHORT(fc+loc+8);
18664  stbtt_int32 off = ttUSHORT(fc+loc+10);
18665 
18666  /* check if there's a prefix match */
18667  stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
18668  if (matchlen >= 0) {
18669  /* check for target_id+1 immediately following, with same encoding & language */
18670  if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
18671  slen = ttUSHORT(fc+loc+12+8);
18672  off = ttUSHORT(fc+loc+12+10);
18673  if (slen == 0) {
18674  if (matchlen == nlen)
18675  return 1;
18676  } else if (matchlen < nlen && name[matchlen] == ' ') {
18677  ++matchlen;
18678  if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
18679  return 1;
18680  }
18681  } else {
18682  /* if nothing immediately following */
18683  if (matchlen == nlen)
18684  return 1;
18685  }
18686  }
18687  }
18688 
18689  /* @TODO handle other encodings */
18690  }
18691  }
18692  return 0;
18693 }
18694 
18695 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
18696 {
18697  stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
18698  stbtt_uint32 nm,hd;
18699  if (!stbtt__isfont(fc+offset)) return 0;
18700 
18701  /* check italics/bold/underline flags in macStyle... */
18702  if (flags) {
18703  hd = stbtt__find_table(fc, offset, "head");
18704  if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
18705  }
18706 
18707  nm = stbtt__find_table(fc, offset, "name");
18708  if (!nm) return 0;
18709 
18710  if (flags) {
18711  /* if we checked the macStyle flags, then just check the family and ignore the subfamily */
18712  if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
18713  if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
18714  if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
18715  } else {
18716  if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
18717  if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
18718  if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
18719  }
18720 
18721  return 0;
18722 }
18723 
18724 static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
18725 {
18726  stbtt_int32 i;
18727  for (i=0;;++i) {
18728  stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
18729  if (off < 0) return off;
18730  if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
18731  return off;
18732  }
18733 }
18734 
18735 #if defined(__GNUC__) || defined(__clang__)
18736 #pragma GCC diagnostic push
18737 #pragma GCC diagnostic ignored "-Wcast-qual"
18738 #endif
18739 
18740 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
18741  float pixel_height, unsigned char *pixels, int pw, int ph,
18742  int first_char, int num_chars, stbtt_bakedchar *chardata)
18743 {
18744  return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
18745 }
18746 
18747 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
18748 {
18749  return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
18750 }
18751 
18752 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
18753 {
18754  return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
18755 }
18756 
18757 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
18758 {
18759  return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
18760 }
18761 
18762 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
18763 {
18764  return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
18765 }
18766 
18767 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
18768 {
18769  return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
18770 }
18771 
18772 #if defined(__GNUC__) || defined(__clang__)
18773 #pragma GCC diagnostic pop
18774 #endif
18775 
18776 #endif /* STB_TRUETYPE_IMPLEMENTATION */
18777 
18778 
18779 /* FULL VERSION HISTORY */
18780 /* */
18781 /* 1.25 (2021-07-11) many fixes */
18782 /* 1.24 (2020-02-05) fix warning */
18783 /* 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) */
18784 /* 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined */
18785 /* 1.21 (2019-02-25) fix warning */
18786 /* 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() */
18787 /* 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod */
18788 /* 1.18 (2018-01-29) add missing function */
18789 /* 1.17 (2017-07-23) make more arguments const; doc fix */
18790 /* 1.16 (2017-07-12) SDF support */
18791 /* 1.15 (2017-03-03) make more arguments const */
18792 /* 1.14 (2017-01-16) num-fonts-in-TTC function */
18793 /* 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts */
18794 /* 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual */
18795 /* 1.11 (2016-04-02) fix unused-variable warning */
18796 /* 1.10 (2016-04-02) allow user-defined fabs() replacement */
18797 /* fix memory leak if fontsize=0.0 */
18798 /* fix warning from duplicate typedef */
18799 /* 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges */
18800 /* 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges */
18801 /* 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; */
18802 /* allow PackFontRanges to pack and render in separate phases; */
18803 /* fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); */
18804 /* fixed an assert() bug in the new rasterizer */
18805 /* replace assert() with STBTT_assert() in new rasterizer */
18806 /* 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) */
18807 /* also more precise AA rasterizer, except if shapes overlap */
18808 /* remove need for STBTT_sort */
18809 /* 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC */
18810 /* 1.04 (2015-04-15) typo in example */
18811 /* 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes */
18812 /* 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ */
18813 /* 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match */
18814 /* non-oversampled; STBTT_POINT_SIZE for packed case only */
18815 /* 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling */
18816 /* 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) */
18817 /* 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID */
18818 /* 0.8b (2014-07-07) fix a warning */
18819 /* 0.8 (2014-05-25) fix a few more warnings */
18820 /* 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back */
18821 /* 0.6c (2012-07-24) improve documentation */
18822 /* 0.6b (2012-07-20) fix a few more warnings */
18823 /* 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, */
18824 /* stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty */
18825 /* 0.5 (2011-12-09) bugfixes: */
18826 /* subpixel glyph renderer computed wrong bounding box */
18827 /* first vertex of shape can be off-curve (FreeSans) */
18828 /* 0.4b (2011-12-03) fixed an error in the font baking example */
18829 /* 0.4 (2011-12-01) kerning, subpixel rendering (tor) */
18830 /* bugfixes for: */
18831 /* codepoint-to-glyph conversion using table fmt=12 */
18832 /* codepoint-to-glyph conversion using table fmt=4 */
18833 /* stbtt_GetBakedQuad with non-square texture (Zer) */
18834 /* updated Hello World! sample to use kerning and subpixel */
18835 /* fixed some warnings */
18836 /* 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) */
18837 /* userdata, malloc-from-userdata, non-zero fill (stb) */
18838 /* 0.2 (2009-03-11) Fix unsigned/signed char warnings */
18839 /* 0.1 (2009-03-09) First public release */
18840 /* */
18841 
18842 /*
18843 ------------------------------------------------------------------------------
18844 This software is available under 2 licenses -- choose whichever you prefer.
18845 ------------------------------------------------------------------------------
18846 ALTERNATIVE A - MIT License
18847 Copyright (c) 2017 Sean Barrett
18848 Permission is hereby granted, free of charge, to any person obtaining a copy of
18849 this software and associated documentation files (the "Software"), to deal in
18850 the Software without restriction, including without limitation the rights to
18851 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
18852 of the Software, and to permit persons to whom the Software is furnished to do
18853 so, subject to the following conditions:
18854 The above copyright notice and this permission notice shall be included in all
18855 copies or substantial portions of the Software.
18856 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18857 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18858 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18859 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18860 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18861 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18862 SOFTWARE.
18863 ------------------------------------------------------------------------------
18864 ALTERNATIVE B - Public Domain (www.unlicense.org)
18865 This is free and unencumbered software released into the public domain.
18866 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
18867 software, either in source code form or as a compiled binary, for any purpose,
18868 commercial or non-commercial, and by any means.
18869 In jurisdictions that recognize copyright laws, the author or authors of this
18870 software dedicate any and all copyright interest in the software to the public
18871 domain. We make this dedication for the benefit of the public at large and to
18872 the detriment of our heirs and successors. We intend this dedication to be an
18873 overt act of relinquishment in perpetuity of all present and future rights to
18874 this software under copyright law.
18875 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18876 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18877 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18878 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18879 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18880 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18881 ------------------------------------------------------------------------------
18882 */
18883 
18884 
18885 
18886 
18887 #ifdef NK_INCLUDE_FONT_BAKING
18888 /* -------------------------------------------------------------
18889  *
18890  * RECT PACK
18891  *
18892  * --------------------------------------------------------------*/
18893 
18894 
18895 
18896 /*
18897  * ==============================================================
18898  *
18899  * TRUETYPE
18900  *
18901  * ===============================================================
18902  */
18903 #define STBTT_MAX_OVERSAMPLE 8
18904 
18905 
18906 /* -------------------------------------------------------------
18907  *
18908  * FONT BAKING
18909  *
18910  * --------------------------------------------------------------*/
18911 struct nk_font_bake_data {
18912  struct stbtt_fontinfo info;
18913  struct stbrp_rect *rects;
18914  stbtt_pack_range *ranges;
18915  nk_rune range_count;
18916 };
18917 
18918 struct nk_font_baker {
18919  struct nk_allocator alloc;
18920  struct stbtt_pack_context spc;
18921  struct nk_font_bake_data *build;
18922  stbtt_packedchar *packed_chars;
18923  struct stbrp_rect *rects;
18924  stbtt_pack_range *ranges;
18925 };
18926 
18927 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct stbrp_rect);
18928 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(stbtt_pack_range);
18929 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(stbtt_packedchar);
18930 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
18931 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
18932 
18943 NK_INTERN int
18944 nk_range_count(const nk_rune *range)
18945 {
18946  const nk_rune *iter = range;
18947  NK_ASSERT(range);
18948  if (!range) return 0;
18949  while (*(iter++) != 0);
18950  return (iter == range) ? 0 : (int)((iter - range)/2);
18951 }
18963 NK_INTERN int
18964 nk_range_glyph_count(const nk_rune *range, int count)
18965 {
18966  int i = 0;
18967  int total_glyphs = 0;
18968  for (i = 0; i < count; ++i) {
18969  int diff;
18970  nk_rune f = range[(i*2)+0];
18971  nk_rune t = range[(i*2)+1];
18972  NK_ASSERT(t >= f);
18973  diff = (int)((t - f) + 1);
18974  total_glyphs += diff;
18975  }
18976  return total_glyphs;
18977 }
18988 NK_API const nk_rune*
18989 nk_font_default_glyph_ranges(void)
18990 {
18991  NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
18992  return ranges;
18993 }
19004 NK_API const nk_rune*
19005 nk_font_chinese_glyph_ranges(void)
19006 {
19007  NK_STORAGE const nk_rune ranges[] = {
19008  0x0020, 0x00FF,
19009  0x3000, 0x30FF,
19010  0x31F0, 0x31FF,
19011  0xFF00, 0xFFEF,
19012  0x4E00, 0x9FAF,
19013  0
19014  };
19015  return ranges;
19016 }
19027 NK_API const nk_rune*
19028 nk_font_cyrillic_glyph_ranges(void)
19029 {
19030  NK_STORAGE const nk_rune ranges[] = {
19031  0x0020, 0x00FF,
19032  0x0400, 0x052F,
19033  0x2DE0, 0x2DFF,
19034  0xA640, 0xA69F,
19035  0
19036  };
19037  return ranges;
19038 }
19049 NK_API const nk_rune*
19050 nk_font_korean_glyph_ranges(void)
19051 {
19052  NK_STORAGE const nk_rune ranges[] = {
19053  0x0020, 0x00FF,
19054  0x3131, 0x3163,
19055  0xAC00, 0xD79D,
19056  0
19057  };
19058  return ranges;
19059 }
19071 NK_INTERN void
19072 nk_font_baker_memory(nk_size *temp, int *glyph_count,
19073  struct nk_font_config *config_list, int count)
19074 {
19075  int range_count = 0;
19076  int total_range_count = 0;
19077  struct nk_font_config *iter, *i;
19078 
19079  NK_ASSERT(config_list);
19080  NK_ASSERT(glyph_count);
19081  if (!config_list) {
19082  *temp = 0;
19083  *glyph_count = 0;
19084  return;
19085  }
19086  *glyph_count = 0;
19087  for (iter = config_list; iter; iter = iter->next) {
19088  i = iter;
19089  do {if (!i->range) iter->range = nk_font_default_glyph_ranges();
19090  range_count = nk_range_count(i->range);
19091  total_range_count += range_count;
19092  *glyph_count += nk_range_glyph_count(i->range, range_count);
19093  } while ((i = i->n) != iter);
19094  }
19095  *temp = (nk_size)*glyph_count * sizeof(struct stbrp_rect);
19096  *temp += (nk_size)total_range_count * sizeof(stbtt_pack_range);
19097  *temp += (nk_size)*glyph_count * sizeof(stbtt_packedchar);
19098  *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
19099  *temp += sizeof(struct nk_font_baker);
19100  *temp += nk_rect_align + nk_range_align + nk_char_align;
19101  *temp += nk_build_align + nk_baker_align;
19102 }
19116 NK_INTERN struct nk_font_baker*
19117 nk_font_baker(void *memory, int glyph_count, int count, const struct nk_allocator *alloc)
19118 {
19119  struct nk_font_baker *baker;
19120  if (!memory) return 0;
19121  /* setup baker inside a memory block */
19122  baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
19123  baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
19124  baker->packed_chars = (stbtt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
19125  baker->rects = (struct stbrp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
19126  baker->ranges = (stbtt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
19127  baker->alloc = *alloc;
19128  return baker;
19129 }
19140 NK_INTERN int
19141 nk_font_bake_pack(struct nk_font_baker *baker,
19142  nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
19143  const struct nk_font_config *config_list, int count,
19144  const struct nk_allocator *alloc)
19145 {
19146  NK_STORAGE const nk_size max_height = 1024 * 32;
19147  const struct nk_font_config *config_iter, *it;
19148  int total_glyph_count = 0;
19149  int total_range_count = 0;
19150  int range_count = 0;
19151  int i = 0;
19152 
19153  NK_ASSERT(image_memory);
19154  NK_ASSERT(width);
19155  NK_ASSERT(height);
19156  NK_ASSERT(config_list);
19157  NK_ASSERT(count);
19158  NK_ASSERT(alloc);
19159 
19160  if (!image_memory || !width || !height || !config_list || !count) return nk_false;
19161  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
19162  it = config_iter;
19163  do {range_count = nk_range_count(it->range);
19164  total_range_count += range_count;
19165  total_glyph_count += nk_range_glyph_count(it->range, range_count);
19166  } while ((it = it->n) != config_iter);
19167  }
19168  /* setup font baker from temporary memory */
19169  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
19170  it = config_iter;
19171  do {
19172  struct stbtt_fontinfo *font_info = &baker->build[i++].info;
19173  font_info->userdata = (void*)alloc;
19174 
19175  if (!stbtt_InitFont(font_info, (const unsigned char*)it->ttf_blob, stbtt_GetFontOffsetForIndex((const unsigned char*)it->ttf_blob, 0)))
19176  return nk_false;
19177  } while ((it = it->n) != config_iter);
19178  }
19179  *height = 0;
19180  *width = (total_glyph_count > 1000) ? 1024 : 512;
19181  stbtt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, (void*)alloc);
19182  {
19183  int input_i = 0;
19184  int range_n = 0;
19185  int rect_n = 0;
19186  int char_n = 0;
19187 
19188  if (custom) {
19189  /* pack custom user data first so it will be in the upper left corner*/
19190  struct stbrp_rect custom_space;
19191  nk_zero(&custom_space, sizeof(custom_space));
19192  custom_space.w = (stbrp_coord)(custom->w);
19193  custom_space.h = (stbrp_coord)(custom->h);
19194 
19195  stbtt_PackSetOversampling(&baker->spc, 1, 1);
19196  stbrp_pack_rects((struct stbrp_context*)baker->spc.pack_info, &custom_space, 1);
19197  *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
19198 
19199  custom->x = (short)custom_space.x;
19200  custom->y = (short)custom_space.y;
19201  custom->w = (short)custom_space.w;
19202  custom->h = (short)custom_space.h;
19203  }
19204 
19205  /* first font pass: pack all glyphs */
19206  for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
19207  config_iter = config_iter->next) {
19208  it = config_iter;
19209  do {int n = 0;
19210  int glyph_count;
19211  const nk_rune *in_range;
19212  const struct nk_font_config *cfg = it;
19213  struct nk_font_bake_data *tmp = &baker->build[input_i++];
19214 
19215  /* count glyphs + ranges in current font */
19216  glyph_count = 0; range_count = 0;
19217  for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
19218  glyph_count += (int)(in_range[1] - in_range[0]) + 1;
19219  range_count++;
19220  }
19221 
19222  /* setup ranges */
19223  tmp->ranges = baker->ranges + range_n;
19224  tmp->range_count = (nk_rune)range_count;
19225  range_n += range_count;
19226  for (i = 0; i < range_count; ++i) {
19227  in_range = &cfg->range[i * 2];
19228  tmp->ranges[i].font_size = cfg->size;
19229  tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
19230  tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
19231  tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
19232  char_n += tmp->ranges[i].num_chars;
19233  }
19234 
19235  /* pack */
19236  tmp->rects = baker->rects + rect_n;
19237  rect_n += glyph_count;
19238  stbtt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
19239  n = stbtt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
19240  tmp->ranges, (int)tmp->range_count, tmp->rects);
19241  stbrp_pack_rects((struct stbrp_context*)baker->spc.pack_info, tmp->rects, (int)n);
19242 
19243  /* texture height */
19244  for (i = 0; i < n; ++i) {
19245  if (tmp->rects[i].was_packed)
19246  *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
19247  }
19248  } while ((it = it->n) != config_iter);
19249  }
19250  NK_ASSERT(rect_n == total_glyph_count);
19251  NK_ASSERT(char_n == total_glyph_count);
19252  NK_ASSERT(range_n == total_range_count);
19253  }
19254  *height = (int)nk_round_up_pow2((nk_uint)*height);
19255  *image_memory = (nk_size)(*width) * (nk_size)(*height);
19256  return nk_true;
19257 }
19271 NK_INTERN void
19272 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
19273  struct nk_font_glyph *glyphs, int glyphs_count,
19274  const struct nk_font_config *config_list, int font_count)
19275 {
19276  int input_i = 0;
19277  nk_rune glyph_n = 0;
19278  const struct nk_font_config *config_iter;
19279  const struct nk_font_config *it;
19280 
19281  NK_ASSERT(image_memory);
19282  NK_ASSERT(width);
19283  NK_ASSERT(height);
19284  NK_ASSERT(config_list);
19285  NK_ASSERT(baker);
19286  NK_ASSERT(font_count);
19287  NK_ASSERT(glyphs_count);
19288  if (!image_memory || !width || !height || !config_list ||
19289  !font_count || !glyphs || !glyphs_count)
19290  return;
19291 
19292  /* second font pass: render glyphs */
19293  nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
19294  baker->spc.pixels = (unsigned char*)image_memory;
19295  baker->spc.height = (int)height;
19296  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
19297  config_iter = config_iter->next) {
19298  it = config_iter;
19299  do {const struct nk_font_config *cfg = it;
19300  struct nk_font_bake_data *tmp = &baker->build[input_i++];
19301  stbtt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
19302  stbtt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges, (int)tmp->range_count, tmp->rects);
19303  } while ((it = it->n) != config_iter);
19304  } stbtt_PackEnd(&baker->spc);
19305 
19306  /* third pass: setup font and glyphs */
19307  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
19308  config_iter = config_iter->next) {
19309  it = config_iter;
19310  do {nk_size i = 0;
19311  int char_idx = 0;
19312  nk_rune glyph_count = 0;
19313  const struct nk_font_config *cfg = it;
19314  struct nk_font_bake_data *tmp = &baker->build[input_i++];
19315  struct nk_baked_font *dst_font = cfg->font;
19316 
19317  float font_scale = stbtt_ScaleForPixelHeight(&tmp->info, cfg->size);
19318  int unscaled_ascent, unscaled_descent, unscaled_line_gap;
19319  stbtt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
19320  &unscaled_line_gap);
19321 
19322  /* fill baked font */
19323  if (!cfg->merge_mode) {
19324  dst_font->ranges = cfg->range;
19325  dst_font->height = cfg->size;
19326  dst_font->ascent = ((float)unscaled_ascent * font_scale);
19327  dst_font->descent = ((float)unscaled_descent * font_scale);
19328  dst_font->glyph_offset = glyph_n;
19329  /*
19330  Need to zero this, or it will carry over from a previous
19331  bake, and cause a segfault when accessing glyphs[].
19332  */
19333  dst_font->glyph_count = 0;
19334  }
19335 
19336  /* fill own baked font glyph array */
19337  for (i = 0; i < tmp->range_count; ++i) {
19338  stbtt_pack_range *range = &tmp->ranges[i];
19339  for (char_idx = 0; char_idx < range->num_chars; char_idx++)
19340  {
19341  nk_rune codepoint = 0;
19342  float dummy_x = 0, dummy_y = 0;
19343  stbtt_aligned_quad q;
19344  struct nk_font_glyph *glyph;
19345 
19346  /* query glyph bounds from stb_truetype */
19347  const stbtt_packedchar *pc = &range->chardata_for_range[char_idx];
19348  codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
19349  stbtt_GetPackedQuad(range->chardata_for_range, (int)width,
19350  (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
19351 
19352  /* fill own glyph type with data */
19353  glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count];
19354  glyph->codepoint = codepoint;
19355  glyph->x0 = q.x0; glyph->y0 = q.y0;
19356  glyph->x1 = q.x1; glyph->y1 = q.y1;
19357  glyph->y0 += (dst_font->ascent + 0.5f);
19358  glyph->y1 += (dst_font->ascent + 0.5f);
19359  glyph->w = glyph->x1 - glyph->x0 + 0.5f;
19360  glyph->h = glyph->y1 - glyph->y0;
19361 
19362  if (cfg->coord_type == NK_COORD_PIXEL) {
19363  glyph->u0 = q.s0 * (float)width;
19364  glyph->v0 = q.t0 * (float)height;
19365  glyph->u1 = q.s1 * (float)width;
19366  glyph->v1 = q.t1 * (float)height;
19367  } else {
19368  glyph->u0 = q.s0;
19369  glyph->v0 = q.t0;
19370  glyph->u1 = q.s1;
19371  glyph->v1 = q.t1;
19372  }
19373  glyph->xadvance = (pc->xadvance + cfg->spacing.x);
19374  if (cfg->pixel_snap)
19375  glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
19376  glyph_count++;
19377  }
19378  }
19379  dst_font->glyph_count += glyph_count;
19380  glyph_n += glyph_count;
19381  } while ((it = it->n) != config_iter);
19382  }
19383 }
19396 NK_INTERN void
19397 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
19398  struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
19399  int tex_height, char white, char black)
19400 {
19401  nk_byte *pixels;
19402  int y = 0;
19403  int x = 0;
19404  int n = 0;
19405 
19406  NK_ASSERT(img_memory);
19407  NK_ASSERT(img_width);
19408  NK_ASSERT(img_height);
19409  NK_ASSERT(texture_data_mask);
19410  NK_UNUSED(tex_height);
19411  if (!img_memory || !img_width || !img_height || !texture_data_mask)
19412  return;
19413 
19414  pixels = (nk_byte*)img_memory;
19415  for (y = 0, n = 0; y < tex_height; ++y) {
19416  for (x = 0; x < tex_width; ++x, ++n) {
19417  const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
19418  const int off1 = off0 + 1 + tex_width;
19419  pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
19420  pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
19421  }
19422  }
19423 }
19436 NK_INTERN void
19437 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
19438  const void *in_memory)
19439 {
19440  int n = 0;
19441  nk_rune *dst;
19442  const nk_byte *src;
19443 
19444  NK_ASSERT(out_memory);
19445  NK_ASSERT(in_memory);
19446  NK_ASSERT(img_width);
19447  NK_ASSERT(img_height);
19448  if (!out_memory || !in_memory || !img_height || !img_width) return;
19449 
19450  dst = (nk_rune*)out_memory;
19451  src = (const nk_byte*)in_memory;
19452  for (n = (int)(img_width * img_height); n > 0; n--)
19453  *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
19454 }
19455 
19456 /* -------------------------------------------------------------
19457  *
19458  * FONT
19459  *
19460  * --------------------------------------------------------------*/
19474 NK_INTERN float
19475 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
19476 {
19477  nk_rune unicode;
19478  int text_len = 0;
19479  float text_width = 0;
19480  int glyph_len = 0;
19481  float scale = 0;
19482 
19483  struct nk_font *font = (struct nk_font*)handle.ptr;
19484  NK_ASSERT(font);
19485  NK_ASSERT(font->glyphs);
19486  if (!font || !text || !len)
19487  return 0;
19488 
19489  scale = height/font->info.height;
19490  glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
19491  if (!glyph_len) return 0;
19492  while (text_len <= (int)len && glyph_len) {
19493  const struct nk_font_glyph *g;
19494  if (unicode == NK_UTF_INVALID) break;
19495 
19496  /* query currently drawn glyph information */
19497  g = nk_font_find_glyph(font, unicode);
19498  text_width += g->xadvance * scale;
19499 
19500  /* offset next glyph */
19501  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
19502  text_len += glyph_len;
19503  }
19504  return text_width;
19505 }
19506 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
19518 NK_INTERN void
19519 nk_font_query_font_glyph(nk_handle handle, float height,
19520  struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
19521 {
19522  float scale;
19523  const struct nk_font_glyph *g;
19524  struct nk_font *font;
19525 
19526  NK_ASSERT(glyph);
19527  NK_UNUSED(next_codepoint);
19528 
19529  font = (struct nk_font*)handle.ptr;
19530  NK_ASSERT(font);
19531  NK_ASSERT(font->glyphs);
19532  if (!font || !glyph)
19533  return;
19534 
19535  scale = height/font->info.height;
19536  g = nk_font_find_glyph(font, codepoint);
19537  glyph->width = (g->x1 - g->x0) * scale;
19538  glyph->height = (g->y1 - g->y0) * scale;
19539  glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
19540  glyph->xadvance = (g->xadvance * scale);
19541  glyph->uv[0] = nk_vec2(g->u0, g->v0);
19542  glyph->uv[1] = nk_vec2(g->u1, g->v1);
19543 }
19544 #endif
19556 NK_API const struct nk_font_glyph*
19557 nk_font_find_glyph(const struct nk_font *font, nk_rune unicode)
19558 {
19559  int i = 0;
19560  int count;
19561  int total_glyphs = 0;
19562  const struct nk_font_glyph *glyph = 0;
19563  const struct nk_font_config *iter = 0;
19564 
19565  NK_ASSERT(font);
19566  NK_ASSERT(font->glyphs);
19567  NK_ASSERT(font->info.ranges);
19568  if (!font || !font->glyphs) return 0;
19569 
19570  glyph = font->fallback;
19571  iter = font->config;
19572  do {count = nk_range_count(iter->range);
19573  for (i = 0; i < count; ++i) {
19574  nk_rune f = iter->range[(i*2)+0];
19575  nk_rune t = iter->range[(i*2)+1];
19576  int diff = (int)((t - f) + 1);
19577  if (unicode >= f && unicode <= t)
19578  return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
19579  total_glyphs += diff;
19580  }
19581  } while ((iter = iter->n) != font->config);
19582  return glyph;
19583 }
19595 NK_INTERN void
19596 nk_font_init(struct nk_font *font, float pixel_height,
19597  nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
19598  const struct nk_baked_font *baked_font, nk_handle atlas)
19599 {
19600  struct nk_baked_font baked;
19601  NK_ASSERT(font);
19602  NK_ASSERT(glyphs);
19603  NK_ASSERT(baked_font);
19604  if (!font || !glyphs || !baked_font)
19605  return;
19606 
19607  baked = *baked_font;
19608  font->fallback = 0;
19609  font->info = baked;
19610  font->scale = (float)pixel_height / (float)font->info.height;
19611  font->glyphs = &glyphs[baked_font->glyph_offset];
19612  font->texture = atlas;
19613  font->fallback_codepoint = fallback_codepoint;
19614  font->fallback = nk_font_find_glyph(font, fallback_codepoint);
19615 
19616  font->handle.height = font->info.height * font->scale;
19617  font->handle.width = nk_font_text_width;
19618  font->handle.userdata.ptr = font;
19619 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
19620  font->handle.query = nk_font_query_font_glyph;
19621  font->handle.texture = font->texture;
19622 #endif
19623 }
19624 
19625 /* ---------------------------------------------------------------------------
19626  *
19627  * DEFAULT FONT
19628  *
19629  * ProggyClean.ttf
19630  * Copyright (c) 2004, 2005 Tristan Grimmer
19631  * MIT license https://github.com/bluescan/proggyfonts/blob/master/LICENSE
19632  * Download and more information at https://github.com/bluescan/proggyfonts
19633  *-----------------------------------------------------------------------------*/
19634 #ifdef __clang__
19635 #pragma clang diagnostic push
19636 #pragma clang diagnostic ignored "-Woverlength-strings"
19637 #elif defined(__GNUC__) || defined(__GNUG__)
19638 #pragma GCC diagnostic push
19639 #pragma GCC diagnostic ignored "-Woverlength-strings"
19640 #endif
19641 
19642 #ifdef NK_INCLUDE_DEFAULT_FONT
19643 
19644 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
19645  "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
19646  "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#"
19647  "`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"
19648  "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"
19649  "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"
19650  "*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)"
19651  "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"
19652  "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."
19653  "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"
19654  "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(,)"
19655  "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#"
19656  "'/###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"
19657  "_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"
19658  "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/"
19659  "/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"
19660  "%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&#"
19661  "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)("
19662  "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"
19663  "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"
19664  "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^-"
19665  "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-"
19666  "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"
19667  "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%"
19668  "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]"
19669  "%(?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"
19670  "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:"
19671  "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("
19672  "$/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<"
19673  "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'?"
19674  "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/;"
19675  ")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"
19676  "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("
19677  "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"
19678  "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
19679  "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<-"
19680  "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"
19681  "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"
19682  ".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@@"
19683  "$&)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*"
19684  "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"
19685  "@-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&#"
19686  "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#"
19687  "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"
19688  "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"
19689  "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&#"
19690  "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"
19691  ":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+"
19692  "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*"
19693  "$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"
19694  ":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"
19695  "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"
19696  "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"
19697  "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"
19698  ":^#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@&]>"
19699  "_>@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%"
19700  "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;"
19701  "^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:"
19702  "+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%"
19703  "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-"
19704  "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*"
19705  "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"
19706  "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
19707  "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`"
19708  "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]%/"
19709  "+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"
19710  "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"
19711  "?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"
19712  "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"
19713  ">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'>"
19714  "[%$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"
19715  "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#"
19716  "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$"
19717  "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,)"
19718  "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"
19719  "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"
19720  "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"
19721  "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(#"
19722  ";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&>"
19723  "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#"
19724  "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"
19725  "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#"
19726  "/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-#"
19727  "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#"
19728  "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
19729  "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
19730  "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
19731 
19732 #endif /* NK_INCLUDE_DEFAULT_FONT */
19733 
19734 #define NK_CURSOR_DATA_W 90
19735 #define NK_CURSOR_DATA_H 27
19736 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
19737 {
19738  "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX"
19739  "..- -X.....X- X.X - X.X -X.....X - X.....X"
19740  "--- -XXX.XXX- X...X - X...X -X....X - X....X"
19741  "X - X.X - X.....X - X.....X -X...X - X...X"
19742  "XX - X.X -X.......X- X.......X -X..X.X - X.X..X"
19743  "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X"
19744  "X..X - X.X - X.X - X.X -XX X.X - X.X XX"
19745  "X...X - X.X - X.X - XX X.X XX - X.X - X.X "
19746  "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X "
19747  "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X "
19748  "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X "
19749  "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X "
19750  "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X "
19751  "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X "
19752  "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X "
19753  "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X "
19754  "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX "
19755  "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------"
19756  "X.X X..X - -X.......X- X.......X - XX XX - "
19757  "XX X..X - - X.....X - X.....X - X.X X.X - "
19758  " X..X - X...X - X...X - X..X X..X - "
19759  " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - "
19760  "------------ - X - X -X.....................X- "
19761  " ----------------------------------- X...XXXXXXXXXXXXX...X - "
19762  " - X..X X..X - "
19763  " - X.X X.X - "
19764  " - XX XX - "
19765 };
19766 
19767 #ifdef __clang__
19768 #pragma clang diagnostic pop
19769 #elif defined(__GNUC__) || defined(__GNUG__)
19770 #pragma GCC diagnostic pop
19771 #endif
19772 
19773 NK_GLOBAL unsigned char *nk__barrier;
19774 NK_GLOBAL unsigned char *nk__barrier2;
19775 NK_GLOBAL unsigned char *nk__barrier3;
19776 NK_GLOBAL unsigned char *nk__barrier4;
19777 NK_GLOBAL unsigned char *nk__dout;
19778 
19789 NK_INTERN unsigned int
19790 nk_decompress_length(unsigned char *input)
19791 {
19792  return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
19793 }
19805 NK_INTERN void
19806 nk__match(unsigned char *data, unsigned int length)
19807 {
19808  /* INVERSE of memmove... write each byte before copying the next...*/
19809  NK_ASSERT (nk__dout + length <= nk__barrier);
19810  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
19811  if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
19812  while (length--) *nk__dout++ = *data++;
19813 }
19825 NK_INTERN void
19826 nk__lit(unsigned char *data, unsigned int length)
19827 {
19828  NK_ASSERT (nk__dout + length <= nk__barrier);
19829  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
19830  if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
19831  NK_MEMCPY(nk__dout, data, length);
19832  nk__dout += length;
19833 }
19844 NK_INTERN unsigned char*
19845 nk_decompress_token(unsigned char *i)
19846 {
19847  #define nk__in2(x) ((i[x] << 8) + i[(x)+1])
19848  #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1))
19849  #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1))
19850 
19851  if (*i >= 0x20) { /* use fewer if's for cases that expand small */
19852  if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
19853  else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
19854  else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
19855  } else { /* more ifs for cases that expand large, since overhead is amortized */
19856  if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
19857  else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
19858  else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
19859  else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
19860  else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
19861  else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
19862  }
19863  return i;
19864 }
19877 NK_INTERN unsigned int
19878 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
19879 {
19880  const unsigned long ADLER_MOD = 65521;
19881  unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
19882  unsigned long blocklen, i;
19883 
19884  blocklen = buflen % 5552;
19885  while (buflen) {
19886  for (i=0; i + 7 < blocklen; i += 8) {
19887  s1 += buffer[0]; s2 += s1;
19888  s1 += buffer[1]; s2 += s1;
19889  s1 += buffer[2]; s2 += s1;
19890  s1 += buffer[3]; s2 += s1;
19891  s1 += buffer[4]; s2 += s1;
19892  s1 += buffer[5]; s2 += s1;
19893  s1 += buffer[6]; s2 += s1;
19894  s1 += buffer[7]; s2 += s1;
19895  buffer += 8;
19896  }
19897  for (; i < blocklen; ++i) {
19898  s1 += *buffer++; s2 += s1;
19899  }
19900 
19901  s1 %= ADLER_MOD; s2 %= ADLER_MOD;
19902  buflen -= (unsigned int)blocklen;
19903  blocklen = 5552;
19904  }
19905  return (unsigned int)(s2 << 16) + (unsigned int)s1;
19906 }
19919 NK_INTERN unsigned int
19920 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
19921 {
19922  unsigned int olen;
19923  if (nk__in4(0) != 0x57bC0000) return 0;
19924  if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */
19925  olen = nk_decompress_length(i);
19926  nk__barrier2 = i;
19927  nk__barrier3 = i+length;
19928  nk__barrier = output + olen;
19929  nk__barrier4 = output;
19930  i += 16;
19931 
19932  nk__dout = output;
19933  for (;;) {
19934  unsigned char *old_i = i;
19935  i = nk_decompress_token(i);
19936  if (i == old_i) {
19937  if (*i == 0x05 && i[1] == 0xfa) {
19938  NK_ASSERT(nk__dout == output + olen);
19939  if (nk__dout != output + olen) return 0;
19940  if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
19941  return 0;
19942  return olen;
19943  } else {
19944  NK_ASSERT(0); /* NOTREACHED */
19945  return 0;
19946  }
19947  }
19948  NK_ASSERT(nk__dout <= output + olen);
19949  if (nk__dout > output + olen)
19950  return 0;
19951  }
19952 }
19963 NK_INTERN unsigned int
19964 nk_decode_85_byte(char c)
19965 {
19966  return (unsigned int)((c >= '\\') ? c-36 : c-35);
19967 }
19979 NK_INTERN void
19980 nk_decode_85(unsigned char* dst, const unsigned char* src)
19981 {
19982  while (*src)
19983  {
19984  unsigned int tmp =
19985  nk_decode_85_byte((char)src[0]) +
19986  85 * (nk_decode_85_byte((char)src[1]) +
19987  85 * (nk_decode_85_byte((char)src[2]) +
19988  85 * (nk_decode_85_byte((char)src[3]) +
19989  85 * nk_decode_85_byte((char)src[4]))));
19990 
19991  /* we can't assume little-endianess. */
19992  dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
19993  dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
19994  dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
19995  dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
19996 
19997  src += 5;
19998  dst += 4;
19999  }
20000 }
20001 
20002 /* -------------------------------------------------------------
20003  *
20004  * FONT ATLAS
20005  *
20006  * --------------------------------------------------------------*/
20017 NK_API struct nk_font_config
20018 nk_font_config(float pixel_height)
20019 {
20020  struct nk_font_config cfg;
20021  nk_zero_struct(cfg);
20022  cfg.ttf_blob = 0;
20023  cfg.ttf_size = 0;
20024  cfg.ttf_data_owned_by_atlas = 0;
20025  cfg.size = pixel_height;
20026  cfg.oversample_h = 3;
20027  cfg.oversample_v = 1;
20028  cfg.pixel_snap = 0;
20029  cfg.coord_type = NK_COORD_UV;
20030  cfg.spacing = nk_vec2(0,0);
20031  cfg.range = nk_font_default_glyph_ranges();
20032  cfg.merge_mode = 0;
20033  cfg.fallback_glyph = '?';
20034  cfg.font = 0;
20035  cfg.n = 0;
20036  return cfg;
20037 }
20038 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
20049 NK_API void
20050 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
20051 {
20052  NK_ASSERT(atlas);
20053  if (!atlas) return;
20054  nk_zero_struct(*atlas);
20055  atlas->temporary.userdata.ptr = 0;
20056  atlas->temporary.alloc = nk_malloc;
20057  atlas->temporary.free = nk_mfree;
20058  atlas->permanent.userdata.ptr = 0;
20059  atlas->permanent.alloc = nk_malloc;
20060  atlas->permanent.free = nk_mfree;
20061 }
20062 #endif
20074 NK_API void
20075 nk_font_atlas_init(struct nk_font_atlas *atlas, const struct nk_allocator *alloc)
20076 {
20077  NK_ASSERT(atlas);
20078  NK_ASSERT(alloc);
20079  if (!atlas || !alloc) return;
20080  nk_zero_struct(*atlas);
20081  atlas->permanent = *alloc;
20082  atlas->temporary = *alloc;
20083 }
20094 NK_API void
20095 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
20096  const struct nk_allocator *permanent, const struct nk_allocator *temporary)
20097 {
20098  NK_ASSERT(atlas);
20099  NK_ASSERT(permanent);
20100  NK_ASSERT(temporary);
20101  if (!atlas || !permanent || !temporary) return;
20102  nk_zero_struct(*atlas);
20103  atlas->permanent = *permanent;
20104  atlas->temporary = *temporary;
20105 }
20116 NK_API void
20117 nk_font_atlas_begin(struct nk_font_atlas *atlas)
20118 {
20119  NK_ASSERT(atlas);
20120  NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
20121  NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
20122  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
20123  !atlas->temporary.alloc || !atlas->temporary.free) return;
20124  if (atlas->glyphs) {
20125  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
20126  atlas->glyphs = 0;
20127  }
20128  if (atlas->pixel) {
20129  atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
20130  atlas->pixel = 0;
20131  }
20132 }
20144 NK_API struct nk_font*
20145 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
20146 {
20147  struct nk_font *font = 0;
20148  struct nk_font_config *cfg;
20149 
20150  NK_ASSERT(atlas);
20151  NK_ASSERT(atlas->permanent.alloc);
20152  NK_ASSERT(atlas->permanent.free);
20153  NK_ASSERT(atlas->temporary.alloc);
20154  NK_ASSERT(atlas->temporary.free);
20155 
20156  NK_ASSERT(config);
20157  NK_ASSERT(config->ttf_blob);
20158  NK_ASSERT(config->ttf_size);
20159  NK_ASSERT(config->size > 0.0f);
20160 
20161  if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
20162  !atlas->permanent.alloc || !atlas->permanent.free ||
20163  !atlas->temporary.alloc || !atlas->temporary.free)
20164  return 0;
20165 
20166  /* allocate font config */
20167  cfg = (struct nk_font_config*)
20168  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
20169  NK_MEMCPY(cfg, config, sizeof(*config));
20170  cfg->n = cfg;
20171  cfg->p = cfg;
20172 
20173  if (!config->merge_mode) {
20174  /* insert font config into list */
20175  if (!atlas->config) {
20176  atlas->config = cfg;
20177  cfg->next = 0;
20178  } else {
20179  struct nk_font_config *i = atlas->config;
20180  while (i->next) i = i->next;
20181  i->next = cfg;
20182  cfg->next = 0;
20183  }
20184  /* allocate new font */
20185  font = (struct nk_font*)
20186  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
20187  NK_ASSERT(font);
20188  nk_zero(font, sizeof(*font));
20189  if (!font) return 0;
20190  font->config = cfg;
20191 
20192  /* insert font into list */
20193  if (!atlas->fonts) {
20194  atlas->fonts = font;
20195  font->next = 0;
20196  } else {
20197  struct nk_font *i = atlas->fonts;
20198  while (i->next) i = i->next;
20199  i->next = font;
20200  font->next = 0;
20201  }
20202  cfg->font = &font->info;
20203  } else {
20204  /* extend previously added font */
20205  struct nk_font *f = 0;
20206  struct nk_font_config *c = 0;
20207  NK_ASSERT(atlas->font_num);
20208  f = atlas->fonts;
20209  c = f->config;
20210  cfg->font = &f->info;
20211 
20212  cfg->n = c;
20213  cfg->p = c->p;
20214  c->p->n = cfg;
20215  c->p = cfg;
20216  }
20217  /* create own copy of .TTF font blob */
20218  if (!config->ttf_data_owned_by_atlas) {
20219  cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
20220  NK_ASSERT(cfg->ttf_blob);
20221  if (!cfg->ttf_blob) {
20222  atlas->font_num++;
20223  return 0;
20224  }
20225  NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
20226  cfg->ttf_data_owned_by_atlas = 1;
20227  }
20228  atlas->font_num++;
20229  return font;
20230 }
20242 NK_API struct nk_font*
20243 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
20244  nk_size size, float height, const struct nk_font_config *config)
20245 {
20246  struct nk_font_config cfg;
20247  NK_ASSERT(memory);
20248  NK_ASSERT(size);
20249 
20250  NK_ASSERT(atlas);
20251  NK_ASSERT(atlas->temporary.alloc);
20252  NK_ASSERT(atlas->temporary.free);
20253  NK_ASSERT(atlas->permanent.alloc);
20254  NK_ASSERT(atlas->permanent.free);
20255  if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
20256  !atlas->permanent.alloc || !atlas->permanent.free)
20257  return 0;
20258 
20259  cfg = (config) ? *config: nk_font_config(height);
20260  cfg.ttf_blob = memory;
20261  cfg.ttf_size = size;
20262  cfg.size = height;
20263  cfg.ttf_data_owned_by_atlas = 0;
20264  return nk_font_atlas_add(atlas, &cfg);
20265 }
20266 #ifdef NK_INCLUDE_STANDARD_IO
20278 NK_API struct nk_font*
20279 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
20280  float height, const struct nk_font_config *config)
20281 {
20282  nk_size size;
20283  char *memory;
20284  struct nk_font_config cfg;
20285 
20286  NK_ASSERT(atlas);
20287  NK_ASSERT(atlas->temporary.alloc);
20288  NK_ASSERT(atlas->temporary.free);
20289  NK_ASSERT(atlas->permanent.alloc);
20290  NK_ASSERT(atlas->permanent.free);
20291 
20292  if (!atlas || !file_path) return 0;
20293  memory = nk_file_load(file_path, &size, &atlas->permanent);
20294  if (!memory) return 0;
20295 
20296  cfg = (config) ? *config: nk_font_config(height);
20297  cfg.ttf_blob = memory;
20298  cfg.ttf_size = size;
20299  cfg.size = height;
20300  cfg.ttf_data_owned_by_atlas = 1;
20301  return nk_font_atlas_add(atlas, &cfg);
20302 }
20303 #endif
20314 NK_API struct nk_font*
20315 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
20316  void *compressed_data, nk_size compressed_size, float height,
20317  const struct nk_font_config *config)
20318 {
20319  unsigned int decompressed_size;
20320  void *decompressed_data;
20321  struct nk_font_config cfg;
20322 
20323  NK_ASSERT(atlas);
20324  NK_ASSERT(atlas->temporary.alloc);
20325  NK_ASSERT(atlas->temporary.free);
20326  NK_ASSERT(atlas->permanent.alloc);
20327  NK_ASSERT(atlas->permanent.free);
20328 
20329  NK_ASSERT(compressed_data);
20330  NK_ASSERT(compressed_size);
20331  if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
20332  !atlas->permanent.alloc || !atlas->permanent.free)
20333  return 0;
20334 
20335  decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
20336  decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
20337  NK_ASSERT(decompressed_data);
20338  if (!decompressed_data) return 0;
20339  nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
20340  (unsigned int)compressed_size);
20341 
20342  cfg = (config) ? *config: nk_font_config(height);
20343  cfg.ttf_blob = decompressed_data;
20344  cfg.ttf_size = decompressed_size;
20345  cfg.size = height;
20346  cfg.ttf_data_owned_by_atlas = 1;
20347  return nk_font_atlas_add(atlas, &cfg);
20348 }
20359 NK_API struct nk_font*
20360 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
20361  const char *data_base85, float height, const struct nk_font_config *config)
20362 {
20363  int compressed_size;
20364  void *compressed_data;
20365  struct nk_font *font;
20366 
20367  NK_ASSERT(atlas);
20368  NK_ASSERT(atlas->temporary.alloc);
20369  NK_ASSERT(atlas->temporary.free);
20370  NK_ASSERT(atlas->permanent.alloc);
20371  NK_ASSERT(atlas->permanent.free);
20372 
20373  NK_ASSERT(data_base85);
20374  if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
20375  !atlas->permanent.alloc || !atlas->permanent.free)
20376  return 0;
20377 
20378  compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
20379  compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
20380  NK_ASSERT(compressed_data);
20381  if (!compressed_data) return 0;
20382  nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
20383  font = nk_font_atlas_add_compressed(atlas, compressed_data,
20384  (nk_size)compressed_size, height, config);
20385  atlas->temporary.free(atlas->temporary.userdata, compressed_data);
20386  return font;
20387 }
20388 
20389 #ifdef NK_INCLUDE_DEFAULT_FONT
20400 NK_API struct nk_font*
20401 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
20402  float pixel_height, const struct nk_font_config *config)
20403 {
20404  NK_ASSERT(atlas);
20405  NK_ASSERT(atlas->temporary.alloc);
20406  NK_ASSERT(atlas->temporary.free);
20407  NK_ASSERT(atlas->permanent.alloc);
20408  NK_ASSERT(atlas->permanent.free);
20409  return nk_font_atlas_add_compressed_base85(atlas,
20410  nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
20411 }
20412 #endif
20425 NK_API const void*
20426 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
20427  enum nk_font_atlas_format fmt)
20428 {
20429  int i = 0;
20430  void *tmp = 0;
20431  nk_size tmp_size, img_size;
20432  struct nk_font *font_iter;
20433  struct nk_font_baker *baker;
20434 
20435  NK_ASSERT(atlas);
20436  NK_ASSERT(atlas->temporary.alloc);
20437  NK_ASSERT(atlas->temporary.free);
20438  NK_ASSERT(atlas->permanent.alloc);
20439  NK_ASSERT(atlas->permanent.free);
20440 
20441  NK_ASSERT(width);
20442  NK_ASSERT(height);
20443  if (!atlas || !width || !height ||
20444  !atlas->temporary.alloc || !atlas->temporary.free ||
20445  !atlas->permanent.alloc || !atlas->permanent.free)
20446  return 0;
20447 
20448 #ifdef NK_INCLUDE_DEFAULT_FONT
20449  /* no font added so just use default font */
20450  if (!atlas->font_num)
20451  atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
20452 #endif
20453  NK_ASSERT(atlas->font_num);
20454  if (!atlas->font_num) return 0;
20455 
20456  /* allocate temporary baker memory required for the baking process */
20457  nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
20458  tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
20459  NK_ASSERT(tmp);
20460  if (!tmp) goto failed;
20461  NK_MEMSET(tmp,0,tmp_size);
20462 
20463  /* allocate glyph memory for all fonts */
20464  baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
20465  atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
20466  atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
20467  NK_ASSERT(atlas->glyphs);
20468  if (!atlas->glyphs)
20469  goto failed;
20470 
20471  /* pack all glyphs into a tight fit space */
20472  atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
20473  atlas->custom.h = NK_CURSOR_DATA_H + 1;
20474  if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
20475  atlas->config, atlas->font_num, &atlas->temporary))
20476  goto failed;
20477 
20478  /* allocate memory for the baked image font atlas */
20479  atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
20480  NK_ASSERT(atlas->pixel);
20481  if (!atlas->pixel)
20482  goto failed;
20483 
20484  /* bake glyphs and custom white pixel into image */
20485  nk_font_bake(baker, atlas->pixel, *width, *height,
20486  atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
20487  nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
20488  nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
20489 
20490  if (fmt == NK_FONT_ATLAS_RGBA32) {
20491  /* convert alpha8 image into rgba32 image */
20492  void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
20493  (nk_size)(*width * *height * 4));
20494  NK_ASSERT(img_rgba);
20495  if (!img_rgba) goto failed;
20496  nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
20497  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
20498  atlas->pixel = img_rgba;
20499  }
20500  atlas->tex_width = *width;
20501  atlas->tex_height = *height;
20502 
20503  /* initialize each font */
20504  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
20505  struct nk_font *font = font_iter;
20506  struct nk_font_config *config = font->config;
20507  nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
20508  config->font, nk_handle_ptr(0));
20509  }
20510 
20511  /* initialize each cursor */
20512  {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
20513  /* Pos Size Offset */
20514  {{ 0, 3}, {12,19}, { 0, 0}},
20515  {{13, 0}, { 7,16}, { 4, 8}},
20516  {{31, 0}, {23,23}, {11,11}},
20517  {{21, 0}, { 9, 23}, { 5,11}},
20518  {{55,18}, {23, 9}, {11, 5}},
20519  {{73, 0}, {17,17}, { 9, 9}},
20520  {{55, 0}, {17,17}, { 9, 9}}
20521  };
20522  for (i = 0; i < NK_CURSOR_COUNT; ++i) {
20523  struct nk_cursor *cursor = &atlas->cursors[i];
20524  cursor->img.w = (unsigned short)*width;
20525  cursor->img.h = (unsigned short)*height;
20526  cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
20527  cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
20528  cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
20529  cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
20530  cursor->size = nk_cursor_data[i][1];
20531  cursor->offset = nk_cursor_data[i][2];
20532  }}
20533  /* free temporary memory */
20534  atlas->temporary.free(atlas->temporary.userdata, tmp);
20535  return atlas->pixel;
20536 
20537 failed:
20538  /* error so cleanup all memory */
20539  if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
20540  if (atlas->glyphs) {
20541  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
20542  atlas->glyphs = 0;
20543  }
20544  if (atlas->pixel) {
20545  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
20546  atlas->pixel = 0;
20547  }
20548  return 0;
20549 }
20561 NK_API void
20562 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
20563  struct nk_draw_null_texture *tex_null)
20564 {
20565  int i = 0;
20566  struct nk_font *font_iter;
20567  NK_ASSERT(atlas);
20568  if (!atlas) {
20569  if (!tex_null) return;
20570  tex_null->texture = texture;
20571  tex_null->uv = nk_vec2(0.5f,0.5f);
20572  }
20573  if (tex_null) {
20574  tex_null->texture = texture;
20575  tex_null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
20576  tex_null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
20577  }
20578  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
20579  font_iter->texture = texture;
20580 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
20581  font_iter->handle.texture = texture;
20582 #endif
20583  }
20584  for (i = 0; i < NK_CURSOR_COUNT; ++i)
20585  atlas->cursors[i].img.handle = texture;
20586 
20587  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
20588  atlas->pixel = 0;
20589  atlas->tex_width = 0;
20590  atlas->tex_height = 0;
20591  atlas->custom.x = 0;
20592  atlas->custom.y = 0;
20593  atlas->custom.w = 0;
20594  atlas->custom.h = 0;
20595 }
20606 NK_API void
20607 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
20608 {
20609  NK_ASSERT(atlas);
20610  NK_ASSERT(atlas->temporary.alloc);
20611  NK_ASSERT(atlas->temporary.free);
20612  NK_ASSERT(atlas->permanent.alloc);
20613  NK_ASSERT(atlas->permanent.free);
20614  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
20615  if (atlas->config) {
20616  struct nk_font_config *iter;
20617  for (iter = atlas->config; iter; iter = iter->next) {
20618  struct nk_font_config *i;
20619  for (i = iter->n; i != iter; i = i->n) {
20620  atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
20621  i->ttf_blob = 0;
20622  }
20623  atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
20624  iter->ttf_blob = 0;
20625  }
20626  }
20627 }
20638 NK_API void
20639 nk_font_atlas_clear(struct nk_font_atlas *atlas)
20640 {
20641  NK_ASSERT(atlas);
20642  NK_ASSERT(atlas->temporary.alloc);
20643  NK_ASSERT(atlas->temporary.free);
20644  NK_ASSERT(atlas->permanent.alloc);
20645  NK_ASSERT(atlas->permanent.free);
20646  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
20647 
20648  if (atlas->config) {
20649  struct nk_font_config *iter, *next;
20650  for (iter = atlas->config; iter; iter = next) {
20651  struct nk_font_config *i, *n;
20652  for (i = iter->n; i != iter; i = n) {
20653  n = i->n;
20654  if (i->ttf_blob)
20655  atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob);
20656  atlas->permanent.free(atlas->permanent.userdata, i);
20657  }
20658  next = iter->next;
20659  if (i->ttf_blob)
20660  atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
20661  atlas->permanent.free(atlas->permanent.userdata, iter);
20662  }
20663  atlas->config = 0;
20664  }
20665  if (atlas->fonts) {
20666  struct nk_font *iter, *next;
20667  for (iter = atlas->fonts; iter; iter = next) {
20668  next = iter->next;
20669  atlas->permanent.free(atlas->permanent.userdata, iter);
20670  }
20671  atlas->fonts = 0;
20672  }
20673  if (atlas->glyphs)
20674  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
20675  nk_zero_struct(*atlas);
20676 }
20677 #endif
20678 
20679 
20680 
20681 
20682 /* ===============================================================
20683  *
20684  * INPUT
20685  *
20686  * ===============================================================*/
20697 NK_API void
20698 nk_input_begin(struct nk_context *ctx)
20699 {
20700  int i;
20701  struct nk_input *in;
20702  NK_ASSERT(ctx);
20703  if (!ctx) return;
20704  in = &ctx->input;
20705  for (i = 0; i < NK_BUTTON_MAX; ++i)
20706  in->mouse.buttons[i].clicked = 0;
20707 
20708  in->keyboard.text_len = 0;
20709  in->mouse.scroll_delta = nk_vec2(0,0);
20710  in->mouse.prev.x = in->mouse.pos.x;
20711  in->mouse.prev.y = in->mouse.pos.y;
20712  in->mouse.delta.x = 0;
20713  in->mouse.delta.y = 0;
20714  for (i = 0; i < NK_KEY_MAX; i++)
20715  in->keyboard.keys[i].clicked = 0;
20716 }
20727 NK_API void
20728 nk_input_end(struct nk_context *ctx)
20729 {
20730  struct nk_input *in;
20731  NK_ASSERT(ctx);
20732  if (!ctx) return;
20733  in = &ctx->input;
20734  if (in->mouse.grab)
20735  in->mouse.grab = 0;
20736  if (in->mouse.ungrab) {
20737  in->mouse.grabbed = 0;
20738  in->mouse.ungrab = 0;
20739  in->mouse.grab = 0;
20740  }
20741 }
20754 NK_API void
20755 nk_input_motion(struct nk_context *ctx, int x, int y)
20756 {
20757  struct nk_input *in;
20758  NK_ASSERT(ctx);
20759  if (!ctx) return;
20760  in = &ctx->input;
20761  in->mouse.pos.x = (float)x;
20762  in->mouse.pos.y = (float)y;
20763  in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
20764  in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
20765 }
20778 NK_API void
20779 nk_input_key(struct nk_context *ctx, enum nk_keys key, nk_bool down)
20780 {
20781  struct nk_input *in;
20782  NK_ASSERT(ctx);
20783  if (!ctx) return;
20784  in = &ctx->input;
20785 #ifdef NK_KEYSTATE_BASED_INPUT
20786  if (in->keyboard.keys[key].down != down)
20787  in->keyboard.keys[key].clicked++;
20788 #else
20789  in->keyboard.keys[key].clicked++;
20790 #endif
20791  in->keyboard.keys[key].down = down;
20792 }
20807 NK_API void
20808 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, nk_bool down)
20809 {
20810  struct nk_mouse_button *btn;
20811  struct nk_input *in;
20812  NK_ASSERT(ctx);
20813  if (!ctx) return;
20814  in = &ctx->input;
20815  if (in->mouse.buttons[id].down == down) return;
20816 
20817  btn = &in->mouse.buttons[id];
20818  btn->clicked_pos.x = (float)x;
20819  btn->clicked_pos.y = (float)y;
20820  btn->down = down;
20821  btn->clicked++;
20822 
20823  /* Fix Click-Drag for touch events. */
20824  in->mouse.delta.x = 0;
20825  in->mouse.delta.y = 0;
20826 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
20827  if (down == 1 && id == NK_BUTTON_LEFT)
20828  {
20829  in->mouse.down_pos.x = btn->clicked_pos.x;
20830  in->mouse.down_pos.y = btn->clicked_pos.y;
20831  }
20832 #endif
20833 }
20845 NK_API void
20846 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
20847 {
20848  NK_ASSERT(ctx);
20849  if (!ctx) return;
20850  ctx->input.mouse.scroll_delta.x += val.x;
20851  ctx->input.mouse.scroll_delta.y += val.y;
20852 }
20864 NK_API void
20865 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
20866 {
20867  int len = 0;
20868  nk_rune unicode;
20869  struct nk_input *in;
20870 
20871  NK_ASSERT(ctx);
20872  if (!ctx) return;
20873  in = &ctx->input;
20874 
20875  len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
20876  if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
20877  nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
20878  NK_INPUT_MAX - in->keyboard.text_len);
20879  in->keyboard.text_len += len;
20880  }
20881 }
20893 NK_API void
20894 nk_input_char(struct nk_context *ctx, char c)
20895 {
20896  nk_glyph glyph;
20897  NK_ASSERT(ctx);
20898  if (!ctx) return;
20899  glyph[0] = c;
20900  nk_input_glyph(ctx, glyph);
20901 }
20913 NK_API void
20914 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
20915 {
20916  nk_glyph rune;
20917  NK_ASSERT(ctx);
20918  if (!ctx) return;
20919  nk_utf_encode(unicode, rune, NK_UTF_SIZE);
20920  nk_input_glyph(ctx, rune);
20921 }
20933 NK_API nk_bool
20934 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
20935 {
20936  const struct nk_mouse_button *btn;
20937  if (!i) return nk_false;
20938  btn = &i->mouse.buttons[id];
20939  return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
20940 }
20952 NK_API nk_bool
20953 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
20954  struct nk_rect b)
20955 {
20956  const struct nk_mouse_button *btn;
20957  if (!i) return nk_false;
20958  btn = &i->mouse.buttons[id];
20959  if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
20960  return nk_false;
20961  return nk_true;
20962 }
20974 NK_API nk_bool
20975 nk_input_has_mouse_click_in_button_rect(const struct nk_input *i, enum nk_buttons id,
20976  struct nk_rect b)
20977 {
20978  const struct nk_mouse_button *btn;
20979  if (!i) return nk_false;
20980  btn = &i->mouse.buttons[id];
20981 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
20982  if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)
20983  || !NK_INBOX(i->mouse.down_pos.x,i->mouse.down_pos.y,b.x,b.y,b.w,b.h))
20984 #else
20985  if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
20986 #endif
20987  return nk_false;
20988  return nk_true;
20989 }
21001 NK_API nk_bool
21002 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
21003  struct nk_rect b, nk_bool down)
21004 {
21005  const struct nk_mouse_button *btn;
21006  if (!i) return nk_false;
21007  btn = &i->mouse.buttons[id];
21008  return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
21009 }
21021 NK_API nk_bool
21022 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
21023  struct nk_rect b)
21024 {
21025  const struct nk_mouse_button *btn;
21026  if (!i) return nk_false;
21027  btn = &i->mouse.buttons[id];
21028  return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
21029  btn->clicked) ? nk_true : nk_false;
21030 }
21042 NK_API nk_bool
21043 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id,
21044  struct nk_rect b, nk_bool down)
21045 {
21046  const struct nk_mouse_button *btn;
21047  if (!i) return nk_false;
21048  btn = &i->mouse.buttons[id];
21049  return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
21050  btn->clicked) ? nk_true : nk_false;
21051 }
21063 NK_API nk_bool
21064 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
21065 {
21066  int i, down = 0;
21067  for (i = 0; i < NK_BUTTON_MAX; ++i)
21068  down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
21069  return down;
21070 }
21082 NK_API nk_bool
21083 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
21084 {
21085  if (!i) return nk_false;
21086  return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
21087 }
21099 NK_API nk_bool
21100 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
21101 {
21102  if (!i) return nk_false;
21103  return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
21104 }
21117 NK_API nk_bool
21118 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
21119 {
21120  if (!i) return nk_false;
21121  if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
21122  return nk_input_is_mouse_click_in_rect(i, id, rect);
21123 }
21135 NK_API nk_bool
21136 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
21137 {
21138  if (!i) return nk_false;
21139  return i->mouse.buttons[id].down;
21140 }
21152 NK_API nk_bool
21153 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
21154 {
21155  const struct nk_mouse_button *b;
21156  if (!i) return nk_false;
21157  b = &i->mouse.buttons[id];
21158  if (b->down && b->clicked)
21159  return nk_true;
21160  return nk_false;
21161 }
21173 NK_API nk_bool
21174 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
21175 {
21176  if (!i) return nk_false;
21177  return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
21178 }
21190 NK_API nk_bool
21191 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
21192 {
21193  const struct nk_key *k;
21194  if (!i) return nk_false;
21195  k = &i->keyboard.keys[key];
21196  if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
21197  return nk_true;
21198  return nk_false;
21199 }
21211 NK_API nk_bool
21212 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
21213 {
21214  const struct nk_key *k;
21215  if (!i) return nk_false;
21216  k = &i->keyboard.keys[key];
21217  if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
21218  return nk_true;
21219  return nk_false;
21220 }
21232 NK_API nk_bool
21233 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
21234 {
21235  const struct nk_key *k;
21236  if (!i) return nk_false;
21237  k = &i->keyboard.keys[key];
21238  if (k->down) return nk_true;
21239  return nk_false;
21240 }
21241 
21242 
21243 
21244 
21245 
21246 /* ===============================================================
21247  *
21248  * STYLE
21249  *
21250  * ===============================================================*/
21263 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
21264 #define NK_COLOR_MAP(NK_COLOR)\
21265  NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \
21266  NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \
21267  NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \
21268  NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \
21269  NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \
21270  NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \
21271  NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \
21272  NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \
21273  NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \
21274  NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \
21275  NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \
21276  NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \
21277  NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \
21278  NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \
21279  NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \
21280  NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
21281  NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \
21282  NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \
21283  NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \
21284  NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \
21285  NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \
21286  NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \
21287  NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT, 255, 0, 0, 255) \
21288  NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \
21289  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \
21290  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \
21291  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \
21292  NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) \
21293  NK_COLOR(NK_COLOR_KNOB, 38, 38, 38, 255) \
21294  NK_COLOR(NK_COLOR_KNOB_CURSOR, 100,100,100,255) \
21295  NK_COLOR(NK_COLOR_KNOB_CURSOR_HOVER, 120,120,120,255) \
21296  NK_COLOR(NK_COLOR_KNOB_CURSOR_ACTIVE, 150,150,150,255)
21297 
21298 NK_GLOBAL const struct nk_color
21299 nk_default_color_style[NK_COLOR_COUNT] = {
21300 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
21301  NK_COLOR_MAP(NK_COLOR)
21302 #undef NK_COLOR
21303 };
21304 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
21305 #define NK_COLOR(a,b,c,d,e) #a,
21306  NK_COLOR_MAP(NK_COLOR)
21307 #undef NK_COLOR
21308 };
21309 
21320 NK_API const char*
21321 nk_style_get_color_by_name(enum nk_style_colors c)
21322 {
21323  return nk_color_names[c];
21324 }
21335 NK_API struct nk_style_item
21336 nk_style_item_color(struct nk_color col)
21337 {
21338  struct nk_style_item i;
21339  i.type = NK_STYLE_ITEM_COLOR;
21340  i.data.color = col;
21341  return i;
21342 }
21353 NK_API struct nk_style_item
21354 nk_style_item_image(struct nk_image img)
21355 {
21356  struct nk_style_item i;
21357  i.type = NK_STYLE_ITEM_IMAGE;
21358  i.data.image = img;
21359  return i;
21360 }
21371 NK_API struct nk_style_item
21372 nk_style_item_nine_slice(struct nk_nine_slice slice)
21373 {
21374  struct nk_style_item i;
21375  i.type = NK_STYLE_ITEM_NINE_SLICE;
21376  i.data.slice = slice;
21377  return i;
21378 }
21389 NK_API struct nk_style_item
21390 nk_style_item_hide(void)
21391 {
21392  struct nk_style_item i;
21393  i.type = NK_STYLE_ITEM_COLOR;
21394  i.data.color = nk_rgba(0,0,0,0);
21395  return i;
21396 }
21408 NK_API void
21409 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
21410 {
21411  struct nk_style *style;
21412  struct nk_style_text *text;
21413  struct nk_style_button *button;
21414  struct nk_style_toggle *toggle;
21415  struct nk_style_selectable *select;
21416  struct nk_style_slider *slider;
21417  struct nk_style_knob *knob;
21418  struct nk_style_progress *prog;
21419  struct nk_style_scrollbar *scroll;
21420  struct nk_style_edit *edit;
21421  struct nk_style_property *property;
21422  struct nk_style_combo *combo;
21423  struct nk_style_chart *chart;
21424  struct nk_style_tab *tab;
21425  struct nk_style_window *win;
21426 
21427  NK_ASSERT(ctx);
21428  if (!ctx) return;
21429  style = &ctx->style;
21430  table = (!table) ? nk_default_color_style: table;
21431 
21432  /* default text */
21433  text = &style->text;
21434  text->color = table[NK_COLOR_TEXT];
21435  text->padding = nk_vec2(0,0);
21436  text->color_factor = 1.0f;
21437  text->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21438 
21439  /* default button */
21440  button = &style->button;
21441  nk_zero_struct(*button);
21442  button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]);
21443  button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
21444  button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
21445  button->border_color = table[NK_COLOR_BORDER];
21446  button->text_background = table[NK_COLOR_BUTTON];
21447  button->text_normal = table[NK_COLOR_TEXT];
21448  button->text_hover = table[NK_COLOR_TEXT];
21449  button->text_active = table[NK_COLOR_TEXT];
21450  button->padding = nk_vec2(2.0f,2.0f);
21451  button->image_padding = nk_vec2(0.0f,0.0f);
21452  button->touch_padding = nk_vec2(0.0f, 0.0f);
21453  button->userdata = nk_handle_ptr(0);
21454  button->text_alignment = NK_TEXT_CENTERED;
21455  button->border = 1.0f;
21456  button->rounding = 4.0f;
21457  button->color_factor_text = 1.0f;
21458  button->color_factor_background = 1.0f;
21459  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21460  button->draw_begin = 0;
21461  button->draw_end = 0;
21462 
21463  /* contextual button */
21464  button = &style->contextual_button;
21465  nk_zero_struct(*button);
21466  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
21467  button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]);
21468  button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]);
21469  button->border_color = table[NK_COLOR_WINDOW];
21470  button->text_background = table[NK_COLOR_WINDOW];
21471  button->text_normal = table[NK_COLOR_TEXT];
21472  button->text_hover = table[NK_COLOR_TEXT];
21473  button->text_active = table[NK_COLOR_TEXT];
21474  button->padding = nk_vec2(2.0f,2.0f);
21475  button->touch_padding = nk_vec2(0.0f,0.0f);
21476  button->userdata = nk_handle_ptr(0);
21477  button->text_alignment = NK_TEXT_CENTERED;
21478  button->border = 0.0f;
21479  button->rounding = 0.0f;
21480  button->color_factor_text = 1.0f;
21481  button->color_factor_background = 1.0f;
21482  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21483  button->draw_begin = 0;
21484  button->draw_end = 0;
21485 
21486  /* menu button */
21487  button = &style->menu_button;
21488  nk_zero_struct(*button);
21489  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
21490  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
21491  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
21492  button->border_color = table[NK_COLOR_WINDOW];
21493  button->text_background = table[NK_COLOR_WINDOW];
21494  button->text_normal = table[NK_COLOR_TEXT];
21495  button->text_hover = table[NK_COLOR_TEXT];
21496  button->text_active = table[NK_COLOR_TEXT];
21497  button->padding = nk_vec2(2.0f,2.0f);
21498  button->touch_padding = nk_vec2(0.0f,0.0f);
21499  button->userdata = nk_handle_ptr(0);
21500  button->text_alignment = NK_TEXT_CENTERED;
21501  button->border = 0.0f;
21502  button->rounding = 1.0f;
21503  button->color_factor_text = 1.0f;
21504  button->color_factor_background = 1.0f;
21505  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21506  button->draw_begin = 0;
21507  button->draw_end = 0;
21508 
21509  /* checkbox toggle */
21510  toggle = &style->checkbox;
21511  nk_zero_struct(*toggle);
21512  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
21513  toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
21514  toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
21515  toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
21516  toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
21517  toggle->userdata = nk_handle_ptr(0);
21518  toggle->text_background = table[NK_COLOR_WINDOW];
21519  toggle->text_normal = table[NK_COLOR_TEXT];
21520  toggle->text_hover = table[NK_COLOR_TEXT];
21521  toggle->text_active = table[NK_COLOR_TEXT];
21522  toggle->padding = nk_vec2(2.0f, 2.0f);
21523  toggle->touch_padding = nk_vec2(0,0);
21524  toggle->border_color = nk_rgba(0,0,0,0);
21525  toggle->border = 0.0f;
21526  toggle->spacing = 4;
21527  toggle->color_factor = 1.0f;
21528  toggle->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21529 
21530  /* option toggle */
21531  toggle = &style->option;
21532  nk_zero_struct(*toggle);
21533  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
21534  toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
21535  toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]);
21536  toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
21537  toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]);
21538  toggle->userdata = nk_handle_ptr(0);
21539  toggle->text_background = table[NK_COLOR_WINDOW];
21540  toggle->text_normal = table[NK_COLOR_TEXT];
21541  toggle->text_hover = table[NK_COLOR_TEXT];
21542  toggle->text_active = table[NK_COLOR_TEXT];
21543  toggle->padding = nk_vec2(3.0f, 3.0f);
21544  toggle->touch_padding = nk_vec2(0,0);
21545  toggle->border_color = nk_rgba(0,0,0,0);
21546  toggle->border = 0.0f;
21547  toggle->spacing = 4;
21548  toggle->color_factor = 1.0f;
21549  toggle->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21550 
21551  /* selectable */
21552  select = &style->selectable;
21553  nk_zero_struct(*select);
21554  select->normal = nk_style_item_color(table[NK_COLOR_SELECT]);
21555  select->hover = nk_style_item_color(table[NK_COLOR_SELECT]);
21556  select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]);
21557  select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
21558  select->hover_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
21559  select->pressed_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]);
21560  select->text_normal = table[NK_COLOR_TEXT];
21561  select->text_hover = table[NK_COLOR_TEXT];
21562  select->text_pressed = table[NK_COLOR_TEXT];
21563  select->text_normal_active = table[NK_COLOR_TEXT];
21564  select->text_hover_active = table[NK_COLOR_TEXT];
21565  select->text_pressed_active = table[NK_COLOR_TEXT];
21566  select->padding = nk_vec2(2.0f,2.0f);
21567  select->image_padding = nk_vec2(2.0f,2.0f);
21568  select->touch_padding = nk_vec2(0,0);
21569  select->userdata = nk_handle_ptr(0);
21570  select->rounding = 0.0f;
21571  select->color_factor = 1.0f;
21572  select->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21573  select->draw_begin = 0;
21574  select->draw_end = 0;
21575 
21576  /* slider */
21577  slider = &style->slider;
21578  nk_zero_struct(*slider);
21579  slider->normal = nk_style_item_hide();
21580  slider->hover = nk_style_item_hide();
21581  slider->active = nk_style_item_hide();
21582  slider->bar_normal = table[NK_COLOR_SLIDER];
21583  slider->bar_hover = table[NK_COLOR_SLIDER];
21584  slider->bar_active = table[NK_COLOR_SLIDER];
21585  slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR];
21586  slider->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
21587  slider->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
21588  slider->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
21589  slider->inc_symbol = NK_SYMBOL_TRIANGLE_RIGHT;
21590  slider->dec_symbol = NK_SYMBOL_TRIANGLE_LEFT;
21591  slider->cursor_size = nk_vec2(16,16);
21592  slider->padding = nk_vec2(2,2);
21593  slider->spacing = nk_vec2(2,2);
21594  slider->userdata = nk_handle_ptr(0);
21595  slider->show_buttons = nk_false;
21596  slider->bar_height = 8;
21597  slider->rounding = 0;
21598  slider->color_factor = 1.0f;
21599  slider->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21600  slider->draw_begin = 0;
21601  slider->draw_end = 0;
21602 
21603  /* slider buttons */
21604  button = &style->slider.inc_button;
21605  button->normal = nk_style_item_color(nk_rgb(40,40,40));
21606  button->hover = nk_style_item_color(nk_rgb(42,42,42));
21607  button->active = nk_style_item_color(nk_rgb(44,44,44));
21608  button->border_color = nk_rgb(65,65,65);
21609  button->text_background = nk_rgb(40,40,40);
21610  button->text_normal = nk_rgb(175,175,175);
21611  button->text_hover = nk_rgb(175,175,175);
21612  button->text_active = nk_rgb(175,175,175);
21613  button->padding = nk_vec2(8.0f,8.0f);
21614  button->touch_padding = nk_vec2(0.0f,0.0f);
21615  button->userdata = nk_handle_ptr(0);
21616  button->text_alignment = NK_TEXT_CENTERED;
21617  button->border = 1.0f;
21618  button->rounding = 0.0f;
21619  button->color_factor_text = 1.0f;
21620  button->color_factor_background = 1.0f;
21621  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21622  button->draw_begin = 0;
21623  button->draw_end = 0;
21624  style->slider.dec_button = style->slider.inc_button;
21625 
21626  /* knob */
21627  knob = &style->knob;
21628  nk_zero_struct(*knob);
21629  knob->normal = nk_style_item_hide();
21630  knob->hover = nk_style_item_hide();
21631  knob->active = nk_style_item_hide();
21632  knob->knob_normal = table[NK_COLOR_KNOB];
21633  knob->knob_hover = table[NK_COLOR_KNOB];
21634  knob->knob_active = table[NK_COLOR_KNOB];
21635  knob->cursor_normal = table[NK_COLOR_KNOB_CURSOR];
21636  knob->cursor_hover = table[NK_COLOR_KNOB_CURSOR_HOVER];
21637  knob->cursor_active = table[NK_COLOR_KNOB_CURSOR_ACTIVE];
21638 
21639  knob->knob_border_color = table[NK_COLOR_BORDER];
21640  knob->knob_border = 1.0f;
21641 
21642  knob->padding = nk_vec2(2,2);
21643  knob->spacing = nk_vec2(2,2);
21644  knob->cursor_width = 2;
21645  knob->color_factor = 1.0f;
21646  knob->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21647 
21648  knob->userdata = nk_handle_ptr(0);
21649  knob->draw_begin = 0;
21650  knob->draw_end = 0;
21651 
21652  /* progressbar */
21653  prog = &style->progress;
21654  nk_zero_struct(*prog);
21655  prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]);
21656  prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]);
21657  prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]);
21658  prog->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]);
21659  prog->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]);
21660  prog->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]);
21661  prog->border_color = nk_rgba(0,0,0,0);
21662  prog->cursor_border_color = nk_rgba(0,0,0,0);
21663  prog->userdata = nk_handle_ptr(0);
21664  prog->padding = nk_vec2(4,4);
21665  prog->rounding = 0;
21666  prog->border = 0;
21667  prog->cursor_rounding = 0;
21668  prog->cursor_border = 0;
21669  prog->color_factor = 1.0f;
21670  prog->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21671  prog->draw_begin = 0;
21672  prog->draw_end = 0;
21673 
21674  /* scrollbars */
21675  scroll = &style->scrollh;
21676  nk_zero_struct(*scroll);
21677  scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
21678  scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
21679  scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
21680  scroll->cursor_normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]);
21681  scroll->cursor_hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]);
21682  scroll->cursor_active = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]);
21683  scroll->dec_symbol = NK_SYMBOL_CIRCLE_SOLID;
21684  scroll->inc_symbol = NK_SYMBOL_CIRCLE_SOLID;
21685  scroll->userdata = nk_handle_ptr(0);
21686  scroll->border_color = table[NK_COLOR_SCROLLBAR];
21687  scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
21688  scroll->padding = nk_vec2(0,0);
21689  scroll->show_buttons = nk_false;
21690  scroll->border = 0;
21691  scroll->rounding = 0;
21692  scroll->border_cursor = 0;
21693  scroll->rounding_cursor = 0;
21694  scroll->color_factor = 1.0f;
21695  scroll->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21696  scroll->draw_begin = 0;
21697  scroll->draw_end = 0;
21698  style->scrollv = style->scrollh;
21699 
21700  /* scrollbars buttons */
21701  button = &style->scrollh.inc_button;
21702  button->normal = nk_style_item_color(nk_rgb(40,40,40));
21703  button->hover = nk_style_item_color(nk_rgb(42,42,42));
21704  button->active = nk_style_item_color(nk_rgb(44,44,44));
21705  button->border_color = nk_rgb(65,65,65);
21706  button->text_background = nk_rgb(40,40,40);
21707  button->text_normal = nk_rgb(175,175,175);
21708  button->text_hover = nk_rgb(175,175,175);
21709  button->text_active = nk_rgb(175,175,175);
21710  button->padding = nk_vec2(4.0f,4.0f);
21711  button->touch_padding = nk_vec2(0.0f,0.0f);
21712  button->userdata = nk_handle_ptr(0);
21713  button->text_alignment = NK_TEXT_CENTERED;
21714  button->border = 1.0f;
21715  button->rounding = 0.0f;
21716  button->color_factor_text = 1.0f;
21717  button->color_factor_background = 1.0f;
21718  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21719  button->draw_begin = 0;
21720  button->draw_end = 0;
21721  style->scrollh.dec_button = style->scrollh.inc_button;
21722  style->scrollv.inc_button = style->scrollh.inc_button;
21723  style->scrollv.dec_button = style->scrollh.inc_button;
21724 
21725  /* edit */
21726  edit = &style->edit;
21727  nk_zero_struct(*edit);
21728  edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]);
21729  edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]);
21730  edit->active = nk_style_item_color(table[NK_COLOR_EDIT]);
21731  edit->cursor_normal = table[NK_COLOR_TEXT];
21732  edit->cursor_hover = table[NK_COLOR_TEXT];
21733  edit->cursor_text_normal= table[NK_COLOR_EDIT];
21734  edit->cursor_text_hover = table[NK_COLOR_EDIT];
21735  edit->border_color = table[NK_COLOR_BORDER];
21736  edit->text_normal = table[NK_COLOR_TEXT];
21737  edit->text_hover = table[NK_COLOR_TEXT];
21738  edit->text_active = table[NK_COLOR_TEXT];
21739  edit->selected_normal = table[NK_COLOR_TEXT];
21740  edit->selected_hover = table[NK_COLOR_TEXT];
21741  edit->selected_text_normal = table[NK_COLOR_EDIT];
21742  edit->selected_text_hover = table[NK_COLOR_EDIT];
21743  edit->scrollbar_size = nk_vec2(10,10);
21744  edit->scrollbar = style->scrollv;
21745  edit->padding = nk_vec2(4,4);
21746  edit->row_padding = 2;
21747  edit->cursor_size = 4;
21748  edit->border = 1;
21749  edit->rounding = 0;
21750  edit->color_factor = 1.0f;
21751  edit->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21752 
21753  /* property */
21754  property = &style->property;
21755  nk_zero_struct(*property);
21756  property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21757  property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21758  property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21759  property->border_color = table[NK_COLOR_BORDER];
21760  property->label_normal = table[NK_COLOR_TEXT];
21761  property->label_hover = table[NK_COLOR_TEXT];
21762  property->label_active = table[NK_COLOR_TEXT];
21763  property->sym_left = NK_SYMBOL_TRIANGLE_LEFT;
21764  property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
21765  property->userdata = nk_handle_ptr(0);
21766  property->padding = nk_vec2(4,4);
21767  property->border = 1;
21768  property->rounding = 10;
21769  property->draw_begin = 0;
21770  property->draw_end = 0;
21771  property->color_factor = 1.0f;
21772  property->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21773 
21774  /* property buttons */
21775  button = &style->property.dec_button;
21776  nk_zero_struct(*button);
21777  button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21778  button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21779  button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21780  button->border_color = nk_rgba(0,0,0,0);
21781  button->text_background = table[NK_COLOR_PROPERTY];
21782  button->text_normal = table[NK_COLOR_TEXT];
21783  button->text_hover = table[NK_COLOR_TEXT];
21784  button->text_active = table[NK_COLOR_TEXT];
21785  button->padding = nk_vec2(0.0f,0.0f);
21786  button->touch_padding = nk_vec2(0.0f,0.0f);
21787  button->userdata = nk_handle_ptr(0);
21788  button->text_alignment = NK_TEXT_CENTERED;
21789  button->border = 0.0f;
21790  button->rounding = 0.0f;
21791  button->color_factor_text = 1.0f;
21792  button->color_factor_background = 1.0f;
21793  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21794  button->draw_begin = 0;
21795  button->draw_end = 0;
21796  style->property.inc_button = style->property.dec_button;
21797 
21798  /* property edit */
21799  edit = &style->property.edit;
21800  nk_zero_struct(*edit);
21801  edit->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21802  edit->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21803  edit->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
21804  edit->border_color = nk_rgba(0,0,0,0);
21805  edit->cursor_normal = table[NK_COLOR_TEXT];
21806  edit->cursor_hover = table[NK_COLOR_TEXT];
21807  edit->cursor_text_normal= table[NK_COLOR_EDIT];
21808  edit->cursor_text_hover = table[NK_COLOR_EDIT];
21809  edit->text_normal = table[NK_COLOR_TEXT];
21810  edit->text_hover = table[NK_COLOR_TEXT];
21811  edit->text_active = table[NK_COLOR_TEXT];
21812  edit->selected_normal = table[NK_COLOR_TEXT];
21813  edit->selected_hover = table[NK_COLOR_TEXT];
21814  edit->selected_text_normal = table[NK_COLOR_EDIT];
21815  edit->selected_text_hover = table[NK_COLOR_EDIT];
21816  edit->padding = nk_vec2(0,0);
21817  edit->cursor_size = 8;
21818  edit->border = 0;
21819  edit->rounding = 0;
21820  edit->color_factor = 1.0f;
21821  edit->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21822 
21823  /* chart */
21824  chart = &style->chart;
21825  nk_zero_struct(*chart);
21826  chart->background = nk_style_item_color(table[NK_COLOR_CHART]);
21827  chart->border_color = table[NK_COLOR_BORDER];
21828  chart->selected_color = table[NK_COLOR_CHART_COLOR_HIGHLIGHT];
21829  chart->color = table[NK_COLOR_CHART_COLOR];
21830  chart->padding = nk_vec2(4,4);
21831  chart->border = 0;
21832  chart->rounding = 0;
21833  chart->color_factor = 1.0f;
21834  chart->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21835  chart->show_markers = nk_true;
21836 
21837  /* combo */
21838  combo = &style->combo;
21839  combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
21840  combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
21841  combo->active = nk_style_item_color(table[NK_COLOR_COMBO]);
21842  combo->border_color = table[NK_COLOR_BORDER];
21843  combo->label_normal = table[NK_COLOR_TEXT];
21844  combo->label_hover = table[NK_COLOR_TEXT];
21845  combo->label_active = table[NK_COLOR_TEXT];
21846  combo->sym_normal = NK_SYMBOL_TRIANGLE_DOWN;
21847  combo->sym_hover = NK_SYMBOL_TRIANGLE_DOWN;
21848  combo->sym_active = NK_SYMBOL_TRIANGLE_DOWN;
21849  combo->content_padding = nk_vec2(4,4);
21850  combo->button_padding = nk_vec2(0,4);
21851  combo->spacing = nk_vec2(4,0);
21852  combo->border = 1;
21853  combo->rounding = 0;
21854  combo->color_factor = 1.0f;
21855  combo->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21856 
21857  /* combo button */
21858  button = &style->combo.button;
21859  nk_zero_struct(*button);
21860  button->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
21861  button->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
21862  button->active = nk_style_item_color(table[NK_COLOR_COMBO]);
21863  button->border_color = nk_rgba(0,0,0,0);
21864  button->text_background = table[NK_COLOR_COMBO];
21865  button->text_normal = table[NK_COLOR_TEXT];
21866  button->text_hover = table[NK_COLOR_TEXT];
21867  button->text_active = table[NK_COLOR_TEXT];
21868  button->padding = nk_vec2(2.0f,2.0f);
21869  button->touch_padding = nk_vec2(0.0f,0.0f);
21870  button->userdata = nk_handle_ptr(0);
21871  button->text_alignment = NK_TEXT_CENTERED;
21872  button->border = 0.0f;
21873  button->rounding = 0.0f;
21874  button->color_factor_text = 1.0f;
21875  button->color_factor_background = 1.0f;
21876  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21877  button->draw_begin = 0;
21878  button->draw_end = 0;
21879 
21880  /* tab */
21881  tab = &style->tab;
21882  tab->background = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
21883  tab->border_color = table[NK_COLOR_BORDER];
21884  tab->text = table[NK_COLOR_TEXT];
21885  tab->sym_minimize = NK_SYMBOL_TRIANGLE_RIGHT;
21886  tab->sym_maximize = NK_SYMBOL_TRIANGLE_DOWN;
21887  tab->padding = nk_vec2(4,4);
21888  tab->spacing = nk_vec2(4,4);
21889  tab->indent = 10.0f;
21890  tab->border = 1;
21891  tab->rounding = 0;
21892  tab->color_factor = 1.0f;
21893  tab->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21894 
21895  /* tab button */
21896  button = &style->tab.tab_minimize_button;
21897  nk_zero_struct(*button);
21898  button->normal = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
21899  button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
21900  button->active = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
21901  button->border_color = nk_rgba(0,0,0,0);
21902  button->text_background = table[NK_COLOR_TAB_HEADER];
21903  button->text_normal = table[NK_COLOR_TEXT];
21904  button->text_hover = table[NK_COLOR_TEXT];
21905  button->text_active = table[NK_COLOR_TEXT];
21906  button->padding = nk_vec2(2.0f,2.0f);
21907  button->touch_padding = nk_vec2(0.0f,0.0f);
21908  button->userdata = nk_handle_ptr(0);
21909  button->text_alignment = NK_TEXT_CENTERED;
21910  button->border = 0.0f;
21911  button->rounding = 0.0f;
21912  button->color_factor_text = 1.0f;
21913  button->color_factor_background = 1.0f;
21914  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21915  button->draw_begin = 0;
21916  button->draw_end = 0;
21917  style->tab.tab_maximize_button =*button;
21918 
21919  /* node button */
21920  button = &style->tab.node_minimize_button;
21921  nk_zero_struct(*button);
21922  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
21923  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
21924  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
21925  button->border_color = nk_rgba(0,0,0,0);
21926  button->text_background = table[NK_COLOR_TAB_HEADER];
21927  button->text_normal = table[NK_COLOR_TEXT];
21928  button->text_hover = table[NK_COLOR_TEXT];
21929  button->text_active = table[NK_COLOR_TEXT];
21930  button->padding = nk_vec2(2.0f,2.0f);
21931  button->touch_padding = nk_vec2(0.0f,0.0f);
21932  button->userdata = nk_handle_ptr(0);
21933  button->text_alignment = NK_TEXT_CENTERED;
21934  button->border = 0.0f;
21935  button->rounding = 0.0f;
21936  button->color_factor_text = 1.0f;
21937  button->color_factor_background = 1.0f;
21938  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21939  button->draw_begin = 0;
21940  button->draw_end = 0;
21941  style->tab.node_maximize_button =*button;
21942 
21943  /* window header */
21944  win = &style->window;
21945  win->header.align = NK_HEADER_RIGHT;
21946  win->header.close_symbol = NK_SYMBOL_X;
21947  win->header.minimize_symbol = NK_SYMBOL_MINUS;
21948  win->header.maximize_symbol = NK_SYMBOL_PLUS;
21949  win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]);
21950  win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]);
21951  win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]);
21952  win->header.label_normal = table[NK_COLOR_TEXT];
21953  win->header.label_hover = table[NK_COLOR_TEXT];
21954  win->header.label_active = table[NK_COLOR_TEXT];
21955  win->header.label_padding = nk_vec2(4,4);
21956  win->header.padding = nk_vec2(4,4);
21957  win->header.spacing = nk_vec2(0,0);
21958 
21959  /* window header close button */
21960  button = &style->window.header.close_button;
21961  nk_zero_struct(*button);
21962  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
21963  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
21964  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
21965  button->border_color = nk_rgba(0,0,0,0);
21966  button->text_background = table[NK_COLOR_HEADER];
21967  button->text_normal = table[NK_COLOR_TEXT];
21968  button->text_hover = table[NK_COLOR_TEXT];
21969  button->text_active = table[NK_COLOR_TEXT];
21970  button->padding = nk_vec2(0.0f,0.0f);
21971  button->touch_padding = nk_vec2(0.0f,0.0f);
21972  button->userdata = nk_handle_ptr(0);
21973  button->text_alignment = NK_TEXT_CENTERED;
21974  button->border = 0.0f;
21975  button->rounding = 0.0f;
21976  button->color_factor_text = 1.0f;
21977  button->color_factor_background = 1.0f;
21978  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
21979  button->draw_begin = 0;
21980  button->draw_end = 0;
21981 
21982  /* window header minimize button */
21983  button = &style->window.header.minimize_button;
21984  nk_zero_struct(*button);
21985  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
21986  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
21987  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
21988  button->border_color = nk_rgba(0,0,0,0);
21989  button->text_background = table[NK_COLOR_HEADER];
21990  button->text_normal = table[NK_COLOR_TEXT];
21991  button->text_hover = table[NK_COLOR_TEXT];
21992  button->text_active = table[NK_COLOR_TEXT];
21993  button->padding = nk_vec2(0.0f,0.0f);
21994  button->touch_padding = nk_vec2(0.0f,0.0f);
21995  button->userdata = nk_handle_ptr(0);
21996  button->text_alignment = NK_TEXT_CENTERED;
21997  button->border = 0.0f;
21998  button->rounding = 0.0f;
21999  button->color_factor_text = 1.0f;
22000  button->color_factor_background = 1.0f;
22001  button->disabled_factor = NK_WIDGET_DISABLED_FACTOR;
22002  button->draw_begin = 0;
22003  button->draw_end = 0;
22004 
22005  /* window */
22006  win->background = table[NK_COLOR_WINDOW];
22007  win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]);
22008  win->border_color = table[NK_COLOR_BORDER];
22009  win->popup_border_color = table[NK_COLOR_BORDER];
22010  win->combo_border_color = table[NK_COLOR_BORDER];
22011  win->contextual_border_color = table[NK_COLOR_BORDER];
22012  win->menu_border_color = table[NK_COLOR_BORDER];
22013  win->group_border_color = table[NK_COLOR_BORDER];
22014  win->tooltip_border_color = table[NK_COLOR_BORDER];
22015  win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
22016 
22017  win->rounding = 0.0f;
22018  win->spacing = nk_vec2(4,4);
22019  win->scrollbar_size = nk_vec2(10,10);
22020  win->min_size = nk_vec2(64,64);
22021 
22022  win->combo_border = 1.0f;
22023  win->contextual_border = 1.0f;
22024  win->menu_border = 1.0f;
22025  win->group_border = 1.0f;
22026  win->tooltip_border = 1.0f;
22027  win->popup_border = 1.0f;
22028  win->border = 2.0f;
22029  win->min_row_height_padding = 8;
22030 
22031  win->padding = nk_vec2(4,4);
22032  win->group_padding = nk_vec2(4,4);
22033  win->popup_padding = nk_vec2(4,4);
22034  win->combo_padding = nk_vec2(4,4);
22035  win->contextual_padding = nk_vec2(4,4);
22036  win->menu_padding = nk_vec2(4,4);
22037  win->tooltip_padding = nk_vec2(4,4);
22038 }
22050 NK_API void
22051 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
22052 {
22053  struct nk_style *style;
22054  NK_ASSERT(ctx);
22055 
22056  if (!ctx) return;
22057  style = &ctx->style;
22058  style->font = font;
22059  ctx->stacks.fonts.head = 0;
22060  if (ctx->current)
22062 }
22074 NK_API nk_bool
22075 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
22076 {
22077  struct nk_config_stack_user_font *font_stack;
22078  struct nk_config_stack_user_font_element *element;
22079 
22080  NK_ASSERT(ctx);
22081  if (!ctx) return 0;
22082 
22083  font_stack = &ctx->stacks.fonts;
22084  NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
22085  if (font_stack->head >= (int)NK_LEN(font_stack->elements))
22086  return 0;
22087 
22088  element = &font_stack->elements[font_stack->head++];
22089  element->address = &ctx->style.font;
22090  element->old_value = ctx->style.font;
22091  ctx->style.font = font;
22092  return 1;
22093 }
22104 NK_API nk_bool
22105 nk_style_pop_font(struct nk_context *ctx)
22106 {
22107  struct nk_config_stack_user_font *font_stack;
22108  struct nk_config_stack_user_font_element *element;
22109 
22110  NK_ASSERT(ctx);
22111  if (!ctx) return 0;
22112 
22113  font_stack = &ctx->stacks.fonts;
22114  NK_ASSERT(font_stack->head > 0);
22115  if (font_stack->head < 1)
22116  return 0;
22117 
22118  element = &font_stack->elements[--font_stack->head];
22119  *element->address = element->old_value;
22120  return 1;
22121 }
22122 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
22123 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
22124 {\
22125  struct nk_config_stack_##type * type_stack;\
22126  struct nk_config_stack_##type##_element *element;\
22127  NK_ASSERT(ctx);\
22128  if (!ctx) return 0;\
22129  type_stack = &ctx->stacks.stack;\
22130  NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
22131  if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
22132  return 0;\
22133  element = &type_stack->elements[type_stack->head++];\
22134  element->address = address;\
22135  element->old_value = *address;\
22136  *address = value;\
22137  return 1;\
22138 }
22139 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
22140 nk_style_pop_##type(struct nk_context *ctx)\
22141 {\
22142  struct nk_config_stack_##type *type_stack;\
22143  struct nk_config_stack_##type##_element *element;\
22144  NK_ASSERT(ctx);\
22145  if (!ctx) return 0;\
22146  type_stack = &ctx->stacks.stack;\
22147  NK_ASSERT(type_stack->head > 0);\
22148  if (type_stack->head < 1)\
22149  return 0;\
22150  element = &type_stack->elements[--type_stack->head];\
22151  *element->address = element->old_value;\
22152  return 1;\
22153 }
22166 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
22167 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
22168 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
22169 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
22170 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
22171 
22172 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
22173 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(float,floats)
22174 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
22175 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(flags,flags)
22176 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(color,colors)
22177 
22178 NK_API nk_bool
22179 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
22180 {
22181  struct nk_style *style;
22182  NK_ASSERT(ctx);
22183  if (!ctx) return 0;
22184  style = &ctx->style;
22185  if (style->cursors[c]) {
22186  style->cursor_active = style->cursors[c];
22187  return 1;
22188  }
22189  return 0;
22190 }
22201 NK_API void
22202 nk_style_show_cursor(struct nk_context *ctx)
22203 {
22204  ctx->style.cursor_visible = nk_true;
22205 }
22216 NK_API void
22217 nk_style_hide_cursor(struct nk_context *ctx)
22218 {
22219  ctx->style.cursor_visible = nk_false;
22220 }
22232 NK_API void
22233 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
22234  const struct nk_cursor *c)
22235 {
22236  struct nk_style *style;
22237  NK_ASSERT(ctx);
22238  if (!ctx) return;
22239  style = &ctx->style;
22240  style->cursors[cursor] = c;
22241 }
22253 NK_API void
22254 nk_style_load_all_cursors(struct nk_context *ctx, const struct nk_cursor *cursors)
22255 {
22256  int i = 0;
22257  struct nk_style *style;
22258  NK_ASSERT(ctx);
22259  if (!ctx) return;
22260  style = &ctx->style;
22261  for (i = 0; i < NK_CURSOR_COUNT; ++i)
22262  style->cursors[i] = &cursors[i];
22263  style->cursor_visible = nk_true;
22264 }
22265 
22266 
22267 
22268 
22269 /* ==============================================================
22270  *
22271  * CONTEXT
22272  *
22273  * ===============================================================*/
22285 NK_INTERN void
22286 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
22287 {
22288  NK_ASSERT(ctx);
22289  if (!ctx) return;
22290  nk_zero_struct(*ctx);
22291  nk_style_default(ctx);
22292  ctx->seq = 1;
22293  if (font) ctx->style.font = font;
22294 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
22295  nk_draw_list_init(&ctx->draw_list);
22296 #endif
22297 }
22298 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
22310 NK_API nk_bool
22311 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
22312 {
22313  struct nk_allocator alloc;
22314  alloc.userdata.ptr = 0;
22315  alloc.alloc = nk_malloc;
22316  alloc.free = nk_mfree;
22317  return nk_init(ctx, &alloc, font);
22318 }
22319 #endif
22332 NK_API nk_bool
22333 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
22334  const struct nk_user_font *font)
22335 {
22336  NK_ASSERT(memory);
22337  if (!memory) return 0;
22338  nk_setup(ctx, font);
22339  nk_buffer_init_fixed(&ctx->memory, memory, size);
22340  ctx->use_pool = nk_false;
22341  return 1;
22342 }
22354 NK_API nk_bool
22355 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
22356  struct nk_buffer *pool, const struct nk_user_font *font)
22357 {
22358  NK_ASSERT(cmds);
22359  NK_ASSERT(pool);
22360  if (!cmds || !pool) return 0;
22361 
22362  nk_setup(ctx, font);
22363  ctx->memory = *cmds;
22364  if (pool->type == NK_BUFFER_FIXED) {
22365  /* take memory from buffer and alloc fixed pool */
22366  nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
22367  } else {
22368  /* create dynamic pool from buffer allocator */
22369  struct nk_allocator *alloc = &pool->pool;
22370  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
22371  }
22372  ctx->use_pool = nk_true;
22373  return 1;
22374 }
22386 NK_API nk_bool
22387 nk_init(struct nk_context *ctx, const struct nk_allocator *alloc,
22388  const struct nk_user_font *font)
22389 {
22390  NK_ASSERT(alloc);
22391  if (!alloc) return 0;
22392  nk_setup(ctx, font);
22393  nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
22394  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
22395  ctx->use_pool = nk_true;
22396  return 1;
22397 }
22398 #ifdef NK_INCLUDE_COMMAND_USERDATA
22410 NK_API void
22411 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
22412 {
22413  if (!ctx) return;
22414  ctx->userdata = handle;
22415  if (ctx->current)
22416  ctx->current->buffer.userdata = handle;
22417 }
22418 #endif
22429 NK_API void
22430 nk_free(struct nk_context *ctx)
22431 {
22432  NK_ASSERT(ctx);
22433  if (!ctx) return;
22434  nk_buffer_free(&ctx->memory);
22435  if (ctx->use_pool)
22436  nk_pool_free(&ctx->pool);
22437 
22438  nk_zero(&ctx->input, sizeof(ctx->input));
22439  nk_zero(&ctx->style, sizeof(ctx->style));
22440  nk_zero(&ctx->memory, sizeof(ctx->memory));
22441 
22442  ctx->seq = 0;
22443  ctx->build = 0;
22444  ctx->begin = 0;
22445  ctx->end = 0;
22446  ctx->active = 0;
22447  ctx->current = 0;
22448  ctx->freelist = 0;
22449  ctx->count = 0;
22450 }
22461 NK_API void
22462 nk_clear(struct nk_context *ctx)
22463 {
22464  struct nk_window *iter;
22465  struct nk_window *next;
22466  NK_ASSERT(ctx);
22467 
22468  if (!ctx) return;
22469  if (ctx->use_pool)
22470  nk_buffer_clear(&ctx->memory);
22471  else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
22472 
22473  ctx->build = 0;
22474  ctx->memory.calls = 0;
22475  ctx->last_widget_state = 0;
22476  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
22477  NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
22478 
22479  /* garbage collector */
22480  iter = ctx->begin;
22481  while (iter) {
22482  /* make sure valid minimized windows do not get removed */
22483  if ((iter->flags & NK_WINDOW_MINIMIZED) &&
22484  !(iter->flags & NK_WINDOW_CLOSED) &&
22485  iter->seq == ctx->seq) {
22486  iter = iter->next;
22487  continue;
22488  }
22489  /* remove hotness from hidden or closed windows*/
22490  if (((iter->flags & NK_WINDOW_HIDDEN) ||
22491  (iter->flags & NK_WINDOW_CLOSED)) &&
22492  iter == ctx->active) {
22493  ctx->active = iter->prev;
22494  ctx->end = iter->prev;
22495  if (!ctx->end)
22496  ctx->begin = 0;
22497  if (ctx->active)
22498  ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
22499  }
22500  /* free unused popup windows */
22501  if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
22502  nk_free_window(ctx, iter->popup.win);
22503  iter->popup.win = 0;
22504  }
22505  /* remove unused window state tables */
22506  {struct nk_table *n, *it = iter->tables;
22507  while (it) {
22508  n = it->next;
22509  if (it->seq != ctx->seq) {
22510  nk_remove_table(iter, it);
22511  nk_zero(it, sizeof(union nk_page_data));
22512  nk_free_table(ctx, it);
22513  if (it == iter->tables)
22514  iter->tables = n;
22515  } it = n;
22516  }}
22517  /* window itself is not used anymore so free */
22518  if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
22519  next = iter->next;
22520  nk_remove_window(ctx, iter);
22521  nk_free_window(ctx, iter);
22522  iter = next;
22523  } else iter = iter->next;
22524  }
22525  ctx->seq++;
22526 }
22538 NK_LIB void
22539 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
22540 {
22541  NK_ASSERT(ctx);
22542  NK_ASSERT(buffer);
22543  if (!ctx || !buffer) return;
22544  buffer->begin = ctx->memory.allocated;
22545  buffer->end = buffer->begin;
22546  buffer->last = buffer->begin;
22547  buffer->clip = nk_null_rect;
22548 }
22560 NK_LIB void
22561 nk_start(struct nk_context *ctx, struct nk_window *win)
22562 {
22563  NK_ASSERT(ctx);
22564  NK_ASSERT(win);
22565  nk_start_buffer(ctx, &win->buffer);
22566 }
22578 NK_LIB void
22579 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
22580 {
22581  struct nk_popup_buffer *buf;
22582  NK_ASSERT(ctx);
22583  NK_ASSERT(win);
22584  if (!ctx || !win) return;
22585 
22586  /* save buffer fill state for popup */
22587  buf = &win->popup.buf;
22588  buf->begin = win->buffer.end;
22589  buf->end = win->buffer.end;
22590  buf->parent = win->buffer.last;
22591  buf->last = buf->begin;
22592  buf->active = nk_true;
22593 }
22605 NK_LIB void
22606 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
22607 {
22608  struct nk_popup_buffer *buf;
22609  NK_ASSERT(ctx);
22610  NK_ASSERT(win);
22611  if (!ctx || !win) return;
22612 
22613  buf = &win->popup.buf;
22614  buf->last = win->buffer.last;
22615  buf->end = win->buffer.end;
22616 }
22628 NK_LIB void
22629 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
22630 {
22631  NK_ASSERT(ctx);
22632  NK_ASSERT(buffer);
22633  if (!ctx || !buffer) return;
22634  buffer->end = ctx->memory.allocated;
22635 }
22647 NK_LIB void
22648 nk_finish(struct nk_context *ctx, struct nk_window *win)
22649 {
22650  struct nk_popup_buffer *buf;
22651  struct nk_command *parent_last;
22652  void *memory;
22653 
22654  NK_ASSERT(ctx);
22655  NK_ASSERT(win);
22656  if (!ctx || !win) return;
22657  nk_finish_buffer(ctx, &win->buffer);
22658  if (!win->popup.buf.active) return;
22659 
22660  buf = &win->popup.buf;
22661  memory = ctx->memory.memory.ptr;
22662  parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
22663  parent_last->next = buf->end;
22664 }
22675 NK_LIB void
22676 nk_build(struct nk_context *ctx)
22677 {
22678  struct nk_window *it = 0;
22679  struct nk_command *cmd = 0;
22680  nk_byte *buffer = 0;
22681 
22682  /* draw cursor overlay */
22683  if (!ctx->style.cursor_active)
22684  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
22685  if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
22686  struct nk_rect mouse_bounds;
22687  const struct nk_cursor *cursor = ctx->style.cursor_active;
22688  nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
22689  nk_start_buffer(ctx, &ctx->overlay);
22690 
22691  mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
22692  mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
22693  mouse_bounds.w = cursor->size.x;
22694  mouse_bounds.h = cursor->size.y;
22695 
22696  nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
22697  nk_finish_buffer(ctx, &ctx->overlay);
22698  }
22699  /* build one big draw command list out of all window buffers */
22700  it = ctx->begin;
22701  buffer = (nk_byte*)ctx->memory.memory.ptr;
22702  while (it != 0) {
22703  struct nk_window *next = it->next;
22704  if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
22705  it->seq != ctx->seq)
22706  goto cont;
22707 
22708  cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
22709  while (next && ((next->buffer.last == next->buffer.begin) ||
22710  (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
22711  next = next->next; /* skip empty command buffers */
22712 
22713  if (next) cmd->next = next->buffer.begin;
22714  cont: it = next;
22715  }
22716  /* append all popup draw commands into lists */
22717  it = ctx->begin;
22718  while (it != 0) {
22719  struct nk_window *next = it->next;
22720  struct nk_popup_buffer *buf;
22721  if (!it->popup.buf.active)
22722  goto skip;
22723 
22724  buf = &it->popup.buf;
22725  cmd->next = buf->begin;
22726  cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
22727  buf->active = nk_false;
22728  skip: it = next;
22729  }
22730  if (cmd) {
22731  /* append overlay commands */
22732  if (ctx->overlay.end != ctx->overlay.begin)
22733  cmd->next = ctx->overlay.begin;
22734  else cmd->next = ctx->memory.allocated;
22735  }
22736 }
22747 NK_API const struct nk_command*
22748 nk__begin(struct nk_context *ctx)
22749 {
22750  struct nk_window *iter;
22751  nk_byte *buffer;
22752  NK_ASSERT(ctx);
22753  if (!ctx) return 0;
22754  if (!ctx->count) return 0;
22755 
22756  buffer = (nk_byte*)ctx->memory.memory.ptr;
22757  if (!ctx->build) {
22758  nk_build(ctx);
22759  ctx->build = nk_true;
22760  }
22761  iter = ctx->begin;
22762  while (iter && ((iter->buffer.begin == iter->buffer.end) ||
22763  (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
22764  iter = iter->next;
22765  if (!iter) return 0;
22766  return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
22767 }
22768 
22780 NK_API const struct nk_command*
22781 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
22782 {
22783  nk_byte *buffer;
22784  const struct nk_command *next;
22785  NK_ASSERT(ctx);
22786  if (!ctx || !cmd || !ctx->count) return 0;
22787  if (cmd->next >= ctx->memory.allocated) return 0;
22788  buffer = (nk_byte*)ctx->memory.memory.ptr;
22789  next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
22790  return next;
22791 }
22792 
22793 
22794 
22795 
22796 
22797 
22798 /* ===============================================================
22799  *
22800  * POOL
22801  *
22802  * ===============================================================*/
22814 NK_LIB void
22815 nk_pool_init(struct nk_pool *pool, const struct nk_allocator *alloc,
22816  unsigned int capacity)
22817 {
22818  NK_ASSERT(capacity >= 1);
22819  nk_zero(pool, sizeof(*pool));
22820  pool->alloc = *alloc;
22821  pool->capacity = capacity;
22822  pool->type = NK_BUFFER_DYNAMIC;
22823  pool->pages = 0;
22824 }
22835 NK_LIB void
22836 nk_pool_free(struct nk_pool *pool)
22837 {
22838  struct nk_page *iter;
22839  if (!pool) return;
22840  iter = pool->pages;
22841  if (pool->type == NK_BUFFER_FIXED) return;
22842  while (iter) {
22843  struct nk_page *next = iter->next;
22844  pool->alloc.free(pool->alloc.userdata, iter);
22845  iter = next;
22846  }
22847 }
22860 NK_LIB void
22861 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
22862 {
22863  nk_zero(pool, sizeof(*pool));
22864  NK_ASSERT(size >= sizeof(struct nk_page));
22865  if (size < sizeof(struct nk_page)) return;
22866  /* first nk_page_element is embedded in nk_page, additional elements follow in adjacent space */
22867  pool->capacity = (unsigned)(1 + (size - sizeof(struct nk_page)) / sizeof(struct nk_page_element));
22868  pool->pages = (struct nk_page*)memory;
22869  pool->type = NK_BUFFER_FIXED;
22870  pool->size = size;
22871 }
22882 NK_LIB struct nk_page_element*
22883 nk_pool_alloc(struct nk_pool *pool)
22884 {
22885  if (!pool->pages || pool->pages->size >= pool->capacity) {
22886  /* allocate new page */
22887  struct nk_page *page;
22888  if (pool->type == NK_BUFFER_FIXED) {
22889  NK_ASSERT(pool->pages);
22890  if (!pool->pages) return 0;
22891  NK_ASSERT(pool->pages->size < pool->capacity);
22892  return 0;
22893  } else {
22894  nk_size size = sizeof(struct nk_page);
22895  size += (pool->capacity - 1) * sizeof(struct nk_page_element);
22896  page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
22897  page->next = pool->pages;
22898  pool->pages = page;
22899  page->size = 0;
22900  }
22901  } return &pool->pages->win[pool->pages->size++];
22902 }
22903 
22904 
22905 
22906 
22907 
22908 /* ===============================================================
22909  *
22910  * PAGE ELEMENT
22911  *
22912  * ===============================================================*/
22923 NK_LIB struct nk_page_element*
22924 nk_create_page_element(struct nk_context *ctx)
22925 {
22926  struct nk_page_element *elem;
22927  if (ctx->freelist) {
22928  /* unlink page element from free list */
22929  elem = ctx->freelist;
22930  ctx->freelist = elem->next;
22931  } else if (ctx->use_pool) {
22932  /* allocate page element from memory pool */
22933  elem = nk_pool_alloc(&ctx->pool);
22934  NK_ASSERT(elem);
22935  if (!elem) return 0;
22936  } else {
22937  /* allocate new page element from back of fixed size memory buffer */
22938  NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
22939  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
22940  elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
22941  NK_ASSERT(elem);
22942  if (!elem) return 0;
22943  }
22944  nk_zero_struct(*elem);
22945  elem->next = 0;
22946  elem->prev = 0;
22947  return elem;
22948 }
22959 NK_LIB void
22960 nk_link_page_element_into_freelist(struct nk_context *ctx,
22961  struct nk_page_element *elem)
22962 {
22963  /* link table into freelist */
22964  if (!ctx->freelist) {
22965  ctx->freelist = elem;
22966  } else {
22967  elem->next = ctx->freelist;
22968  ctx->freelist = elem;
22969  }
22970 }
22982 NK_LIB void
22983 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
22984 {
22985  /* we have a pool so just add to free list */
22986  if (ctx->use_pool) {
22987  nk_link_page_element_into_freelist(ctx, elem);
22988  return;
22989  }
22990  /* if possible remove last element from back of fixed memory buffer */
22991  {void *elem_end = (void*)(elem + 1);
22992  void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
22993  if (elem_end == buffer_end)
22994  ctx->memory.size -= sizeof(struct nk_page_element);
22995  else nk_link_page_element_into_freelist(ctx, elem);}
22996 }
22997 
22998 
22999 
23000 
23001 
23002 /* ===============================================================
23003  *
23004  * TABLE
23005  *
23006  * ===============================================================*/
23017 NK_LIB struct nk_table*
23018 nk_create_table(struct nk_context *ctx)
23019 {
23020  struct nk_page_element *elem;
23021  elem = nk_create_page_element(ctx);
23022  if (!elem) return 0;
23023  nk_zero_struct(*elem);
23024  return &elem->data.tbl;
23025 }
23037 NK_LIB void
23038 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
23039 {
23040  union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
23041  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
23042  nk_free_page_element(ctx, pe);
23043 }
23055 NK_LIB void
23056 nk_push_table(struct nk_window *win, struct nk_table *tbl)
23057 {
23058  if (!win->tables) {
23059  win->tables = tbl;
23060  tbl->next = 0;
23061  tbl->prev = 0;
23062  tbl->size = 0;
23063  win->table_count = 1;
23064  return;
23065  }
23066  win->tables->prev = tbl;
23067  tbl->next = win->tables;
23068  tbl->prev = 0;
23069  tbl->size = 0;
23070  win->tables = tbl;
23071  win->table_count++;
23072 }
23084 NK_LIB void
23085 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
23086 {
23087  if (win->tables == tbl)
23088  win->tables = tbl->next;
23089  if (tbl->next)
23090  tbl->next->prev = tbl->prev;
23091  if (tbl->prev)
23092  tbl->prev->next = tbl->next;
23093  tbl->next = 0;
23094  tbl->prev = 0;
23095 }
23107 NK_LIB nk_uint*
23108 nk_add_value(struct nk_context *ctx, struct nk_window *win,
23109  nk_hash name, nk_uint value)
23110 {
23111  NK_ASSERT(ctx);
23112  NK_ASSERT(win);
23113  if (!win || !ctx) return 0;
23114  if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
23115  struct nk_table *tbl = nk_create_table(ctx);
23116  NK_ASSERT(tbl);
23117  if (!tbl) return 0;
23118  nk_push_table(win, tbl);
23119  }
23120  win->tables->seq = win->seq;
23121  win->tables->keys[win->tables->size] = name;
23122  win->tables->values[win->tables->size] = value;
23123  return &win->tables->values[win->tables->size++];
23124 }
23136 NK_LIB nk_uint*
23137 nk_find_value(const struct nk_window *win, nk_hash name)
23138 {
23139  struct nk_table *iter = win->tables;
23140  while (iter) {
23141  unsigned int i = 0;
23142  unsigned int size = iter->size;
23143  for (i = 0; i < size; ++i) {
23144  if (iter->keys[i] == name) {
23145  iter->seq = win->seq;
23146  return &iter->values[i];
23147  }
23148  } size = NK_VALUE_PAGE_CAPACITY;
23149  iter = iter->next;
23150  }
23151  return 0;
23152 }
23153 
23154 
23155 
23156 
23157 /* ===============================================================
23158  *
23159  * PANEL
23160  *
23161  * ===============================================================*/
23172 NK_LIB void*
23173 nk_create_panel(struct nk_context *ctx)
23174 {
23175  struct nk_page_element *elem;
23176  elem = nk_create_page_element(ctx);
23177  if (!elem) return 0;
23178  nk_zero_struct(*elem);
23179  return &elem->data.pan;
23180 }
23192 NK_LIB void
23193 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
23194 {
23195  union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
23196  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
23197  nk_free_page_element(ctx, pe);
23198 }
23210 NK_LIB nk_bool
23211 nk_panel_has_header(nk_flags flags, const char *title)
23212 {
23213  nk_bool active = 0;
23214  active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
23215  active = active || (flags & NK_WINDOW_TITLE);
23216  active = active && !(flags & NK_WINDOW_HIDDEN) && title;
23217  return active;
23218 }
23230 NK_LIB struct nk_vec2
23231 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
23232 {
23233  switch (type) {
23234  default:
23235  case NK_PANEL_WINDOW: return style->window.padding;
23236  case NK_PANEL_GROUP: return style->window.group_padding;
23237  case NK_PANEL_POPUP: return style->window.popup_padding;
23238  case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
23239  case NK_PANEL_COMBO: return style->window.combo_padding;
23240  case NK_PANEL_MENU: return style->window.menu_padding;
23241  case NK_PANEL_TOOLTIP: return style->window.menu_padding;}
23242 }
23254 NK_LIB float
23255 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
23256  enum nk_panel_type type)
23257 {
23258  if (flags & NK_WINDOW_BORDER) {
23259  switch (type) {
23260  default:
23261  case NK_PANEL_WINDOW: return style->window.border;
23262  case NK_PANEL_GROUP: return style->window.group_border;
23263  case NK_PANEL_POPUP: return style->window.popup_border;
23264  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
23265  case NK_PANEL_COMBO: return style->window.combo_border;
23266  case NK_PANEL_MENU: return style->window.menu_border;
23267  case NK_PANEL_TOOLTIP: return style->window.menu_border;
23268  }} else return 0;
23269 }
23281 NK_LIB struct nk_color
23282 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
23283 {
23284  switch (type) {
23285  default:
23286  case NK_PANEL_WINDOW: return style->window.border_color;
23287  case NK_PANEL_GROUP: return style->window.group_border_color;
23288  case NK_PANEL_POPUP: return style->window.popup_border_color;
23289  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
23290  case NK_PANEL_COMBO: return style->window.combo_border_color;
23291  case NK_PANEL_MENU: return style->window.menu_border_color;
23292  case NK_PANEL_TOOLTIP: return style->window.menu_border_color;}
23293 }
23304 NK_LIB nk_bool
23305 nk_panel_is_sub(enum nk_panel_type type)
23306 {
23307  return ((int)type & (int)NK_PANEL_SET_SUB)?1:0;
23308 }
23319 NK_LIB nk_bool
23320 nk_panel_is_nonblock(enum nk_panel_type type)
23321 {
23322  return ((int)type & (int)NK_PANEL_SET_NONBLOCK)?1:0;
23323 }
23336 NK_LIB nk_bool
23337 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
23338 {
23339  struct nk_input *in;
23340  struct nk_window *win;
23341  struct nk_panel *layout;
23342  struct nk_command_buffer *out;
23343  const struct nk_style *style;
23344  const struct nk_user_font *font;
23345 
23346  struct nk_vec2 scrollbar_size;
23347  struct nk_vec2 panel_padding;
23348 
23349  NK_ASSERT(ctx);
23350  NK_ASSERT(ctx->current);
23351  NK_ASSERT(ctx->current->layout);
23352  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
23353  nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
23354  if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
23355  nk_zero(ctx->current->layout, sizeof(struct nk_panel));
23356  ctx->current->layout->type = panel_type;
23357  return 0;
23358  }
23359  /* pull state into local stack */
23360  style = &ctx->style;
23361  font = style->font;
23362  win = ctx->current;
23363  layout = win->layout;
23364  out = &win->buffer;
23365  in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
23366 #ifdef NK_INCLUDE_COMMAND_USERDATA
23367  win->buffer.userdata = ctx->userdata;
23368 #endif
23369  /* pull style configuration into local stack */
23370  scrollbar_size = style->window.scrollbar_size;
23371  panel_padding = nk_panel_get_padding(style, panel_type);
23372 
23373  /* window movement */
23374  if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
23375  nk_bool left_mouse_down;
23376  unsigned int left_mouse_clicked;
23377  int left_mouse_click_in_cursor;
23378 
23379  /* calculate draggable window space */
23380  struct nk_rect header;
23381  header.x = win->bounds.x;
23382  header.y = win->bounds.y;
23383  header.w = win->bounds.w;
23384  if (nk_panel_has_header(win->flags, title)) {
23385  header.h = font->height + 2.0f * style->window.header.padding.y;
23386  header.h += 2.0f * style->window.header.label_padding.y;
23387  } else header.h = panel_padding.y;
23388 
23389  /* window movement by dragging */
23390  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
23391  left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked;
23392  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
23393  NK_BUTTON_LEFT, header, nk_true);
23394  if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
23395  win->bounds.x = win->bounds.x + in->mouse.delta.x;
23396  win->bounds.y = win->bounds.y + in->mouse.delta.y;
23397  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
23398  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
23399  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
23400  }
23401  }
23402 
23403  /* setup panel */
23404  layout->type = panel_type;
23405  layout->flags = win->flags;
23406  layout->bounds = win->bounds;
23407  layout->bounds.x += panel_padding.x;
23408  layout->bounds.w -= 2*panel_padding.x;
23409  if (win->flags & NK_WINDOW_BORDER) {
23410  layout->border = nk_panel_get_border(style, win->flags, panel_type);
23411  layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
23412  } else layout->border = 0;
23413  layout->at_y = layout->bounds.y;
23414  layout->at_x = layout->bounds.x;
23415  layout->max_x = 0;
23416  layout->header_height = 0;
23417  layout->footer_height = 0;
23419  layout->row.index = 0;
23420  layout->row.columns = 0;
23421  layout->row.ratio = 0;
23422  layout->row.item_width = 0;
23423  layout->row.tree_depth = 0;
23424  layout->row.height = panel_padding.y;
23425  layout->has_scrolling = nk_true;
23426  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
23427  layout->bounds.w -= scrollbar_size.x;
23428  if (!nk_panel_is_nonblock(panel_type)) {
23429  layout->footer_height = 0;
23430  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
23431  layout->footer_height = scrollbar_size.y;
23432  layout->bounds.h -= layout->footer_height;
23433  }
23434 
23435  /* panel header */
23436  if (nk_panel_has_header(win->flags, title))
23437  {
23438  struct nk_text text;
23439  struct nk_rect header;
23440  const struct nk_style_item *background = 0;
23441 
23442  /* calculate header bounds */
23443  header.x = win->bounds.x;
23444  header.y = win->bounds.y;
23445  header.w = win->bounds.w;
23446  header.h = font->height + 2.0f * style->window.header.padding.y;
23447  header.h += (2.0f * style->window.header.label_padding.y);
23448 
23449  /* shrink panel by header */
23450  layout->header_height = header.h;
23451  layout->bounds.y += header.h;
23452  layout->bounds.h -= header.h;
23453  layout->at_y += header.h;
23454 
23455  /* select correct header background and text color */
23456  if (ctx->active == win) {
23457  background = &style->window.header.active;
23458  text.text = style->window.header.label_active;
23459  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
23460  background = &style->window.header.hover;
23461  text.text = style->window.header.label_hover;
23462  } else {
23463  background = &style->window.header.normal;
23464  text.text = style->window.header.label_normal;
23465  }
23466 
23467  /* draw header background */
23468  header.h += 1.0f;
23469 
23470  switch(background->type) {
23471  case NK_STYLE_ITEM_IMAGE:
23472  text.background = nk_rgba(0,0,0,0);
23473  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23474  break;
23475  case NK_STYLE_ITEM_NINE_SLICE:
23476  text.background = nk_rgba(0, 0, 0, 0);
23477  nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
23478  break;
23479  case NK_STYLE_ITEM_COLOR:
23480  text.background = background->data.color;
23481  nk_fill_rect(out, header, 0, background->data.color);
23482  break;
23483  }
23484 
23485  /* window close button */
23486  {struct nk_rect button;
23487  button.y = header.y + style->window.header.padding.y;
23488  button.h = header.h - 2 * style->window.header.padding.y;
23489  button.w = button.h;
23490  if (win->flags & NK_WINDOW_CLOSABLE) {
23491  nk_flags ws = 0;
23492  if (style->window.header.align == NK_HEADER_RIGHT) {
23493  button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
23494  header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
23495  } else {
23496  button.x = header.x + style->window.header.padding.x;
23497  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
23498  }
23499 
23500  if (nk_do_button_symbol(&ws, &win->buffer, button,
23501  style->window.header.close_symbol, NK_BUTTON_DEFAULT,
23502  &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
23503  {
23504  layout->flags |= NK_WINDOW_HIDDEN;
23505  layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
23506  }
23507  }
23508 
23509  /* window minimize button */
23510  if (win->flags & NK_WINDOW_MINIMIZABLE) {
23511  nk_flags ws = 0;
23512  if (style->window.header.align == NK_HEADER_RIGHT) {
23513  button.x = (header.w + header.x) - button.w;
23514  if (!(win->flags & NK_WINDOW_CLOSABLE)) {
23515  button.x -= style->window.header.padding.x;
23516  header.w -= style->window.header.padding.x;
23517  }
23518  header.w -= button.w + style->window.header.spacing.x;
23519  } else {
23520  button.x = header.x;
23521  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
23522  }
23523  if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
23524  style->window.header.maximize_symbol: style->window.header.minimize_symbol,
23525  NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
23526  layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
23527  layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
23528  layout->flags | NK_WINDOW_MINIMIZED;
23529  }}
23530 
23531  {/* window header title */
23532  int text_len = nk_strlen(title);
23533  struct nk_rect label = {0,0,0,0};
23534  float t = font->width(font->userdata, font->height, title, text_len);
23535  text.padding = nk_vec2(0,0);
23536 
23537  label.x = header.x + style->window.header.padding.x;
23538  label.x += style->window.header.label_padding.x;
23539  label.y = header.y + style->window.header.label_padding.y;
23540  label.h = font->height + 2 * style->window.header.label_padding.y;
23541  label.w = t + 2 * style->window.header.spacing.x;
23542  label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
23543  nk_widget_text(out, label, (const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
23544  }
23545 
23546  /* draw window background */
23547  if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
23548  struct nk_rect body;
23549  body.x = win->bounds.x;
23550  body.w = win->bounds.w;
23551  body.y = (win->bounds.y + layout->header_height);
23552  body.h = (win->bounds.h - layout->header_height);
23553 
23554  switch(style->window.fixed_background.type) {
23555  case NK_STYLE_ITEM_IMAGE:
23556  nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
23557  break;
23558  case NK_STYLE_ITEM_NINE_SLICE:
23559  nk_draw_nine_slice(out, body, &style->window.fixed_background.data.slice, nk_white);
23560  break;
23561  case NK_STYLE_ITEM_COLOR:
23562  nk_fill_rect(out, body, style->window.rounding, style->window.fixed_background.data.color);
23563  break;
23564  }
23565  }
23566 
23567  /* set clipping rectangle */
23568  {struct nk_rect clip;
23569  layout->clip = layout->bounds;
23570  nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
23571  layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
23572  nk_push_scissor(out, clip);
23573  layout->clip = clip;}
23574  return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
23575 }
23586 NK_LIB void
23587 nk_panel_end(struct nk_context *ctx)
23588 {
23589  struct nk_input *in;
23590  struct nk_window *window;
23591  struct nk_panel *layout;
23592  const struct nk_style *style;
23593  struct nk_command_buffer *out;
23594 
23595  struct nk_vec2 scrollbar_size;
23596  struct nk_vec2 panel_padding;
23597 
23598  NK_ASSERT(ctx);
23599  NK_ASSERT(ctx->current);
23600  NK_ASSERT(ctx->current->layout);
23601  if (!ctx || !ctx->current || !ctx->current->layout)
23602  return;
23603 
23604  window = ctx->current;
23605  layout = window->layout;
23606  style = &ctx->style;
23607  out = &window->buffer;
23608  in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
23609  if (!nk_panel_is_sub(layout->type))
23610  nk_push_scissor(out, nk_null_rect);
23611 
23612  /* cache configuration data */
23613  scrollbar_size = style->window.scrollbar_size;
23614  panel_padding = nk_panel_get_padding(style, layout->type);
23615 
23616  /* update the current cursor Y-position to point over the last added widget */
23617  layout->at_y += layout->row.height;
23618 
23619  /* dynamic panels */
23620  if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
23621  {
23622  /* update panel height to fit dynamic growth */
23623  struct nk_rect empty_space;
23624  if (layout->at_y < (layout->bounds.y + layout->bounds.h))
23625  layout->bounds.h = layout->at_y - layout->bounds.y;
23626 
23627  /* fill top empty space */
23628  empty_space.x = window->bounds.x;
23629  empty_space.y = layout->bounds.y;
23630  empty_space.h = panel_padding.y;
23631  empty_space.w = window->bounds.w;
23632  nk_fill_rect(out, empty_space, 0, style->window.background);
23633 
23634  /* fill left empty space */
23635  empty_space.x = window->bounds.x;
23636  empty_space.y = layout->bounds.y;
23637  empty_space.w = panel_padding.x + layout->border;
23638  empty_space.h = layout->bounds.h;
23639  nk_fill_rect(out, empty_space, 0, style->window.background);
23640 
23641  /* fill right empty space */
23642  empty_space.x = layout->bounds.x + layout->bounds.w;
23643  empty_space.y = layout->bounds.y;
23644  empty_space.w = panel_padding.x + layout->border;
23645  empty_space.h = layout->bounds.h;
23646  if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
23647  empty_space.w += scrollbar_size.x;
23648  nk_fill_rect(out, empty_space, 0, style->window.background);
23649 
23650  /* fill bottom empty space */
23651  if (layout->footer_height > 0) {
23652  empty_space.x = window->bounds.x;
23653  empty_space.y = layout->bounds.y + layout->bounds.h;
23654  empty_space.w = window->bounds.w;
23655  empty_space.h = layout->footer_height;
23656  nk_fill_rect(out, empty_space, 0, style->window.background);
23657  }
23658  }
23659 
23660  /* scrollbars */
23661  if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
23662  !(layout->flags & NK_WINDOW_MINIMIZED) &&
23663  window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
23664  {
23665  struct nk_rect scroll;
23666  int scroll_has_scrolling;
23667  float scroll_target;
23668  float scroll_offset;
23669  float scroll_step;
23670  float scroll_inc;
23671 
23672  /* mouse wheel scrolling */
23673  if (nk_panel_is_sub(layout->type))
23674  {
23675  /* sub-window mouse wheel scrolling */
23676  struct nk_window *root_window = window;
23677  struct nk_panel *root_panel = window->layout;
23678  while (root_panel->parent)
23679  root_panel = root_panel->parent;
23680  while (root_window->parent)
23681  root_window = root_window->parent;
23682 
23683  /* only allow scrolling if parent window is active */
23684  scroll_has_scrolling = 0;
23685  if ((root_window == ctx->active) && layout->has_scrolling) {
23686  /* and panel is being hovered and inside clip rect*/
23687  if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
23688  NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
23689  root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
23690  {
23691  /* deactivate all parent scrolling */
23692  root_panel = window->layout;
23693  while (root_panel->parent) {
23694  root_panel->has_scrolling = nk_false;
23695  root_panel = root_panel->parent;
23696  }
23697  root_panel->has_scrolling = nk_false;
23698  scroll_has_scrolling = nk_true;
23699  }
23700  }
23701  } else if (!nk_panel_is_sub(layout->type)) {
23702  /* window mouse wheel scrolling */
23703  scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
23704  if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
23705  window->scrolled = nk_true;
23706  else window->scrolled = nk_false;
23707  } else scroll_has_scrolling = nk_false;
23708 
23709  {
23710  /* vertical scrollbar */
23711  nk_flags state = 0;
23712  scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
23713  scroll.y = layout->bounds.y;
23714  scroll.w = scrollbar_size.x;
23715  scroll.h = layout->bounds.h;
23716 
23717  scroll_offset = (float)*layout->offset_y;
23718  scroll_step = scroll.h * 0.10f;
23719  scroll_inc = scroll.h * 0.01f;
23720  scroll_target = (float)(int)(layout->at_y - scroll.y);
23721  scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
23722  scroll_offset, scroll_target, scroll_step, scroll_inc,
23723  &ctx->style.scrollv, in, style->font);
23724  *layout->offset_y = (nk_uint)scroll_offset;
23725  if (in && scroll_has_scrolling)
23726  in->mouse.scroll_delta.y = 0;
23727  }
23728  {
23729  /* horizontal scrollbar */
23730  nk_flags state = 0;
23731  scroll.x = layout->bounds.x;
23732  scroll.y = layout->bounds.y + layout->bounds.h;
23733  scroll.w = layout->bounds.w;
23734  scroll.h = scrollbar_size.y;
23735 
23736  scroll_offset = (float)*layout->offset_x;
23737  scroll_target = (float)(int)(layout->max_x - scroll.x);
23738  scroll_step = layout->max_x * 0.05f;
23739  scroll_inc = layout->max_x * 0.005f;
23740  scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
23741  scroll_offset, scroll_target, scroll_step, scroll_inc,
23742  &ctx->style.scrollh, in, style->font);
23743  *layout->offset_x = (nk_uint)scroll_offset;
23744  }
23745  }
23746 
23747  /* hide scroll if no user input */
23748  if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
23749  int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
23750  int is_window_hovered = nk_window_is_hovered(ctx);
23751  int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
23752  if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
23753  window->scrollbar_hiding_timer += ctx->delta_time_seconds;
23754  else window->scrollbar_hiding_timer = 0;
23755  } else window->scrollbar_hiding_timer = 0;
23756 
23757  /* window border */
23758  if (layout->flags & NK_WINDOW_BORDER)
23759  {
23760  struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
23761  const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED)
23762  ? (style->window.border + window->bounds.y + layout->header_height)
23763  : ((layout->flags & NK_WINDOW_DYNAMIC)
23764  ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
23765  : (window->bounds.y + window->bounds.h));
23766  struct nk_rect b = window->bounds;
23767  b.h = padding_y - window->bounds.y;
23768  nk_stroke_rect(out, b, style->window.rounding, layout->border, border_color);
23769  }
23770 
23771  /* scaler */
23772  if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
23773  {
23774  /* calculate scaler bounds */
23775  struct nk_rect scaler;
23776  scaler.w = scrollbar_size.x;
23777  scaler.h = scrollbar_size.y;
23778  scaler.y = layout->bounds.y + layout->bounds.h;
23779  if (layout->flags & NK_WINDOW_SCALE_LEFT)
23780  scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
23781  else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
23782  if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
23783  scaler.x -= scaler.w;
23784 
23785  /* draw scaler */
23786  {const struct nk_style_item *item = &style->window.scaler;
23787  if (item->type == NK_STYLE_ITEM_IMAGE)
23788  nk_draw_image(out, scaler, &item->data.image, nk_white);
23789  else {
23790  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
23791  nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
23792  scaler.y + scaler.h, scaler.x + scaler.w,
23793  scaler.y + scaler.h, item->data.color);
23794  } else {
23795  nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
23796  scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
23797  }
23798  }}
23799 
23800  /* do window scaling */
23801  if (!(window->flags & NK_WINDOW_ROM)) {
23802  struct nk_vec2 window_size = style->window.min_size;
23803  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
23804  int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
23805  NK_BUTTON_LEFT, scaler, nk_true);
23806 
23807  if (left_mouse_down && left_mouse_click_in_scaler) {
23808  float delta_x = in->mouse.delta.x;
23809  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
23810  delta_x = -delta_x;
23811  window->bounds.x += in->mouse.delta.x;
23812  }
23813  /* dragging in x-direction */
23814  if (window->bounds.w + delta_x >= window_size.x) {
23815  if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
23816  window->bounds.w = window->bounds.w + delta_x;
23817  scaler.x += in->mouse.delta.x;
23818  }
23819  }
23820  /* dragging in y-direction (only possible if static window) */
23821  if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
23822  if (window_size.y < window->bounds.h + in->mouse.delta.y) {
23823  if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
23824  window->bounds.h = window->bounds.h + in->mouse.delta.y;
23825  scaler.y += in->mouse.delta.y;
23826  }
23827  }
23828  }
23829  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
23830  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
23831  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
23832  }
23833  }
23834  }
23835  if (!nk_panel_is_sub(layout->type)) {
23836  /* window is hidden so clear command buffer */
23837  if (layout->flags & NK_WINDOW_HIDDEN)
23838  nk_command_buffer_reset(&window->buffer);
23839  /* window is visible and not tab */
23840  else nk_finish(ctx, window);
23841  }
23842 
23843  /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
23844  if (layout->flags & NK_WINDOW_REMOVE_ROM) {
23845  layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
23846  layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
23847  }
23848  window->flags = layout->flags;
23849 
23850  /* property garbage collector */
23851  if (window->property.active && window->property.old != window->property.seq &&
23852  window->property.active == window->property.prev) {
23853  nk_zero(&window->property, sizeof(window->property));
23854  } else {
23855  window->property.old = window->property.seq;
23856  window->property.prev = window->property.active;
23857  window->property.seq = 0;
23858  }
23859  /* edit garbage collector */
23860  if (window->edit.active && window->edit.old != window->edit.seq &&
23861  window->edit.active == window->edit.prev) {
23862  nk_zero(&window->edit, sizeof(window->edit));
23863  } else {
23864  window->edit.old = window->edit.seq;
23865  window->edit.prev = window->edit.active;
23866  window->edit.seq = 0;
23867  }
23868  /* contextual garbage collector */
23869  if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
23870  window->popup.con_count = 0;
23871  window->popup.con_old = 0;
23872  window->popup.active_con = 0;
23873  } else {
23874  window->popup.con_old = window->popup.con_count;
23875  window->popup.con_count = 0;
23876  }
23877  window->popup.combo_count = 0;
23878  /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
23879  NK_ASSERT(!layout->row.tree_depth);
23880 }
23881 
23882 
23883 
23884 
23885 
23886 /* ===============================================================
23887  *
23888  * WINDOW
23889  *
23890  * ===============================================================*/
23901 NK_LIB void*
23902 nk_create_window(struct nk_context *ctx)
23903 {
23904  struct nk_page_element *elem;
23905  elem = nk_create_page_element(ctx);
23906  if (!elem) return 0;
23907  elem->data.win.seq = ctx->seq;
23908  return &elem->data.win;
23909 }
23921 NK_LIB void
23922 nk_free_window(struct nk_context *ctx, struct nk_window *win)
23923 {
23924  /* unlink windows from list */
23925  struct nk_table *it = win->tables;
23926  if (win->popup.win) {
23927  nk_free_window(ctx, win->popup.win);
23928  win->popup.win = 0;
23929  }
23930  win->next = 0;
23931  win->prev = 0;
23932 
23933  while (it) {
23934  /*free window state tables */
23935  struct nk_table *n = it->next;
23936  nk_remove_table(win, it);
23937  nk_free_table(ctx, it);
23938  if (it == win->tables)
23939  win->tables = n;
23940  it = n;
23941  }
23942 
23943  /* link windows into freelist */
23944  {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
23945  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
23946  nk_free_page_element(ctx, pe);}
23947 }
23960 NK_LIB struct nk_window*
23961 nk_find_window(const struct nk_context *ctx, nk_hash hash, const char *name)
23962 {
23963  struct nk_window *iter;
23964  iter = ctx->begin;
23965  while (iter) {
23966  NK_ASSERT(iter != iter->next);
23967  if (iter->name == hash) {
23968  int max_len = nk_strlen(iter->name_string);
23969  if (!nk_stricmpn(iter->name_string, name, max_len))
23970  return iter;
23971  }
23972  iter = iter->next;
23973  }
23974  return 0;
23975 }
23987 NK_LIB void
23988 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
23989  enum nk_window_insert_location loc)
23990 {
23991  const struct nk_window *iter;
23992  NK_ASSERT(ctx);
23993  NK_ASSERT(win);
23994  if (!win || !ctx) return;
23995 
23996  iter = ctx->begin;
23997  while (iter) {
23998  NK_ASSERT(iter != iter->next);
23999  NK_ASSERT(iter != win);
24000  if (iter == win) return;
24001  iter = iter->next;
24002  }
24003 
24004  if (!ctx->begin) {
24005  win->next = 0;
24006  win->prev = 0;
24007  ctx->begin = win;
24008  ctx->end = win;
24009  ctx->count = 1;
24010  return;
24011  }
24012  if (loc == NK_INSERT_BACK) {
24013  struct nk_window *end;
24014  end = ctx->end;
24015  end->flags |= NK_WINDOW_ROM;
24016  end->next = win;
24017  win->prev = ctx->end;
24018  win->next = 0;
24019  ctx->end = win;
24020  ctx->active = ctx->end;
24021  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
24022  } else {
24023  /*ctx->end->flags |= NK_WINDOW_ROM;*/
24024  ctx->begin->prev = win;
24025  win->next = ctx->begin;
24026  win->prev = 0;
24027  ctx->begin = win;
24028  ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
24029  }
24030  ctx->count++;
24031 }
24043 NK_LIB void
24044 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
24045 {
24046  if (win == ctx->begin || win == ctx->end) {
24047  if (win == ctx->begin) {
24048  ctx->begin = win->next;
24049  if (win->next)
24050  win->next->prev = 0;
24051  }
24052  if (win == ctx->end) {
24053  ctx->end = win->prev;
24054  if (win->prev)
24055  win->prev->next = 0;
24056  }
24057  } else {
24058  if (win->next)
24059  win->next->prev = win->prev;
24060  if (win->prev)
24061  win->prev->next = win->next;
24062  }
24063  if (win == ctx->active || !ctx->active) {
24064  ctx->active = ctx->end;
24065  if (ctx->end)
24066  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
24067  }
24068  win->next = 0;
24069  win->prev = 0;
24070  ctx->count--;
24071 }
24083 NK_API nk_bool
24084 nk_begin(struct nk_context *ctx, const char *title,
24085  struct nk_rect bounds, nk_flags flags)
24086 {
24087  return nk_begin_titled(ctx, title, title, bounds, flags);
24088 }
24101 NK_API nk_bool
24102 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
24103  struct nk_rect bounds, nk_flags flags)
24104 {
24105  struct nk_window *win;
24106  struct nk_style *style;
24107  nk_hash name_hash;
24108  int name_len;
24109  int ret = 0;
24110 
24111  NK_ASSERT(ctx);
24112  NK_ASSERT(name);
24113  NK_ASSERT(title);
24114  NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
24115  NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
24116  if (!ctx || ctx->current || !title || !name)
24117  return 0;
24118 
24119  /* find or create window */
24120  style = &ctx->style;
24121  name_len = (int)nk_strlen(name);
24122  name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE);
24123  win = nk_find_window(ctx, name_hash, name);
24124  if (!win) {
24125  /* create new window */
24126  nk_size name_length = (nk_size)name_len;
24127  win = (struct nk_window*)nk_create_window(ctx);
24128  NK_ASSERT(win);
24129  if (!win) return 0;
24130 
24131  if (flags & NK_WINDOW_BACKGROUND)
24132  nk_insert_window(ctx, win, NK_INSERT_FRONT);
24133  else nk_insert_window(ctx, win, NK_INSERT_BACK);
24134  nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
24135 
24136  win->flags = flags;
24137  win->bounds = bounds;
24138  win->name = name_hash;
24139  name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
24140  NK_MEMCPY(win->name_string, name, name_length);
24141  win->name_string[name_length] = 0;
24142  win->popup.win = 0;
24143  win->widgets_disabled = nk_false;
24144  if (!ctx->active)
24145  ctx->active = win;
24146  } else {
24147  /* update window */
24148  win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
24149  win->flags |= flags;
24150  if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
24151  win->bounds = bounds;
24152  /* If this assert triggers you either:
24153  *
24154  * I.) Have more than one window with the same name or
24155  * II.) You forgot to actually draw the window.
24156  * More specific you did not call `nk_clear` (nk_clear will be
24157  * automatically called for you if you are using one of the
24158  * provided demo backends). */
24159  NK_ASSERT(win->seq != ctx->seq);
24160  win->seq = ctx->seq;
24161  if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
24162  ctx->active = win;
24163  ctx->end = win;
24164  }
24165  }
24166  if (win->flags & NK_WINDOW_HIDDEN) {
24167  ctx->current = win;
24168  win->layout = 0;
24169  return 0;
24170  } else nk_start(ctx, win);
24171 
24172  /* window overlapping */
24173  if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
24174  {
24175  int inpanel, ishovered;
24176  struct nk_window *iter = win;
24177  float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
24178  (2.0f * style->window.header.label_padding.y);
24179  struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
24180  win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
24181 
24182  /* activate window if hovered and no other window is overlapping this window */
24183  inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
24184  inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
24185  ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
24186  if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
24187  iter = win->next;
24188  while (iter) {
24189  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
24190  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
24191  if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
24192  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
24193  (!(iter->flags & NK_WINDOW_HIDDEN)))
24194  break;
24195 
24196  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
24197  NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
24198  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
24199  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
24200  break;
24201  iter = iter->next;
24202  }
24203  }
24204 
24205  /* activate window if clicked */
24206  if (iter && inpanel && (win != ctx->end)) {
24207  iter = win->next;
24208  while (iter) {
24209  /* try to find a panel with higher priority in the same position */
24210  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
24211  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
24212  if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
24213  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
24214  !(iter->flags & NK_WINDOW_HIDDEN))
24215  break;
24216  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
24217  NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
24218  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
24219  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
24220  break;
24221  iter = iter->next;
24222  }
24223  }
24224  if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
24225  win->flags |= (nk_flags)NK_WINDOW_ROM;
24226  iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
24227  ctx->active = iter;
24228  if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
24229  /* current window is active in that position so transfer to top
24230  * at the highest priority in stack */
24231  nk_remove_window(ctx, iter);
24232  nk_insert_window(ctx, iter, NK_INSERT_BACK);
24233  }
24234  } else {
24235  if (!iter && ctx->end != win) {
24236  if (!(win->flags & NK_WINDOW_BACKGROUND)) {
24237  /* current window is active in that position so transfer to top
24238  * at the highest priority in stack */
24239  nk_remove_window(ctx, win);
24240  nk_insert_window(ctx, win, NK_INSERT_BACK);
24241  }
24242  win->flags &= ~(nk_flags)NK_WINDOW_ROM;
24243  ctx->active = win;
24244  }
24245  if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
24246  win->flags |= NK_WINDOW_ROM;
24247  }
24248  }
24249  win->layout = (struct nk_panel*)nk_create_panel(ctx);
24250  ctx->current = win;
24251  ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
24252  win->layout->offset_x = &win->scrollbar.x;
24253  win->layout->offset_y = &win->scrollbar.y;
24254  return ret;
24255 }
24266 NK_API void
24267 nk_end(struct nk_context *ctx)
24268 {
24269  struct nk_panel *layout;
24270  NK_ASSERT(ctx);
24271  NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
24272  if (!ctx || !ctx->current)
24273  return;
24274 
24275  layout = ctx->current->layout;
24276  if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
24277  ctx->current = 0;
24278  return;
24279  }
24280  nk_panel_end(ctx);
24281  nk_free_panel(ctx, ctx->current->layout);
24282  ctx->current = 0;
24283 }
24294 NK_API struct nk_rect
24295 nk_window_get_bounds(const struct nk_context *ctx)
24296 {
24297  NK_ASSERT(ctx);
24298  NK_ASSERT(ctx->current);
24299  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
24300  return ctx->current->bounds;
24301 }
24312 NK_API struct nk_vec2
24313 nk_window_get_position(const struct nk_context *ctx)
24314 {
24315  NK_ASSERT(ctx);
24316  NK_ASSERT(ctx->current);
24317  if (!ctx || !ctx->current) return nk_vec2(0,0);
24318  return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
24319 }
24330 NK_API struct nk_vec2
24331 nk_window_get_size(const struct nk_context *ctx)
24332 {
24333  NK_ASSERT(ctx);
24334  NK_ASSERT(ctx->current);
24335  if (!ctx || !ctx->current) return nk_vec2(0,0);
24336  return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
24337 }
24348 NK_API float
24349 nk_window_get_width(const struct nk_context *ctx)
24350 {
24351  NK_ASSERT(ctx);
24352  NK_ASSERT(ctx->current);
24353  if (!ctx || !ctx->current) return 0;
24354  return ctx->current->bounds.w;
24355 }
24366 NK_API float
24367 nk_window_get_height(const struct nk_context *ctx)
24368 {
24369  NK_ASSERT(ctx);
24370  NK_ASSERT(ctx->current);
24371  if (!ctx || !ctx->current) return 0;
24372  return ctx->current->bounds.h;
24373 }
24384 NK_API struct nk_rect
24385 nk_window_get_content_region(const struct nk_context *ctx)
24386 {
24387  NK_ASSERT(ctx);
24388  NK_ASSERT(ctx->current);
24389  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
24390  return ctx->current->layout->clip;
24391 }
24402 NK_API struct nk_vec2
24404 {
24405  NK_ASSERT(ctx);
24406  NK_ASSERT(ctx->current);
24407  NK_ASSERT(ctx->current->layout);
24408  if (!ctx || !ctx->current) return nk_vec2(0,0);
24409  return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
24410 }
24421 NK_API struct nk_vec2
24423 {
24424  NK_ASSERT(ctx);
24425  NK_ASSERT(ctx->current);
24426  NK_ASSERT(ctx->current->layout);
24427  if (!ctx || !ctx->current) return nk_vec2(0,0);
24428  return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
24429  ctx->current->layout->clip.y + ctx->current->layout->clip.h);
24430 }
24441 NK_API struct nk_vec2
24443 {
24444  NK_ASSERT(ctx);
24445  NK_ASSERT(ctx->current);
24446  NK_ASSERT(ctx->current->layout);
24447  if (!ctx || !ctx->current) return nk_vec2(0,0);
24448  return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
24449 }
24460 NK_API struct nk_command_buffer*
24461 nk_window_get_canvas(const struct nk_context *ctx)
24462 {
24463  NK_ASSERT(ctx);
24464  NK_ASSERT(ctx->current);
24465  NK_ASSERT(ctx->current->layout);
24466  if (!ctx || !ctx->current) return 0;
24467  return &ctx->current->buffer;
24468 }
24479 NK_API struct nk_panel*
24480 nk_window_get_panel(const struct nk_context *ctx)
24481 {
24482  NK_ASSERT(ctx);
24483  NK_ASSERT(ctx->current);
24484  if (!ctx || !ctx->current) return 0;
24485  return ctx->current->layout;
24486 }
24499 NK_API void
24500 nk_window_get_scroll(const struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
24501 {
24502  struct nk_window *win;
24503  NK_ASSERT(ctx);
24504  NK_ASSERT(ctx->current);
24505  if (!ctx || !ctx->current)
24506  return ;
24507  win = ctx->current;
24508  if (offset_x)
24509  *offset_x = win->scrollbar.x;
24510  if (offset_y)
24511  *offset_y = win->scrollbar.y;
24512 }
24523 NK_API nk_bool
24524 nk_window_has_focus(const struct nk_context *ctx)
24525 {
24526  NK_ASSERT(ctx);
24527  NK_ASSERT(ctx->current);
24528  NK_ASSERT(ctx->current->layout);
24529  if (!ctx || !ctx->current) return 0;
24530  return ctx->current == ctx->active;
24531 }
24542 NK_API nk_bool
24543 nk_window_is_hovered(const struct nk_context *ctx)
24544 {
24545  NK_ASSERT(ctx);
24546  NK_ASSERT(ctx->current);
24547  if (!ctx || !ctx->current || (ctx->current->flags & NK_WINDOW_HIDDEN))
24548  return 0;
24549  else {
24550  struct nk_rect actual_bounds = ctx->current->bounds;
24551  if (ctx->begin->flags & NK_WINDOW_MINIMIZED) {
24552  actual_bounds.h = ctx->current->layout->header_height;
24553  }
24554  return nk_input_is_mouse_hovering_rect(&ctx->input, actual_bounds);
24555  }
24556 }
24567 NK_API nk_bool
24568 nk_window_is_any_hovered(const struct nk_context *ctx)
24569 {
24570  struct nk_window *iter;
24571  NK_ASSERT(ctx);
24572  if (!ctx) return 0;
24573  iter = ctx->begin;
24574  while (iter) {
24575  /* check if window is being hovered */
24576  if(!(iter->flags & NK_WINDOW_HIDDEN)) {
24577  /* check if window popup is being hovered */
24578  if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
24579  return 1;
24580 
24581  if (iter->flags & NK_WINDOW_MINIMIZED) {
24582  struct nk_rect header = iter->bounds;
24583  header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
24584  if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
24585  return 1;
24586  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
24587  return 1;
24588  }
24589  }
24590  iter = iter->next;
24591  }
24592  return 0;
24593 }
24604 NK_API nk_bool
24605 nk_item_is_any_active(const struct nk_context *ctx)
24606 {
24607  int any_hovered = nk_window_is_any_hovered(ctx);
24608  int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
24609  return any_hovered || any_active;
24610 }
24622 NK_API nk_bool
24623 nk_window_is_collapsed(const struct nk_context *ctx, const char *name)
24624 {
24625  int title_len;
24626  nk_hash title_hash;
24627  struct nk_window *win;
24628  NK_ASSERT(ctx);
24629  if (!ctx) return 0;
24630 
24631  title_len = (int)nk_strlen(name);
24632  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
24633  win = nk_find_window(ctx, title_hash, name);
24634  if (!win) return 0;
24635  return win->flags & NK_WINDOW_MINIMIZED;
24636 }
24648 NK_API nk_bool
24649 nk_window_is_closed(const struct nk_context *ctx, const char *name)
24650 {
24651  int title_len;
24652  nk_hash title_hash;
24653  struct nk_window *win;
24654  NK_ASSERT(ctx);
24655  if (!ctx) return 1;
24656 
24657  title_len = (int)nk_strlen(name);
24658  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
24659  win = nk_find_window(ctx, title_hash, name);
24660  if (!win) return 1;
24661  return (win->flags & NK_WINDOW_CLOSED);
24662 }
24674 NK_API nk_bool
24675 nk_window_is_hidden(const struct nk_context *ctx, const char *name)
24676 {
24677  int title_len;
24678  nk_hash title_hash;
24679  struct nk_window *win;
24680  NK_ASSERT(ctx);
24681  if (!ctx) return 1;
24682 
24683  title_len = (int)nk_strlen(name);
24684  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
24685  win = nk_find_window(ctx, title_hash, name);
24686  if (!win) return 1;
24687  return (win->flags & NK_WINDOW_HIDDEN);
24688 }
24700 NK_API nk_bool
24701 nk_window_is_active(const struct nk_context *ctx, const char *name)
24702 {
24703  int title_len;
24704  nk_hash title_hash;
24705  struct nk_window *win;
24706  NK_ASSERT(ctx);
24707  if (!ctx) return 0;
24708 
24709  title_len = (int)nk_strlen(name);
24710  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
24711  win = nk_find_window(ctx, title_hash, name);
24712  if (!win) return 0;
24713  return win == ctx->active;
24714 }
24726 NK_API struct nk_window*
24727 nk_window_find(const struct nk_context *ctx, const char *name)
24728 {
24729  int title_len;
24730  nk_hash title_hash;
24731  title_len = (int)nk_strlen(name);
24732  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
24733  return nk_find_window(ctx, title_hash, name);
24734 }
24746 NK_API void
24747 nk_window_close(struct nk_context *ctx, const char *name)
24748 {
24749  struct nk_window *win;
24750  NK_ASSERT(ctx);
24751  if (!ctx) return;
24752  win = nk_window_find(ctx, name);
24753  if (!win) return;
24754  NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
24755  if (ctx->current == win) return;
24756  win->flags |= NK_WINDOW_HIDDEN;
24757  win->flags |= NK_WINDOW_CLOSED;
24758 }
24769 NK_API void
24770 nk_window_set_bounds(struct nk_context *ctx,
24771  const char *name, struct nk_rect bounds)
24772 {
24773  struct nk_window *win;
24774  NK_ASSERT(ctx);
24775  if (!ctx) return;
24776  win = nk_window_find(ctx, name);
24777  if (!win) return;
24778  win->bounds = bounds;
24779 }
24790 NK_API void
24792  const char *name, struct nk_vec2 pos)
24793 {
24794  struct nk_window *win = nk_window_find(ctx, name);
24795  if (!win) return;
24796  win->bounds.x = pos.x;
24797  win->bounds.y = pos.y;
24798 }
24809 NK_API void
24810 nk_window_set_size(struct nk_context *ctx,
24811  const char *name, struct nk_vec2 size)
24812 {
24813  struct nk_window *win = nk_window_find(ctx, name);
24814  if (!win) return;
24815  win->bounds.w = size.x;
24816  win->bounds.h = size.y;
24817 }
24829 NK_API void
24830 nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
24831 {
24832  struct nk_window *win;
24833  NK_ASSERT(ctx);
24834  NK_ASSERT(ctx->current);
24835  if (!ctx || !ctx->current)
24836  return;
24837  win = ctx->current;
24838  win->scrollbar.x = offset_x;
24839  win->scrollbar.y = offset_y;
24840 }
24852 NK_API void
24853 nk_window_collapse(struct nk_context *ctx, const char *name,
24854  enum nk_collapse_states c)
24855 {
24856  int title_len;
24857  nk_hash title_hash;
24858  struct nk_window *win;
24859  NK_ASSERT(ctx);
24860  if (!ctx) return;
24861 
24862  title_len = (int)nk_strlen(name);
24863  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
24864  win = nk_find_window(ctx, title_hash, name);
24865  if (!win) return;
24866  if (c == NK_MINIMIZED)
24867  win->flags |= NK_WINDOW_MINIMIZED;
24868  else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
24869 }
24881 NK_API void
24882 nk_window_collapse_if(struct nk_context *ctx, const char *name,
24883  enum nk_collapse_states c, int cond)
24884 {
24885  NK_ASSERT(ctx);
24886  if (!ctx || !cond) return;
24887  nk_window_collapse(ctx, name, c);
24888 }
24901 NK_API void
24902 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
24903 {
24904  int title_len;
24905  nk_hash title_hash;
24906  struct nk_window *win;
24907  NK_ASSERT(ctx);
24908  if (!ctx) return;
24909 
24910  title_len = (int)nk_strlen(name);
24911  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
24912  win = nk_find_window(ctx, title_hash, name);
24913  if (!win) return;
24914  if (s == NK_HIDDEN) {
24915  win->flags |= NK_WINDOW_HIDDEN;
24916  } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
24917 }
24929 NK_API void
24930 nk_window_show_if(struct nk_context *ctx, const char *name,
24931  enum nk_show_states s, int cond)
24932 {
24933  NK_ASSERT(ctx);
24934  if (!ctx || !cond) return;
24935  nk_window_show(ctx, name, s);
24936 }
24937 
24949 NK_API void
24950 nk_window_set_focus(struct nk_context *ctx, const char *name)
24951 {
24952  int title_len;
24953  nk_hash title_hash;
24954  struct nk_window *win;
24955  NK_ASSERT(ctx);
24956  if (!ctx) return;
24957 
24958  title_len = (int)nk_strlen(name);
24959  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
24960  win = nk_find_window(ctx, title_hash, name);
24961  if (win && ctx->end != win) {
24962  nk_remove_window(ctx, win);
24963  nk_insert_window(ctx, win, NK_INSERT_BACK);
24964  }
24965  ctx->active = win;
24966 }
24979 NK_API void
24980 nk_rule_horizontal(struct nk_context *ctx, struct nk_color color, nk_bool rounding)
24981 {
24982  struct nk_rect space;
24983  enum nk_widget_layout_states state = nk_widget(&space, ctx);
24984  struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
24985  if (!state) return;
24986  nk_fill_rect(canvas, space, rounding && space.h > 1.5f ? space.h / 2.0f : 0, color);
24987 }
24988 
24989 
24990 
24991 
24992 /* ===============================================================
24993  *
24994  * POPUP
24995  *
24996  * ===============================================================*/
25008 NK_API nk_bool
25009 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
25010  const char *title, nk_flags flags, struct nk_rect rect)
25011 {
25012  struct nk_window *popup;
25013  struct nk_window *win;
25014  struct nk_panel *panel;
25015 
25016  int title_len;
25017  nk_hash title_hash;
25018  nk_size allocated;
25019 
25020  NK_ASSERT(ctx);
25021  NK_ASSERT(title);
25022  NK_ASSERT(ctx->current);
25023  NK_ASSERT(ctx->current->layout);
25024  if (!ctx || !ctx->current || !ctx->current->layout)
25025  return 0;
25026 
25027  win = ctx->current;
25028  panel = win->layout;
25029  NK_ASSERT(!((int)panel->type & (int)NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
25030  (void)panel;
25031  title_len = (int)nk_strlen(title);
25032  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
25033 
25034  popup = win->popup.win;
25035  if (!popup) {
25036  popup = (struct nk_window*)nk_create_window(ctx);
25037  popup->parent = win;
25038  win->popup.win = popup;
25039  win->popup.active = 0;
25040  win->popup.type = NK_PANEL_POPUP;
25041  }
25042 
25043  /* make sure we have correct popup */
25044  if (win->popup.name != title_hash) {
25045  if (!win->popup.active) {
25046  nk_zero(popup, sizeof(*popup));
25047  win->popup.name = title_hash;
25048  win->popup.active = 1;
25049  win->popup.type = NK_PANEL_POPUP;
25050  } else return 0;
25051  }
25052 
25053  /* popup position is local to window */
25054  ctx->current = popup;
25055  rect.x += win->layout->clip.x;
25056  rect.y += win->layout->clip.y;
25057 
25058  /* setup popup data */
25059  popup->parent = win;
25060  popup->bounds = rect;
25061  popup->seq = ctx->seq;
25062  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
25063  popup->flags = flags;
25064  popup->flags |= NK_WINDOW_BORDER;
25065  if (type == NK_POPUP_DYNAMIC)
25066  popup->flags |= NK_WINDOW_DYNAMIC;
25067 
25068  popup->buffer = win->buffer;
25069  nk_start_popup(ctx, win);
25070  allocated = ctx->memory.allocated;
25071  nk_push_scissor(&popup->buffer, nk_null_rect);
25072 
25073  if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
25074  /* popup is running therefore invalidate parent panels */
25075  struct nk_panel *root;
25076  root = win->layout;
25077  while (root) {
25078  root->flags |= NK_WINDOW_ROM;
25079  root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
25080  root = root->parent;
25081  }
25082  win->popup.active = 1;
25083  popup->layout->offset_x = &popup->scrollbar.x;
25084  popup->layout->offset_y = &popup->scrollbar.y;
25085  popup->layout->parent = win->layout;
25086  return 1;
25087  } else {
25088  /* popup was closed/is invalid so cleanup */
25089  struct nk_panel *root;
25090  root = win->layout;
25091  while (root) {
25092  root->flags |= NK_WINDOW_REMOVE_ROM;
25093  root = root->parent;
25094  }
25095  win->popup.buf.active = 0;
25096  win->popup.active = 0;
25097  ctx->memory.allocated = allocated;
25098  ctx->current = win;
25099  nk_free_panel(ctx, popup->layout);
25100  popup->layout = 0;
25101  return 0;
25102  }
25103 }
25114 NK_LIB nk_bool
25115 nk_nonblock_begin(struct nk_context *ctx,
25116  nk_flags flags, struct nk_rect body, struct nk_rect header,
25117  enum nk_panel_type panel_type)
25118 {
25119  struct nk_window *popup;
25120  struct nk_window *win;
25121  struct nk_panel *panel;
25122  int is_active = nk_true;
25123 
25124  NK_ASSERT(ctx);
25125  NK_ASSERT(ctx->current);
25126  NK_ASSERT(ctx->current->layout);
25127  if (!ctx || !ctx->current || !ctx->current->layout)
25128  return 0;
25129 
25130  /* popups cannot have popups */
25131  win = ctx->current;
25132  panel = win->layout;
25133  NK_ASSERT(!((int)panel->type & (int)NK_PANEL_SET_POPUP));
25134  (void)panel;
25135  popup = win->popup.win;
25136  if (!popup) {
25137  /* create window for nonblocking popup */
25138  popup = (struct nk_window*)nk_create_window(ctx);
25139  popup->parent = win;
25140  win->popup.win = popup;
25141  win->popup.type = panel_type;
25142  nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
25143  } else {
25144  /* close the popup if user pressed outside or in the header */
25145  int pressed, in_body, in_header;
25146 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
25147  pressed = nk_input_is_mouse_released(&ctx->input, NK_BUTTON_LEFT);
25148 #else
25149  pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
25150 #endif
25151  in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
25152  in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
25153  if (pressed && (!in_body || in_header))
25154  is_active = nk_false;
25155  }
25156  win->popup.header = header;
25157 
25158  if (!is_active) {
25159  /* remove read only mode from all parent panels */
25160  struct nk_panel *root = win->layout;
25161  while (root) {
25162  root->flags |= NK_WINDOW_REMOVE_ROM;
25163  root = root->parent;
25164  }
25165  return is_active;
25166  }
25167  popup->bounds = body;
25168  popup->parent = win;
25169  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
25170  popup->flags = flags;
25171  popup->flags |= NK_WINDOW_BORDER;
25172  popup->flags |= NK_WINDOW_DYNAMIC;
25173  popup->seq = ctx->seq;
25174  win->popup.active = 1;
25175  NK_ASSERT(popup->layout);
25176 
25177  nk_start_popup(ctx, win);
25178  popup->buffer = win->buffer;
25179  nk_push_scissor(&popup->buffer, nk_null_rect);
25180  ctx->current = popup;
25181 
25182  nk_panel_begin(ctx, 0, panel_type);
25183  win->buffer = popup->buffer;
25184  popup->layout->parent = win->layout;
25185  popup->layout->offset_x = &popup->scrollbar.x;
25186  popup->layout->offset_y = &popup->scrollbar.y;
25187 
25188  /* set read only mode to all parent panels */
25189  {struct nk_panel *root;
25190  root = win->layout;
25191  while (root) {
25192  root->flags |= NK_WINDOW_ROM;
25193  root = root->parent;
25194  }}
25195  return is_active;
25196 }
25207 NK_API void
25208 nk_popup_close(struct nk_context *ctx)
25209 {
25210  struct nk_window *popup;
25211  NK_ASSERT(ctx);
25212  if (!ctx || !ctx->current) return;
25213 
25214  popup = ctx->current;
25215  NK_ASSERT(popup->parent);
25216  NK_ASSERT((int)popup->layout->type & (int)NK_PANEL_SET_POPUP);
25217  popup->flags |= NK_WINDOW_HIDDEN;
25218 }
25229 NK_API void
25230 nk_popup_end(struct nk_context *ctx)
25231 {
25232  struct nk_window *win;
25233  struct nk_window *popup;
25234 
25235  NK_ASSERT(ctx);
25236  NK_ASSERT(ctx->current);
25237  NK_ASSERT(ctx->current->layout);
25238  if (!ctx || !ctx->current || !ctx->current->layout)
25239  return;
25240 
25241  popup = ctx->current;
25242  if (!popup->parent) return;
25243  win = popup->parent;
25244  if (popup->flags & NK_WINDOW_HIDDEN) {
25245  struct nk_panel *root;
25246  root = win->layout;
25247  while (root) {
25248  root->flags |= NK_WINDOW_REMOVE_ROM;
25249  root = root->parent;
25250  }
25251  win->popup.active = 0;
25252  }
25253  nk_push_scissor(&popup->buffer, nk_null_rect);
25254  nk_end(ctx);
25255 
25256  win->buffer = popup->buffer;
25257  nk_finish_popup(ctx, win);
25258  ctx->current = win;
25259  nk_push_scissor(&win->buffer, win->layout->clip);
25260 }
25273 NK_API void
25274 nk_popup_get_scroll(const struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
25275 {
25276  struct nk_window *popup;
25277 
25278  NK_ASSERT(ctx);
25279  NK_ASSERT(ctx->current);
25280  NK_ASSERT(ctx->current->layout);
25281  if (!ctx || !ctx->current || !ctx->current->layout)
25282  return;
25283 
25284  popup = ctx->current;
25285  if (offset_x)
25286  *offset_x = popup->scrollbar.x;
25287  if (offset_y)
25288  *offset_y = popup->scrollbar.y;
25289 }
25302 NK_API void
25303 nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
25304 {
25305  struct nk_window *popup;
25306 
25307  NK_ASSERT(ctx);
25308  NK_ASSERT(ctx->current);
25309  NK_ASSERT(ctx->current->layout);
25310  if (!ctx || !ctx->current || !ctx->current->layout)
25311  return;
25312 
25313  popup = ctx->current;
25314  popup->scrollbar.x = offset_x;
25315  popup->scrollbar.y = offset_y;
25316 }
25317 
25318 
25319 
25320 
25321 /* ==============================================================
25322  *
25323  * CONTEXTUAL
25324  *
25325  * ===============================================================*/
25338 NK_API nk_bool
25339 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
25340  struct nk_rect trigger_bounds)
25341 {
25342  struct nk_window *win;
25343  struct nk_window *popup;
25344  struct nk_rect body;
25345  struct nk_input* in;
25346 
25347  NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0};
25348  int is_clicked = 0;
25349  int is_open = 0;
25350  int ret = 0;
25351 
25352  NK_ASSERT(ctx);
25353  NK_ASSERT(ctx->current);
25354  NK_ASSERT(ctx->current->layout);
25355  if (!ctx || !ctx->current || !ctx->current->layout)
25356  return 0;
25357 
25358  win = ctx->current;
25359  ++win->popup.con_count;
25360  if (ctx->current != ctx->active)
25361  return 0;
25362 
25363  /* check if currently active contextual is active */
25364  popup = win->popup.win;
25365  is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
25366  in = win->widgets_disabled ? 0 : &ctx->input;
25367  if (in) {
25368  is_clicked = nk_input_mouse_clicked(in, NK_BUTTON_RIGHT, trigger_bounds);
25369  if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
25370  return 0;
25371  if (!is_open && win->popup.active_con)
25372  win->popup.active_con = 0;
25373  if ((!is_open && !is_clicked))
25374  return 0;
25375 
25376  /* calculate contextual position on click */
25377  win->popup.active_con = win->popup.con_count;
25378  if (is_clicked) {
25379  body.x = in->mouse.pos.x;
25380  body.y = in->mouse.pos.y;
25381  } else {
25382  body.x = popup->bounds.x;
25383  body.y = popup->bounds.y;
25384  }
25385 
25386  body.w = size.x;
25387  body.h = size.y;
25388 
25389  /* start nonblocking contextual popup */
25390  ret = nk_nonblock_begin(ctx, flags | NK_WINDOW_NO_SCROLLBAR, body,
25391  null_rect, NK_PANEL_CONTEXTUAL);
25392  if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
25393  else {
25394  win->popup.active_con = 0;
25395  win->popup.type = NK_PANEL_NONE;
25396  if (win->popup.win)
25397  win->popup.win->flags = 0;
25398  }
25399  }
25400  return ret;
25401 }
25414 NK_API nk_bool
25415 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
25416  nk_flags alignment)
25417 {
25418  struct nk_window *win;
25419  const struct nk_input *in;
25420  const struct nk_style *style;
25421 
25422  struct nk_rect bounds;
25423  enum nk_widget_layout_states state;
25424 
25425  NK_ASSERT(ctx);
25426  NK_ASSERT(ctx->current);
25427  NK_ASSERT(ctx->current->layout);
25428  if (!ctx || !ctx->current || !ctx->current->layout)
25429  return 0;
25430 
25431  win = ctx->current;
25432  style = &ctx->style;
25433  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
25434  if (!state) return nk_false;
25435 
25436  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25437  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
25438  text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
25439  nk_contextual_close(ctx);
25440  return nk_true;
25441  }
25442  return nk_false;
25443 }
25456 NK_API nk_bool
25457 nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
25458 {
25459  return nk_contextual_item_text(ctx, label, nk_strlen(label), align);
25460 }
25472 NK_API nk_bool
25473 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
25474  const char *text, int len, nk_flags align)
25475 {
25476  struct nk_window *win;
25477  const struct nk_input *in;
25478  const struct nk_style *style;
25479 
25480  struct nk_rect bounds;
25481  enum nk_widget_layout_states state;
25482 
25483  NK_ASSERT(ctx);
25484  NK_ASSERT(ctx->current);
25485  NK_ASSERT(ctx->current->layout);
25486  if (!ctx || !ctx->current || !ctx->current->layout)
25487  return 0;
25488 
25489  win = ctx->current;
25490  style = &ctx->style;
25491  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
25492  if (!state) return nk_false;
25493 
25494  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25495  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
25496  img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
25497  nk_contextual_close(ctx);
25498  return nk_true;
25499  }
25500  return nk_false;
25501 }
25513 NK_API nk_bool
25514 nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
25515  const char *label, nk_flags align)
25516 {
25517  return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);
25518 }
25530 NK_API nk_bool
25531 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
25532  const char *text, int len, nk_flags align)
25533 {
25534  struct nk_window *win;
25535  const struct nk_input *in;
25536  const struct nk_style *style;
25537 
25538  struct nk_rect bounds;
25539  enum nk_widget_layout_states state;
25540 
25541  NK_ASSERT(ctx);
25542  NK_ASSERT(ctx->current);
25543  NK_ASSERT(ctx->current->layout);
25544  if (!ctx || !ctx->current || !ctx->current->layout)
25545  return 0;
25546 
25547  win = ctx->current;
25548  style = &ctx->style;
25549  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
25550  if (!state) return nk_false;
25551 
25552  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25553  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
25554  symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
25555  nk_contextual_close(ctx);
25556  return nk_true;
25557  }
25558  return nk_false;
25559 }
25571 NK_API nk_bool
25572 nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
25573  const char *text, nk_flags align)
25574 {
25575  return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);
25576 }
25587 NK_API void
25588 nk_contextual_close(struct nk_context *ctx)
25589 {
25590  NK_ASSERT(ctx);
25591  NK_ASSERT(ctx->current);
25592  NK_ASSERT(ctx->current->layout);
25593  if (!ctx || !ctx->current || !ctx->current->layout) return;
25594  nk_popup_close(ctx);
25595 }
25606 NK_API void
25607 nk_contextual_end(struct nk_context *ctx)
25608 {
25609  struct nk_window *popup;
25610  struct nk_panel *panel;
25611  NK_ASSERT(ctx);
25612  NK_ASSERT(ctx->current);
25613  if (!ctx || !ctx->current) return;
25614 
25615  popup = ctx->current;
25616  panel = popup->layout;
25617  NK_ASSERT(popup->parent);
25618  NK_ASSERT((int)panel->type & (int)NK_PANEL_SET_POPUP);
25619  if (panel->flags & NK_WINDOW_DYNAMIC) {
25620  /* Close behavior
25621  This is a bit of a hack solution since we do not know before we end our popup
25622  how big it will be. We therefore do not directly know when a
25623  click outside the non-blocking popup must close it at that direct frame.
25624  Instead it will be closed in the next frame.*/
25625  struct nk_rect body = {0,0,0,0};
25626  if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
25627  struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
25628  body = panel->bounds;
25629  body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
25630  body.h = (panel->bounds.y + panel->bounds.h) - body.y;
25631  }
25632  {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
25633  int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
25634  if (pressed && in_body)
25635  popup->flags |= NK_WINDOW_HIDDEN;
25636  }
25637  }
25638  if (popup->flags & NK_WINDOW_HIDDEN)
25639  popup->seq = 0;
25640  nk_popup_end(ctx);
25641  return;
25642 }
25643 
25644 
25645 
25646 
25647 
25648 /* ===============================================================
25649  *
25650  * MENU
25651  *
25652  * ===============================================================*/
25663 NK_API void
25664 nk_menubar_begin(struct nk_context *ctx)
25665 {
25666  struct nk_panel *layout;
25667  NK_ASSERT(ctx);
25668  NK_ASSERT(ctx->current);
25669  NK_ASSERT(ctx->current->layout);
25670  if (!ctx || !ctx->current || !ctx->current->layout)
25671  return;
25672 
25673  layout = ctx->current->layout;
25674  NK_ASSERT(layout->at_y == layout->bounds.y);
25675  /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
25676  If you want a menubar the first nuklear function after `nk_begin` has to be a
25677  `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
25678  widgets (also supports multiple rows).
25679  Example:
25680  if (nk_begin(...)) {
25681  nk_menubar_begin(...);
25682  nk_layout_xxxx(...);
25683  nk_button(...);
25684  nk_layout_xxxx(...);
25685  nk_button(...);
25686  nk_menubar_end(...);
25687  }
25688  nk_end(...);
25689  */
25690  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
25691  return;
25692 
25693  layout->menu.x = layout->at_x;
25694  layout->menu.y = layout->at_y + layout->row.height;
25695  layout->menu.w = layout->bounds.w;
25696  layout->menu.offset.x = *layout->offset_x;
25697  layout->menu.offset.y = *layout->offset_y;
25698  *layout->offset_y = 0;
25699 }
25710 NK_API void
25711 nk_menubar_end(struct nk_context *ctx)
25712 {
25713  struct nk_window *win;
25714  struct nk_panel *layout;
25715  struct nk_command_buffer *out;
25716 
25717  NK_ASSERT(ctx);
25718  NK_ASSERT(ctx->current);
25719  NK_ASSERT(ctx->current->layout);
25720  if (!ctx || !ctx->current || !ctx->current->layout)
25721  return;
25722 
25723  win = ctx->current;
25724  out = &win->buffer;
25725  layout = win->layout;
25726  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
25727  return;
25728 
25729  layout->menu.h = layout->at_y - layout->menu.y;
25730  layout->menu.h += layout->row.height + ctx->style.window.spacing.y;
25731 
25732  layout->bounds.y += layout->menu.h;
25733  layout->bounds.h -= layout->menu.h;
25734 
25735  *layout->offset_x = layout->menu.offset.x;
25736  *layout->offset_y = layout->menu.offset.y;
25737  layout->at_y = layout->bounds.y - layout->row.height;
25738 
25739  layout->clip.y = layout->bounds.y;
25740  layout->clip.h = layout->bounds.h;
25741  nk_push_scissor(out, layout->clip);
25742 }
25754 NK_INTERN int
25755 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
25756  const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
25757 {
25758  int is_open = 0;
25759  int is_active = 0;
25760  struct nk_rect body;
25761  struct nk_window *popup;
25762  nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
25763 
25764  NK_ASSERT(ctx);
25765  NK_ASSERT(ctx->current);
25766  NK_ASSERT(ctx->current->layout);
25767  if (!ctx || !ctx->current || !ctx->current->layout)
25768  return 0;
25769 
25770  body.x = header.x;
25771  body.w = size.x;
25772  body.y = header.y + header.h;
25773  body.h = size.y;
25774 
25775  popup = win->popup.win;
25776  is_open = popup ? nk_true : nk_false;
25777  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
25778  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
25779  (!is_open && !is_active && !is_clicked)) return 0;
25780  if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
25781  return 0;
25782 
25783  win->popup.type = NK_PANEL_MENU;
25784  win->popup.name = hash;
25785  return 1;
25786 }
25799 NK_API nk_bool
25800 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
25801  nk_flags align, struct nk_vec2 size)
25802 {
25803  struct nk_window *win;
25804  const struct nk_input *in;
25805  struct nk_rect header;
25806  int is_clicked = nk_false;
25807  nk_flags state;
25808 
25809  NK_ASSERT(ctx);
25810  NK_ASSERT(ctx->current);
25811  NK_ASSERT(ctx->current->layout);
25812  if (!ctx || !ctx->current || !ctx->current->layout)
25813  return 0;
25814 
25815  win = ctx->current;
25816  state = nk_widget(&header, ctx);
25817  if (!state) return 0;
25818  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25819  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
25820  title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
25821  is_clicked = nk_true;
25822  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
25833 }
25834 NK_API nk_bool nk_menu_begin_label(struct nk_context *ctx,
25835  const char *text, nk_flags align, struct nk_vec2 size)
25836 {
25837  return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);
25838 }
25851 NK_API nk_bool
25852 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
25853  struct nk_vec2 size)
25854 {
25855  struct nk_window *win;
25856  struct nk_rect header;
25857  const struct nk_input *in;
25858  int is_clicked = nk_false;
25859  nk_flags state;
25860 
25861  NK_ASSERT(ctx);
25862  NK_ASSERT(ctx->current);
25863  NK_ASSERT(ctx->current->layout);
25864  if (!ctx || !ctx->current || !ctx->current->layout)
25865  return 0;
25866 
25867  win = ctx->current;
25868  state = nk_widget(&header, ctx);
25869  if (!state) return 0;
25870  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25871  if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
25872  img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
25873  is_clicked = nk_true;
25874  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
25875 }
25887 NK_API nk_bool
25888 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
25889  enum nk_symbol_type sym, struct nk_vec2 size)
25890 {
25891  struct nk_window *win;
25892  const struct nk_input *in;
25893  struct nk_rect header;
25894  int is_clicked = nk_false;
25895  nk_flags state;
25896 
25897  NK_ASSERT(ctx);
25898  NK_ASSERT(ctx->current);
25899  NK_ASSERT(ctx->current->layout);
25900  if (!ctx || !ctx->current || !ctx->current->layout)
25901  return 0;
25902 
25903  win = ctx->current;
25904  state = nk_widget(&header, ctx);
25905  if (!state) return 0;
25906  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25907  if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header,
25908  sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
25909  is_clicked = nk_true;
25910  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
25911 }
25924 NK_API nk_bool
25925 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
25926  nk_flags align, struct nk_image img, struct nk_vec2 size)
25927 {
25928  struct nk_window *win;
25929  struct nk_rect header;
25930  const struct nk_input *in;
25931  int is_clicked = nk_false;
25932  nk_flags state;
25933 
25934  NK_ASSERT(ctx);
25935  NK_ASSERT(ctx->current);
25936  NK_ASSERT(ctx->current->layout);
25937  if (!ctx || !ctx->current || !ctx->current->layout)
25938  return 0;
25939 
25940  win = ctx->current;
25941  state = nk_widget(&header, ctx);
25942  if (!state) return 0;
25943  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25944  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
25945  header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
25946  ctx->style.font, in))
25947  is_clicked = nk_true;
25948  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
25949 }
25960 NK_API nk_bool
25961 nk_menu_begin_image_label(struct nk_context *ctx,
25962  const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
25963 {
25964  return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);
25965 }
25978 NK_API nk_bool
25979 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
25980  nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
25981 {
25982  struct nk_window *win;
25983  struct nk_rect header;
25984  const struct nk_input *in;
25985  int is_clicked = nk_false;
25986  nk_flags state;
25987 
25988  NK_ASSERT(ctx);
25989  NK_ASSERT(ctx->current);
25990  NK_ASSERT(ctx->current->layout);
25991  if (!ctx || !ctx->current || !ctx->current->layout)
25992  return 0;
25993 
25994  win = ctx->current;
25995  state = nk_widget(&header, ctx);
25996  if (!state) return 0;
25997 
25998  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
25999  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
26000  header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
26001  ctx->style.font, in)) is_clicked = nk_true;
26002  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
26003 }
26014 NK_API nk_bool
26015 nk_menu_begin_symbol_label(struct nk_context *ctx,
26016  const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
26017 {
26018  return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);
26019 }
26033 NK_API nk_bool
26034 nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
26035 {
26036  return nk_contextual_item_text(ctx, title, len, align);
26037 }
26050 NK_API nk_bool
26051 nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
26052 {
26053  return nk_contextual_item_label(ctx, label, align);
26054 }
26066 NK_API nk_bool
26067 nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
26068  const char *label, nk_flags align)
26069 {
26070  return nk_contextual_item_image_label(ctx, img, label, align);
26071 }
26083 NK_API nk_bool
26084 nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
26085  const char *text, int len, nk_flags align)
26086 {
26087  return nk_contextual_item_image_text(ctx, img, text, len, align);
26099 }
26100 NK_API nk_bool nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
26101  const char *text, int len, nk_flags align)
26102 {
26103  return nk_contextual_item_symbol_text(ctx, sym, text, len, align);
26115 }
26116 NK_API nk_bool nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
26117  const char *label, nk_flags align)
26118 {
26119  return nk_contextual_item_symbol_label(ctx, sym, label, align);
26130 }
26131 NK_API void nk_menu_close(struct nk_context *ctx)
26132 {
26133  nk_contextual_close(ctx);
26134 }
26145 NK_API void
26146 nk_menu_end(struct nk_context *ctx)
26147 {
26148  nk_contextual_end(ctx);
26149 }
26150 
26151 
26152 
26153 
26154 
26155 /* ===============================================================
26156  *
26157  * LAYOUT
26158  *
26159  * ===============================================================*/
26171 NK_API void
26172 nk_layout_set_min_row_height(struct nk_context *ctx, float height)
26173 {
26174  struct nk_window *win;
26175  struct nk_panel *layout;
26176 
26177  NK_ASSERT(ctx);
26178  NK_ASSERT(ctx->current);
26179  NK_ASSERT(ctx->current->layout);
26180  if (!ctx || !ctx->current || !ctx->current->layout)
26181  return;
26182 
26183  win = ctx->current;
26184  layout = win->layout;
26185  layout->row.min_height = height;
26186 }
26197 NK_API void
26199 {
26200  struct nk_window *win;
26201  struct nk_panel *layout;
26202 
26203  NK_ASSERT(ctx);
26204  NK_ASSERT(ctx->current);
26205  NK_ASSERT(ctx->current->layout);
26206  if (!ctx || !ctx->current || !ctx->current->layout)
26207  return;
26208 
26209  win = ctx->current;
26210  layout = win->layout;
26211  layout->row.min_height = ctx->style.font->height;
26212  layout->row.min_height += ctx->style.text.padding.y*2;
26213  layout->row.min_height += ctx->style.window.min_row_height_padding*2;
26214 }
26226 NK_LIB float
26227 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
26228  float total_space, int columns)
26229 {
26230  float panel_spacing;
26231  float panel_space;
26232 
26233  struct nk_vec2 spacing;
26234 
26235  NK_UNUSED(type);
26236 
26237  spacing = style->window.spacing;
26238 
26239  /* calculate the usable panel space */
26240  panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
26241  panel_space = total_space - panel_spacing;
26242  return panel_space;
26243 }
26255 NK_LIB void
26256 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
26257  float height, int cols)
26258 {
26259  struct nk_panel *layout;
26260  const struct nk_style *style;
26261  struct nk_command_buffer *out;
26262 
26263  struct nk_vec2 item_spacing;
26264  struct nk_color color;
26265 
26266  NK_ASSERT(ctx);
26267  NK_ASSERT(ctx->current);
26268  NK_ASSERT(ctx->current->layout);
26269  if (!ctx || !ctx->current || !ctx->current->layout)
26270  return;
26271 
26272  /* prefetch some configuration data */
26273  layout = win->layout;
26274  style = &ctx->style;
26275  out = &win->buffer;
26276  color = style->window.background;
26277  item_spacing = style->window.spacing;
26278 
26279  /* if one of these triggers you forgot to add an `if` condition around either
26280  a window, group, popup, combobox or contextual menu `begin` and `end` block.
26281  Example:
26282  if (nk_begin(...) {...} nk_end(...); or
26283  if (nk_group_begin(...) { nk_group_end(...);} */
26284  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
26285  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
26286  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
26287 
26288  /* update the current row and set the current row layout */
26289  layout->row.index = 0;
26290  layout->at_y += layout->row.height;
26291  layout->row.columns = cols;
26292  if (height == 0.0f)
26293  layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
26294  else layout->row.height = height + item_spacing.y;
26295 
26296  layout->row.item_offset = 0;
26297  if (layout->flags & NK_WINDOW_DYNAMIC) {
26298  /* draw background for dynamic panels */
26299  struct nk_rect background;
26300  background.x = win->bounds.x;
26301  background.w = win->bounds.w;
26302  background.y = layout->at_y - 1.0f;
26303  background.h = layout->row.height + 1.0f;
26304  nk_fill_rect(out, background, 0, color);
26305  }
26306 }
26318 NK_LIB void
26319 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
26320  float height, int cols, int width)
26321 {
26322  /* update the current row and set the current row layout */
26323  struct nk_window *win;
26324  NK_ASSERT(ctx);
26325  NK_ASSERT(ctx->current);
26326  NK_ASSERT(ctx->current->layout);
26327  if (!ctx || !ctx->current || !ctx->current->layout)
26328  return;
26329 
26330  win = ctx->current;
26331  nk_panel_layout(ctx, win, height, cols);
26332  if (fmt == NK_DYNAMIC)
26333  win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED;
26334  else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
26335 
26336  win->layout->row.ratio = 0;
26337  win->layout->row.filled = 0;
26338  win->layout->row.item_offset = 0;
26339  win->layout->row.item_width = (float)width;
26340 }
26352 NK_API float
26353 nk_layout_ratio_from_pixel(const struct nk_context *ctx, float pixel_width)
26354 {
26355  struct nk_window *win;
26356  NK_ASSERT(ctx);
26357  NK_ASSERT(pixel_width);
26358  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
26359  win = ctx->current;
26360  return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
26361 }
26374 NK_API void
26375 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
26376 {
26377  nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
26378 }
26392 NK_API void
26393 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
26394 {
26395  nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
26396 }
26408 NK_API void
26409 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
26410  float row_height, int cols)
26411 {
26412  struct nk_window *win;
26413  struct nk_panel *layout;
26414 
26415  NK_ASSERT(ctx);
26416  NK_ASSERT(ctx->current);
26417  NK_ASSERT(ctx->current->layout);
26418  if (!ctx || !ctx->current || !ctx->current->layout)
26419  return;
26420 
26421  win = ctx->current;
26422  layout = win->layout;
26423  nk_panel_layout(ctx, win, row_height, cols);
26424  if (fmt == NK_DYNAMIC)
26425  layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
26426  else layout->row.type = NK_LAYOUT_STATIC_ROW;
26427 
26428  layout->row.ratio = 0;
26429  layout->row.filled = 0;
26430  layout->row.item_width = 0;
26431  layout->row.item_offset = 0;
26432  layout->row.columns = cols;
26433 }
26445 NK_API void
26446 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
26447 {
26448  struct nk_window *win;
26449  struct nk_panel *layout;
26450 
26451  NK_ASSERT(ctx);
26452  NK_ASSERT(ctx->current);
26453  NK_ASSERT(ctx->current->layout);
26454  if (!ctx || !ctx->current || !ctx->current->layout)
26455  return;
26456 
26457  win = ctx->current;
26458  layout = win->layout;
26459  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
26460  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
26461  return;
26462 
26463  if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
26464  float ratio = ratio_or_width;
26465  if ((ratio + layout->row.filled) > 1.0f) return;
26466  if (ratio > 0.0f)
26467  layout->row.item_width = NK_SATURATE(ratio);
26468  else layout->row.item_width = 1.0f - layout->row.filled;
26469  } else layout->row.item_width = ratio_or_width;
26470 }
26481 NK_API void
26482 nk_layout_row_end(struct nk_context *ctx)
26483 {
26484  struct nk_window *win;
26485  struct nk_panel *layout;
26486 
26487  NK_ASSERT(ctx);
26488  NK_ASSERT(ctx->current);
26489  NK_ASSERT(ctx->current->layout);
26490  if (!ctx || !ctx->current || !ctx->current->layout)
26491  return;
26492 
26493  win = ctx->current;
26494  layout = win->layout;
26495  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
26496  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
26497  return;
26498  layout->row.item_width = 0;
26499  layout->row.item_offset = 0;
26500 }
26512 NK_API void
26513 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
26514  float height, int cols, const float *ratio)
26515 {
26516  int i;
26517  int n_undef = 0;
26518  struct nk_window *win;
26519  struct nk_panel *layout;
26520 
26521  NK_ASSERT(ctx);
26522  NK_ASSERT(ctx->current);
26523  NK_ASSERT(ctx->current->layout);
26524  if (!ctx || !ctx->current || !ctx->current->layout)
26525  return;
26526 
26527  win = ctx->current;
26528  layout = win->layout;
26529  nk_panel_layout(ctx, win, height, cols);
26530  if (fmt == NK_DYNAMIC) {
26531  /* calculate width of undefined widget ratios */
26532  float r = 0;
26533  layout->row.ratio = ratio;
26534  for (i = 0; i < cols; ++i) {
26535  if (ratio[i] < 0.0f)
26536  n_undef++;
26537  else r += ratio[i];
26538  }
26539  r = NK_SATURATE(1.0f - r);
26540  layout->row.type = NK_LAYOUT_DYNAMIC;
26541  layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
26542  } else {
26543  layout->row.ratio = ratio;
26544  layout->row.type = NK_LAYOUT_STATIC;
26545  layout->row.item_width = 0;
26546  layout->row.item_offset = 0;
26547  }
26548  layout->row.item_offset = 0;
26549  layout->row.filled = 0;
26550 }
26562 NK_API void
26563 nk_layout_row_template_begin(struct nk_context *ctx, float height)
26564 {
26565  struct nk_window *win;
26566  struct nk_panel *layout;
26567 
26568  NK_ASSERT(ctx);
26569  NK_ASSERT(ctx->current);
26570  NK_ASSERT(ctx->current->layout);
26571  if (!ctx || !ctx->current || !ctx->current->layout)
26572  return;
26573 
26574  win = ctx->current;
26575  layout = win->layout;
26576  nk_panel_layout(ctx, win, height, 1);
26577  layout->row.type = NK_LAYOUT_TEMPLATE;
26578  layout->row.columns = 0;
26579  layout->row.ratio = 0;
26580  layout->row.item_width = 0;
26581  layout->row.item_height = 0;
26582  layout->row.item_offset = 0;
26583  layout->row.filled = 0;
26584  layout->row.item.x = 0;
26585  layout->row.item.y = 0;
26586  layout->row.item.w = 0;
26587  layout->row.item.h = 0;
26588 }
26599 NK_API void
26601 {
26602  struct nk_window *win;
26603  struct nk_panel *layout;
26604 
26605  NK_ASSERT(ctx);
26606  NK_ASSERT(ctx->current);
26607  NK_ASSERT(ctx->current->layout);
26608  if (!ctx || !ctx->current || !ctx->current->layout)
26609  return;
26610 
26611  win = ctx->current;
26612  layout = win->layout;
26613  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
26614  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
26615  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
26616  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
26617  layout->row.templates[layout->row.columns++] = -1.0f;
26618 }
26630 NK_API void
26631 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
26632 {
26633  struct nk_window *win;
26634  struct nk_panel *layout;
26635 
26636  NK_ASSERT(ctx);
26637  NK_ASSERT(ctx->current);
26638  NK_ASSERT(ctx->current->layout);
26639  if (!ctx || !ctx->current || !ctx->current->layout)
26640  return;
26641 
26642  win = ctx->current;
26643  layout = win->layout;
26644  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
26645  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
26646  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
26647  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
26648  layout->row.templates[layout->row.columns++] = -min_width;
26649 }
26661 NK_API void
26662 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
26663 {
26664  struct nk_window *win;
26665  struct nk_panel *layout;
26666 
26667  NK_ASSERT(ctx);
26668  NK_ASSERT(ctx->current);
26669  NK_ASSERT(ctx->current->layout);
26670  if (!ctx || !ctx->current || !ctx->current->layout)
26671  return;
26672 
26673  win = ctx->current;
26674  layout = win->layout;
26675  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
26676  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
26677  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
26678  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
26679  layout->row.templates[layout->row.columns++] = width;
26680 }
26691 NK_API void
26693 {
26694  struct nk_window *win;
26695  struct nk_panel *layout;
26696 
26697  int i = 0;
26698  int variable_count = 0;
26699  int min_variable_count = 0;
26700  float min_fixed_width = 0.0f;
26701  float total_fixed_width = 0.0f;
26702  float max_variable_width = 0.0f;
26703 
26704  NK_ASSERT(ctx);
26705  NK_ASSERT(ctx->current);
26706  NK_ASSERT(ctx->current->layout);
26707  if (!ctx || !ctx->current || !ctx->current->layout)
26708  return;
26709 
26710  win = ctx->current;
26711  layout = win->layout;
26712  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
26713  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
26714  for (i = 0; i < layout->row.columns; ++i) {
26715  float width = layout->row.templates[i];
26716  if (width >= 0.0f) {
26717  total_fixed_width += width;
26718  min_fixed_width += width;
26719  } else if (width < -1.0f) {
26720  width = -width;
26721  total_fixed_width += width;
26722  max_variable_width = NK_MAX(max_variable_width, width);
26723  variable_count++;
26724  } else {
26725  min_variable_count++;
26726  variable_count++;
26727  }
26728  }
26729  if (variable_count) {
26730  float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
26731  layout->bounds.w, layout->row.columns);
26732  float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
26733  int enough_space = var_width >= max_variable_width;
26734  if (!enough_space)
26735  var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
26736  for (i = 0; i < layout->row.columns; ++i) {
26737  float *width = &layout->row.templates[i];
26738  *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
26739  }
26740  }
26741 }
26753 NK_API void
26754 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
26755  float height, int widget_count)
26756 {
26757  struct nk_window *win;
26758  struct nk_panel *layout;
26759 
26760  NK_ASSERT(ctx);
26761  NK_ASSERT(ctx->current);
26762  NK_ASSERT(ctx->current->layout);
26763  if (!ctx || !ctx->current || !ctx->current->layout)
26764  return;
26765 
26766  win = ctx->current;
26767  layout = win->layout;
26768  nk_panel_layout(ctx, win, height, widget_count);
26769  if (fmt == NK_STATIC)
26770  layout->row.type = NK_LAYOUT_STATIC_FREE;
26771  else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
26772 
26773  layout->row.ratio = 0;
26774  layout->row.filled = 0;
26775  layout->row.item_width = 0;
26776  layout->row.item_offset = 0;
26777 }
26788 NK_API void
26789 nk_layout_space_end(struct nk_context *ctx)
26790 {
26791  struct nk_window *win;
26792  struct nk_panel *layout;
26793 
26794  NK_ASSERT(ctx);
26795  NK_ASSERT(ctx->current);
26796  NK_ASSERT(ctx->current->layout);
26797  if (!ctx || !ctx->current || !ctx->current->layout)
26798  return;
26799 
26800  win = ctx->current;
26801  layout = win->layout;
26802  layout->row.item_width = 0;
26803  layout->row.item_height = 0;
26804  layout->row.item_offset = 0;
26805  nk_zero(&layout->row.item, sizeof(layout->row.item));
26806 }
26818 NK_API void
26819 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
26820 {
26821  struct nk_window *win;
26822  struct nk_panel *layout;
26823 
26824  NK_ASSERT(ctx);
26825  NK_ASSERT(ctx->current);
26826  NK_ASSERT(ctx->current->layout);
26827  if (!ctx || !ctx->current || !ctx->current->layout)
26828  return;
26829 
26830  win = ctx->current;
26831  layout = win->layout;
26832  layout->row.item = rect;
26833 }
26844 NK_API struct nk_rect
26845 nk_layout_space_bounds(const struct nk_context *ctx)
26846 {
26847  struct nk_rect ret;
26848  struct nk_window *win;
26849  struct nk_panel *layout;
26850 
26851  NK_ASSERT(ctx);
26852  NK_ASSERT(ctx->current);
26853  NK_ASSERT(ctx->current->layout);
26854  win = ctx->current;
26855  layout = win->layout;
26856 
26857  ret.x = layout->clip.x;
26858  ret.y = layout->clip.y;
26859  ret.w = layout->clip.w;
26860  ret.h = layout->row.height;
26861  return ret;
26862 }
26873 NK_API struct nk_rect
26874 nk_layout_widget_bounds(const struct nk_context *ctx)
26875 {
26876  struct nk_rect ret;
26877  struct nk_window *win;
26878  struct nk_panel *layout;
26879 
26880  NK_ASSERT(ctx);
26881  NK_ASSERT(ctx->current);
26882  NK_ASSERT(ctx->current->layout);
26883  win = ctx->current;
26884  layout = win->layout;
26885 
26886  ret.x = layout->at_x;
26887  ret.y = layout->at_y;
26888  ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
26889  ret.h = layout->row.height;
26890  return ret;
26891 }
26903 NK_API struct nk_vec2
26904 nk_layout_space_to_screen(const struct nk_context *ctx, struct nk_vec2 ret)
26905 {
26906  struct nk_window *win;
26907  struct nk_panel *layout;
26908 
26909  NK_ASSERT(ctx);
26910  NK_ASSERT(ctx->current);
26911  NK_ASSERT(ctx->current->layout);
26912  win = ctx->current;
26913  layout = win->layout;
26914 
26915  ret.x += layout->at_x - (float)*layout->offset_x;
26916  ret.y += layout->at_y - (float)*layout->offset_y;
26917  return ret;
26918 }
26930 NK_API struct nk_vec2
26931 nk_layout_space_to_local(const struct nk_context *ctx, struct nk_vec2 ret)
26932 {
26933  struct nk_window *win;
26934  struct nk_panel *layout;
26935 
26936  NK_ASSERT(ctx);
26937  NK_ASSERT(ctx->current);
26938  NK_ASSERT(ctx->current->layout);
26939  win = ctx->current;
26940  layout = win->layout;
26941 
26942  ret.x += -layout->at_x + (float)*layout->offset_x;
26943  ret.y += -layout->at_y + (float)*layout->offset_y;
26944  return ret;
26945 }
26957 NK_API struct nk_rect
26958 nk_layout_space_rect_to_screen(const struct nk_context *ctx, struct nk_rect ret)
26959 {
26960  struct nk_window *win;
26961  struct nk_panel *layout;
26962 
26963  NK_ASSERT(ctx);
26964  NK_ASSERT(ctx->current);
26965  NK_ASSERT(ctx->current->layout);
26966  win = ctx->current;
26967  layout = win->layout;
26968 
26969  ret.x += layout->at_x - (float)*layout->offset_x;
26970  ret.y += layout->at_y - (float)*layout->offset_y;
26971  return ret;
26972 }
26984 NK_API struct nk_rect
26985 nk_layout_space_rect_to_local(const struct nk_context *ctx, struct nk_rect ret)
26986 {
26987  struct nk_window *win;
26988  struct nk_panel *layout;
26989 
26990  NK_ASSERT(ctx);
26991  NK_ASSERT(ctx->current);
26992  NK_ASSERT(ctx->current->layout);
26993  win = ctx->current;
26994  layout = win->layout;
26995 
26996  ret.x += -layout->at_x + (float)*layout->offset_x;
26997  ret.y += -layout->at_y + (float)*layout->offset_y;
26998  return ret;
26999 }
27011 NK_LIB void
27012 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
27013 {
27014  struct nk_panel *layout = win->layout;
27015  struct nk_vec2 spacing = ctx->style.window.spacing;
27016  const float row_height = layout->row.height - spacing.y;
27017  nk_panel_layout(ctx, win, row_height, layout->row.columns);
27018 }
27030 NK_LIB void
27031 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
27032  struct nk_window *win, int modify)
27033 {
27034  struct nk_panel *layout;
27035  const struct nk_style *style;
27036 
27037  struct nk_vec2 spacing;
27038 
27039  float item_offset = 0;
27040  float item_width = 0;
27041  float item_spacing = 0;
27042  float panel_space = 0;
27043 
27044  NK_ASSERT(ctx);
27045  NK_ASSERT(ctx->current);
27046  NK_ASSERT(ctx->current->layout);
27047  if (!ctx || !ctx->current || !ctx->current->layout)
27048  return;
27049 
27050  win = ctx->current;
27051  layout = win->layout;
27052  style = &ctx->style;
27053  NK_ASSERT(bounds);
27054 
27055  spacing = style->window.spacing;
27056  panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
27057  layout->bounds.w, layout->row.columns);
27058 
27059  #define NK_FRAC(x) (x - (float)(int)nk_roundf(x)) /* will be used to remove fookin gaps */
27060  /* calculate the width of one item inside the current layout space */
27061  switch (layout->row.type) {
27062  case NK_LAYOUT_DYNAMIC_FIXED: {
27063  /* scaling fixed size widgets item width */
27064  float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns;
27065  item_offset = (float)layout->row.index * w;
27066  item_width = w + NK_FRAC(item_offset);
27067  item_spacing = (float)layout->row.index * spacing.x;
27068  } break;
27069  case NK_LAYOUT_DYNAMIC_ROW: {
27070  /* scaling single ratio widget width */
27071  float w = layout->row.item_width * panel_space;
27072  item_offset = layout->row.item_offset;
27073  item_width = w + NK_FRAC(item_offset);
27074  item_spacing = 0;
27075 
27076  if (modify) {
27077  layout->row.item_offset += w + spacing.x;
27078  layout->row.filled += layout->row.item_width;
27079  layout->row.index = 0;
27080  }
27081  } break;
27082  case NK_LAYOUT_DYNAMIC_FREE: {
27083  /* panel width depended free widget placing */
27084  bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
27085  bounds->x -= (float)*layout->offset_x;
27086  bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
27087  bounds->y -= (float)*layout->offset_y;
27088  bounds->w = layout->bounds.w * layout->row.item.w + NK_FRAC(bounds->x);
27089  bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y);
27090  return;
27091  }
27092  case NK_LAYOUT_DYNAMIC: {
27093  /* scaling arrays of panel width ratios for every widget */
27094  float ratio, w;
27095  NK_ASSERT(layout->row.ratio);
27096  ratio = (layout->row.ratio[layout->row.index] < 0) ?
27097  layout->row.item_width : layout->row.ratio[layout->row.index];
27098 
27099  w = (ratio * panel_space);
27100  item_spacing = (float)layout->row.index * spacing.x;
27101  item_offset = layout->row.item_offset;
27102  item_width = w + NK_FRAC(item_offset);
27103 
27104  if (modify) {
27105  layout->row.item_offset += w;
27106  layout->row.filled += ratio;
27107  }
27108  } break;
27109  case NK_LAYOUT_STATIC_FIXED: {
27110  /* non-scaling fixed widgets item width */
27111  item_width = layout->row.item_width;
27112  item_offset = (float)layout->row.index * item_width;
27113  item_spacing = (float)layout->row.index * spacing.x;
27114  } break;
27115  case NK_LAYOUT_STATIC_ROW: {
27116  /* scaling single ratio widget width */
27117  item_width = layout->row.item_width;
27118  item_offset = layout->row.item_offset;
27119  item_spacing = (float)layout->row.index * spacing.x;
27120  if (modify) layout->row.item_offset += item_width;
27121  } break;
27122  case NK_LAYOUT_STATIC_FREE: {
27123  /* free widget placing */
27124  bounds->x = layout->at_x + layout->row.item.x;
27125  bounds->w = layout->row.item.w;
27126  if (((bounds->x + bounds->w) > layout->max_x) && modify)
27127  layout->max_x = (bounds->x + bounds->w);
27128  bounds->x -= (float)*layout->offset_x;
27129  bounds->y = layout->at_y + layout->row.item.y;
27130  bounds->y -= (float)*layout->offset_y;
27131  bounds->h = layout->row.item.h;
27132  return;
27133  }
27134  case NK_LAYOUT_STATIC: {
27135  /* non-scaling array of panel pixel width for every widget */
27136  item_spacing = (float)layout->row.index * spacing.x;
27137  item_width = layout->row.ratio[layout->row.index];
27138  item_offset = layout->row.item_offset;
27139  if (modify) layout->row.item_offset += item_width;
27140  } break;
27141  case NK_LAYOUT_TEMPLATE: {
27142  /* stretchy row layout with combined dynamic/static widget width*/
27143  float w;
27144  NK_ASSERT(layout->row.index < layout->row.columns);
27145  NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
27146  w = layout->row.templates[layout->row.index];
27147  item_offset = layout->row.item_offset;
27148  item_width = w + NK_FRAC(item_offset);
27149  item_spacing = (float)layout->row.index * spacing.x;
27150  if (modify) layout->row.item_offset += w;
27151  } break;
27152  #undef NK_FRAC
27153  default: NK_ASSERT(0); break;
27154  };
27155 
27156  /* set the bounds of the newly allocated widget */
27157  bounds->w = item_width;
27158  bounds->h = layout->row.height - spacing.y;
27159  bounds->y = layout->at_y - (float)*layout->offset_y;
27160  bounds->x = layout->at_x + item_offset + item_spacing;
27161  if (((bounds->x + bounds->w) > layout->max_x) && modify)
27162  layout->max_x = bounds->x + bounds->w;
27163  bounds->x -= (float)*layout->offset_x;
27164 }
27176 NK_LIB void
27177 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
27178 {
27179  struct nk_window *win;
27180  struct nk_panel *layout;
27181 
27182  NK_ASSERT(ctx);
27183  NK_ASSERT(ctx->current);
27184  NK_ASSERT(ctx->current->layout);
27185  if (!ctx || !ctx->current || !ctx->current->layout)
27186  return;
27187 
27188  /* check if the end of the row has been hit and begin new row if so */
27189  win = ctx->current;
27190  layout = win->layout;
27191  if (layout->row.index >= layout->row.columns)
27192  nk_panel_alloc_row(ctx, win);
27193 
27194  /* calculate widget position and size */
27195  nk_layout_widget_space(bounds, ctx, win, nk_true);
27196  layout->row.index++;
27197 }
27209 NK_LIB void
27210 nk_layout_peek(struct nk_rect *bounds, const struct nk_context *ctx)
27211 {
27212  float y;
27213  int index;
27214  struct nk_window *win;
27215  struct nk_panel *layout;
27216 
27217  NK_ASSERT(ctx);
27218  NK_ASSERT(ctx->current);
27219  NK_ASSERT(ctx->current->layout);
27220  if (!ctx || !ctx->current || !ctx->current->layout) {
27221  *bounds = nk_rect(0,0,0,0);
27222  return;
27223  }
27224 
27225  win = ctx->current;
27226  layout = win->layout;
27227  y = layout->at_y;
27228  index = layout->row.index;
27229  if (layout->row.index >= layout->row.columns) {
27230  layout->at_y += layout->row.height;
27231  layout->row.index = 0;
27232  }
27233  nk_layout_widget_space(bounds, ctx, win, nk_false);
27234  if (!layout->row.index) {
27235  bounds->x -= layout->row.item_offset;
27236  }
27237  layout->at_y = y;
27238  layout->row.index = index;
27239 }
27249 NK_API void
27250 nk_spacer(struct nk_context *ctx )
27251 {
27252  struct nk_rect dummy_rect = { 0, 0, 0, 0 };
27253  nk_panel_alloc_space( &dummy_rect, ctx );
27254 }
27255 
27256 
27257 
27258 
27259 /* ===============================================================
27260  *
27261  * TREE
27262  *
27263  * ===============================================================*/
27275 NK_INTERN int
27276 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
27277  struct nk_image *img, const char *title, enum nk_collapse_states *state)
27278 {
27279  struct nk_window *win;
27280  struct nk_panel *layout;
27281  const struct nk_style *style;
27282  struct nk_command_buffer *out;
27283  const struct nk_input *in;
27284  const struct nk_style_button *button;
27285  enum nk_symbol_type symbol;
27286  float row_height;
27287 
27288  struct nk_vec2 item_spacing;
27289  struct nk_rect header = {0,0,0,0};
27290  struct nk_rect sym = {0,0,0,0};
27291  struct nk_text text;
27292 
27293  nk_flags ws = 0;
27294  enum nk_widget_layout_states widget_state;
27295 
27296  NK_ASSERT(ctx);
27297  NK_ASSERT(ctx->current);
27298  NK_ASSERT(ctx->current->layout);
27299  if (!ctx || !ctx->current || !ctx->current->layout)
27300  return 0;
27301 
27302  /* cache some data */
27303  win = ctx->current;
27304  layout = win->layout;
27305  out = &win->buffer;
27306  style = &ctx->style;
27307  item_spacing = style->window.spacing;
27308 
27309  /* calculate header bounds and draw background */
27310  row_height = style->font->height + 2 * style->tab.padding.y;
27311  nk_layout_set_min_row_height(ctx, row_height);
27312  nk_layout_row_dynamic(ctx, row_height, 1);
27314 
27315  widget_state = nk_widget(&header, ctx);
27316  if (type == NK_TREE_TAB) {
27317  const struct nk_style_item *background = &style->tab.background;
27318 
27319  switch(background->type) {
27320  case NK_STYLE_ITEM_IMAGE:
27321  nk_draw_image(out, header, &background->data.image, nk_rgb_factor(nk_white, style->tab.color_factor));
27322  break;
27323  case NK_STYLE_ITEM_NINE_SLICE:
27324  nk_draw_nine_slice(out, header, &background->data.slice, nk_rgb_factor(nk_white, style->tab.color_factor));
27325  break;
27326  case NK_STYLE_ITEM_COLOR:
27327  nk_fill_rect(out, header, 0, nk_rgb_factor(style->tab.border_color, style->tab.color_factor));
27328  nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
27329  style->tab.rounding, nk_rgb_factor(background->data.color, style->tab.color_factor));
27330  break;
27331  }
27332  } else text.background = style->window.background;
27333 
27334  /* update node state */
27335  in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
27336  in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
27337  if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
27338  *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
27339 
27340  /* select correct button style */
27341  if (*state == NK_MAXIMIZED) {
27342  symbol = style->tab.sym_maximize;
27343  if (type == NK_TREE_TAB)
27344  button = &style->tab.tab_maximize_button;
27345  else button = &style->tab.node_maximize_button;
27346  } else {
27347  symbol = style->tab.sym_minimize;
27348  if (type == NK_TREE_TAB)
27349  button = &style->tab.tab_minimize_button;
27350  else button = &style->tab.node_minimize_button;
27351  }
27352 
27353  {/* draw triangle button */
27354  sym.w = sym.h = style->font->height;
27355  sym.y = header.y + style->tab.padding.y;
27356  sym.x = header.x + style->tab.padding.x;
27357  nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
27358  button, 0, style->font);
27359 
27360  if (img) {
27361  /* draw optional image icon */
27362  sym.x = sym.x + sym.w + 4 * item_spacing.x;
27363  nk_draw_image(&win->buffer, sym, img, nk_white);
27364  sym.w = style->font->height + style->tab.spacing.x;}
27365  }
27366 
27367  {/* draw label */
27368  struct nk_rect label;
27369  header.w = NK_MAX(header.w, sym.w + item_spacing.x);
27370  label.x = sym.x + sym.w + item_spacing.x;
27371  label.y = sym.y;
27372  label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
27373  label.h = style->font->height;
27374  text.text = nk_rgb_factor(style->tab.text, style->tab.color_factor);
27375  text.padding = nk_vec2(0,0);
27376  nk_widget_text(out, label, title, nk_strlen(title), &text,
27377  NK_TEXT_LEFT, style->font);}
27378 
27379  /* increase x-axis cursor widget position pointer */
27380  if (*state == NK_MAXIMIZED) {
27381  layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
27382  layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
27383  layout->bounds.w -= (style->tab.indent + style->window.padding.x);
27384  layout->row.tree_depth++;
27385  return nk_true;
27386  } else return nk_false;
27387 }
27399 NK_INTERN int
27400 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
27401  struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
27402  const char *hash, int len, int line)
27403 {
27404  struct nk_window *win = ctx->current;
27405  int title_len = 0;
27406  nk_hash tree_hash = 0;
27407  nk_uint *state = 0;
27408 
27409  /* retrieve tree state from internal widget state tables */
27410  if (!hash) {
27411  title_len = (int)nk_strlen(title);
27412  tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
27413  } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
27414  state = nk_find_value(win, tree_hash);
27415  if (!state) {
27416  state = nk_add_value(ctx, win, tree_hash, 0);
27417  *state = initial_state;
27418  }
27419  return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
27420 }
27432 NK_API nk_bool
27433 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
27434  const char *title, enum nk_collapse_states *state)
27435 {
27436  return nk_tree_state_base(ctx, type, 0, title, state);
27437 }
27449 NK_API nk_bool
27450 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
27451  struct nk_image img, const char *title, enum nk_collapse_states *state)
27452 {
27453  return nk_tree_state_base(ctx, type, &img, title, state);
27454 }
27465 NK_API void
27466 nk_tree_state_pop(struct nk_context *ctx)
27467 {
27468  struct nk_window *win = 0;
27469  struct nk_panel *layout = 0;
27470 
27471  NK_ASSERT(ctx);
27472  NK_ASSERT(ctx->current);
27473  NK_ASSERT(ctx->current->layout);
27474  if (!ctx || !ctx->current || !ctx->current->layout)
27475  return;
27476 
27477  win = ctx->current;
27478  layout = win->layout;
27479  layout->at_x -= ctx->style.tab.indent + (float)*layout->offset_x;
27480  layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
27481  NK_ASSERT(layout->row.tree_depth);
27482  layout->row.tree_depth--;
27483 }
27495 NK_API nk_bool
27496 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
27497  const char *title, enum nk_collapse_states initial_state,
27498  const char *hash, int len, int line)
27499 {
27500  return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);
27501 }
27513 NK_API nk_bool
27514 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
27515  struct nk_image img, const char *title, enum nk_collapse_states initial_state,
27516  const char *hash, int len,int seed)
27517 {
27518  return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);
27519 }
27530 NK_API void
27531 nk_tree_pop(struct nk_context *ctx)
27532 {
27533  nk_tree_state_pop(ctx);
27534 }
27546 NK_INTERN int
27547 nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type,
27548  struct nk_image *img, const char *title, int title_len,
27549  enum nk_collapse_states *state, nk_bool *selected)
27550 {
27551  struct nk_window *win;
27552  struct nk_panel *layout;
27553  const struct nk_style *style;
27554  struct nk_command_buffer *out;
27555  const struct nk_input *in;
27556  const struct nk_style_button *button;
27557  enum nk_symbol_type symbol;
27558  float row_height;
27559  struct nk_vec2 padding;
27560 
27561  int text_len;
27562  float text_width;
27563 
27564  struct nk_vec2 item_spacing;
27565  struct nk_rect header = {0,0,0,0};
27566  struct nk_rect sym = {0,0,0,0};
27567 
27568  nk_flags ws = 0;
27569  enum nk_widget_layout_states widget_state;
27570 
27571  NK_ASSERT(ctx);
27572  NK_ASSERT(ctx->current);
27573  NK_ASSERT(ctx->current->layout);
27574  if (!ctx || !ctx->current || !ctx->current->layout)
27575  return 0;
27576 
27577  /* cache some data */
27578  win = ctx->current;
27579  layout = win->layout;
27580  out = &win->buffer;
27581  style = &ctx->style;
27582  item_spacing = style->window.spacing;
27583  padding = style->selectable.padding;
27584 
27585  /* calculate header bounds and draw background */
27586  row_height = style->font->height + 2 * style->tab.padding.y;
27587  nk_layout_set_min_row_height(ctx, row_height);
27588  nk_layout_row_dynamic(ctx, row_height, 1);
27590 
27591  widget_state = nk_widget(&header, ctx);
27592  if (type == NK_TREE_TAB) {
27593  const struct nk_style_item *background = &style->tab.background;
27594 
27595  switch (background->type) {
27596  case NK_STYLE_ITEM_IMAGE:
27597  nk_draw_image(out, header, &background->data.image, nk_rgb_factor(nk_white, style->tab.color_factor));
27598  break;
27599  case NK_STYLE_ITEM_NINE_SLICE:
27600  nk_draw_nine_slice(out, header, &background->data.slice, nk_rgb_factor(nk_white, style->tab.color_factor));
27601  break;
27602  case NK_STYLE_ITEM_COLOR:
27603  nk_fill_rect(out, header, 0, nk_rgb_factor(style->tab.border_color, style->tab.color_factor));
27604  nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
27605  style->tab.rounding, nk_rgb_factor(background->data.color, style->tab.color_factor));
27606 
27607  break;
27608  }
27609  }
27610 
27611  in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
27612  in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
27613 
27614  /* select correct button style */
27615  if (*state == NK_MAXIMIZED) {
27616  symbol = style->tab.sym_maximize;
27617  if (type == NK_TREE_TAB)
27618  button = &style->tab.tab_maximize_button;
27619  else button = &style->tab.node_maximize_button;
27620  } else {
27621  symbol = style->tab.sym_minimize;
27622  if (type == NK_TREE_TAB)
27623  button = &style->tab.tab_minimize_button;
27624  else button = &style->tab.node_minimize_button;
27625  }
27626  {/* draw triangle button */
27627  sym.w = sym.h = style->font->height;
27628  sym.y = header.y + style->tab.padding.y;
27629  sym.x = header.x + style->tab.padding.x;
27630  if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font))
27631  *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;}
27632 
27633  /* draw label */
27634  {nk_flags dummy = 0;
27635  struct nk_rect label;
27636  /* calculate size of the text and tooltip */
27637  text_len = nk_strlen(title);
27638  text_width = style->font->width(style->font->userdata, style->font->height, title, text_len);
27639  text_width += (4 * padding.x);
27640 
27641  header.w = NK_MAX(header.w, sym.w + item_spacing.x);
27642  label.x = sym.x + sym.w + item_spacing.x;
27643  label.y = sym.y;
27644  label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width);
27645  label.h = style->font->height;
27646 
27647  if (img) {
27648  nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
27649  selected, img, &style->selectable, in, style->font);
27650  } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT,
27651  selected, &style->selectable, in, style->font);
27652  }
27653  /* increase x-axis cursor widget position pointer */
27654  if (*state == NK_MAXIMIZED) {
27655  layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
27656  layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
27657  layout->bounds.w -= (style->tab.indent + style->window.padding.x);
27658  layout->row.tree_depth++;
27659  return nk_true;
27660  } else return nk_false;
27661 }
27673 NK_INTERN int
27674 nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type,
27675  struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
27676  nk_bool *selected, const char *hash, int len, int line)
27677 {
27678  struct nk_window *win = ctx->current;
27679  int title_len = 0;
27680  nk_hash tree_hash = 0;
27681  nk_uint *state = 0;
27682 
27683  /* retrieve tree state from internal widget state tables */
27684  if (!hash) {
27685  title_len = (int)nk_strlen(title);
27686  tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
27687  } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
27688  state = nk_find_value(win, tree_hash);
27689  if (!state) {
27690  state = nk_add_value(ctx, win, tree_hash, 0);
27691  *state = initial_state;
27692  } return nk_tree_element_image_push_hashed_base(ctx, type, img, title,
27693  nk_strlen(title), (enum nk_collapse_states*)state, selected);
27694 }
27706 NK_API nk_bool
27707 nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
27708  const char *title, enum nk_collapse_states initial_state,
27709  nk_bool *selected, const char *hash, int len, int seed)
27710 {
27711  return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed);
27712 }
27724 NK_API nk_bool
27725 nk_tree_element_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
27726  struct nk_image img, const char *title, enum nk_collapse_states initial_state,
27727  nk_bool *selected, const char *hash, int len,int seed)
27728 {
27729  return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed);
27730 }
27741 NK_API void
27742 nk_tree_element_pop(struct nk_context *ctx)
27743 {
27744  nk_tree_state_pop(ctx);
27745 }
27746 
27747 
27748 
27749 
27750 
27751 /* ===============================================================
27752  *
27753  * GROUP
27754  *
27755  * ===============================================================*/
27766 NK_API nk_bool
27768  nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
27769 {
27770  struct nk_rect bounds;
27771  struct nk_window panel;
27772  struct nk_window *win;
27773 
27774  win = ctx->current;
27775  nk_panel_alloc_space(&bounds, ctx);
27776  {const struct nk_rect *c = &win->layout->clip;
27777  if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
27778  !(flags & NK_WINDOW_MOVABLE)) {
27779  return 0;
27780  }}
27781  if (win->flags & NK_WINDOW_ROM)
27782  flags |= NK_WINDOW_ROM;
27783 
27784  /* initialize a fake window to create the panel from */
27785  nk_zero(&panel, sizeof(panel));
27786  panel.bounds = bounds;
27787  panel.flags = flags;
27788  panel.scrollbar.x = *x_offset;
27789  panel.scrollbar.y = *y_offset;
27790  panel.buffer = win->buffer;
27791  panel.layout = (struct nk_panel*)nk_create_panel(ctx);
27792  ctx->current = &panel;
27793  nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
27794 
27795  win->buffer = panel.buffer;
27796  win->buffer.clip = panel.layout->clip;
27797  panel.layout->offset_x = x_offset;
27798  panel.layout->offset_y = y_offset;
27799  panel.layout->parent = win->layout;
27800  win->layout = panel.layout;
27801 
27802  ctx->current = win;
27803  if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
27804  (panel.layout->flags & NK_WINDOW_MINIMIZED))
27805  {
27806  nk_flags f = panel.layout->flags;
27807  nk_group_scrolled_end(ctx);
27808  if (f & NK_WINDOW_CLOSED)
27809  return NK_WINDOW_CLOSED;
27810  if (f & NK_WINDOW_MINIMIZED)
27811  return NK_WINDOW_MINIMIZED;
27812  }
27813  return 1;
27814 }
27825 NK_API void
27826 nk_group_scrolled_end(struct nk_context *ctx)
27827 {
27828  struct nk_window *win;
27829  struct nk_panel *parent;
27830  struct nk_panel *g;
27831 
27832  struct nk_rect clip;
27833  struct nk_window pan;
27834  struct nk_vec2 panel_padding;
27835 
27836  NK_ASSERT(ctx);
27837  NK_ASSERT(ctx->current);
27838  if (!ctx || !ctx->current)
27839  return;
27840 
27841  /* make sure nk_group_begin was called correctly */
27842  NK_ASSERT(ctx->current);
27843  win = ctx->current;
27844  NK_ASSERT(win->layout);
27845  g = win->layout;
27846  NK_ASSERT(g->parent);
27847  parent = g->parent;
27848 
27849  /* dummy window */
27850  nk_zero_struct(pan);
27851  panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
27852  pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
27853  pan.bounds.x = g->bounds.x - panel_padding.x;
27854  pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
27855  pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
27856  if (g->flags & NK_WINDOW_BORDER) {
27857  pan.bounds.x -= g->border;
27858  pan.bounds.y -= g->border;
27859  pan.bounds.w += 2*g->border;
27860  pan.bounds.h += 2*g->border;
27861  }
27862  if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
27863  pan.bounds.w += ctx->style.window.scrollbar_size.x;
27864  pan.bounds.h += ctx->style.window.scrollbar_size.y;
27865  }
27866  pan.scrollbar.x = *g->offset_x;
27867  pan.scrollbar.y = *g->offset_y;
27868  pan.flags = g->flags;
27869  pan.buffer = win->buffer;
27870  pan.layout = g;
27871  pan.parent = win;
27872  ctx->current = &pan;
27873 
27874  /* make sure group has correct clipping rectangle */
27875  nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
27876  pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
27877  nk_push_scissor(&pan.buffer, clip);
27878  nk_end(ctx);
27879 
27880  win->buffer = pan.buffer;
27881  nk_push_scissor(&win->buffer, parent->clip);
27882  ctx->current = win;
27883  win->layout = parent;
27884  g->bounds = pan.bounds;
27885  return;
27886 }
27897 NK_API nk_bool
27899  struct nk_scroll *scroll, const char *title, nk_flags flags)
27900 {
27901  return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);
27902 }
27914 NK_API nk_bool
27915 nk_group_begin_titled(struct nk_context *ctx, const char *id,
27916  const char *title, nk_flags flags)
27917 {
27918  int id_len;
27919  nk_hash id_hash;
27920  struct nk_window *win;
27921  nk_uint *x_offset;
27922  nk_uint *y_offset;
27923 
27924  NK_ASSERT(ctx);
27925  NK_ASSERT(id);
27926  NK_ASSERT(ctx->current);
27927  NK_ASSERT(ctx->current->layout);
27928  if (!ctx || !ctx->current || !ctx->current->layout || !id)
27929  return 0;
27930 
27931  /* find persistent group scrollbar value */
27932  win = ctx->current;
27933  id_len = (int)nk_strlen(id);
27934  id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
27935  x_offset = nk_find_value(win, id_hash);
27936  if (!x_offset) {
27937  x_offset = nk_add_value(ctx, win, id_hash, 0);
27938  y_offset = nk_add_value(ctx, win, id_hash+1, 0);
27939 
27940  NK_ASSERT(x_offset);
27941  NK_ASSERT(y_offset);
27942  if (!x_offset || !y_offset) return 0;
27943  *x_offset = *y_offset = 0;
27944  } else y_offset = nk_find_value(win, id_hash+1);
27945  return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
27946 }
27959 NK_API nk_bool
27960 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
27961 {
27962  return nk_group_begin_titled(ctx, title, title, flags);
27963 }
27974 NK_API void
27975 nk_group_end(struct nk_context *ctx)
27976 {
27977  nk_group_scrolled_end(ctx);
27978 }
27991 NK_API void
27992 nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset)
27993 {
27994  int id_len;
27995  nk_hash id_hash;
27996  struct nk_window *win;
27997  nk_uint *x_offset_ptr;
27998  nk_uint *y_offset_ptr;
27999 
28000  NK_ASSERT(ctx);
28001  NK_ASSERT(id);
28002  NK_ASSERT(ctx->current);
28003  NK_ASSERT(ctx->current->layout);
28004  if (!ctx || !ctx->current || !ctx->current->layout || !id)
28005  return;
28006 
28007  /* find persistent group scrollbar value */
28008  win = ctx->current;
28009  id_len = (int)nk_strlen(id);
28010  id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
28011  x_offset_ptr = nk_find_value(win, id_hash);
28012  if (!x_offset_ptr) {
28013  x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
28014  y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
28015 
28016  NK_ASSERT(x_offset_ptr);
28017  NK_ASSERT(y_offset_ptr);
28018  if (!x_offset_ptr || !y_offset_ptr) return;
28019  *x_offset_ptr = *y_offset_ptr = 0;
28020  } else y_offset_ptr = nk_find_value(win, id_hash+1);
28021  if (x_offset)
28022  *x_offset = *x_offset_ptr;
28023  if (y_offset)
28024  *y_offset = *y_offset_ptr;
28025 }
28039 NK_API void
28040 nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset)
28041 {
28042  int id_len;
28043  nk_hash id_hash;
28044  struct nk_window *win;
28045  nk_uint *x_offset_ptr;
28046  nk_uint *y_offset_ptr;
28047 
28048  NK_ASSERT(ctx);
28049  NK_ASSERT(id);
28050  NK_ASSERT(ctx->current);
28051  NK_ASSERT(ctx->current->layout);
28052  if (!ctx || !ctx->current || !ctx->current->layout || !id)
28053  return;
28054 
28055  /* find persistent group scrollbar value */
28056  win = ctx->current;
28057  id_len = (int)nk_strlen(id);
28058  id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP);
28059  x_offset_ptr = nk_find_value(win, id_hash);
28060  if (!x_offset_ptr) {
28061  x_offset_ptr = nk_add_value(ctx, win, id_hash, 0);
28062  y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0);
28063 
28064  NK_ASSERT(x_offset_ptr);
28065  NK_ASSERT(y_offset_ptr);
28066  if (!x_offset_ptr || !y_offset_ptr) return;
28067  *x_offset_ptr = *y_offset_ptr = 0;
28068  } else y_offset_ptr = nk_find_value(win, id_hash+1);
28069  *x_offset_ptr = x_offset;
28070  *y_offset_ptr = y_offset;
28071 }
28072 
28073 
28074 
28075 
28076 /* ===============================================================
28077  *
28078  * LIST VIEW
28079  *
28080  * ===============================================================*/
28092 NK_API nk_bool
28093 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
28094  const char *title, nk_flags flags, int row_height, int row_count)
28095 {
28096  int title_len;
28097  nk_hash title_hash;
28098  nk_uint *x_offset;
28099  nk_uint *y_offset;
28100 
28101  int result;
28102  struct nk_window *win;
28103  struct nk_panel *layout;
28104  const struct nk_style *style;
28105  struct nk_vec2 item_spacing;
28106 
28107  NK_ASSERT(ctx);
28108  NK_ASSERT(view);
28109  NK_ASSERT(title);
28110  if (!ctx || !view || !title) return 0;
28111 
28112  win = ctx->current;
28113  style = &ctx->style;
28114  item_spacing = style->window.spacing;
28115  row_height += NK_MAX(0, (int)item_spacing.y);
28116 
28117  /* find persistent list view scrollbar offset */
28118  title_len = (int)nk_strlen(title);
28119  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
28120  x_offset = nk_find_value(win, title_hash);
28121  if (!x_offset) {
28122  x_offset = nk_add_value(ctx, win, title_hash, 0);
28123  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
28124 
28125  NK_ASSERT(x_offset);
28126  NK_ASSERT(y_offset);
28127  if (!x_offset || !y_offset) return 0;
28128  *x_offset = *y_offset = 0;
28129  } else y_offset = nk_find_value(win, title_hash+1);
28130  view->scroll_value = *y_offset;
28131  view->scroll_pointer = y_offset;
28132 
28133  *y_offset = 0;
28134  result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
28135  win = ctx->current;
28136  layout = win->layout;
28137 
28138  view->total_height = row_height * NK_MAX(row_count,1);
28139  view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
28140  view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0);
28141  view->count = NK_MIN(view->count, row_count - view->begin);
28142  view->end = view->begin + view->count;
28143  view->ctx = ctx;
28144  return result;
28145 }
28156 NK_API void
28157 nk_list_view_end(struct nk_list_view *view)
28158 {
28159  struct nk_context *ctx;
28160  struct nk_window *win;
28161  struct nk_panel *layout;
28162 
28163  NK_ASSERT(view);
28164  NK_ASSERT(view->ctx);
28165  NK_ASSERT(view->scroll_pointer);
28166  if (!view || !view->ctx) return;
28167 
28168  ctx = view->ctx;
28169  win = ctx->current;
28170  layout = win->layout;
28171  layout->at_y = layout->bounds.y + (float)view->total_height;
28172  *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
28173  nk_group_end(view->ctx);
28174 }
28175 
28176 
28177 
28178 
28179 
28180 /* ===============================================================
28181  *
28182  * WIDGET
28183  *
28184  * ===============================================================*/
28195 NK_API struct nk_rect
28196 nk_widget_bounds(const struct nk_context *ctx)
28197 {
28198  struct nk_rect bounds;
28199  NK_ASSERT(ctx);
28200  NK_ASSERT(ctx->current);
28201  if (!ctx || !ctx->current)
28202  return nk_rect(0,0,0,0);
28203  nk_layout_peek(&bounds, ctx);
28204  return bounds;
28205 }
28216 NK_API struct nk_vec2
28217 nk_widget_position(const struct nk_context *ctx)
28218 {
28219  struct nk_rect bounds;
28220  NK_ASSERT(ctx);
28221  NK_ASSERT(ctx->current);
28222  if (!ctx || !ctx->current)
28223  return nk_vec2(0,0);
28224 
28225  nk_layout_peek(&bounds, ctx);
28226  return nk_vec2(bounds.x, bounds.y);
28227 }
28238 NK_API struct nk_vec2
28239 nk_widget_size(const struct nk_context *ctx)
28240 {
28241  struct nk_rect bounds;
28242  NK_ASSERT(ctx);
28243  NK_ASSERT(ctx->current);
28244  if (!ctx || !ctx->current)
28245  return nk_vec2(0,0);
28246 
28247  nk_layout_peek(&bounds, ctx);
28248  return nk_vec2(bounds.w, bounds.h);
28249 }
28260 NK_API float
28261 nk_widget_width(const struct nk_context *ctx)
28262 {
28263  struct nk_rect bounds;
28264  NK_ASSERT(ctx);
28265  NK_ASSERT(ctx->current);
28266  if (!ctx || !ctx->current)
28267  return 0;
28268 
28269  nk_layout_peek(&bounds, ctx);
28270  return bounds.w;
28271 }
28282 NK_API float
28283 nk_widget_height(const struct nk_context *ctx)
28284 {
28285  struct nk_rect bounds;
28286  NK_ASSERT(ctx);
28287  NK_ASSERT(ctx->current);
28288  if (!ctx || !ctx->current)
28289  return 0;
28290 
28291  nk_layout_peek(&bounds, ctx);
28292  return bounds.h;
28293 }
28304 NK_API nk_bool
28305 nk_widget_is_hovered(const struct nk_context *ctx)
28306 {
28307  struct nk_rect c, v;
28308  struct nk_rect bounds;
28309  NK_ASSERT(ctx);
28310  NK_ASSERT(ctx->current);
28311  if (!ctx || !ctx->current || ctx->active != ctx->current)
28312  return 0;
28313 
28314  c = ctx->current->layout->clip;
28315  c.x = (float)((int)c.x);
28316  c.y = (float)((int)c.y);
28317  c.w = (float)((int)c.w);
28318  c.h = (float)((int)c.h);
28319 
28320  nk_layout_peek(&bounds, ctx);
28321  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
28322  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
28323  return 0;
28324  return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
28325 }
28337 NK_API nk_bool
28338 nk_widget_is_mouse_clicked(const struct nk_context *ctx, enum nk_buttons btn)
28339 {
28340  struct nk_rect c, v;
28341  struct nk_rect bounds;
28342  NK_ASSERT(ctx);
28343  NK_ASSERT(ctx->current);
28344  if (!ctx || !ctx->current || ctx->active != ctx->current)
28345  return 0;
28346 
28347  c = ctx->current->layout->clip;
28348  c.x = (float)((int)c.x);
28349  c.y = (float)((int)c.y);
28350  c.w = (float)((int)c.w);
28351  c.h = (float)((int)c.h);
28352 
28353  nk_layout_peek(&bounds, ctx);
28354  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
28355  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
28356  return 0;
28357  return nk_input_mouse_clicked(&ctx->input, btn, bounds);
28358 }
28371 NK_API nk_bool
28372 nk_widget_has_mouse_click_down(const struct nk_context *ctx, enum nk_buttons btn, nk_bool down)
28373 {
28374  struct nk_rect c, v;
28375  struct nk_rect bounds;
28376  NK_ASSERT(ctx);
28377  NK_ASSERT(ctx->current);
28378  if (!ctx || !ctx->current || ctx->active != ctx->current)
28379  return 0;
28380 
28381  c = ctx->current->layout->clip;
28382  c.x = (float)((int)c.x);
28383  c.y = (float)((int)c.y);
28384  c.w = (float)((int)c.w);
28385  c.h = (float)((int)c.h);
28386 
28387  nk_layout_peek(&bounds, ctx);
28388  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
28389  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
28390  return 0;
28391  return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
28392 }
28404 NK_API enum nk_widget_layout_states
28405 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
28406 {
28407  struct nk_rect c, v;
28408  struct nk_window *win;
28409  struct nk_panel *layout;
28410  const struct nk_input *in;
28411 
28412  NK_ASSERT(ctx);
28413  NK_ASSERT(ctx->current);
28414  NK_ASSERT(ctx->current->layout);
28415  if (!ctx || !ctx->current || !ctx->current->layout)
28416  return NK_WIDGET_INVALID;
28417 
28418  /* allocate space and check if the widget needs to be updated and drawn */
28419  nk_panel_alloc_space(bounds, ctx);
28420  win = ctx->current;
28421  layout = win->layout;
28422  in = &ctx->input;
28423  c = layout->clip;
28424 
28425  /* if one of these triggers you forgot to add an `if` condition around either
28426  a window, group, popup, combobox or contextual menu `begin` and `end` block.
28427  Example:
28428  if (nk_begin(...) {...} nk_end(...); or
28429  if (nk_group_begin(...) { nk_group_end(...);} */
28430  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
28431  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
28432  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
28433 
28434  /* need to convert to int here to remove floating point errors */
28435  bounds->x = (float)((int)bounds->x);
28436  bounds->y = (float)((int)bounds->y);
28437  bounds->w = (float)((int)bounds->w);
28438  bounds->h = (float)((int)bounds->h);
28439 
28440  c.x = (float)((int)c.x);
28441  c.y = (float)((int)c.y);
28442  c.w = (float)((int)c.w);
28443  c.h = (float)((int)c.h);
28444 
28445  nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
28446  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
28447  return NK_WIDGET_INVALID;
28448  if (win->widgets_disabled)
28449  return NK_WIDGET_DISABLED;
28450  if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
28451  return NK_WIDGET_ROM;
28452  return NK_WIDGET_VALID;
28453 }
28465 NK_API enum nk_widget_layout_states
28466 nk_widget_fitting(struct nk_rect *bounds, const struct nk_context *ctx,
28467  struct nk_vec2 item_padding)
28468 {
28469  /* update the bounds to stand without padding */
28470  enum nk_widget_layout_states state;
28471  NK_UNUSED(item_padding);
28472 
28473  NK_ASSERT(ctx);
28474  NK_ASSERT(ctx->current);
28475  NK_ASSERT(ctx->current->layout);
28476  if (!ctx || !ctx->current || !ctx->current->layout)
28477  return NK_WIDGET_INVALID;
28478 
28479  state = nk_widget(bounds, ctx);
28480  return state;
28481 }
28493 NK_API void
28494 nk_spacing(struct nk_context *ctx, int cols)
28495 {
28496  struct nk_window *win;
28497  struct nk_panel *layout;
28498  struct nk_rect none;
28499  int i, index, rows;
28500 
28501  NK_ASSERT(ctx);
28502  NK_ASSERT(ctx->current);
28503  NK_ASSERT(ctx->current->layout);
28504  if (!ctx || !ctx->current || !ctx->current->layout)
28505  return;
28506 
28507  /* spacing over row boundaries */
28508  win = ctx->current;
28509  layout = win->layout;
28510  index = (layout->row.index + cols) % layout->row.columns;
28511  rows = (layout->row.index + cols) / layout->row.columns;
28512  if (rows) {
28513  for (i = 0; i < rows; ++i)
28514  nk_panel_alloc_row(ctx, win);
28515  cols = index;
28516  }
28517  /* non table layout need to allocate space */
28518  if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
28519  layout->row.type != NK_LAYOUT_STATIC_FIXED) {
28520  for (i = 0; i < cols; ++i)
28521  nk_panel_alloc_space(&none, ctx);
28522  } layout->row.index = index;
28523 }
28534 NK_API void
28535 nk_widget_disable_begin(struct nk_context* ctx)
28536 {
28537  struct nk_window* win;
28538  struct nk_style* style;
28539 
28540  NK_ASSERT(ctx);
28541  NK_ASSERT(ctx->current);
28542 
28543  if (!ctx || !ctx->current)
28544  return;
28545 
28546  win = ctx->current;
28547  style = &ctx->style;
28548 
28549  win->widgets_disabled = nk_true;
28550 
28551  style->button.color_factor_text = style->button.disabled_factor;
28552  style->button.color_factor_background = style->button.disabled_factor;
28553  style->chart.color_factor = style->chart.disabled_factor;
28554  style->checkbox.color_factor = style->checkbox.disabled_factor;
28555  style->combo.color_factor = style->combo.disabled_factor;
28556  style->combo.button.color_factor_text = style->combo.button.disabled_factor;
28557  style->combo.button.color_factor_background = style->combo.button.disabled_factor;
28558  style->contextual_button.color_factor_text = style->contextual_button.disabled_factor;
28559  style->contextual_button.color_factor_background = style->contextual_button.disabled_factor;
28560  style->edit.color_factor = style->edit.disabled_factor;
28561  style->edit.scrollbar.color_factor = style->edit.scrollbar.disabled_factor;
28562  style->menu_button.color_factor_text = style->menu_button.disabled_factor;
28563  style->menu_button.color_factor_background = style->menu_button.disabled_factor;
28564  style->option.color_factor = style->option.disabled_factor;
28565  style->progress.color_factor = style->progress.disabled_factor;
28566  style->property.color_factor = style->property.disabled_factor;
28567  style->property.inc_button.color_factor_text = style->property.inc_button.disabled_factor;
28568  style->property.inc_button.color_factor_background = style->property.inc_button.disabled_factor;
28569  style->property.dec_button.color_factor_text = style->property.dec_button.disabled_factor;
28570  style->property.dec_button.color_factor_background = style->property.dec_button.disabled_factor;
28571  style->property.edit.color_factor = style->property.edit.disabled_factor;
28572  style->scrollh.color_factor = style->scrollh.disabled_factor;
28573  style->scrollh.inc_button.color_factor_text = style->scrollh.inc_button.disabled_factor;
28574  style->scrollh.inc_button.color_factor_background = style->scrollh.inc_button.disabled_factor;
28575  style->scrollh.dec_button.color_factor_text = style->scrollh.dec_button.disabled_factor;
28576  style->scrollh.dec_button.color_factor_background = style->scrollh.dec_button.disabled_factor;
28577  style->scrollv.color_factor = style->scrollv.disabled_factor;
28578  style->scrollv.inc_button.color_factor_text = style->scrollv.inc_button.disabled_factor;
28579  style->scrollv.inc_button.color_factor_background = style->scrollv.inc_button.disabled_factor;
28580  style->scrollv.dec_button.color_factor_text = style->scrollv.dec_button.disabled_factor;
28581  style->scrollv.dec_button.color_factor_background = style->scrollv.dec_button.disabled_factor;
28582  style->selectable.color_factor = style->selectable.disabled_factor;
28583  style->slider.color_factor = style->slider.disabled_factor;
28584  style->slider.inc_button.color_factor_text = style->slider.inc_button.disabled_factor;
28585  style->slider.inc_button.color_factor_background = style->slider.inc_button.disabled_factor;
28586  style->slider.dec_button.color_factor_text = style->slider.dec_button.disabled_factor;
28587  style->slider.dec_button.color_factor_background = style->slider.dec_button.disabled_factor;
28588  style->tab.color_factor = style->tab.disabled_factor;
28589  style->tab.node_maximize_button.color_factor_text = style->tab.node_maximize_button.disabled_factor;
28590  style->tab.node_minimize_button.color_factor_text = style->tab.node_minimize_button.disabled_factor;
28591  style->tab.tab_maximize_button.color_factor_text = style->tab.tab_maximize_button.disabled_factor;
28592  style->tab.tab_maximize_button.color_factor_background = style->tab.tab_maximize_button.disabled_factor;
28593  style->tab.tab_minimize_button.color_factor_text = style->tab.tab_minimize_button.disabled_factor;
28594  style->tab.tab_minimize_button.color_factor_background = style->tab.tab_minimize_button.disabled_factor;
28595  style->text.color_factor = style->text.disabled_factor;
28596 }
28607 NK_API void
28608 nk_widget_disable_end(struct nk_context* ctx)
28609 {
28610  struct nk_window* win;
28611  struct nk_style* style;
28612 
28613  NK_ASSERT(ctx);
28614  NK_ASSERT(ctx->current);
28615 
28616  if (!ctx || !ctx->current)
28617  return;
28618 
28619  win = ctx->current;
28620  style = &ctx->style;
28621 
28622  win->widgets_disabled = nk_false;
28623 
28624  style->button.color_factor_text = 1.0f;
28625  style->button.color_factor_background = 1.0f;
28626  style->chart.color_factor = 1.0f;
28627  style->checkbox.color_factor = 1.0f;
28628  style->combo.color_factor = 1.0f;
28629  style->combo.button.color_factor_text = 1.0f;
28630  style->combo.button.color_factor_background = 1.0f;
28631  style->contextual_button.color_factor_text = 1.0f;
28632  style->contextual_button.color_factor_background = 1.0f;
28633  style->edit.color_factor = 1.0f;
28634  style->edit.scrollbar.color_factor = 1.0f;
28635  style->menu_button.color_factor_text = 1.0f;
28636  style->menu_button.color_factor_background = 1.0f;
28637  style->option.color_factor = 1.0f;
28638  style->progress.color_factor = 1.0f;
28639  style->property.color_factor = 1.0f;
28640  style->property.inc_button.color_factor_text = 1.0f;
28641  style->property.inc_button.color_factor_background = 1.0f;
28642  style->property.dec_button.color_factor_text = 1.0f;
28643  style->property.dec_button.color_factor_background = 1.0f;
28644  style->property.edit.color_factor = 1.0f;
28645  style->scrollh.color_factor = 1.0f;
28646  style->scrollh.inc_button.color_factor_text = 1.0f;
28647  style->scrollh.inc_button.color_factor_background = 1.0f;
28648  style->scrollh.dec_button.color_factor_text = 1.0f;
28649  style->scrollh.dec_button.color_factor_background = 1.0f;
28650  style->scrollv.color_factor = 1.0f;
28651  style->scrollv.inc_button.color_factor_text = 1.0f;
28652  style->scrollv.inc_button.color_factor_background = 1.0f;
28653  style->scrollv.dec_button.color_factor_text = 1.0f;
28654  style->scrollv.dec_button.color_factor_background = 1.0f;
28655  style->selectable.color_factor = 1.0f;
28656  style->slider.color_factor = 1.0f;
28657  style->slider.inc_button.color_factor_text = 1.0f;
28658  style->slider.inc_button.color_factor_background = 1.0f;
28659  style->slider.dec_button.color_factor_text = 1.0f;
28660  style->slider.dec_button.color_factor_background = 1.0f;
28661  style->tab.color_factor = 1.0f;
28662  style->tab.node_maximize_button.color_factor_text = 1.0f;
28663  style->tab.node_minimize_button.color_factor_text = 1.0f;
28664  style->tab.tab_maximize_button.color_factor_text = 1.0f;
28665  style->tab.tab_maximize_button.color_factor_background = 1.0f;
28666  style->tab.tab_minimize_button.color_factor_text = 1.0f;
28667  style->tab.tab_minimize_button.color_factor_background = 1.0f;
28668  style->text.color_factor = 1.0f;
28669 }
28670 
28671 
28672 
28673 
28674 /* ===============================================================
28675  *
28676  * TEXT
28677  *
28678  * ===============================================================*/
28690 NK_LIB void
28691 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
28692  const char *string, int len, const struct nk_text *t,
28693  nk_flags a, const struct nk_user_font *f)
28694 {
28695  struct nk_rect label;
28696  float text_width;
28697 
28698  NK_ASSERT(o);
28699  NK_ASSERT(t);
28700  if (!o || !t) return;
28701 
28702  b.h = NK_MAX(b.h, 2 * t->padding.y);
28703  label.x = 0; label.w = 0;
28704  label.y = b.y + t->padding.y;
28705  label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
28706 
28707  text_width = f->width(f->userdata, f->height, (const char*)string, len);
28708  text_width += (2.0f * t->padding.x);
28709 
28710  /* align in x-axis */
28711  if (a & NK_TEXT_ALIGN_LEFT) {
28712  label.x = b.x + t->padding.x;
28713  label.w = NK_MAX(0, b.w - 2 * t->padding.x);
28714  } else if (a & NK_TEXT_ALIGN_CENTERED) {
28715  label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
28716  label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
28717  label.x = NK_MAX(b.x + t->padding.x, label.x);
28718  label.w = NK_MIN(b.x + b.w, label.x + label.w);
28719  if (label.w >= label.x) label.w -= label.x;
28720  } else if (a & NK_TEXT_ALIGN_RIGHT) {
28721  label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
28722  label.w = (float)text_width + 2 * t->padding.x;
28723  } else return;
28724 
28725  /* align in y-axis */
28726  if (a & NK_TEXT_ALIGN_MIDDLE) {
28727  label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
28728  label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
28729  } else if (a & NK_TEXT_ALIGN_BOTTOM) {
28730  label.y = b.y + b.h - f->height;
28731  label.h = f->height;
28732  }
28733  nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text);
28734 }
28746 NK_LIB void
28747 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
28748  const char *string, int len, const struct nk_text *t,
28749  const struct nk_user_font *f)
28750 {
28751  float width;
28752  int glyphs = 0;
28753  int fitting = 0;
28754  int done = 0;
28755  struct nk_rect line;
28756  struct nk_text text;
28757  NK_INTERN nk_rune seperator[] = {' '};
28758 
28759  NK_ASSERT(o);
28760  NK_ASSERT(t);
28761  if (!o || !t) return;
28762 
28763  text.padding = nk_vec2(0,0);
28764  text.background = t->background;
28765  text.text = t->text;
28766 
28767  b.w = NK_MAX(b.w, 2 * t->padding.x);
28768  b.h = NK_MAX(b.h, 2 * t->padding.y);
28769  b.h = b.h - 2 * t->padding.y;
28770 
28771  line.x = b.x + t->padding.x;
28772  line.y = b.y + t->padding.y;
28773  line.w = b.w - 2 * t->padding.x;
28774  line.h = 2 * t->padding.y + f->height;
28775 
28776  fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
28777  while (done < len) {
28778  if (!fitting || line.y + line.h >= (b.y + b.h)) break;
28779  nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
28780  done += fitting;
28781  line.y += f->height + 2 * t->padding.y;
28782  fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
28783  }
28784 }
28797 NK_API void
28798 nk_text_colored(struct nk_context *ctx, const char *str, int len,
28799  nk_flags alignment, struct nk_color color)
28800 {
28801  struct nk_window *win;
28802  const struct nk_style *style;
28803 
28804  struct nk_vec2 item_padding;
28805  struct nk_rect bounds;
28806  struct nk_text text;
28807 
28808  NK_ASSERT(ctx);
28809  NK_ASSERT(ctx->current);
28810  NK_ASSERT(ctx->current->layout);
28811  if (!ctx || !ctx->current || !ctx->current->layout) return;
28812 
28813  win = ctx->current;
28814  style = &ctx->style;
28815  nk_panel_alloc_space(&bounds, ctx);
28816  item_padding = style->text.padding;
28817 
28818  text.padding.x = item_padding.x;
28819  text.padding.y = item_padding.y;
28820  text.background = style->window.background;
28821  text.text = nk_rgb_factor(color, style->text.color_factor);
28822  nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
28823 }
28835 NK_API void
28836 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
28837  int len, struct nk_color color)
28838 {
28839  struct nk_window *win;
28840  const struct nk_style *style;
28841 
28842  struct nk_vec2 item_padding;
28843  struct nk_rect bounds;
28844  struct nk_text text;
28845 
28846  NK_ASSERT(ctx);
28847  NK_ASSERT(ctx->current);
28848  NK_ASSERT(ctx->current->layout);
28849  if (!ctx || !ctx->current || !ctx->current->layout) return;
28850 
28851  win = ctx->current;
28852  style = &ctx->style;
28853  nk_panel_alloc_space(&bounds, ctx);
28854  item_padding = style->text.padding;
28855 
28856  text.padding.x = item_padding.x;
28857  text.padding.y = item_padding.y;
28858  text.background = style->window.background;
28859  text.text = nk_rgb_factor(color, style->text.color_factor);
28860  nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
28861 }
28862 #ifdef NK_INCLUDE_STANDARD_VARARGS
28874 NK_API void
28875 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
28876  struct nk_color color, const char *fmt, ...)
28877 {
28878  va_list args;
28879  va_start(args, fmt);
28880  nk_labelfv_colored(ctx, flags, color, fmt, args);
28881  va_end(args);
28882 }
28894 NK_API void
28895 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
28896  const char *fmt, ...)
28897 {
28898  va_list args;
28899  va_start(args, fmt);
28900  nk_labelfv_colored_wrap(ctx, color, fmt, args);
28901  va_end(args);
28902 }
28915 NK_API void
28916 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
28917 {
28918  va_list args;
28919  va_start(args, fmt);
28920  nk_labelfv(ctx, flags, fmt, args);
28921  va_end(args);
28922 }
28934 NK_API void
28935 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
28936 {
28937  va_list args;
28938  va_start(args, fmt);
28939  nk_labelfv_wrap(ctx, fmt, args);
28940  va_end(args);
28941 }
28953 NK_API void
28954 nk_labelfv_colored(struct nk_context *ctx, nk_flags flags,
28955  struct nk_color color, const char *fmt, va_list args)
28956 {
28957  char buf[256];
28958  nk_strfmt(buf, NK_LEN(buf), fmt, args);
28959  nk_label_colored(ctx, buf, flags, color);
28960 }
28961 
28973 NK_API void
28974 nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color,
28975  const char *fmt, va_list args)
28976 {
28977  char buf[256];
28978  nk_strfmt(buf, NK_LEN(buf), fmt, args);
28979  nk_label_colored_wrap(ctx, buf, color);
28980 }
28981 
28995 NK_API void
28996 nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args)
28997 {
28998  char buf[256];
28999  nk_strfmt(buf, NK_LEN(buf), fmt, args);
29000  nk_label(ctx, buf, flags);
29001 }
29002 
29015 NK_API void
29016 nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args)
29017 {
29018  char buf[256];
29019  nk_strfmt(buf, NK_LEN(buf), fmt, args);
29020  nk_label_wrap(ctx, buf);
29021 }
29022 
29035 NK_API void
29036 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
29037 {
29038  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));
29039 }
29052 NK_API void
29053 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
29054 {
29055  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);
29056 }
29069 NK_API void
29070 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
29071 {
29072  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);
29073 }
29086 NK_API void
29087 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
29088 {
29089  double double_value = (double)value;
29090  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
29091 }
29104 NK_API void
29105 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
29106 {
29107  nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);
29108 }
29121 NK_API void
29122 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
29123 {
29124  double c[4]; nk_color_dv(c, color);
29125  nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
29126  p, c[0], c[1], c[2], c[3]);
29127 }
29140 NK_API void
29141 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
29142 {
29143  char hex[16];
29144  nk_color_hex_rgba(hex, color);
29145  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
29146 }
29147 #endif
29161 NK_API void
29162 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
29163 {
29164  NK_ASSERT(ctx);
29165  if (!ctx) return;
29166  nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
29167 }
29180 NK_API void
29181 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
29182 {
29183  NK_ASSERT(ctx);
29184  if (!ctx) return;
29185  nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
29186 }
29199 NK_API void
29200 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
29201 {
29202  nk_text(ctx, str, nk_strlen(str), alignment);
29203 }
29216 NK_API void
29217 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
29218  struct nk_color color)
29219 {
29220  nk_text_colored(ctx, str, nk_strlen(str), align, color);
29221 }
29233 NK_API void
29234 nk_label_wrap(struct nk_context *ctx, const char *str)
29235 {
29236  nk_text_wrap(ctx, str, nk_strlen(str));
29237 }
29250 NK_API void
29251 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
29252 {
29253  nk_text_wrap_colored(ctx, str, nk_strlen(str), color);
29254 }
29255 
29256 
29257 
29258 
29259 
29260 /* ===============================================================
29261  *
29262  * IMAGE
29263  *
29264  * ===============================================================*/
29275 NK_API nk_handle
29276 nk_handle_ptr(void *ptr)
29277 {
29278  nk_handle handle = {0};
29279  handle.ptr = ptr;
29280  return handle;
29281 }
29292 NK_API nk_handle
29293 nk_handle_id(int id)
29294 {
29295  nk_handle handle;
29296  nk_zero_struct(handle);
29297  handle.id = id;
29298  return handle;
29299 }
29313 NK_API struct nk_image
29314 nk_subimage_ptr(void *ptr, nk_ushort w, nk_ushort h, struct nk_rect r)
29315 {
29316  struct nk_image s;
29317  nk_zero(&s, sizeof(s));
29318  s.handle.ptr = ptr;
29319  s.w = w; s.h = h;
29320  s.region[0] = (nk_ushort)r.x;
29321  s.region[1] = (nk_ushort)r.y;
29322  s.region[2] = (nk_ushort)r.w;
29323  s.region[3] = (nk_ushort)r.h;
29324  return s;
29325 }
29339 NK_API struct nk_image
29340 nk_subimage_id(int id, nk_ushort w, nk_ushort h, struct nk_rect r)
29341 {
29342  struct nk_image s;
29343  nk_zero(&s, sizeof(s));
29344  s.handle.id = id;
29345  s.w = w; s.h = h;
29346  s.region[0] = (nk_ushort)r.x;
29347  s.region[1] = (nk_ushort)r.y;
29348  s.region[2] = (nk_ushort)r.w;
29349  s.region[3] = (nk_ushort)r.h;
29350  return s;
29351 }
29365 NK_API struct nk_image
29366 nk_subimage_handle(nk_handle handle, nk_ushort w, nk_ushort h, struct nk_rect r)
29367 {
29368  struct nk_image s;
29369  nk_zero(&s, sizeof(s));
29370  s.handle = handle;
29371  s.w = w; s.h = h;
29372  s.region[0] = (nk_ushort)r.x;
29373  s.region[1] = (nk_ushort)r.y;
29374  s.region[2] = (nk_ushort)r.w;
29375  s.region[3] = (nk_ushort)r.h;
29376  return s;
29377 }
29388 NK_API struct nk_image
29389 nk_image_handle(nk_handle handle)
29390 {
29391  struct nk_image s;
29392  nk_zero(&s, sizeof(s));
29393  s.handle = handle;
29394  s.w = 0; s.h = 0;
29395  s.region[0] = 0;
29396  s.region[1] = 0;
29397  s.region[2] = 0;
29398  s.region[3] = 0;
29399  return s;
29400 }
29411 NK_API struct nk_image
29412 nk_image_ptr(void *ptr)
29413 {
29414  struct nk_image s;
29415  nk_zero(&s, sizeof(s));
29416  NK_ASSERT(ptr);
29417  s.handle.ptr = ptr;
29418  s.w = 0; s.h = 0;
29419  s.region[0] = 0;
29420  s.region[1] = 0;
29421  s.region[2] = 0;
29422  s.region[3] = 0;
29423  return s;
29424 }
29435 NK_API struct nk_image
29436 nk_image_id(int id)
29437 {
29438  struct nk_image s;
29439  nk_zero(&s, sizeof(s));
29440  s.handle.id = id;
29441  s.w = 0; s.h = 0;
29442  s.region[0] = 0;
29443  s.region[1] = 0;
29444  s.region[2] = 0;
29445  s.region[3] = 0;
29446  return s;
29447 }
29458 NK_API nk_bool
29459 nk_image_is_subimage(const struct nk_image* img)
29460 {
29461  NK_ASSERT(img);
29462  return !(img->w == 0 && img->h == 0);
29463 }
29475 NK_API void
29476 nk_image(struct nk_context *ctx, struct nk_image img)
29477 {
29478  struct nk_window *win;
29479  struct nk_rect bounds;
29480 
29481  NK_ASSERT(ctx);
29482  NK_ASSERT(ctx->current);
29483  NK_ASSERT(ctx->current->layout);
29484  if (!ctx || !ctx->current || !ctx->current->layout) return;
29485 
29486  win = ctx->current;
29487  if (!nk_widget(&bounds, ctx)) return;
29488  nk_draw_image(&win->buffer, bounds, &img, nk_white);
29489 }
29502 NK_API void
29503 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col)
29504 {
29505  struct nk_window *win;
29506  struct nk_rect bounds;
29507 
29508  NK_ASSERT(ctx);
29509  NK_ASSERT(ctx->current);
29510  NK_ASSERT(ctx->current->layout);
29511  if (!ctx || !ctx->current || !ctx->current->layout) return;
29512 
29513  win = ctx->current;
29514  if (!nk_widget(&bounds, ctx)) return;
29515  nk_draw_image(&win->buffer, bounds, &img, col);
29516 }
29517 
29518 
29519 
29520 
29521 
29522 /* ===============================================================
29523  *
29524  * 9-SLICE
29525  *
29526  * ===============================================================*/
29541 NK_API struct nk_nine_slice
29542 nk_sub9slice_ptr(void *ptr, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
29543 {
29544  struct nk_nine_slice s;
29545  struct nk_image *i = &s.img;
29546  nk_zero(&s, sizeof(s));
29547  i->handle.ptr = ptr;
29548  i->w = w; i->h = h;
29549  i->region[0] = (nk_ushort)rgn.x;
29550  i->region[1] = (nk_ushort)rgn.y;
29551  i->region[2] = (nk_ushort)rgn.w;
29552  i->region[3] = (nk_ushort)rgn.h;
29553  s.l = l; s.t = t; s.r = r; s.b = b;
29554  return s;
29555 }
29571 NK_API struct nk_nine_slice
29572 nk_sub9slice_id(int id, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
29573 {
29574  struct nk_nine_slice s;
29575  struct nk_image *i = &s.img;
29576  nk_zero(&s, sizeof(s));
29577  i->handle.id = id;
29578  i->w = w; i->h = h;
29579  i->region[0] = (nk_ushort)rgn.x;
29580  i->region[1] = (nk_ushort)rgn.y;
29581  i->region[2] = (nk_ushort)rgn.w;
29582  i->region[3] = (nk_ushort)rgn.h;
29583  s.l = l; s.t = t; s.r = r; s.b = b;
29584  return s;
29585 }
29600 NK_API struct nk_nine_slice
29601 nk_sub9slice_handle(nk_handle handle, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
29602 {
29603  struct nk_nine_slice s;
29604  struct nk_image *i = &s.img;
29605  nk_zero(&s, sizeof(s));
29606  i->handle = handle;
29607  i->w = w; i->h = h;
29608  i->region[0] = (nk_ushort)rgn.x;
29609  i->region[1] = (nk_ushort)rgn.y;
29610  i->region[2] = (nk_ushort)rgn.w;
29611  i->region[3] = (nk_ushort)rgn.h;
29612  s.l = l; s.t = t; s.r = r; s.b = b;
29613  return s;
29614 }
29629 NK_API struct nk_nine_slice
29630 nk_nine_slice_handle(nk_handle handle, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
29631 {
29632  struct nk_nine_slice s;
29633  struct nk_image *i = &s.img;
29634  nk_zero(&s, sizeof(s));
29635  i->handle = handle;
29636  i->w = 0; i->h = 0;
29637  i->region[0] = 0;
29638  i->region[1] = 0;
29639  i->region[2] = 0;
29640  i->region[3] = 0;
29641  s.l = l; s.t = t; s.r = r; s.b = b;
29642  return s;
29643 }
29658 NK_API struct nk_nine_slice
29659 nk_nine_slice_ptr(void *ptr, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
29660 {
29661  struct nk_nine_slice s;
29662  struct nk_image *i = &s.img;
29663  nk_zero(&s, sizeof(s));
29664  NK_ASSERT(ptr);
29665  i->handle.ptr = ptr;
29666  i->w = 0; i->h = 0;
29667  i->region[0] = 0;
29668  i->region[1] = 0;
29669  i->region[2] = 0;
29670  i->region[3] = 0;
29671  s.l = l; s.t = t; s.r = r; s.b = b;
29672  return s;
29673 }
29688 NK_API struct nk_nine_slice
29689 nk_nine_slice_id(int id, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b)
29690 {
29691  struct nk_nine_slice s;
29692  struct nk_image *i = &s.img;
29693  nk_zero(&s, sizeof(s));
29694  i->handle.id = id;
29695  i->w = 0; i->h = 0;
29696  i->region[0] = 0;
29697  i->region[1] = 0;
29698  i->region[2] = 0;
29699  i->region[3] = 0;
29700  s.l = l; s.t = t; s.r = r; s.b = b;
29701  return s;
29702 }
29713 NK_API int
29714 nk_nine_slice_is_sub9slice(const struct nk_nine_slice* slice)
29715 {
29716  NK_ASSERT(slice);
29717  return !(slice->img.w == 0 && slice->img.h == 0);
29718 }
29719 
29720 
29721 
29722 
29723 
29724 /* ==============================================================
29725  *
29726  * BUTTON
29727  *
29728  * ===============================================================*/
29729 
29730 /********************************************************************
29731  * @brief ADD DOCUMENTATION
29732  *
29733  * @details
29734  * ADD Detailed DOCUMENTATION
29735  *
29736  * @param[out] nk_command_buffer is the buffer with the commands.
29737  * @param[in] nk_symbol_type
29738  * @param[in] nk_rect_content
29739  * @param[in] nk_color_background
29740  * @param[in] nk_color_foreground
29741  * @param[in] border_width
29742  * @param[in] nk_user_font
29743  *
29744  * @returns void
29745  *******************************************************************/
29746 NK_LIB void
29747 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
29748  struct nk_rect content, struct nk_color background, struct nk_color foreground,
29749  float border_width, const struct nk_user_font *font)
29750 {
29751  switch (type) {
29752  case NK_SYMBOL_X:
29753  case NK_SYMBOL_UNDERSCORE:
29754  case NK_SYMBOL_PLUS:
29755  case NK_SYMBOL_MINUS: {
29756  /* single character text symbol */
29757  const char *X = (type == NK_SYMBOL_X) ? "x":
29758  (type == NK_SYMBOL_UNDERSCORE) ? "_":
29759  (type == NK_SYMBOL_PLUS) ? "+": "-";
29760  struct nk_text text;
29761  text.padding = nk_vec2(0,0);
29762  text.background = background;
29763  text.text = foreground;
29764  nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
29765  } break;
29766  case NK_SYMBOL_CIRCLE_SOLID:
29767  case NK_SYMBOL_CIRCLE_OUTLINE:
29768  case NK_SYMBOL_RECT_SOLID:
29769  case NK_SYMBOL_RECT_OUTLINE: {
29770  /* simple empty/filled shapes */
29771  if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
29772  nk_fill_rect(out, content, 0, foreground);
29773  if (type == NK_SYMBOL_RECT_OUTLINE)
29774  nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
29775  } else {
29776  nk_fill_circle(out, content, foreground);
29777  if (type == NK_SYMBOL_CIRCLE_OUTLINE)
29778  nk_fill_circle(out, nk_shrink_rect(content, 1), background);
29779  }
29780  } break;
29781  case NK_SYMBOL_TRIANGLE_UP:
29782  case NK_SYMBOL_TRIANGLE_DOWN:
29783  case NK_SYMBOL_TRIANGLE_LEFT:
29784  case NK_SYMBOL_TRIANGLE_RIGHT: {
29785  enum nk_heading heading;
29786  struct nk_vec2 points[3];
29787  heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
29788  (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
29789  (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
29790  nk_triangle_from_direction(points, content, 0, 0, heading);
29791  nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
29792  points[2].x, points[2].y, foreground);
29793  } break;
29794  case NK_SYMBOL_TRIANGLE_UP_OUTLINE:
29795  case NK_SYMBOL_TRIANGLE_DOWN_OUTLINE:
29796  case NK_SYMBOL_TRIANGLE_LEFT_OUTLINE:
29797  case NK_SYMBOL_TRIANGLE_RIGHT_OUTLINE: {
29798  enum nk_heading heading;
29799  struct nk_vec2 points[3];
29800  heading = (type == NK_SYMBOL_TRIANGLE_RIGHT_OUTLINE) ? NK_RIGHT :
29801  (type == NK_SYMBOL_TRIANGLE_LEFT_OUTLINE) ? NK_LEFT:
29802  (type == NK_SYMBOL_TRIANGLE_UP_OUTLINE) ? NK_UP: NK_DOWN;
29803  nk_triangle_from_direction(points, content, 0, 0, heading);
29804  nk_stroke_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
29805  points[2].x, points[2].y, border_width, foreground);
29806  } break;
29807  default:
29808  case NK_SYMBOL_NONE:
29809  case NK_SYMBOL_MAX: break;
29810  }
29811 }
29812 /********************************************************************
29813  * @brief ADD DOCUMENTATION
29814  *
29815  * @details
29816  * ADD Detailed DOCUMENTATION
29817  *
29818  * @param[in] state
29819  * @param[in] r
29820  * @param[in] i
29821  * @param[in] behavior
29822  *
29823  * @returns void
29824  *******************************************************************/
29825 NK_LIB nk_bool
29826 nk_button_behavior(nk_flags *state, struct nk_rect r,
29827  const struct nk_input *i, enum nk_button_behavior behavior)
29828 {
29829  int ret = 0;
29830  nk_widget_state_reset(state);
29831  if (!i) return 0;
29832  if (nk_input_is_mouse_hovering_rect(i, r)) {
29833  *state = NK_WIDGET_STATE_HOVERED;
29834  if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT))
29835  *state = NK_WIDGET_STATE_ACTIVE;
29836  if (nk_input_has_mouse_click_in_button_rect(i, NK_BUTTON_LEFT, r)) {
29837  ret = (behavior != NK_BUTTON_DEFAULT) ?
29838  nk_input_is_mouse_down(i, NK_BUTTON_LEFT):
29839 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
29840  nk_input_is_mouse_released(i, NK_BUTTON_LEFT);
29841 #else
29842  nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT);
29843 #endif
29844  }
29845  }
29846  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r))
29847  *state |= NK_WIDGET_STATE_ENTERED;
29848  else if (nk_input_is_mouse_prev_hovering_rect(i, r))
29849  *state |= NK_WIDGET_STATE_LEFT;
29850  return ret;
29851 }
29852 /********************************************************************
29853  * @brief ADD DOCUMENTATION
29854  *
29855  * @details
29856  * ADD Detailed DOCUMENTATION
29857  *
29858  * @param[out] nk_command_buffer is the buffer with the commands.
29859  * @param[in] nk_symbol_type
29860  * @param[in] nk_rect_content
29861  * @param[in] nk_color_background
29862  * @param[in] nk_color_foreground
29863  * @param[in] border_width
29864  * @param[in] nk_user_font
29865  *
29866  * @returns void
29867  *******************************************************************/
29868 NK_LIB const struct nk_style_item*
29869 nk_draw_button(struct nk_command_buffer *out,
29870  const struct nk_rect *bounds, nk_flags state,
29871  const struct nk_style_button *style)
29872 {
29873  const struct nk_style_item *background;
29874  if (state & NK_WIDGET_STATE_HOVER)
29875  background = &style->hover;
29876  else if (state & NK_WIDGET_STATE_ACTIVED)
29877  background = &style->active;
29878  else background = &style->normal;
29879 
29880  switch (background->type) {
29881  case NK_STYLE_ITEM_IMAGE:
29882  nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor_background));
29883  break;
29884  case NK_STYLE_ITEM_NINE_SLICE:
29885  nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor_background));
29886  break;
29887  case NK_STYLE_ITEM_COLOR:
29888  nk_fill_rect(out, *bounds, style->rounding, nk_rgb_factor(background->data.color, style->color_factor_background));
29889  nk_stroke_rect(out, *bounds, style->rounding, style->border, nk_rgb_factor(style->border_color, style->color_factor_background));
29890  break;
29891  }
29892  return background;
29893 }
29894 /********************************************************************
29895  * @brief ADD DOCUMENTATION
29896  *
29897  * @details
29898  * ADD Detailed DOCUMENTATION
29899  *
29900  * @param[out] nk_command_buffer is the buffer with the commands.
29901  * @param[in] nk_symbol_type
29902  * @param[in] nk_rect_content
29903  * @param[in] nk_color_background
29904  * @param[in] nk_color_foreground
29905  * @param[in] border_width
29906  * @param[in] nk_user_font
29907  *
29908  * @returns void
29909  *******************************************************************/
29910 NK_LIB nk_bool
29911 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
29912  const struct nk_style_button *style, const struct nk_input *in,
29913  enum nk_button_behavior behavior, struct nk_rect *content)
29914 {
29915  struct nk_rect bounds;
29916  NK_ASSERT(style);
29917  NK_ASSERT(state);
29918  NK_ASSERT(out);
29919  if (!out || !style)
29920  return nk_false;
29921 
29922  /* calculate button content space */
29923  content->x = r.x + style->padding.x + style->border + style->rounding;
29924  content->y = r.y + style->padding.y + style->border + style->rounding;
29925  content->w = r.w - (2 * (style->padding.x + style->border + style->rounding));
29926  content->h = r.h - (2 * (style->padding.y + style->border + style->rounding));
29927 
29928  /* execute button behavior */
29929  bounds.x = r.x - style->touch_padding.x;
29930  bounds.y = r.y - style->touch_padding.y;
29931  bounds.w = r.w + 2 * style->touch_padding.x;
29932  bounds.h = r.h + 2 * style->touch_padding.y;
29933  return nk_button_behavior(state, bounds, in, behavior);
29934 }
29935 /********************************************************************
29936  * @brief ADD DOCUMENTATION
29937  *
29938  * @details
29939  * ADD Detailed DOCUMENTATION
29940  *
29941  * @param[out] nk_command_buffer is the buffer with the commands.
29942  * @param[in] nk_symbol_type
29943  * @param[in] nk_rect_content
29944  * @param[in] nk_color_background
29945  * @param[in] nk_color_foreground
29946  * @param[in] border_width
29947  * @param[in] nk_user_font
29948  *
29949  * @returns void
29950  *******************************************************************/
29951 NK_LIB void
29952 nk_draw_button_text(struct nk_command_buffer *out,
29953  const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
29954  const struct nk_style_button *style, const char *txt, int len,
29955  nk_flags text_alignment, const struct nk_user_font *font)
29956 {
29957  struct nk_text text;
29958  const struct nk_style_item *background;
29959  background = nk_draw_button(out, bounds, state, style);
29960 
29961  /* select correct colors/images */
29962  if (background->type == NK_STYLE_ITEM_COLOR)
29963  text.background = background->data.color;
29964  else text.background = style->text_background;
29965  if (state & NK_WIDGET_STATE_HOVER)
29966  text.text = style->text_hover;
29967  else if (state & NK_WIDGET_STATE_ACTIVED)
29968  text.text = style->text_active;
29969  else text.text = style->text_normal;
29970 
29971  text.text = nk_rgb_factor(text.text, style->color_factor_text);
29972 
29973  text.padding = nk_vec2(0,0);
29974  nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
29975 }
29976 /********************************************************************
29977  * @brief ADD DOCUMENTATION
29978  *
29979  * @details
29980  * ADD Detailed DOCUMENTATION
29981  *
29982  * @param[out] nk_command_buffer is the buffer with the commands.
29983  * @param[in] nk_symbol_type
29984  * @param[in] nk_rect_content
29985  * @param[in] nk_color_background
29986  * @param[in] nk_color_foreground
29987  * @param[in] border_width
29988  * @param[in] nk_user_font
29989  *
29990  * @returns void
29991  *******************************************************************/
29992 NK_LIB nk_bool
29993 nk_do_button_text(nk_flags *state,
29994  struct nk_command_buffer *out, struct nk_rect bounds,
29995  const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
29996  const struct nk_style_button *style, const struct nk_input *in,
29997  const struct nk_user_font *font)
29998 {
29999  struct nk_rect content;
30000  int ret = nk_false;
30001 
30002  NK_ASSERT(state);
30003  NK_ASSERT(style);
30004  NK_ASSERT(out);
30005  NK_ASSERT(string);
30006  NK_ASSERT(font);
30007  if (!out || !style || !font || !string)
30008  return nk_false;
30009 
30010  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
30011  if (style->draw_begin) style->draw_begin(out, style->userdata);
30012  nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
30013  if (style->draw_end) style->draw_end(out, style->userdata);
30014  return ret;
30015 }
30016 /********************************************************************
30017  * @brief ADD DOCUMENTATION
30018  *
30019  * @details
30020  * ADD Detailed DOCUMENTATION
30021  *
30022  * @param[out] nk_command_buffer is the buffer with the commands.
30023  * @param[in] nk_symbol_type
30024  * @param[in] nk_rect_content
30025  * @param[in] nk_color_background
30026  * @param[in] nk_color_foreground
30027  * @param[in] border_width
30028  * @param[in] nk_user_font
30029  *
30030  * @returns void
30031  *******************************************************************/
30032 NK_LIB void
30033 nk_draw_button_symbol(struct nk_command_buffer *out,
30034  const struct nk_rect *bounds, const struct nk_rect *content,
30035  nk_flags state, const struct nk_style_button *style,
30036  enum nk_symbol_type type, const struct nk_user_font *font)
30037 {
30038  struct nk_color sym, bg;
30039  const struct nk_style_item *background;
30040 
30041  /* select correct colors/images */
30042  background = nk_draw_button(out, bounds, state, style);
30043  if (background->type == NK_STYLE_ITEM_COLOR)
30044  bg = background->data.color;
30045  else bg = style->text_background;
30046 
30047  if (state & NK_WIDGET_STATE_HOVER)
30048  sym = style->text_hover;
30049  else if (state & NK_WIDGET_STATE_ACTIVED)
30050  sym = style->text_active;
30051  else sym = style->text_normal;
30052 
30053  sym = nk_rgb_factor(sym, style->color_factor_text);
30054  nk_draw_symbol(out, type, *content, bg, sym, 1, font);
30055 }
30056 /********************************************************************
30057  * @brief ADD DOCUMENTATION
30058  *
30059  * @details
30060  * ADD Detailed DOCUMENTATION
30061  *
30062  * @param[out] nk_command_buffer is the buffer with the commands.
30063  * @param[in] nk_symbol_type
30064  * @param[in] nk_rect_content
30065  * @param[in] nk_color_background
30066  * @param[in] nk_color_foreground
30067  * @param[in] border_width
30068  * @param[in] nk_user_font
30069  *
30070  * @returns void
30071  *******************************************************************/
30072 NK_LIB nk_bool
30073 nk_do_button_symbol(nk_flags *state,
30074  struct nk_command_buffer *out, struct nk_rect bounds,
30075  enum nk_symbol_type symbol, enum nk_button_behavior behavior,
30076  const struct nk_style_button *style, const struct nk_input *in,
30077  const struct nk_user_font *font)
30078 {
30079  int ret;
30080  struct nk_rect content;
30081 
30082  NK_ASSERT(state);
30083  NK_ASSERT(style);
30084  NK_ASSERT(font);
30085  NK_ASSERT(out);
30086  if (!out || !style || !font || !state)
30087  return nk_false;
30088 
30089  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
30090  if (style->draw_begin) style->draw_begin(out, style->userdata);
30091  nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
30092  if (style->draw_end) style->draw_end(out, style->userdata);
30093  return ret;
30094 }
30095 /********************************************************************
30096  * @brief ADD DOCUMENTATION
30097  *
30098  * @details
30099  * ADD Detailed DOCUMENTATION
30100  *
30101  * @param[out] nk_command_buffer is the buffer with the commands.
30102  * @param[in] nk_symbol_type
30103  * @param[in] nk_rect_content
30104  * @param[in] nk_color_background
30105  * @param[in] nk_color_foreground
30106  * @param[in] border_width
30107  * @param[in] nk_user_font
30108  *
30109  * @returns void
30110  *******************************************************************/
30111 NK_LIB void
30112 nk_draw_button_image(struct nk_command_buffer *out,
30113  const struct nk_rect *bounds, const struct nk_rect *content,
30114  nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
30115 {
30116  nk_draw_button(out, bounds, state, style);
30117  nk_draw_image(out, *content, img, nk_rgb_factor(nk_white, style->color_factor_background));
30118 }
30119 /********************************************************************
30120  * @brief ADD DOCUMENTATION
30121  *
30122  * @details
30123  * ADD Detailed DOCUMENTATION
30124  *
30125  * @param[out] nk_command_buffer is the buffer with the commands.
30126  * @param[in] nk_symbol_type
30127  * @param[in] nk_rect_content
30128  * @param[in] nk_color_background
30129  * @param[in] nk_color_foreground
30130  * @param[in] border_width
30131  * @param[in] nk_user_font
30132  *
30133  * @returns void
30134  *******************************************************************/
30135 NK_LIB nk_bool
30136 nk_do_button_image(nk_flags *state,
30137  struct nk_command_buffer *out, struct nk_rect bounds,
30138  struct nk_image img, enum nk_button_behavior b,
30139  const struct nk_style_button *style, const struct nk_input *in)
30140 {
30141  int ret;
30142  struct nk_rect content;
30143 
30144  NK_ASSERT(state);
30145  NK_ASSERT(style);
30146  NK_ASSERT(out);
30147  if (!out || !style || !state)
30148  return nk_false;
30149 
30150  ret = nk_do_button(state, out, bounds, style, in, b, &content);
30151  content.x += style->image_padding.x;
30152  content.y += style->image_padding.y;
30153  content.w -= 2 * style->image_padding.x;
30154  content.h -= 2 * style->image_padding.y;
30155 
30156  if (style->draw_begin) style->draw_begin(out, style->userdata);
30157  nk_draw_button_image(out, &bounds, &content, *state, style, &img);
30158  if (style->draw_end) style->draw_end(out, style->userdata);
30159  return ret;
30160 }
30161 /********************************************************************
30162  * @brief ADD DOCUMENTATION
30163  *
30164  * @details
30165  * ADD Detailed DOCUMENTATION
30166  *
30167  * @param[out] nk_command_buffer is the buffer with the commands.
30168  * @param[in] nk_symbol_type
30169  * @param[in] nk_rect_content
30170  * @param[in] nk_color_background
30171  * @param[in] nk_color_foreground
30172  * @param[in] border_width
30173  * @param[in] nk_user_font
30174  *
30175  * @returns void
30176  *******************************************************************/
30177 NK_LIB void
30178 nk_draw_button_text_symbol(struct nk_command_buffer *out,
30179  const struct nk_rect *bounds, const struct nk_rect *label,
30180  const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
30181  const char *str, int len, enum nk_symbol_type type,
30182  const struct nk_user_font *font)
30183 {
30184  struct nk_color sym;
30185  struct nk_text text;
30186  const struct nk_style_item *background;
30187 
30188  /* select correct background colors/images */
30189  background = nk_draw_button(out, bounds, state, style);
30190  if (background->type == NK_STYLE_ITEM_COLOR)
30191  text.background = background->data.color;
30192  else text.background = style->text_background;
30193 
30194  /* select correct text colors */
30195  if (state & NK_WIDGET_STATE_HOVER) {
30196  sym = style->text_hover;
30197  text.text = style->text_hover;
30198  } else if (state & NK_WIDGET_STATE_ACTIVED) {
30199  sym = style->text_active;
30200  text.text = style->text_active;
30201  } else {
30202  sym = style->text_normal;
30203  text.text = style->text_normal;
30204  }
30205 
30206  sym = nk_rgb_factor(sym, style->color_factor_text);
30207  text.text = nk_rgb_factor(text.text, style->color_factor_text);
30208  text.padding = nk_vec2(0,0);
30209  nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
30210  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
30211 }
30212 /********************************************************************
30213  * @brief ADD DOCUMENTATION
30214  *
30215  * @details
30216  * ADD Detailed DOCUMENTATION
30217  *
30218  * @param[out] nk_command_buffer is the buffer with the commands.
30219  * @param[in] nk_symbol_type
30220  * @param[in] nk_rect_content
30221  * @param[in] nk_color_background
30222  * @param[in] nk_color_foreground
30223  * @param[in] border_width
30224  * @param[in] nk_user_font
30225  *
30226  * @returns void
30227  *******************************************************************/
30228 NK_LIB nk_bool
30229 nk_do_button_text_symbol(nk_flags *state,
30230  struct nk_command_buffer *out, struct nk_rect bounds,
30231  enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
30232  enum nk_button_behavior behavior, const struct nk_style_button *style,
30233  const struct nk_user_font *font, const struct nk_input *in)
30234 {
30235  int ret;
30236  struct nk_rect tri = {0,0,0,0};
30237  struct nk_rect content;
30238 
30239  NK_ASSERT(style);
30240  NK_ASSERT(out);
30241  NK_ASSERT(font);
30242  if (!out || !style || !font)
30243  return nk_false;
30244 
30245  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
30246  tri.y = content.y + (content.h/2) - font->height/2;
30247  tri.w = font->height; tri.h = font->height;
30248  if (align & NK_TEXT_ALIGN_LEFT) {
30249  tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
30250  tri.x = NK_MAX(tri.x, 0);
30251  } else tri.x = content.x + 2 * style->padding.x;
30252 
30253  /* draw button */
30254  if (style->draw_begin) style->draw_begin(out, style->userdata);
30255  nk_draw_button_text_symbol(out, &bounds, &content, &tri,
30256  *state, style, str, len, symbol, font);
30257  if (style->draw_end) style->draw_end(out, style->userdata);
30258  return ret;
30259 }
30260 /********************************************************************
30261  * @brief ADD DOCUMENTATION
30262  *
30263  * @details
30264  * ADD Detailed DOCUMENTATION
30265  *
30266  * @param[out] nk_command_buffer is the buffer with the commands.
30267  * @param[in] nk_symbol_type
30268  * @param[in] nk_rect_content
30269  * @param[in] nk_color_background
30270  * @param[in] nk_color_foreground
30271  * @param[in] border_width
30272  * @param[in] nk_user_font
30273  *
30274  * @returns void
30275  *******************************************************************/
30276 NK_LIB void
30277 nk_draw_button_text_image(struct nk_command_buffer *out,
30278  const struct nk_rect *bounds, const struct nk_rect *label,
30279  const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
30280  const char *str, int len, const struct nk_user_font *font,
30281  const struct nk_image *img)
30282 {
30283  struct nk_text text;
30284  const struct nk_style_item *background;
30285  background = nk_draw_button(out, bounds, state, style);
30286 
30287  /* select correct colors */
30288  if (background->type == NK_STYLE_ITEM_COLOR)
30289  text.background = background->data.color;
30290  else text.background = style->text_background;
30291  if (state & NK_WIDGET_STATE_HOVER)
30292  text.text = style->text_hover;
30293  else if (state & NK_WIDGET_STATE_ACTIVED)
30294  text.text = style->text_active;
30295  else text.text = style->text_normal;
30296 
30297  text.text = nk_rgb_factor(text.text, style->color_factor_text);
30298  text.padding = nk_vec2(0, 0);
30299  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
30300  nk_draw_image(out, *image, img, nk_rgb_factor(nk_white, style->color_factor_background));
30301 }
30302 /********************************************************************
30303  * @brief ADD DOCUMENTATION
30304  *
30305  * @details
30306  * ADD Detailed DOCUMENTATION
30307  *
30308  * @param[out] nk_command_buffer is the buffer with the commands.
30309  * @param[in] nk_symbol_type
30310  * @param[in] nk_rect_content
30311  * @param[in] nk_color_background
30312  * @param[in] nk_color_foreground
30313  * @param[in] border_width
30314  * @param[in] nk_user_font
30315  *
30316  * @returns void
30317  *******************************************************************/
30318 NK_LIB nk_bool
30319 nk_do_button_text_image(nk_flags *state,
30320  struct nk_command_buffer *out, struct nk_rect bounds,
30321  struct nk_image img, const char* str, int len, nk_flags align,
30322  enum nk_button_behavior behavior, const struct nk_style_button *style,
30323  const struct nk_user_font *font, const struct nk_input *in)
30324 {
30325  int ret;
30326  struct nk_rect icon;
30327  struct nk_rect content;
30328 
30329  NK_ASSERT(style);
30330  NK_ASSERT(state);
30331  NK_ASSERT(font);
30332  NK_ASSERT(out);
30333  if (!out || !font || !style || !str)
30334  return nk_false;
30335 
30336  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
30337  icon.y = bounds.y + style->padding.y;
30338  icon.w = icon.h = bounds.h - 2 * style->padding.y;
30339  if (align & NK_TEXT_ALIGN_LEFT) {
30340  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
30341  icon.x = NK_MAX(icon.x, 0);
30342  } else icon.x = bounds.x + 2 * style->padding.x;
30343 
30344  icon.x += style->image_padding.x;
30345  icon.y += style->image_padding.y;
30346  icon.w -= 2 * style->image_padding.x;
30347  icon.h -= 2 * style->image_padding.y;
30348 
30349  if (style->draw_begin) style->draw_begin(out, style->userdata);
30350  nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
30351  if (style->draw_end) style->draw_end(out, style->userdata);
30352  return ret;
30353 }
30354 /********************************************************************
30355  * @brief ADD DOCUMENTATION
30356  *
30357  * @details
30358  * ADD Detailed DOCUMENTATION
30359  *
30360  * @param[out] nk_command_buffer is the buffer with the commands.
30361  * @param[in] nk_symbol_type
30362  * @param[in] nk_rect_content
30363  * @param[in] nk_color_background
30364  * @param[in] nk_color_foreground
30365  * @param[in] border_width
30366  * @param[in] nk_user_font
30367  *
30368  * @returns void
30369  *******************************************************************/
30370 NK_API void
30371 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
30372 {
30373  NK_ASSERT(ctx);
30374  if (!ctx) return;
30375  ctx->button_behavior = behavior;
30376 }
30377 /********************************************************************
30378  * @brief ADD DOCUMENTATION
30379  *
30380  * @details
30381  * ADD Detailed DOCUMENTATION
30382  *
30383  * @param[out] nk_command_buffer is the buffer with the commands.
30384  * @param[in] nk_symbol_type
30385  * @param[in] nk_rect_content
30386  * @param[in] nk_color_background
30387  * @param[in] nk_color_foreground
30388  * @param[in] border_width
30389  * @param[in] nk_user_font
30390  *
30391  * @returns void
30392  *******************************************************************/
30393 NK_API nk_bool
30394 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
30395 {
30396  struct nk_config_stack_button_behavior *button_stack;
30397  struct nk_config_stack_button_behavior_element *element;
30398 
30399  NK_ASSERT(ctx);
30400  if (!ctx) return 0;
30401 
30402  button_stack = &ctx->stacks.button_behaviors;
30403  NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
30404  if (button_stack->head >= (int)NK_LEN(button_stack->elements))
30405  return 0;
30406 
30407  element = &button_stack->elements[button_stack->head++];
30408  element->address = &ctx->button_behavior;
30409  element->old_value = ctx->button_behavior;
30410  ctx->button_behavior = behavior;
30411  return 1;
30412 }
30413 /********************************************************************
30414  * @brief ADD DOCUMENTATION
30415  *
30416  * @details
30417  * ADD Detailed DOCUMENTATION
30418  *
30419  * @param[out] nk_command_buffer is the buffer with the commands.
30420  * @param[in] nk_symbol_type
30421  * @param[in] nk_rect_content
30422  * @param[in] nk_color_background
30423  * @param[in] nk_color_foreground
30424  * @param[in] border_width
30425  * @param[in] nk_user_font
30426  *
30427  * @returns void
30428  *******************************************************************/
30429 NK_API nk_bool
30430 nk_button_pop_behavior(struct nk_context *ctx)
30431 {
30432  struct nk_config_stack_button_behavior *button_stack;
30433  struct nk_config_stack_button_behavior_element *element;
30434 
30435  NK_ASSERT(ctx);
30436  if (!ctx) return 0;
30437 
30438  button_stack = &ctx->stacks.button_behaviors;
30439  NK_ASSERT(button_stack->head > 0);
30440  if (button_stack->head < 1)
30441  return 0;
30442 
30443  element = &button_stack->elements[--button_stack->head];
30444  *element->address = element->old_value;
30445  return 1;
30446 }
30447 /********************************************************************
30448  * @brief ADD DOCUMENTATION
30449  *
30450  * @details
30451  * ADD Detailed DOCUMENTATION
30452  *
30453  * @param[out] nk_command_buffer is the buffer with the commands.
30454  * @param[in] nk_symbol_type
30455  * @param[in] nk_rect_content
30456  * @param[in] nk_color_background
30457  * @param[in] nk_color_foreground
30458  * @param[in] border_width
30459  * @param[in] nk_user_font
30460  *
30461  * @returns void
30462  *******************************************************************/
30463 NK_API nk_bool
30464 nk_button_text_styled(struct nk_context *ctx,
30465  const struct nk_style_button *style, const char *title, int len)
30466 {
30467  struct nk_window *win;
30468  struct nk_panel *layout;
30469  const struct nk_input *in;
30470 
30471  struct nk_rect bounds;
30472  enum nk_widget_layout_states state;
30473 
30474  NK_ASSERT(ctx);
30475  NK_ASSERT(style);
30476  NK_ASSERT(ctx->current);
30477  NK_ASSERT(ctx->current->layout);
30478  if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
30479 
30480  win = ctx->current;
30481  layout = win->layout;
30482  state = nk_widget(&bounds, ctx);
30483 
30484  if (!state) return 0;
30485  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
30486  return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
30487  title, len, style->text_alignment, ctx->button_behavior,
30488  style, in, ctx->style.font);
30489 }
30490 /********************************************************************
30491  * @brief ADD DOCUMENTATION
30492  *
30493  * @details
30494  * ADD Detailed DOCUMENTATION
30495  *
30496  * @param[out] nk_command_buffer is the buffer with the commands.
30497  * @param[in] nk_symbol_type
30498  * @param[in] nk_rect_content
30499  * @param[in] nk_color_background
30500  * @param[in] nk_color_foreground
30501  * @param[in] border_width
30502  * @param[in] nk_user_font
30503  *
30504  * @returns void
30505  *******************************************************************/
30506 NK_API nk_bool
30507 nk_button_text(struct nk_context *ctx, const char *title, int len)
30508 {
30509  NK_ASSERT(ctx);
30510  if (!ctx) return 0;
30511  return nk_button_text_styled(ctx, &ctx->style.button, title, len);
30512 }
30513 /********************************************************************
30514  * @brief ADD DOCUMENTATION
30515  *
30516  * @details
30517  * ADD Detailed DOCUMENTATION
30518  *
30519  * @param[out] nk_command_buffer is the buffer with the commands.
30520  * @param[in] nk_symbol_type
30521  * @param[in] nk_rect_content
30522  * @param[in] nk_color_background
30523  * @param[in] nk_color_foreground
30524  * @param[in] border_width
30525  * @param[in] nk_user_font
30526  *
30527  * @returns void
30528  *******************************************************************/
30529 NK_API nk_bool nk_button_label_styled(struct nk_context *ctx,
30530  const struct nk_style_button *style, const char *title)
30531 {
30532  return nk_button_text_styled(ctx, style, title, nk_strlen(title));
30533 }
30534 /********************************************************************
30535  * @brief ADD DOCUMENTATION
30536  *
30537  * @details
30538  * ADD Detailed DOCUMENTATION
30539  *
30540  * @param[out] nk_command_buffer is the buffer with the commands.
30541  * @param[in] nk_symbol_type
30542  * @param[in] nk_rect_content
30543  * @param[in] nk_color_background
30544  * @param[in] nk_color_foreground
30545  * @param[in] border_width
30546  * @param[in] nk_user_font
30547  *
30548  * @returns void
30549  *******************************************************************/
30550 NK_API nk_bool nk_button_label(struct nk_context *ctx, const char *title)
30551 {
30552  return nk_button_text(ctx, title, nk_strlen(title));
30553 }
30554 /********************************************************************
30555  * @brief ADD DOCUMENTATION
30556  *
30557  * @details
30558  * ADD Detailed DOCUMENTATION
30559  *
30560  * @param[out] nk_command_buffer is the buffer with the commands.
30561  * @param[in] nk_symbol_type
30562  * @param[in] nk_rect_content
30563  * @param[in] nk_color_background
30564  * @param[in] nk_color_foreground
30565  * @param[in] border_width
30566  * @param[in] nk_user_font
30567  *
30568  * @returns void
30569  *******************************************************************/
30570 NK_API nk_bool
30571 nk_button_color(struct nk_context *ctx, struct nk_color color)
30572 {
30573  struct nk_window *win;
30574  struct nk_panel *layout;
30575  const struct nk_input *in;
30576  struct nk_style_button button;
30577 
30578  int ret = 0;
30579  struct nk_rect bounds;
30580  struct nk_rect content;
30581  enum nk_widget_layout_states state;
30582 
30583  NK_ASSERT(ctx);
30584  NK_ASSERT(ctx->current);
30585  NK_ASSERT(ctx->current->layout);
30586  if (!ctx || !ctx->current || !ctx->current->layout)
30587  return 0;
30588 
30589  win = ctx->current;
30590  layout = win->layout;
30591 
30592  state = nk_widget(&bounds, ctx);
30593  if (!state) return 0;
30594  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
30595 
30596  button = ctx->style.button;
30597  button.normal = nk_style_item_color(color);
30598  button.hover = nk_style_item_color(color);
30599  button.active = nk_style_item_color(color);
30600  ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
30601  &button, in, ctx->button_behavior, &content);
30602  nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
30603  return ret;
30604 }
30605 /********************************************************************
30606  * @brief ADD DOCUMENTATION
30607  *
30608  * @details
30609  * ADD Detailed DOCUMENTATION
30610  *
30611  * @param[out] nk_command_buffer is the buffer with the commands.
30612  * @param[in] nk_symbol_type
30613  * @param[in] nk_rect_content
30614  * @param[in] nk_color_background
30615  * @param[in] nk_color_foreground
30616  * @param[in] border_width
30617  * @param[in] nk_user_font
30618  *
30619  * @returns void
30620  *******************************************************************/
30621 NK_API nk_bool
30622 nk_button_symbol_styled(struct nk_context *ctx,
30623  const struct nk_style_button *style, enum nk_symbol_type symbol)
30624 {
30625  struct nk_window *win;
30626  struct nk_panel *layout;
30627  const struct nk_input *in;
30628 
30629  struct nk_rect bounds;
30630  enum nk_widget_layout_states state;
30631 
30632  NK_ASSERT(ctx);
30633  NK_ASSERT(ctx->current);
30634  NK_ASSERT(ctx->current->layout);
30635  if (!ctx || !ctx->current || !ctx->current->layout)
30636  return 0;
30637 
30638  win = ctx->current;
30639  layout = win->layout;
30640  state = nk_widget(&bounds, ctx);
30641  if (!state) return 0;
30642  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
30643  return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
30644  symbol, ctx->button_behavior, style, in, ctx->style.font);
30645 }
30646 /********************************************************************
30647  * @brief ADD DOCUMENTATION
30648  *
30649  * @details
30650  * ADD Detailed DOCUMENTATION
30651  *
30652  * @param[out] nk_command_buffer is the buffer with the commands.
30653  * @param[in] nk_symbol_type
30654  * @param[in] nk_rect_content
30655  * @param[in] nk_color_background
30656  * @param[in] nk_color_foreground
30657  * @param[in] border_width
30658  * @param[in] nk_user_font
30659  *
30660  * @returns void
30661  *******************************************************************/
30662 NK_API nk_bool
30663 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
30664 {
30665  NK_ASSERT(ctx);
30666  if (!ctx) return 0;
30667  return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
30668 }
30669 /********************************************************************
30670  * @brief ADD DOCUMENTATION
30671  *
30672  * @details
30673  * ADD Detailed DOCUMENTATION
30674  *
30675  * @param[out] nk_command_buffer is the buffer with the commands.
30676  * @param[in] nk_symbol_type
30677  * @param[in] nk_rect_content
30678  * @param[in] nk_color_background
30679  * @param[in] nk_color_foreground
30680  * @param[in] border_width
30681  * @param[in] nk_user_font
30682  *
30683  * @returns void
30684  *******************************************************************/
30685 NK_API nk_bool
30686 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
30687  struct nk_image img)
30688 {
30689  struct nk_window *win;
30690  struct nk_panel *layout;
30691  const struct nk_input *in;
30692 
30693  struct nk_rect bounds;
30694  enum nk_widget_layout_states state;
30695 
30696  NK_ASSERT(ctx);
30697  NK_ASSERT(ctx->current);
30698  NK_ASSERT(ctx->current->layout);
30699  if (!ctx || !ctx->current || !ctx->current->layout)
30700  return 0;
30701 
30702  win = ctx->current;
30703  layout = win->layout;
30704 
30705  state = nk_widget(&bounds, ctx);
30706  if (!state) return 0;
30707  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
30708  return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
30709  img, ctx->button_behavior, style, in);
30710 }
30711 /********************************************************************
30712  * @brief ADD DOCUMENTATION
30713  *
30714  * @details
30715  * ADD Detailed DOCUMENTATION
30716  *
30717  * @param[out] nk_command_buffer is the buffer with the commands.
30718  * @param[in] nk_symbol_type
30719  * @param[in] nk_rect_content
30720  * @param[in] nk_color_background
30721  * @param[in] nk_color_foreground
30722  * @param[in] border_width
30723  * @param[in] nk_user_font
30724  *
30725  * @returns void
30726  *******************************************************************/
30727 NK_API nk_bool
30728 nk_button_image(struct nk_context *ctx, struct nk_image img)
30729 {
30730  NK_ASSERT(ctx);
30731  if (!ctx) return 0;
30732  return nk_button_image_styled(ctx, &ctx->style.button, img);
30733 }
30734 /********************************************************************
30735  * @brief ADD DOCUMENTATION
30736  *
30737  * @details
30738  * ADD Detailed DOCUMENTATION
30739  *
30740  * @param[out] nk_command_buffer is the buffer with the commands.
30741  * @param[in] nk_symbol_type
30742  * @param[in] nk_rect_content
30743  * @param[in] nk_color_background
30744  * @param[in] nk_color_foreground
30745  * @param[in] border_width
30746  * @param[in] nk_user_font
30747  *
30748  * @returns void
30749  *******************************************************************/
30750 NK_API nk_bool
30751 nk_button_symbol_text_styled(struct nk_context *ctx,
30752  const struct nk_style_button *style, enum nk_symbol_type symbol,
30753  const char *text, int len, nk_flags align)
30754 {
30755  struct nk_window *win;
30756  struct nk_panel *layout;
30757  const struct nk_input *in;
30758 
30759  struct nk_rect bounds;
30760  enum nk_widget_layout_states state;
30761 
30762  NK_ASSERT(ctx);
30763  NK_ASSERT(ctx->current);
30764  NK_ASSERT(ctx->current->layout);
30765  if (!ctx || !ctx->current || !ctx->current->layout)
30766  return 0;
30767 
30768  win = ctx->current;
30769  layout = win->layout;
30770 
30771  state = nk_widget(&bounds, ctx);
30772  if (!state) return 0;
30773  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
30774  return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
30775  symbol, text, len, align, ctx->button_behavior,
30776  style, ctx->style.font, in);
30777 }
30778 /********************************************************************
30779  * @brief ADD DOCUMENTATION
30780  *
30781  * @details
30782  * ADD Detailed DOCUMENTATION
30783  *
30784  * @param[out] nk_command_buffer is the buffer with the commands.
30785  * @param[in] nk_symbol_type
30786  * @param[in] nk_rect_content
30787  * @param[in] nk_color_background
30788  * @param[in] nk_color_foreground
30789  * @param[in] border_width
30790  * @param[in] nk_user_font
30791  *
30792  * @returns void
30793  *******************************************************************/
30794 NK_API nk_bool
30795 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
30796  const char* text, int len, nk_flags align)
30797 {
30798  NK_ASSERT(ctx);
30799  if (!ctx) return 0;
30800  return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
30801 }
30802 /********************************************************************
30803  * @brief ADD DOCUMENTATION
30804  *
30805  * @details
30806  * ADD Detailed DOCUMENTATION
30807  *
30808  * @param[out] nk_command_buffer is the buffer with the commands.
30809  * @param[in] nk_symbol_type
30810  * @param[in] nk_rect_content
30811  * @param[in] nk_color_background
30812  * @param[in] nk_color_foreground
30813  * @param[in] border_width
30814  * @param[in] nk_user_font
30815  *
30816  * @returns void
30817  *******************************************************************/
30818 NK_API nk_bool nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
30819  const char *label, nk_flags align)
30820 {
30821  return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);
30822 }
30823 /********************************************************************
30824  * @brief ADD DOCUMENTATION
30825  *
30826  * @details
30827  * ADD Detailed DOCUMENTATION
30828  *
30829  * @param[out] nk_command_buffer is the buffer with the commands.
30830  * @param[in] nk_symbol_type
30831  * @param[in] nk_rect_content
30832  * @param[in] nk_color_background
30833  * @param[in] nk_color_foreground
30834  * @param[in] border_width
30835  * @param[in] nk_user_font
30836  *
30837  * @returns void
30838  *******************************************************************/
30839 NK_API nk_bool nk_button_symbol_label_styled(struct nk_context *ctx,
30840  const struct nk_style_button *style, enum nk_symbol_type symbol,
30841  const char *title, nk_flags align)
30842 {
30843  return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);
30844 }
30845 /********************************************************************
30846  * @brief ADD DOCUMENTATION
30847  *
30848  * @details
30849  * ADD Detailed DOCUMENTATION
30850  *
30851  * @param[out] nk_command_buffer is the buffer with the commands.
30852  * @param[in] nk_symbol_type
30853  * @param[in] nk_rect_content
30854  * @param[in] nk_color_background
30855  * @param[in] nk_color_foreground
30856  * @param[in] border_width
30857  * @param[in] nk_user_font
30858  *
30859  * @returns void
30860  *******************************************************************/
30861 NK_API nk_bool
30862 nk_button_image_text_styled(struct nk_context *ctx,
30863  const struct nk_style_button *style, struct nk_image img, const char *text,
30864  int len, nk_flags align)
30865 {
30866  struct nk_window *win;
30867  struct nk_panel *layout;
30868  const struct nk_input *in;
30869 
30870  struct nk_rect bounds;
30871  enum nk_widget_layout_states state;
30872 
30873  NK_ASSERT(ctx);
30874  NK_ASSERT(ctx->current);
30875  NK_ASSERT(ctx->current->layout);
30876  if (!ctx || !ctx->current || !ctx->current->layout)
30877  return 0;
30878 
30879  win = ctx->current;
30880  layout = win->layout;
30881 
30882  state = nk_widget(&bounds, ctx);
30883  if (!state) return 0;
30884  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
30885  return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
30886  bounds, img, text, len, align, ctx->button_behavior,
30887  style, ctx->style.font, in);
30888 }
30889 /********************************************************************
30890  * @brief ADD DOCUMENTATION
30891  *
30892  * @details
30893  * ADD Detailed DOCUMENTATION
30894  *
30895  * @param[out] nk_command_buffer is the buffer with the commands.
30896  * @param[in] nk_symbol_type
30897  * @param[in] nk_rect_content
30898  * @param[in] nk_color_background
30899  * @param[in] nk_color_foreground
30900  * @param[in] border_width
30901  * @param[in] nk_user_font
30902  *
30903  * @returns void
30904  *******************************************************************/
30905 NK_API nk_bool
30906 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
30907  const char *text, int len, nk_flags align)
30908 {
30909  return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);
30910 }
30911 /********************************************************************
30912  * @brief ADD DOCUMENTATION
30913  *
30914  * @details
30915  * ADD Detailed DOCUMENTATION
30916  *
30917  * @param[out] nk_command_buffer is the buffer with the commands.
30918  * @param[in] nk_symbol_type
30919  * @param[in] nk_rect_content
30920  * @param[in] nk_color_background
30921  * @param[in] nk_color_foreground
30922  * @param[in] border_width
30923  * @param[in] nk_user_font
30924  *
30925  * @returns void
30926  *******************************************************************/
30927 NK_API nk_bool nk_button_image_label(struct nk_context *ctx, struct nk_image img,
30928  const char *label, nk_flags align)
30929 {
30930  return nk_button_image_text(ctx, img, label, nk_strlen(label), align);
30931 }
30932 /********************************************************************
30933  * @brief ADD DOCUMENTATION
30934  *
30935  * @details
30936  * ADD Detailed DOCUMENTATION
30937  *
30938  * @param[out] nk_command_buffer is the buffer with the commands.
30939  * @param[in] nk_symbol_type
30940  * @param[in] nk_rect_content
30941  * @param[in] nk_color_background
30942  * @param[in] nk_color_foreground
30943  * @param[in] border_width
30944  * @param[in] nk_user_font
30945  *
30946  * @returns void
30947  *******************************************************************/
30948 NK_API nk_bool nk_button_image_label_styled(struct nk_context *ctx,
30949  const struct nk_style_button *style, struct nk_image img,
30950  const char *label, nk_flags text_alignment)
30951 {
30952  return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);
30953 }
30954 
30955 
30956 
30957 
30958 
30959 /* ===============================================================
30960  *
30961  * TOGGLE
30962  *
30963  * ===============================================================*/
30975 NK_LIB nk_bool
30976 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
30977  nk_flags *state, nk_bool active)
30978 {
30979  nk_widget_state_reset(state);
30980  if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
30981  *state = NK_WIDGET_STATE_ACTIVE;
30982  active = !active;
30983  }
30984  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
30985  *state |= NK_WIDGET_STATE_ENTERED;
30986  else if (nk_input_is_mouse_prev_hovering_rect(in, select))
30987  *state |= NK_WIDGET_STATE_LEFT;
30988  return active;
30989 }
31000 NK_LIB void
31001 nk_draw_checkbox(struct nk_command_buffer *out,
31002  nk_flags state, const struct nk_style_toggle *style, nk_bool active,
31003  const struct nk_rect *label, const struct nk_rect *selector,
31004  const struct nk_rect *cursors, const char *string, int len,
31005  const struct nk_user_font *font, nk_flags text_alignment)
31006 {
31007  const struct nk_style_item *background;
31008  const struct nk_style_item *cursor;
31009  struct nk_text text;
31010 
31011  /* select correct colors/images */
31012  if (state & NK_WIDGET_STATE_HOVER) {
31013  background = &style->hover;
31014  cursor = &style->cursor_hover;
31015  text.text = style->text_hover;
31016  } else if (state & NK_WIDGET_STATE_ACTIVED) {
31017  background = &style->hover;
31018  cursor = &style->cursor_hover;
31019  text.text = style->text_active;
31020  } else {
31021  background = &style->normal;
31022  cursor = &style->cursor_normal;
31023  text.text = style->text_normal;
31024  }
31025 
31026  text.text = nk_rgb_factor(text.text, style->color_factor);
31027  text.padding.x = 0;
31028  text.padding.y = 0;
31029  text.background = style->text_background;
31030  nk_widget_text(out, *label, string, len, &text, text_alignment, font);
31031 
31032  /* draw background and cursor */
31033  if (background->type == NK_STYLE_ITEM_COLOR) {
31034  nk_fill_rect(out, *selector, 0, nk_rgb_factor(style->border_color, style->color_factor));
31035  nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, nk_rgb_factor(background->data.color, style->color_factor));
31036  } else nk_draw_image(out, *selector, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
31037  if (active) {
31038  if (cursor->type == NK_STYLE_ITEM_IMAGE)
31039  nk_draw_image(out, *cursors, &cursor->data.image, nk_rgb_factor(nk_white, style->color_factor));
31040  else nk_fill_rect(out, *cursors, 0, cursor->data.color);
31041  }
31042 }
31053 NK_LIB void
31054 nk_draw_option(struct nk_command_buffer *out,
31055  nk_flags state, const struct nk_style_toggle *style, nk_bool active,
31056  const struct nk_rect *label, const struct nk_rect *selector,
31057  const struct nk_rect *cursors, const char *string, int len,
31058  const struct nk_user_font *font, nk_flags text_alignment)
31059 {
31060  const struct nk_style_item *background;
31061  const struct nk_style_item *cursor;
31062  struct nk_text text;
31063 
31064  /* select correct colors/images */
31065  if (state & NK_WIDGET_STATE_HOVER) {
31066  background = &style->hover;
31067  cursor = &style->cursor_hover;
31068  text.text = style->text_hover;
31069  } else if (state & NK_WIDGET_STATE_ACTIVED) {
31070  background = &style->hover;
31071  cursor = &style->cursor_hover;
31072  text.text = style->text_active;
31073  } else {
31074  background = &style->normal;
31075  cursor = &style->cursor_normal;
31076  text.text = style->text_normal;
31077  }
31078 
31079  text.text = nk_rgb_factor(text.text, style->color_factor);
31080  text.padding.x = 0;
31081  text.padding.y = 0;
31082  text.background = style->text_background;
31083  nk_widget_text(out, *label, string, len, &text, text_alignment, font);
31084 
31085  /* draw background and cursor */
31086  if (background->type == NK_STYLE_ITEM_COLOR) {
31087  nk_fill_circle(out, *selector, nk_rgb_factor(style->border_color, style->color_factor));
31088  nk_fill_circle(out, nk_shrink_rect(*selector, style->border), nk_rgb_factor(background->data.color, style->color_factor));
31089  } else nk_draw_image(out, *selector, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
31090  if (active) {
31091  if (cursor->type == NK_STYLE_ITEM_IMAGE)
31092  nk_draw_image(out, *cursors, &cursor->data.image, nk_rgb_factor(nk_white, style->color_factor));
31093  else nk_fill_circle(out, *cursors, cursor->data.color);
31094  }
31095 }
31106 NK_LIB nk_bool
31107 nk_do_toggle(nk_flags *state,
31108  struct nk_command_buffer *out, struct nk_rect r,
31109  nk_bool *active, const char *str, int len, enum nk_toggle_type type,
31110  const struct nk_style_toggle *style, const struct nk_input *in,
31111  const struct nk_user_font *font, nk_flags widget_alignment, nk_flags text_alignment)
31112 {
31113  int was_active;
31114  struct nk_rect bounds;
31115  struct nk_rect select;
31116  struct nk_rect cursor;
31117  struct nk_rect label;
31118 
31119  NK_ASSERT(style);
31120  NK_ASSERT(out);
31121  NK_ASSERT(font);
31122  if (!out || !style || !font || !active)
31123  return 0;
31124 
31125  r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
31126  r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
31127 
31128  /* add additional touch padding for touch screen devices */
31129  bounds.x = r.x - style->touch_padding.x;
31130  bounds.y = r.y - style->touch_padding.y;
31131  bounds.w = r.w + 2 * style->touch_padding.x;
31132  bounds.h = r.h + 2 * style->touch_padding.y;
31133 
31134  /* calculate the selector space */
31135  select.w = font->height;
31136  select.h = select.w;
31137 
31138  if (widget_alignment & NK_WIDGET_ALIGN_RIGHT) {
31139  select.x = r.x + r.w - font->height;
31140 
31141  /* label in front of the selector */
31142  label.x = r.x;
31143  label.w = r.w - select.w - style->spacing * 2;
31144  } else if (widget_alignment & NK_WIDGET_ALIGN_CENTERED) {
31145  select.x = r.x + (r.w - select.w) / 2;
31146 
31147  /* label in front of selector */
31148  label.x = r.x;
31149  label.w = (r.w - select.w - style->spacing * 2) / 2;
31150  } else { /* Default: NK_WIDGET_ALIGN_LEFT */
31151  select.x = r.x;
31152 
31153  /* label behind the selector */
31154  label.x = select.x + select.w + style->spacing;
31155  label.w = NK_MAX(r.x + r.w, label.x) - label.x;
31156  }
31157 
31158  if (widget_alignment & NK_WIDGET_ALIGN_TOP) {
31159  select.y = r.y;
31160  } else if (widget_alignment & NK_WIDGET_ALIGN_BOTTOM) {
31161  select.y = r.y + r.h - select.h - 2 * style->padding.y;
31162  } else { /* Default: NK_WIDGET_ALIGN_MIDDLE */
31163  select.y = r.y + r.h/2.0f - select.h/2.0f;
31164  }
31165 
31166  label.y = select.y;
31167  label.h = select.w;
31168 
31169  /* calculate the bounds of the cursor inside the selector */
31170  cursor.x = select.x + style->padding.x + style->border;
31171  cursor.y = select.y + style->padding.y + style->border;
31172  cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
31173  cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
31174 
31175  /* update selector */
31176  was_active = *active;
31177  *active = nk_toggle_behavior(in, bounds, state, *active);
31178 
31179  /* draw selector */
31180  if (style->draw_begin)
31181  style->draw_begin(out, style->userdata);
31182  if (type == NK_TOGGLE_CHECK) {
31183  nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font, text_alignment);
31184  } else {
31185  nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font, text_alignment);
31186  }
31187  if (style->draw_end)
31188  style->draw_end(out, style->userdata);
31189  return (was_active != *active);
31190 }
31191 /*----------------------------------------------------------------
31192  *
31193  * CHECKBOX
31194  *
31195  * --------------------------------------------------------------*/
31209 NK_API nk_bool
31210 nk_check_text(struct nk_context *ctx, const char *text, int len, nk_bool active)
31211 {
31212  struct nk_window *win;
31213  struct nk_panel *layout;
31214  const struct nk_input *in;
31215  const struct nk_style *style;
31216 
31217  struct nk_rect bounds;
31218  enum nk_widget_layout_states state;
31219 
31220  NK_ASSERT(ctx);
31221  NK_ASSERT(ctx->current);
31222  NK_ASSERT(ctx->current->layout);
31223  if (!ctx || !ctx->current || !ctx->current->layout)
31224  return active;
31225 
31226  win = ctx->current;
31227  style = &ctx->style;
31228  layout = win->layout;
31229 
31230  state = nk_widget(&bounds, ctx);
31231  if (!state) return active;
31232  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
31233  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
31234  text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font, NK_WIDGET_LEFT, NK_TEXT_LEFT);
31235  return active;
31236 }
31250 NK_API nk_bool
31251 nk_check_text_align(struct nk_context *ctx, const char *text, int len, nk_bool active, nk_flags widget_alignment, nk_flags text_alignment)
31252 {
31253  struct nk_window *win;
31254  struct nk_panel *layout;
31255  const struct nk_input *in;
31256  const struct nk_style *style;
31257 
31258  struct nk_rect bounds;
31259  enum nk_widget_layout_states state;
31260 
31261  NK_ASSERT(ctx);
31262  NK_ASSERT(ctx->current);
31263  NK_ASSERT(ctx->current->layout);
31264  if (!ctx || !ctx->current || !ctx->current->layout)
31265  return active;
31266 
31267  win = ctx->current;
31268  style = &ctx->style;
31269  layout = win->layout;
31270 
31271  state = nk_widget(&bounds, ctx);
31272  if (!state) return active;
31273  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
31274  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
31275  text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font, widget_alignment, text_alignment);
31276  return active;
31277 }
31290 NK_API unsigned int
31291 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
31292  unsigned int flags, unsigned int value)
31293 {
31294  int old_active;
31295  NK_ASSERT(ctx);
31296  NK_ASSERT(text);
31297  if (!ctx || !text) return flags;
31298  old_active = (int)((flags & value) & value);
31299  if (nk_check_text(ctx, text, len, old_active))
31300  flags |= value;
31301  else flags &= ~value;
31302  return flags;
31303 }
31317 NK_API nk_bool
31318 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, nk_bool *active)
31319 {
31320  int old_val;
31321  NK_ASSERT(ctx);
31322  NK_ASSERT(text);
31323  NK_ASSERT(active);
31324  if (!ctx || !text || !active) return 0;
31325  old_val = *active;
31326  *active = nk_check_text(ctx, text, len, *active);
31327  return old_val != *active;
31328 }
31342 NK_API nk_bool
31343 nk_checkbox_text_align(struct nk_context *ctx, const char *text, int len, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment)
31344 {
31345  int old_val;
31346  NK_ASSERT(ctx);
31347  NK_ASSERT(text);
31348  NK_ASSERT(active);
31349  if (!ctx || !text || !active) return 0;
31350  old_val = *active;
31351  *active = nk_check_text_align(ctx, text, len, *active, widget_alignment, text_alignment);
31352  return old_val != *active;
31353 }
31366 NK_API nk_bool
31367 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
31368  unsigned int *flags, unsigned int value)
31369 {
31370  nk_bool active;
31371  NK_ASSERT(ctx);
31372  NK_ASSERT(text);
31373  NK_ASSERT(flags);
31374  if (!ctx || !text || !flags) return 0;
31375 
31376  active = (int)((*flags & value) & value);
31377  if (nk_checkbox_text(ctx, text, len, &active)) {
31378  if (active) *flags |= value;
31379  else *flags &= ~value;
31380  return 1;
31381  }
31382  return 0;
31395 }
31396 NK_API nk_bool nk_check_label(struct nk_context *ctx, const char *label, nk_bool active)
31397 {
31398  return nk_check_text(ctx, label, nk_strlen(label), active);
31410 }
31411 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
31412  unsigned int flags, unsigned int value)
31413 {
31414  return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);
31427 }
31428 NK_API nk_bool nk_checkbox_label(struct nk_context *ctx, const char *label, nk_bool *active)
31429 {
31430  return nk_checkbox_text(ctx, label, nk_strlen(label), active);
31442 }
31443 NK_API nk_bool nk_checkbox_label_align(struct nk_context *ctx, const char *label, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment)
31444 {
31445  return nk_checkbox_text_align(ctx, label, nk_strlen(label), active, widget_alignment, text_alignment);
31457 }
31458 NK_API nk_bool nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
31459  unsigned int *flags, unsigned int value)
31460 {
31461  return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);
31462 }
31463 /*----------------------------------------------------------------
31464  *
31465  * OPTION
31466  *
31467  * --------------------------------------------------------------*/
31481 NK_API nk_bool
31482 nk_option_text(struct nk_context *ctx, const char *text, int len, nk_bool is_active)
31483 {
31484  struct nk_window *win;
31485  struct nk_panel *layout;
31486  const struct nk_input *in;
31487  const struct nk_style *style;
31488 
31489  struct nk_rect bounds;
31490  enum nk_widget_layout_states state;
31491 
31492  NK_ASSERT(ctx);
31493  NK_ASSERT(ctx->current);
31494  NK_ASSERT(ctx->current->layout);
31495  if (!ctx || !ctx->current || !ctx->current->layout)
31496  return is_active;
31497 
31498  win = ctx->current;
31499  style = &ctx->style;
31500  layout = win->layout;
31501 
31502  state = nk_widget(&bounds, ctx);
31503  if (!state) return (int)state;
31504  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
31505  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
31506  text, len, NK_TOGGLE_OPTION, &style->option, in, style->font, NK_WIDGET_LEFT, NK_TEXT_LEFT);
31507  return is_active;
31508 }
31522 NK_API nk_bool
31523 nk_option_text_align(struct nk_context *ctx, const char *text, int len, nk_bool is_active, nk_flags widget_alignment, nk_flags text_alignment)
31524 {
31525  struct nk_window *win;
31526  struct nk_panel *layout;
31527  const struct nk_input *in;
31528  const struct nk_style *style;
31529 
31530  struct nk_rect bounds;
31531  enum nk_widget_layout_states state;
31532 
31533  NK_ASSERT(ctx);
31534  NK_ASSERT(ctx->current);
31535  NK_ASSERT(ctx->current->layout);
31536  if (!ctx || !ctx->current || !ctx->current->layout)
31537  return is_active;
31538 
31539  win = ctx->current;
31540  style = &ctx->style;
31541  layout = win->layout;
31542 
31543  state = nk_widget(&bounds, ctx);
31544  if (!state) return (int)state;
31545  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
31546  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
31547  text, len, NK_TOGGLE_OPTION, &style->option, in, style->font, widget_alignment, text_alignment);
31548  return is_active;
31549 }
31563 NK_API nk_bool
31564 nk_radio_text(struct nk_context *ctx, const char *text, int len, nk_bool *active)
31565 {
31566  int old_value;
31567  NK_ASSERT(ctx);
31568  NK_ASSERT(text);
31569  NK_ASSERT(active);
31570  if (!ctx || !text || !active) return 0;
31571  old_value = *active;
31572  *active = nk_option_text(ctx, text, len, old_value);
31573  return old_value != *active;
31574 }
31588 NK_API nk_bool
31589 nk_radio_text_align(struct nk_context *ctx, const char *text, int len, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment)
31590 {
31591  int old_value;
31592  NK_ASSERT(ctx);
31593  NK_ASSERT(text);
31594  NK_ASSERT(active);
31595  if (!ctx || !text || !active) return 0;
31596  old_value = *active;
31597  *active = nk_option_text_align(ctx, text, len, old_value, widget_alignment, text_alignment);
31598  return old_value != *active;
31599 }
31612 NK_API nk_bool
31613 nk_option_label(struct nk_context *ctx, const char *label, nk_bool active)
31614 {
31615  return nk_option_text(ctx, label, nk_strlen(label), active);
31616 }
31629 NK_API nk_bool
31630 nk_option_label_align(struct nk_context *ctx, const char *label, nk_bool active, nk_flags widget_alignment, nk_flags text_alignment)
31631 {
31632  return nk_option_text_align(ctx, label, nk_strlen(label), active, widget_alignment, text_alignment);
31633 }
31646 NK_API nk_bool
31647 nk_radio_label(struct nk_context *ctx, const char *label, nk_bool *active)
31648 {
31649  return nk_radio_text(ctx, label, nk_strlen(label), active);
31650 }
31663 NK_API nk_bool
31664 nk_radio_label_align(struct nk_context *ctx, const char *label, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment)
31665 {
31666  return nk_radio_text_align(ctx, label, nk_strlen(label), active, widget_alignment, text_alignment);
31667 }
31668 
31669 
31670 
31671 
31672 
31673 /* ===============================================================
31674  *
31675  * SELECTABLE
31676  *
31677  * ===============================================================*/
31688 NK_LIB void
31689 nk_draw_selectable(struct nk_command_buffer *out,
31690  nk_flags state, const struct nk_style_selectable *style, nk_bool active,
31691  const struct nk_rect *bounds,
31692  const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym,
31693  const char *string, int len, nk_flags align, const struct nk_user_font *font)
31694 {
31695  const struct nk_style_item *background;
31696  struct nk_text text;
31697  text.padding = style->padding;
31698 
31699  /* select correct colors/images */
31700  if (!active) {
31701  if (state & NK_WIDGET_STATE_ACTIVED) {
31702  background = &style->pressed;
31703  text.text = style->text_pressed;
31704  } else if (state & NK_WIDGET_STATE_HOVER) {
31705  background = &style->hover;
31706  text.text = style->text_hover;
31707  } else {
31708  background = &style->normal;
31709  text.text = style->text_normal;
31710  }
31711  } else {
31712  if (state & NK_WIDGET_STATE_ACTIVED) {
31713  background = &style->pressed_active;
31714  text.text = style->text_pressed_active;
31715  } else if (state & NK_WIDGET_STATE_HOVER) {
31716  background = &style->hover_active;
31717  text.text = style->text_hover_active;
31718  } else {
31719  background = &style->normal_active;
31720  text.text = style->text_normal_active;
31721  }
31722  }
31723 
31724  text.text = nk_rgb_factor(text.text, style->color_factor);
31725 
31726  /* draw selectable background and text */
31727  switch (background->type) {
31728  case NK_STYLE_ITEM_IMAGE:
31729  text.background = nk_rgba(0, 0, 0, 0);
31730  nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
31731  break;
31732  case NK_STYLE_ITEM_NINE_SLICE:
31733  text.background = nk_rgba(0, 0, 0, 0);
31734  nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
31735  break;
31736  case NK_STYLE_ITEM_COLOR:
31737  text.background = background->data.color;
31738  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
31739  break;
31740  }
31741  if (icon) {
31742  if (img) nk_draw_image(out, *icon, img, nk_rgb_factor(nk_white, style->color_factor));
31743  else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font);
31744  }
31745  nk_widget_text(out, *bounds, string, len, &text, align, font);
31746 }
31758 NK_LIB nk_bool
31759 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
31760  struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value,
31761  const struct nk_style_selectable *style, const struct nk_input *in,
31762  const struct nk_user_font *font)
31763 {
31764  int old_value;
31765  struct nk_rect touch;
31766 
31767  NK_ASSERT(state);
31768  NK_ASSERT(out);
31769  NK_ASSERT(str);
31770  NK_ASSERT(len);
31771  NK_ASSERT(value);
31772  NK_ASSERT(style);
31773  NK_ASSERT(font);
31774 
31775  if (!state || !out || !str || !len || !value || !style || !font) return 0;
31776  old_value = *value;
31777 
31778  /* remove padding */
31779  touch.x = bounds.x - style->touch_padding.x;
31780  touch.y = bounds.y - style->touch_padding.y;
31781  touch.w = bounds.w + style->touch_padding.x * 2;
31782  touch.h = bounds.h + style->touch_padding.y * 2;
31783 
31784  /* update button */
31785  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
31786  *value = !(*value);
31787 
31788  /* draw selectable */
31789  if (style->draw_begin) style->draw_begin(out, style->userdata);
31790  nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font);
31791  if (style->draw_end) style->draw_end(out, style->userdata);
31792  return old_value != *value;
31793 }
31805 NK_LIB nk_bool
31806 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
31807  struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value,
31808  const struct nk_image *img, const struct nk_style_selectable *style,
31809  const struct nk_input *in, const struct nk_user_font *font)
31810 {
31811  nk_bool old_value;
31812  struct nk_rect touch;
31813  struct nk_rect icon;
31814 
31815  NK_ASSERT(state);
31816  NK_ASSERT(out);
31817  NK_ASSERT(str);
31818  NK_ASSERT(len);
31819  NK_ASSERT(value);
31820  NK_ASSERT(style);
31821  NK_ASSERT(font);
31822 
31823  if (!state || !out || !str || !len || !value || !style || !font) return 0;
31824  old_value = *value;
31825 
31826  /* toggle behavior */
31827  touch.x = bounds.x - style->touch_padding.x;
31828  touch.y = bounds.y - style->touch_padding.y;
31829  touch.w = bounds.w + style->touch_padding.x * 2;
31830  touch.h = bounds.h + style->touch_padding.y * 2;
31831  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
31832  *value = !(*value);
31833 
31834  icon.y = bounds.y + style->padding.y;
31835  icon.w = icon.h = bounds.h - 2 * style->padding.y;
31836  if (align & NK_TEXT_ALIGN_LEFT) {
31837  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
31838  icon.x = NK_MAX(icon.x, 0);
31839  } else icon.x = bounds.x + 2 * style->padding.x;
31840 
31841  icon.x += style->image_padding.x;
31842  icon.y += style->image_padding.y;
31843  icon.w -= 2 * style->image_padding.x;
31844  icon.h -= 2 * style->image_padding.y;
31845 
31846  /* draw selectable */
31847  if (style->draw_begin) style->draw_begin(out, style->userdata);
31848  nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font);
31849  if (style->draw_end) style->draw_end(out, style->userdata);
31850  return old_value != *value;
31851 }
31863 NK_LIB nk_bool
31864 nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out,
31865  struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value,
31866  enum nk_symbol_type sym, const struct nk_style_selectable *style,
31867  const struct nk_input *in, const struct nk_user_font *font)
31868 {
31869  int old_value;
31870  struct nk_rect touch;
31871  struct nk_rect icon;
31872 
31873  NK_ASSERT(state);
31874  NK_ASSERT(out);
31875  NK_ASSERT(str);
31876  NK_ASSERT(len);
31877  NK_ASSERT(value);
31878  NK_ASSERT(style);
31879  NK_ASSERT(font);
31880 
31881  if (!state || !out || !str || !len || !value || !style || !font) return 0;
31882  old_value = *value;
31883 
31884  /* toggle behavior */
31885  touch.x = bounds.x - style->touch_padding.x;
31886  touch.y = bounds.y - style->touch_padding.y;
31887  touch.w = bounds.w + style->touch_padding.x * 2;
31888  touch.h = bounds.h + style->touch_padding.y * 2;
31889  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
31890  *value = !(*value);
31891 
31892  icon.y = bounds.y + style->padding.y;
31893  icon.w = icon.h = bounds.h - 2 * style->padding.y;
31894  if (align & NK_TEXT_ALIGN_LEFT) {
31895  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
31896  icon.x = NK_MAX(icon.x, 0);
31897  } else icon.x = bounds.x + 2 * style->padding.x;
31898 
31899  icon.x += style->image_padding.x;
31900  icon.y += style->image_padding.y;
31901  icon.w -= 2 * style->image_padding.x;
31902  icon.h -= 2 * style->image_padding.y;
31903 
31904  /* draw selectable */
31905  if (style->draw_begin) style->draw_begin(out, style->userdata);
31906  nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font);
31907  if (style->draw_end) style->draw_end(out, style->userdata);
31908  return old_value != *value;
31909 }
31910 
31923 NK_API nk_bool
31924 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
31925  nk_flags align, nk_bool *value)
31926 {
31927  struct nk_window *win;
31928  struct nk_panel *layout;
31929  const struct nk_input *in;
31930  const struct nk_style *style;
31931 
31932  enum nk_widget_layout_states state;
31933  struct nk_rect bounds;
31934 
31935  NK_ASSERT(ctx);
31936  NK_ASSERT(value);
31937  NK_ASSERT(ctx->current);
31938  NK_ASSERT(ctx->current->layout);
31939  if (!ctx || !ctx->current || !ctx->current->layout || !value)
31940  return 0;
31941 
31942  win = ctx->current;
31943  layout = win->layout;
31944  style = &ctx->style;
31945 
31946  state = nk_widget(&bounds, ctx);
31947  if (!state) return 0;
31948  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
31949  return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
31950  str, len, align, value, &style->selectable, in, style->font);
31951 }
31963 NK_API nk_bool
31964 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
31965  const char *str, int len, nk_flags align, nk_bool *value)
31966 {
31967  struct nk_window *win;
31968  struct nk_panel *layout;
31969  const struct nk_input *in;
31970  const struct nk_style *style;
31971 
31972  enum nk_widget_layout_states state;
31973  struct nk_rect bounds;
31974 
31975  NK_ASSERT(ctx);
31976  NK_ASSERT(value);
31977  NK_ASSERT(ctx->current);
31978  NK_ASSERT(ctx->current->layout);
31979  if (!ctx || !ctx->current || !ctx->current->layout || !value)
31980  return 0;
31981 
31982  win = ctx->current;
31983  layout = win->layout;
31984  style = &ctx->style;
31985 
31986  state = nk_widget(&bounds, ctx);
31987  if (!state) return 0;
31988  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
31989  return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
31990  str, len, align, value, &img, &style->selectable, in, style->font);
31991 }
32003 NK_API nk_bool
32004 nk_selectable_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
32005  const char *str, int len, nk_flags align, nk_bool *value)
32006 {
32007  struct nk_window *win;
32008  struct nk_panel *layout;
32009  const struct nk_input *in;
32010  const struct nk_style *style;
32011 
32012  enum nk_widget_layout_states state;
32013  struct nk_rect bounds;
32014 
32015  NK_ASSERT(ctx);
32016  NK_ASSERT(value);
32017  NK_ASSERT(ctx->current);
32018  NK_ASSERT(ctx->current->layout);
32019  if (!ctx || !ctx->current || !ctx->current->layout || !value)
32020  return 0;
32021 
32022  win = ctx->current;
32023  layout = win->layout;
32024  style = &ctx->style;
32025 
32026  state = nk_widget(&bounds, ctx);
32027  if (!state) return 0;
32028  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
32029  return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds,
32030  str, len, align, value, sym, &style->selectable, in, style->font);
32031 }
32043 NK_API nk_bool
32044 nk_selectable_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
32045  const char *title, nk_flags align, nk_bool *value)
32046 {
32047  return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
32060 }
32061 NK_API nk_bool nk_select_text(struct nk_context *ctx, const char *str, int len,
32062  nk_flags align, nk_bool value)
32063 {
32064  nk_selectable_text(ctx, str, len, align, &value);return value;
32077 }
32078 NK_API nk_bool nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, nk_bool *value)
32079 {
32080  return nk_selectable_text(ctx, str, nk_strlen(str), align, value);
32092 }
32093 NK_API nk_bool nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
32094  const char *str, nk_flags align, nk_bool *value)
32095 {
32096  return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);
32109 }
32110 NK_API nk_bool nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, nk_bool value)
32111 {
32112  nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;
32124 }
32125 NK_API nk_bool nk_select_image_label(struct nk_context *ctx, struct nk_image img,
32126  const char *str, nk_flags align, nk_bool value)
32127 {
32128  nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;
32140 }
32141 NK_API nk_bool nk_select_image_text(struct nk_context *ctx, struct nk_image img,
32142  const char *str, int len, nk_flags align, nk_bool value)
32143 {
32144  nk_selectable_image_text(ctx, img, str, len, align, &value);return value;
32145 }
32157 NK_API nk_bool
32158 nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
32159  const char *title, int title_len, nk_flags align, nk_bool value)
32160 {
32161  nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value;
32162 }
32174 NK_API nk_bool
32175 nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
32176  const char *title, nk_flags align, nk_bool value)
32177 {
32178  return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value);
32179 }
32180 
32181 
32182 
32183 
32184 
32185 /* ===============================================================
32186  *
32187  * SLIDER
32188  *
32189  * ===============================================================*/
32201 NK_LIB float
32202 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
32203  struct nk_rect *visual_cursor, struct nk_input *in,
32204  struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
32205  float slider_step, float slider_steps)
32206 {
32207  int left_mouse_down;
32208  int left_mouse_click_in_cursor;
32209 
32210  /* check if visual cursor is being dragged */
32211  nk_widget_state_reset(state);
32212  left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
32213  left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
32214  NK_BUTTON_LEFT, *visual_cursor, nk_true);
32215 
32216  if (left_mouse_down && left_mouse_click_in_cursor) {
32217  float ratio = 0;
32218  const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
32219  const float pxstep = bounds.w / slider_steps;
32220 
32221  /* only update value if the next slider step is reached */
32222  *state = NK_WIDGET_STATE_ACTIVE;
32223  if (NK_ABS(d) >= pxstep) {
32224  const float steps = (float)((int)(NK_ABS(d) / pxstep));
32225  slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
32226  slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
32227  ratio = (slider_value - slider_min)/slider_step;
32228  logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
32229  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
32230  }
32231  }
32232 
32233  /* slider widget state */
32234  if (nk_input_is_mouse_hovering_rect(in, bounds))
32235  *state = NK_WIDGET_STATE_HOVERED;
32236  if (*state & NK_WIDGET_STATE_HOVER &&
32237  !nk_input_is_mouse_prev_hovering_rect(in, bounds))
32238  *state |= NK_WIDGET_STATE_ENTERED;
32239  else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
32240  *state |= NK_WIDGET_STATE_LEFT;
32241  return slider_value;
32242 }
32254 NK_LIB void
32255 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
32256  const struct nk_style_slider *style, const struct nk_rect *bounds,
32257  const struct nk_rect *visual_cursor, float min, float value, float max)
32258 {
32259  struct nk_rect fill;
32260  struct nk_rect bar;
32261  const struct nk_style_item *background;
32262 
32263  /* select correct slider images/colors */
32264  struct nk_color bar_color;
32265  const struct nk_style_item *cursor;
32266 
32267  NK_UNUSED(min);
32268  NK_UNUSED(max);
32269  NK_UNUSED(value);
32270 
32271  if (state & NK_WIDGET_STATE_ACTIVED) {
32272  background = &style->active;
32273  bar_color = style->bar_active;
32274  cursor = &style->cursor_active;
32275  } else if (state & NK_WIDGET_STATE_HOVER) {
32276  background = &style->hover;
32277  bar_color = style->bar_hover;
32278  cursor = &style->cursor_hover;
32279  } else {
32280  background = &style->normal;
32281  bar_color = style->bar_normal;
32282  cursor = &style->cursor_normal;
32283  }
32284 
32285  /* calculate slider background bar */
32286  bar.x = bounds->x;
32287  bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
32288  bar.w = bounds->w;
32289  bar.h = bounds->h/6;
32290 
32291  /* filled background bar style */
32292  fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
32293  fill.x = bar.x;
32294  fill.y = bar.y;
32295  fill.h = bar.h;
32296 
32297  /* draw background */
32298  switch(background->type) {
32299  case NK_STYLE_ITEM_IMAGE:
32300  nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
32301  break;
32302  case NK_STYLE_ITEM_NINE_SLICE:
32303  nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
32304  break;
32305  case NK_STYLE_ITEM_COLOR:
32306  nk_fill_rect(out, *bounds, style->rounding, nk_rgb_factor(background->data.color, style->color_factor));
32307  nk_stroke_rect(out, *bounds, style->rounding, style->border, nk_rgb_factor(style->border_color, style->color_factor));
32308  break;
32309  }
32310 
32311  /* draw slider bar */
32312  nk_fill_rect(out, bar, style->rounding, nk_rgb_factor(bar_color, style->color_factor));
32313  nk_fill_rect(out, fill, style->rounding, nk_rgb_factor(style->bar_filled, style->color_factor));
32314 
32315  /* draw cursor */
32316  if (cursor->type == NK_STYLE_ITEM_IMAGE)
32317  nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_rgb_factor(nk_white, style->color_factor));
32318  else
32319  nk_fill_circle(out, *visual_cursor, nk_rgb_factor(cursor->data.color, style->color_factor));
32320 }
32331 NK_LIB float
32332 nk_do_slider(nk_flags *state,
32333  struct nk_command_buffer *out, struct nk_rect bounds,
32334  float min, float val, float max, float step,
32335  const struct nk_style_slider *style, struct nk_input *in,
32336  const struct nk_user_font *font)
32337 {
32338  float slider_range;
32339  float slider_min;
32340  float slider_max;
32341  float slider_value;
32342  float slider_steps;
32343  float cursor_offset;
32344 
32345  struct nk_rect visual_cursor;
32346  struct nk_rect logical_cursor;
32347 
32348  NK_ASSERT(style);
32349  NK_ASSERT(out);
32350  if (!out || !style)
32351  return 0;
32352 
32353  /* remove padding from slider bounds */
32354  bounds.x = bounds.x + style->padding.x;
32355  bounds.y = bounds.y + style->padding.y;
32356  bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
32357  bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
32358  bounds.w -= 2 * style->padding.x;
32359  bounds.h -= 2 * style->padding.y;
32360 
32361  /* optional buttons */
32362  if (style->show_buttons) {
32363  nk_flags ws;
32364  struct nk_rect button;
32365  button.y = bounds.y;
32366  button.w = bounds.h;
32367  button.h = bounds.h;
32368 
32369  /* decrement button */
32370  button.x = bounds.x;
32371  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
32372  &style->dec_button, in, font))
32373  val -= step;
32374 
32375  /* increment button */
32376  button.x = (bounds.x + bounds.w) - button.w;
32377  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
32378  &style->inc_button, in, font))
32379  val += step;
32380 
32381  bounds.x = bounds.x + button.w + style->spacing.x;
32382  bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
32383  }
32384 
32385  /* remove one cursor size to support visual cursor */
32386  bounds.x += style->cursor_size.x*0.5f;
32387  bounds.w -= style->cursor_size.x;
32388 
32389  /* make sure the provided values are correct */
32390  slider_max = NK_MAX(min, max);
32391  slider_min = NK_MIN(min, max);
32392  slider_value = NK_CLAMP(slider_min, val, slider_max);
32393  slider_range = slider_max - slider_min;
32394  slider_steps = slider_range / step;
32395  cursor_offset = (slider_value - slider_min) / step;
32396 
32397  /* calculate cursor
32398  Basically you have two cursors. One for visual representation and interaction
32399  and one for updating the actual cursor value. */
32400  logical_cursor.h = bounds.h;
32401  logical_cursor.w = bounds.w / slider_steps;
32402  logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
32403  logical_cursor.y = bounds.y;
32404 
32405  visual_cursor.h = style->cursor_size.y;
32406  visual_cursor.w = style->cursor_size.x;
32407  visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
32408  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
32409 
32410  slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
32411  in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
32412  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
32413 
32414  /* draw slider */
32415  if (style->draw_begin) style->draw_begin(out, style->userdata);
32416  nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
32417  if (style->draw_end) style->draw_end(out, style->userdata);
32418  return slider_value;
32419 }
32433 NK_API nk_bool
32434 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
32435  float value_step)
32436 {
32437  struct nk_window *win;
32438  struct nk_panel *layout;
32439  struct nk_input *in;
32440  const struct nk_style *style;
32441 
32442  int ret = 0;
32443  float old_value;
32444  struct nk_rect bounds;
32445  enum nk_widget_layout_states state;
32446 
32447  NK_ASSERT(ctx);
32448  NK_ASSERT(ctx->current);
32449  NK_ASSERT(ctx->current->layout);
32450  NK_ASSERT(value);
32451  if (!ctx || !ctx->current || !ctx->current->layout || !value)
32452  return ret;
32453 
32454  win = ctx->current;
32455  style = &ctx->style;
32456  layout = win->layout;
32457 
32458  state = nk_widget(&bounds, ctx);
32459  if (!state) return ret;
32460  in = (/*state == NK_WIDGET_ROM || */ state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
32461 
32462  old_value = *value;
32463  *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
32464  old_value, max_value, value_step, &style->slider, in, style->font);
32465  return (old_value > *value || old_value < *value);
32466 }
32481 NK_API float
32482 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
32483 {
32484  nk_slider_float(ctx, min, &val, max, step); return val;
32485 }
32500 NK_API int
32501 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
32502 {
32503  float value = (float)val;
32504  nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
32505  return (int)value;
32506 }
32521 NK_API nk_bool
32522 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
32523 {
32524  int ret;
32525  float value = (float)*val;
32526  ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
32527  *val = (int)value;
32528  return ret;
32529 }
32530 
32531 
32532 
32533 
32534 
32535 /* ===============================================================
32536  *
32537  * KNOB
32538  *
32539  * ===============================================================*/
32552 NK_LIB float
32553 nk_knob_behavior(nk_flags *state, struct nk_input *in,
32554  struct nk_rect bounds, float knob_min, float knob_max, float knob_value,
32555  float knob_step, float knob_steps,
32556  enum nk_heading zero_direction, float dead_zone_percent)
32557 {
32558  struct nk_vec2 origin;
32559  float angle = 0.0f;
32560  origin.x = bounds.x + (bounds.w / 2);
32561  origin.y = bounds.y + (bounds.h / 2);
32562 
32563  nk_widget_state_reset(state);
32564 
32565  /* handle click and drag input */
32566  if(in &&
32567  in->mouse.buttons[NK_BUTTON_LEFT].down &&
32568  nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, bounds, nk_true)){
32569  /* calculate angle from origin and rotate */
32570  const float direction_rads[4] = {
32571  NK_PI * 2.5f, /* 90 NK_UP */
32572  NK_PI * 2.0f, /* 0 NK_RIGHT */
32573  NK_PI * 1.5f, /* 270 NK_DOWN */
32574  NK_PI, /* 180 NK_LEFT */
32575  };
32576  *state = NK_WIDGET_STATE_ACTIVE;
32577 
32578  angle = NK_ATAN2(in->mouse.pos.y - origin.y, in->mouse.pos.x - origin.x) + direction_rads[zero_direction];
32579  angle -= (angle > NK_PI * 2) ? NK_PI * 3 : NK_PI;
32580 
32581  /* account for dead space applied when drawing */
32582  angle *= 1.0f / (1.0f - dead_zone_percent);
32583  angle = NK_CLAMP(-NK_PI, angle, NK_PI);
32584 
32585  /* convert -pi -> pi range to 0.0 -> 1.0 */
32586  angle = (angle + NK_PI) / (NK_PI * 2);
32587 
32588  /* click to closest step */
32589  knob_value = knob_min + ( (int)(angle * knob_steps + (knob_step / 2)) ) * knob_step;
32590  knob_value = NK_CLAMP(knob_min, knob_value, knob_max);
32591  }
32592 
32593  /* knob widget state */
32594  if (nk_input_is_mouse_hovering_rect(in, bounds)){
32595  *state = NK_WIDGET_STATE_HOVERED;
32596  if (in) {
32597  /* handle scroll and arrow inputs */
32598  if (in->mouse.scroll_delta.y > 0 ||
32599  (in->keyboard.keys[NK_KEY_UP].down && in->keyboard.keys[NK_KEY_UP].clicked))
32600  knob_value += knob_step;
32601 
32602  if (in->mouse.scroll_delta.y < 0 ||
32603  (in->keyboard.keys[NK_KEY_DOWN].down && in->keyboard.keys[NK_KEY_DOWN].clicked))
32604  knob_value -= knob_step;
32605  }
32606  knob_value = NK_CLAMP(knob_min, knob_value, knob_max);
32607  }
32608  if (*state & NK_WIDGET_STATE_HOVER &&
32609  !nk_input_is_mouse_prev_hovering_rect(in, bounds))
32610  *state |= NK_WIDGET_STATE_ENTERED;
32611  else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
32612  *state |= NK_WIDGET_STATE_LEFT;
32613 
32614  return knob_value;
32626 }
32627 NK_LIB void
32628 nk_draw_knob(struct nk_command_buffer *out, nk_flags state,
32629  const struct nk_style_knob *style, const struct nk_rect *bounds, float min, float value, float max,
32630  enum nk_heading zero_direction, float dead_zone_percent)
32631 {
32632  const struct nk_style_item *background;
32633  struct nk_color knob_color, cursor;
32634 
32635  NK_UNUSED(min);
32636  NK_UNUSED(max);
32637  NK_UNUSED(value);
32638 
32639  if (state & NK_WIDGET_STATE_ACTIVED) {
32640  background = &style->active;
32641  knob_color = style->knob_active;
32642  cursor = style->cursor_active;
32643  } else if (state & NK_WIDGET_STATE_HOVER) {
32644  background = &style->hover;
32645  knob_color = style->knob_hover;
32646  cursor = style->cursor_hover;
32647  } else {
32648  background = &style->normal;
32649  knob_color = style->knob_normal;
32650  cursor = style->cursor_normal;
32651  }
32652 
32653  /* draw background */
32654  switch(background->type) {
32655  case NK_STYLE_ITEM_IMAGE:
32656  nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
32657  break;
32658  case NK_STYLE_ITEM_NINE_SLICE:
32659  nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
32660  break;
32661  case NK_STYLE_ITEM_COLOR:
32662  nk_fill_rect(out, *bounds, 0, nk_rgb_factor(background->data.color, style->color_factor));
32663  nk_stroke_rect(out, *bounds, 0, style->border, nk_rgb_factor(style->border_color, style->color_factor));
32664  break;
32665  }
32666 
32667  /* draw knob */
32668  nk_fill_circle(out, *bounds, nk_rgb_factor(knob_color, style->color_factor));
32669  if(style->knob_border > 0){
32670  struct nk_rect border_bounds = *bounds;
32671  border_bounds.x += style->knob_border / 2;
32672  border_bounds.y += style->knob_border / 2;
32673  border_bounds.w -= style->knob_border;
32674  border_bounds.h -= style->knob_border;
32675  nk_stroke_circle(out, border_bounds, style->knob_border, nk_rgb_factor(style->knob_border_color, style->color_factor));
32676  }
32677  { /* calculate cursor line cords */
32678  float half_circle_size = (bounds->w / 2);
32679  float angle = (value - min) / (max - min);
32680  float alive_zone = 1.0f - dead_zone_percent;
32681  struct nk_vec2 cursor_start, cursor_end;
32682  const float direction_rads[4] = {
32683  NK_PI * 1.5f, /* 90 NK_UP */
32684  0.0f, /* 0 NK_RIGHT */
32685  NK_PI * 0.5f, /* 270 NK_DOWN */
32686  NK_PI, /* 180 NK_LEFT */
32687  };
32688  /* calculate + apply dead zone */
32689  angle = (angle * alive_zone) + (dead_zone_percent / 2);
32690 
32691  /* percentage 0.0 -> 1.0 to radians, rads are 0.0 to (2*pi) NOT -pi to pi */
32692  angle *= NK_PI * 2;
32693 
32694  /* apply zero angle */
32695  angle += direction_rads[zero_direction];
32696  if(angle > NK_PI * 2)
32697  angle -= NK_PI * 2;
32698 
32699  cursor_start.x = bounds->x + half_circle_size + (angle > NK_PI);
32700  cursor_start.y = bounds->y + half_circle_size + (angle < NK_PI_HALF || angle > (NK_PI * 1.5f));
32701 
32702  cursor_end.x = cursor_start.x + (half_circle_size * NK_COS(angle));
32703  cursor_end.y = cursor_start.y + (half_circle_size * NK_SIN(angle));
32704 
32705  /* cut off half of the cursor */
32706  cursor_start.x = (cursor_start.x + cursor_end.x) / 2;
32707  cursor_start.y = (cursor_start.y + cursor_end.y) / 2;
32708 
32709  /* draw cursor */
32710  nk_stroke_line(out, cursor_start.x, cursor_start.y, cursor_end.x, cursor_end.y, 2, nk_rgb_factor(cursor, style->color_factor));
32711  }
32722 }
32723 NK_LIB float
32724 nk_do_knob(nk_flags *state,
32725  struct nk_command_buffer *out, struct nk_rect bounds,
32726  float min, float val, float max, float step,
32727  enum nk_heading zero_direction, float dead_zone_percent,
32728  const struct nk_style_knob *style, struct nk_input *in)
32729 {
32730  float knob_range;
32731  float knob_min;
32732  float knob_max;
32733  float knob_value;
32734  float knob_steps;
32735 
32736  NK_ASSERT(style);
32737  NK_ASSERT(out);
32738  if (!out || !style)
32739  return 0;
32740 
32741  /* remove padding from knob bounds */
32742  bounds.y = bounds.y + style->padding.y;
32743  bounds.x = bounds.x + style->padding.x;
32744  bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
32745  bounds.w = NK_MAX(bounds.w, 2*style->padding.x);
32746  bounds.w -= 2 * style->padding.x;
32747  bounds.h -= 2 * style->padding.y;
32748  if(bounds.h < bounds.w){
32749  bounds.x += (bounds.w - bounds.h) / 2;
32750  bounds.w = bounds.h;
32751  }
32752 
32753  /* make sure the provided values are correct */
32754  knob_max = NK_MAX(min, max);
32755  knob_min = NK_MIN(min, max);
32756  knob_value = NK_CLAMP(knob_min, val, knob_max);
32757  knob_range = knob_max - knob_min;
32758  knob_steps = knob_range / step;
32759 
32760  knob_value = nk_knob_behavior(state, in, bounds, knob_min, knob_max, knob_value, step, knob_steps, zero_direction, dead_zone_percent);
32761 
32762  /* draw knob */
32763  if (style->draw_begin) style->draw_begin(out, style->userdata);
32764  nk_draw_knob(out, *state, style, &bounds, knob_min, knob_value, knob_max, zero_direction, dead_zone_percent);
32765  if (style->draw_end) style->draw_end(out, style->userdata);
32766  return knob_value;
32780 }
32781 NK_API nk_bool
32782 nk_knob_float(struct nk_context *ctx, float min_value, float *value, float max_value,
32783  float value_step, enum nk_heading zero_direction, float dead_zone_degrees)
32784 {
32785  struct nk_window *win;
32786  struct nk_panel *layout;
32787  struct nk_input *in;
32788  const struct nk_style *style;
32789 
32790  int ret = 0;
32791  float old_value;
32792  struct nk_rect bounds;
32793  enum nk_widget_layout_states state;
32794 
32795  NK_ASSERT(ctx);
32796  NK_ASSERT(ctx->current);
32797  NK_ASSERT(ctx->current->layout);
32798  NK_ASSERT(value);
32799  NK_ASSERT(NK_BETWEEN(dead_zone_degrees, 0.0f, 360.0f));
32800  if (!ctx || !ctx->current || !ctx->current->layout || !value)
32801  return ret;
32802 
32803  win = ctx->current;
32804  style = &ctx->style;
32805  layout = win->layout;
32806 
32807  state = nk_widget(&bounds, ctx);
32808  if (!state) return ret;
32809  in = (state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
32810 
32811  old_value = *value;
32812  *value = nk_do_knob(&ctx->last_widget_state, &win->buffer, bounds, min_value,
32813  old_value, max_value, value_step, zero_direction, dead_zone_degrees / 360.0f, &style->knob, in);
32814 
32815  return (old_value > *value || old_value < *value);
32830 }
32831 NK_API nk_bool
32832 nk_knob_int(struct nk_context *ctx, int min, int *val, int max, int step,
32833  enum nk_heading zero_direction, float dead_zone_degrees)
32834 {
32835  int ret;
32836  float value = (float)*val;
32837  ret = nk_knob_float(ctx, (float)min, &value, (float)max, (float)step, zero_direction, dead_zone_degrees);
32838  *val = (int)value;
32839  return ret;
32840 }
32841 
32842 
32843 
32844 
32845 /* ===============================================================
32846  *
32847  * PROGRESS
32848  *
32849  * ===============================================================*/
32861 NK_LIB nk_size
32862 nk_progress_behavior(nk_flags *state, struct nk_input *in,
32863  struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, nk_bool modifiable)
32864 {
32865  int left_mouse_down = 0;
32866  int left_mouse_click_in_cursor = 0;
32867 
32868  nk_widget_state_reset(state);
32869  if (!in || !modifiable) return value;
32870  left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
32871  left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
32872  NK_BUTTON_LEFT, cursor, nk_true);
32873  if (nk_input_is_mouse_hovering_rect(in, r))
32874  *state = NK_WIDGET_STATE_HOVERED;
32875 
32876  if (in && left_mouse_down && left_mouse_click_in_cursor) {
32877  if (left_mouse_down && left_mouse_click_in_cursor) {
32878  float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w;
32879  value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max);
32880  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f;
32881  *state |= NK_WIDGET_STATE_ACTIVE;
32882  }
32883  }
32884  /* set progressbar widget state */
32885  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
32886  *state |= NK_WIDGET_STATE_ENTERED;
32887  else if (nk_input_is_mouse_prev_hovering_rect(in, r))
32888  *state |= NK_WIDGET_STATE_LEFT;
32889  return value;
32890 }
32902 NK_LIB void
32903 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
32904  const struct nk_style_progress *style, const struct nk_rect *bounds,
32905  const struct nk_rect *scursor, nk_size value, nk_size max)
32906 {
32907  const struct nk_style_item *background;
32908  const struct nk_style_item *cursor;
32909 
32910  NK_UNUSED(max);
32911  NK_UNUSED(value);
32912 
32913  /* select correct colors/images to draw */
32914  if (state & NK_WIDGET_STATE_ACTIVED) {
32915  background = &style->active;
32916  cursor = &style->cursor_active;
32917  } else if (state & NK_WIDGET_STATE_HOVER){
32918  background = &style->hover;
32919  cursor = &style->cursor_hover;
32920  } else {
32921  background = &style->normal;
32922  cursor = &style->cursor_normal;
32923  }
32924 
32925  /* draw background */
32926  switch(background->type) {
32927  case NK_STYLE_ITEM_IMAGE:
32928  nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
32929  break;
32930  case NK_STYLE_ITEM_NINE_SLICE:
32931  nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
32932  break;
32933  case NK_STYLE_ITEM_COLOR:
32934  nk_fill_rect(out, *bounds, style->rounding, nk_rgb_factor(background->data.color, style->color_factor));
32935  nk_stroke_rect(out, *bounds, style->rounding, style->border, nk_rgb_factor(style->border_color, style->color_factor));
32936  break;
32937  }
32938 
32939  /* draw cursor */
32940  switch(cursor->type) {
32941  case NK_STYLE_ITEM_IMAGE:
32942  nk_draw_image(out, *scursor, &cursor->data.image, nk_rgb_factor(nk_white, style->color_factor));
32943  break;
32944  case NK_STYLE_ITEM_NINE_SLICE:
32945  nk_draw_nine_slice(out, *scursor, &cursor->data.slice, nk_rgb_factor(nk_white, style->color_factor));
32946  break;
32947  case NK_STYLE_ITEM_COLOR:
32948  nk_fill_rect(out, *scursor, style->rounding, nk_rgb_factor(cursor->data.color, style->color_factor));
32949  nk_stroke_rect(out, *scursor, style->rounding, style->border, nk_rgb_factor(style->border_color, style->color_factor));
32950  break;
32951  }
32952 }
32963 NK_LIB nk_size
32964 nk_do_progress(nk_flags *state,
32965  struct nk_command_buffer *out, struct nk_rect bounds,
32966  nk_size value, nk_size max, nk_bool modifiable,
32967  const struct nk_style_progress *style, struct nk_input *in)
32968 {
32969  float prog_scale;
32970  nk_size prog_value;
32971  struct nk_rect cursor;
32972 
32973  NK_ASSERT(style);
32974  NK_ASSERT(out);
32975  if (!out || !style) return 0;
32976 
32977  /* calculate progressbar cursor */
32978  cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
32979  cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
32980  cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
32981  prog_scale = (float)value / (float)max;
32982 
32983  /* update progressbar */
32984  prog_value = NK_MIN(value, max);
32985  prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable);
32986  cursor.w = cursor.w * prog_scale;
32987 
32988  /* draw progressbar */
32989  if (style->draw_begin) style->draw_begin(out, style->userdata);
32990  nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
32991  if (style->draw_end) style->draw_end(out, style->userdata);
32992  return prog_value;
32993 }
33007 NK_API nk_bool
33008 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, nk_bool is_modifyable)
33009 {
33010  struct nk_window *win;
33011  struct nk_panel *layout;
33012  const struct nk_style *style;
33013  struct nk_input *in;
33014 
33015  struct nk_rect bounds;
33016  enum nk_widget_layout_states state;
33017  nk_size old_value;
33018 
33019  NK_ASSERT(ctx);
33020  NK_ASSERT(cur);
33021  NK_ASSERT(ctx->current);
33022  NK_ASSERT(ctx->current->layout);
33023  if (!ctx || !ctx->current || !ctx->current->layout || !cur)
33024  return 0;
33025 
33026  win = ctx->current;
33027  style = &ctx->style;
33028  layout = win->layout;
33029  state = nk_widget(&bounds, ctx);
33030  if (!state) return 0;
33031 
33032  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
33033  old_value = *cur;
33034  *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
33035  *cur, max, is_modifyable, &style->progress, in);
33036  return (*cur != old_value);
33037 }
33051 NK_API nk_size
33052 nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, nk_bool modifyable)
33053 {
33054  nk_progress(ctx, &cur, max, modifyable);
33055  return cur;
33056 }
33057 
33058 
33059 
33060 
33061 
33062 /* ===============================================================
33063  *
33064  * SCROLLBAR
33065  *
33066  * ===============================================================*/
33078 NK_LIB float
33079 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
33080  int has_scrolling, const struct nk_rect *scroll,
33081  const struct nk_rect *cursor, const struct nk_rect *empty0,
33082  const struct nk_rect *empty1, float scroll_offset,
33083  float target, float scroll_step, enum nk_orientation o)
33084 {
33085  nk_flags ws = 0;
33086  int left_mouse_down;
33087  unsigned int left_mouse_clicked;
33088  int left_mouse_click_in_cursor;
33089  float scroll_delta;
33090 
33091  nk_widget_state_reset(state);
33092  if (!in) return scroll_offset;
33093 
33094  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
33095  left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked;
33096  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
33097  NK_BUTTON_LEFT, *cursor, nk_true);
33098  if (nk_input_is_mouse_hovering_rect(in, *scroll))
33099  *state = NK_WIDGET_STATE_HOVERED;
33100 
33101  scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
33102  if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
33103  /* update cursor by mouse dragging */
33104  float pixel, delta;
33105  *state = NK_WIDGET_STATE_ACTIVE;
33106  if (o == NK_VERTICAL) {
33107  float cursor_y;
33108  pixel = in->mouse.delta.y;
33109  delta = (pixel / scroll->h) * target;
33110  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
33111  cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
33112  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
33113  } else {
33114  float cursor_x;
33115  pixel = in->mouse.delta.x;
33116  delta = (pixel / scroll->w) * target;
33117  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
33118  cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
33119  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
33120  }
33121  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
33122  nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
33123  /* scroll page up by click on empty space or shortcut */
33124  if (o == NK_VERTICAL)
33125  scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
33126  else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
33127  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
33128  nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
33129  /* scroll page down by click on empty space or shortcut */
33130  if (o == NK_VERTICAL)
33131  scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
33132  else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
33133  } else if (has_scrolling) {
33134  if ((scroll_delta < 0 || (scroll_delta > 0))) {
33135  /* update cursor by mouse scrolling */
33136  scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
33137  if (o == NK_VERTICAL)
33138  scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
33139  else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
33140  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
33141  /* update cursor to the beginning */
33142  if (o == NK_VERTICAL) scroll_offset = 0;
33143  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
33144  /* update cursor to the end */
33145  if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
33146  }
33147  }
33148  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
33149  *state |= NK_WIDGET_STATE_ENTERED;
33150  else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
33151  *state |= NK_WIDGET_STATE_LEFT;
33152  return scroll_offset;
33153 }
33165 NK_LIB void
33166 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
33167  const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
33168  const struct nk_rect *scroll)
33169 {
33170  const struct nk_style_item *background;
33171  const struct nk_style_item *cursor;
33172 
33173  /* select correct colors/images to draw */
33174  if (state & NK_WIDGET_STATE_ACTIVED) {
33175  background = &style->active;
33176  cursor = &style->cursor_active;
33177  } else if (state & NK_WIDGET_STATE_HOVER) {
33178  background = &style->hover;
33179  cursor = &style->cursor_hover;
33180  } else {
33181  background = &style->normal;
33182  cursor = &style->cursor_normal;
33183  }
33184 
33185  /* draw background */
33186  switch (background->type) {
33187  case NK_STYLE_ITEM_IMAGE:
33188  nk_draw_image(out, *bounds, &background->data.image, nk_white);
33189  break;
33190  case NK_STYLE_ITEM_NINE_SLICE:
33191  nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white);
33192  break;
33193  case NK_STYLE_ITEM_COLOR:
33194  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
33195  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
33196  break;
33197  }
33198 
33199  /* draw cursor */
33200  switch (cursor->type) {
33201  case NK_STYLE_ITEM_IMAGE:
33202  nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
33203  break;
33204  case NK_STYLE_ITEM_NINE_SLICE:
33205  nk_draw_nine_slice(out, *scroll, &cursor->data.slice, nk_white);
33206  break;
33207  case NK_STYLE_ITEM_COLOR:
33208  nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
33209  nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
33210  break;
33211  }
33212 }
33223 NK_LIB float
33224 nk_do_scrollbarv(nk_flags *state,
33225  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
33226  float offset, float target, float step, float button_pixel_inc,
33227  const struct nk_style_scrollbar *style, struct nk_input *in,
33228  const struct nk_user_font *font)
33229 {
33230  struct nk_rect empty_north;
33231  struct nk_rect empty_south;
33232  struct nk_rect cursor;
33233 
33234  float scroll_step;
33235  float scroll_offset;
33236  float scroll_off;
33237  float scroll_ratio;
33238 
33239  NK_ASSERT(out);
33240  NK_ASSERT(style);
33241  NK_ASSERT(state);
33242  if (!out || !style) return 0;
33243 
33244  scroll.w = NK_MAX(scroll.w, 1);
33245  scroll.h = NK_MAX(scroll.h, 0);
33246  if (target <= scroll.h) return 0;
33247 
33248  /* optional scrollbar buttons */
33249  if (style->show_buttons) {
33250  nk_flags ws;
33251  float scroll_h;
33252  struct nk_rect button;
33253 
33254  button.x = scroll.x;
33255  button.w = scroll.w;
33256  button.h = scroll.w;
33257 
33258  scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
33259  scroll_step = NK_MIN(step, button_pixel_inc);
33260 
33261  /* decrement button */
33262  button.y = scroll.y;
33263  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
33264  NK_BUTTON_REPEATER, &style->dec_button, in, font))
33265  offset = offset - scroll_step;
33266 
33267  /* increment button */
33268  button.y = scroll.y + scroll.h - button.h;
33269  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
33270  NK_BUTTON_REPEATER, &style->inc_button, in, font))
33271  offset = offset + scroll_step;
33272 
33273  scroll.y = scroll.y + button.h;
33274  scroll.h = scroll_h;
33275  }
33276 
33277  /* calculate scrollbar constants */
33278  scroll_step = NK_MIN(step, scroll.h);
33279  scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
33280  scroll_ratio = scroll.h / target;
33281  scroll_off = scroll_offset / target;
33282 
33283  /* calculate scrollbar cursor bounds */
33284  cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
33285  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
33286  cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
33287  cursor.x = scroll.x + style->border + style->padding.x;
33288 
33289  /* calculate empty space around cursor */
33290  empty_north.x = scroll.x;
33291  empty_north.y = scroll.y;
33292  empty_north.w = scroll.w;
33293  empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
33294 
33295  empty_south.x = scroll.x;
33296  empty_south.y = cursor.y + cursor.h;
33297  empty_south.w = scroll.w;
33298  empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
33299 
33300  /* update scrollbar */
33301  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
33302  &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
33303  scroll_off = scroll_offset / target;
33304  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
33305 
33306  /* draw scrollbar */
33307  if (style->draw_begin) style->draw_begin(out, style->userdata);
33308  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
33309  if (style->draw_end) style->draw_end(out, style->userdata);
33310  return scroll_offset;
33311 }
33322 NK_LIB float
33323 nk_do_scrollbarh(nk_flags *state,
33324  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
33325  float offset, float target, float step, float button_pixel_inc,
33326  const struct nk_style_scrollbar *style, struct nk_input *in,
33327  const struct nk_user_font *font)
33328 {
33329  struct nk_rect cursor;
33330  struct nk_rect empty_west;
33331  struct nk_rect empty_east;
33332 
33333  float scroll_step;
33334  float scroll_offset;
33335  float scroll_off;
33336  float scroll_ratio;
33337 
33338  NK_ASSERT(out);
33339  NK_ASSERT(style);
33340  if (!out || !style) return 0;
33341 
33342  /* scrollbar background */
33343  scroll.h = NK_MAX(scroll.h, 1);
33344  scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
33345  if (target <= scroll.w) return 0;
33346 
33347  /* optional scrollbar buttons */
33348  if (style->show_buttons) {
33349  nk_flags ws;
33350  float scroll_w;
33351  struct nk_rect button;
33352  button.y = scroll.y;
33353  button.w = scroll.h;
33354  button.h = scroll.h;
33355 
33356  scroll_w = scroll.w - 2 * button.w;
33357  scroll_step = NK_MIN(step, button_pixel_inc);
33358 
33359  /* decrement button */
33360  button.x = scroll.x;
33361  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
33362  NK_BUTTON_REPEATER, &style->dec_button, in, font))
33363  offset = offset - scroll_step;
33364 
33365  /* increment button */
33366  button.x = scroll.x + scroll.w - button.w;
33367  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
33368  NK_BUTTON_REPEATER, &style->inc_button, in, font))
33369  offset = offset + scroll_step;
33370 
33371  scroll.x = scroll.x + button.w;
33372  scroll.w = scroll_w;
33373  }
33374 
33375  /* calculate scrollbar constants */
33376  scroll_step = NK_MIN(step, scroll.w);
33377  scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
33378  scroll_ratio = scroll.w / target;
33379  scroll_off = scroll_offset / target;
33380 
33381  /* calculate cursor bounds */
33382  cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
33383  cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
33384  cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
33385  cursor.y = scroll.y + style->border + style->padding.y;
33386 
33387  /* calculate empty space around cursor */
33388  empty_west.x = scroll.x;
33389  empty_west.y = scroll.y;
33390  empty_west.w = cursor.x - scroll.x;
33391  empty_west.h = scroll.h;
33392 
33393  empty_east.x = cursor.x + cursor.w;
33394  empty_east.y = scroll.y;
33395  empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
33396  empty_east.h = scroll.h;
33397 
33398  /* update scrollbar */
33399  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
33400  &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
33401  scroll_off = scroll_offset / target;
33402  cursor.x = scroll.x + (scroll_off * scroll.w);
33403 
33404  /* draw scrollbar */
33405  if (style->draw_begin) style->draw_begin(out, style->userdata);
33406  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
33407  if (style->draw_end) style->draw_end(out, style->userdata);
33408  return scroll_offset;
33409 }
33410 
33411 
33412 
33413 
33414 
33415 /* ===============================================================
33416  *
33417  * TEXT EDITOR
33418  *
33419  * ===============================================================*/
33420 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */
33421 struct nk_text_find {
33422  float x,y; /* position of n'th character */
33423  float height; /* height of line */
33424  int first_char, length; /* first char of row, and length */
33425  int prev_first; /*_ first char of previous row */
33426 };
33427 
33428 struct nk_text_edit_row {
33429  float x0,x1;
33430  /* starting x location, end x location (allows for align=right, etc) */
33431  float baseline_y_delta;
33432  /* position of baseline relative to previous row's baseline*/
33433  float ymin,ymax;
33434  /* height of row above and below baseline */
33435  int num_chars;
33436 };
33437 
33438 /* forward declarations */
33439 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
33440 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
33441 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
33442 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
33443 
33456 NK_INTERN float
33457 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
33458  const struct nk_user_font *font)
33459 {
33460  int len = 0;
33461  nk_rune unicode = 0;
33462  const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
33463  return font->width(font->userdata, font->height, str, len);
33464 }
33476 NK_INTERN void
33477 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
33478  int line_start_id, float row_height, const struct nk_user_font *font)
33479 {
33480  int l;
33481  int glyphs = 0;
33482  nk_rune unicode;
33483  const char *remaining;
33484  int len = nk_str_len_char(&edit->string);
33485  const char *end = nk_str_get_const(&edit->string) + len;
33486  const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
33487  const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
33488  text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
33489 
33490  r->x0 = 0.0f;
33491  r->x1 = size.x;
33492  r->baseline_y_delta = size.y;
33493  r->ymin = 0.0f;
33494  r->ymax = size.y;
33495  r->num_chars = glyphs;
33496 }
33509 NK_INTERN int
33510 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
33511  const struct nk_user_font *font, float row_height)
33512 {
33513  struct nk_text_edit_row r;
33514  int n = edit->string.len;
33515  float base_y = 0, prev_x;
33516  int i=0, k;
33517 
33518  r.x0 = r.x1 = 0;
33519  r.ymin = r.ymax = 0;
33520  r.num_chars = 0;
33521 
33522  /* search rows to find one that straddles 'y' */
33523  while (i < n) {
33524  nk_textedit_layout_row(&r, edit, i, row_height, font);
33525  if (r.num_chars <= 0)
33526  return n;
33527 
33528  if (i==0 && y < base_y + r.ymin)
33529  return 0;
33530 
33531  if (y < base_y + r.ymax)
33532  break;
33533 
33534  i += r.num_chars;
33535  base_y += r.baseline_y_delta;
33536  }
33537 
33538  /* below all text, return 'after' last character */
33539  if (i >= n)
33540  return n;
33541 
33542  /* check if it's before the beginning of the line */
33543  if (x < r.x0)
33544  return i;
33545 
33546  /* check if it's before the end of the line */
33547  if (x < r.x1) {
33548  /* search characters in row for one that straddles 'x' */
33549  k = i;
33550  prev_x = r.x0;
33551  for (i=0; i < r.num_chars; ++i) {
33552  float w = nk_textedit_get_width(edit, k, i, font);
33553  if (x < prev_x+w) {
33554  if (x < prev_x+w/2)
33555  return k+i;
33556  else return k+i+1;
33557  }
33558  prev_x += w;
33559  }
33560  /* shouldn't happen, but if it does, fall through to end-of-line case */
33561  }
33562 
33563  /* if the last character is a newline, return that.
33564  * otherwise return 'after' the last character */
33565  if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
33566  return i+r.num_chars-1;
33567  else return i+r.num_chars;
33568 }
33581 NK_LIB void
33582 nk_textedit_click(struct nk_text_edit *state, float x, float y,
33583  const struct nk_user_font *font, float row_height)
33584 {
33585  /* API click: on mouse down, move the cursor to the clicked location,
33586  * and reset the selection */
33587  state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
33588  state->select_start = state->cursor;
33589  state->select_end = state->cursor;
33590  state->has_preferred_x = 0;
33591 }
33604 NK_LIB void
33605 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
33606  const struct nk_user_font *font, float row_height)
33607 {
33608  /* API drag: on mouse drag, move the cursor and selection endpoint
33609  * to the clicked location */
33610  int p = nk_textedit_locate_coord(state, x, y, font, row_height);
33611  if (state->select_start == state->select_end)
33612  state->select_start = state->cursor;
33613  state->cursor = state->select_end = p;
33614 }
33626 NK_INTERN void
33627 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
33628  int n, int single_line, const struct nk_user_font *font, float row_height)
33629 {
33630  /* find the x/y location of a character, and remember info about the previous
33631  * row in case we get a move-up event (for page up, we'll have to rescan) */
33632  struct nk_text_edit_row r;
33633  int prev_start = 0;
33634  int z = state->string.len;
33635  int i=0, first;
33636 
33637  nk_zero_struct(r);
33638  if (n == z) {
33639  /* if it's at the end, then find the last line -- simpler than trying to
33640  explicitly handle this case in the regular code */
33641  nk_textedit_layout_row(&r, state, 0, row_height, font);
33642  if (single_line) {
33643  find->first_char = 0;
33644  find->length = z;
33645  } else {
33646  while (i < z) {
33647  prev_start = i;
33648  i += r.num_chars;
33649  nk_textedit_layout_row(&r, state, i, row_height, font);
33650  }
33651 
33652  find->first_char = i;
33653  find->length = r.num_chars;
33654  }
33655  find->x = r.x1;
33656  find->y = r.ymin;
33657  find->height = r.ymax - r.ymin;
33658  find->prev_first = prev_start;
33659  return;
33660  }
33661 
33662  /* search rows to find the one that straddles character n */
33663  find->y = 0;
33664 
33665  for(;;) {
33666  nk_textedit_layout_row(&r, state, i, row_height, font);
33667  if (n < i + r.num_chars) break;
33668  prev_start = i;
33669  i += r.num_chars;
33670  find->y += r.baseline_y_delta;
33671  }
33672 
33673  find->first_char = first = i;
33674  find->length = r.num_chars;
33675  find->height = r.ymax - r.ymin;
33676  find->prev_first = prev_start;
33677 
33678  /* now scan to find xpos */
33679  find->x = r.x0;
33680  for (i=0; first+i < n; ++i)
33681  find->x += nk_textedit_get_width(state, first, i, font);
33682 }
33693 NK_INTERN void
33694 nk_textedit_clamp(struct nk_text_edit *state)
33695 {
33696  /* make the selection/cursor state valid if client altered the string */
33697  int n = state->string.len;
33698  if (NK_TEXT_HAS_SELECTION(state)) {
33699  if (state->select_start > n) state->select_start = n;
33700  if (state->select_end > n) state->select_end = n;
33701  /* if clamping forced them to be equal, move the cursor to match */
33702  if (state->select_start == state->select_end)
33703  state->cursor = state->select_start;
33704  }
33705  if (state->cursor > n) state->cursor = n;
33706 }
33719 NK_API void
33720 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
33721 {
33722  /* delete characters while updating undo */
33723  nk_textedit_makeundo_delete(state, where, len);
33724  nk_str_delete_runes(&state->string, where, len);
33725  state->has_preferred_x = 0;
33726 }
33737 NK_API void
33738 nk_textedit_delete_selection(struct nk_text_edit *state)
33739 {
33740  /* delete the section */
33741  nk_textedit_clamp(state);
33742  if (NK_TEXT_HAS_SELECTION(state)) {
33743  if (state->select_start < state->select_end) {
33744  nk_textedit_delete(state, state->select_start,
33745  state->select_end - state->select_start);
33746  state->select_end = state->cursor = state->select_start;
33747  } else {
33748  nk_textedit_delete(state, state->select_end,
33749  state->select_start - state->select_end);
33750  state->select_start = state->cursor = state->select_end;
33751  }
33752  state->has_preferred_x = 0;
33753  }
33754 }
33765 NK_INTERN void
33766 nk_textedit_sortselection(struct nk_text_edit *state)
33767 {
33768  /* canonicalize the selection so start <= end */
33769  if (state->select_end < state->select_start) {
33770  int temp = state->select_end;
33771  state->select_end = state->select_start;
33772  state->select_start = temp;
33773  }
33774 }
33785 NK_INTERN void
33786 nk_textedit_move_to_first(struct nk_text_edit *state)
33787 {
33788  /* move cursor to first character of selection */
33789  if (NK_TEXT_HAS_SELECTION(state)) {
33790  nk_textedit_sortselection(state);
33791  state->cursor = state->select_start;
33792  state->select_end = state->select_start;
33793  state->has_preferred_x = 0;
33794  }
33795 }
33806 NK_INTERN void
33807 nk_textedit_move_to_last(struct nk_text_edit *state)
33808 {
33809  /* move cursor to last character of selection */
33810  if (NK_TEXT_HAS_SELECTION(state)) {
33811  nk_textedit_sortselection(state);
33812  nk_textedit_clamp(state);
33813  state->cursor = state->select_end;
33814  state->select_start = state->select_end;
33815  state->has_preferred_x = 0;
33816  }
33817 }
33829 NK_INTERN int
33830 nk_is_word_boundary( struct nk_text_edit *state, int idx)
33831 {
33832  int len;
33833  nk_rune c;
33834  if (idx <= 0) return 1;
33835  if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
33836  return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
33837  c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
33838  c == '|');
33839 }
33850 NK_INTERN int
33851 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
33852 {
33853  int c = state->cursor - 1;
33854  while( c >= 0 && !nk_is_word_boundary(state, c))
33855  --c;
33856 
33857  if( c < 0 )
33858  c = 0;
33859 
33860  return c;
33861 }
33872 NK_INTERN int
33873 nk_textedit_move_to_word_next(struct nk_text_edit *state)
33874 {
33875  const int len = state->string.len;
33876  int c = state->cursor+1;
33877  while( c < len && !nk_is_word_boundary(state, c))
33878  ++c;
33879 
33880  if( c > len )
33881  c = len;
33882 
33883  return c;
33884 }
33895 NK_INTERN void
33896 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
33897 {
33898  /* update selection and cursor to match each other */
33899  if (!NK_TEXT_HAS_SELECTION(state))
33900  state->select_start = state->select_end = state->cursor;
33901  else state->cursor = state->select_end;
33902 }
33913 NK_API nk_bool
33914 nk_textedit_cut(struct nk_text_edit *state)
33915 {
33916  /* API cut: delete selection */
33917  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
33918  return 0;
33919  if (NK_TEXT_HAS_SELECTION(state)) {
33920  nk_textedit_delete_selection(state); /* implicitly clamps */
33921  state->has_preferred_x = 0;
33922  return 1;
33923  }
33924  return 0;
33925 }
33938 NK_API nk_bool
33939 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
33940 {
33941  /* API paste: replace existing selection with passed-in text */
33942  int glyphs;
33943  const char *text = (const char *) ctext;
33944  if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
33945 
33946  /* if there's a selection, the paste should delete it */
33947  nk_textedit_clamp(state);
33948  nk_textedit_delete_selection(state);
33949 
33950  /* try to insert the characters */
33951  glyphs = nk_utf_len(ctext, len);
33952  if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
33953  nk_textedit_makeundo_insert(state, state->cursor, glyphs);
33954  state->cursor += len;
33955  state->has_preferred_x = 0;
33956  return 1;
33957  }
33958  /* remove the undo since we didn't actually insert the characters */
33959  if (state->undo.undo_point)
33960  --state->undo.undo_point;
33961  return 0;
33962 }
33975 NK_API void
33976 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
33977 {
33978  nk_rune unicode;
33979  int glyph_len;
33980  int text_len = 0;
33981 
33982  NK_ASSERT(state);
33983  NK_ASSERT(text);
33984  if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
33985 
33986  glyph_len = nk_utf_decode(text, &unicode, total_len);
33987  while ((text_len < total_len) && glyph_len)
33988  {
33989  /* don't insert a backward delete, just process the event */
33990  if (unicode == 127) goto next;
33991  /* can't add newline in single-line mode */
33992  if (unicode == '\n' && state->single_line) goto next;
33993  /* filter incoming text */
33994  if (state->filter && !state->filter(state, unicode)) goto next;
33995 
33996  if (!NK_TEXT_HAS_SELECTION(state) &&
33997  state->cursor < state->string.len)
33998  {
33999  if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
34000  nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
34001  nk_str_delete_runes(&state->string, state->cursor, 1);
34002  }
34003  if (nk_str_insert_text_utf8(&state->string, state->cursor,
34004  text+text_len, 1))
34005  {
34006  ++state->cursor;
34007  state->has_preferred_x = 0;
34008  }
34009  } else {
34010  nk_textedit_delete_selection(state); /* implicitly clamps */
34011  if (nk_str_insert_text_utf8(&state->string, state->cursor,
34012  text+text_len, 1))
34013  {
34014  nk_textedit_makeundo_insert(state, state->cursor, 1);
34015  state->cursor = NK_MIN(state->cursor + 1, state->string.len);
34016  state->has_preferred_x = 0;
34017  }
34018  }
34019  next:
34020  text_len += glyph_len;
34021  glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
34022  }
34023 }
34036 NK_LIB void
34037 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
34038  const struct nk_user_font *font, float row_height)
34039 {
34040 retry:
34041  switch (key)
34042  {
34043  case NK_KEY_NONE:
34044  case NK_KEY_CTRL:
34045  case NK_KEY_ENTER:
34046  case NK_KEY_SHIFT:
34047  case NK_KEY_TAB:
34048  case NK_KEY_COPY:
34049  case NK_KEY_CUT:
34050  case NK_KEY_PASTE:
34051  case NK_KEY_MAX:
34052  default: break;
34053  case NK_KEY_TEXT_UNDO:
34054  nk_textedit_undo(state);
34055  state->has_preferred_x = 0;
34056  break;
34057 
34058  case NK_KEY_TEXT_REDO:
34059  nk_textedit_redo(state);
34060  state->has_preferred_x = 0;
34061  break;
34062 
34063  case NK_KEY_TEXT_SELECT_ALL:
34064  nk_textedit_select_all(state);
34065  state->has_preferred_x = 0;
34066  break;
34067 
34068  case NK_KEY_TEXT_INSERT_MODE:
34069  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
34070  state->mode = NK_TEXT_EDIT_MODE_INSERT;
34071  break;
34072  case NK_KEY_TEXT_REPLACE_MODE:
34073  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
34074  state->mode = NK_TEXT_EDIT_MODE_REPLACE;
34075  break;
34076  case NK_KEY_TEXT_RESET_MODE:
34077  if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
34078  state->mode == NK_TEXT_EDIT_MODE_REPLACE)
34079  state->mode = NK_TEXT_EDIT_MODE_VIEW;
34080  break;
34081 
34082  case NK_KEY_LEFT:
34083  if (shift_mod) {
34084  nk_textedit_clamp(state);
34085  nk_textedit_prep_selection_at_cursor(state);
34086  /* move selection left */
34087  if (state->select_end > 0)
34088  --state->select_end;
34089  state->cursor = state->select_end;
34090  state->has_preferred_x = 0;
34091  } else {
34092  /* if currently there's a selection,
34093  * move cursor to start of selection */
34094  if (NK_TEXT_HAS_SELECTION(state))
34095  nk_textedit_move_to_first(state);
34096  else if (state->cursor > 0)
34097  --state->cursor;
34098  state->has_preferred_x = 0;
34099  } break;
34100 
34101  case NK_KEY_RIGHT:
34102  if (shift_mod) {
34103  nk_textedit_prep_selection_at_cursor(state);
34104  /* move selection right */
34105  ++state->select_end;
34106  nk_textedit_clamp(state);
34107  state->cursor = state->select_end;
34108  state->has_preferred_x = 0;
34109  } else {
34110  /* if currently there's a selection,
34111  * move cursor to end of selection */
34112  if (NK_TEXT_HAS_SELECTION(state))
34113  nk_textedit_move_to_last(state);
34114  else ++state->cursor;
34115  nk_textedit_clamp(state);
34116  state->has_preferred_x = 0;
34117  } break;
34118 
34119  case NK_KEY_TEXT_WORD_LEFT:
34120  if (shift_mod) {
34121  if( !NK_TEXT_HAS_SELECTION( state ) )
34122  nk_textedit_prep_selection_at_cursor(state);
34123  state->cursor = nk_textedit_move_to_word_previous(state);
34124  state->select_end = state->cursor;
34125  nk_textedit_clamp(state );
34126  } else {
34127  if (NK_TEXT_HAS_SELECTION(state))
34128  nk_textedit_move_to_first(state);
34129  else {
34130  state->cursor = nk_textedit_move_to_word_previous(state);
34131  nk_textedit_clamp(state );
34132  }
34133  } break;
34134 
34135  case NK_KEY_TEXT_WORD_RIGHT:
34136  if (shift_mod) {
34137  if( !NK_TEXT_HAS_SELECTION( state ) )
34138  nk_textedit_prep_selection_at_cursor(state);
34139  state->cursor = nk_textedit_move_to_word_next(state);
34140  state->select_end = state->cursor;
34141  nk_textedit_clamp(state);
34142  } else {
34143  if (NK_TEXT_HAS_SELECTION(state))
34144  nk_textedit_move_to_last(state);
34145  else {
34146  state->cursor = nk_textedit_move_to_word_next(state);
34147  nk_textedit_clamp(state );
34148  }
34149  } break;
34150 
34151  case NK_KEY_DOWN: {
34152  struct nk_text_find find;
34153  struct nk_text_edit_row row;
34154  int i, sel = shift_mod;
34155 
34156  if (state->single_line) {
34157  /* on windows, up&down in single-line behave like left&right */
34158  key = NK_KEY_RIGHT;
34159  goto retry;
34160  }
34161 
34162  if (sel)
34163  nk_textedit_prep_selection_at_cursor(state);
34164  else if (NK_TEXT_HAS_SELECTION(state))
34165  nk_textedit_move_to_last(state);
34166 
34167  /* compute current position of cursor point */
34168  nk_textedit_clamp(state);
34169  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
34170  font, row_height);
34171 
34172  /* now find character position down a row */
34173  if (find.length)
34174  {
34175  float x;
34176  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
34177  int start = find.first_char + find.length;
34178 
34179  state->cursor = start;
34180  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
34181  x = row.x0;
34182 
34183  for (i=0; i < row.num_chars && x < row.x1; ++i) {
34184  float dx = nk_textedit_get_width(state, start, i, font);
34185  x += dx;
34186  if (x > goal_x)
34187  break;
34188  ++state->cursor;
34189  }
34190  nk_textedit_clamp(state);
34191 
34192  state->has_preferred_x = 1;
34193  state->preferred_x = goal_x;
34194  if (sel)
34195  state->select_end = state->cursor;
34196  }
34197  } break;
34198 
34199  case NK_KEY_UP: {
34200  struct nk_text_find find;
34201  struct nk_text_edit_row row;
34202  int i, sel = shift_mod;
34203 
34204  if (state->single_line) {
34205  /* on windows, up&down become left&right */
34206  key = NK_KEY_LEFT;
34207  goto retry;
34208  }
34209 
34210  if (sel)
34211  nk_textedit_prep_selection_at_cursor(state);
34212  else if (NK_TEXT_HAS_SELECTION(state))
34213  nk_textedit_move_to_first(state);
34214 
34215  /* compute current position of cursor point */
34216  nk_textedit_clamp(state);
34217  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
34218  font, row_height);
34219 
34220  /* can only go up if there's a previous row */
34221  if (find.prev_first != find.first_char) {
34222  /* now find character position up a row */
34223  float x;
34224  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
34225 
34226  state->cursor = find.prev_first;
34227  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
34228  x = row.x0;
34229 
34230  for (i=0; i < row.num_chars && x < row.x1; ++i) {
34231  float dx = nk_textedit_get_width(state, find.prev_first, i, font);
34232  x += dx;
34233  if (x > goal_x)
34234  break;
34235  ++state->cursor;
34236  }
34237  nk_textedit_clamp(state);
34238 
34239  state->has_preferred_x = 1;
34240  state->preferred_x = goal_x;
34241  if (sel) state->select_end = state->cursor;
34242  }
34243  } break;
34244 
34245  case NK_KEY_DEL:
34246  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
34247  break;
34248  if (NK_TEXT_HAS_SELECTION(state))
34249  nk_textedit_delete_selection(state);
34250  else {
34251  int n = state->string.len;
34252  if (state->cursor < n)
34253  nk_textedit_delete(state, state->cursor, 1);
34254  }
34255  state->has_preferred_x = 0;
34256  break;
34257 
34258  case NK_KEY_BACKSPACE:
34259  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
34260  break;
34261  if (NK_TEXT_HAS_SELECTION(state))
34262  nk_textedit_delete_selection(state);
34263  else {
34264  nk_textedit_clamp(state);
34265  if (state->cursor > 0) {
34266  nk_textedit_delete(state, state->cursor-1, 1);
34267  --state->cursor;
34268  }
34269  }
34270  state->has_preferred_x = 0;
34271  break;
34272 
34273  case NK_KEY_TEXT_START:
34274  if (shift_mod) {
34275  nk_textedit_prep_selection_at_cursor(state);
34276  state->cursor = state->select_end = 0;
34277  state->has_preferred_x = 0;
34278  } else {
34279  state->cursor = state->select_start = state->select_end = 0;
34280  state->has_preferred_x = 0;
34281  }
34282  break;
34283 
34284  case NK_KEY_TEXT_END:
34285  if (shift_mod) {
34286  nk_textedit_prep_selection_at_cursor(state);
34287  state->cursor = state->select_end = state->string.len;
34288  state->has_preferred_x = 0;
34289  } else {
34290  state->cursor = state->string.len;
34291  state->select_start = state->select_end = 0;
34292  state->has_preferred_x = 0;
34293  }
34294  break;
34295 
34296  case NK_KEY_TEXT_LINE_START: {
34297  if (shift_mod) {
34298  struct nk_text_find find;
34299  nk_textedit_clamp(state);
34300  nk_textedit_prep_selection_at_cursor(state);
34301  if (state->string.len && state->cursor == state->string.len)
34302  --state->cursor;
34303  nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
34304  font, row_height);
34305  state->cursor = state->select_end = find.first_char;
34306  state->has_preferred_x = 0;
34307  } else {
34308  struct nk_text_find find;
34309  if (state->string.len && state->cursor == state->string.len)
34310  --state->cursor;
34311  nk_textedit_clamp(state);
34312  nk_textedit_move_to_first(state);
34313  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
34314  font, row_height);
34315  state->cursor = find.first_char;
34316  state->has_preferred_x = 0;
34317  }
34318  } break;
34319 
34320  case NK_KEY_TEXT_LINE_END: {
34321  if (shift_mod) {
34322  struct nk_text_find find;
34323  nk_textedit_clamp(state);
34324  nk_textedit_prep_selection_at_cursor(state);
34325  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
34326  font, row_height);
34327  state->has_preferred_x = 0;
34328  state->cursor = find.first_char + find.length;
34329  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
34330  --state->cursor;
34331  state->select_end = state->cursor;
34332  } else {
34333  struct nk_text_find find;
34334  nk_textedit_clamp(state);
34335  nk_textedit_move_to_first(state);
34336  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
34337  font, row_height);
34338 
34339  state->has_preferred_x = 0;
34340  state->cursor = find.first_char + find.length;
34341  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
34342  --state->cursor;
34343  }} break;
34344  }
34345 }
34356 NK_INTERN void
34357 nk_textedit_flush_redo(struct nk_text_undo_state *state)
34358 {
34359  state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
34360  state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
34361 }
34372 NK_INTERN void
34373 nk_textedit_discard_undo(struct nk_text_undo_state *state)
34374 {
34375  /* discard the oldest entry in the undo list */
34376  if (state->undo_point > 0) {
34377  /* if the 0th undo state has characters, clean those up */
34378  if (state->undo_rec[0].char_storage >= 0) {
34379  int n = state->undo_rec[0].insert_length, i;
34380  /* delete n characters from all other records */
34381  state->undo_char_point = (short)(state->undo_char_point - n);
34382  NK_MEMCPY(state->undo_char, state->undo_char + n,
34383  (nk_size)state->undo_char_point*sizeof(nk_rune));
34384  for (i=0; i < state->undo_point; ++i) {
34385  if (state->undo_rec[i].char_storage >= 0)
34386  state->undo_rec[i].char_storage = (short)
34387  (state->undo_rec[i].char_storage - n);
34388  }
34389  }
34390  --state->undo_point;
34391  NK_MEMCPY(state->undo_rec, state->undo_rec+1,
34392  (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
34393  }
34394 }
34405 NK_INTERN void
34406 nk_textedit_discard_redo(struct nk_text_undo_state *state)
34407 {
34408 /* discard the oldest entry in the redo list--it's bad if this
34409  ever happens, but because undo & redo have to store the actual
34410  characters in different cases, the redo character buffer can
34411  fill up even though the undo buffer didn't */
34412  nk_size num;
34413  int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
34414  if (state->redo_point <= k) {
34415  /* if the k'th undo state has characters, clean those up */
34416  if (state->undo_rec[k].char_storage >= 0) {
34417  int n = state->undo_rec[k].insert_length, i;
34418  /* delete n characters from all other records */
34419  state->redo_char_point = (short)(state->redo_char_point + n);
34420  num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point);
34421  NK_MEMCPY(state->undo_char + state->redo_char_point,
34422  state->undo_char + state->redo_char_point-n, num * sizeof(char));
34423  for (i = state->redo_point; i < k; ++i) {
34424  if (state->undo_rec[i].char_storage >= 0) {
34425  state->undo_rec[i].char_storage = (short)
34426  (state->undo_rec[i].char_storage + n);
34427  }
34428  }
34429  }
34430  ++state->redo_point;
34431  num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
34432  if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
34433  state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
34434  }
34435 }
34447 NK_INTERN struct nk_text_undo_record*
34448 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
34449 {
34450  /* any time we create a new undo record, we discard redo*/
34451  nk_textedit_flush_redo(state);
34452 
34453  /* if we have no free records, we have to make room,
34454  * by sliding the existing records down */
34455  if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
34456  nk_textedit_discard_undo(state);
34457 
34458  /* if the characters to store won't possibly fit in the buffer,
34459  * we can't undo */
34460  if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
34461  state->undo_point = 0;
34462  state->undo_char_point = 0;
34463  return 0;
34464  }
34465 
34466  /* if we don't have enough free characters in the buffer,
34467  * we have to make room */
34468  while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
34469  nk_textedit_discard_undo(state);
34470  return &state->undo_rec[state->undo_point++];
34471 }
34483 NK_INTERN nk_rune*
34484 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
34485  int insert_len, int delete_len)
34486 {
34487  struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
34488  if (r == 0)
34489  return 0;
34490 
34491  r->where = pos;
34492  r->insert_length = (short) insert_len;
34493  r->delete_length = (short) delete_len;
34494 
34495  if (insert_len == 0) {
34496  r->char_storage = -1;
34497  return 0;
34498  } else {
34499  r->char_storage = state->undo_char_point;
34500  state->undo_char_point = (short)(state->undo_char_point + insert_len);
34501  return &state->undo_char[r->char_storage];
34502  }
34503 }
34514 NK_API void
34515 nk_textedit_undo(struct nk_text_edit *state)
34516 {
34517  struct nk_text_undo_state *s = &state->undo;
34518  struct nk_text_undo_record u, *r;
34519  if (s->undo_point == 0)
34520  return;
34521 
34522  /* we need to do two things: apply the undo record, and create a redo record */
34523  u = s->undo_rec[s->undo_point-1];
34524  r = &s->undo_rec[s->redo_point-1];
34525  r->char_storage = -1;
34526 
34527  r->insert_length = u.delete_length;
34528  r->delete_length = u.insert_length;
34529  r->where = u.where;
34530 
34531  if (u.delete_length)
34532  {
34533  /* if the undo record says to delete characters, then the redo record will
34534  need to re-insert the characters that get deleted, so we need to store
34535  them.
34536  there are three cases:
34537  - there's enough room to store the characters
34538  - characters stored for *redoing* don't leave room for redo
34539  - characters stored for *undoing* don't leave room for redo
34540  if the last is true, we have to bail */
34541  if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
34542  /* the undo records take up too much character space; there's no space
34543  * to store the redo characters */
34544  r->insert_length = 0;
34545  } else {
34546  int i;
34547  /* there's definitely room to store the characters eventually */
34548  while (s->undo_char_point + u.delete_length > s->redo_char_point) {
34549  /* there's currently not enough room, so discard a redo record */
34550  nk_textedit_discard_redo(s);
34551  /* should never happen: */
34552  if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
34553  return;
34554  }
34555 
34556  r = &s->undo_rec[s->redo_point-1];
34557  r->char_storage = (short)(s->redo_char_point - u.delete_length);
34558  s->redo_char_point = (short)(s->redo_char_point - u.delete_length);
34559 
34560  /* now save the characters */
34561  for (i=0; i < u.delete_length; ++i)
34562  s->undo_char[r->char_storage + i] =
34563  nk_str_rune_at(&state->string, u.where + i);
34564  }
34565  /* now we can carry out the deletion */
34566  nk_str_delete_runes(&state->string, u.where, u.delete_length);
34567  }
34568 
34569  /* check type of recorded action: */
34570  if (u.insert_length) {
34571  /* easy case: was a deletion, so we need to insert n characters */
34572  nk_str_insert_text_runes(&state->string, u.where,
34573  &s->undo_char[u.char_storage], u.insert_length);
34574  s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
34575  }
34576  state->cursor = (short)(u.where + u.insert_length);
34577 
34578  s->undo_point--;
34579  s->redo_point--;
34580 }
34591 NK_API void
34592 nk_textedit_redo(struct nk_text_edit *state)
34593 {
34594  struct nk_text_undo_state *s = &state->undo;
34595  struct nk_text_undo_record *u, r;
34596  if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
34597  return;
34598 
34599  /* we need to do two things: apply the redo record, and create an undo record */
34600  u = &s->undo_rec[s->undo_point];
34601  r = s->undo_rec[s->redo_point];
34602 
34603  /* we KNOW there must be room for the undo record, because the redo record
34604  was derived from an undo record */
34605  u->delete_length = r.insert_length;
34606  u->insert_length = r.delete_length;
34607  u->where = r.where;
34608  u->char_storage = -1;
34609 
34610  if (r.delete_length) {
34611  /* the redo record requires us to delete characters, so the undo record
34612  needs to store the characters */
34613  if (s->undo_char_point + u->insert_length > s->redo_char_point) {
34614  u->insert_length = 0;
34615  u->delete_length = 0;
34616  } else {
34617  int i;
34618  u->char_storage = s->undo_char_point;
34619  s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
34620 
34621  /* now save the characters */
34622  for (i=0; i < u->insert_length; ++i) {
34623  s->undo_char[u->char_storage + i] =
34624  nk_str_rune_at(&state->string, u->where + i);
34625  }
34626  }
34627  nk_str_delete_runes(&state->string, r.where, r.delete_length);
34628  }
34629 
34630  if (r.insert_length) {
34631  /* easy case: need to insert n characters */
34632  nk_str_insert_text_runes(&state->string, r.where,
34633  &s->undo_char[r.char_storage], r.insert_length);
34634  }
34635  state->cursor = r.where + r.insert_length;
34636 
34637  s->undo_point++;
34638  s->redo_point++;
34639 }
34652 NK_INTERN void
34653 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
34654 {
34655  nk_textedit_createundo(&state->undo, where, 0, length);
34656 }
34669 NK_INTERN void
34670 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
34671 {
34672  int i;
34673  nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
34674  if (p) {
34675  for (i=0; i < length; ++i)
34676  p[i] = nk_str_rune_at(&state->string, where+i);
34677  }
34678 }
34690 NK_INTERN void
34691 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
34692  int old_length, int new_length)
34693 {
34694  int i;
34695  nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
34696  if (p) {
34697  for (i=0; i < old_length; ++i)
34698  p[i] = nk_str_rune_at(&state->string, where+i);
34699  }
34700 }
34712 NK_LIB void
34713 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
34714  nk_plugin_filter filter)
34715 {
34716  /* reset the state to default */
34717  state->undo.undo_point = 0;
34718  state->undo.undo_char_point = 0;
34719  state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
34720  state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
34721  state->select_end = state->select_start = 0;
34722  state->cursor = 0;
34723  state->has_preferred_x = 0;
34724  state->preferred_x = 0;
34725  state->cursor_at_end_of_line = 0;
34726  state->initialized = 1;
34727  state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
34728  state->mode = NK_TEXT_EDIT_MODE_VIEW;
34729  state->filter = filter;
34730  state->scrollbar = nk_vec2(0,0);
34731 }
34744 NK_API void
34745 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
34746 {
34747  NK_ASSERT(state);
34748  NK_ASSERT(memory);
34749  if (!state || !memory || !size) return;
34750  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
34751  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
34752  nk_str_init_fixed(&state->string, memory, size);
34753 }
34766 NK_API void
34767 nk_textedit_init(struct nk_text_edit *state, const struct nk_allocator *alloc, nk_size size)
34768 {
34769  NK_ASSERT(state);
34770  NK_ASSERT(alloc);
34771  if (!state || !alloc) return;
34772  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
34773  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
34774  nk_str_init(&state->string, alloc, size);
34775 }
34776 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
34787 NK_API void
34788 nk_textedit_init_default(struct nk_text_edit *state)
34789 {
34790  NK_ASSERT(state);
34791  if (!state) return;
34792  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
34793  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
34794  nk_str_init_default(&state->string);
34795 }
34796 #endif
34807 NK_API void
34808 nk_textedit_select_all(struct nk_text_edit *state)
34809 {
34810  NK_ASSERT(state);
34811  state->select_start = 0;
34812  state->select_end = state->string.len;
34813 }
34824 NK_API void
34825 nk_textedit_free(struct nk_text_edit *state)
34826 {
34827  NK_ASSERT(state);
34828  if (!state) return;
34829  nk_str_free(&state->string);
34830 }
34831 
34832 
34833 
34834 
34835 
34836 /* ===============================================================
34837  *
34838  * FILTER
34839  *
34840  * ===============================================================*/
34852 NK_API nk_bool
34853 nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
34854 {
34855  NK_UNUSED(unicode);
34856  NK_UNUSED(box);
34857  return nk_true;
34858 }
34870 NK_API nk_bool
34871 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
34872 {
34873  NK_UNUSED(box);
34874  if (unicode > 128) return nk_false;
34875  else return nk_true;
34876 }
34888 NK_API nk_bool
34889 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
34890 {
34891  NK_UNUSED(box);
34892  if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
34893  return nk_false;
34894  else return nk_true;
34895 }
34907 NK_API nk_bool
34908 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
34909 {
34910  NK_UNUSED(box);
34911  if ((unicode < '0' || unicode > '9') && unicode != '-')
34912  return nk_false;
34913  else return nk_true;
34914 }
34926 NK_API nk_bool
34927 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
34928 {
34929  NK_UNUSED(box);
34930  if ((unicode < '0' || unicode > '9') &&
34931  (unicode < 'a' || unicode > 'f') &&
34932  (unicode < 'A' || unicode > 'F'))
34933  return nk_false;
34934  else return nk_true;
34935 }
34947 NK_API nk_bool
34948 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
34949 {
34950  NK_UNUSED(box);
34951  if (unicode < '0' || unicode > '7')
34952  return nk_false;
34953  else return nk_true;
34954 }
34966 NK_API nk_bool
34967 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
34968 {
34969  NK_UNUSED(box);
34970  if (unicode != '0' && unicode != '1')
34971  return nk_false;
34972  else return nk_true;
34973 }
34974 
34975 /* ===============================================================
34976  *
34977  * EDIT
34978  *
34979  * ===============================================================*/
34990 NK_LIB void
34991 nk_edit_draw_text(struct nk_command_buffer *out,
34992  const struct nk_style_edit *style, float pos_x, float pos_y,
34993  float x_offset, const char *text, int byte_len, float row_height,
34994  const struct nk_user_font *font, struct nk_color background,
34995  struct nk_color foreground, nk_bool is_selected)
34996 {
34997  NK_ASSERT(out);
34998  NK_ASSERT(font);
34999  NK_ASSERT(style);
35000  if (!text || !byte_len || !out || !style) return;
35001 
35002  {int glyph_len = 0;
35003  nk_rune unicode = 0;
35004  int text_len = 0;
35005  float line_width = 0;
35006  float glyph_width;
35007  const char *line = text;
35008  float line_offset = 0;
35009  int line_count = 0;
35010 
35011  struct nk_text txt;
35012  txt.padding = nk_vec2(0,0);
35013  txt.background = background;
35014  txt.text = foreground;
35015 
35016  foreground = nk_rgb_factor(foreground, style->color_factor);
35017  background = nk_rgb_factor(background, style->color_factor);
35018 
35019  glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
35020  if (!glyph_len) return;
35021  while ((text_len < byte_len) && glyph_len)
35022  {
35023  if (unicode == '\n') {
35024  /* new line separator so draw previous line */
35025  struct nk_rect label;
35026  label.y = pos_y + line_offset;
35027  label.h = row_height;
35028  label.w = line_width;
35029  label.x = pos_x;
35030  if (!line_count)
35031  label.x += x_offset;
35032 
35033  if (is_selected) /* selection needs to draw different background color */
35034  nk_fill_rect(out, label, 0, background);
35035  nk_widget_text(out, label, line, (int)((text + text_len) - line),
35036  &txt, NK_TEXT_CENTERED, font);
35037 
35038  text_len++;
35039  line_count++;
35040  line_width = 0;
35041  line = text + text_len;
35042  line_offset += row_height;
35043  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
35044  continue;
35045  }
35046  if (unicode == '\r') {
35047  text_len++;
35048  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
35049  continue;
35050  }
35051  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
35052  line_width += (float)glyph_width;
35053  text_len += glyph_len;
35054  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
35055  continue;
35056  }
35057  if (line_width > 0) {
35058  /* draw last line */
35059  struct nk_rect label;
35060  label.y = pos_y + line_offset;
35061  label.h = row_height;
35062  label.w = line_width;
35063  label.x = pos_x;
35064  if (!line_count)
35065  label.x += x_offset;
35066 
35067  if (is_selected)
35068  nk_fill_rect(out, label, 0, background);
35069  nk_widget_text(out, label, line, (int)((text + text_len) - line),
35070  &txt, NK_TEXT_LEFT, font);
35071  }}
35072 }
35084 NK_LIB nk_flags
35085 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
35086  struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
35087  struct nk_text_edit *edit, const struct nk_style_edit *style,
35088  struct nk_input *in, const struct nk_user_font *font)
35089 {
35090  struct nk_rect area;
35091  nk_flags ret = 0;
35092  float row_height;
35093  char prev_state = 0;
35094  char is_hovered = 0;
35095  char select_all = 0;
35096  char cursor_follow = 0;
35097  struct nk_rect old_clip;
35098  struct nk_rect clip;
35099 
35100  NK_ASSERT(state);
35101  NK_ASSERT(out);
35102  NK_ASSERT(style);
35103  if (!state || !out || !style)
35104  return ret;
35105 
35106  /* visible text area calculation */
35107  area.x = bounds.x + style->padding.x + style->border;
35108  area.y = bounds.y + style->padding.y + style->border;
35109  area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
35110  area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
35111  if (flags & NK_EDIT_MULTILINE)
35112  area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
35113  row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
35114 
35115  /* calculate clipping rectangle */
35116  old_clip = out->clip;
35117  nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
35118 
35119  /* update edit state */
35120  prev_state = (char)edit->active;
35121  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
35122  if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) {
35123  edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
35124  bounds.x, bounds.y, bounds.w, bounds.h);
35125  }
35126 
35127  /* (de)activate text editor */
35128  if (!prev_state && edit->active) {
35129  const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
35130  NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE;
35131  /* keep scroll position when re-activating edit widget */
35132  struct nk_vec2 oldscrollbar = edit->scrollbar;
35133  nk_textedit_clear_state(edit, type, filter);
35134  edit->scrollbar = oldscrollbar;
35135  if (flags & NK_EDIT_AUTO_SELECT)
35136  select_all = nk_true;
35137  if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
35138  edit->cursor = edit->string.len;
35139  in = 0;
35140  }
35141  } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
35142  if (flags & NK_EDIT_READ_ONLY)
35143  edit->mode = NK_TEXT_EDIT_MODE_VIEW;
35144  else if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
35145  edit->mode = NK_TEXT_EDIT_MODE_INSERT;
35146 
35147  ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
35148  if (prev_state != edit->active)
35149  ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
35150 
35151  /* handle user input */
35152  if (edit->active && in)
35153  {
35154  int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
35155  const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
35156  const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
35157 
35158  /* mouse click handler */
35159  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
35160  if (select_all) {
35161  nk_textedit_select_all(edit);
35162  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
35163  in->mouse.buttons[NK_BUTTON_LEFT].clicked) {
35164  nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
35165  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
35166  (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
35167  nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
35168  cursor_follow = nk_true;
35169  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
35170  in->mouse.buttons[NK_BUTTON_RIGHT].down) {
35171  nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
35172  nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
35173  cursor_follow = nk_true;
35174  }
35175 
35176  {int i; /* keyboard input */
35177  int old_mode = edit->mode;
35178  for (i = 0; i < NK_KEY_MAX; ++i) {
35179  if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
35180  if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
35181  nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
35182  cursor_follow = nk_true;
35183  }
35184  }
35185  if (old_mode != edit->mode) {
35186  in->keyboard.text_len = 0;
35187  }}
35188 
35189  /* text input */
35190  edit->filter = filter;
35191  if (in->keyboard.text_len) {
35192  nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
35193  cursor_follow = nk_true;
35194  in->keyboard.text_len = 0;
35195  }
35196 
35197  /* enter key handler */
35198  if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) {
35199  cursor_follow = nk_true;
35200  if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
35201  nk_textedit_text(edit, "\n", 1);
35202  else if (flags & NK_EDIT_SIG_ENTER)
35203  ret |= NK_EDIT_COMMITED;
35204  else nk_textedit_text(edit, "\n", 1);
35205  }
35206 
35207  /* cut & copy handler */
35208  {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
35209  int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
35210  if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
35211  {
35212  int glyph_len;
35213  nk_rune unicode;
35214  const char *text;
35215  int b = edit->select_start;
35216  int e = edit->select_end;
35217 
35218  int begin = NK_MIN(b, e);
35219  int end = NK_MAX(b, e);
35220  text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
35221  if (edit->clip.copy)
35222  edit->clip.copy(edit->clip.userdata, text, end - begin);
35223  if (cut && !(flags & NK_EDIT_READ_ONLY)){
35224  nk_textedit_cut(edit);
35225  cursor_follow = nk_true;
35226  }
35227  }}
35228 
35229  /* paste handler */
35230  {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
35231  if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
35232  edit->clip.paste(edit->clip.userdata, edit);
35233  cursor_follow = nk_true;
35234  }}
35235 
35236  /* tab handler */
35237  {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
35238  if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
35239  nk_textedit_text(edit, " ", 4);
35240  cursor_follow = nk_true;
35241  }}
35242  }
35243 
35244  /* set widget state */
35245  if (edit->active)
35246  *state = NK_WIDGET_STATE_ACTIVE;
35247  else nk_widget_state_reset(state);
35248 
35249  if (is_hovered)
35250  *state |= NK_WIDGET_STATE_HOVERED;
35251 
35252  /* DRAW EDIT */
35253  {const char *text = nk_str_get_const(&edit->string);
35254  int len = nk_str_len_char(&edit->string);
35255 
35256  {/* select background colors/images */
35257  const struct nk_style_item *background;
35258  if (*state & NK_WIDGET_STATE_ACTIVED)
35259  background = &style->active;
35260  else if (*state & NK_WIDGET_STATE_HOVER)
35261  background = &style->hover;
35262  else background = &style->normal;
35263 
35264  /* draw background frame */
35265  switch(background->type) {
35266  case NK_STYLE_ITEM_IMAGE:
35267  nk_draw_image(out, bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
35268  break;
35269  case NK_STYLE_ITEM_NINE_SLICE:
35270  nk_draw_nine_slice(out, bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
35271  break;
35272  case NK_STYLE_ITEM_COLOR:
35273  nk_fill_rect(out, bounds, style->rounding, nk_rgb_factor(background->data.color, style->color_factor));
35274  nk_stroke_rect(out, bounds, style->rounding, style->border, nk_rgb_factor(style->border_color, style->color_factor));
35275  break;
35276  }}
35277 
35278 
35279  area.w = NK_MAX(0, area.w - style->cursor_size);
35280  if (edit->active)
35281  {
35282  int total_lines = 1;
35283  struct nk_vec2 text_size = nk_vec2(0,0);
35284 
35285  /* text pointer positions */
35286  const char *cursor_ptr = 0;
35287  const char *select_begin_ptr = 0;
35288  const char *select_end_ptr = 0;
35289 
35290  /* 2D pixel positions */
35291  struct nk_vec2 cursor_pos = nk_vec2(0,0);
35292  struct nk_vec2 selection_offset_start = nk_vec2(0,0);
35293  struct nk_vec2 selection_offset_end = nk_vec2(0,0);
35294 
35295  int selection_begin = NK_MIN(edit->select_start, edit->select_end);
35296  int selection_end = NK_MAX(edit->select_start, edit->select_end);
35297 
35298  /* calculate total line count + total space + cursor/selection position */
35299  float line_width = 0.0f;
35300  if (text && len)
35301  {
35302  /* utf8 encoding */
35303  float glyph_width;
35304  int glyph_len = 0;
35305  nk_rune unicode = 0;
35306  int text_len = 0;
35307  int glyphs = 0;
35308  int row_begin = 0;
35309 
35310  glyph_len = nk_utf_decode(text, &unicode, len);
35311  glyph_width = font->width(font->userdata, font->height, text, glyph_len);
35312  line_width = 0;
35313 
35314  /* iterate all lines */
35315  while ((text_len < len) && glyph_len)
35316  {
35317  /* set cursor 2D position and line */
35318  if (!cursor_ptr && glyphs == edit->cursor)
35319  {
35320  int glyph_offset;
35321  struct nk_vec2 out_offset;
35322  struct nk_vec2 row_size;
35323  const char *remaining;
35324 
35325  /* calculate 2d position */
35326  cursor_pos.y = (float)(total_lines-1) * row_height;
35327  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
35328  text_len-row_begin, row_height, &remaining,
35329  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
35330  cursor_pos.x = row_size.x;
35331  cursor_ptr = text + text_len;
35332  }
35333 
35334  /* set start selection 2D position and line */
35335  if (!select_begin_ptr && edit->select_start != edit->select_end &&
35336  glyphs == selection_begin)
35337  {
35338  int glyph_offset;
35339  struct nk_vec2 out_offset;
35340  struct nk_vec2 row_size;
35341  const char *remaining;
35342 
35343  /* calculate 2d position */
35344  selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
35345  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
35346  text_len-row_begin, row_height, &remaining,
35347  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
35348  selection_offset_start.x = row_size.x;
35349  select_begin_ptr = text + text_len;
35350  }
35351 
35352  /* set end selection 2D position and line */
35353  if (!select_end_ptr && edit->select_start != edit->select_end &&
35354  glyphs == selection_end)
35355  {
35356  int glyph_offset;
35357  struct nk_vec2 out_offset;
35358  struct nk_vec2 row_size;
35359  const char *remaining;
35360 
35361  /* calculate 2d position */
35362  selection_offset_end.y = (float)(total_lines-1) * row_height;
35363  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
35364  text_len-row_begin, row_height, &remaining,
35365  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
35366  selection_offset_end.x = row_size.x;
35367  select_end_ptr = text + text_len;
35368  }
35369  if (unicode == '\n') {
35370  text_size.x = NK_MAX(text_size.x, line_width);
35371  total_lines++;
35372  line_width = 0;
35373  text_len++;
35374  glyphs++;
35375  row_begin = text_len;
35376  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
35377  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
35378  continue;
35379  }
35380 
35381  glyphs++;
35382  text_len += glyph_len;
35383  line_width += (float)glyph_width;
35384 
35385  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
35386  glyph_width = font->width(font->userdata, font->height,
35387  text+text_len, glyph_len);
35388  continue;
35389  }
35390  text_size.y = (float)total_lines * row_height;
35391 
35392  /* handle case when cursor is at end of text buffer */
35393  if (!cursor_ptr && edit->cursor == edit->string.len) {
35394  cursor_pos.x = line_width;
35395  cursor_pos.y = text_size.y - row_height;
35396  }
35397  }
35398  {
35399  /* scrollbar */
35400  if (cursor_follow)
35401  {
35402  /* update scrollbar to follow cursor */
35403  if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
35404  /* horizontal scroll */
35405  const float scroll_increment = area.w * 0.25f;
35406  if (cursor_pos.x < edit->scrollbar.x)
35407  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
35408  if (cursor_pos.x >= edit->scrollbar.x + area.w)
35409  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - area.w + scroll_increment);
35410  } else edit->scrollbar.x = 0;
35411 
35412  if (flags & NK_EDIT_MULTILINE) {
35413  /* vertical scroll */
35414  if (cursor_pos.y < edit->scrollbar.y)
35415  edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
35416  if (cursor_pos.y >= edit->scrollbar.y + row_height)
35417  edit->scrollbar.y = edit->scrollbar.y + row_height;
35418  } else edit->scrollbar.y = 0;
35419  }
35420 
35421  /* scrollbar widget */
35422  if (flags & NK_EDIT_MULTILINE)
35423  {
35424  nk_flags ws;
35425  struct nk_rect scroll;
35426  float scroll_target;
35427  float scroll_offset;
35428  float scroll_step;
35429  float scroll_inc;
35430 
35431  scroll = area;
35432  scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
35433  scroll.w = style->scrollbar_size.x;
35434 
35435  scroll_offset = edit->scrollbar.y;
35436  scroll_step = scroll.h * 0.10f;
35437  scroll_inc = scroll.h * 0.01f;
35438  scroll_target = text_size.y;
35439  edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
35440  scroll_offset, scroll_target, scroll_step, scroll_inc,
35441  &style->scrollbar, in, font);
35442  }
35443  }
35444 
35445  /* draw text */
35446  {struct nk_color background_color;
35447  struct nk_color text_color;
35448  struct nk_color sel_background_color;
35449  struct nk_color sel_text_color;
35450  struct nk_color cursor_color;
35451  struct nk_color cursor_text_color;
35452  const struct nk_style_item *background;
35453  nk_push_scissor(out, clip);
35454 
35455  /* select correct colors to draw */
35456  if (*state & NK_WIDGET_STATE_ACTIVED) {
35457  background = &style->active;
35458  text_color = style->text_active;
35459  sel_text_color = style->selected_text_hover;
35460  sel_background_color = style->selected_hover;
35461  cursor_color = style->cursor_hover;
35462  cursor_text_color = style->cursor_text_hover;
35463  } else if (*state & NK_WIDGET_STATE_HOVER) {
35464  background = &style->hover;
35465  text_color = style->text_hover;
35466  sel_text_color = style->selected_text_hover;
35467  sel_background_color = style->selected_hover;
35468  cursor_text_color = style->cursor_text_hover;
35469  cursor_color = style->cursor_hover;
35470  } else {
35471  background = &style->normal;
35472  text_color = style->text_normal;
35473  sel_text_color = style->selected_text_normal;
35474  sel_background_color = style->selected_normal;
35475  cursor_color = style->cursor_normal;
35476  cursor_text_color = style->cursor_text_normal;
35477  }
35478  if (background->type == NK_STYLE_ITEM_IMAGE)
35479  background_color = nk_rgba(0,0,0,0);
35480  else
35481  background_color = background->data.color;
35482 
35483  cursor_color = nk_rgb_factor(cursor_color, style->color_factor);
35484  cursor_text_color = nk_rgb_factor(cursor_text_color, style->color_factor);
35485 
35486  if (edit->select_start == edit->select_end) {
35487  /* no selection so just draw the complete text */
35488  const char *begin = nk_str_get_const(&edit->string);
35489  int l = nk_str_len_char(&edit->string);
35490  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
35491  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
35492  background_color, text_color, nk_false);
35493  } else {
35494  /* edit has selection so draw 1-3 text chunks */
35495  if (edit->select_start != edit->select_end && selection_begin > 0){
35496  /* draw unselected text before selection */
35497  const char *begin = nk_str_get_const(&edit->string);
35498  NK_ASSERT(select_begin_ptr);
35499  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
35500  area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
35501  row_height, font, background_color, text_color, nk_false);
35502  }
35503  if (edit->select_start != edit->select_end) {
35504  /* draw selected text */
35505  NK_ASSERT(select_begin_ptr);
35506  if (!select_end_ptr) {
35507  const char *begin = nk_str_get_const(&edit->string);
35508  select_end_ptr = begin + nk_str_len_char(&edit->string);
35509  }
35510  nk_edit_draw_text(out, style,
35511  area.x - edit->scrollbar.x,
35512  area.y + selection_offset_start.y - edit->scrollbar.y,
35513  selection_offset_start.x,
35514  select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
35515  row_height, font, sel_background_color, sel_text_color, nk_true);
35516  }
35517  if ((edit->select_start != edit->select_end &&
35518  selection_end < edit->string.len))
35519  {
35520  /* draw unselected text after selected text */
35521  const char *begin = select_end_ptr;
35522  const char *end = nk_str_get_const(&edit->string) +
35523  nk_str_len_char(&edit->string);
35524  NK_ASSERT(select_end_ptr);
35525  nk_edit_draw_text(out, style,
35526  area.x - edit->scrollbar.x,
35527  area.y + selection_offset_end.y - edit->scrollbar.y,
35528  selection_offset_end.x,
35529  begin, (int)(end - begin), row_height, font,
35530  background_color, text_color, nk_true);
35531  }
35532  }
35533 
35534  /* cursor */
35535  if (edit->select_start == edit->select_end)
35536  {
35537  if (edit->cursor >= nk_str_len(&edit->string) ||
35538  (cursor_ptr && *cursor_ptr == '\n')) {
35539  /* draw cursor at end of line */
35540  struct nk_rect cursor;
35541  cursor.w = style->cursor_size;
35542  cursor.h = font->height;
35543  cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
35544  cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
35545  cursor.y -= edit->scrollbar.y;
35546  nk_fill_rect(out, cursor, 0, cursor_color);
35547  } else {
35548  /* draw cursor inside text */
35549  int glyph_len;
35550  struct nk_rect label;
35551  struct nk_text txt;
35552 
35553  nk_rune unicode;
35554  NK_ASSERT(cursor_ptr);
35555  glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
35556 
35557  label.x = area.x + cursor_pos.x - edit->scrollbar.x;
35558  label.y = area.y + cursor_pos.y - edit->scrollbar.y;
35559  label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
35560  label.h = row_height;
35561 
35562  txt.padding = nk_vec2(0,0);
35563  txt.background = cursor_color;;
35564  txt.text = cursor_text_color;
35565  nk_fill_rect(out, label, 0, cursor_color);
35566  nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
35567  }
35568  }}
35569  } else {
35570  /* not active so just draw text */
35571  int l = nk_str_len_char(&edit->string);
35572  const char *begin = nk_str_get_const(&edit->string);
35573 
35574  const struct nk_style_item *background;
35575  struct nk_color background_color;
35576  struct nk_color text_color;
35577  nk_push_scissor(out, clip);
35578  if (*state & NK_WIDGET_STATE_ACTIVED) {
35579  background = &style->active;
35580  text_color = style->text_active;
35581  } else if (*state & NK_WIDGET_STATE_HOVER) {
35582  background = &style->hover;
35583  text_color = style->text_hover;
35584  } else {
35585  background = &style->normal;
35586  text_color = style->text_normal;
35587  }
35588  if (background->type == NK_STYLE_ITEM_IMAGE)
35589  background_color = nk_rgba(0,0,0,0);
35590  else
35591  background_color = background->data.color;
35592 
35593  background_color = nk_rgb_factor(background_color, style->color_factor);
35594  text_color = nk_rgb_factor(text_color, style->color_factor);
35595 
35596  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
35597  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
35598  background_color, text_color, nk_false);
35599  }
35600  nk_push_scissor(out, old_clip);}
35601  return ret;
35602 }
35614 NK_API void
35615 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
35616 {
35617  nk_hash hash;
35618  struct nk_window *win;
35619 
35620  NK_ASSERT(ctx);
35621  NK_ASSERT(ctx->current);
35622  if (!ctx || !ctx->current) return;
35623 
35624  win = ctx->current;
35625  hash = win->edit.seq;
35626  win->edit.active = nk_true;
35627  win->edit.name = hash;
35628  if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
35629  win->edit.mode = NK_TEXT_EDIT_MODE_INSERT;
35630 }
35641 NK_API void
35642 nk_edit_unfocus(struct nk_context *ctx)
35643 {
35644  struct nk_window *win;
35645  NK_ASSERT(ctx);
35646  NK_ASSERT(ctx->current);
35647  if (!ctx || !ctx->current) return;
35648 
35649  win = ctx->current;
35650  win->edit.active = nk_false;
35651  win->edit.name = 0;
35652 }
35664 NK_API nk_flags
35665 nk_edit_string(struct nk_context *ctx, nk_flags flags,
35666  char *memory, int *len, int max, nk_plugin_filter filter)
35667 {
35668  nk_hash hash;
35669  nk_flags state;
35670  struct nk_text_edit *edit;
35671  struct nk_window *win;
35672 
35673  NK_ASSERT(ctx);
35674  NK_ASSERT(memory);
35675  NK_ASSERT(len);
35676  if (!ctx || !memory || !len)
35677  return 0;
35678 
35679  filter = (!filter) ? nk_filter_default: filter;
35680  win = ctx->current;
35681  hash = win->edit.seq;
35682  edit = &ctx->text_edit;
35683  nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
35684  NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter);
35685 
35686  if (win->edit.active && hash == win->edit.name) {
35687  if (flags & NK_EDIT_NO_CURSOR)
35688  edit->cursor = nk_utf_len(memory, *len);
35689  else edit->cursor = win->edit.cursor;
35690  if (!(flags & NK_EDIT_SELECTABLE)) {
35691  edit->select_start = win->edit.cursor;
35692  edit->select_end = win->edit.cursor;
35693  } else {
35694  edit->select_start = win->edit.sel_start;
35695  edit->select_end = win->edit.sel_end;
35696  }
35697  edit->mode = win->edit.mode;
35698  edit->scrollbar.x = (float)win->edit.scrollbar.x;
35699  edit->scrollbar.y = (float)win->edit.scrollbar.y;
35700  edit->active = nk_true;
35701  } else edit->active = nk_false;
35702 
35703  max = NK_MAX(1, max);
35704  *len = NK_MIN(*len, max-1);
35705  nk_str_init_fixed(&edit->string, memory, (nk_size)max);
35706  edit->string.buffer.allocated = (nk_size)*len;
35707  edit->string.len = nk_utf_len(memory, *len);
35708  state = nk_edit_buffer(ctx, flags, edit, filter);
35709  *len = (int)edit->string.buffer.allocated;
35710 
35711  if (edit->active) {
35712  win->edit.cursor = edit->cursor;
35713  win->edit.sel_start = edit->select_start;
35714  win->edit.sel_end = edit->select_end;
35715  win->edit.mode = edit->mode;
35716  win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x;
35717  win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y;
35718  } return state;
35719 }
35731 NK_API nk_flags
35732 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
35733  struct nk_text_edit *edit, nk_plugin_filter filter)
35734 {
35735  struct nk_window *win;
35736  struct nk_style *style;
35737  struct nk_input *in;
35738 
35739  enum nk_widget_layout_states state;
35740  struct nk_rect bounds;
35741 
35742  nk_flags ret_flags = 0;
35743  unsigned char prev_state;
35744  nk_hash hash;
35745 
35746  /* make sure correct values */
35747  NK_ASSERT(ctx);
35748  NK_ASSERT(edit);
35749  NK_ASSERT(ctx->current);
35750  NK_ASSERT(ctx->current->layout);
35751  if (!ctx || !ctx->current || !ctx->current->layout)
35752  return 0;
35753 
35754  win = ctx->current;
35755  style = &ctx->style;
35756  state = nk_widget(&bounds, ctx);
35757  if (!state) return state;
35758  else if (state == NK_WIDGET_DISABLED)
35759  flags |= NK_EDIT_READ_ONLY;
35760  in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
35761 
35762  /* check if edit is currently hot item */
35763  hash = win->edit.seq++;
35764  if (win->edit.active && hash == win->edit.name) {
35765  if (flags & NK_EDIT_NO_CURSOR)
35766  edit->cursor = edit->string.len;
35767  if (!(flags & NK_EDIT_SELECTABLE)) {
35768  edit->select_start = edit->cursor;
35769  edit->select_end = edit->cursor;
35770  }
35771  if (flags & NK_EDIT_CLIPBOARD)
35772  edit->clip = ctx->clip;
35773  edit->active = (unsigned char)win->edit.active;
35774  } else edit->active = nk_false;
35775  edit->mode = win->edit.mode;
35776 
35777  filter = (!filter) ? nk_filter_default: filter;
35778  prev_state = (unsigned char)edit->active;
35779  in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
35780  ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
35781  filter, edit, &style->edit, in, style->font);
35782 
35783  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
35784  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT];
35785  if (edit->active && prev_state != edit->active) {
35786  /* current edit is now hot */
35787  win->edit.active = nk_true;
35788  win->edit.name = hash;
35789  } else if (prev_state && !edit->active) {
35790  /* current edit is now cold */
35791  win->edit.active = nk_false;
35792  } return ret_flags;
35793 }
35805 NK_API nk_flags
35806 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
35807  char *buffer, int max, nk_plugin_filter filter)
35808 {
35809  nk_flags result;
35810  int len = nk_strlen(buffer);
35811  result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
35812  buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
35813  return result;
35814 }
35815 
35816 
35817 
35818 
35819 
35820 /* ===============================================================
35821  *
35822  * PROPERTY
35823  *
35824  * ===============================================================*/
35836 NK_LIB void
35837 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
35838  struct nk_rect drag, struct nk_property_variant *variant,
35839  float inc_per_pixel)
35840 {
35841  int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
35842  int left_mouse_click_in_cursor = in &&
35843  nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true);
35844 
35845  nk_widget_state_reset(state);
35846  if (nk_input_is_mouse_hovering_rect(in, drag))
35847  *state = NK_WIDGET_STATE_HOVERED;
35848 
35849  if (left_mouse_down && left_mouse_click_in_cursor) {
35850  float delta, pixels;
35851  pixels = in->mouse.delta.x;
35852  delta = pixels * inc_per_pixel;
35853  switch (variant->kind) {
35854  default: break;
35855  case NK_PROPERTY_INT:
35856  variant->value.i = variant->value.i + (int)delta;
35857  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
35858  break;
35859  case NK_PROPERTY_FLOAT:
35860  variant->value.f = variant->value.f + (float)delta;
35861  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
35862  break;
35863  case NK_PROPERTY_DOUBLE:
35864  variant->value.d = variant->value.d + (double)delta;
35865  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
35866  break;
35867  }
35868  *state = NK_WIDGET_STATE_ACTIVE;
35869  }
35870  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
35871  *state |= NK_WIDGET_STATE_ENTERED;
35872  else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
35873  *state |= NK_WIDGET_STATE_LEFT;
35874 }
35886 NK_LIB void
35887 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
35888  struct nk_rect property, struct nk_rect label, struct nk_rect edit,
35889  struct nk_rect empty, int *state, struct nk_property_variant *variant,
35890  float inc_per_pixel)
35891 {
35892  nk_widget_state_reset(ws);
35893  if (in && *state == NK_PROPERTY_DEFAULT) {
35894  if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
35895  *state = NK_PROPERTY_EDIT;
35896  else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true))
35897  *state = NK_PROPERTY_DRAG;
35898  else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true))
35899  *state = NK_PROPERTY_DRAG;
35900  }
35901  if (*state == NK_PROPERTY_DRAG) {
35902  nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
35903  if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
35904  }
35905 }
35917 NK_LIB void
35918 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
35919  const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
35920  const char *name, int len, const struct nk_user_font *font)
35921 {
35922  struct nk_text text;
35923  const struct nk_style_item *background;
35924 
35925  /* select correct background and text color */
35926  if (state & NK_WIDGET_STATE_ACTIVED) {
35927  background = &style->active;
35928  text.text = style->label_active;
35929  } else if (state & NK_WIDGET_STATE_HOVER) {
35930  background = &style->hover;
35931  text.text = style->label_hover;
35932  } else {
35933  background = &style->normal;
35934  text.text = style->label_normal;
35935  }
35936 
35937  text.text = nk_rgb_factor(text.text, style->color_factor);
35938 
35939  /* draw background */
35940  switch(background->type) {
35941  case NK_STYLE_ITEM_IMAGE:
35942  text.background = nk_rgba(0, 0, 0, 0);
35943  nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
35944  break;
35945  case NK_STYLE_ITEM_NINE_SLICE:
35946  text.background = nk_rgba(0, 0, 0, 0);
35947  nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
35948  break;
35949  case NK_STYLE_ITEM_COLOR:
35950  text.background = background->data.color;
35951  nk_fill_rect(out, *bounds, style->rounding, nk_rgb_factor(background->data.color, style->color_factor));
35952  nk_stroke_rect(out, *bounds, style->rounding, style->border, nk_rgb_factor(background->data.color, style->color_factor));
35953  break;
35954  }
35955 
35956  /* draw label */
35957  text.padding = nk_vec2(0,0);
35958  if (name && name[0] != '#') {
35959  nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
35960  }
35961 }
35972 NK_LIB void
35973 nk_do_property(nk_flags *ws,
35974  struct nk_command_buffer *out, struct nk_rect property,
35975  const char *name, struct nk_property_variant *variant,
35976  float inc_per_pixel, char *buffer, int *len,
35977  int *state, int *cursor, int *select_begin, int *select_end,
35978  const struct nk_style_property *style,
35979  enum nk_property_filter filter, struct nk_input *in,
35980  const struct nk_user_font *font, struct nk_text_edit *text_edit,
35981  enum nk_button_behavior behavior)
35982 {
35983  const nk_plugin_filter filters[] = {
35984  nk_filter_decimal,
35985  nk_filter_float
35986  };
35987  nk_bool active, old;
35988  int num_len = 0, name_len = 0;
35989  char string[NK_MAX_NUMBER_BUFFER];
35990  float size;
35991 
35992  char *dst = 0;
35993  int *length;
35994 
35995  struct nk_rect left;
35996  struct nk_rect right;
35997  struct nk_rect label;
35998  struct nk_rect edit;
35999  struct nk_rect empty;
36000 
36001  /* left decrement button */
36002  left.h = font->height/2;
36003  left.w = left.h;
36004  left.x = property.x + style->border + style->padding.x;
36005  left.y = property.y + style->border + property.h/2.0f - left.h/2;
36006 
36007  /* text label */
36008  if (name && name[0] != '#') {
36009  name_len = nk_strlen(name);
36010  }
36011  size = font->width(font->userdata, font->height, name, name_len);
36012  label.x = left.x + left.w + style->padding.x;
36013  label.w = (float)size + 2 * style->padding.x;
36014  label.y = property.y + style->border + style->padding.y;
36015  label.h = property.h - (2 * style->border + 2 * style->padding.y);
36016 
36017  /* right increment button */
36018  right.y = left.y;
36019  right.w = left.w;
36020  right.h = left.h;
36021  right.x = property.x + property.w - (right.w + style->padding.x);
36022 
36023  /* edit */
36024  if (*state == NK_PROPERTY_EDIT) {
36025  size = font->width(font->userdata, font->height, buffer, *len);
36026  size += style->edit.cursor_size;
36027  length = len;
36028  dst = buffer;
36029  } else {
36030  switch (variant->kind) {
36031  default: break;
36032  case NK_PROPERTY_INT:
36033  nk_itoa(string, variant->value.i);
36034  num_len = nk_strlen(string);
36035  break;
36036  case NK_PROPERTY_FLOAT:
36037  NK_DTOA(string, (double)variant->value.f);
36038  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
36039  break;
36040  case NK_PROPERTY_DOUBLE:
36041  NK_DTOA(string, variant->value.d);
36042  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
36043  break;
36044  }
36045  size = font->width(font->userdata, font->height, string, num_len);
36046  dst = string;
36047  length = &num_len;
36048  }
36049 
36050  edit.w = (float)size + 2 * style->padding.x;
36051  edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
36052  edit.x = right.x - (edit.w + style->padding.x);
36053  edit.y = property.y + style->border;
36054  edit.h = property.h - (2 * style->border);
36055 
36056  /* empty left space activator */
36057  empty.w = edit.x - (label.x + label.w);
36058  empty.x = label.x + label.w;
36059  empty.y = property.y;
36060  empty.h = property.h;
36061 
36062  /* update property */
36063  old = (*state == NK_PROPERTY_EDIT);
36064  nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
36065 
36066  /* draw property */
36067  if (style->draw_begin) style->draw_begin(out, style->userdata);
36068  nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
36069  if (style->draw_end) style->draw_end(out, style->userdata);
36070 
36071  /* execute right button */
36072  if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
36073  switch (variant->kind) {
36074  default: break;
36075  case NK_PROPERTY_INT:
36076  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
36077  case NK_PROPERTY_FLOAT:
36078  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
36079  case NK_PROPERTY_DOUBLE:
36080  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
36081  }
36082  }
36083  /* execute left button */
36084  if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
36085  switch (variant->kind) {
36086  default: break;
36087  case NK_PROPERTY_INT:
36088  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
36089  case NK_PROPERTY_FLOAT:
36090  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
36091  case NK_PROPERTY_DOUBLE:
36092  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
36093  }
36094  }
36095  if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
36096  /* property has been activated so setup buffer */
36097  NK_MEMCPY(buffer, dst, (nk_size)*length);
36098  *cursor = nk_utf_len(buffer, *length);
36099  *len = *length;
36100  length = len;
36101  dst = buffer;
36102  active = 0;
36103  } else active = (*state == NK_PROPERTY_EDIT);
36104 
36105  /* execute and run text edit field */
36106  nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
36107  text_edit->active = (unsigned char)active;
36108  text_edit->string.len = *length;
36109  text_edit->cursor = NK_CLAMP(0, *cursor, *length);
36110  text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
36111  text_edit->select_end = NK_CLAMP(0,*select_end, *length);
36112  text_edit->string.buffer.allocated = (nk_size)*length;
36113  text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER;
36114  text_edit->string.buffer.memory.ptr = dst;
36115  text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
36116  text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
36117  nk_do_edit(ws, out, edit, (int)NK_EDIT_FIELD|(int)NK_EDIT_AUTO_SELECT,
36118  filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
36119 
36120  *length = text_edit->string.len;
36121  *cursor = text_edit->cursor;
36122  *select_begin = text_edit->select_start;
36123  *select_end = text_edit->select_end;
36124  if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
36125  text_edit->active = nk_false;
36126 
36127  if (active && !text_edit->active) {
36128  /* property is now not active so convert edit text to value*/
36129  *state = NK_PROPERTY_DEFAULT;
36130  buffer[*len] = '\0';
36131  switch (variant->kind) {
36132  default: break;
36133  case NK_PROPERTY_INT:
36134  variant->value.i = nk_strtoi(buffer, 0);
36135  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
36136  break;
36137  case NK_PROPERTY_FLOAT:
36138  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
36139  variant->value.f = nk_strtof(buffer, 0);
36140  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
36141  break;
36142  case NK_PROPERTY_DOUBLE:
36143  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
36144  variant->value.d = nk_strtod(buffer, 0);
36145  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
36146  break;
36147  }
36148  }
36149 }
36163 NK_LIB struct nk_property_variant
36164 nk_property_variant_int(int value, int min_value, int max_value, int step)
36165 {
36166  struct nk_property_variant result;
36167  result.kind = NK_PROPERTY_INT;
36168  result.value.i = value;
36169  result.min_value.i = min_value;
36170  result.max_value.i = max_value;
36171  result.step.i = step;
36172  return result;
36173 }
36187 NK_LIB struct nk_property_variant
36188 nk_property_variant_float(float value, float min_value, float max_value, float step)
36189 {
36190  struct nk_property_variant result;
36191  result.kind = NK_PROPERTY_FLOAT;
36192  result.value.f = value;
36193  result.min_value.f = min_value;
36194  result.max_value.f = max_value;
36195  result.step.f = step;
36196  return result;
36197 }
36210 NK_LIB struct nk_property_variant
36211 nk_property_variant_double(double value, double min_value, double max_value,
36212  double step)
36213 {
36214  struct nk_property_variant result;
36215  result.kind = NK_PROPERTY_DOUBLE;
36216  result.value.d = value;
36217  result.min_value.d = min_value;
36218  result.max_value.d = max_value;
36219  result.step.d = step;
36220  return result;
36221 }
36234 NK_LIB void
36235 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
36236  float inc_per_pixel, const enum nk_property_filter filter)
36237 {
36238  struct nk_window *win;
36239  struct nk_panel *layout;
36240  struct nk_input *in;
36241  const struct nk_style *style;
36242 
36243  struct nk_rect bounds;
36244  enum nk_widget_layout_states s;
36245 
36246  int *state = 0;
36247  nk_hash hash = 0;
36248  char *buffer = 0;
36249  int *len = 0;
36250  int *cursor = 0;
36251  int *select_begin = 0;
36252  int *select_end = 0;
36253  int old_state;
36254 
36255  char dummy_buffer[NK_MAX_NUMBER_BUFFER];
36256  int dummy_state = NK_PROPERTY_DEFAULT;
36257  int dummy_length = 0;
36258  int dummy_cursor = 0;
36259  int dummy_select_begin = 0;
36260  int dummy_select_end = 0;
36261 
36262  NK_ASSERT(ctx);
36263  NK_ASSERT(ctx->current);
36264  NK_ASSERT(ctx->current->layout);
36265  if (!ctx || !ctx->current || !ctx->current->layout)
36266  return;
36267 
36268  win = ctx->current;
36269  layout = win->layout;
36270  style = &ctx->style;
36271  s = nk_widget(&bounds, ctx);
36272  if (!s) return;
36273 
36274  /* calculate hash from name */
36275  if (name[0] == '#') {
36276  hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
36277  name++; /* special number hash */
36278  } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
36279 
36280  /* check if property is currently hot item */
36281  if (win->property.active && hash == win->property.name) {
36282  buffer = win->property.buffer;
36283  len = &win->property.length;
36284  cursor = &win->property.cursor;
36285  state = &win->property.state;
36286  select_begin = &win->property.select_start;
36287  select_end = &win->property.select_end;
36288  } else {
36289  buffer = dummy_buffer;
36290  len = &dummy_length;
36291  cursor = &dummy_cursor;
36292  state = &dummy_state;
36293  select_begin = &dummy_select_begin;
36294  select_end = &dummy_select_end;
36295  }
36296 
36297  /* execute property widget */
36298  old_state = *state;
36299  ctx->text_edit.clip = ctx->clip;
36300  in = ((s == NK_WIDGET_ROM && !win->property.active) ||
36301  layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED) ? 0 : &ctx->input;
36302  nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
36303  variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
36304  select_end, &style->property, filter, in, style->font, &ctx->text_edit,
36305  ctx->button_behavior);
36306 
36307  if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
36308  /* current property is now hot */
36309  win->property.active = 1;
36310  NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
36311  win->property.length = *len;
36312  win->property.cursor = *cursor;
36313  win->property.state = *state;
36314  win->property.name = hash;
36315  win->property.select_start = *select_begin;
36316  win->property.select_end = *select_end;
36317  if (*state == NK_PROPERTY_DRAG) {
36318  ctx->input.mouse.grab = nk_true;
36319  ctx->input.mouse.grabbed = nk_true;
36320  }
36321  }
36322  /* check if previously active property is now inactive */
36323  if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
36324  if (old_state == NK_PROPERTY_DRAG) {
36325  ctx->input.mouse.grab = nk_false;
36326  ctx->input.mouse.grabbed = nk_false;
36327  ctx->input.mouse.ungrab = nk_true;
36328  }
36329  win->property.select_start = 0;
36330  win->property.select_end = 0;
36331  win->property.active = 0;
36332  }
36333 }
36345 NK_API void
36346 nk_property_int(struct nk_context *ctx, const char *name,
36347  int min, int *val, int max, int step, float inc_per_pixel)
36348 {
36349  struct nk_property_variant variant;
36350  NK_ASSERT(ctx);
36351  NK_ASSERT(name);
36352  NK_ASSERT(val);
36353 
36354  if (!ctx || !ctx->current || !name || !val) return;
36355  variant = nk_property_variant_int(*val, min, max, step);
36356  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
36357  *val = variant.value.i;
36358 }
36370 NK_API void
36371 nk_property_float(struct nk_context *ctx, const char *name,
36372  float min, float *val, float max, float step, float inc_per_pixel)
36373 {
36374  struct nk_property_variant variant;
36375  NK_ASSERT(ctx);
36376  NK_ASSERT(name);
36377  NK_ASSERT(val);
36378 
36379  if (!ctx || !ctx->current || !name || !val) return;
36380  variant = nk_property_variant_float(*val, min, max, step);
36381  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
36382  *val = variant.value.f;
36383 }
36395 NK_API void
36396 nk_property_double(struct nk_context *ctx, const char *name,
36397  double min, double *val, double max, double step, float inc_per_pixel)
36398 {
36399  struct nk_property_variant variant;
36400  NK_ASSERT(ctx);
36401  NK_ASSERT(name);
36402  NK_ASSERT(val);
36403 
36404  if (!ctx || !ctx->current || !name || !val) return;
36405  variant = nk_property_variant_double(*val, min, max, step);
36406  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
36407  *val = variant.value.d;
36408 }
36422 NK_API int
36423 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
36424  int max, int step, float inc_per_pixel)
36425 {
36426  struct nk_property_variant variant;
36427  NK_ASSERT(ctx);
36428  NK_ASSERT(name);
36429 
36430  if (!ctx || !ctx->current || !name) return val;
36431  variant = nk_property_variant_int(val, min, max, step);
36432  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
36433  val = variant.value.i;
36434  return val;
36435 }
36448 NK_API float
36449 nk_propertyf(struct nk_context *ctx, const char *name, float min,
36450  float val, float max, float step, float inc_per_pixel)
36451 {
36452  struct nk_property_variant variant;
36453  NK_ASSERT(ctx);
36454  NK_ASSERT(name);
36455 
36456  if (!ctx || !ctx->current || !name) return val;
36457  variant = nk_property_variant_float(val, min, max, step);
36458  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
36459  val = variant.value.f;
36460  return val;
36461 }
36474 NK_API double
36475 nk_propertyd(struct nk_context *ctx, const char *name, double min,
36476  double val, double max, double step, float inc_per_pixel)
36477 {
36478  struct nk_property_variant variant;
36479  NK_ASSERT(ctx);
36480  NK_ASSERT(name);
36481 
36482  if (!ctx || !ctx->current || !name) return val;
36483  variant = nk_property_variant_double(val, min, max, step);
36484  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
36485  val = variant.value.d;
36486  return val;
36487 }
36488 
36489 
36490 
36491 
36492 
36493 /* ==============================================================
36494  *
36495  * CHART
36496  *
36497  * ===============================================================*/
36509 NK_API nk_bool
36510 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
36511  struct nk_color color, struct nk_color highlight,
36512  int count, float min_value, float max_value)
36513 {
36514  struct nk_window *win;
36515  struct nk_chart *chart;
36516  const struct nk_style *config;
36517  const struct nk_style_chart *style;
36518 
36519  const struct nk_style_item *background;
36520  struct nk_rect bounds = {0, 0, 0, 0};
36521 
36522  NK_ASSERT(ctx);
36523  NK_ASSERT(ctx->current);
36524  NK_ASSERT(ctx->current->layout);
36525 
36526  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
36527  if (!nk_widget(&bounds, ctx)) {
36528  chart = &ctx->current->layout->chart;
36529  nk_zero(chart, sizeof(*chart));
36530  return 0;
36531  }
36532 
36533  win = ctx->current;
36534  config = &ctx->style;
36535  chart = &win->layout->chart;
36536  style = &config->chart;
36537 
36538  /* setup basic generic chart */
36539  nk_zero(chart, sizeof(*chart));
36540  chart->x = bounds.x + style->padding.x;
36541  chart->y = bounds.y + style->padding.y;
36542  chart->w = bounds.w - 2 * style->padding.x;
36543  chart->h = bounds.h - 2 * style->padding.y;
36544  chart->w = NK_MAX(chart->w, 2 * style->padding.x);
36545  chart->h = NK_MAX(chart->h, 2 * style->padding.y);
36546 
36547  /* add first slot into chart */
36548  {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
36549  slot->type = type;
36550  slot->count = count;
36551  slot->color = nk_rgb_factor(color, style->color_factor);
36552  slot->highlight = highlight;
36553  slot->min = NK_MIN(min_value, max_value);
36554  slot->max = NK_MAX(min_value, max_value);
36555  slot->range = slot->max - slot->min;
36556  slot->show_markers = style->show_markers;}
36557 
36558  /* draw chart background */
36559  background = &style->background;
36560 
36561  switch(background->type) {
36562  case NK_STYLE_ITEM_IMAGE:
36563  nk_draw_image(&win->buffer, bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
36564  break;
36565  case NK_STYLE_ITEM_NINE_SLICE:
36566  nk_draw_nine_slice(&win->buffer, bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
36567  break;
36568  case NK_STYLE_ITEM_COLOR:
36569  nk_fill_rect(&win->buffer, bounds, style->rounding, nk_rgb_factor(style->border_color, style->color_factor));
36570  nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
36571  style->rounding, nk_rgb_factor(style->background.data.color, style->color_factor));
36572  break;
36573  }
36574  return 1;
36575 }
36587 NK_API nk_bool
36588 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
36589  int count, float min_value, float max_value)
36590 {
36591  return nk_chart_begin_colored(ctx, type, ctx->style.chart.color,
36592  ctx->style.chart.selected_color, count, min_value, max_value);
36593 }
36605 NK_API void
36606 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
36607  struct nk_color color, struct nk_color highlight,
36608  int count, float min_value, float max_value)
36609 {
36610  const struct nk_style_chart* style;
36611 
36612  NK_ASSERT(ctx);
36613  NK_ASSERT(ctx->current);
36614  NK_ASSERT(ctx->current->layout);
36615  NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
36616  if (!ctx || !ctx->current || !ctx->current->layout) return;
36617  if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
36618 
36619  style = &ctx->style.chart;
36620 
36621  /* add another slot into the graph */
36622  {struct nk_chart *chart = &ctx->current->layout->chart;
36623  struct nk_chart_slot *slot = &chart->slots[chart->slot++];
36624  slot->type = type;
36625  slot->count = count;
36626  slot->color = nk_rgb_factor(color, style->color_factor);
36627  slot->highlight = highlight;
36628  slot->min = NK_MIN(min_value, max_value);
36629  slot->max = NK_MAX(min_value, max_value);
36630  slot->range = slot->max - slot->min;
36631  slot->show_markers = style->show_markers;}
36632 }
36644 NK_API void
36645 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
36646  int count, float min_value, float max_value)
36647 {
36648  nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color,
36649  ctx->style.chart.selected_color, count, min_value, max_value);
36650 }
36662 NK_INTERN nk_flags
36663 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
36664  struct nk_chart *g, float value, int slot)
36665 {
36666  struct nk_panel *layout = win->layout;
36667  const struct nk_input *i = ctx->current->widgets_disabled ? 0 : &ctx->input;
36668  struct nk_command_buffer *out = &win->buffer;
36669 
36670  nk_flags ret = 0;
36671  struct nk_vec2 cur;
36672  struct nk_rect bounds;
36673  struct nk_color color;
36674  float step;
36675  float range;
36676  float ratio;
36677 
36678  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
36679  step = g->w / (float)g->slots[slot].count;
36680  range = g->slots[slot].max - g->slots[slot].min;
36681  ratio = (value - g->slots[slot].min) / range;
36682 
36683  if (g->slots[slot].index == 0) {
36684  /* first data point does not have a connection */
36685  g->slots[slot].last.x = g->x;
36686  g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
36687 
36688  bounds.x = g->slots[slot].last.x - 2;
36689  bounds.y = g->slots[slot].last.y - 2;
36690  bounds.w = bounds.h = 4;
36691 
36692  color = g->slots[slot].color;
36693  if (!(layout->flags & NK_WINDOW_ROM) && i &&
36694  NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
36695  ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
36696  ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
36697  i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
36698  color = g->slots[slot].highlight;
36699  }
36700  if (g->slots[slot].show_markers) {
36701  nk_fill_rect(out, bounds, 0, color);
36702  }
36703  g->slots[slot].index += 1;
36704  return ret;
36705  }
36706 
36707  /* draw a line between the last data point and the new one */
36708  color = g->slots[slot].color;
36709  cur.x = g->x + (float)(step * (float)g->slots[slot].index);
36710  cur.y = (g->y + g->h) - (ratio * (float)g->h);
36711  nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
36712 
36713  bounds.x = cur.x - 3;
36714  bounds.y = cur.y - 3;
36715  bounds.w = bounds.h = 6;
36716 
36717  /* user selection of current data point */
36718  if (!(layout->flags & NK_WINDOW_ROM)) {
36719  if (nk_input_is_mouse_hovering_rect(i, bounds)) {
36720  ret = NK_CHART_HOVERING;
36721  ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
36722  i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
36723  color = g->slots[slot].highlight;
36724  }
36725  }
36726  if (g->slots[slot].show_markers) {
36727  nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
36728  }
36729 
36730  /* save current data point position */
36731  g->slots[slot].last.x = cur.x;
36732  g->slots[slot].last.y = cur.y;
36733  g->slots[slot].index += 1;
36734  return ret;
36735 }
36747 NK_INTERN nk_flags
36748 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
36749  struct nk_chart *chart, float value, int slot)
36750 {
36751  struct nk_command_buffer *out = &win->buffer;
36752  const struct nk_input *in = ctx->current->widgets_disabled ? 0 : &ctx->input;
36753  struct nk_panel *layout = win->layout;
36754 
36755  float ratio;
36756  nk_flags ret = 0;
36757  struct nk_color color;
36758  struct nk_rect item = {0,0,0,0};
36759 
36760  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
36761  if (chart->slots[slot].index >= chart->slots[slot].count)
36762  return nk_false;
36763  if (chart->slots[slot].count) {
36764  float padding = (float)(chart->slots[slot].count-1);
36765  item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
36766  }
36767 
36768  /* calculate bounds of current bar chart entry */
36769  color = chart->slots[slot].color;;
36770  item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
36771  if (value >= 0) {
36772  ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
36773  item.y = (chart->y + chart->h) - chart->h * ratio;
36774  } else {
36775  ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
36776  item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
36777  }
36778  item.x = chart->x + ((float)chart->slots[slot].index * item.w);
36779  item.x = item.x + ((float)chart->slots[slot].index);
36780 
36781  /* user chart bar selection */
36782  if (!(layout->flags & NK_WINDOW_ROM) && in &&
36783  NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
36784  ret = NK_CHART_HOVERING;
36785  ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
36786  in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
36787  color = chart->slots[slot].highlight;
36788  }
36789  nk_fill_rect(out, item, 0, color);
36790  chart->slots[slot].index += 1;
36791  return ret;
36792 }
36805 NK_API nk_flags
36806 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
36807 {
36808  nk_flags flags;
36809  struct nk_window *win;
36810 
36811  NK_ASSERT(ctx);
36812  NK_ASSERT(ctx->current);
36813  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
36814  NK_ASSERT(slot < ctx->current->layout->chart.slot);
36815  if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
36816  if (slot >= ctx->current->layout->chart.slot) return nk_false;
36817 
36818  win = ctx->current;
36819  if (win->layout->chart.slot < slot) return nk_false;
36820  switch (win->layout->chart.slots[slot].type) {
36821  case NK_CHART_LINES:
36822  flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
36823  case NK_CHART_COLUMN:
36824  flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
36825  default:
36826  case NK_CHART_MAX:
36827  flags = 0;
36828  }
36829  return flags;
36830 }
36842 NK_API nk_flags
36843 nk_chart_push(struct nk_context *ctx, float value)
36844 {
36845  return nk_chart_push_slot(ctx, value, 0);
36846 }
36857 NK_API void
36858 nk_chart_end(struct nk_context *ctx)
36859 {
36860  struct nk_window *win;
36861  struct nk_chart *chart;
36862 
36863  NK_ASSERT(ctx);
36864  NK_ASSERT(ctx->current);
36865  if (!ctx || !ctx->current)
36866  return;
36867 
36868  win = ctx->current;
36869  chart = &win->layout->chart;
36870  NK_MEMSET(chart, 0, sizeof(*chart));
36871  return;
36872 }
36885 NK_API void
36886 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
36887  int count, int offset)
36888 {
36889  int i = 0;
36890  float min_value;
36891  float max_value;
36892 
36893  NK_ASSERT(ctx);
36894  NK_ASSERT(values);
36895  if (!ctx || !values || !count) return;
36896 
36897  min_value = values[offset];
36898  max_value = values[offset];
36899  for (i = 0; i < count; ++i) {
36900  min_value = NK_MIN(values[i + offset], min_value);
36901  max_value = NK_MAX(values[i + offset], max_value);
36902  }
36903 
36904  if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
36905  for (i = 0; i < count; ++i)
36906  nk_chart_push(ctx, values[i + offset]);
36907  nk_chart_end(ctx);
36908  }
36909 }
36922 NK_API void
36923 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
36924  float(*value_getter)(void* user, int index), int count, int offset)
36925 {
36926  int i = 0;
36927  float min_value;
36928  float max_value;
36929 
36930  NK_ASSERT(ctx);
36931  NK_ASSERT(value_getter);
36932  if (!ctx || !value_getter || !count) return;
36933 
36934  max_value = min_value = value_getter(userdata, offset);
36935  for (i = 0; i < count; ++i) {
36936  float value = value_getter(userdata, i + offset);
36937  min_value = NK_MIN(value, min_value);
36938  max_value = NK_MAX(value, max_value);
36939  }
36940 
36941  if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
36942  for (i = 0; i < count; ++i)
36943  nk_chart_push(ctx, value_getter(userdata, i + offset));
36944  nk_chart_end(ctx);
36945  }
36946 }
36947 
36948 
36949 
36950 
36951 
36952 /* ==============================================================
36953  *
36954  * COLOR PICKER
36955  *
36956  * ===============================================================*/
36967 NK_LIB nk_bool
36968 nk_color_picker_behavior(nk_flags *state,
36969  const struct nk_rect *bounds, const struct nk_rect *matrix,
36970  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
36971  struct nk_colorf *color, const struct nk_input *in)
36972 {
36973  float hsva[4];
36974  nk_bool value_changed = 0;
36975  nk_bool hsv_changed = 0;
36976 
36977  NK_ASSERT(state);
36978  NK_ASSERT(matrix);
36979  NK_ASSERT(hue_bar);
36980  NK_ASSERT(color);
36981 
36982  /* color matrix */
36983  nk_colorf_hsva_fv(hsva, *color);
36984  if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
36985  hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
36986  hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
36987  value_changed = hsv_changed = 1;
36988  }
36989  /* hue bar */
36990  if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
36991  hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
36992  value_changed = hsv_changed = 1;
36993  }
36994  /* alpha bar */
36995  if (alpha_bar) {
36996  if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
36997  hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
36998  value_changed = 1;
36999  }
37000  }
37001  nk_widget_state_reset(state);
37002  if (hsv_changed) {
37003  *color = nk_hsva_colorfv(hsva);
37004  *state = NK_WIDGET_STATE_ACTIVE;
37005  }
37006  if (value_changed) {
37007  color->a = hsva[3];
37008  *state = NK_WIDGET_STATE_ACTIVE;
37009  }
37010  /* set color picker widget state */
37011  if (nk_input_is_mouse_hovering_rect(in, *bounds))
37012  *state = NK_WIDGET_STATE_HOVERED;
37013  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
37014  *state |= NK_WIDGET_STATE_ENTERED;
37015  else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
37016  *state |= NK_WIDGET_STATE_LEFT;
37017  return value_changed;
37018 }
37030 NK_LIB void
37031 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
37032  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
37033  struct nk_colorf col)
37034 {
37035  NK_STORAGE const struct nk_color black = {0,0,0,255};
37036  NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
37037  NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
37038 
37039  const float crosshair_size = 7.0f;
37040  struct nk_color temp;
37041  float hsva[4];
37042  float line_y;
37043  int i;
37044 
37045  NK_ASSERT(o);
37046  NK_ASSERT(matrix);
37047  NK_ASSERT(hue_bar);
37048 
37049  /* draw hue bar */
37050  nk_colorf_hsva_fv(hsva, col);
37051  for (i = 0; i < 6; ++i) {
37052  NK_GLOBAL const struct nk_color hue_colors[] = {
37053  {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255},
37054  {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}
37055  };
37056  nk_fill_rect_multi_color(o,
37057  nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
37058  hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
37059  hue_colors[i+1], hue_colors[i+1]);
37060  }
37061  line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
37062  nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
37063  line_y, 1, nk_rgb(255,255,255));
37064 
37065  /* draw alpha bar */
37066  if (alpha_bar) {
37067  float alpha = NK_SATURATE(col.a);
37068  line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f);
37069 
37070  nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
37071  nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
37072  line_y, 1, nk_rgb(255,255,255));
37073  }
37074 
37075  /* draw color matrix */
37076  temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
37077  nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
37078  nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
37079 
37080  /* draw cross-hair */
37081  {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
37082  p.x = (float)(int)(matrix->x + S * matrix->w);
37083  p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
37084  nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
37085  nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
37086  nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
37087  nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
37088 }
37099 NK_LIB nk_bool
37100 nk_do_color_picker(nk_flags *state,
37101  struct nk_command_buffer *out, struct nk_colorf *col,
37102  enum nk_color_format fmt, struct nk_rect bounds,
37103  struct nk_vec2 padding, const struct nk_input *in,
37104  const struct nk_user_font *font)
37105 {
37106  int ret = 0;
37107  struct nk_rect matrix;
37108  struct nk_rect hue_bar;
37109  struct nk_rect alpha_bar;
37110  float bar_w;
37111 
37112  NK_ASSERT(out);
37113  NK_ASSERT(col);
37114  NK_ASSERT(state);
37115  NK_ASSERT(font);
37116  if (!out || !col || !state || !font)
37117  return ret;
37118 
37119  bar_w = font->height;
37120  bounds.x += padding.x;
37121  bounds.y += padding.x;
37122  bounds.w -= 2 * padding.x;
37123  bounds.h -= 2 * padding.y;
37124 
37125  matrix.x = bounds.x;
37126  matrix.y = bounds.y;
37127  matrix.h = bounds.h;
37128  matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
37129 
37130  hue_bar.w = bar_w;
37131  hue_bar.y = bounds.y;
37132  hue_bar.h = matrix.h;
37133  hue_bar.x = matrix.x + matrix.w + padding.x;
37134 
37135  alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
37136  alpha_bar.y = bounds.y;
37137  alpha_bar.w = bar_w;
37138  alpha_bar.h = matrix.h;
37139 
37140  ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
37141  (fmt == NK_RGBA) ? &alpha_bar:0, col, in);
37142  nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col);
37143  return ret;
37144 }
37156 NK_API nk_bool
37157 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color,
37158  enum nk_color_format fmt)
37159 {
37160  struct nk_window *win;
37161  struct nk_panel *layout;
37162  const struct nk_style *config;
37163  const struct nk_input *in;
37164 
37165  enum nk_widget_layout_states state;
37166  struct nk_rect bounds;
37167 
37168  NK_ASSERT(ctx);
37169  NK_ASSERT(color);
37170  NK_ASSERT(ctx->current);
37171  NK_ASSERT(ctx->current->layout);
37172  if (!ctx || !ctx->current || !ctx->current->layout || !color)
37173  return 0;
37174 
37175  win = ctx->current;
37176  config = &ctx->style;
37177  layout = win->layout;
37178  state = nk_widget(&bounds, ctx);
37179  if (!state) return 0;
37180  in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
37181  return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
37182  nk_vec2(0,0), in, config->font);
37183 }
37195 NK_API struct nk_colorf
37196 nk_color_picker(struct nk_context *ctx, struct nk_colorf color,
37197  enum nk_color_format fmt)
37198 {
37199  nk_color_pick(ctx, &color, fmt);
37200  return color;
37201 }
37202 
37203 
37204 
37205 
37206 
37207 /* ==============================================================
37208  *
37209  * COMBO
37210  *
37211  * ===============================================================*/
37223 NK_INTERN nk_bool
37224 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
37225  struct nk_vec2 size, nk_bool is_clicked, struct nk_rect header)
37226 {
37227  struct nk_window *popup;
37228  int is_open = 0;
37229  int is_active = 0;
37230  struct nk_rect body;
37231  nk_hash hash;
37232 
37233  NK_ASSERT(ctx);
37234  NK_ASSERT(ctx->current);
37235  NK_ASSERT(ctx->current->layout);
37236  if (!ctx || !ctx->current || !ctx->current->layout)
37237  return 0;
37238 
37239  popup = win->popup.win;
37240  body.x = header.x;
37241  body.w = size.x;
37242  body.y = header.y + header.h-ctx->style.window.combo_border;
37243  body.h = size.y;
37244 
37245  hash = win->popup.combo_count++;
37246  is_open = (popup) ? nk_true:nk_false;
37247  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
37248  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
37249  (!is_open && !is_active && !is_clicked)) return 0;
37250  if (!nk_nonblock_begin(ctx, 0, body,
37251  (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
37252 
37253  win->popup.type = NK_PANEL_COMBO;
37254  win->popup.name = hash;
37255  return 1;
37256 }
37269 NK_API nk_bool
37270 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
37271  struct nk_vec2 size)
37272 {
37273  const struct nk_input *in;
37274  struct nk_window *win;
37275  struct nk_style *style;
37276 
37277  enum nk_widget_layout_states s;
37278  int is_clicked = nk_false;
37279  struct nk_rect header;
37280  const struct nk_style_item *background;
37281  struct nk_text text;
37282 
37283  NK_ASSERT(ctx);
37284  NK_ASSERT(selected);
37285  NK_ASSERT(ctx->current);
37286  NK_ASSERT(ctx->current->layout);
37287  if (!ctx || !ctx->current || !ctx->current->layout || !selected)
37288  return 0;
37289 
37290  win = ctx->current;
37291  style = &ctx->style;
37292  s = nk_widget(&header, ctx);
37293  if (s == NK_WIDGET_INVALID)
37294  return 0;
37295 
37296  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED || s == NK_WIDGET_ROM)? 0: &ctx->input;
37297  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
37298  is_clicked = nk_true;
37299 
37300  /* draw combo box header background and border */
37301  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
37302  background = &style->combo.active;
37303  text.text = style->combo.label_active;
37304  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
37305  background = &style->combo.hover;
37306  text.text = style->combo.label_hover;
37307  } else {
37308  background = &style->combo.normal;
37309  text.text = style->combo.label_normal;
37310  }
37311 
37312  text.text = nk_rgb_factor(text.text, style->combo.color_factor);
37313 
37314  switch(background->type) {
37315  case NK_STYLE_ITEM_IMAGE:
37316  text.background = nk_rgba(0, 0, 0, 0);
37317  nk_draw_image(&win->buffer, header, &background->data.image, nk_rgb_factor(nk_white, style->combo.color_factor));
37318  break;
37319  case NK_STYLE_ITEM_NINE_SLICE:
37320  text.background = nk_rgba(0, 0, 0, 0);
37321  nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_rgb_factor(nk_white, style->combo.color_factor));
37322  break;
37323  case NK_STYLE_ITEM_COLOR:
37324  text.background = background->data.color;
37325  nk_fill_rect(&win->buffer, header, style->combo.rounding, nk_rgb_factor(background->data.color, style->combo.color_factor));
37326  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, nk_rgb_factor(style->combo.border_color, style->combo.color_factor));
37327  break;
37328  }
37329  {
37330  /* print currently selected text item */
37331  struct nk_rect label;
37332  struct nk_rect button;
37333  struct nk_rect content;
37334  int draw_button_symbol;
37335 
37336  enum nk_symbol_type sym;
37337  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
37338  sym = style->combo.sym_hover;
37339  else if (is_clicked)
37340  sym = style->combo.sym_active;
37341  else
37342  sym = style->combo.sym_normal;
37343 
37344  /* represents whether or not the combo's button symbol should be drawn */
37345  draw_button_symbol = sym != NK_SYMBOL_NONE;
37346 
37347  /* calculate button */
37348  button.w = header.h - 2 * style->combo.button_padding.y;
37349  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
37350  button.y = header.y + style->combo.button_padding.y;
37351  button.h = button.w;
37352 
37353  content.x = button.x + style->combo.button.padding.x;
37354  content.y = button.y + style->combo.button.padding.y;
37355  content.w = button.w - 2 * style->combo.button.padding.x;
37356  content.h = button.h - 2 * style->combo.button.padding.y;
37357 
37358  /* draw selected label */
37359  text.padding = nk_vec2(0,0);
37360  label.x = header.x + style->combo.content_padding.x;
37361  label.y = header.y + style->combo.content_padding.y;
37362  label.h = header.h - 2 * style->combo.content_padding.y;
37363  if (draw_button_symbol)
37364  label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;
37365  else
37366  label.w = header.w - 2 * style->combo.content_padding.x;
37367  nk_widget_text(&win->buffer, label, selected, len, &text,
37368  NK_TEXT_LEFT, ctx->style.font);
37369 
37370  /* draw open/close button */
37371  if (draw_button_symbol)
37372  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
37373  &ctx->style.combo.button, sym, style->font);
37374  }
37375  return nk_combo_begin(ctx, win, size, is_clicked, header);
37376 }
37389 NK_API nk_bool
37390 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
37391 {
37392  return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);
37393 }
37406 NK_API nk_bool
37407 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
37408 {
37409  struct nk_window *win;
37410  struct nk_style *style;
37411  const struct nk_input *in;
37412 
37413  struct nk_rect header;
37414  int is_clicked = nk_false;
37415  enum nk_widget_layout_states s;
37416  const struct nk_style_item *background;
37417 
37418  NK_ASSERT(ctx);
37419  NK_ASSERT(ctx->current);
37420  NK_ASSERT(ctx->current->layout);
37421  if (!ctx || !ctx->current || !ctx->current->layout)
37422  return 0;
37423 
37424  win = ctx->current;
37425  style = &ctx->style;
37426  s = nk_widget(&header, ctx);
37427  if (s == NK_WIDGET_INVALID)
37428  return 0;
37429 
37430  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED || s == NK_WIDGET_ROM)? 0: &ctx->input;
37431  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
37432  is_clicked = nk_true;
37433 
37434  /* draw combo box header background and border */
37435  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
37436  background = &style->combo.active;
37437  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
37438  background = &style->combo.hover;
37439  else background = &style->combo.normal;
37440 
37441  switch(background->type) {
37442  case NK_STYLE_ITEM_IMAGE:
37443  nk_draw_image(&win->buffer, header, &background->data.image, nk_rgb_factor(nk_white, style->combo.color_factor));
37444  break;
37445  case NK_STYLE_ITEM_NINE_SLICE:
37446  nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_rgb_factor(nk_white, style->combo.color_factor));
37447  break;
37448  case NK_STYLE_ITEM_COLOR:
37449  nk_fill_rect(&win->buffer, header, style->combo.rounding, nk_rgb_factor(background->data.color, style->combo.color_factor));
37450  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, nk_rgb_factor(style->combo.border_color, style->combo.color_factor));
37451  break;
37452  }
37453  {
37454  struct nk_rect content;
37455  struct nk_rect button;
37456  struct nk_rect bounds;
37457  int draw_button_symbol;
37458 
37459  enum nk_symbol_type sym;
37460  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
37461  sym = style->combo.sym_hover;
37462  else if (is_clicked)
37463  sym = style->combo.sym_active;
37464  else sym = style->combo.sym_normal;
37465 
37466  /* represents whether or not the combo's button symbol should be drawn */
37467  draw_button_symbol = sym != NK_SYMBOL_NONE;
37468 
37469  /* calculate button */
37470  button.w = header.h - 2 * style->combo.button_padding.y;
37471  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
37472  button.y = header.y + style->combo.button_padding.y;
37473  button.h = button.w;
37474 
37475  content.x = button.x + style->combo.button.padding.x;
37476  content.y = button.y + style->combo.button.padding.y;
37477  content.w = button.w - 2 * style->combo.button.padding.x;
37478  content.h = button.h - 2 * style->combo.button.padding.y;
37479 
37480  /* draw color */
37481  bounds.h = header.h - 4 * style->combo.content_padding.y;
37482  bounds.y = header.y + 2 * style->combo.content_padding.y;
37483  bounds.x = header.x + 2 * style->combo.content_padding.x;
37484  if (draw_button_symbol)
37485  bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
37486  else
37487  bounds.w = header.w - 4 * style->combo.content_padding.x;
37488  nk_fill_rect(&win->buffer, bounds, 0, nk_rgb_factor(color, style->combo.color_factor));
37489 
37490  /* draw open/close button */
37491  if (draw_button_symbol)
37492  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
37493  &ctx->style.combo.button, sym, style->font);
37494  }
37495  return nk_combo_begin(ctx, win, size, is_clicked, header);
37496 }
37509 NK_API nk_bool
37510 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
37511 {
37512  struct nk_window *win;
37513  struct nk_style *style;
37514  const struct nk_input *in;
37515 
37516  struct nk_rect header;
37517  int is_clicked = nk_false;
37518  enum nk_widget_layout_states s;
37519  const struct nk_style_item *background;
37520  struct nk_color sym_background;
37521  struct nk_color symbol_color;
37522 
37523  NK_ASSERT(ctx);
37524  NK_ASSERT(ctx->current);
37525  NK_ASSERT(ctx->current->layout);
37526  if (!ctx || !ctx->current || !ctx->current->layout)
37527  return 0;
37528 
37529  win = ctx->current;
37530  style = &ctx->style;
37531  s = nk_widget(&header, ctx);
37532  if (s == NK_WIDGET_INVALID)
37533  return 0;
37534 
37535  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED || s == NK_WIDGET_ROM)? 0: &ctx->input;
37536  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
37537  is_clicked = nk_true;
37538 
37539  /* draw combo box header background and border */
37540  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
37541  background = &style->combo.active;
37542  symbol_color = style->combo.symbol_active;
37543  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
37544  background = &style->combo.hover;
37545  symbol_color = style->combo.symbol_hover;
37546  } else {
37547  background = &style->combo.normal;
37548  symbol_color = style->combo.symbol_hover;
37549  }
37550 
37551  symbol_color = nk_rgb_factor(symbol_color, style->combo.color_factor);
37552 
37553  switch(background->type) {
37554  case NK_STYLE_ITEM_IMAGE:
37555  sym_background = nk_rgba(0, 0, 0, 0);
37556  nk_draw_image(&win->buffer, header, &background->data.image, nk_rgb_factor(nk_white, style->combo.color_factor));
37557  break;
37558  case NK_STYLE_ITEM_NINE_SLICE:
37559  sym_background = nk_rgba(0, 0, 0, 0);
37560  nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_rgb_factor(nk_white, style->combo.color_factor));
37561  break;
37562  case NK_STYLE_ITEM_COLOR:
37563  sym_background = background->data.color;
37564  nk_fill_rect(&win->buffer, header, style->combo.rounding, nk_rgb_factor(background->data.color, style->combo.color_factor));
37565  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, nk_rgb_factor(style->combo.border_color, style->combo.color_factor));
37566  break;
37567  }
37568  {
37569  struct nk_rect bounds = {0,0,0,0};
37570  struct nk_rect content;
37571  struct nk_rect button;
37572 
37573  enum nk_symbol_type sym;
37574  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
37575  sym = style->combo.sym_hover;
37576  else if (is_clicked)
37577  sym = style->combo.sym_active;
37578  else sym = style->combo.sym_normal;
37579 
37580  /* calculate button */
37581  button.w = header.h - 2 * style->combo.button_padding.y;
37582  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
37583  button.y = header.y + style->combo.button_padding.y;
37584  button.h = button.w;
37585 
37586  content.x = button.x + style->combo.button.padding.x;
37587  content.y = button.y + style->combo.button.padding.y;
37588  content.w = button.w - 2 * style->combo.button.padding.x;
37589  content.h = button.h - 2 * style->combo.button.padding.y;
37590 
37591  /* draw symbol */
37592  bounds.h = header.h - 2 * style->combo.content_padding.y;
37593  bounds.y = header.y + style->combo.content_padding.y;
37594  bounds.x = header.x + style->combo.content_padding.x;
37595  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
37596  nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
37597  1.0f, style->font);
37598 
37599  /* draw open/close button */
37600  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
37601  &ctx->style.combo.button, sym, style->font);
37602  }
37603  return nk_combo_begin(ctx, win, size, is_clicked, header);
37604 }
37617 NK_API nk_bool
37618 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
37619  enum nk_symbol_type symbol, struct nk_vec2 size)
37620 {
37621  struct nk_window *win;
37622  struct nk_style *style;
37623  struct nk_input *in;
37624 
37625  struct nk_rect header;
37626  int is_clicked = nk_false;
37627  enum nk_widget_layout_states s;
37628  const struct nk_style_item *background;
37629  struct nk_color symbol_color;
37630  struct nk_text text;
37631 
37632  NK_ASSERT(ctx);
37633  NK_ASSERT(ctx->current);
37634  NK_ASSERT(ctx->current->layout);
37635  if (!ctx || !ctx->current || !ctx->current->layout)
37636  return 0;
37637 
37638  win = ctx->current;
37639  style = &ctx->style;
37640  s = nk_widget(&header, ctx);
37641  if (!s) return 0;
37642 
37643  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED || s == NK_WIDGET_ROM)? 0: &ctx->input;
37644  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
37645  is_clicked = nk_true;
37646 
37647  /* draw combo box header background and border */
37648  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
37649  background = &style->combo.active;
37650  symbol_color = style->combo.symbol_active;
37651  text.text = style->combo.label_active;
37652  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
37653  background = &style->combo.hover;
37654  symbol_color = style->combo.symbol_hover;
37655  text.text = style->combo.label_hover;
37656  } else {
37657  background = &style->combo.normal;
37658  symbol_color = style->combo.symbol_normal;
37659  text.text = style->combo.label_normal;
37660  }
37661 
37662  text.text = nk_rgb_factor(text.text, style->combo.color_factor);
37663  symbol_color = nk_rgb_factor(symbol_color, style->combo.color_factor);
37664 
37665  switch(background->type) {
37666  case NK_STYLE_ITEM_IMAGE:
37667  text.background = nk_rgba(0, 0, 0, 0);
37668  nk_draw_image(&win->buffer, header, &background->data.image, nk_rgb_factor(nk_white, style->combo.color_factor));
37669  break;
37670  case NK_STYLE_ITEM_NINE_SLICE:
37671  text.background = nk_rgba(0, 0, 0, 0);
37672  nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_rgb_factor(nk_white, style->combo.color_factor));
37673  break;
37674  case NK_STYLE_ITEM_COLOR:
37675  text.background = background->data.color;
37676  nk_fill_rect(&win->buffer, header, style->combo.rounding, nk_rgb_factor(background->data.color, style->combo.color_factor));
37677  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, nk_rgb_factor(style->combo.border_color, style->combo.color_factor));
37678  break;
37679  }
37680  {
37681  struct nk_rect content;
37682  struct nk_rect button;
37683  struct nk_rect label;
37684  struct nk_rect image;
37685 
37686  enum nk_symbol_type sym;
37687  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
37688  sym = style->combo.sym_hover;
37689  else if (is_clicked)
37690  sym = style->combo.sym_active;
37691  else sym = style->combo.sym_normal;
37692 
37693  /* calculate button */
37694  button.w = header.h - 2 * style->combo.button_padding.y;
37695  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
37696  button.y = header.y + style->combo.button_padding.y;
37697  button.h = button.w;
37698 
37699  content.x = button.x + style->combo.button.padding.x;
37700  content.y = button.y + style->combo.button.padding.y;
37701  content.w = button.w - 2 * style->combo.button.padding.x;
37702  content.h = button.h - 2 * style->combo.button.padding.y;
37703  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
37704  &ctx->style.combo.button, sym, style->font);
37705 
37706  /* draw symbol */
37707  image.x = header.x + style->combo.content_padding.x;
37708  image.y = header.y + style->combo.content_padding.y;
37709  image.h = header.h - 2 * style->combo.content_padding.y;
37710  image.w = image.h;
37711  nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
37712  1.0f, style->font);
37713 
37714  /* draw label */
37715  text.padding = nk_vec2(0,0);
37716  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
37717  label.y = header.y + style->combo.content_padding.y;
37718  label.w = (button.x - style->combo.content_padding.x) - label.x;
37719  label.h = header.h - 2 * style->combo.content_padding.y;
37720  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
37721  }
37722  return nk_combo_begin(ctx, win, size, is_clicked, header);
37723 }
37736 NK_API nk_bool
37737 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
37738 {
37739  struct nk_window *win;
37740  struct nk_style *style;
37741  const struct nk_input *in;
37742 
37743  struct nk_rect header;
37744  int is_clicked = nk_false;
37745  enum nk_widget_layout_states s;
37746  const struct nk_style_item *background;
37747 
37748  NK_ASSERT(ctx);
37749  NK_ASSERT(ctx->current);
37750  NK_ASSERT(ctx->current->layout);
37751  if (!ctx || !ctx->current || !ctx->current->layout)
37752  return 0;
37753 
37754  win = ctx->current;
37755  style = &ctx->style;
37756  s = nk_widget(&header, ctx);
37757  if (s == NK_WIDGET_INVALID)
37758  return 0;
37759 
37760  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED || s == NK_WIDGET_ROM)? 0: &ctx->input;
37761  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
37762  is_clicked = nk_true;
37763 
37764  /* draw combo box header background and border */
37765  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
37766  background = &style->combo.active;
37767  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
37768  background = &style->combo.hover;
37769  else background = &style->combo.normal;
37770 
37771  switch (background->type) {
37772  case NK_STYLE_ITEM_IMAGE:
37773  nk_draw_image(&win->buffer, header, &background->data.image, nk_rgb_factor(nk_white, style->combo.color_factor));
37774  break;
37775  case NK_STYLE_ITEM_NINE_SLICE:
37776  nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_rgb_factor(nk_white, style->combo.color_factor));
37777  break;
37778  case NK_STYLE_ITEM_COLOR:
37779  nk_fill_rect(&win->buffer, header, style->combo.rounding, nk_rgb_factor(background->data.color, style->combo.color_factor));
37780  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, nk_rgb_factor(style->combo.border_color, style->combo.color_factor));
37781  break;
37782  }
37783  {
37784  struct nk_rect bounds = {0,0,0,0};
37785  struct nk_rect content;
37786  struct nk_rect button;
37787  int draw_button_symbol;
37788 
37789  enum nk_symbol_type sym;
37790  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
37791  sym = style->combo.sym_hover;
37792  else if (is_clicked)
37793  sym = style->combo.sym_active;
37794  else sym = style->combo.sym_normal;
37795 
37796  /* represents whether or not the combo's button symbol should be drawn */
37797  draw_button_symbol = sym != NK_SYMBOL_NONE;
37798 
37799  /* calculate button */
37800  button.w = header.h - 2 * style->combo.button_padding.y;
37801  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
37802  button.y = header.y + style->combo.button_padding.y;
37803  button.h = button.w;
37804 
37805  content.x = button.x + style->combo.button.padding.x;
37806  content.y = button.y + style->combo.button.padding.y;
37807  content.w = button.w - 2 * style->combo.button.padding.x;
37808  content.h = button.h - 2 * style->combo.button.padding.y;
37809 
37810  /* draw image */
37811  bounds.h = header.h - 2 * style->combo.content_padding.y;
37812  bounds.y = header.y + style->combo.content_padding.y;
37813  bounds.x = header.x + style->combo.content_padding.x;
37814  if (draw_button_symbol)
37815  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
37816  else
37817  bounds.w = header.w - 2 * style->combo.content_padding.x;
37818  nk_draw_image(&win->buffer, bounds, &img, nk_rgb_factor(nk_white, style->combo.color_factor));
37819 
37820  /* draw open/close button */
37821  if (draw_button_symbol)
37822  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
37823  &ctx->style.combo.button, sym, style->font);
37824  }
37825  return nk_combo_begin(ctx, win, size, is_clicked, header);
37826 }
37839 NK_API nk_bool
37840 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
37841  struct nk_image img, struct nk_vec2 size)
37842 {
37843  struct nk_window *win;
37844  struct nk_style *style;
37845  struct nk_input *in;
37846 
37847  struct nk_rect header;
37848  int is_clicked = nk_false;
37849  enum nk_widget_layout_states s;
37850  const struct nk_style_item *background;
37851  struct nk_text text;
37852 
37853  NK_ASSERT(ctx);
37854  NK_ASSERT(ctx->current);
37855  NK_ASSERT(ctx->current->layout);
37856  if (!ctx || !ctx->current || !ctx->current->layout)
37857  return 0;
37858 
37859  win = ctx->current;
37860  style = &ctx->style;
37861  s = nk_widget(&header, ctx);
37862  if (!s) return 0;
37863 
37864  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED || s == NK_WIDGET_ROM)? 0: &ctx->input;
37865  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
37866  is_clicked = nk_true;
37867 
37868  /* draw combo box header background and border */
37869  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
37870  background = &style->combo.active;
37871  text.text = style->combo.label_active;
37872  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
37873  background = &style->combo.hover;
37874  text.text = style->combo.label_hover;
37875  } else {
37876  background = &style->combo.normal;
37877  text.text = style->combo.label_normal;
37878  }
37879 
37880  text.text = nk_rgb_factor(text.text, style->combo.color_factor);
37881 
37882  switch(background->type) {
37883  case NK_STYLE_ITEM_IMAGE:
37884  text.background = nk_rgba(0, 0, 0, 0);
37885  nk_draw_image(&win->buffer, header, &background->data.image, nk_rgb_factor(nk_white, style->combo.color_factor));
37886  break;
37887  case NK_STYLE_ITEM_NINE_SLICE:
37888  text.background = nk_rgba(0, 0, 0, 0);
37889  nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_rgb_factor(nk_white, style->combo.color_factor));
37890  break;
37891  case NK_STYLE_ITEM_COLOR:
37892  text.background = background->data.color;
37893  nk_fill_rect(&win->buffer, header, style->combo.rounding, nk_rgb_factor(background->data.color, style->combo.color_factor));
37894  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, nk_rgb_factor(style->combo.border_color, style->combo.color_factor));
37895  break;
37896  }
37897  {
37898  struct nk_rect content;
37899  struct nk_rect button;
37900  struct nk_rect label;
37901  struct nk_rect image;
37902  int draw_button_symbol;
37903 
37904  enum nk_symbol_type sym;
37905  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
37906  sym = style->combo.sym_hover;
37907  else if (is_clicked)
37908  sym = style->combo.sym_active;
37909  else sym = style->combo.sym_normal;
37910 
37911  /* represents whether or not the combo's button symbol should be drawn */
37912  draw_button_symbol = sym != NK_SYMBOL_NONE;
37913 
37914  /* calculate button */
37915  button.w = header.h - 2 * style->combo.button_padding.y;
37916  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
37917  button.y = header.y + style->combo.button_padding.y;
37918  button.h = button.w;
37919 
37920  content.x = button.x + style->combo.button.padding.x;
37921  content.y = button.y + style->combo.button.padding.y;
37922  content.w = button.w - 2 * style->combo.button.padding.x;
37923  content.h = button.h - 2 * style->combo.button.padding.y;
37924  if (draw_button_symbol)
37925  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
37926  &ctx->style.combo.button, sym, style->font);
37927 
37928  /* draw image */
37929  image.x = header.x + style->combo.content_padding.x;
37930  image.y = header.y + style->combo.content_padding.y;
37931  image.h = header.h - 2 * style->combo.content_padding.y;
37932  image.w = image.h;
37933  nk_draw_image(&win->buffer, image, &img, nk_rgb_factor(nk_white, style->combo.color_factor));
37934 
37935  /* draw label */
37936  text.padding = nk_vec2(0,0);
37937  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
37938  label.y = header.y + style->combo.content_padding.y;
37939  label.h = header.h - 2 * style->combo.content_padding.y;
37940  if (draw_button_symbol)
37941  label.w = (button.x - style->combo.content_padding.x) - label.x;
37942  else
37943  label.w = (header.x + header.w - style->combo.content_padding.x) - label.x;
37944  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
37945  }
37946  return nk_combo_begin(ctx, win, size, is_clicked, header);
37947 }
37958 NK_API nk_bool
37959 nk_combo_begin_symbol_label(struct nk_context *ctx,
37960  const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
37961 {
37962  return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);
37963 }
37974 NK_API nk_bool
37975 nk_combo_begin_image_label(struct nk_context *ctx,
37976  const char *selected, struct nk_image img, struct nk_vec2 size)
37977 {
37978  return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);
37979 }
37993 NK_API nk_bool
37994 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
37995 {
37996  return nk_contextual_item_text(ctx, text, len, align);
37997 }
38010 NK_API nk_bool
38011 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
38012 {
38013  return nk_contextual_item_label(ctx, label, align);
38014 }
38027 NK_API nk_bool
38028 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
38029  int len, nk_flags alignment)
38030 {
38031  return nk_contextual_item_image_text(ctx, img, text, len, alignment);
38032 }
38044 NK_API nk_bool
38045 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
38046  const char *text, nk_flags alignment)
38047 {
38048  return nk_contextual_item_image_label(ctx, img, text, alignment);
38049 }
38061 NK_API nk_bool
38062 nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
38063  const char *text, int len, nk_flags alignment)
38064 {
38065  return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);
38066 }
38078 NK_API nk_bool
38079 nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
38080  const char *label, nk_flags alignment)
38081 {
38082  return nk_contextual_item_symbol_label(ctx, sym, label, alignment);
38093 }
38094 NK_API void nk_combo_end(struct nk_context *ctx)
38095 {
38096  nk_contextual_end(ctx);
38107 }
38108 NK_API void nk_combo_close(struct nk_context *ctx)
38109 {
38110  nk_contextual_close(ctx);
38111 }
38124 NK_API int
38125 nk_combo(struct nk_context *ctx, const char *const *items, int count,
38126  int selected, int item_height, struct nk_vec2 size)
38127 {
38128  int i = 0;
38129  int max_height;
38130  struct nk_vec2 item_spacing;
38131  struct nk_vec2 window_padding;
38132 
38133  NK_ASSERT(ctx);
38134  NK_ASSERT(items);
38135  NK_ASSERT(ctx->current);
38136  if (!ctx || !items ||!count)
38137  return selected;
38138 
38139  item_spacing = ctx->style.window.spacing;
38140  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
38141  max_height = count * item_height + count * (int)item_spacing.y;
38142  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
38143  size.y = NK_MIN(size.y, (float)max_height);
38144  if (nk_combo_begin_label(ctx, items[selected], size)) {
38145  nk_layout_row_dynamic(ctx, (float)item_height, 1);
38146  for (i = 0; i < count; ++i) {
38147  if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
38148  selected = i;
38149  }
38150  nk_combo_end(ctx);
38151  }
38152  return selected;
38153 }
38165 NK_API int
38166 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
38167  int separator, int selected, int count, int item_height, struct nk_vec2 size)
38168 {
38169  int i;
38170  int max_height;
38171  struct nk_vec2 item_spacing;
38172  struct nk_vec2 window_padding;
38173  const char *current_item;
38174  const char *iter;
38175  int length = 0;
38176 
38177  NK_ASSERT(ctx);
38178  NK_ASSERT(items_separated_by_separator);
38179  if (!ctx || !items_separated_by_separator)
38180  return selected;
38181 
38182  /* calculate popup window */
38183  item_spacing = ctx->style.window.spacing;
38184  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
38185  max_height = count * item_height + count * (int)item_spacing.y;
38186  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
38187  size.y = NK_MIN(size.y, (float)max_height);
38188 
38189  /* find selected item */
38190  current_item = items_separated_by_separator;
38191  for (i = 0; i < count; ++i) {
38192  iter = current_item;
38193  while (*iter && *iter != separator) iter++;
38194  length = (int)(iter - current_item);
38195  if (i == selected) break;
38196  current_item = iter + 1;
38197  }
38198 
38199  if (nk_combo_begin_text(ctx, current_item, length, size)) {
38200  current_item = items_separated_by_separator;
38201  nk_layout_row_dynamic(ctx, (float)item_height, 1);
38202  for (i = 0; i < count; ++i) {
38203  iter = current_item;
38204  while (*iter && *iter != separator) iter++;
38205  length = (int)(iter - current_item);
38206  if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
38207  selected = i;
38208  current_item = current_item + length + 1;
38209  }
38210  nk_combo_end(ctx);
38211  }
38212  return selected;
38213 }
38225 NK_API int
38226 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
38227  int selected, int count, int item_height, struct nk_vec2 size)
38228 {
38229  return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);
38230 }
38243 NK_API int
38244 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
38245  void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
38246 {
38247  int i;
38248  int max_height;
38249  struct nk_vec2 item_spacing;
38250  struct nk_vec2 window_padding;
38251  const char *item;
38252 
38253  NK_ASSERT(ctx);
38254  NK_ASSERT(item_getter);
38255  if (!ctx || !item_getter)
38256  return selected;
38257 
38258  /* calculate popup window */
38259  item_spacing = ctx->style.window.spacing;
38260  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
38261  max_height = count * item_height + count * (int)item_spacing.y;
38262  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
38263  size.y = NK_MIN(size.y, (float)max_height);
38264 
38265  item_getter(userdata, selected, &item);
38266  if (nk_combo_begin_label(ctx, item, size)) {
38267  nk_layout_row_dynamic(ctx, (float)item_height, 1);
38268  for (i = 0; i < count; ++i) {
38269  item_getter(userdata, i, &item);
38270  if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
38271  selected = i;
38272  }
38273  nk_combo_end(ctx);
38274  } return selected;
38275 }
38288 NK_API void
38289 nk_combobox(struct nk_context *ctx, const char *const *items, int count,
38290  int *selected, int item_height, struct nk_vec2 size)
38291 {
38292  *selected = nk_combo(ctx, items, count, *selected, item_height, size);
38293 }
38305 NK_API void
38306 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
38307  int *selected, int count, int item_height, struct nk_vec2 size)
38308 {
38309  *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);
38310 }
38322 NK_API void
38323 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
38324  int separator, int *selected, int count, int item_height, struct nk_vec2 size)
38325 {
38326  *selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
38327  *selected, count, item_height, size);
38328 }
38339 NK_API void
38340 nk_combobox_callback(struct nk_context *ctx,
38341  void(*item_getter)(void* data, int id, const char **out_text),
38342  void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
38343 {
38344  *selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);
38345 }
38346 
38347 
38348 
38349 
38350 /* ===============================================================
38351  *
38352  * TOOLTIP
38353  *
38354  * ===============================================================*/
38366 NK_API nk_bool
38367 nk_tooltip_begin(struct nk_context *ctx, float width)
38368 {
38369  int x,y,w,h;
38370  struct nk_window *win;
38371  const struct nk_input *in;
38372  struct nk_rect bounds;
38373  int ret;
38374 
38375  NK_ASSERT(ctx);
38376  NK_ASSERT(ctx->current);
38377  NK_ASSERT(ctx->current->layout);
38378  if (!ctx || !ctx->current || !ctx->current->layout)
38379  return 0;
38380 
38381  /* make sure that no nonblocking popup is currently active */
38382  win = ctx->current;
38383  in = &ctx->input;
38384  if (win->popup.win && ((int)win->popup.type & (int)NK_PANEL_SET_NONBLOCK))
38385  return 0;
38386 
38387  w = nk_iceilf(width);
38388  h = nk_iceilf(nk_null_rect.h);
38389  x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x;
38390  y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y;
38391 
38392  bounds.x = (float)x;
38393  bounds.y = (float)y;
38394  bounds.w = (float)w;
38395  bounds.h = (float)h;
38396 
38397  ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
38398  "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
38399  if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
38400  win->popup.type = NK_PANEL_TOOLTIP;
38401  ctx->current->layout->type = NK_PANEL_TOOLTIP;
38402  return ret;
38403 }
38404 
38415 NK_API void
38416 nk_tooltip_end(struct nk_context *ctx)
38417 {
38418  NK_ASSERT(ctx);
38419  NK_ASSERT(ctx->current);
38420  if (!ctx || !ctx->current) return;
38421  ctx->current->seq--;
38422  nk_popup_close(ctx);
38423  nk_popup_end(ctx);
38424 }
38436 NK_API void
38437 nk_tooltip(struct nk_context *ctx, const char *text)
38438 {
38439  const struct nk_style *style;
38440  struct nk_vec2 padding;
38441 
38442  int text_len;
38443  float text_width;
38444  float text_height;
38445 
38446  NK_ASSERT(ctx);
38447  NK_ASSERT(ctx->current);
38448  NK_ASSERT(ctx->current->layout);
38449  NK_ASSERT(text);
38450  if (!ctx || !ctx->current || !ctx->current->layout || !text)
38451  return;
38452 
38453  /* fetch configuration data */
38454  style = &ctx->style;
38455  padding = style->window.padding;
38456 
38457  /* calculate size of the text and tooltip */
38458  text_len = nk_strlen(text);
38459  text_width = style->font->width(style->font->userdata,
38460  style->font->height, text, text_len);
38461  text_width += (4 * padding.x);
38462  text_height = (style->font->height + 2 * padding.y);
38463 
38464  /* execute tooltip and fill with text */
38465  if (nk_tooltip_begin(ctx, (float)text_width)) {
38466  nk_layout_row_dynamic(ctx, (float)text_height, 1);
38467  nk_text(ctx, text, text_len, NK_TEXT_LEFT);
38468  nk_tooltip_end(ctx);
38469  }
38470 }
38471 #ifdef NK_INCLUDE_STANDARD_VARARGS
38483 NK_API void
38484 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...)
38485 {
38486  va_list args;
38487  va_start(args, fmt);
38488  nk_tooltipfv(ctx, fmt, args);
38489  va_end(args);
38490 }
38503 NK_API void
38504 nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
38505 {
38506  char buf[256];
38507  nk_strfmt(buf, NK_LEN(buf), fmt, args);
38508  nk_tooltip(ctx, buf);
38509 }
38510 #endif
38511 
38512 
38513 
38514 #endif /* NK_IMPLEMENTATION */
38515 
38516 /*
38517 ------------------------------------------------------------------------------
38518 This software is available under 2 licenses -- choose whichever you prefer.
38519 ------------------------------------------------------------------------------
38520 ALTERNATIVE A - MIT License
38521 Copyright (c) 2017 Micha Mettke
38522 Permission is hereby granted, free of charge, to any person obtaining a copy of
38523 this software and associated documentation files (the "Software"), to deal in
38524 the Software without restriction, including without limitation the rights to
38525 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
38526 of the Software, and to permit persons to whom the Software is furnished to do
38527 so, subject to the following conditions:
38528 The above copyright notice and this permission notice shall be included in all
38529 copies or substantial portions of the Software.
38530 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38531 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38532 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38533 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38534 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38535 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38536 SOFTWARE.
38537 ------------------------------------------------------------------------------
38538 ALTERNATIVE B - Public Domain (www.unlicense.org)
38539 This is free and unencumbered software released into the public domain.
38540 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
38541 software, either in source code form or as a compiled binary, for any purpose,
38542 commercial or non-commercial, and by any means.
38543 In jurisdictions that recognize copyright laws, the author or authors of this
38544 software dedicate any and all copyright interest in the software to the public
38545 domain. We make this dedication for the benefit of the public at large and to
38546 the detriment of our heirs and successors. We intend this dedication to be an
38547 overt act of relinquishment in perpetuity of all present and future rights to
38548 this software under copyright law.
38549 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38550 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38551 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38552 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
38553 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
38554 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38555 -----------------------------------------------------------------------------
38556 ## Changelog
38557 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none
38558 [date] ([x.y.z]) - [description]
38559 - [date]: date on which the change has been pushed
38560 - [x.y.z]: Version string, represented in Semantic Versioning format
38561  - [x]: Major version with API and library breaking changes
38562  - [y]: Minor version with non-breaking API and library changes
38563  - [z]: Patch version with no direct changes to the API
38564 
38565 - 2024/03/07 (4.12.1) - Fix bitwise operations warnings in C++20
38566 - 2023/11/26 (4.12.0) - Added an alignment option to checkboxes and radio buttons.
38567 - 2023/10/11 (4.11.0) - Added nk_widget_disable_begin() and nk_widget_disable_end()
38568 - 2022/12/23 (4.10.6) - Fix incorrect glyph index in nk_font_bake()
38569 - 2022/12/17 (4.10.5) - Fix nk_font_bake_pack() using TTC font offset incorrectly
38570 - 2022/10/24 (4.10.4) - Fix nk_str_{append,insert}_str_utf8 always returning 0
38571 - 2022/09/03 (4.10.3) - Renamed the `null` texture variable to `tex_null`
38572 - 2022/08/01 (4.10.2) - Fix Apple Silicon with incorrect NK_SITE_TYPE and NK_POINTER_TYPE
38573 - 2022/08/01 (4.10.1) - Fix cursor jumping back to beginning of text when typing more than
38574  nk_edit_xxx limit
38575 - 2022/05/27 (4.10.0) - Add nk_input_has_mouse_click_in_button_rect() to fix window move bug
38576 - 2022/04/19 (4.9.8) - Added nk_rule_horizontal() widget
38577 - 2022/04/18 (4.9.7) - Change button behavior when NK_BUTTON_TRIGGER_ON_RELEASE is defined to
38578  only trigger when the mouse position was inside the same button on down
38579 - 2022/02/03 (4.9.6) - Allow overriding the NK_INV_SQRT function, similar to NK_SIN and NK_COS
38580 - 2021/12/22 (4.9.5) - Revert layout bounds not accounting for padding due to regressions
38581 - 2021/12/22 (4.9.4) - Fix checking hovering when window is minimized
38582 - 2021/12/22 (4.09.3) - Fix layout bounds not accounting for padding
38583 - 2021/12/19 (4.09.2) - Update to stb_rect_pack.h v1.01 and stb_truetype.h v1.26
38584 - 2021/12/16 (4.09.1) - Fix the majority of GCC warnings
38585 - 2021/10/16 (4.09.0) - Added nk_spacer() widget
38586 - 2021/09/22 (4.08.6) - Fix "may be used uninitialized" warnings in nk_widget
38587 - 2021/09/22 (4.08.5) - GCC __builtin_offsetof only exists in version 4 and later
38588 - 2021/09/15 (4.08.4) - Fix "'num_len' may be used uninitialized" in nk_do_property
38589 - 2021/09/15 (4.08.3) - Fix "Templates cannot be declared to have 'C' Linkage"
38590 - 2021/09/08 (4.08.2) - Fix warnings in C89 builds
38591 - 2021/09/08 (4.08.1) - Use compiler builtins for NK_OFFSETOF when possible
38592 - 2021/08/17 (4.08.0) - Implemented 9-slice scaling support for widget styles
38593 - 2021/08/16 (4.07.5) - Replace usage of memset in nk_font_atlas_bake with NK_MEMSET
38594 - 2021/08/15 (4.07.4) - Fix conversion and sign conversion warnings
38595 - 2021/08/08 (4.07.3) - Fix crash when baking merged fonts
38596 - 2021/08/08 (4.07.2) - Fix Multiline Edit wrong offset
38597 - 2021/03/17 (4.07.1) - Fix warning about unused parameter
38598 - 2021/03/17 (4.07.0) - Fix nk_property hover bug
38599 - 2021/03/15 (4.06.4) - Change nk_propertyi back to int
38600 - 2021/03/15 (4.06.3) - Update documentation for functions that now return nk_bool
38601 - 2020/12/19 (4.06.2) - Fix additional C++ style comments which are not allowed in ISO C90.
38602 - 2020/10/11 (4.06.1) - Fix C++ style comments which are not allowed in ISO C90.
38603 - 2020/10/07 (4.06.0) - Fix nk_combo return type wrongly changed to nk_bool
38604 - 2020/09/05 (4.05.0) - Use the nk_font_atlas allocator for stb_truetype memory management.
38605 - 2020/09/04 (4.04.1) - Replace every boolean int by nk_bool
38606 - 2020/09/04 (4.04.0) - Add nk_bool with NK_INCLUDE_STANDARD_BOOL
38607 - 2020/06/13 (4.03.1) - Fix nk_pool allocation sizes.
38608 - 2020/06/04 (4.03.0) - Made nk_combo header symbols optional.
38609 - 2020/05/27 (4.02.5) - Fix nk_do_edit: Keep scroll position when re-activating edit widget.
38610 - 2020/05/09 (4.02.4) - Fix nk_menubar height calculation bug
38611 - 2020/05/08 (4.02.3) - Fix missing stdarg.h with NK_INCLUDE_STANDARD_VARARGS
38612 - 2020/04/30 (4.02.2) - Fix nk_edit border drawing bug
38613 - 2020/04/09 (4.02.1) - Removed unused nk_sqrt function to fix compiler warnings
38614  - Fixed compiler warnings if you bring your own methods for
38615  nk_cos/nk_sin/nk_strtod/nk_memset/nk_memcopy/nk_dtoa
38616 - 2020/04/06 (4.01.10) - Fix bug: Do not use pool before checking for NULL
38617 - 2020/03/22 (4.01.9) - Fix bug where layout state wasn't restored correctly after
38618  popping a tree.
38619 - 2020/03/11 (4.01.8) - Fix bug where padding is subtracted from widget
38620 - 2020/03/06 (4.01.7) - Fix bug where width padding was applied twice
38621 - 2020/02/06 (4.01.6) - Update stb_truetype.h and stb_rect_pack.h and separate them
38622 - 2019/12/10 (4.01.5) - Fix off-by-one error in NK_INTERSECT
38623 - 2019/10/09 (4.01.4) - Fix bug for autoscrolling in nk_do_edit
38624 - 2019/09/20 (4.01.3) - Fixed a bug wherein combobox cannot be closed by clicking the header
38625  when NK_BUTTON_TRIGGER_ON_RELEASE is defined.
38626 - 2019/09/10 (4.01.2) - Fixed the nk_cos function, which deviated significantly.
38627 - 2019/09/08 (4.01.1) - Fixed a bug wherein re-baking of fonts caused a segmentation
38628  fault due to dst_font->glyph_count not being zeroed on subsequent
38629  bakes of the same set of fonts.
38630 - 2019/06/23 (4.01.0) - Added nk_***_get_scroll and nk_***_set_scroll for groups, windows, and popups.
38631 - 2019/06/12 (4.00.3) - Fix panel background drawing bug.
38632 - 2018/10/31 (4.00.2) - Added NK_KEYSTATE_BASED_INPUT to "fix" state based backends
38633  like GLFW without breaking key repeat behavior on event based.
38634 - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame.
38635 - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to
38636  clear provided buffers. So make sure to either free
38637  or clear each passed buffer after calling nk_convert.
38638 - 2018/02/23 (3.00.6) - Fixed slider dragging behavior.
38639 - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process.
38640 - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype.
38641 - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug.
38642 - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separated group identifier and title.
38643 - 2018/01/07 (3.00.1) - Started to change documentation style.
38644 - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken
38645  because of conversions between float and byte color representation.
38646  Color pickers now use floating point values to represent
38647  HSV values. To get back the old behavior I added some additional
38648  color conversion functions to cast between nk_color and
38649  nk_colorf.
38650 - 2017/12/23 (2.00.7) - Fixed small warning.
38651 - 2017/12/23 (2.00.7) - Fixed `nk_edit_buffer` behavior if activated to allow input.
38652 - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior.
38653 - 2017/12/04 (2.00.6) - Added formatted string tooltip widget.
38654 - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag `NK_WINDOW_NO_INPUT`.
38655 - 2017/11/15 (2.00.4) - Fixed font merging.
38656 - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions.
38657 - 2017/09/14 (2.00.2) - Fixed `nk_edit_buffer` and `nk_edit_focus` behavior.
38658 - 2017/09/14 (2.00.1) - Fixed window closing behavior.
38659 - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifying window position and size functions now
38660  require the name of the window and must happen outside the window
38661  building process (between function call nk_begin and nk_end).
38662 - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last.
38663 - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows.
38664 - 2017/08/27 (1.40.7) - Fixed window background flag.
38665 - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked
38666  query for widgets.
38667 - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked
38668  and filled rectangles.
38669 - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in
38670  process of being destroyed.
38671 - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in
38672  window instead of directly in table.
38673 - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro.
38674 - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero.
38675 - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only
38676  comes in effect if you pass in zero was row height argument.
38677 - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change
38678  how layouting works. From now there will be an internal minimum
38679  row height derived from font height. If you need a row smaller than
38680  that you can directly set it by `nk_layout_set_min_row_height` and
38681  reset the value back by calling `nk_layout_reset_min_row_height.
38682 - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix.
38683 - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a `nk_layout_xxx` function.
38684 - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer.
38685 - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped.
38686 - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundaries.
38687 - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space.
38688 - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size.
38689 - 2017/05/06 (1.38.0) - Added platform double-click support.
38690 - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends.
38691 - 2017/04/20 (1.37.0) - Extended properties with selection and clipboard support.
38692 - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing.
38693 - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error.
38694 - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags.
38695 - 2017/04/09 (1.35.3) - Fixed buffer heap corruption.
38696 - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows.
38697 - 2017/03/25 (1.35.1) - Fixed windows closing behavior.
38698 - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377.
38699 - 2017/03/18 (1.34.3) - Fixed long window header titles.
38700 - 2017/03/04 (1.34.2) - Fixed text edit filtering.
38701 - 2017/03/04 (1.34.1) - Fixed group closable flag.
38702 - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support.
38703 - 2017/01/24 (1.33.0) - Added programmatic way to remove edit focus.
38704 - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows.
38705 - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows.
38706 - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing.
38707 - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner.
38708 - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both
38709  dynamic and static widgets.
38710 - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit.
38711 - 2016/12/31 (1.29.2) - Fixed closing window bug of minimized windows.
38712 - 2016/12/03 (1.29.1) - Fixed wrapped text with no separator and C89 error.
38713 - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters.
38714 - 2016/11/22 (1.28.6) - Fixed window minimized closing bug.
38715 - 2016/11/19 (1.28.5) - Fixed abstract combo box closing behavior.
38716 - 2016/11/19 (1.28.4) - Fixed tooltip flickering.
38717 - 2016/11/19 (1.28.3) - Fixed memory leak caused by popup repeated closing.
38718 - 2016/11/18 (1.28.2) - Fixed memory leak caused by popup panel allocation.
38719 - 2016/11/10 (1.28.1) - Fixed some warnings and C++ error.
38720 - 2016/11/10 (1.28.0) - Added additional `nk_button` versions which allows to directly
38721  pass in a style struct to change buttons visual.
38722 - 2016/11/10 (1.27.0) - Added additional `nk_tree` versions to support external state
38723  storage. Just like last the `nk_group` commit the main
38724  advantage is that you optionally can minimize nuklears runtime
38725  memory consumption or handle hash collisions.
38726 - 2016/11/09 (1.26.0) - Added additional `nk_group` version to support external scrollbar
38727  offset storage. Main advantage is that you can externalize
38728  the memory management for the offset. It could also be helpful
38729  if you have a hash collision in `nk_group_begin` but really
38730  want the name. In addition I added `nk_list_view` which allows
38731  to draw big lists inside a group without actually having to
38732  commit the whole list to nuklear (issue #269).
38733 - 2016/10/30 (1.25.1) - Fixed clipping rectangle bug inside `nk_draw_list`.
38734 - 2016/10/29 (1.25.0) - Pulled `nk_panel` memory management into nuklear and out of
38735  the hands of the user. From now on users don't have to care
38736  about panels unless they care about some information. If you
38737  still need the panel just call `nk_window_get_panel`.
38738 - 2016/10/21 (1.24.0) - Changed widget border drawing to stroked rectangle from filled
38739  rectangle for less overdraw and widget background transparency.
38740 - 2016/10/18 (1.23.0) - Added `nk_edit_focus` for manually edit widget focus control.
38741 - 2016/09/29 (1.22.7) - Fixed deduction of basic type in non `<stdint.h>` compilation.
38742 - 2016/09/29 (1.22.6) - Fixed edit widget UTF-8 text cursor drawing bug.
38743 - 2016/09/28 (1.22.5) - Fixed edit widget UTF-8 text appending/inserting/removing.
38744 - 2016/09/28 (1.22.4) - Fixed drawing bug inside edit widgets which offset all text
38745  text in every edit widget if one of them is scrolled.
38746 - 2016/09/28 (1.22.3) - Fixed small bug in edit widgets if not active. The wrong
38747  text length is passed. It should have been in bytes but
38748  was passed as glyphs.
38749 - 2016/09/20 (1.22.2) - Fixed color button size calculation.
38750 - 2016/09/20 (1.22.1) - Fixed some `nk_vsnprintf` behavior bugs and removed `<stdio.h>`
38751  again from `NK_INCLUDE_STANDARD_VARARGS`.
38752 - 2016/09/18 (1.22.0) - C89 does not support vsnprintf only C99 and newer as well
38753  as C++11 and newer. In addition to use vsnprintf you have
38754  to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS`
38755  is not enough. That behavior is now fixed. By default if
38756  both varargs as well as stdio is selected I try to use
38757  vsnprintf if not possible I will revert to vsprintf. If
38758  varargs but not stdio was defined I will use my own function.
38759 - 2016/09/15 (1.21.2) - Fixed panel `close` behavior for deeper panel levels.
38760 - 2016/09/15 (1.21.1) - Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`.
38761 - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo,
38762  and contextual which prevented closing in y-direction if
38763  popup did not reach max height.
38764  In addition the height parameter was changed into vec2
38765  for width and height to have more control over the popup size.
38766 - 2016/09/13 (1.20.3) - Cleaned up and extended type selection.
38767 - 2016/09/13 (1.20.2) - Fixed slider behavior hopefully for the last time. This time
38768  all calculation are correct so no more hackery.
38769 - 2016/09/13 (1.20.1) - Internal change to divide window/panel flags into panel flags and types.
38770  Suprisinly spend years in C and still happened to confuse types
38771  with flags. Probably something to take note.
38772 - 2016/09/08 (1.20.0) - Added additional helper function to make it easier to just
38773  take the produced buffers from `nk_convert` and unplug the
38774  iteration process from `nk_context`. So now you can
38775  just use the vertex,element and command buffer + two pointer
38776  inside the command buffer retrieved by calls `nk__draw_begin`
38777  and `nk__draw_end` and macro `nk_draw_foreach_bounded`.
38778 - 2016/09/08 (1.19.0) - Added additional asserts to make sure every `nk_xxx_begin` call
38779  for windows, popups, combobox, menu and contextual is guarded by
38780  `if` condition and does not produce false drawing output.
38781 - 2016/09/08 (1.18.0) - Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT`
38782  to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and
38783  `NK_SYMBOL_RECT_OUTLINE`.
38784 - 2016/09/08 (1.17.0) - Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE`
38785  to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and
38786  `NK_SYMBOL_CIRCLE_OUTLINE`.
38787 - 2016/09/08 (1.16.0) - Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES`
38788  is not defined by supporting the biggest compiler GCC, clang and MSVC.
38789 - 2016/09/07 (1.15.3) - Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error.
38790 - 2016/09/04 (1.15.2) - Fixed wrong combobox height calculation.
38791 - 2016/09/03 (1.15.1) - Fixed gaps inside combo boxes in OpenGL.
38792 - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and
38793  instead made it user provided. The range of types to convert
38794  to is quite limited at the moment, but I would be more than
38795  happy to accept PRs to add additional.
38796 - 2016/08/30 (1.14.2) - Removed unused variables.
38797 - 2016/08/30 (1.14.1) - Fixed C++ build errors.
38798 - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly.
38799 - 2016/08/30 (1.13.4) - Tweaked some default styling variables.
38800 - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would
38801  refrain from using slider with a big number of steps.
38802 - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the
38803  window was in Read Only Mode.
38804 - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just
38805  a hack for combo box and menu.
38806 - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since
38807  it is bugged and causes issues in window selection.
38808 - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now
38809  determined by the scrollbar size.
38810 - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11.0.
38811 - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection.
38812 - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code
38813  handling panel padding and panel border.
38814 - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`.
38815 - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups.
38816 - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes.
38817 - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for
38818  hash collisions. Currently limited to `NK_WINDOW_MAX_NAME`
38819  which in term can be redefined if not big enough.
38820 - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code.
38821 - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released'
38822  to account for key press and release happening in one frame.
38823 - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate.
38824 - 2016/08/17 (1.09.6) - Removed invalid check for value zero in `nk_propertyx`.
38825 - 2016/08/16 (1.09.5) - Fixed ROM mode for deeper levels of popup windows parents.
38826 - 2016/08/15 (1.09.4) - Editbox are now still active if enter was pressed with flag
38827  `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep
38828  typing after committing.
38829 - 2016/08/15 (1.09.4) - Removed redundant code.
38830 - 2016/08/15 (1.09.4) - Fixed negative numbers in `nk_strtoi` and remove unused variable.
38831 - 2016/08/15 (1.09.3) - Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background
38832  window only as selected by hovering and not by clicking.
38833 - 2016/08/14 (1.09.2) - Fixed a bug in font atlas which caused wrong loading
38834  of glyphs for font with multiple ranges.
38835 - 2016/08/12 (1.09.1) - Added additional function to check if window is currently
38836  hidden and therefore not visible.
38837 - 2016/08/12 (1.09.1) - nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED`
38838  instead of the old flag `NK_WINDOW_HIDDEN`.
38839 - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed
38840  the underlying implementation to not cast to float and instead
38841  work directly on the given values.
38842 - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
38843  floating pointer number to string conversion for additional
38844  precision.
38845 - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal
38846  string to floating point number conversion for additional
38847  precision.
38848 - 2016/08/08 (1.07.2) - Fixed compiling error without define `NK_INCLUDE_FIXED_TYPE`.
38849 - 2016/08/08 (1.07.1) - Fixed possible floating point error inside `nk_widget` leading
38850  to wrong widget width calculation which results in widgets falsely
38851  becoming tagged as not inside window and cannot be accessed.
38852 - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and
38853  closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown
38854  by using `nk_window_show` and closed by either clicking the close
38855  icon in a window or by calling `nk_window_close`. Only closed
38856  windows get removed at the end of the frame while hidden windows
38857  remain.
38858 - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to
38859  `nk_edit_string` which takes, edits and outputs a '\0' terminated string.
38860 - 2016/08/08 (1.05.4) - Fixed scrollbar auto hiding behavior.
38861 - 2016/08/08 (1.05.3) - Fixed wrong panel padding selection in `nk_layout_widget_space`.
38862 - 2016/08/07 (1.05.2) - Fixed old bug in dynamic immediate mode layout API, calculating
38863  wrong item spacing and panel width.
38864 - 2016/08/07 (1.05.1) - Hopefully finally fixed combobox popup drawing bug.
38865 - 2016/08/07 (1.05.0) - Split varargs away from `NK_INCLUDE_STANDARD_IO` into own
38866  define `NK_INCLUDE_STANDARD_VARARGS` to allow more fine
38867  grained controlled over library includes.
38868 - 2016/08/06 (1.04.5) - Changed memset calls to `NK_MEMSET`.
38869 - 2016/08/04 (1.04.4) - Fixed fast window scaling behavior.
38870 - 2016/08/04 (1.04.3) - Fixed window scaling, movement bug which appears if you
38871  move/scale a window and another window is behind it.
38872  If you are fast enough then the window behind gets activated
38873  and the operation is blocked. I now require activating
38874  by hovering only if mouse is not pressed.
38875 - 2016/08/04 (1.04.2) - Fixed changing fonts.
38876 - 2016/08/03 (1.04.1) - Fixed `NK_WINDOW_BACKGROUND` behavior.
38877 - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`.
38878 - 2016/08/03 (1.04.0) - Added additional window padding style attributes for
38879  sub windows (combo, menu, ...).
38880 - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor.
38881 - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window
38882  to be always in the background of the screen.
38883 - 2016/08/03 (1.03.2) - Removed invalid assert macro for NK_RGB color picker.
38884 - 2016/08/01 (1.03.1) - Added helper macros into header include guard.
38885 - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to
38886  simplify memory management by removing the need to
38887  allocate the pool.
38888 - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled
38889  will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT
38890  seconds without window interaction. To make it work
38891  you have to also set a delta time inside the `nk_context`.
38892 - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs.
38893 - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`.
38894 - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument.
38895 - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified
38896  font atlas memory management by converting pointer
38897  arrays for fonts and font configurations to lists.
38898 - 2016/07/15 (1.00.0) - Changed button API to use context dependent button
38899  behavior instead of passing it for every function call.
38900 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38901 ## Gallery
38902 ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png)
38903 ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png)
38904 ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png)
38905 ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png)
38906 ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png)
38907 ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png)
38908 ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif)
38909 ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png)
38910 ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png)
38911 
38912 ## Credits
38913 Developed by Micha Mettke and every direct or indirect github contributor. <br /><br />
38914 
38915 Embeds [stb_texedit](https://github.com/nothings/stb/blob/master/stb_textedit.h), [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) and [stb_rectpack](https://github.com/nothings/stb/blob/master/stb_rect_pack.h) by Sean Barret (public domain) <br />
38916 Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from r-lyeh@github.com for documentation generation <br /><br />
38917 Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br />
38918 
38919 Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and
38920 giving me the inspiration for this library, Casey Muratori for handmade hero
38921 and his original immediate mode graphical user interface idea and Sean
38922 Barret for his amazing single header libraries which restored my faith
38923 in libraries and brought me to create some of my own. Finally Apoorva Joshi
38924 for his single header file packer.
38925 */
38926 
NK_API void nk_tree_pop(struct nk_context *)
Ends a collapsabale UI section.
NK_API void nk_free(struct nk_context *)
Frees all memory allocated by nuklear; Not needed if context was initialized with nk_init_fixed.
NK_API nk_bool nk_group_begin(struct nk_context *, const char *title, nk_flags)
Starts a new widget group.
NK_API struct nk_vec2 nk_window_get_content_region_max(const struct nk_context *ctx)
NK_API void nk_layout_row_end(struct nk_context *)
Finished previously started row.
NK_API void nk_input_end(struct nk_context *)
End the input mirroring process by resetting mouse grabbing state to ensure the mouse cursor is not g...
NK_API void nk_window_close(struct nk_context *ctx, const char *name)
Closes a window and marks it for being freed at the end of the frame.
NK_API void nk_spacer(struct nk_context *ctx)
Spacer is a dummy widget that consumes space as usual but doesn't draw anything.
NK_API void nk_input_begin(struct nk_context *)
Begins the input mirroring process by resetting text, scroll mouse, previous mouse position and movem...
NK_API float nk_propertyf(struct nk_context *, const char *name, float min, float val, float max, float step, float inc_per_pixel)
Float property modifying a passed in value and returning the new value.
NK_API void nk_rule_horizontal(struct nk_context *ctx, struct nk_color color, nk_bool rounding)
Line for visual separation.
NK_API void nk_layout_space_end(struct nk_context *)
Marks the end of the layout space.
NK_API nk_bool nk_init_fixed(struct nk_context *, void *memory, nk_size size, const struct nk_user_font *)
Initializes a nk_context struct from single fixed size memory block Should be used if you want comple...
NK_API void nk_property_float(struct nk_context *, const char *name, float min, float *val, float max, float step, float inc_per_pixel)
Float property directly modifying a passed in value !!!
nk_window_flags
Definition: nuklear.h:5287
@ NK_WINDOW_CLOSED
Directly closes and frees the window at the end of the frame.
Definition: nuklear.h:5293
@ NK_WINDOW_MINIMIZED
marks the window as minimized
Definition: nuklear.h:5294
@ NK_WINDOW_HIDDEN
Hides window and stops any window interaction and drawing.
Definition: nuklear.h:5292
@ NK_WINDOW_ROM
sets window widgets into a read only mode and does not allow input changes
Definition: nuklear.h:5290
@ NK_WINDOW_NOT_INTERACTIVE
prevents all interaction caused by input to either window or widgets inside
Definition: nuklear.h:5291
@ NK_WINDOW_DYNAMIC
special window type growing up in height while being filled to a certain maximum height
Definition: nuklear.h:5289
@ NK_WINDOW_REMOVE_ROM
Removes read only mode at the end of the window.
Definition: nuklear.h:5295
NK_API void nk_layout_row(struct nk_context *, enum nk_layout_format, float height, int cols, const float *ratio)
Specifies row columns in array as either window ratio or size.
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
misc
NK_API nk_bool nk_window_is_hovered(const struct nk_context *ctx)
Return if the current window is being hovered.
NK_API void nk_window_collapse_if(struct nk_context *ctx, const char *name, enum nk_collapse_states state, int cond)
Updates collapse state of a window with given name if given condition is met.
NK_API struct nk_vec2 nk_layout_space_to_screen(const struct nk_context *ctx, struct nk_vec2 vec)
Converts vector from nk_layout_space coordinate space into screen space.
#define NK_UTF_INVALID
internal invalid utf8 rune
Definition: nuklear.h:5548
#define NK_BOOL
could be char, use int for drop-in replacement backwards compatibility
Definition: nuklear.h:414
NK_API nk_bool nk_init_custom(struct nk_context *, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *)
Initializes a nk_context struct from two different either fixed or growing buffers.
NK_API nk_bool nk_tree_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
Start a collapsible UI section with internal state management with full control over internal unique ...
NK_API void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
Sets the scroll offset for the current window.
NK_API void nk_group_scrolled_end(struct nk_context *)
Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin.
NK_API struct nk_vec2 nk_window_get_size(const struct nk_context *ctx)
NK_API void nk_layout_row_template_push_dynamic(struct nk_context *)
Adds a dynamic column that dynamically grows and can go to zero if not enough space.
NK_API nk_bool nk_window_is_active(const struct nk_context *ctx, const char *name)
Same as nk_window_has_focus for some reason.
NK_API void nk_group_get_scroll(struct nk_context *, const char *id, nk_uint *x_offset, nk_uint *y_offset)
Gets the scroll position of the given group.
NK_API struct nk_vec2 nk_layout_space_to_local(const struct nk_context *ctx, struct nk_vec2 vec)
Converts vector from layout space into screen space.
NK_API void nk_window_set_focus(struct nk_context *ctx, const char *name)
Sets the window with given name as active.
NK_API nk_bool nk_item_is_any_active(const struct nk_context *ctx)
#define NK_UTF_SIZE
describes the number of bytes a glyph consists of
Definition: nuklear.h:244
NK_API void nk_input_unicode(struct nk_context *, nk_rune)
Converts a unicode rune into UTF-8 and copies the result into an internal text buffer.
NK_API nk_bool nk_window_is_any_hovered(const struct nk_context *ctx)
NK_API nk_bool nk_window_is_hidden(const struct nk_context *ctx, const char *name)
NK_API void nk_input_key(struct nk_context *, enum nk_keys, nk_bool down)
Mirrors the state of a specific key to nuklear.
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)
shape outlines
NK_API void nk_property_double(struct nk_context *, const char *name, double min, double *val, double max, double step, float inc_per_pixel)
Double property directly modifying a passed in value.
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
filled shades
NK_API void nk_layout_row_template_push_static(struct nk_context *, float width)
Adds a static column that does not grow and will always have the same size.
NK_API struct nk_vec2 nk_window_get_content_region_size(const struct nk_context *ctx)
NK_API void nk_window_get_scroll(const struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
Gets the scroll offset for the current window.
NK_API nk_bool nk_group_scrolled_offset_begin(struct nk_context *, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
starts a new widget group.
NK_API nk_bool nk_tree_state_image_push(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state)
Start a collapsible UI section with image and label header and external state management.
NK_API void nk_window_set_position(struct nk_context *ctx, const char *name, struct nk_vec2 pos)
Updates position of window with passed name.
NK_API void nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states state)
updates visibility state of a window with given name
NK_API nk_bool nk_window_is_collapsed(const struct nk_context *ctx, const char *name)
NK_API struct nk_command_buffer * nk_window_get_canvas(const struct nk_context *ctx)
NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
Sets current row layout to share horizontal space between cols number of widgets evenly.
NK_API void nk_window_collapse(struct nk_context *ctx, const char *name, enum nk_collapse_states state)
Updates collapse state of a window with given name.
NK_API nk_bool nk_filter_default(const struct nk_text_edit *, nk_rune unicode)
filter function
NK_API const struct nk_command * nk__begin(struct nk_context *)
Returns a draw command list iterator to iterate all draw commands accumulated over one frame.
NK_API void nk_layout_row_template_end(struct nk_context *)
Marks the end of the row template.
NK_API nk_bool nk_window_has_focus(const struct nk_context *ctx)
NK_API void nk_layout_reset_min_row_height(struct nk_context *)
Reset the currently used minimum row height back to font_height + text_padding + padding
nk_widget_states
Definition: nuklear.h:2907
@ NK_WIDGET_STATE_LEFT
!< widget is currently activated
Definition: nuklear.h:2913
@ NK_WIDGET_STATE_ACTIVED
!< widget is being hovered
Definition: nuklear.h:2912
@ NK_WIDGET_STATE_ENTERED
!< widget is neither active nor hovered
Definition: nuklear.h:2910
@ NK_WIDGET_STATE_HOVER
!< widget has been hovered on the current frame
Definition: nuklear.h:2911
@ NK_WIDGET_STATE_ACTIVE
!< widget is being hovered
Definition: nuklear.h:2915
@ NK_WIDGET_STATE_HOVERED
!< widget is from this frame on not hovered anymore
Definition: nuklear.h:2914
NK_API struct nk_rect nk_layout_space_rect_to_local(const struct nk_context *ctx, struct nk_rect bounds)
Converts rectangle from layout space into screen space.
NK_API void nk_window_set_bounds(struct nk_context *ctx, const char *name, struct nk_rect bounds)
Updates position and size of window with passed in name.
NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx)
NK_API nk_bool nk_tree_state_push(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states *state)
Start a collapsible UI section with external state management.
NK_API struct nk_panel * nk_window_get_panel(const struct nk_context *ctx)
NK_API nk_bool nk_tree_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
Start a collapsible UI section with internal state management with full control over internal unique ...
NK_API void nk_layout_set_min_row_height(struct nk_context *, float height)
Sets the currently used minimum row height.
NK_API void nk_window_show_if(struct nk_context *ctx, const char *name, enum nk_show_states state, int cond)
Updates visibility state of a window with given name if a given condition is met.
NK_API float nk_window_get_height(const struct nk_context *ctx)
NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols)
Starts a new dynamic or fixed row with given height and columns.
NK_API nk_bool nk_group_begin_titled(struct nk_context *, const char *name, const char *title, nk_flags)
Starts a new widget group.
NK_API nk_bool nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags)
Extended window start with separated title and identifier to allow multiple.
#define nk_foreach(c, ctx)
Iterates over each draw command inside the context draw command list.
Definition: nuklear.h:1187
NK_API void nk_layout_space_push(struct nk_context *, struct nk_rect bounds)
Pushes position and size of the next widget in own coordinate space either as pixel or ratio.
NK_API nk_bool nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags)
Starts a new window; needs to be called every frame for every.
NK_API void nk_window_set_size(struct nk_context *ctx, const char *name, struct nk_vec2 size)
Updates size of window with passed in name.
NK_API void nk_input_button(struct nk_context *, enum nk_buttons, int x, int y, nk_bool down)
Mirrors the state of a specific mouse button to nuklear.
NK_API void nk_group_set_scroll(struct nk_context *, const char *id, nk_uint x_offset, nk_uint y_offset)
Sets the scroll position of the given group.
NK_API void nk_layout_row_template_begin(struct nk_context *, float row_height)
Begins the row template declaration.
NK_API nk_bool nk_init(struct nk_context *, const struct nk_allocator *, const struct nk_user_font *)
Initializes a nk_context struct with memory allocation callbacks for nuklear to allocate memory from.
NK_API float nk_layout_ratio_from_pixel(const struct nk_context *ctx, float pixel_width)
Utility functions to calculate window ratio from pixel size.
NK_API void nk_tree_state_pop(struct nk_context *)
Ends a collapsabale UI section.
NK_API void nk_layout_row_push(struct nk_context *, float value)
Specifies either window ratio or width of a single column.
NK_API struct nk_rect nk_layout_widget_bounds(const struct nk_context *ctx)
Returns the width of the next row allocate by one of the layouting functions.
NK_API struct nk_rect nk_layout_space_rect_to_screen(const struct nk_context *ctx, struct nk_rect bounds)
Converts rectangle from screen space into layout space.
NK_API struct nk_vec2 nk_window_get_content_region_min(const struct nk_context *ctx)
NK_API void nk_input_char(struct nk_context *, char)
Copies a single ASCII character into an internal text buffer.
NK_API float nk_window_get_width(const struct nk_context *ctx)
NK_API void nk_input_scroll(struct nk_context *, struct nk_vec2 val)
Copies the last mouse scroll value to nuklear.
nk_widget_layout_states
Definition: nuklear.h:2901
@ NK_WIDGET_DISABLED
The widget is manually disabled and acts like NK_WIDGET_ROM.
Definition: nuklear.h:2905
@ NK_WIDGET_ROM
The widget is partially visible and cannot be updated.
Definition: nuklear.h:2904
@ NK_WIDGET_VALID
The widget is completely inside the window and can be updated and drawn.
Definition: nuklear.h:2903
@ NK_WIDGET_INVALID
The widget cannot be seen and is completely out of view.
Definition: nuklear.h:2902
NK_API double nk_propertyd(struct nk_context *, const char *name, double min, double val, double max, double step, float inc_per_pixel)
Float property modifying a passed in value and returning the new value.
NK_API void nk_input_motion(struct nk_context *, int x, int y)
Mirrors current mouse position to nuklear.
NK_API void nk_layout_space_begin(struct nk_context *, enum nk_layout_format, float height, int widget_count)
Begins a new layouting space that allows to specify each widgets position and size.
NK_API struct nk_rect nk_layout_space_bounds(const struct nk_context *ctx)
Utility function to calculate total space allocated for nk_layout_space
NK_API struct nk_rect nk_window_get_content_region(const struct nk_context *ctx)
NK_API nk_bool nk_window_is_closed(const struct nk_context *ctx, const char *name)
NK_API const struct nk_command * nk__next(struct nk_context *, const struct nk_command *)
Returns draw command pointer pointing to the next command inside the draw command list.
NK_API void nk_clear(struct nk_context *)
Resets the context state at the end of the frame.
NK_API void nk_end(struct nk_context *ctx)
Needs to be called at the end of the window building process to process scaling, scrollbars and gener...
NK_API void nk_group_end(struct nk_context *)
Ends a widget group.
NK_API void nk_layout_row_template_push_variable(struct nk_context *, float min_width)
Adds a variable column that dynamically grows but does not shrink below specified pixel width.
NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx)
nk_edit_events
Definition: nuklear.h:3299
@ NK_EDIT_INACTIVE
!< edit widget is currently being modified
Definition: nuklear.h:3301
@ NK_EDIT_DEACTIVATED
!< edit widget went from state inactive to state active
Definition: nuklear.h:3303
@ NK_EDIT_COMMITED
!< edit widget went from state active to state inactive
Definition: nuklear.h:3304
@ NK_EDIT_ACTIVATED
!< edit widget is not active and is not being modified
Definition: nuklear.h:3302
NK_API int nk_propertyi(struct nk_context *, const char *name, int min, int val, int max, int step, float inc_per_pixel)
Integer property modifying a passed in value and returning the new value.
NK_API nk_bool nk_group_scrolled_begin(struct nk_context *, struct nk_scroll *off, const char *title, nk_flags)
Starts a new widget group.
NK_API void nk_input_glyph(struct nk_context *, const nk_glyph)
Converts an encoded unicode rune into UTF-8 and copies the result into an internal text buffer.
NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
Sets current row layout to fill cols number of widgets in row with same @item_width horizontal size.
NK_API void nk_textedit_init(struct nk_text_edit *, const struct nk_allocator *, nk_size size)
text editor
NK_API struct nk_window * nk_window_find(const struct nk_context *ctx, const char *name)
Finds and returns a window from passed name.
struct nk_allocator pool
!< buffer marker to free a buffer to a certain offset
Definition: nuklear.h:3989
struct nk_memory memory
!< memory management type
Definition: nuklear.h:3991
enum nk_allocation_type type
!< allocator callback for dynamic buffers
Definition: nuklear.h:3990
nk_size needed
!< total amount of memory allocated
Definition: nuklear.h:3994
nk_size size
!< number of allocation calls
Definition: nuklear.h:3996
nk_size allocated
!< growing factor for dynamic memory management
Definition: nuklear.h:3993
float grow_factor
!< memory and size of the current memory block
Definition: nuklear.h:3992
nk_size calls
!< totally consumed memory given that enough memory is present
Definition: nuklear.h:3995
command base and header of every command inside the buffer
Definition: nuklear.h:4265
int build
windows
Definition: nuklear.h:5531
struct nk_text_edit text_edit
text editor objects are quite big because of an internal undo/redo stack.
Definition: nuklear.h:5526
struct nk_command_buffer overlay
draw buffer used for overlay drawing operation like cursor
Definition: nuklear.h:5528
enum nk_anti_aliasing shape_AA
!< line anti-aliasing flag can be turned off if you are tight on memory
Definition: nuklear.h:1146
enum nk_anti_aliasing line_AA
!< global alpha value
Definition: nuklear.h:1145
nk_size vertex_alignment
!< sizeof one vertex for vertex packing
Definition: nuklear.h:1153
nk_size vertex_size
!< describes the vertex output format and packing
Definition: nuklear.h:1152
const struct nk_draw_vertex_layout_element * vertex_layout
!< handle to texture with a white pixel for shape drawing
Definition: nuklear.h:1151
unsigned arc_segment_count
!< number of segments used for circles: default to 22
Definition: nuklear.h:1148
unsigned circle_segment_count
!< shape anti-aliasing flag can be turned off if you are tight on memory
Definition: nuklear.h:1147
unsigned curve_segment_count
!< number of segments used for arcs: default to 22
Definition: nuklear.h:1149
struct nk_draw_null_texture tex_null
!< number of segments used for curves: default to 22
Definition: nuklear.h:1150
struct nk_vec2 uv
!< texture handle to a texture with a white pixel
Definition: nuklear.h:1141
==============================================================
Definition: nuklear.h:4024
nk_text_width_f width
!< max height of the font
Definition: nuklear.h:3807
float height
!< user provided font handle
Definition: nuklear.h:3806